/* * main.c * * Created on: 2020年9月10日 * Author: Wendell */ #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 "Config.h" #include #include #include "timeout.h" #include "Module_EvComm.h" #include "Module_CabinetParallel.h" #include "Common.h" #define BTN_RELEASE 0 #define BTN_PRESS 1 #define MAX_BUF 64 #define MtdBlockSize 0x300000 #define SYSFS_GPIO_DIR "/sys/class/gpio" #define UPGRADE_FAN 0x02 #define UPGRADE_RB 0x03 #define UPGRADE_PRI 0x04 #define UPGRADE_AC 0x05 #define UPGRADE_LED 0x06 #define UPGRADE_DORC1 0x07 #define UPGRADE_DORC2 0x08 #define UPGRADE_DDRB 0x09 #define SYSTEM_MIN_VOL 150 #define MIN_OUTPUT_CUR 0 #define AC_OUTPUT_VOL 220 #define NO_DEFINE 255 #define DEFAULT_AC_INDEX 2 #define PSU_MIN_CUR 100 #define MAIN_PRIORITY_INTERVAL 5 #define CABINET_ROLE_TIMEOUT 3 // unit: 1s #define GUN_PREPARE_TIMEOUT 30 #define GUN_EV_WAIT_TIMEOUT (120 + 10) #define GUN_EVSE_WAIT_TIMEOUT (60 + 10) #define GUN_COMP_WAIT_TIMEOUT 10 #define GUN_PRECHARGING_TIMEOUT 60 #define REBOOT_TIMEOUT 10 #define RESET_TIMEOUT 10 #define OCPP_COST_REQ_INTERVAL 1 #define DISPENSER_RECONNECTE_TIME 30 #define DISPENSER_AUTH_COMP_TIME 3 #define FORCE_BALANCE_TIME 5 #define DISPENSER_UPGRADE_TIME 600 #define AC_CONTACTOR_REOPEN_TIME 60 #define PSU_FAILURE_RESUME_TIME 180 #define MAX_AC_CONTACTOR_COUNT 3 #define STANDBY_TIME 600 #define FAST_STANDBY_TIME 10 #define E4U_STANDBY_TIME 1800 #define WIRING_INFO_DELAY 30 #define WAIT_REASSIGN_TIME 40 // unit: second #define MAX_REQUEST_CHARGING_TIME 15 // unit: second #define MIN_WAIT_PREPARNING_TIME 1 // unit: second #define FORCE_CHARGING_CMD_DELAY 3 // unit: second #define FORCE_CHARGING_WAIT_EVSE 10 // unit: second #define TRY_RESET_4G_WIFI_TIME 300 // unit: second #define FAST_RESET_4G_WIFI_TIME 60 // unit: second #define ENERAGY_INTERVAL 1 // unit: second #define FAULT_RELEASE_TIME 2 // unit: second #define MAINTAIN_RECOVERY_TIME 1 // unit: second #define PARALLEL_WAIT_TIME 3 // unit: second #define START_UPGRADE_TIME 60 // unit: second #define PCABINET_UPGRADE_TIME 300 // unit: second #define MCABINET_UPGRADE_TIME 60 // unit: second #define CONNECTION_TIME_OFFSET 5 // unit: second #define PLUG_IN_HOLD_TIME 1 // unit: second #define FINAL_COST_TIMEOUT 3 // unit: second #define FINAL_COST_UPDATE_TIME 10 // unit: second #define MAX_FINAL_COST_MISC_COUNT 3 #define PARKING_STATUS_TIMEOUT 3 // unit: second #define OCCUPANCY_FEE_TIMEOUT 10 // unit: second #define MIN_AVAILABLE_MEMORY 200 // unit: MB #define AUTO_START_CHARGING "AutoStartCharging" #define CONTACTOR_AUTO_ON_OFF 0 #define CONTACTOR_AUTO_ON_TIME 60 #define CONTACTOR_AUTO_OFF_TIME 300 #define WAIT_DISPENSER_STOP_TIMEOUT 3 // unit: second #define STARTTRANSATION_TIME 1 #define STOP_TARTTRANSATION_DELAY 2 #define WAIT_DIAGNOSTICS_CONFIRM 10 // unit: second #define WAIT_DIAGNOSTICS_TIMEOUT 120 // unit: second char *valid_Internet[2] = {"8.8.8.8", "180.76.76.76"}; unsigned char mask_table[] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 }; int whileLoopTime = 10000; // 10 ms int wtdFd = -1; byte _authorizeIndex = NO_DEFINE; BOOL _UpgradeNeedReboot = FALSE; bool _isBridgeModeConfig = false; #define GUN_DERATING_COUNT 2 const int GunDeratingTemp[GUN_DERATING_COUNT] = {80, 85}; const byte Group_to_Location_2_Gun[GENERAL_GUN_QUANTITY] = {0, 1, 0, 0}; const byte Location_to_Group_2_Gun[GENERAL_GUN_QUANTITY] = {0, 1, 0, 0}; const byte GroupParallelRelay_2_Gun[GENERAL_GUN_QUANTITY][GENERAL_GUN_QUANTITY] = { {0, 1, 0, 0}, {1, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0} }; //Location: 1 2 3 4 // Gun: 1 3 4 2 //Parallel: 1 2 3 //const byte Group_to_Location_4_Gun[GENERAL_GUN_QUANTITY] = {0, 3, 1, 2}; //const byte Location_to_Group_4_Gun[GENERAL_GUN_QUANTITY] = {0, 2, 3, 1}; //const byte GroupParallelRelay_4_Gun[GENERAL_GUN_QUANTITY][GENERAL_GUN_QUANTITY] = //{ // {0, 3, 1, 2}, // group 0 // {1, 0, 2, 3}, // group 1 // {1, 3, 0, 2}, // group 2 // {1, 3, 2, 0} // group 3 //}; //Location: 1 2 3 4 // Gun: 1 4 3 2 //Parallel: 1 2 3 const byte Group_to_Location_4_Gun[GENERAL_GUN_QUANTITY] = {0, 3, 2, 1}; const byte Location_to_Group_4_Gun[GENERAL_GUN_QUANTITY] = {0, 3, 2, 1}; const byte GroupParallelRelay_4_Gun[GENERAL_GUN_QUANTITY][GENERAL_GUN_QUANTITY] = { {0, 3, 2, 1}, // group 0 {1, 0, 3, 2}, // group 1 {1, 3, 0, 2}, // group 2 {1, 3, 2, 0} // group 3 }; const byte GroupParallelRelay_4_Gun_6Parallel[GENERAL_GUN_QUANTITY][GENERAL_GUN_QUANTITY] = { {0, 4, 6, 1}, // group 0 {4, 0, 3, 5}, // group 1 {6, 3, 0, 2}, // group 2 {1, 5, 2, 0} // group 3 }; long long DiffTimebWithNow(struct timeb ST); unsigned char DetectBitValue(unsigned char _byte, unsigned char _bit); void SetBitValue(unsigned char *_byte, unsigned char _bit, unsigned char value); void ChargingTerminalProcess(byte gunIndex); void ChkPrimaryStatus(); void ChargingAlarmProcess(byte gunIndex); void InformOcppErrOccur(byte codeType); void SetOcppErrorCode(unsigned char _index, char *errCode); void SetOcppVendorErrorCode(unsigned char _index, char *vendorCode); void ReleaseAlarmCode(byte gunIndex); int DB_Open(sqlite3 *db); int DB_Insert_Record(sqlite3 *db, int gun_index); int DB_Update_Operactive(sqlite3 *db, uint8_t gun_index, uint8_t IsAvailable); int DB_Get_Operactive(sqlite3 *db, uint8_t gun_index); void DB_Update_LocalConsumption(sqlite3 *db, uint8_t gun_index, float value); void DB_Update_GunConsumption(sqlite3 *db, uint8_t gun_index, float value); float DB_Get_LocalConsumption(sqlite3 *db, uint8_t gun_index); float DB_Get_GunConsumption(sqlite3 *db, uint8_t gun_index); float Get_PowerConsumption(uint8_t gun_index); void Update_PowerConsumption(uint8_t gun_index); int DB_Insert_FinalCost(sqlite3 *db, uint8_t gun_index, int txId, char *description); int DB_Update_FinalCost_Status(sqlite3 *db, int txId, int status); int DB_Get_Undisposed_FinalCost(sqlite3 *db, int gunIndex, char *costString); int DB_Reboot_Record(sqlite3 *db); int DB_Insert_Ocmf(sqlite3 *db, int gun_index, char *txId, char *ocmfKey, char *ocmfInfo); int DB_Update_Ocmf_Status(sqlite3 *db, char *txId, int status); int DB_Get_Undisposed_Ocmf(sqlite3 *db, int *gunIndex, char *txId, char *ocmfKey, char *ocmfInfo); void InitialDHCP(); void InitialDispenserDhcpServerConfig(void); void StartDispenserDhcpServer(void); int GetStartScheduleTime(unsigned char *time); void CheckConnectionTimeout(void); bool IsParallelCabinetIdle(void); bool IsStandbyEnable(void); bool IsGunIdle(int gunIndex, int idleType); bool IsDispenserIdle(int dispenserIndex); bool IsConnectorWholeIdle(void); void SetAcContactor(unsigned char OnOff); void UpdateErrorCodeToOcpp(byte index); bool CheckConnectorTypeStatus(void); void CreateWatchdog(void); void TryCloseWatchdog(void); void TryFeedWatchdog(void); bool IsReadyParalleling(void); void SetParallelingStart(void); void SetParallelingDone(void); void SetPCabinetOutputRelay(unsigned char index, unsigned char OnOff); void SetParallelCabinetAcContactor(unsigned char OnOff); unsigned short GetTotalParallelCabinetPower(void); void MCabinetParallelingProcess(void); void SCabinetControllProcess(void); bool Is_WebServer_Alive(void); void Run_WebServer_Service(void); bool Get_Ocpp_ConnectionStatus(void); void Run_Ocpp_Service(void); bool Is_Ocpp_Task_Alive(void); void Kill_Ocpp_Service(void); void Run_MaintainOcpp_Service(void); bool Is_MaintainOcpp_Task_Alive(void); void Kill_MaintainOcpp_Service(void); long int Get_Ocpp_procDogTime(void); void Clean_Ocpp_procDogTime(void); bool Is_Ocpp_BootNotification(void); void Clean_Ocpp_BootNotification(void); bool Is_Ocpp_ResetReq(void); bool Chk_Ocpp_Reset_Type(char *type); void Clean_Ocpp_ResetReq(void); void Set_Ocpp_AuthorizeReq(void); bool Is_Ocpp_AuthorizeConf(void); bool Is_Ocpp_Authorize_Status(char *status); bool Is_Ocpp_UpdateFirmwareReq(void); void Clean_Ocpp_UpdateFirmwareReq(void); bool Is_Ocpp_UpdateFirmwareStatus(char *status); void Set_Ocpp_UpdateFirmwareStatus(char *status); void Clean_Ocpp_UpdateFirmwareStatus(char *status); void Set_Ocpp_FirmwareStatusNotificationReq(void); bool Is_Ocpp_StopOnInvalidId_Enable(void); bool Is_Ocpp_AuthorizeRemoteTxRequests(void); int Get_Ocpp_ConnectionTimeOut(void); void Get_Ocpp_DefaultPrice(char *defaultPrice); void Get_Ocpp_UserPrice(char * userId, char *userPrice); void Clean_Ocpp_UserPrice(void); void Get_Ocpp_RunningCost(int gun_index, char *cost); void Clean_Ocpp_RunningCost(int gun_index); void Get_Ocpp_FinalCost(int gun_index, char *cost); void Clean_Ocpp_FinalCost(int gun_index); int Get_Ocpp_FinalCostTxId(int gun_index); void Get_Ocpp_TimeOffset(char *timeOffset); void Get_Ocpp_PreAuthAmount(char *amount); void Get_Ocpp_PowerSharingServerIP(char *ip); void Get_Ocpp_Refunding(char *Refunding); void Clean_Ocpp_Refunding(void); bool Is_Ocpp_LcdOverideReq(int *gun, int *page); void Clean_Ocpp_LcdOverideReq(void); void Get_Ocpp_ChargerStationInfo(int *station_id, char *name); bool Is_Ocpp_ChargerStationReq(void); void Clean_Ocpp_ChargerStationReq(void); void Get_Ocpp_WeatherInfo(int *weatherID, float *temperature); bool Is_Ocpp_WeatherReq(void); void Clean_Ocpp_WeatherReq(void); void Set_Ocpp_DeductTransaction(int transaction); void Set_Ocpp_DeductCreditNo(char *userId); void Set_Ocpp_DeductVemData(char *vemData); void Set_Ocpp_DeductAmount(double value); void Set_Ocpp_DeductResult(unsigned char result); void Set_Ocpp_DonateInvoice(unsigned char donate); bool Is_Ocpp_ReportCreditDeductReq(void); void Set_Ocpp_ReportCreditDeductReq(void); void Clean_Ocpp_TcciSerialNo(int gun_index); bool Set_Ocpp_TcciReaderStatus(int gun_index, DeductResultInfoData *ReaderStatus); void Clean_Ocpp_TcciCreditInfo(int gun_index); void Set_Ocpp_TcciReaderStatusReq(int gun_index); bool Is_Ocpp_TcciReaderStatusReq(int gun_index); void Set_Ocpp_StartTransactionIdTag(int gun_index, char *id); void Set_Ocpp_StartTransactionReq(int gun_index); bool Is_Ocpp_StartTransactionConf(int gun_index); void Clean_Ocpp_StartTransactionConf(int gun_index); bool Is_Ocpp_StartTransaction_Status(int gun_index, char *status); bool Is_Ocpp_StartTransaction_Accepted(int gun_index); void Get_Ocpp_StartTransaction_Status(int gun_index, char *status); void Get_Ocpp_TransactionId(int gun_index, char *transactionId); bool Is_Invalid_StartTransactionId(int gun_index); void Set_Ocpp_StopTransactionId(int gun_index, char *id); void Set_Ocpp_StopTransactionReq(int gun_index); void Chk_Ocpp_Backup_ErrorCode(int gun_index); bool Is_Ocpp_ReserveNowReq(int gun_index); void Clean_Ocpp_ReserveNowReq(int gun_index); int Get_Ocpp_ReserveNowId(int gun_index); void Set_Ocpp_ReserveNowConf(int gun_index); void Get_Ocpp_ReserveNowExpiryDate(int gun_index, char *date); bool Is_Ocpp_ReserveNowExpired(int gun_index); void Get_Ocpp_ReserveNowIdTag(int gun_index, char *idTag); bool Is_Ocpp_ReserveNowIdTag(uint8_t gun_index, char *authIdTag); bool Is_Ocpp_CancelReservationReq(int gun_index); void Clean_Ocpp_CancelReservationReq(int gun_index); void Set_Ocpp_CancelReservationConf(int gun_index); bool Is_Ocpp_ChangeAvailabilityReq(int gun_index); void Clean_Ocpp_ChangeAvailabilityReq(int gun_index); bool Chk_Ocpp_Availability_Type(int gun_index, char *type); bool Is_Ocpp_UnlockConnectorReq(int gun_index); void Clean_Ocpp_UnlockConnectorReq(int gun_index); void Set_Ocpp_UnlockConnectorConf(int gun_index); bool Is_Ocpp_RemoteStartReq(int gun_index); void Clean_Ocpp_RemoteStartReq(int gun_index); void Get_Ocpp_RemoteStartIdTag(int gun_index, char *idTag); bool Is_Ocpp_RemoteStopReq(int gun_index); void Clean_Ocpp_RemoteStopReq(int gun_index); void Set_Ocpp_StopReason(int gun_index, char *reason); void Get_Ocpp_StopReason(int gun_index, char *reason); void Clean_Ocpp_StopReason(int gun_index); void Set_Ocpp_StatusNotificationErrorCode(int gun_index, char *errCode); bool Is_Ocpp_StatusNotificationErrorCode(int gun_index, char *errCode); void Set_Ocpp_StatusNotificationVendorCode(int gun_index, char *vendorCode); bool Is_Ocpp_StatusNotificationVendorCode(int gun_index, char *vendorCode); bool Is_Ocpp_ChargingProfileConf(int gun_index); void Clean_Ocpp_ChargingProfileConf(int gun_index); bool Is_Ocpp_ChargingProfileReq(int gun_index); void Set_Ocpp_ChargingProfileReq(int gun_index); bool Is_Ocpp_ChargingProfileKind(int gun_index, char *kind); bool Is_Ocpp_ChargingProfileId(int gun_index); int Get_Ocpp_ChargingProfileStartTime(int gun_index); int Get_Ocpp_ChargingProfileScheduleCount(int gun_index); int Get_Ocpp_ChargingProfileScheduleTime(int gun_index, int schedule_index); float Get_Ocpp_ChargingProfileScheduleLimit(int gun_index, int schedule_index); int Get_Ocpp_ChargingProfileScheduleNumberPhases(int gun_index, int schedule_index); int Get_Ocpp_ChargingProfileStartIndex(int gun_index); bool Is_Ocpp_MaxChargingProfileKind(char *kind); bool Is_Ocpp_MaxChargingProfileId(void); int Get_Ocpp_MaxProfileStartTime(void); int Get_Ocpp_MaxProfileScheduleCount(void); int Get_Ocpp_MaxProfileScheduleTime(int schedule_index); float Get_Ocpp_MaxProfileScheduleLimit(int schedule_index); int Get_Ocpp_MaxProfileScheduleNumberPhases(int schedule_index); int Get_Ocpp_MaxProfileStartIndex(void); int Is_Ocpp_RemoteStartWaitReq(void); void Get_Ocpp_SessionTarget(int gunIndex, struct StructSessionTarget *sessionTarget); int Get_Ocpp_OffLineMaxChargingPower(void); bool Is_Ocpp_SendOcmfDataReq(int gunIndex); void Set_Ocpp_SendOcmfDataReq(int gunIndex); void Clean_Ocpp_SendOcmfDataReq(int gunIndex); void Set_Ocpp_OcmfData(int gunIndex, char *key, char *ocmfInfo); void Set_Deduct_UserId(int gunIndex, char *userId); void Set_Deduct_TransactionId(int gunIndex, int transaction); void Clean_DeductInfo(int gunIndex); bool Is_DeductResultReq(int gunIndex); bool Is_ReaderStatusReq(int gunIndex); void Clean_ReaderStatusInfo(int gunIndex); void Set_UserTransactionId(int gunIndex, int transaction); void Set_UserPrice(int gunIndex, float price); void Set_UserTotalCost(int gunIndex, float cost); void Set_UserAccountBalance(int gunIndex, float balance); void Set_UserDiscount(int gunIndex, float discount); void Clean_UserTransaction(int gunIndex); bool Is_OccupancyDeductReq(int gunIndex); void Clean_OccupancyDeductReq(int gunIndex); bool Is_OccupancyKeepCountingReq(int gunIndex); void Set_OccupancyKeepCountingReq(int gunIndex); void Clean_OccupancyKeepCountingReq(int gunIndex); bool Is_OccupancyFeeForceCancelReq(int gunIndex); void Set_OccupancyFeeForceCancelReq(int gunIndex); void Clean_OccupancyFeeForceCancelReq(int gunIndex); bool Is_Ocpp_GetDiagnosticsReq(void); void Clean_Ocpp_GetDiagnosticsReq(void); struct SysConfigAndInfo *ShmSysConfigAndInfo; struct StatusCodeData *ShmStatusCodeData; struct PsuData *ShmPsuData; struct CHAdeMOData *ShmCHAdeMOData; struct GBTData *ShmGBTData; struct CcsData *ShmCcsData; struct PrimaryMcuData *ShmPrimaryMcuData; struct FanModuleData *ShmFanModuleData; struct RelayModuleData *ShmRelayModuleData[2]; struct LedModuleData *ShmLedModuleData; struct OCPP16Data *ShmOCPP16Data; struct OCPP20Data *ShmOCPP20Data; struct OCPP16Data *ShmOCPP16DataPH; struct MeterInformation *ShmCsuMeterData; ChargerInfoData *ShmChargerInfo; PsuPositionInfoData *ShmPsuPosition; PsuGroupingInfoData *ShmPsuGrouping; struct ChargingInfoData *chargingInfo[CONNECTOR_QUANTITY]; struct ChargingInfoData *ac_chargingInfo[AC_QUANTITY]; struct timespec _cmdMainPriority_time; struct timespec _cmdSubPriority_time; struct timespec _ConnectorAuthorizing_Time[CONNECTOR_QUANTITY]; struct timespec _ConnectorAuthorizeFail_Time[CONNECTOR_QUANTITY]; struct timespec _DispenserAuthorizing_Time[CONNECTOR_QUANTITY]; struct timespec _DispenserUpgrade_time; struct timespec _Standby_time; struct timespec _SystemStatus_Time[CONNECTOR_QUANTITY]; struct timespec _ChargedEnergy_Time[CONNECTOR_QUANTITY]; struct timespec _Parallel_Time; struct timespec _RemoteStartNoId_Time; float gunOutputVol[CONNECTOR_QUANTITY]; unsigned char _ocppProfileChkFlag[CONNECTOR_QUANTITY]; float _lastProfilePower[CONNECTOR_QUANTITY]; float _lastProfileCurrent[CONNECTOR_QUANTITY]; float _lastMaxProfilePower; float _lsatGunMeterValue[CONNECTOR_QUANTITY]; struct StructStatusNotification _BackupStatusNotification[CONNECTOR_QUANTITY]; bool _useGunMeterValue[MAX_GUN_QUANTITY]; bool _triggerTransaction[MAX_GUN_QUANTITY]; bool _plugInHold[MAX_GUN_QUANTITY]; struct timespec _PlugInHold_Time[MAX_GUN_QUANTITY]; struct timespec _DispenserBill_Time[MAX_DISPENSER_QUANTITY]; struct timespec _ConnectorBill_Time[MAX_GUN_QUANTITY]; struct timespec _ParkingStatus_Time[MAX_GUN_QUANTITY]; struct timespec _GetOccupancyFee_Time[MAX_GUN_QUANTITY]; struct timespec _Diagnostics_Time; bool _canUpdateFinalCost[MAX_DISPENSER_QUANTITY]; bool _isUndisposedFinalCost[MAX_DISPENSER_QUANTITY]; int _notifyOccupancyFeeAct[MAX_GUN_QUANTITY]; bool _NeedReset4gWifi; struct timespec _4gWifiReset_time; int _psuLostQuantity = 0; bool _isStandbyEnable = true; bool isModelNameMatch = true; bool _NeedDiagnostics = false; //int rfidFd = -1; //char* rfidPortName = "/dev/ttyS2"; #if ENABLE_PCBA_TEST == 0 char* fwVersion = "V2.05.00.0000.00"; char* subVersion = "03"; #else char* fwVersion = "PCBA.00.04"; char* subVersion = "00"; #endif sqlite3 *localDb; bool isDb_ready; sqlite3 *networkDb; //================================================ // initial can-bus //================================================ int InitCanBus() { int s0,nbytes; struct timeval tv; struct ifreq ifr0; struct sockaddr_can addr0; system("/sbin/ip link set can0 down"); system("/sbin/ip link set can0 type can bitrate 500000 restart-ms 100"); system("/sbin/ip link set can0 up"); s0 = socket(PF_CAN, SOCK_RAW, CAN_RAW); tv.tv_sec = 0; tv.tv_usec = 10000; if (setsockopt(s0, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(struct timeval)) < 0) { #ifdef SystemLogMessage LOG_ERROR("Set SO_RCVTIMEO NG"); #endif } nbytes=40960; if (setsockopt(s0, SOL_SOCKET, SO_RCVBUF, &nbytes, sizeof(int)) < 0) { #ifdef SystemLogMessage LOG_ERROR("Set SO_RCVBUF NG"); #endif } nbytes=40960; if (setsockopt(s0, SOL_SOCKET, SO_SNDBUF, &nbytes, sizeof(int)) < 0) { #ifdef SystemLogMessage LOG_ERROR("Set SO_SNDBUF NG"); #endif } strcpy(ifr0.ifr_name, "can0" ); ioctl(s0, SIOCGIFINDEX, &ifr0); /* ifr.ifr_ifindex gets filled with that device's index */ addr0.can_family = AF_CAN; addr0.can_ifindex = ifr0.ifr_ifindex; bind(s0, (struct sockaddr *)&addr0, sizeof(addr0)); return s0; } //================================================ // initial uart port //================================================ char *_priPortName = "/dev/ttyS1"; char *_485PortName = "/dev/ttyS5"; int InitComPort(byte target) { int fd; struct termios tios; if(target == UPGRADE_PRI) fd = open(_priPortName, O_RDWR); else if (target == UPGRADE_FAN || target == UPGRADE_RB || target == UPGRADE_AC || target == UPGRADE_LED) fd = open(_485PortName, O_RDWR); if(fd<=0) { #ifdef SystemLogMessage LOG_ERROR("open 407 Communication port NG"); #endif return -1; } ioctl (fd, TCGETS, &tios); tios.c_cflag = B115200| CS8 | CLOCAL | CREAD; tios.c_lflag = 0; tios.c_iflag = 0; tios.c_oflag = 0; tios.c_cc[VMIN]=0; tios.c_cc[VTIME]=(unsigned char)1; tios.c_lflag=0; tcflush(fd, TCIFLUSH); ioctl (fd, TCSETS, &tios); return fd; } //================================= // Common routine //================================= void substr(char *dest, const char* src, unsigned int start, unsigned int cnt) { strncpy(dest, src + start, cnt); dest[cnt] = 0; } int InitWatchDog() { int fd; int timeout = 180; system("/usr/bin/fuser -k /dev/watchdog"); sleep(1); system("echo V > /dev/watchdog"); sleep(1); fd=open("/dev/watchdog", O_RDWR); if(fd<=0) { LOG_ERROR("System watch dog initial fail.\r\n"); } ioctl(fd, _IOWR('W', 6, int), &timeout); return fd; } void setChargerMode(byte gun_index, byte mode) { chargingInfo[gun_index]->SystemStatus = mode; } long long DiffTimebWithNow(struct timeb ST) { //return milli-second struct timeb ET; long long StartTime,StopTime; ftime(&ET); StartTime=(long long)ST.time; StopTime=(long long)ET.time; return ((StopTime-StartTime)*1000) + (ET.millitm-ST.millitm); } //================================= // Create all share memory //================================= int CreateShareMemory() { int MeterSMId; if ((MeterSMId = shmget(ShmSysConfigAndInfoKey, sizeof(struct SysConfigAndInfo), IPC_CREAT | 0777)) < 0) { #ifdef SystemLogMessage LOG_ERROR("[main]CreatShareMemory:shmget ShmSysConfigAndInfo NG"); #endif return 0; } else if ((ShmSysConfigAndInfo = shmat(MeterSMId, NULL, 0)) == (void *) -1) { #ifdef SystemLogMessage LOG_ERROR("[main]CreatShareMemory:shmat ShmSysConfigAndInfo NG"); #endif return 0; } memset(ShmSysConfigAndInfo, 0, sizeof(struct SysConfigAndInfo)); if ((MeterSMId = shmget(ShmStatusCodeKey, sizeof(struct StatusCodeData), IPC_CREAT | 0777)) < 0) { #ifdef SystemLogMessage LOG_ERROR("[main]CreatShareMemory:shmget ShmStatusCodeData NG"); #endif return 0; } else if ((ShmStatusCodeData = shmat(MeterSMId, NULL, 0)) == (void *) -1) { #ifdef SystemLogMessage LOG_ERROR("[main]CreatShareMemory:shmat ShmStatusCodeData NG"); #endif return 0; } memset(ShmStatusCodeData, 0, sizeof(struct StatusCodeData)); //creat ShmPsuData if ((MeterSMId = shmget(ShmPsuKey, sizeof(struct PsuData), IPC_CREAT | 0777)) < 0) { #ifdef SystemLogMessage LOG_ERROR("[main]CreatShareMemory:shmget ShmPsuData NG"); #endif return 0; } else if ((ShmPsuData = shmat(MeterSMId, NULL, 0)) == (void *) -1) { #ifdef SystemLogMessage LOG_ERROR("[main]CreatShareMemory:shmat ShmPsuData NG"); #endif return 0; } memset(ShmPsuData, 0, sizeof(struct PsuData)); /* if(CHAdeMO_QUANTITY > 0) { if ((MeterSMId = shmget(ShmCHAdeMOCommKey, sizeof(struct CHAdeMOData), IPC_CREAT | 0777)) < 0) { #ifdef SystemLogMessage LOG_ERROR("[main]CreatShareMemory:shmget ShmCHAdeMOData NG"); #endif return 0; } else if ((ShmCHAdeMOData = shmat(MeterSMId, NULL, 0)) == (void *) -1) { #ifdef SystemLogMessage LOG_ERROR("[main]CreatShareMemory:shmat ShmCHAdeMOData NG"); #endif return 0; } memset(ShmCHAdeMOData, 0, sizeof(struct CHAdeMOData)); } if(GB_QUANTITY > 0) { if ((MeterSMId = shmget(ShmGBTCommKey, sizeof(struct GBTData), IPC_CREAT | 0777)) < 0) { #ifdef SystemLogMessage LOG_ERROR("[main]CreatShareMemory:shmget ShmGBTData NG"); #endif return 0; } else if ((ShmGBTData = shmat(MeterSMId, NULL, 0)) == (void *) -1) { #ifdef SystemLogMessage LOG_ERROR("[main]CreatShareMemory:shmat ShmGBTData NG"); #endif return 0; } memset(ShmGBTData, 0, sizeof(struct GBTData)); } //creat ShmCcsData if(CCS_QUANTITY > 0) { if ((MeterSMId = shmget(ShmCcsCommKey, sizeof(struct CcsData), IPC_CREAT | 0777)) < 0) { #ifdef SystemLogMessage LOG_ERROR("[main]CreatShareMemory:shmget ShmCcsData NG"); #endif return 0; } else if ((ShmCcsData = shmat(MeterSMId, NULL, 0)) == (void *) -1) { #ifdef SystemLogMessage LOG_ERROR("[main]CreatShareMemory:shmat ShmCcsData NG"); #endif return 0; } memset(ShmCcsData, 0, sizeof(struct CcsData)); } */ //creat ShmPrimaryMcuData if ((MeterSMId = shmget(ShmPrimaryMcuKey, sizeof(struct PrimaryMcuData), IPC_CREAT | 0777)) < 0) { #ifdef SystemLogMessage LOG_ERROR("[main]CreatShareMemory:shmget ShmPrimaryMcuData NGn"); #endif return 0; } else if ((ShmPrimaryMcuData = shmat(MeterSMId, NULL, 0)) == (void *) -1) { #ifdef SystemLogMessage LOG_ERROR("[main]CreatShareMemory:shmat ShmPrimaryMcuData NG"); #endif return 0; } memset(ShmPrimaryMcuData, 0, sizeof(struct PrimaryMcuData)); //creat ShmFanModuleData if ((MeterSMId = shmget(ShmFanBdKey, sizeof(struct FanModuleData), IPC_CREAT | 0777)) < 0) { #ifdef SystemLogMessage LOG_ERROR("[main]CreatShareMemory:shmget ShmFanModuleData NG"); #endif return 0; } else if ((ShmFanModuleData = shmat(MeterSMId, NULL, 0)) == (void *) -1) { #ifdef SystemLogMessage LOG_ERROR("[main]CreatShareMemory:shmat ShmFanModuleData NG"); #endif return 0; } memset(ShmFanModuleData, 0, sizeof(struct FanModuleData)); //creat ShmRelayModuleData if ((MeterSMId = shmget(ShmRelayBdKey, sizeof(struct RelayModuleData), IPC_CREAT | 0777)) < 0) { #ifdef SystemLogMessage LOG_ERROR("[main]CreatShareMemory:shmget ShmRelayModuleData[0] NG"); #endif return 0; } else if ((ShmRelayModuleData[0] = shmat(MeterSMId, NULL, 0)) == (void *) -1) { #ifdef SystemLogMessage LOG_ERROR("[main]CreatShareMemory:shmat ShmRelayModuleData[0] NG"); #endif return 0; } memset(ShmRelayModuleData[0], 0, sizeof(struct RelayModuleData)); // DO360 RC2 if ((MeterSMId = shmget(ShmRelay2BdKey, sizeof(struct RelayModuleData), IPC_CREAT | 0777)) < 0) { #ifdef SystemLogMessage LOG_ERROR("[main]CreatShareMemory:shmget ShmRelayModuleData[1] NG"); #endif return 0; } else if ((ShmRelayModuleData[1] = shmat(MeterSMId, NULL, 0)) == (void *) -1) { #ifdef SystemLogMessage LOG_ERROR("[main]CreatShareMemory:shmat ShmRelayModuleData[1] NG"); #endif return 0; } memset(ShmRelayModuleData[1], 0, sizeof(struct RelayModuleData)); if ((MeterSMId = shmget(ShmLedBdKey, sizeof(struct LedModuleData), IPC_CREAT | 0777)) < 0) { #ifdef SystemLogMessage LOG_ERROR("[main]CreatShareMemory:shmget ShmLedModuleData NG"); #endif return 0; } else if ((ShmLedModuleData = shmat(MeterSMId, NULL, 0)) == (void *) -1) { #ifdef SystemLogMessage LOG_ERROR("[main]CreatShareMemory:shmat ShmLedModuleData NG"); #endif return 0; } memset(ShmLedModuleData, 0, sizeof(struct LedModuleData)); //creat ShmOCPP16Data if ((MeterSMId = shmget(ShmOcppModuleKey, sizeof(struct OCPP16Data), IPC_CREAT | 0777)) < 0) { #ifdef SystemLogMessage LOG_ERROR("[main]CreatShareMemory:shmget ShmOCPP16Data NG"); #endif return 0; } else if ((ShmOCPP16Data = shmat(MeterSMId, NULL, 0)) == (void *) -1) { #ifdef SystemLogMessage LOG_ERROR("[main]CreatShareMemory:shmat ShmOCPP16Data NG"); #endif return 0; } memset(ShmOCPP16Data,0,sizeof(struct OCPP16Data)); if ((MeterSMId = shmget(ShmOcpp20ModuleKey, sizeof(struct OCPP20Data), IPC_CREAT | 0777)) < 0) { LOG_ERROR("[main]CreatShareMemory:shmget OCPP20Data NG"); return 0; } else if ((ShmOCPP20Data = shmat(MeterSMId, NULL, 0)) == (void *) -1) { LOG_ERROR("[main]CreatShareMemory:shmat OCPP20Data NG"); return 0; } memset(ShmOCPP20Data,0,sizeof(struct OCPP20Data)); //creat ShmOCPP16DataPH if ((MeterSMId = shmget(ShmOcppPHModuleKey, sizeof(struct OCPP16Data), IPC_CREAT | 0777)) < 0) { LOG_ERROR("shmget ShmOCPP16DataPH NG"); return 0; } else if ((ShmOCPP16DataPH = shmat(MeterSMId, NULL, 0)) == (void *) -1) { LOG_ERROR("shmat ShmOCPP16DataPH NG"); return 0; } memset(ShmOCPP16DataPH,0,sizeof(struct OCPP16Data)); if ((MeterSMId = shmget(SM_ChargerInfoKey, sizeof(ChargerInfoData), IPC_CREAT | 0777)) < 0) { #ifdef SystemLogMessage LOG_ERROR("[main]CreatShareMemory:shmget ChargerInfoData NG"); #endif return 0; } else if ((ShmChargerInfo = shmat(MeterSMId, NULL, 0)) == (void *) -1) { #ifdef SystemLogMessage LOG_ERROR("[main]CreatShareMemory:shmat ChargerInfoData NG"); #endif return 0; } memset(ShmChargerInfo, 0, sizeof(ChargerInfoData)); ShmPsuPosition = &ShmChargerInfo->PsuPosition; ShmPsuGrouping = &ShmChargerInfo->PsuGrouping; return 1; } //====================================================== // Peripheral initial //====================================================== void InitGPIO() { /*****************0~3, 4 bank, bank x 32+ num*********************/ /***************************************************************/ /*************** GPIO 0 ***************************************/ /***************************************************************/ /* GPMC_AD8 => GPIO0_22 *//*ID BD1_1*/ // no use system("echo 22 > /sys/class/gpio/export"); system("echo \"in\" > /sys/class/gpio/gpio22/direction"); /* GPMC_AD9 => GPIO0_23 *//*ID BD1_2*/ // no use system("echo 23 > /sys/class/gpio/export"); system("echo \"in\" > /sys/class/gpio/gpio23/direction"); /* GPMC_AD10 => GPIO0_26 *//*IO BD1_1*/ // no use system("echo 26 > /sys/class/gpio/export"); system("echo \"out\" > /sys/class/gpio/gpio26/direction"); system("echo 1 > /sys/class/gpio/gpio26/value"); /* GPMC_AD11 => GPIO0_27 *//*IO BD1_2*/ // no use system("echo 27 > /sys/class/gpio/export"); system("echo \"in\" > /sys/class/gpio/gpio27/direction"); /* RMII1_REF_CLK => GPIO0_29 *//*USB 0 OCP detection*/ system("echo 29 > /sys/class/gpio/export"); system("echo \"in\" > /sys/class/gpio/gpio29/direction"); /*XDMA_EVENT_INTR0 => GPIO0_19 *//*AM_RFID_RST*/ // no use system("echo 19 > /sys/class/gpio/export"); system("echo \"out\" > /sys/class/gpio/gpio19/direction"); system("echo 1 > /sys/class/gpio/gpio19/value"); /*XDMA_EVENT_INTR1 => GPIO0_20 *//*AM_RFID_ICC*/ // no use system("echo 20 > /sys/class/gpio/export"); system("echo \"in\" > /sys/class/gpio/gpio20/direction"); /***************************************************************/ /*************** GPIO 1 ***************************************/ /***************************************************************/ /* GPMC_AD12 => GPIO1_12 *//*ID BD2_1*/ // no use system("echo 44 > /sys/class/gpio/export"); system("echo \"in\" > /sys/class/gpio/gpio44/direction"); /* GPMC_AD13 => GPIO1_13 *//*ID BD2_2*/ // no use system("echo 45 > /sys/class/gpio/export"); system("echo \"in\" > /sys/class/gpio/gpio45/direction"); /* GPMC_AD14 => GPIO1_14 *//*IO BD2_1*/ // no use system("echo 46 > /sys/class/gpio/export"); system("echo \"out\" > /sys/class/gpio/gpio46/direction"); system("echo 0 > /sys/class/gpio/gpio46/value"); /* GPMC_AD15 => GPIO1_15 *//*IO BD2_2*/ // no use system("echo 47 > /sys/class/gpio/export"); system("echo \"in\" > /sys/class/gpio/gpio47/direction"); /***************************************************************/ /*************** GPIO 2 ***************************************/ /***************************************************************/ /*LCD_AC_BIAS_EN => GPIO2_25*//*RS-485 for module DE control*/ system("echo 89 > /sys/class/gpio/export"); system("echo \"out\" > /sys/class/gpio/gpio89/direction"); system("echo 1 > /sys/class/gpio/gpio89/value"); /*LCD_HSYNC => GPIO2_23*//*RS-485 for module RE control*/ system("echo 87 > /sys/class/gpio/export"); system("echo \"out\" > /sys/class/gpio/gpio87/direction"); system("echo 0 > /sys/class/gpio/gpio87/value"); /*LCD_PCLK => GPIO2_24*//*CCS communication board 1 proximity*/ // no use system("echo 88 > /sys/class/gpio/export"); system("echo \"in\" > /sys/class/gpio/gpio88/direction"); /*LCD_VSYNC => GPIO2_22*//*CCS communication board 2 proximity*/ // no use system("echo 86 > /sys/class/gpio/export"); system("echo \"in\" > /sys/class/gpio/gpio86/direction"); /***************************************************************/ /*************** GPIO 3 ***************************************/ /***************************************************************/ /*MCASP0_FSX => GPIO3_15*//*Emergency Stop button detect*/ system("echo 111 > /sys/class/gpio/export"); system("echo \"in\" > /sys/class/gpio/gpio111/direction"); /*MCASP0_ACLKR => GPIO3_18*//*USB1 OCP detect*/ system("echo 114 > /sys/class/gpio/export"); system("echo \"in\" > /sys/class/gpio/gpio114/direction"); /*MCASP0_AHCLKR => GPIO3_17*//*Emergency IO for AM3352 and STM32F407*/ system("echo 113 > /sys/class/gpio/export"); system("echo \"in\" > /sys/class/gpio/gpio113/direction"); /*MCASP0_ACLKX => GPIO3_14*//*Ethernet PHY reset*/ system("echo 110 > /sys/class/gpio/export"); system("echo \"out\" > /sys/class/gpio/gpio110/direction"); system("echo 0 > /sys/class/gpio/gpio110/value"); /* MCASP0_FSR => GPIO3_19 *//*SMR Enable control_1 for Pskill_1*/ // no use system("echo 115 > /sys/class/gpio/export"); system("echo \"out\" > /sys/class/gpio/gpio115/direction"); system("echo 0 > /sys/class/gpio/gpio115/value"); /* MCASP0_AXR0 => GPIO3_16 *//*CSU board function OK indicator.*/ system("echo 112 > /sys/class/gpio/export"); system("echo \"out\" > /sys/class/gpio/gpio112/direction"); system("echo 1 > /sys/class/gpio/gpio112/value"); /* MCASP0_AXR1 => GPIO3_20 *//*SMR Enable control_2 for Pskill_2*/ // no use system("echo 116 > /sys/class/gpio/export"); system("echo \"out\" > /sys/class/gpio/gpio116/direction"); system("echo 0 > /sys/class/gpio/gpio116/value"); /* (C14) EMU0.gpio3[7] */ /*CP open/short feature enable/disable, pull low for default enable*/ system("echo 103 > /sys/class/gpio/export"); system("echo \"out\" > /sys/class/gpio/gpio103/direction"); system("echo 0 > /sys/class/gpio/gpio103/value"); /* (B14) EMU1.gpio3[8] */ /*4G module reset, pull high to reset when entry kernel, after Application start, it should be pull low.*/ system("echo 104 > /sys/class/gpio/export"); system("echo \"out\" > /sys/class/gpio/gpio104/direction"); system("echo 0 > /sys/class/gpio/gpio104/value"); LOG_INFO("[main]InitGPIO: Initial GPIO OK"); } int LoadSysConfigAndInfo(struct SysConfigData *ptr) { int fd, wrd; unsigned char *buf; unsigned int ChkSum, ChkSumOrg; if((buf = malloc(MtdBlockSize)) == NULL) { LOG_ERROR("malloc buffer NG, rebooting..\n"); if(ShmStatusCodeData!=NULL) { ShmStatusCodeData->AlarmCode.AlarmEvents.bits.CsuInitFailed=1; } sleep(5); system("reboot -f"); sleep(5); system("reboot -f"); } memset(buf, 0, MtdBlockSize); //================================================ // Load configuration from mtdblock10 //================================================ system("nanddump /dev/mtd10 -f /mnt/EvseConfig.bin"); fd = open("/mnt/EvseConfig.bin", O_RDWR); if(fd < 0) { free(buf); LOG_ERROR("open mtdblock10 NG, rebooting..\n"); if(ShmStatusCodeData != NULL) { ShmStatusCodeData->AlarmCode.AlarmEvents.bits.CsuInitFailed = 1; } sleep(5); system("reboot -f"); sleep(5); system("reboot -f"); } wrd = read(fd, buf, MtdBlockSize); close(fd); if(wrd < MtdBlockSize) { free(buf); LOG_ERROR("read SysConfigData data NG, rebooting..\n"); if(ShmStatusCodeData != NULL) { ShmStatusCodeData->AlarmCode.AlarmEvents.bits.CsuInitFailed = 1; } sleep(5); system("reboot -f"); sleep(5); system("reboot -f"); } ChkSum = 0; for(wrd = ARRAY_SIZE(ptr->CsuBootLoadFwRev); wrd < MtdBlockSize - 4; wrd++) { ChkSum += buf[wrd]; } memcpy(&ChkSumOrg, buf + (MtdBlockSize - 4), sizeof(ChkSumOrg)); memcpy(&ptr->ModelName, buf + (ARRAY_SIZE(ptr->CsuBootLoadFwRev)), ARRAY_SIZE(ptr->ModelName)); memcpy(&ptr->SerialNumber, buf + (ARRAY_SIZE(ptr->CsuBootLoadFwRev) + ARRAY_SIZE(ptr->ModelName) + ARRAY_SIZE(ptr->AcModelName)), ARRAY_SIZE(ptr->SerialNumber)); //================================================ // Load configuration from mtdblock11 //================================================ if(ChkSum != ChkSumOrg) { LOG_ERROR("Primary SysConfigData checksum NG, read backup\n"); system("nanddump /dev/mtd11 -f /mnt/EvseConfig.bin"); fd = open("/mnt/EvseConfig.bin", O_RDWR); if(fd < 0) { free(buf); LOG_ERROR("open mtdblock11 (backup) NG, rebooting..\n"); if(ShmStatusCodeData != NULL) { ShmStatusCodeData->AlarmCode.AlarmEvents.bits.CsuInitFailed = 1; } sleep(5); system("reboot -f"); sleep(5); system("reboot -f"); } memset(buf, 0, MtdBlockSize); wrd = read(fd, buf, MtdBlockSize); close(fd); if(wrd < MtdBlockSize) { free(buf); LOG_ERROR("read backup SysConfigData data NG, rebooting..\n"); if(ShmStatusCodeData != NULL) { ShmStatusCodeData->AlarmCode.AlarmEvents.bits.CsuInitFailed = 1; } sleep(5); system("reboot -f"); sleep(5); system("reboot -f"); } ChkSum = 0; for(wrd = ARRAY_SIZE(ptr->CsuBootLoadFwRev); wrd < MtdBlockSize - 4; wrd++) { ChkSum += buf[wrd]; } memcpy(&ChkSumOrg, buf + (MtdBlockSize - 4), sizeof(ChkSumOrg)); //================================================ // Load configuration from mtdblock12 (Factory default) //================================================ if(ChkSum != ChkSumOrg) { LOG_ERROR("backup SysConfigData checksum NG, read Factory default\n"); system("nanddump /dev/mtd12 -f /mnt/EvseConfig.bin"); fd = open("/mnt/EvseConfig.bin", O_RDWR); if(fd < 0) { free(buf); LOG_ERROR("open mtdblock12 (Factory default) NG, rebooting..\n"); if(ShmStatusCodeData != NULL) { ShmStatusCodeData->AlarmCode.AlarmEvents.bits.CsuInitFailed = 1; } sleep(5); system("reboot -f"); sleep(5); system("reboot -f"); } memset(buf, 0, MtdBlockSize); wrd = read(fd, buf, MtdBlockSize); close(fd); if(wrd < MtdBlockSize) { free(buf); LOG_ERROR("read factory default SysConfigData data NG, rebooting..\n"); if(ShmStatusCodeData != NULL) { ShmStatusCodeData->AlarmCode.AlarmEvents.bits.CsuInitFailed = 1; } sleep(5); system("reboot -f"); sleep(5); system("reboot -f"); } ChkSum = 0; for(wrd = ARRAY_SIZE(ptr->CsuBootLoadFwRev); wrd < MtdBlockSize - 4; wrd++) { ChkSum += buf[wrd]; } memcpy(&ChkSumOrg, buf + (MtdBlockSize - 4), sizeof(ChkSumOrg)); memcpy(buf + (ARRAY_SIZE(ptr->CsuBootLoadFwRev)), &ptr->ModelName, ARRAY_SIZE(ptr->ModelName)); memcpy(buf + (ARRAY_SIZE(ptr->CsuBootLoadFwRev) + ARRAY_SIZE(ptr->ModelName) + ARRAY_SIZE(ptr->AcModelName)), &ptr->SerialNumber, ARRAY_SIZE(ptr->SerialNumber)); if(ChkSum != ChkSumOrg) { LOG_ERROR("factory default SysConfigData checksum NG, restore factory default\n"); free(buf); system("cd /root;./FactoryConfig -m"); system("rm -f /Storage/OCPP/OCPPConfiguration"); system("sync"); sleep(5); system("reboot -f"); sleep(5); system("reboot -f"); return FAIL; } } } //load OK memcpy((struct SysConfigData *)ptr, buf, sizeof(struct SysConfigData)); free(buf); system("rm -f /mnt/EvseConfig.bin"); // SysConfig in flash is empty (0xffffffff) if((strlen((char*)ShmSysConfigAndInfo->SysConfig.ModelName) > ARRAY_SIZE(ShmSysConfigAndInfo->SysConfig.ModelName)) || (strlen((char*)ShmSysConfigAndInfo->SysConfig.SerialNumber) > ARRAY_SIZE(ShmSysConfigAndInfo->SysConfig.SerialNumber)) || (strlen((char*)ShmSysConfigAndInfo->SysConfig.SystemId) > ARRAY_SIZE(ShmSysConfigAndInfo->SysConfig.SystemId)) || (ShmSysConfigAndInfo->SysConfig.Eth0Interface.EthDhcpClient == 0xff)) { if(strlen((char*)ShmSysConfigAndInfo->SysConfig.ModelName) > ARRAY_SIZE(ShmSysConfigAndInfo->SysConfig.ModelName)) { LOG_INFO("Model name over length."); memset(ShmSysConfigAndInfo->SysConfig.ModelName, 0x00, ARRAY_SIZE(ShmSysConfigAndInfo->SysConfig.ModelName)); } if(strlen((char*)ShmSysConfigAndInfo->SysConfig.SerialNumber) > ARRAY_SIZE(ShmSysConfigAndInfo->SysConfig.SerialNumber)) { LOG_INFO("Model serial number over length."); memset(ShmSysConfigAndInfo->SysConfig.SerialNumber, 0x00, ARRAY_SIZE(ShmSysConfigAndInfo->SysConfig.SerialNumber)); } if(strlen((char*)ShmSysConfigAndInfo->SysConfig.SystemId) > ARRAY_SIZE(ShmSysConfigAndInfo->SysConfig.SystemId)) { LOG_INFO("System id over length."); memset(ShmSysConfigAndInfo->SysConfig.SystemId, 0x00, ARRAY_SIZE(ShmSysConfigAndInfo->SysConfig.SystemId)); } if(ShmSysConfigAndInfo->SysConfig.Eth0Interface.EthDhcpClient == 0xff) { LOG_INFO("Ethernet dhcp config is null."); } system("cd /root;./Module_FactoryConfig -m"); sleep(3); system("/usr/bin/run_evse_restart.sh"); } LOG_INFO("Load SysConfigData OK"); return PASS; } int isEthernetCablePlugIn(int ethernet) { int fd, PlugInStatus = 0; char ch[2]; char buffer[64]; snprintf(buffer, sizeof(buffer), "/sys/class/net/eth%d/carrier", ethernet); fd = open(buffer, O_RDONLY); if(fd < 0) { return -1; } if(read(fd, ch, 1) < 0) { return -1; } PlugInStatus = atoi(ch); close(fd); return PlugInStatus; } int isRouteFail() { int result = YES; FILE *fp; char buf[512]; fp = popen("route -n", "r"); if(fp != NULL) { while(fgets(buf, sizeof(buf), fp) != NULL) { if(strstr(buf, "eth0") != NULL) result = NO; } } pclose(fp); return result; } int isReachableInternet() { int result = FAIL; FILE *fp; char cmd[256]; char buf[512]; char tmp[512]; // if (ShmOCPP16Data->OcppConnStatus == PASS) // { // result = PASS; // } // else { strcpy(cmd, "ifconfig eth0"); fp = popen(cmd, "r"); if (fp != NULL) { while(fgets(buf, sizeof(buf), fp) != NULL) { if (strstr(buf, "inet addr:") > 0) { sscanf(buf, "%*s%s", tmp); substr(tmp, tmp, strspn(tmp, "addr:"), strlen(tmp)-strspn(tmp, "addr:")); if (strcmp(tmp, (char *)ShmSysConfigAndInfo->SysConfig.Eth0Interface.EthIpAddress) != EQUAL) { strcpy((char *) ShmSysConfigAndInfo->SysConfig.Eth0Interface.EthIpAddress, tmp); } } } } pclose(fp); memset(buf, 0x00, sizeof(buf)); for(int idx=0;idx 0) { //sscanf(buf, "%*s%*s%*s%*s%*s%*s%s", tmp); if(strstr(buf,"100%") != NULL) { } else { result = PASS; } //DEBUG_INFO("%s",buf); //DEBUG_INFO("%s\n",tmp); } } } pclose(fp); } } return result; } int isUap0up(void) { int result = FAIL; FILE *fp; char cmd[256]; char buf[512]; strcpy(cmd, "ifconfig uap0");; fp = popen(cmd, "r"); if(fp != NULL) { while(fgets(buf, sizeof(buf), fp) != NULL) { if(strstr(buf, "uap0") > 0) { result = PASS; } } } pclose(fp); return result; } void InitialApModeDhcpServerConfig(void) { system("echo 'start 192.168.10.100' > /etc/udhcpd.conf"); system("echo 'end 192.168.10.150' >> /etc/udhcpd.conf"); system("echo 'interface uap0' >> /etc/udhcpd.conf"); system("echo 'lease_file /var/log/udhcpd.leases'>> /etc/udhcpd.conf"); system("echo 'opt dns 8.8.8.8' >> /etc/udhcpd.conf"); system("echo 'option subnet 255.255.255.0' >> /etc/udhcpd.conf"); system("echo 'opt router 192.168.10.10' >> /etc/udhcpd.conf"); system("echo 'option domain local' >> /etc/udhcpd.conf"); system("echo 'option lease 86400' >> /etc/udhcpd.conf"); usleep(1000); } void InitialBridgeModeDhcpServerConfig(void) { system("echo 'start 192.168.10.100' > /etc/udhcpd.conf"); system("echo 'end 192.168.10.150' >> /etc/udhcpd.conf"); system("echo 'interface br0' >> /etc/udhcpd.conf"); system("echo 'lease_file /var/log/udhcpd.leases'>> /etc/udhcpd.conf"); system("echo 'opt dns 8.8.8.8' >> /etc/udhcpd.conf"); system("echo 'option subnet 255.255.255.0' >> /etc/udhcpd.conf"); system("echo 'opt router 192.168.10.10' >> /etc/udhcpd.conf"); system("echo 'option domain local' >> /etc/udhcpd.conf"); system("echo 'option lease 86400' >> /etc/udhcpd.conf"); usleep(1000); } bool Is_Dispenser_MiscCommand(int dispenser, int misc_cmd) { return (ShmChargerInfo->DispenserMiscReq[dispenser].CtrlValue & misc_cmd) > 0 ? true : false; } void Set_Dispenser_MiscCommand(int dispenser, int misc_cmd) { ShmChargerInfo->DispenserMiscReq[dispenser].CtrlValue |= misc_cmd; } void Clean_Dispenser_MiscCommand(int dispenser, int misc_cmd) { ShmChargerInfo->DispenserMiscReq[dispenser].CtrlValue &= ~misc_cmd; } bool Is_Connector_MiscCommand(int connector, int misc_cmd) { return (ShmChargerInfo->ConnectorMiscReq[connector].CtrlValue & misc_cmd) > 0 ? true : false; } void Set_Connector_MiscCommand(int connector, int misc_cmd) { ShmChargerInfo->ConnectorMiscReq[connector].CtrlValue |= misc_cmd; } void Clean_Connector_MiscCommand(int connector, int misc_cmd) { ShmChargerInfo->ConnectorMiscReq[connector].CtrlValue &= ~misc_cmd; } void AnnounceEthernetStatus(void) { for(int index = 0; index < GENERAL_GUN_QUANTITY; index++) { if(ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[index].LocalStatus != _DS_None && ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[index].LocalStatus != _DS_Timeout) { Set_Dispenser_MiscCommand(index, MISC_DISP_ETHERNET_STATUS); } } } void AnnounceWiFiStatus(void) { for(int index = 0; index < GENERAL_GUN_QUANTITY; index++) { if(ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[index].LocalStatus != _DS_None && ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[index].LocalStatus != _DS_Timeout) { Set_Dispenser_MiscCommand(index, MISC_DISP_WIFI_STATUS); } } } void AnnounceTelcomModemStatus(void) { for(int index = 0; index < GENERAL_GUN_QUANTITY; index++) { if(ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[index].LocalStatus != _DS_None && ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[index].LocalStatus != _DS_Timeout) { Set_Dispenser_MiscCommand(index, MISC_DISP_TELCOM_MODEM_STATUS); } } } void AnnounceBackendStatus(void) { for(int index = 0; index < GENERAL_GUN_QUANTITY; index++) { if(ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[index].LocalStatus != _DS_None && ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[index].LocalStatus != _DS_Timeout) { Set_Dispenser_MiscCommand(index, MISC_DISP_BACKEND_STATUS); } } } void AnnounceBillingStatus(void) { for(int index = 0; index < GENERAL_GUN_QUANTITY; index++) { if(ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[index].LocalStatus != _DS_None && ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[index].LocalStatus != _DS_Timeout) { Set_Dispenser_MiscCommand(index, MISC_DISP_BILLING_STATUS); } } } void AnnounceStopChargingButtonStatus(void) { for(int index = 0; index < GENERAL_GUN_QUANTITY; index++) { if(ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[index].LocalStatus != _DS_None && ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[index].LocalStatus != _DS_Timeout) { Set_Dispenser_MiscCommand(index, MISC_DISP_STOP_BUTTON_STATUS); } } } void AnnounceAuthModeConfig(void) { for(int index = 0; index < GENERAL_GUN_QUANTITY; index++) { if(ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[index].LocalStatus != _DS_None && ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[index].LocalStatus != _DS_Timeout) { Set_Dispenser_MiscCommand(index, MISC_DISP_AUTH_MODE_CONFIG); } } } void AnnounceEVCCIDConfig(void) { for(int index = 0; index < GENERAL_GUN_QUANTITY; index++) { if(ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[index].LocalStatus != _DS_None && ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[index].LocalStatus != _DS_Timeout) { Set_Dispenser_MiscCommand(index, MISC_DISP_EVCCID_CONFIG); } } } void AnnounceLEDIntensity(void) { for(int index = 0; index < GENERAL_GUN_QUANTITY; index++) { if(ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[index].LocalStatus != _DS_None && ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[index].LocalStatus != _DS_Timeout) { Set_Dispenser_MiscCommand(index, MISC_DISP_LED_INTENSITY); } } } void AnnounceCurrency(void) { for(int index = 0; index < GENERAL_GUN_QUANTITY; index++) { if(ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[index].LocalStatus != _DS_None && ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[index].LocalStatus != _DS_Timeout) { Set_Dispenser_MiscCommand(index, MISC_DISP_CURRENCY); } } } void AnnounceRfidEndian(void) { for(int index = 0; index < GENERAL_GUN_QUANTITY; index++) { if(ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[index].LocalStatus != _DS_None && ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[index].LocalStatus != _DS_Timeout) { Set_Dispenser_MiscCommand(index, MISC_DISP_RFID_CARD_ENDIAN); } } } void AnnounceRfidReader(void) { for(int index = 0; index < GENERAL_GUN_QUANTITY; index++) { if(ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[index].LocalStatus != _DS_None && ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[index].LocalStatus != _DS_Timeout) { Set_Dispenser_MiscCommand(index, MISC_DISP_RFID_ENABLE); } } } void AnnounceRemoteStartNoID(void) { for(int index = 0; index < CONNECTOR_QUANTITY; index++) { if(ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[index].LocalStatus != _DS_None && ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[index].LocalStatus != _DS_Timeout) { for(int i = 0; i < ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[index].ConnectorQuantity; i++) { int gun = ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[index].ConnectorID[i] - 1; if(chargingInfo[gun]->SystemStatus == S_IDLE) { ShmChargerInfo->ConnectorPageReq[gun].bits.RemoteStartNoID = true; break; } } } } } void AnnounceLineStatusCode(int gun, int status) { int dispenser = 0; dispenser = ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gun].ParentDispensetIndex; if(ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[dispenser].LocalStatus != _DS_None && ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[dispenser].LocalStatus != _DS_Timeout) { ShmChargerInfo->LineApi.StatusCode[gun] = status; Set_Connector_MiscCommand(gun, MISC_CONN_LINE_STATUS); } } void AnnounceStationInfo(void) { for(int index = 0; index < GENERAL_GUN_QUANTITY; index++) { if(ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[index].LocalStatus != _DS_None && ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[index].LocalStatus != _DS_Timeout) { Set_Dispenser_MiscCommand(index, MISC_DISP_STATION_INFO); } } } void AnnounceOccupancyPrice(void) { for(int index = 0; index < GENERAL_GUN_QUANTITY; index++) { if(ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[index].LocalStatus != _DS_None && ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[index].LocalStatus != _DS_Timeout) { Set_Dispenser_MiscCommand(index, MISC_DISP_PARKING_PRICE); } } } void UpdateConfigAndIcon(void) { unsigned char status = _Connnection_Disable; // update ethernet connection status status = ShmStatusCodeData->InfoCode.InfoEvents.bits.InternetDisconnectViaEthernet == YES ? _Connnection_Disconnected : _Connnection_Connected; if(ShmChargerInfo->CabinetMiscValue.EthernetStatus != status) { ShmChargerInfo->CabinetMiscValue.EthernetStatus = status; AnnounceEthernetStatus(); } // update wifi connection status if(ShmSysConfigAndInfo->SysConfig.AthInterface.WifiMode != _SYS_WIFI_MODE_DISABLE) { status = ShmStatusCodeData->InfoCode.InfoEvents.bits.InternetDisconnectViaWiFi == YES ? _Connnection_Disconnected : _Connnection_Connected; } else { status = _Connnection_Disable; } if(ShmChargerInfo->CabinetMiscValue.WiFiStatus != status) { ShmChargerInfo->CabinetMiscValue.WiFiStatus = status; AnnounceWiFiStatus(); } // update 4g connection status if(ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomEnabled == YES) { status = (ShmStatusCodeData->InfoCode.InfoEvents.bits.InternetDisconnectVia4Gi == NO && ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomNetworkConn == YES) ? _Connnection_Connected : _Connnection_Disconnected; } else { status = _Connnection_Disable; } if(ShmChargerInfo->CabinetMiscValue.TelcomModemStatus != status) { ShmChargerInfo->CabinetMiscValue.TelcomModemStatus = status; AnnounceTelcomModemStatus(); } // update backend connection status status = ShmStatusCodeData->InfoCode.InfoEvents.bits.BackendDisconnectedViaEthernet == YES ? _Connnection_Disconnected : _Connnection_Connected; if(ShmChargerInfo->CabinetMiscValue.BackendStatus != status) { ShmChargerInfo->CabinetMiscValue.BackendStatus = status; AnnounceBackendStatus(); } // update billing status status = ShmSysConfigAndInfo->SysConfig.BillingData.isBilling; if(ShmChargerInfo->CabinetMiscValue.BillingStatus != status) { ShmChargerInfo->CabinetMiscValue.BillingStatus = status; AnnounceBillingStatus(); } // update stop charging button status = ShmSysConfigAndInfo->SysConfig.StopChargingByButton; if(ShmChargerInfo->CabinetMiscValue.StopChargingButton != status) { ShmChargerInfo->CabinetMiscValue.StopChargingButton = status; AnnounceStopChargingButtonStatus(); } // update AuthMode config status = ShmSysConfigAndInfo->SysConfig.AuthorisationMode; if(ShmChargerInfo->CabinetMiscValue.AuthModeConfig != status) { ShmChargerInfo->CabinetMiscValue.AuthModeConfig = status; AnnounceAuthModeConfig(); AnnounceEVCCIDConfig(); } // update EVCCID config status = ShmSysConfigAndInfo->SysConfig.isAuthrizeByEVCCID; if(ShmChargerInfo->CabinetMiscValue.EVCCIDConfig != status) { ShmChargerInfo->CabinetMiscValue.EVCCIDConfig = status; AnnounceEVCCIDConfig(); } // update LED Intensity status = ShmSysConfigAndInfo->SysConfig.LedInfo.Intensity; if(ShmChargerInfo->CabinetMiscValue.LEDIntensity != status) { ShmChargerInfo->CabinetMiscValue.LEDIntensity = status; AnnounceLEDIntensity(); } // update currency status = ShmSysConfigAndInfo->SysConfig.BillingData.Currency; if(ShmChargerInfo->CabinetMiscValue.Currency != status) { ShmChargerInfo->CabinetMiscValue.Currency = status; AnnounceCurrency(); } // update RfidCardNumEndian status = ShmSysConfigAndInfo->SysConfig.RfidCardNumEndian; if(ShmChargerInfo->CabinetMiscValue.RfidEndian != status) { ShmChargerInfo->CabinetMiscValue.RfidEndian = status; if(ShmChargerInfo->Control.CustomerCode == _CUSTOMER_CODE_Phihong || ShmChargerInfo->Control.CustomerCode == _CUSTOMER_CODE_Shell) { AnnounceRfidEndian(); } } // update AuthMode config status = ShmSysConfigAndInfo->SysConfig.isRFID; if(ShmChargerInfo->AuthInfo.AuthMode.bits.RFIDEnable != status) { ShmChargerInfo->AuthInfo.AuthMode.bits.RFIDEnable = status; ShmChargerInfo->CabinetMiscValue.RfidReaderEnable = status; AnnounceRfidReader(); } } void Check4gWifiReset(void) { int timeDelay = 0; if(ShmChargerInfo->Control.SysCtrl.bits.BackendEnable) { if((!ShmSysConfigAndInfo->SysInfo.InternetConn && !ShmSysConfigAndInfo->SysInfo.OcppConnStatus && (ShmSysConfigAndInfo->SysConfig.AthInterface.WifiMode != _SYS_WIFI_MODE_DISABLE || ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomEnabled == YES)) || ShmStatusCodeData->FaultCode.FaultEvents.bits.Telecom4GModuleBroken == YES) { if(!_NeedReset4gWifi) { GetClockTime(&_4gWifiReset_time); LOG_INFO("Backend Enable But Internet Not Available!"); } _NeedReset4gWifi = true; } else { _NeedReset4gWifi = false; } if(_NeedReset4gWifi) { timeDelay = ShmStatusCodeData->FaultCode.FaultEvents.bits.Telecom4GModuleBroken == YES ? FAST_RESET_4G_WIFI_TIME : TRY_RESET_4G_WIFI_TIME; if(GetTimeoutValue(_4gWifiReset_time) / uSEC_VAL >= timeDelay) { ShmChargerInfo->Control.SysCtrl.bits.Wifi4gResetEnable = true; usleep(100000); // before reset 4g io, kill Module_4g & Module_Wifi task if(ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomEnabled == YES) { system("killall Module_4g &"); } usleep(100000); if(ShmSysConfigAndInfo->SysConfig.AthInterface.WifiMode != _SYS_WIFI_MODE_DISABLE) { system("killall Module_Wifi &"); } LOG_INFO("Reset 4g_Wifi Module"); system("echo 1 > /sys/class/gpio/gpio104/value"); sleep(1); system("echo 0 > /sys/class/gpio/gpio104/value"); _NeedReset4gWifi = false; ShmChargerInfo->Control.SysCtrl.bits.Wifi4gResetEnable = false; } } } else { _NeedReset4gWifi = false; } } void MasterCabinetDhcpClientConfig(void) { char tmpbuf[256]; //Run DHCP client if enabled system("killall udhcpc"); system("rm -rf /etc/resolv.conf"); system("echo nameserver 8.8.8.8 > /etc/resolv.conf"); //Google DNS server system("echo nameserver 180.76.76.76 >> /etc/resolv.conf"); //Baidu DNS server //system("/sbin/ifconfig eth0 down;/sbin/ifconfig eth0 up"); if(ShmSysConfigAndInfo->SysConfig.Eth0Interface.EthDhcpClient == 0) { sprintf(tmpbuf, "/sbin/udhcpc -i eth0 -x hostname:CSU3_%s -s /root/dhcp_script/eth0.script > /dev/null &", ShmSysConfigAndInfo->SysConfig.SystemId); system(tmpbuf); } //Upgrade system id to /etc/hostname sprintf(tmpbuf, "echo %s > /etc/hostname", ShmSysConfigAndInfo->SysConfig.SystemId); system(tmpbuf); } void InitMasterCabinetEthernet(void) { char tmpbuf[256]; //Init Eth0 for internet memset(tmpbuf,0,256); sprintf(tmpbuf,"/sbin/ifconfig eth0 %s netmask %s up", ShmSysConfigAndInfo->SysConfig.Eth0Interface.EthIpAddress, ShmSysConfigAndInfo->SysConfig.Eth0Interface.EthSubmaskAddress); system(tmpbuf); memset(tmpbuf,0,256); sprintf(tmpbuf,"route add default gw %s eth0 ", ShmSysConfigAndInfo->SysConfig.Eth0Interface.EthGatewayAddress); system(tmpbuf); //system("ifconfig lo up"); // /sbin/ifconfig eth0 192.168.1.10 netmask 255.255.255.0 up //Init Eth1 for administrator tool memset(tmpbuf,0,256); sprintf(tmpbuf,"/sbin/ifconfig eth1 %s netmask %s up", "192.168.100.1", "255.255.255.0"); system(tmpbuf); } void InitSlaveCabinetEthernet(void) { char tmpbuf[256]; system("/sbin/ifconfig eth0 down"); system("/sbin/ifconfig eth1 down"); system("killall udhcpc"); system("rm -rf /etc/resolv.conf"); system("pgrep -f \"udhcpd /etc/udhcpd_eth1.conf\" | xargs kill"); //Init Eth0 for internet memset(tmpbuf,0,256); sprintf(tmpbuf,"/sbin/ifconfig eth0 192.168.100.3%d netmask %s up", (ShmChargerInfo->Control.CabinetSwitch - 1), "255.255.255.0"); system(tmpbuf); system("/sbin/route add default gw 192.168.100.1 eth0"); //Init Eth1 for internet memset(tmpbuf,0,256); sprintf(tmpbuf,"/sbin/ifconfig eth1 %s netmask %s up", SLAVE_ETH1_IP, SLAVE_ETH1_SUBMASK); system(tmpbuf); } void InitEthernet(void) { system("ifconfig eth0 down"); system("ifconfig eth1 down"); sleep(2); char tmpbuf[256]; // /sbin/ifconfig eth0 192.168.1.10 netmask 255.255.255.0 down system("echo 1 > /sys/class/gpio/gpio110/value");//reset PHY sleep(2); InitMasterCabinetEthernet(); MasterCabinetDhcpClientConfig(); // DO360 DHCP Server InitialDispenserDhcpServerConfig(); StartDispenserDhcpServer(); pid_t pid = fork(); uint8_t cnt_pingDNS_Fail; if(pid == 0) { ShmChargerInfo->CabinetMiscValue.BackendStatus = _Connnection_Disconnected; ShmChargerInfo->CabinetMiscValue.EthernetStatus = _Connnection_Disconnected; ShmChargerInfo->CabinetMiscValue.WiFiStatus = _Connnection_Disable; ShmChargerInfo->CabinetMiscValue.TelcomModemStatus = _Connnection_Disable; LOG_INFO("Internet Fork PID = %d", getpid()); for(;;) { if(isEthernetCablePlugIn(0) == YES) { if(isRouteFail()) { LOG_INFO("eth0 not in route, restart eht0."); system("/sbin/ifconfig eth0 down;/sbin/ifconfig eth0 up"); if (ShmSysConfigAndInfo->SysConfig.Eth0Interface.EthDhcpClient == 0) { InitialDHCP(); } else { system("pgrep -f \"udhcpc -i eth0\" | xargs kill"); memset(tmpbuf,0,256); sprintf(tmpbuf,"/sbin/ifconfig eth0 %s netmask %s up &", ShmSysConfigAndInfo->SysConfig.Eth0Interface.EthIpAddress, ShmSysConfigAndInfo->SysConfig.Eth0Interface.EthSubmaskAddress); system(tmpbuf); memset(tmpbuf,0,256); sprintf(tmpbuf,"route add default gw %s eth0 &", ShmSysConfigAndInfo->SysConfig.Eth0Interface.EthGatewayAddress); system(tmpbuf); } } } if(isReachableInternet() == PASS) { if(ShmStatusCodeData->InfoCode.InfoEvents.bits.InternetDisconnectViaEthernet != NO) { LOG_INFO("Internet is Reachable"); } ShmStatusCodeData->InfoCode.InfoEvents.bits.InternetDisconnectViaEthernet = NO; ShmSysConfigAndInfo->SysInfo.ethInternetConn = YES; cnt_pingDNS_Fail = 0; } else { if(++cnt_pingDNS_Fail > 3) { if(ShmStatusCodeData->InfoCode.InfoEvents.bits.InternetDisconnectViaEthernet != YES) { LOG_INFO("Internet is Disconnect Via Ethernet"); } ShmStatusCodeData->InfoCode.InfoEvents.bits.InternetDisconnectViaEthernet = YES; ShmSysConfigAndInfo->SysInfo.ethInternetConn = NO; } } bool ethResult = ShmSysConfigAndInfo->SysInfo.ethInternetConn; if(ethResult == YES) { system("/sbin/ifmetric eth0 0"); if(ShmSysConfigAndInfo->SysConfig.AthInterface.WifiMode != _SYS_WIFI_MODE_DISABLE && ((ShmSysConfigAndInfo->SysConfig.ModelName[10] == 'W') || (ShmSysConfigAndInfo->SysConfig.ModelName[10] == 'D'))) { system("/sbin/ifmetric mlan0 1"); } if(ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomEnabled == YES && ((ShmSysConfigAndInfo->SysConfig.ModelName[10] == 'T') || (ShmSysConfigAndInfo->SysConfig.ModelName[10] == 'D'))) { system("/sbin/ifmetric ppp0 2"); } } if (!ethResult && ShmSysConfigAndInfo->SysConfig.AthInterface.WifiMode != _SYS_WIFI_MODE_DISABLE && (ShmSysConfigAndInfo->SysConfig.ModelName[10] == 'W' || ShmSysConfigAndInfo->SysConfig.ModelName[10] == 'D')) { ethResult = ShmStatusCodeData->InfoCode.InfoEvents.bits.InternetDisconnectViaWiFi == YES ? NO : YES; if (ethResult) { if((ShmSysConfigAndInfo->SysConfig.ModelName[10] == 'W') || (ShmSysConfigAndInfo->SysConfig.ModelName[10] == 'D')) { system("/sbin/ifmetric eth0 1"); system("/sbin/ifmetric mlan0 0"); } if(ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomEnabled == YES && ((ShmSysConfigAndInfo->SysConfig.ModelName[10] == 'T') || (ShmSysConfigAndInfo->SysConfig.ModelName[10] == 'D'))) { system("/sbin/ifmetric ppp0 2"); } } } if (!ethResult && ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomEnabled == YES && (ShmSysConfigAndInfo->SysConfig.ModelName[10] == 'T' || ShmSysConfigAndInfo->SysConfig.ModelName[10] == 'D')) { ethResult = (ShmStatusCodeData->InfoCode.InfoEvents.bits.InternetDisconnectVia4Gi == NO && ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomNetworkConn == YES) ? YES : NO; if (ethResult) { if(ShmSysConfigAndInfo->SysConfig.AthInterface.WifiMode != _SYS_WIFI_MODE_DISABLE && ((ShmSysConfigAndInfo->SysConfig.ModelName[10] == 'W') || (ShmSysConfigAndInfo->SysConfig.ModelName[10] == 'D'))) { system("/sbin/ifmetric mlan0 2"); } if((ShmSysConfigAndInfo->SysConfig.ModelName[10] == 'T') || (ShmSysConfigAndInfo->SysConfig.ModelName[10] == 'D')) { system("/sbin/ifmetric eth0 1"); system("/sbin/ifmetric ppp0 0"); } } } // Bridge ethernet to uap0 to get dynamic ip address if(ShmSysConfigAndInfo->SysConfig.isEnableLocalPowerSharing > _SYS_POWER_SHARING_MODE_DISABLE && (ShmSysConfigAndInfo->SysConfig.AthInterface.WifiMode == _SYS_WIFI_MODE_AP)) { if((isUap0up() == PASS) && access("/sys/class/net/br0/address", F_OK) == -1) { system("/usr/sbin/brctl addbr br0"); system("/usr/sbin/brctl addif br0 eth0"); system("/usr/sbin/brctl addif br0 uap0"); system("/sbin/ifconfig br0 192.168.10.200 up"); InitialBridgeModeDhcpServerConfig(); //system("/bin/sed -i '/interface/d' /etc/udhcpd.conf"); //system("/bin/echo 'interface br0' >> /etc/udhcpd.conf"); system("pgrep -f \"udhcpd /etc/udhcpd.conf\" | xargs kill"); system("/usr/sbin/udhcpd /etc/udhcpd.conf"); LOG_INFO("Bridge uap0 & eth0 for local power sharing by ethernet."); _isBridgeModeConfig = true; } } else { if(access("/sys/class/net/br0/address", F_OK) != -1) { system("/sbin/ifconfig br0 down"); system("/usr/sbin/brctl delbr br0"); LOG_INFO("Disable uap0 & eth0 Bridge."); } if(ShmSysConfigAndInfo->SysConfig.AthInterface.WifiMode == _SYS_WIFI_MODE_AP && _isBridgeModeConfig) { InitialApModeDhcpServerConfig(); system("pgrep -f \"udhcpd /etc/udhcpd.conf\" | xargs kill"); system("/usr/sbin/udhcpd /etc/udhcpd.conf"); LOG_INFO("Restart uap0 udhcpd."); _isBridgeModeConfig = false; } } // Change uap0 to low priority if(ShmSysConfigAndInfo->SysConfig.isEnableLocalPowerSharing > _SYS_POWER_SHARING_MODE_DISABLE && (ShmSysConfigAndInfo->SysConfig.AthInterface.WifiMode == _SYS_WIFI_MODE_AP) && (isUap0up() == PASS)) { system("/sbin/ifmetric uap0 1"); } //============================================== // Check Local Power Sharing Communication //============================================== if(ShmSysConfigAndInfo->SysConfig.isEnableLocalPowerSharing == _SYS_POWER_SHARING_MODE_SLAVE) { if(ShmSysConfigAndInfo->SysInfo.localSharingInfo.isConnectedSharingServer) { if(ShmStatusCodeData->AlarmCode.AlarmEvents.bits.LocalPowerSharingCommunicationError == ON) { ShmStatusCodeData->AlarmCode.AlarmEvents.bits.LocalPowerSharingCommunicationError = OFF; } } else { if(ShmStatusCodeData->AlarmCode.AlarmEvents.bits.LocalPowerSharingCommunicationError == OFF) { ShmStatusCodeData->AlarmCode.AlarmEvents.bits.LocalPowerSharingCommunicationError = ON; } } } else { ShmStatusCodeData->AlarmCode.AlarmEvents.bits.LocalPowerSharingCommunicationError = OFF; } if(!Is_Ocpp_Task_Alive()) { ShmSysConfigAndInfo->SysInfo.OcppConnStatus = false; } ShmSysConfigAndInfo->SysInfo.InternetConn = ethResult; ShmStatusCodeData->InfoCode.InfoEvents.bits.WiFiDisable = ShmSysConfigAndInfo->SysConfig.AthInterface.WifiMode == _SYS_WIFI_MODE_DISABLE ? true : false; ShmStatusCodeData->InfoCode.InfoEvents.bits.Telocom4GModuleDisable = ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomEnabled == false ? true : false; ShmStatusCodeData->InfoCode.InfoEvents.bits.BackendDisconnectedViaEthernet = ShmSysConfigAndInfo->SysInfo.OcppConnStatus == false ? true : false; UpdateConfigAndIcon(); Check4gWifiReset(); sleep(5); } } #ifdef SystemLogMessage LOG_INFO("[main]InitEthernet: Initial Ethernet OK."); #endif } void GetMacAddress() { for (byte index = 0; index < 2; index++) { int fd; struct ifreq ifr; char tarEth[5]; char Mac[18]; sprintf(tarEth,"eth%d",index); fd = socket(AF_INET, SOCK_DGRAM, 0); ifr.ifr_addr.sa_family = AF_INET; strncpy(ifr.ifr_name, tarEth, IFNAMSIZ - 1); ioctl(fd, SIOCGIFHWADDR, &ifr); close(fd); sprintf(Mac, "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x", ifr.ifr_hwaddr.sa_data[0], ifr.ifr_hwaddr.sa_data[1], ifr.ifr_hwaddr.sa_data[2], ifr.ifr_hwaddr.sa_data[3], ifr.ifr_hwaddr.sa_data[4], ifr.ifr_hwaddr.sa_data[5]); if (index == 0) strcpy((char *) ShmSysConfigAndInfo->SysConfig.Eth0Interface.EthMacAddress, Mac); else strcpy((char *) ShmSysConfigAndInfo->SysConfig.Eth1Interface.EthMacAddress, Mac); } } void GetFirmwareVersion() { // Get CSU root file system version sprintf((char*)ShmSysConfigAndInfo->SysInfo.CsuRootFsFwRev, fwVersion); sprintf(ShmChargerInfo->SysMisc.MainVersion, fwVersion); sprintf(ShmChargerInfo->SysMisc.SubVersion, subVersion); #if ENABLE_PCBA_TEST == 0 byte count = 0, chademo = 0, ccs = 0, gb = 0; for(uint8_t idx=0;idx<3;idx++) { if (ShmSysConfigAndInfo->SysConfig.ModelName[7+idx] == 'J') { chademo++; count++; } else if (ShmSysConfigAndInfo->SysConfig.ModelName[7+idx] == 'G') { gb++; count++; } else if (ShmSysConfigAndInfo->SysConfig.ModelName[7+idx] == 'U' || ShmSysConfigAndInfo->SysConfig.ModelName[7+idx] == 'E') { ccs++; count++; } } if (count == 1) { if (chademo > 0) ShmSysConfigAndInfo->SysInfo.CsuRootFsFwRev[7] = '1'; else if (ccs > 0) ShmSysConfigAndInfo->SysInfo.CsuRootFsFwRev[7] = '2'; else if (gb > 0) ShmSysConfigAndInfo->SysInfo.CsuRootFsFwRev[7] = '3'; } else { if (chademo > 0 && ccs > 0) ShmSysConfigAndInfo->SysInfo.CsuRootFsFwRev[7] = '4'; else if (chademo > 0 && gb > 0) ShmSysConfigAndInfo->SysInfo.CsuRootFsFwRev[7] = '5'; else if (ccs > 0 && gb > 0) ShmSysConfigAndInfo->SysInfo.CsuRootFsFwRev[7] = '6'; } // Get network option from model name switch(ShmSysConfigAndInfo->SysConfig.ModelName[10]) { case 'B': case 'U': //Blue tooth ShmSysConfigAndInfo->SysInfo.CsuRootFsFwRev[9] = '3'; break; case 'W': // WIFI ShmSysConfigAndInfo->SysInfo.CsuRootFsFwRev[9] = '1'; break; case 'T': // 3G/4G ShmSysConfigAndInfo->SysInfo.CsuRootFsFwRev[9] = '2'; break; case 'D': ShmSysConfigAndInfo->SysInfo.CsuRootFsFwRev[9] = '5'; break; default: // LAN ShmSysConfigAndInfo->SysInfo.CsuRootFsFwRev[9] = '0'; break; } // Get rating power from model name memcpy(&ShmSysConfigAndInfo->SysInfo.CsuRootFsFwRev[10], &ShmSysConfigAndInfo->SysConfig.ModelName[4], 0x03); // Get IEC or UL char _buf[3] = {0}; memcpy(_buf, &ShmSysConfigAndInfo->SysConfig.ModelName[2], 2); if (strcmp(_buf, "YE") == EQUAL || strcmp(_buf, "YC") == EQUAL) ShmSysConfigAndInfo->SysInfo.ChargerType = _CHARGER_TYPE_IEC; else if (strcmp(_buf, "WU") == EQUAL) ShmSysConfigAndInfo->SysInfo.ChargerType = _CHARGER_TYPE_UL; #endif } void InitialShareMemoryInfo() { FILE *fp; char cmd[512]; char buf[512]; _UpgradeNeedReboot = FALSE; _psuLostQuantity = 0; //sprintf((char *)ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomApn, "Internet"); //sprintf((char *)ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomChapPapId, " "); //sprintf((char *)ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomChapPapPwd, " "); ShmSysConfigAndInfo->SysConfig.TotalConnectorCount = 0; ShmSysConfigAndInfo->SysConfig.AcConnectorCount = 0; ShmSysConfigAndInfo->SysInfo.FactoryConfiguration = 0; ShmSysConfigAndInfo->SysInfo.InputVoltageR = 0; ShmSysConfigAndInfo->SysInfo.InputVoltageS = 0; ShmSysConfigAndInfo->SysInfo.InputVoltageT = 0; ShmSysConfigAndInfo->SysInfo.SystemFanRotaSpeed = 0; ShmSysConfigAndInfo->SysInfo.PsuFanRotaSpeed = 0; ShmSysConfigAndInfo->SysInfo.AuxPower5V = 0; ShmSysConfigAndInfo->SysInfo.AuxPower12V = 0; ShmSysConfigAndInfo->SysInfo.AuxPower24V = 0; ShmSysConfigAndInfo->SysInfo.AuxPower48V = 0; sprintf((char *)ShmSysConfigAndInfo->SysInfo.CsuHwRev, "REV:5.0"); memcpy(ShmSysConfigAndInfo->SysInfo.CsuBootLoadFwRev, ShmSysConfigAndInfo->SysConfig.CsuBootLoadFwRev, ARRAY_SIZE(ShmSysConfigAndInfo->SysConfig.CsuBootLoadFwRev)); sprintf(cmd, "/bin/uname -r"); fp = popen(cmd, "r"); if(fp == NULL) sprintf((char*)ShmSysConfigAndInfo->SysInfo.CsuKernelFwRev, "Unknown version"); else { while(fgets(buf, sizeof(buf), fp) != NULL) { strcpy((char*)ShmSysConfigAndInfo->SysInfo.CsuKernelFwRev, buf); } } // 雙槍 CCS + Chademo GetFirmwareVersion(); //sprintf((char *) ShmSysConfigAndInfo->SysInfo.CsuRootFsFwRev, fwVersion); sprintf((char *) ShmSysConfigAndInfo->SysInfo.CsuPrimFwRev, " "); sprintf((char *) ShmSysConfigAndInfo->SysInfo.LcmHwRev, " "); sprintf((char *) ShmSysConfigAndInfo->SysInfo.LcmFwRev, " "); sprintf((char *) ShmSysConfigAndInfo->SysInfo.PsuHwRev, " "); sprintf((char *) ShmSysConfigAndInfo->SysInfo.PsuPrimFwRev, " "); sprintf((char *) ShmSysConfigAndInfo->SysInfo.PsuSecFwRev, " "); sprintf((char *) ShmSysConfigAndInfo->SysInfo.AuxPwrHwRev, " "); sprintf((char *) ShmSysConfigAndInfo->SysInfo.AuxPwrFwRev, " "); sprintf((char *) ShmSysConfigAndInfo->SysInfo.FanModuleHwRev, " "); sprintf((char *) ShmSysConfigAndInfo->SysInfo.FanModuleFwRev, " "); sprintf((char *) ShmSysConfigAndInfo->SysInfo.RelayModuleHwRev, " "); sprintf((char *) ShmSysConfigAndInfo->SysInfo.RelayModuleFwRev, " "); sprintf((char *) ShmSysConfigAndInfo->SysInfo.Relay2ModuleHwRev, " "); //DO360 RC2 sprintf((char *) ShmSysConfigAndInfo->SysInfo.Relay2ModuleFwRev, " "); //DO360 RC2 sprintf((char *) ShmSysConfigAndInfo->SysInfo.TelcomModemFwRev, " "); sprintf((char *) ShmSysConfigAndInfo->SysInfo.LedModuleFwRev, " "); sprintf((char *) ShmSysConfigAndInfo->SysInfo.Connector1FwRev, " "); sprintf((char *) ShmSysConfigAndInfo->SysInfo.Connector2FwRev, " "); ShmSysConfigAndInfo->SysInfo.SystemAmbientTemp = 0; ShmSysConfigAndInfo->SysInfo.SystemCriticalTemp = 0; ShmSysConfigAndInfo->SysInfo.PsuAmbientTemp = 0; ShmSysConfigAndInfo->SysInfo.CcsConnectorTemp = 0; ShmSysConfigAndInfo->SysInfo.InternetConn = 0; ShmSysConfigAndInfo->SysInfo.OcppConnStatus = 0; ShmSysConfigAndInfo->SysInfo.OrderCharging = NO_DEFINE; ShmSysConfigAndInfo->SysInfo.MaxChargingProfilePower = -1; strcpy((char *) ShmSysConfigAndInfo->SysConfig.UserId, ""); ShmStatusCodeData->AlarmCode.AlarmEvents.bits.RelayboardStestFail = NO; ShmStatusCodeData->AlarmCode.AlarmEvents.bits.FanboardStestFail = NO; ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PrimaryStestFail = NO; ShmStatusCodeData->AlarmCode.AlarmEvents.bits.ChademoboardStestFail = NO; ShmStatusCodeData->AlarmCode.AlarmEvents.bits.CCSboardStestFail = NO; ShmStatusCodeData->AlarmCode.AlarmEvents.bits.AcContactStestFail = NO; ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuModuleStestFail = NO; memset(ShmSysConfigAndInfo->SysInfo.FanModuleFwRev, 0, ARRAY_SIZE(ShmSysConfigAndInfo->SysInfo.FanModuleFwRev)); memset(ShmSysConfigAndInfo->SysInfo.RelayModuleFwRev, 0, ARRAY_SIZE(ShmSysConfigAndInfo->SysInfo.RelayModuleFwRev)); memset(ShmSysConfigAndInfo->SysInfo.Relay2ModuleFwRev, 0, ARRAY_SIZE(ShmSysConfigAndInfo->SysInfo.Relay2ModuleFwRev)); //DO360 RC2 ShmPrimaryMcuData->SelfTest_Comp = NO; ShmRelayModuleData[0]->SelfTest_Comp = NO; ShmRelayModuleData[1]->SelfTest_Comp = NO; ShmFanModuleData->SelfTest_Comp = NO; ShmLedModuleData->SelfTest_Comp = NO; ShmSysConfigAndInfo->SysInfo.SystemPage = _LCM_NONE; ShmSysConfigAndInfo->SysInfo.MainChargingMode = _MAIN_CHARGING_MODE_MAX; ShmSysConfigAndInfo->SysInfo.ReAssignedFlag = _REASSIGNED_NONE; ShmSysConfigAndInfo->SysInfo.CurGunSelectedByAc = NO_DEFINE; ShmFanModuleData->TestFanSpeed = 0; ShmStatusCodeData->AlarmCode.AlarmEvents.bits.ModelNameNoneMatchStestFail = NO; ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuNoResource = NO; ShmSysConfigAndInfo->SysConfig.SwitchDebugFlag = NO; ShmSysConfigAndInfo->SysConfig.AlwaysGfdFlag = NO; LOG_INFO("DispenserSequence = %d, MaxConnectorQuantity = %d", ShmSysConfigAndInfo->SysConfig.WiringInfo.DispenserSequence, ShmSysConfigAndInfo->SysConfig.WiringInfo.MaxConnectorQuantity); for(int i = 0; i < ShmSysConfigAndInfo->SysConfig.WiringInfo.DispenserSequence; i++) { LOG_INFO("Dispenser[%d] <=> %d", i, ShmSysConfigAndInfo->SysConfig.WiringInfo.WiringSetting[i]); } for(int i = 0; i < CONNECTOR_QUANTITY; i++) { memset((char *)&_BackupStatusNotification[i], 0, sizeof(struct StructStatusNotification)); _useGunMeterValue[i] = false; _notifyOccupancyFeeAct[i] = _Notify_None; } for(int i = 0; i < MAX_DISPENSER_QUANTITY; i++) { _canUpdateFinalCost[i] = false; _isUndisposedFinalCost[i] = true; } } int Initialization(void) { // int pinOut[2] = { 116, 115 }; for (byte count = 0; count < CONNECTOR_QUANTITY; count++) { chargingInfo[count]->RemoteStartFlag = NO; ShmSysConfigAndInfo->SysInfo.ConnectorInfo[count].Parameter.bits.RemoteStartConfirm = false; ShmSysConfigAndInfo->SysInfo.ConnectorInfo[count].Parameter.bits.RemoteStopConfirm = false; SetOcppErrorCode(count, "NoError"); } LOG_INFO("Initialization OK"); return PASS; } void InitialPsuGroupingAndLocation(void) { if(ShmChargerInfo->Control.SysCtrl.bits.SecondRelayBoardEnable) { memcpy(ShmPsuGrouping->Location, Group_to_Location_4_Gun, sizeof(ShmPsuGrouping->Location)); memcpy(ShmPsuGrouping->Layout, Location_to_Group_4_Gun, sizeof(ShmPsuGrouping->Layout)); } else { memcpy(ShmPsuGrouping->Location, Group_to_Location_2_Gun, sizeof(ShmPsuGrouping->Location)); memcpy(ShmPsuGrouping->Layout, Location_to_Group_2_Gun, sizeof(ShmPsuGrouping->Layout)); } for(int i = 0; i < CONNECTOR_QUANTITY; i++) { ShmPsuGrouping->GroupCollection[i].Index = i; ShmPsuGrouping->GroupCollection[i].Location = ShmPsuGrouping->Location[i]; if(ShmChargerInfo->Control.SysCtrl.bits.SecondRelayBoardEnable) { if(ShmChargerInfo->Control.SysCtrl.bits.Enable6ParallelRelay == 0) { memcpy(&ShmPsuGrouping->GroupCollection[i].ParallelConfig[0], &GroupParallelRelay_4_Gun[i][0], GENERAL_GUN_QUANTITY); } else { memcpy(&ShmPsuGrouping->GroupCollection[i].ParallelConfig[0], &GroupParallelRelay_4_Gun_6Parallel[i][0], GENERAL_GUN_QUANTITY); } } else { memcpy(&ShmPsuGrouping->GroupCollection[i].ParallelConfig[0], &GroupParallelRelay_2_Gun[i][0], GENERAL_GUN_QUANTITY); } ShmChargerInfo->Control.GunAvailable[i] = NO; } } void InitialCustomerCode(void) { if(ShmSysConfigAndInfo->SysConfig.ModelName[12] == 'A' && ShmSysConfigAndInfo->SysConfig.ModelName[13] == 'D') { ShmChargerInfo->Control.CustomerCode = _CUSTOMER_CODE_Audi; } else if(ShmSysConfigAndInfo->SysConfig.ModelName[12] == 'E' && ShmSysConfigAndInfo->SysConfig.ModelName[13] == '4') { ShmChargerInfo->Control.CustomerCode = _CUSTOMER_CODE_E4U; } else if(ShmSysConfigAndInfo->SysConfig.ModelName[12] == 'U' && ShmSysConfigAndInfo->SysConfig.ModelName[13] == 'U') { ShmChargerInfo->Control.CustomerCode = _CUSTOMER_CODE_UCar; } else if(ShmSysConfigAndInfo->SysConfig.ModelName[12] == 'T' && ShmSysConfigAndInfo->SysConfig.ModelName[13] == 'C') { ShmChargerInfo->Control.CustomerCode = _CUSTOMER_CODE_TCC; } else if(ShmSysConfigAndInfo->SysConfig.ModelName[12] == 'O' && ShmSysConfigAndInfo->SysConfig.ModelName[13] == 'L') { ShmChargerInfo->Control.CustomerCode = _CUSTOMER_CODE_Shell; } else { ShmChargerInfo->Control.CustomerCode = _CUSTOMER_CODE_Phihong; } } void InitialCustomizedSetting(void) { ShmChargerInfo->Control.CustomizedInfo.StandbyTime = STANDBY_TIME; if(ShmChargerInfo->Control.CustomerCode == _CUSTOMER_CODE_TCC) { ShmChargerInfo->Control.CustomizedInfo.Flag.bits.StandbyTimeDisableForTcc = true; } if(ShmChargerInfo->Control.CustomerCode == _CUSTOMER_CODE_E4U) { ShmChargerInfo->Control.CustomizedInfo.Flag.bits.CustomizedStandbyTime = true; ShmChargerInfo->Control.CustomizedInfo.StandbyTime = E4U_STANDBY_TIME; } } void InitialMaxDispenserConnectorQuantity(void) { if(ShmChargerInfo->Control.SysCtrl.bits.SecondRelayBoardEnable == false) { ShmChargerInfo->Control.MaxDispenser = 2; ShmChargerInfo->Control.MaxConnector = 2; } else { ShmChargerInfo->Control.MaxDispenser = GENERAL_GUN_QUANTITY; ShmChargerInfo->Control.MaxConnector = GENERAL_GUN_QUANTITY; } } void InitialAuthMode(void) { if(ShmSysConfigAndInfo->SysConfig.ModelName[0] == 'D' && ShmSysConfigAndInfo->SysConfig.ModelName[1] == 'K') { } } void InitialQRCodeMode(void) { if(ShmChargerInfo->Control.CustomerCode == _CUSTOMER_CODE_Audi || ShmChargerInfo->Control.CustomerCode == _CUSTOMER_CODE_TCC) { ShmChargerInfo->AuthInfo.QRCodeMode = _QR_MODE_ChargeBoxId; } else { // customized if(ShmSysConfigAndInfo->SysConfig.QRCodeMadeMode) { ShmChargerInfo->AuthInfo.QRCodeMode = _QR_MODE_Customized; } else { ShmChargerInfo->AuthInfo.QRCodeMode = _QR_MODE_Default; } } } void InitialPowerCabinetSetting(void) { if(ShmSysConfigAndInfo->SysConfig.ModelName[12] == 'A' && ShmSysConfigAndInfo->SysConfig.ModelName[13] == 'D') { ShmSysConfigAndInfo->SysConfig.BillingData.isBilling = true; } ShmChargerInfo->CabinetMiscValue.BillingStatus = ShmSysConfigAndInfo->SysConfig.BillingData.isBilling; ShmChargerInfo->CabinetMiscValue.StopChargingButton = ShmSysConfigAndInfo->SysConfig.StopChargingByButton; ShmChargerInfo->CabinetMiscValue.AuthModeConfig = ShmSysConfigAndInfo->SysConfig.AuthorisationMode; ShmChargerInfo->CabinetMiscValue.EVCCIDConfig = ShmSysConfigAndInfo->SysConfig.isAuthrizeByEVCCID; } void Initial6ParallelSetting(void) { if(ShmSysConfigAndInfo->SysConfig.ModelName[11] == '3') { ShmChargerInfo->Control.SysCtrl.bits.Enable6ParallelRelay = 1; } } void PowerModuleLibSelection(void) { if(ShmSysConfigAndInfo->SysConfig.ModelName[0] == 'D' && ShmSysConfigAndInfo->SysConfig.ModelName[1] == 'L') { ShmChargerInfo->Control.LibCtrl.bits.PhPwrLib = true; } else { ShmChargerInfo->Control.LibCtrl.bits.InfyPwrLib = true; } } bool InitialChargerSetting(void) { bool result = true; if(ShmSysConfigAndInfo->SysConfig.ModelName[0] == 'D' && (ShmSysConfigAndInfo->SysConfig.ModelName[1] == 'O' || ShmSysConfigAndInfo->SysConfig.ModelName[1] == 'L')) { ShmChargerInfo->Control.PrimaryCtrl.bits.AcContactorReverse = false; ShmChargerInfo->Control.PrimaryCtrl.bits.DoorSensorReverse = false; ShmChargerInfo->Control.SysCtrl.bits.LedBoardDisable = true; ShmChargerInfo->Control.SysCtrl.bits.SecondRelayBoardEnable = true; ShmChargerInfo->Control.SysCtrl.bits.DOLedIndication = true; } else if(ShmSysConfigAndInfo->SysConfig.ModelName[0] == 'D' && ShmSysConfigAndInfo->SysConfig.ModelName[1] == 'K') { if(!(ShmSysConfigAndInfo->SysConfig.ModelName[12] == 'P' && ShmSysConfigAndInfo->SysConfig.ModelName[13] == 'K')) { ShmChargerInfo->Control.SysCtrl.bits.FanBoardDisable = true; } ShmChargerInfo->Control.SysCtrl.bits.LedBoardDisable = true; ShmChargerInfo->Control.SysCtrl.bits.DKLedIndication = true; } else if(ShmSysConfigAndInfo->SysConfig.ModelName[0] == 'D' && ShmSysConfigAndInfo->SysConfig.ModelName[1] == 'B') { //ShmChargerInfo->Control.SysCtrl.bits.FanBoardDisable = true; ShmChargerInfo->Control.SysCtrl.bits.LedBoardDisable = true; ShmChargerInfo->Control.SysCtrl.bits.DOLedIndication = true; //ShmChargerInfo->Control.SysCtrl.bits.DKLedIndication = true; ShmChargerInfo->Control.RelayCtrl.bits.AcInputDisable = true; ShmChargerInfo->Control.RelayCtrl.bits.DcInputEnable = true; } else { result = false; } LOG_INFO("door sensor reverse = %d", ShmChargerInfo->Control.PrimaryCtrl.bits.DoorSensorReverse); LOG_INFO("ac contactor reverse = %d",ShmChargerInfo->Control.PrimaryCtrl.bits.AcContactorReverse); InitialCustomerCode(); InitialCustomizedSetting(); InitialMaxDispenserConnectorQuantity(); InitialAuthMode(); InitialQRCodeMode(); Initial6ParallelSetting(); InitialPsuGroupingAndLocation(); InitialPowerCabinetSetting(); PowerModuleLibSelection(); if(!CheckConnectorTypeStatus()) { result = false; } return result; } bool InitialSystemDefaultConfig() { bool result = true; LoadSysConfigAndInfo(&ShmSysConfigAndInfo->SysConfig); InitGPIO(); InitEthernet(); GetMacAddress(); return result; } void SelfTestRun(void) { LOG_INFO("Self test."); system("/root/Module_ChargerSelfTest &"); } void SpawnPowerModuleTask(void) { if(ShmChargerInfo->Control.LibCtrl.bits.PhPwrLib) { system("/root/Module_PsuComm_PH &"); } else { system("/root/Module_PsuComm &"); } } void KillPowerModuleTask(void) { if(ShmChargerInfo->Control.LibCtrl.bits.PhPwrLib) { system("killall Module_PsuComm_PH"); } else { system("killall Module_PsuComm"); } } void SpawnNormalService(void) { system("/root/Module_EventLogging &"); system("/root/Module_PrimaryComm &"); system("/root/Module_EvComm &"); //system("/root/Module_LcmControl &"); system("/root/Module_InternalComm &"); SpawnPowerModuleTask(); system("/root/Module_ProduceUtils &"); system("/root/Module_CabinetParallel &"); system("/root/Module_LedIndication &"); system("/root/Module_Authorize &"); } void SpawnOcppService(void) { if(strcmp((char *)ShmSysConfigAndInfo->SysConfig.OcppServerURL, "") != EQUAL && strcmp((char *)ShmSysConfigAndInfo->SysConfig.ChargeBoxId, "") != EQUAL) { Run_Ocpp_Service(); } } void SpawnMaintainOcppService(void) { if(ShmChargerInfo->Control.CabinetRole != _CROLE_SLAVE && strcmp((char *)ShmSysConfigAndInfo->SysConfig.MaintainServerURL, "") != EQUAL) { Run_MaintainOcpp_Service(); } } void SpawnInternetService(void) { if(ShmSysConfigAndInfo->SysConfig.ModelName[10] == 'T') { if(ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomEnabled == YES) { system("/root/Module_4g &"); } } if(ShmSysConfigAndInfo->SysConfig.ModelName[10] == 'W') { if(ShmSysConfigAndInfo->SysConfig.AthInterface.WifiMode != _SYS_WIFI_MODE_DISABLE) { system("/root/Module_Wifi &"); } } if(ShmSysConfigAndInfo->SysConfig.ModelName[10] == 'D') { if(ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomEnabled == YES) { system("/root/Module_4g &"); } if(ShmSysConfigAndInfo->SysConfig.AthInterface.WifiMode != _SYS_WIFI_MODE_DISABLE) { system("/root/Module_Wifi &"); } } } int SpawnTask(void) { sleep(2); SpawnNormalService(); SpawnInternetService(); return PASS; } int runFlashShellCmd(const char *cmd) { int result = FAIL; char buf[256]; FILE *fp; fp = popen(cmd, "r"); if(fp != NULL) { while(fgets(buf, sizeof(buf), fp) != NULL) { LOG_INFO("%s\n", buf); } result = PASS; } pclose(fp); return result; } int StoreUsrConfigData(struct SysConfigData *UsrData) { int result = PASS; int fd, wrd; unsigned int i, Chk; unsigned char *ptr, *BufTmp; Chk = 0; ptr = (unsigned char *)UsrData; if((BufTmp = malloc(MtdBlockSize)) != NULL) { memset(BufTmp, 0, MtdBlockSize); memcpy(BufTmp, ptr, sizeof(struct SysConfigData)); for(i = ARRAY_SIZE(UsrData->CsuBootLoadFwRev); i < MtdBlockSize - 4; i++) { Chk += *(BufTmp+i); } memcpy(BufTmp + MtdBlockSize - 4, &Chk, 4); // Output configuration to file. fd = open("/mnt/EvseTempConfig.bin", O_RDWR | O_CREAT | O_TRUNC); if(fd < 0) { LOG_ERROR("open /mnt/EvseTempConfig.bin NG"); free(BufTmp); return 0; } wrd = write(fd, BufTmp, MtdBlockSize); close(fd); if(wrd < MtdBlockSize) { LOG_ERROR("write /mnt/EvseTempConfig.bin NG"); free(BufTmp); return 0; } LOG_INFO("EvseTempConfig write to file in /mnt OK."); LOG_INFO("Erase /dev/mtd10."); runFlashShellCmd("flash_erase /dev/mtd10 0 0"); LOG_INFO("Write /dev/mtd10."); runFlashShellCmd("nandwrite -p /dev/mtd10 /mnt/EvseTempConfig.bin"); LOG_INFO("Erase /dev/mtd11."); runFlashShellCmd("flash_erase /dev/mtd11 0 0"); LOG_INFO("Write /dev/mtd11."); runFlashShellCmd("nandwrite -p /dev/mtd11 /mnt/EvseTempConfig.bin"); system("rm -f /mnt/EvseTempConfig.bin"); LOG_INFO("EvseTempConfig write to flash OK"); } else { LOG_ERROR("alloc BlockSize NG"); result = FAIL; } if(BufTmp != NULL) { free(BufTmp); } return result; } //=============================================== // Common Detect Chk - Stop Charging ? //=============================================== bool isEvBoardStopChargeFlag(byte gunIndex) { return chargingInfo[gunIndex]->ChargingStopFlag.bits.AlarmStop; } bool isNormalStopChargeFlag(byte gunIndex) { return (chargingInfo[gunIndex]->ChargingStopFlag.bits.NormalStop || chargingInfo[gunIndex]->ChargingStopFlag.bits.ManualStop); } bool isResetStopChargeFlag(byte gunIndex) { return (chargingInfo[gunIndex]->ChargingStopFlag.bits.HardResetStop || chargingInfo[gunIndex]->ChargingStopFlag.bits.SoftResetStop); } bool isInvalidIdStopFlag(byte gunIndex) { return chargingInfo[gunIndex]->ChargingStopFlag.bits.InvalidIdStop; } bool isSessionTargetStopFlag(byte gunIndex) { return chargingInfo[gunIndex]->ChargingStopFlag.bits.SessionTargetStop; } bool isBackendStopFlag(byte gunIndex) { return (chargingInfo[gunIndex]->ChargingStopFlag.bits.BackendStop || chargingInfo[gunIndex]->ChargingStopFlag.bits.RemoteStop || chargingInfo[gunIndex]->ChargingStopFlag.bits.UnlockStop); } void ReleaseAlarmCode(byte gunIndex) { if(!Is_Ocpp_StatusNotificationErrorCode(gunIndex, "NoError")) { SetOcppErrorCode(gunIndex, "NoError"); } if(!Is_Ocpp_StatusNotificationVendorCode(gunIndex, "")) { SetOcppVendorErrorCode(gunIndex, ""); } if (strcmp((char *)chargingInfo[gunIndex]->ConnectorAlarmCode, "") != EQUAL) { strcpy((char *)chargingInfo[gunIndex]->ConnectorAlarmCode, ""); } if (strcmp((char *)chargingInfo[gunIndex]->EvConnAlarmCode, "") != EQUAL) { strcpy((char *)chargingInfo[gunIndex]->EvConnAlarmCode, ""); } if (strcmp((char *)ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gunIndex].RemotenAlarmCode, "") != EQUAL) { strcpy((char *)ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gunIndex].RemotenAlarmCode, ""); } if (strcmp((char *)ShmChargerInfo->GunError[gunIndex].GunAlarmCode, "") != EQUAL) { strcpy((char *)ShmChargerInfo->GunError[gunIndex].GunAlarmCode, ""); } } //=============================================== // EmergencyStop and Charging Stop //=============================================== void ChargingTerminalProcess(byte gunIndex) { setChargerMode(gunIndex, MODE_TERMINATING); } void ChargingAlarmProcess(byte gunIndex) { UpdateErrorCodeToOcpp(gunIndex); setChargerMode(gunIndex, MODE_ALARM); } void AcChargingTerminalProcess() { ac_chargingInfo[0]->SystemStatus = MODE_TERMINATING; } void StopChargingProcessByString(byte level) { if (level > ShmSysConfigAndInfo->SysWarningInfo.Level) { ShmSysConfigAndInfo->SysWarningInfo.Level = level; } } void ReleaseChargingProcessByString(byte level) { if (level >= ShmSysConfigAndInfo->SysWarningInfo.Level) ShmSysConfigAndInfo->SysWarningInfo.Level = 0; } // 一般錯誤停止充電處理函式 void BoardErrOccurByString(byte index, char *code) { byte level = 1; if ((chargingInfo[index]->SystemStatus > S_IDLE && chargingInfo[index]->SystemStatus < S_TERMINATING) || (chargingInfo[index]->SystemStatus >= S_CCS_PRECHARGE_ST0 && chargingInfo[index]->SystemStatus <= S_CCS_PRECHARGE_ST1)) { if (strncmp(code, "023730", 6) == EQUAL && ShmStatusCodeData->InfoCode.InfoEvents.bits.ChademoChargerGetEmergencyStop == NO) { ShmStatusCodeData->InfoCode.InfoEvents.bits.ChademoChargerGetEmergencyStop = YES; } ChargingTerminalProcess(index); } StopChargingProcessByString(level); } // 急停狀況的停止充電處理函式 void EmcOccureByString(char *code) { byte level = 2; if(ShmSysConfigAndInfo->SysInfo.SelfTestSeq != _STEST_COMPLETE) { return; } // 嚴重的急停有以下幾種 : EMC 按鈕、Mainbreak、Dooropen // 其錯誤等級為 2 if (strncmp(code, "042251", 6) == EQUAL || strncmp(code, "042252", 6) == EQUAL || strncmp(code, "042238", 6) == EQUAL || strncmp(code, "042267", 6) == EQUAL || strncmp(code, "042328", 6) == EQUAL) { for (byte gun = 0; gun < ShmSysConfigAndInfo->SysConfig.TotalConnectorCount; gun++) { if ((chargingInfo[gun]->SystemStatus > S_IDLE && chargingInfo[gun]->SystemStatus < S_TERMINATING) || (chargingInfo[gun]->SystemStatus >= S_CCS_PRECHARGE_ST0 && chargingInfo[gun]->SystemStatus <= S_CCS_PRECHARGE_ST1)) { if (strncmp((char *)chargingInfo[gun]->ConnectorAlarmCode, "", 6) == EQUAL) { memcpy(chargingInfo[gun]->ConnectorAlarmCode, code, 6); } InformOcppErrOccur(4); ChargingAlarmProcess(gun); } } StopChargingProcessByString(level); } } void ReleaseEmsOccureByString(byte index, char *code) { bool isTrigger = false; byte level = 2; if (strncmp(code, "042251", 6) == 0 && ShmStatusCodeData->AlarmCode.AlarmEvents.bits.EmergencyStopTrip == YES) { isTrigger = true; ShmStatusCodeData->AlarmCode.AlarmEvents.bits.EmergencyStopTrip = NO; } else if (strncmp(code, "042252", 6) == 0 && ShmStatusCodeData->AlarmCode.AlarmEvents.bits.DoorOpen == YES) { isTrigger = true; ShmStatusCodeData->AlarmCode.AlarmEvents.bits.DoorOpen = NO; } else if (strncmp(code, "042237", 6) == 0 && ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SpdTrip == YES) { isTrigger = true; ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SpdTrip = NO; } else if (strncmp(code, "042238", 6) == 0 && ShmStatusCodeData->AlarmCode.AlarmEvents.bits.MainPowerBreakerTrip == YES) { isTrigger = true; ShmStatusCodeData->AlarmCode.AlarmEvents.bits.MainPowerBreakerTrip = NO; } else if (strncmp(code, "042267", 6) == 0 && ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuFailureAlarm == YES) { isTrigger = true; ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuFailureAlarm = NO; } if (isTrigger) { ReleaseChargingProcessByString(level); } } //=============================================== // 確認硬體 (按鈕) 狀態 //=============================================== void ChkPrimaryStatus() { if(ShmChargerInfo->Control.TestCtrl.bits.ChargingSimulation) { ShmStatusCodeData->AlarmCode.AlarmEvents.bits.EmergencyStopTrip = NO; ShmStatusCodeData->AlarmCode.AlarmEvents.bits.DoorOpen = NO; ShmStatusCodeData->AlarmCode.AlarmEvents.bits.MainPowerBreakerTrip = NO; ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SpdTrip = NO; ShmChargerInfo->Control.RelayCtrl.bits.AcContactorOffByEmergency = NO; return; } if (ShmPrimaryMcuData->InputDet.bits.EmergencyButton == ABNORMAL) { ShmStatusCodeData->AlarmCode.AlarmEvents.bits.EmergencyStopTrip = YES; ShmChargerInfo->Control.RelayCtrl.bits.AcContactorOffByEmergency = YES; EmcOccureByString("042251"); } else { ReleaseEmsOccureByString(0, "042251"); ShmChargerInfo->Control.RelayCtrl.bits.AcContactorOffByEmergency = NO; } if (ShmPrimaryMcuData->InputDet.bits.AcMainBreakerDetec == ABNORMAL) { ShmStatusCodeData->AlarmCode.AlarmEvents.bits.MainPowerBreakerTrip = YES; //EmcOccureByString("042238"); } else { //ReleaseEmsOccureByString(0, "042238"); ShmStatusCodeData->AlarmCode.AlarmEvents.bits.MainPowerBreakerTrip = NO; } if (ShmPrimaryMcuData->InputDet.bits.SpdDetec == ABNORMAL) { ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SpdTrip = YES; } else { ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SpdTrip = NO; } if(ShmPrimaryMcuData->InputDet.bits.DoorOpen == ABNORMAL && (ShmChargerInfo->Control.CustomizedInfo.TiltSensorStep == _TILT_SENSOR_NONE || ShmChargerInfo->Control.CustomizedInfo.TiltSensorStep == _TILT_SENSOR_FINISH)) { ShmStatusCodeData->AlarmCode.AlarmEvents.bits.DoorOpen = YES; EmcOccureByString("042252"); } else { ReleaseEmsOccureByString(0, "042252"); } if(ShmStatusCodeData->AlarmCode.AlarmEvents.bits.DcInputUVP == YES) { EmcOccureByString("042328"); SetAcContactor(OFF); } if(ShmChargerInfo->Control.CustomizedInfo.TiltSensorFail) { ShmStatusCodeData->AlarmCode.AlarmEvents.bits.TiltSensorStestFail = YES; } else { ShmStatusCodeData->AlarmCode.AlarmEvents.bits.TiltSensorStestFail = NO; } } struct timespec _AcContactReOpen_Time; void ChkPsuStatus(void) { if(!ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuFailureAlarm) { if(IsConnectorWholeIdle()) { for(int psuGroup = 0; psuGroup < ShmSysConfigAndInfo->SysConfig.TotalConnectorCount; psuGroup++) { //if(ShmPsuData->PsuGroup[psuGroup].GroupErrorFlag.PsuGroupErrorValue != 0) //{ // ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuFailureAlarm = YES; //} if(ShmChargerInfo->PsuGrouping.GroupPsuStatus_OR[psuGroup].StatusVal & PSU_STATUS_FLAG_FAULT) { ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuFailureAlarm = YES; } } } if(ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuFailureAlarm) { EmcOccureByString("042267"); } } else { if(ShmChargerInfo->Control.RelayCtrl.bits.AcContactor && ShmChargerInfo->Control.PsuCtrl.bits.FailureResume == NO) { bool allFaultStatus = true; for(int gunIndex = 0; gunIndex < ShmSysConfigAndInfo->SysConfig.TotalConnectorCount; gunIndex++) { if(chargingInfo[gunIndex]->SystemStatus != S_FAULT && chargingInfo[gunIndex]->SystemStatus != S_MAINTAIN) { allFaultStatus = false; } } if(allFaultStatus) { LOG_INFO("PSU Failure, Need Resume"); ShmChargerInfo->Control.PsuCtrl.bits.FailureResume = YES; } } } } int AcContactorReOpenCount = 0; void PsuFailureResume(void) { if(ShmChargerInfo->Control.PsuCtrl.bits.FailureResume) { if(ShmChargerInfo->Control.RelayCtrl.bits.AcContactorOffByPsu == NO) { LOG_INFO("Ac Contactor Off By Psu Failure"); // update _AcContactReOpen_Time GetClockTime(&_AcContactReOpen_Time); ShmChargerInfo->Control.RelayCtrl.bits.AcContactorOffByPsu = YES; AcContactorReOpenCount++; } else { if(AcContactorReOpenCount < MAX_AC_CONTACTOR_COUNT) { if(GetTimeoutValue(_AcContactReOpen_Time) / uSEC_VAL >= AC_CONTACTOR_REOPEN_TIME) { ReleaseEmsOccureByString(0, "042267"); // update _AcContactReOpen_Time GetClockTime(&_AcContactReOpen_Time); ShmChargerInfo->Control.RelayCtrl.bits.AcContactorOffByPsu = NO; ShmChargerInfo->Control.PsuCtrl.bits.FailureResume = NO; LOG_INFO("Psu Failure Resume"); } } } } else { if(AcContactorReOpenCount > 0) { if(GetTimeoutValue(_AcContactReOpen_Time) / uSEC_VAL >= PSU_FAILURE_RESUME_TIME) { AcContactorReOpenCount = 0; } } } } void SetAcContactor(unsigned char OnOff) { OnOff = OnOff ? ON : OFF; if(ShmChargerInfo->Control.RelayCtrl.bits.AcContactor != OnOff) { if(OnOff) { ShmChargerInfo->Control.RelayCtrl.bits.StandbyCountdown = NO; } LOG_INFO("Set Ac Contactor %s", OnOff == ON ? "On" : "Off"); } ShmChargerInfo->Control.RelayCtrl.bits.AcContactor = OnOff == ON ? ON : OFF; if(ShmChargerInfo->Control.CabinetRole == _CROLE_MASTER && ShmChargerInfo->ParallelCabinet.ParallelStatus == _Parallel_None) { SetParallelCabinetAcContactor(OnOff); } } int GetStandbyTime(void) { int time = STANDBY_TIME; if(ShmChargerInfo->Control.TestCtrl.bits.FastStandbyTime) { time = FAST_STANDBY_TIME; } if(ShmChargerInfo->Control.CustomizedInfo.Flag.bits.CustomizedStandbyTime) { time = ShmChargerInfo->Control.CustomizedInfo.StandbyTime; } if(ShmChargerInfo->Control.CustomizedInfo.Flag.bits.StandbyImmediately) { time = FAST_STANDBY_TIME; } return time; } void StandbyCheck(void) { bool enable = IsStandbyEnable(); if(IsConnectorWholeIdle() && IsParallelCabinetIdle()) { if(ShmChargerInfo->Control.RelayCtrl.bits.StandbyCountdown) { int time = GetStandbyTime(); #if CONTACTOR_AUTO_ON_OFF == 1 time = CONTACTOR_AUTO_ON_TIME; #endif if(ShmChargerInfo->Control.RelayCtrl.bits.AcContactor) { if(GetSecTimeoutValue(_Standby_time) >= time && enable) { SetAcContactor(OFF); } } #if CONTACTOR_AUTO_ON_OFF == 1 time = CONTACTOR_AUTO_ON_TIME + CONTACTOR_AUTO_OFF_TIME; if((GetTimeoutValue(_Standby_time) / uSEC_VAL) >= time) { SetAcContactor(ON); } #endif } else { ShmChargerInfo->Control.RelayCtrl.bits.StandbyCountdown = YES; GetClockTime(&_Standby_time); } } else { if(ShmChargerInfo->Control.RelayCtrl.bits.StandbyCountdown) { ShmChargerInfo->Control.RelayCtrl.bits.StandbyCountdown = NO; } } } void CheckDisconnectionStatusRecovery(void) { bool recovery = true; // check all connector for(int i = 0; i < CONNECTOR_QUANTITY; i++) { if(ShmSysConfigAndInfo->SysInfo.ConnectorInfo[i].Parameter.bits.Disconnection) { recovery = false; } } if(recovery) { ShmStatusCodeData->AlarmCode.AlarmEvents.bits.DisconnectedFromDo = false; } } //=============================================== // 確認各小板偵測的錯誤狀況 //=============================================== void CheckErrorOccurStatus(byte index) { if(ShmSysConfigAndInfo->SysInfo.ConnectorInfo[index].Parameter.bits.NormalStopRequest) { chargingInfo[index]->ChargingStopFlag.bits.NormalStop = true; } if(ShmSysConfigAndInfo->SysInfo.ConnectorInfo[index].Parameter.bits.AlarmStopRequest) { if(strncmp((char *)chargingInfo[index]->ConnectorAlarmCode, "", 6) == EQUAL) { memcpy(chargingInfo[index]->ConnectorAlarmCode, ShmSysConfigAndInfo->SysInfo.ConnectorInfo[index].RemotenAlarmCode, 6); } if(!chargingInfo[index]->ChargingStopFlag.bits.AlarmStop) { LOG_INFO("Connector %d Error Occur %s", index + 1, chargingInfo[index]->ConnectorAlarmCode); } chargingInfo[index]->ChargingStopFlag.bits.AlarmStop = true; } if(ShmChargerInfo->GunError[index].ErrFlag.ErrorValue != 0) { if(strncmp((char *)chargingInfo[index]->ConnectorAlarmCode, "", 6) == EQUAL) { memcpy(chargingInfo[index]->ConnectorAlarmCode, ShmChargerInfo->GunError[index].GunAlarmCode, 6); } if(!chargingInfo[index]->ChargingStopFlag.bits.AlarmStop) { LOG_INFO("Connector %d GunError Occur %s", index + 1, chargingInfo[index]->ConnectorAlarmCode); } chargingInfo[index]->ChargingStopFlag.bits.AlarmStop = true; } if(ShmSysConfigAndInfo->SysInfo.ConnectorInfo[index].Parameter.bits.TimeoutStopRequest) { ShmSysConfigAndInfo->SysInfo.ConnectorInfo[index].Parameter.bits.TimeoutStopRequest = false; ShmSysConfigAndInfo->SysInfo.ConnectorInfo[index].Parameter.bits.Disconnection = true; ShmStatusCodeData->AlarmCode.AlarmEvents.bits.DisconnectedFromDo = true; if(chargingInfo[index]->SystemStatus == S_AUTHORIZING || chargingInfo[index]->SystemStatus == S_PREPARNING || chargingInfo[index]->SystemStatus == S_PREPARING_FOR_EV || chargingInfo[index]->SystemStatus == S_PREPARING_FOR_EVSE || chargingInfo[index]->SystemStatus == S_CHARGING) { if(strncmp((char *)chargingInfo[index]->ConnectorAlarmCode, "", 6) == EQUAL) { memcpy(chargingInfo[index]->ConnectorAlarmCode, "042304", 6); } if(!chargingInfo[index]->ChargingStopFlag.bits.AlarmStop) { LOG_INFO("Connector %d Disconnect Alarm Occur %s", index + 1, chargingInfo[index]->ConnectorAlarmCode); } chargingInfo[index]->ChargingStopFlag.bits.AlarmStop = true; } else if(chargingInfo[index]->SystemStatus == S_REASSIGN_CHECK || chargingInfo[index]->SystemStatus == S_REASSIGN) { setChargerMode(index, MODE_IDLE); } } if(ShmStatusCodeData->AlarmCode.AlarmEvents.bits.DisconnectedFromDo) { CheckDisconnectionStatusRecovery(); } if(ShmStatusCodeData->AlarmCode.AlarmEvents.bits.EmergencyStopTrip == YES || ShmStatusCodeData->AlarmCode.AlarmEvents.bits.DoorOpen) { if (ShmSysConfigAndInfo->SysWarningInfo.ExtraErrProcess == _EXTRA_ERR_PROCESS_NONE) { ShmSysConfigAndInfo->SysWarningInfo.ExtraErrProcess = _EXTRA_ERR_PROCESS_PRIMARY; StopChargingProcessByString(2); } if (strncmp((char *)chargingInfo[index]->ConnectorAlarmCode, "", 6) == EQUAL) { if (ShmStatusCodeData->AlarmCode.AlarmEvents.bits.EmergencyStopTrip == YES) memcpy(chargingInfo[index]->ConnectorAlarmCode, "042251", 6); else if (ShmStatusCodeData->AlarmCode.AlarmEvents.bits.DoorOpen == YES) memcpy(chargingInfo[index]->ConnectorAlarmCode, "042252", 6); } } else { if (ShmSysConfigAndInfo->SysWarningInfo.ExtraErrProcess == _EXTRA_ERR_PROCESS_PRIMARY) { ShmSysConfigAndInfo->SysWarningInfo.ExtraErrProcess = _EXTRA_ERR_PROCESS_NONE; ReleaseChargingProcessByString(2); } } // RB if (ShmSysConfigAndInfo->SysConfig.PhaseLossPolicy == YES) { if (ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL1InputUVP == YES || ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL2InputUVP == YES || ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL3InputUVP == YES) { if (ShmSysConfigAndInfo->SysWarningInfo.ExtraErrProcess == _EXTRA_ERR_PROCESS_NONE) { ShmSysConfigAndInfo->SysWarningInfo.ExtraErrProcess = _EXTRA_ERR_PROCESS_INUVP; StopChargingProcessByString(2); } if (strncmp((char *)chargingInfo[index]->ConnectorAlarmCode, "", 6) == EQUAL) { if (ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL1InputUVP == YES) memcpy(chargingInfo[index]->ConnectorAlarmCode, "042203", 6); else if (ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL2InputUVP == YES) memcpy(chargingInfo[index]->ConnectorAlarmCode, "042204", 6); else if (ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL3InputUVP == YES) memcpy(chargingInfo[index]->ConnectorAlarmCode, "042205", 6); } if(!chargingInfo[index]->ChargingStopFlag.bits.AlarmStop) { LOG_INFO("Connector %d RC Board Input UVP Occur %s", index + 1, chargingInfo[index]->ConnectorAlarmCode); } chargingInfo[index]->ChargingStopFlag.bits.AlarmStop = true; } else { if (ShmSysConfigAndInfo->SysWarningInfo.ExtraErrProcess == _EXTRA_ERR_PROCESS_INUVP) { ShmSysConfigAndInfo->SysWarningInfo.ExtraErrProcess = _EXTRA_ERR_PROCESS_NONE; ReleaseChargingProcessByString(2); } } } else { if (ShmSysConfigAndInfo->SysWarningInfo.ExtraErrProcess == _EXTRA_ERR_PROCESS_INUVP) { ShmSysConfigAndInfo->SysWarningInfo.ExtraErrProcess = _EXTRA_ERR_PROCESS_NONE; ReleaseChargingProcessByString(2); } } if(ShmChargerInfo->Control.RelayCtrl.bits.AcInputDisable == NO) { if (ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL1InputOVP == YES || ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL2InputOVP == YES || ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL3InputOVP == YES) { if (ShmSysConfigAndInfo->SysWarningInfo.ExtraErrProcess == _EXTRA_ERR_PROCESS_NONE) { ShmSysConfigAndInfo->SysWarningInfo.ExtraErrProcess = _EXTRA_ERR_PROCESS_INOVP; StopChargingProcessByString(2); } if (strncmp((char *)chargingInfo[index]->ConnectorAlarmCode, "", 6) == EQUAL) { if (ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL1InputOVP == YES) memcpy(chargingInfo[index]->ConnectorAlarmCode, "042200", 6); else if (ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL2InputOVP == YES) memcpy(chargingInfo[index]->ConnectorAlarmCode, "042201", 6); else if (ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL3InputOVP == YES) memcpy(chargingInfo[index]->ConnectorAlarmCode, "042202", 6); } if(!chargingInfo[index]->ChargingStopFlag.bits.AlarmStop) { LOG_INFO("Connector %d RC Board Input OVP Occur %s", index + 1, chargingInfo[index]->ConnectorAlarmCode); } chargingInfo[index]->ChargingStopFlag.bits.AlarmStop = true; } else { if (ShmSysConfigAndInfo->SysWarningInfo.ExtraErrProcess == _EXTRA_ERR_PROCESS_INOVP) { ShmSysConfigAndInfo->SysWarningInfo.ExtraErrProcess = _EXTRA_ERR_PROCESS_NONE; ReleaseChargingProcessByString(2); } } } else { if (ShmStatusCodeData->AlarmCode.AlarmEvents.bits.DcInputOVP == YES || ShmStatusCodeData->AlarmCode.AlarmEvents.bits.DcInputUVP == YES) { if (ShmSysConfigAndInfo->SysWarningInfo.ExtraErrProcess == _EXTRA_ERR_PROCESS_NONE) { ShmSysConfigAndInfo->SysWarningInfo.ExtraErrProcess = _EXTRA_ERR_PROCESS_INOVP; StopChargingProcessByString(2); } if (strncmp((char *)chargingInfo[index]->ConnectorAlarmCode, "", 6) == EQUAL) { if (ShmStatusCodeData->AlarmCode.AlarmEvents.bits.DcInputOVP == YES) memcpy(chargingInfo[index]->ConnectorAlarmCode, "042327", 6); else if (ShmStatusCodeData->AlarmCode.AlarmEvents.bits.DcInputUVP == YES) memcpy(chargingInfo[index]->ConnectorAlarmCode, "042328", 6); } if(!chargingInfo[index]->ChargingStopFlag.bits.AlarmStop) { LOG_INFO("Gun %d DC Input OVP/UVP Occur %s", index + 1, chargingInfo[index]->ConnectorAlarmCode); } chargingInfo[index]->ChargingStopFlag.bits.AlarmStop = true; } else { if (ShmSysConfigAndInfo->SysWarningInfo.ExtraErrProcess == _EXTRA_ERR_PROCESS_INOVP) { ShmSysConfigAndInfo->SysWarningInfo.ExtraErrProcess = _EXTRA_ERR_PROCESS_NONE; ReleaseChargingProcessByString(2); } } } } int DiffTimebWithNowSec(struct timeb ST) { //return milli-second struct timeb ET; unsigned int StartTime,StopTime; ftime(&ET); StartTime=(unsigned int)ST.time; StopTime=(unsigned int)ET.time; return (StopTime-StartTime); } int CheckTimeOut(char *start) { int result = YES; struct ParsingResult { int result; int scanedElement; int year; int month; int mday; int hour; int min; int sec; int tz_hour; int tz_min; float minSec; }parsingResult; struct tm tmStart; struct timeb tbStart; memset(&parsingResult, 0x00, sizeof(struct ParsingResult)); if(strstr((char*)start, ".") != NULL) { // Original data with mini second if(strstr((char*)start, "Z") != NULL) { // Original data with Z parsingResult.scanedElement = sscanf((char*)start, "%d-%d-%dT%d:%d:%d.%fZ", &parsingResult.year, &parsingResult.month, &parsingResult.mday, &parsingResult.hour, &parsingResult.min, &parsingResult.sec, &parsingResult.minSec); } else { // Original data without Z parsingResult.scanedElement = sscanf((char*)start, "%d-%d-%dT%d:%d:%d.%f%d:%d", &parsingResult.year, &parsingResult.month, &parsingResult.mday, &parsingResult.hour, &parsingResult.min, &parsingResult.sec, &parsingResult.minSec, &parsingResult.tz_hour, &parsingResult.tz_min); } } else { // Original data without mini second if(strstr((char*)start, "Z") != NULL) { // Original data with Z parsingResult.scanedElement = sscanf((char*)start, "%d-%d-%dT%d:%d:%dZ", &parsingResult.year, &parsingResult.month, &parsingResult.mday, &parsingResult.hour, &parsingResult.min, &parsingResult.sec); } else { // Original data without Z parsingResult.scanedElement = sscanf((char*)start, "%d-%d-%dT%d:%d:%d%d:%d", &parsingResult.year, &parsingResult.month, &parsingResult.mday, &parsingResult.hour, &parsingResult.min, &parsingResult.sec, &parsingResult.tz_hour, &parsingResult.tz_min); } } if(parsingResult.scanedElement >= 6) { tmStart.tm_year = parsingResult.year - 1900; tmStart.tm_mon = parsingResult.month - 1; tmStart.tm_mday = parsingResult.mday; tmStart.tm_hour = parsingResult.hour; tmStart.tm_min = parsingResult.min; tmStart.tm_sec = parsingResult.sec; tmStart.tm_gmtoff = 0; tbStart.time = mktime(&tmStart); tbStart.timezone = 0; tbStart.millitm = 0; tbStart.time -= (parsingResult.tz_hour*3600) + (parsingResult.tz_min*60*(parsingResult.tz_hour>=0?1:-1)); if(DiffTimebWithNowSec(tbStart) <= 0) result = NO; else result = YES; } else { LOG_INFO("Start date parsing error"); } return result; } bool Is_WebServer_Alive(void) { if(system("pidof -s lighttpd > /dev/null") != 0) { return false; } return true; } void Run_WebServer_Service(void) { system("/root/web.sh"); } bool Is_LocalPowerSharing_Alive(void) { if(system("pidof -s Module_PowerSharing > /dev/null") != 0) { return false; } return true; } void Run_LocalPowerSharing_Service(void) { system ("/root/Module_PowerSharing &"); } //=============================================== // Ocpp_Service //=============================================== void Run_Ocpp_Service(void) { if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { system("/root/OcppBackend &"); return; } if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { system("/root/OcppBackend20 &"); return; } } bool Is_Ocpp_Task_Alive(void) { if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { if(system("pidof -s OcppBackend > /dev/null") != 0) { return false; } return true; } if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { if(system("pidof -s OcppBackend20 > /dev/null") != 0) { return false; } return true; } return false; } void Kill_Ocpp_Service(void) { system("killall OcppBackend"); system("killall OcppBackend20"); } //=============================================== // Maintain Ocpp_Service //=============================================== void Run_MaintainOcpp_Service(void) { system("/root/OcppBackendPH &"); } bool Is_MaintainOcpp_Task_Alive(void) { if(system("pidof -s OcppBackendPH > /dev/null") != 0) { return false; } return true; } void Kill_MaintainOcpp_Service(void) { system("killall OcppBackendPH"); } //=============================================== // Ocpp OcppConnStatus //=============================================== bool Get_Ocpp_ConnectionStatus(void) { if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { return ShmOCPP16Data->OcppConnStatus > 0 ? true : false; } if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { return ShmOCPP20Data->OcppConnStatus > 0 ? true : false; } return false; } //=============================================== // Ocpp procDogTime //=============================================== long int Get_Ocpp_procDogTime(void) { if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { return ShmOCPP16Data->procDogTime; } if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { return ShmOCPP20Data->procDogTime; } return 0; } void Clean_Ocpp_procDogTime(void) { if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { ShmOCPP16Data->procDogTime = time((time_t*)NULL); return; } if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { ShmOCPP20Data->procDogTime = time((time_t*)NULL); return; } } //=============================================== // Ocpp Boot Notification //=============================================== bool Is_Ocpp_BootNotification(void) { if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { return ShmOCPP16Data->SpMsg.bits.BootNotificationConf == YES ? true : false; } if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { return ShmOCPP20Data->SpMsg.bits.BootNotificationConf == YES ? true : false; } return false; } void Clean_Ocpp_BootNotification(void) { if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { ShmOCPP16Data->SpMsg.bits.BootNotificationConf = false; return; } if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { ShmOCPP20Data->SpMsg.bits.BootNotificationConf = false; return; } } //=============================================== // Ocpp Rest //=============================================== bool Is_Ocpp_ResetReq(void) { if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { return ShmOCPP16Data->MsMsg.bits.ResetReq == YES ? true : false; } if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { return ShmOCPP20Data->MsMsg.bits.ResetReq == YES ? true : false; } return false; } bool Chk_Ocpp_Reset_Type(char *type) { if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { return strcmp((char *)ShmOCPP16Data->Reset.Type, type) == EQUAL ? true : false; } if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { return strcmp((char *)ShmOCPP20Data->Reset.type, type) == EQUAL ? true : false; } return false; } void Clean_Ocpp_ResetReq(void) { if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { sprintf((char*)ShmOCPP16Data->Reset.ResponseStatus, "Accepted"); ShmOCPP16Data->MsMsg.bits.ResetReq = false; ShmOCPP16Data->MsMsg.bits.ResetConf = true; return; } if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { sprintf ( (char*) ShmOCPP20Data->Reset.Response_status, "Accepted" ); ShmOCPP20Data->MsMsg.bits.ResetReq = false; ShmOCPP20Data->MsMsg.bits.ResetConf = true; return; } } //=============================================== // Ocpp AuthorizeReq //=============================================== void Set_Ocpp_AuthorizeReq(void) { if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { ShmOCPP16Data->SpMsg.bits.AuthorizeConf = false; ShmOCPP16Data->SpMsg.bits.AuthorizeReq = true; return; } if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { ShmOCPP20Data->SpMsg.bits.AuthorizeConf = false; ShmOCPP20Data->SpMsg.bits.AuthorizeReq = true; return; } } bool Is_Ocpp_AuthorizeConf(void) { if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { return ShmOCPP16Data->SpMsg.bits.AuthorizeConf == YES ? true : false; } if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { return ShmOCPP20Data->SpMsg.bits.AuthorizeConf == YES ? true : false; } return false; } bool Is_Ocpp_Authorize_Status(char *status) { if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { return strcmp((char *)ShmOCPP16Data->Authorize.ResponseIdTagInfo.Status, status) == EQUAL ? true : false; } if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { return strcmp((char *)ShmOCPP20Data->Authorize.Response_idTokenInfo.status, status) == EQUAL ? true : false; } return false; } //=============================================== // Ocpp UpdateFirmwareReq //=============================================== bool Is_Ocpp_UpdateFirmwareReq(void) { if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { return ShmOCPP16Data->MsMsg.bits.UpdateFirmwareReq == YES ? true : false; } if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { return ShmOCPP20Data->MsMsg.bits.UpdateFirmwareReq == YES ? true : false; } return false; } void Clean_Ocpp_UpdateFirmwareReq(void) { if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { ShmOCPP16Data->MsMsg.bits.UpdateFirmwareReq = false; return; } if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { ShmOCPP20Data->MsMsg.bits.UpdateFirmwareReq = false; return; } } bool Is_Ocpp_UpdateFirmwareStatus(char *status) { if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { return strcmp((char *)ShmOCPP16Data->FirmwareStatusNotification.Status, status) == EQUAL ? true : false; } if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { return strcmp((char *)ShmOCPP20Data->FirmwareStatusNotification.status, status) == EQUAL ? true : false; } return false; } void Set_Ocpp_UpdateFirmwareStatus(char *status) { if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { strcpy((char *)ShmOCPP16Data->FirmwareStatusNotification.Status, status); return; } if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { strcpy((char *)ShmOCPP20Data->FirmwareStatusNotification.status, status); return; } } void Clean_Ocpp_UpdateFirmwareStatus(char *status) { Set_Ocpp_UpdateFirmwareStatus(""); } void Set_Ocpp_FirmwareStatusNotificationReq(void) { if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { ShmOCPP16Data->SpMsg.bits.FirmwareStatusNotificationReq = YES; return; } if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { ShmOCPP20Data->SpMsg.bits.FirmwareStatusNotificationReq = YES; return; } } //=============================================== // Ocpp StopTransactionOnInvalidId //=============================================== bool Is_Ocpp_StopOnInvalidId_Enable(void) { if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { return strstr((char *)ShmOCPP16Data->ConfigurationTable.CoreProfile[StopTransactionOnInvalidId].ItemData, "TRUE") > 0 ? true : false; } if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { return strstr((char *)ShmOCPP20Data->ControllerComponentVariable[TxCtrlr_StopTxOnInvalidId].variableAttribute[0].value, "TRUE") > 0 ? true : false; } return false; } //=============================================== // Ocpp AuthorizeRemoteTxRequests //=============================================== bool Is_Ocpp_AuthorizeRemoteTxRequests(void) { if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { return strstr((char *)ShmOCPP16Data->ConfigurationTable.CoreProfile[AuthorizeRemoteTxRequests].ItemData, "TRUE") > 0 ? true : false; } if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { return strstr((char *)ShmOCPP20Data->ControllerComponentVariable[AuthCtrlr_AuthorizeRemoteStart].variableAttribute[0].value, "TRUE") > 0 ? true : false; } return false; } //=============================================== // Ocpp ConnectionTimeOut //=============================================== int Get_Ocpp_ConnectionTimeOut(void) { int timeout = 0; if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { if(strcmp((char *)ShmOCPP16Data->ConfigurationTable.CoreProfile[ConnectionTimeOut].ItemData, "") != 0) { timeout = atoi((char *)ShmOCPP16Data->ConfigurationTable.CoreProfile[ConnectionTimeOut].ItemData); } } if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { if(strcmp((char *)ShmOCPP20Data->ControllerComponentVariable[TxCtrlr_EVConnectionTimeOut].variableAttribute[0].value, "" ) != 0) { timeout = atoi((char *)ShmOCPP20Data->ControllerComponentVariable[TxCtrlr_EVConnectionTimeOut].variableAttribute[0].value); } } return timeout > 0 ? timeout : 0; } //=============================================== // Ocpp DefaultPrice //=============================================== void Get_Ocpp_DefaultPrice(char *defaultPrice) { if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { strcpy(defaultPrice, (char *)ShmOCPP16Data->ConfigurationTable.CoreProfile[DefaultPrice].ItemData); return; } if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { strcpy(defaultPrice, ""); return; } strcpy(defaultPrice, ""); } //=============================================== // Ocpp UserPrice //=============================================== void Get_Ocpp_UserPrice(char *userId, char *userPrice) { if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { strcpy(userId, (char *)ShmOCPP16Data->Cost.SetUserPrice.idToken); strcpy(userPrice, (char *)ShmOCPP16Data->Cost.SetUserPrice.price); return; } if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { strcpy(userId, ""); strcpy(userPrice, ""); return; } strcpy(userId, ""); strcpy(userPrice, ""); } void Clean_Ocpp_UserPrice(void) { if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { memset(&ShmOCPP16Data->Cost.SetUserPrice, 0x00, sizeof(struct StrcutSetUserPrice)); return; } if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { return; } } //=============================================== // Ocpp RunningCost //=============================================== void Get_Ocpp_RunningCost(int gun_index, char *cost) { if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { strcpy(cost, (char *)ShmOCPP16Data->Cost.RunningCost[gun_index].description); return; } if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { strcpy(cost, (char *)""); return; } } void Clean_Ocpp_RunningCost(int gun_index) { if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { memset(&ShmOCPP16Data->Cost.RunningCost[gun_index], 0x00, sizeof(struct StrcutRunningCost)); return; } if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { return; } } //=============================================== // Ocpp FinalCost //=============================================== void Get_Ocpp_FinalCost(int gun_index, char *cost) { if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { strcpy(cost, (char *)ShmOCPP16Data->Cost.FinalCost[gun_index].description); return; } if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { strcpy(cost, (char *)""); return; } } void Clean_Ocpp_FinalCost(int gun_index) { if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { memset(&ShmOCPP16Data->Cost.FinalCost[gun_index], 0x00, sizeof(struct StrcutFinalCost)); return; } if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { return; } } int Get_Ocpp_FinalCostTxId(int gun_index) { int txId = 0; if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { txId = ShmOCPP16Data->Cost.FinalCost[gun_index].txId; } if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { } return txId; } //=============================================== // Ocpp TimeOffset //=============================================== void Get_Ocpp_TimeOffset(char *timeOffset) { if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { strcpy(timeOffset, (char *)ShmOCPP16Data->ConfigurationTable.CoreProfile[TimeOffset].ItemData); return; } if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { strcpy(timeOffset, ""); return; } strcpy(timeOffset, ""); } //=============================================== // Ocpp PreAuthAmount //=============================================== void Get_Ocpp_PreAuthAmount(char *amount) { if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { strcpy(amount, (char *)ShmOCPP16Data->ConfigurationTable.CoreProfile[PreAuthAmount].ItemData); return; } if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { strcpy(amount, ""); return; } strcpy(amount, ""); } //=============================================== // Ocpp PowerSharingServerIP //=============================================== void Get_Ocpp_PowerSharingServerIP(char *ip) { if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { strcpy(ip, (char *)ShmOCPP16Data->ConfigurationTable.CoreProfile[PowerSharingServerIP].ItemData); return; } if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { strcpy(ip, ""); return; } strcpy(ip, ""); } //=============================================== // Ocpp Refunding //=============================================== void Get_Ocpp_Refunding(char *Refunding) { if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { return; } if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { return; } } void Clean_Ocpp_Refunding(void) { if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { return; } if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { return; } } //=============================================== // Ocpp LcdOveride //=============================================== bool Is_Ocpp_LcdOverideReq(int *gun, int *page) { *gun = ShmSysConfigAndInfo->SysInfo.LcdOveride.connectorId; *page = ShmSysConfigAndInfo->SysInfo.LcdOveride.page_index; return ShmSysConfigAndInfo->SysInfo.LcdOveride.isOverideReq ? true : false; } void Clean_Ocpp_LcdOverideReq(void) { ShmSysConfigAndInfo->SysInfo.LcdOveride.isOverideReq = false; } //=============================================== // Ocpp StationInfo //=============================================== void Get_Ocpp_ChargerStationInfo(int *station_id, char *name) { if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { strcpy(name, (char *)ShmOCPP16Data->TcciCustomData.ChargerInfo.station_name); } if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { } } bool Is_Ocpp_ChargerStationReq(void) { if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { return ShmOCPP16Data->TcciCustomData.ChargerInfoReq ? true : false; } if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { return false; } return false; } void Clean_Ocpp_ChargerStationReq(void) { if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { ShmOCPP16Data->TcciCustomData.ChargerInfoReq = false; } if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { } } //=============================================== // Ocpp WeatherInfo //=============================================== void Get_Ocpp_WeatherInfo(int *weatherID, float *temperature) { if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { *weatherID = ShmOCPP16Data->TcciCustomData.WeatherInfo.weatherId; *temperature = ShmOCPP16Data->TcciCustomData.WeatherInfo.temperature; } if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { } } bool Is_Ocpp_WeatherReq(void) { if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { return ShmOCPP16Data->TcciCustomData.WeatherInfoReq ? true : false; } if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { return false; } return false; } void Clean_Ocpp_WeatherReq(void) { if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { ShmOCPP16Data->TcciCustomData.WeatherInfoReq = false; } if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { } } //=============================================== // Ocpp DeductInfo //=============================================== void Set_Ocpp_DeductTransaction(int transaction) { if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { ShmOCPP16Data->TcciCustomData.DeductInfo.txId = transaction; } if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { } } void Set_Ocpp_DeductCreditNo(char *userId) { if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { memcpy((char *)&ShmOCPP16Data->TcciCustomData.DeductInfo.creditNo, userId, strlen(userId)); } if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { } } void Set_Ocpp_DeductVemData(char *vemData) { if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { strcpy((char *)&ShmOCPP16Data->TcciCustomData.DeductInfo.vemData, vemData); } if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { } } void Set_Ocpp_DeductAmount(double value) { if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { ShmOCPP16Data->TcciCustomData.DeductInfo.amount = value; } if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { } } void Set_Ocpp_DeductResult(unsigned char result) { if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { ShmOCPP16Data->TcciCustomData.DeductInfo.deductResult = result; } if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { } } void Set_Ocpp_DonateInvoice(unsigned char donate) { if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { ShmOCPP16Data->TcciCustomData.DeductInfo.isDonateInvoice = donate ? YES : NO; } if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { } } bool Set_Ocpp_DeductInfo(DeductResultInfoData *deductInfo) { if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { ShmOCPP16Data->TcciCustomData.DeductInfo.txId = deductInfo->TransactionId; memcpy((char *)&ShmOCPP16Data->TcciCustomData.DeductInfo.creditNo, (char *)deductInfo->creditNo, sizeof(deductInfo->creditNo)); memcpy((char *)&ShmOCPP16Data->TcciCustomData.DeductInfo.vemData, deductInfo->VemData, sizeof(deductInfo->VemData)); ShmOCPP16Data->TcciCustomData.DeductInfo.amount = ((double)deductInfo->DeductAmount / 100); memcpy((char *)&ShmOCPP16Data->TcciCustomData.DeductInfo.approvalNo, deductInfo->ApprovalNumber, sizeof(deductInfo->ApprovalNumber)); ShmOCPP16Data->TcciCustomData.DeductInfo.deductResult = deductInfo->DeductResult; ShmOCPP16Data->TcciCustomData.DeductInfo.isDonateInvoice = deductInfo->IsDonateInvoice ? YES : NO; return true; } if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { } return false; } bool Is_Ocpp_ReportCreditDeductReq(void) { if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { return ShmOCPP16Data->TcciCustomData.ReportCreditDeductReq ? true : false; } if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { return false; } return false; } void Set_Ocpp_ReportCreditDeductReq(void) { if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { ShmOCPP16Data->TcciCustomData.ReportCreditDeductReq = YES; } if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { } } //=============================================== // Ocpp Tcci SerialNo //=============================================== void Clean_Ocpp_TcciSerialNo(int gun_index) { if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { memset((char *)&ShmOCPP16Data->TcciCustomData.SerialNo[gun_index], 0x00, sizeof(37)); } if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { } } //=============================================== // Ocpp Tcci ReaderStatus //=============================================== bool Set_Ocpp_TcciReaderStatus(int gun_index, DeductResultInfoData *ReaderStatus) { if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { if(ReaderStatus->DeductResult == _Deduct_PreAuth_Cancel || ReaderStatus->DeductResult == _Deduct_PreAuth || ReaderStatus->DeductResult == _Deduct_PreAuth_Pass) { switch(ReaderStatus->DeductResult) { case _Deduct_PreAuth_Pass: ShmOCPP16Data->TcciCustomData.ReaderStatus[gun_index].readerStatus = 1; break; case _Deduct_PreAuth_Cancel: ShmOCPP16Data->TcciCustomData.ReaderStatus[gun_index].readerStatus = 2; break; case _Deduct_PreAuth: ShmOCPP16Data->TcciCustomData.ReaderStatus[gun_index].readerStatus = 0; break; } memcpy((char *)&ShmOCPP16Data->TcciCustomData.ReaderStatus[gun_index].creditNo, ReaderStatus->creditNo, sizeof(ReaderStatus->creditNo)); memcpy((char *)&ShmOCPP16Data->TcciCustomData.VEMData[gun_index], ReaderStatus->VemData, sizeof(ReaderStatus->VemData)); return true; } } if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { } return false; } void Clean_Ocpp_TcciCreditInfo(int gun_index) { if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { memset((char *)&ShmOCPP16Data->TcciCustomData.ReaderStatus[gun_index].creditNo, 0x00, sizeof(ShmOCPP16Data->TcciCustomData.ReaderStatus[gun_index].creditNo)); memset((char *)&ShmOCPP16Data->TcciCustomData.VEMData[gun_index], 0x00, sizeof(ShmOCPP16Data->TcciCustomData.VEMData[gun_index])); } if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { } } void Set_Ocpp_TcciReaderStatusReq(int gun_index) { if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { ShmOCPP16Data->TcciCustomData.ReaderStatus[gun_index].ReportReaderStatusReq = true; } if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { } } bool Is_Ocpp_TcciReaderStatusReq(int gun_index) { if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { return ShmOCPP16Data->TcciCustomData.ReaderStatus[gun_index].ReportReaderStatusReq ? true : false; } if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { return false; } return false; } //=============================================== // Ocpp Tcci OccupancyFeeDisplay //=============================================== bool Is_Ocpp_TcciOccupancyDisplayReq(int gun_index) { if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { return ShmOCPP16Data->TcciCustomData.OccupancyFeeDisplay[gun_index].OccupancyFeeDisplayReq ? true : false; } if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { return false; } return false; } void Clean_Ocpp_TcciOccupancyDisplayReq(int gun_index) { if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { ShmOCPP16Data->TcciCustomData.OccupancyFeeDisplay[gun_index].OccupancyFeeDisplayReq = false; } if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { } } // input: gun_index, sn_len // output: sn // return: action int Get_Ocpp_TcciOccupancyAction(int gun_index, int sn_len, char *sn) { int action = 0; if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { action = ShmOCPP16Data->TcciCustomData.OccupancyFeeDisplay[gun_index].actionId; if(action == _ParkingAction_DisplayButton) { memcpy(sn, ShmOCPP16Data->TcciCustomData.OccupancyFeeDisplay[gun_index].occupancySN, sn_len); } } if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { } return action; } void Clean_Ocpp_TcciOccupancyActionAndSn(int gun_index) { if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { ShmOCPP16Data->TcciCustomData.OccupancyFeeDisplay[gun_index].actionId = 0; memset(ShmOCPP16Data->TcciCustomData.OccupancyFeeDisplay[gun_index].occupancySN, 0x00, sizeof(ShmOCPP16Data->TcciCustomData.OccupancyFeeDisplay[gun_index].occupancySN)); } if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { } } //=============================================== // Ocpp Tcci SetOccupancyPrice //=============================================== bool Is_Ocpp_TcciSetOccupancyPriceReq(void) { if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { return ShmOCPP16Data->TcciCustomData.SetOccupancyPrice.SetOccupancyPriceReq ? true : false; } if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { return false; } return false; } void Clean_Ocpp_TcciSetOccupancyPriceReq(void) { if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { ShmOCPP16Data->TcciCustomData.SetOccupancyPrice.SetOccupancyPriceReq = false; } if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { } } float Get_Ocpp_TcciOccupancyPrice(void) { if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { return ShmOCPP16Data->TcciCustomData.SetOccupancyPrice.price; } if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { } return 0; } //=============================================== // Ocpp Tcci GetOccupancyFee //=============================================== bool Is_Ocpp_TcciOccupancyFeeActReq(int gun_index) { if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { return ShmOCPP16Data->TcciCustomData.OccupancyFeeAct[gun_index].OccupancyFeeActReq ? true : false; } if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { return false; } return false; } void Set_Ocpp_TcciOccupancyFeeAct(int gun_index, OccupancyBillInfo *bill, int action) { if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { memset(ShmOCPP16Data->TcciCustomData.OccupancyFeeAct[gun_index].occupancySN, 0x00, sizeof(ShmOCPP16Data->TcciCustomData.OccupancyFeeAct[gun_index].occupancySN)); memcpy(ShmOCPP16Data->TcciCustomData.OccupancyFeeAct[gun_index].occupancySN, bill->Sn, sizeof(bill->Sn)); ShmOCPP16Data->TcciCustomData.OccupancyFeeAct[gun_index].action = action; ShmOCPP16Data->TcciCustomData.OccupancyFeeAct[gun_index].OccupancyFeeActReq = true; } if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { } } void Clean_Ocpp_TcciNotifyOccupancyFeeActReq(int gun_index) { if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { ShmOCPP16Data->TcciCustomData.OccupancyFeeAct[gun_index].action = _Notify_None; ShmOCPP16Data->TcciCustomData.OccupancyFeeAct[gun_index].OccupancyFeeActReq = false; } if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { } } void Get_Ocpp_TcciGetOccupancyFeeResponse(int gun_index, OccupancyBillInfo *bill) { if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { bill->Duration = ShmOCPP16Data->TcciCustomData.OccupancyFeeAct[gun_index].response_duration; bill->Fee = ShmOCPP16Data->TcciCustomData.OccupancyFeeAct[gun_index].response_occupancyFee; memcpy(bill->StartTime, ShmOCPP16Data->TcciCustomData.OccupancyFeeAct[gun_index].response_startTime, sizeof(bill->StartTime)); } if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { } } bool Is_Ocpp_TcciOccupancyFeeActStatus(int gun_index, char *status) { if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { return strcmp((char *)ShmOCPP16Data->TcciCustomData.OccupancyFeeAct[gun_index].response_status, status) == EQUAL ? true : false; } if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { } return false; } //=============================================== // Ocpp Tcci ReportOccupancyDeductReq //=============================================== bool Is_Ocpp_TcciReportOccupancyDeductReq(void) { if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { return ShmOCPP16Data->TcciCustomData.ReportOccupancyDeductReq ? true : false; } if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { return false; } return false; } void Set_Ocpp_TcciReportOccupancyDeductReq(void) { if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { ShmOCPP16Data->TcciCustomData.ReportOccupancyDeductReq = true; } if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { } } //=============================================== // Ocpp Tcci OccupancyDeductResult //=============================================== bool Set_Ocpp_OccupancyDeductResult(OccupancyDeductInfo *deduct, bool pass_fail) { if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { memset(&ShmOCPP16Data->TcciCustomData.OccupancyDeductResult, 0x00, sizeof(struct StructOccupancyDeductResult)); ShmOCPP16Data->TcciCustomData.OccupancyDeductResult.deductResult = pass_fail; ShmOCPP16Data->TcciCustomData.OccupancyDeductResult.amount = deduct->Fee; memcpy(&ShmOCPP16Data->TcciCustomData.OccupancyDeductResult.occupancySN[0], &deduct->Sn[0], sizeof(deduct->Sn)); memcpy(&ShmOCPP16Data->TcciCustomData.OccupancyDeductResult.creditNo[0], &deduct->creditNo[0], sizeof(deduct->creditNo)); memcpy(&ShmOCPP16Data->TcciCustomData.OccupancyDeductResult.approvalNo[0], &deduct->ApprovalNumber[0], sizeof(deduct->ApprovalNumber)); return true; } if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { } return false; } //=============================================== // Ocpp Start Transaction //=============================================== void Set_Ocpp_StartTransactionIdTag(int gun_index, char *id) { if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { strcpy((char *)ShmOCPP16Data->StartTransaction[gun_index].IdTag, id); } if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { strcpy((char *)ShmOCPP20Data->TransactionEvent [gun_index].idToken.idToken, id); } // MaintainServer if(strcmp((char *)&ShmSysConfigAndInfo->SysConfig.MaintainServerURL, "") != EQUAL) { strcpy((char *)ShmOCPP16DataPH->StartTransaction[gun_index].IdTag, id); } } void Set_Ocpp_StartTransactionReq(int gun_index) { if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { ShmOCPP16Data->CpMsg.bits[gun_index].StartTransactionReq = true; } if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { ShmOCPP20Data->CpMsg.bits [gun_index].TransactionEventReq = true; } // MaintainServer if(strcmp((char *)&ShmSysConfigAndInfo->SysConfig.MaintainServerURL, "") != EQUAL) { ShmOCPP16DataPH->CpMsg.bits[gun_index].StartTransactionReq = true; } } bool Is_Ocpp_StartTransactionConf(int gun_index) { if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { return ShmOCPP16Data->CpMsg.bits[gun_index].StartTransactionConf == YES ? true : false; } if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { if(ShmOCPP20Data->CpMsg.bits[gun_index].TransactionEventConf == YES) { if(strstr((char*)ShmOCPP20Data->TransactionEvent[gun_index].eventType, "Started") != NULL) { return true; } else { ShmOCPP20Data->CpMsg.bits[gun_index].TransactionEventConf = false; return false; } } else { return false; } } return false; } void Clean_Ocpp_StartTransactionConf(int gun_index) { if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { ShmOCPP16Data->CpMsg.bits[gun_index].StartTransactionConf = false; } if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { ShmOCPP20Data->CpMsg.bits[gun_index].TransactionEventConf = false; } // MaintainServer if(strcmp((char *)&ShmSysConfigAndInfo->SysConfig.MaintainServerURL, "") != EQUAL) { ShmOCPP16DataPH->CpMsg.bits[gun_index].StartTransactionConf = false; } } bool Is_Ocpp_StartTransaction_Status(int gun_index, char *status) { if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { return strcmp((char *)ShmOCPP16Data->StartTransaction[gun_index].ResponseIdTagInfo.Status, status) == EQUAL ? true : false; } if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { return strcmp((char *)ShmOCPP20Data->TransactionEvent[gun_index].Response_idTokenInfo.status, status) == EQUAL ? true : false; } return false; } bool Is_Ocpp_StartTransaction_Accepted(int gun_index) { return Is_Ocpp_StartTransaction_Status(gun_index, "Accepted"); } void Get_Ocpp_StartTransaction_Status(int gun_index, char *status) { if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { strcpy(status, (char *)ShmOCPP16Data->StartTransaction[gun_index].ResponseIdTagInfo.Status); } if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { strcpy(status, (char *)ShmOCPP20Data->TransactionEvent[gun_index].Response_idTokenInfo.status); } } void Get_Ocpp_TransactionId(int gun_index, char *transactionId) { if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { sprintf(transactionId, "%d", ShmOCPP16Data->StartTransaction[gun_index].ResponseTransactionId); return; } if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { strcpy(transactionId, (char *)&ShmOCPP20Data->TransactionEvent [gun_index].transactionInfo.transactionId[0]); return; } sprintf(transactionId, "%d", 0); } bool Is_Invalid_StartTransactionId(int gun_index) { if(Is_Ocpp_StartTransaction_Status(gun_index, "Blocked") || Is_Ocpp_StartTransaction_Status(gun_index, "Expired") || Is_Ocpp_StartTransaction_Status(gun_index, "Invalid") || Is_Ocpp_StartTransaction_Status(gun_index, "NoCredit") || Is_Ocpp_StartTransaction_Status(gun_index, "NotAllowedTypeEVSE") || Is_Ocpp_StartTransaction_Status(gun_index, "NotAtThisLocation") || Is_Ocpp_StartTransaction_Status(gun_index, "NotAtThisTime") || Is_Ocpp_StartTransaction_Status(gun_index, "Unknown")) { return true; } return false; } //=============================================== // Ocpp Stop Transaction //=============================================== void Set_Ocpp_StopTransactionId(int gun_index, char *id) { if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { strcpy((char *)ShmOCPP16Data->StopTransaction[gun_index].IdTag, id); return; } if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { strcpy((char *)ShmOCPP20Data->TransactionEvent [gun_index].idToken.idToken, id); return; } } void Set_Ocpp_StopTransactionReq(int gun_index) { if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { ShmOCPP16Data->CpMsg.bits[gun_index].StopTransactionReq = true; } if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { ShmOCPP20Data->CpMsg.bits [gun_index].TransactionEventReq = true; } // MaintainServer if(strcmp((char *)&ShmSysConfigAndInfo->SysConfig.MaintainServerURL, "") != EQUAL) { ShmOCPP16DataPH->CpMsg.bits[gun_index].StopTransactionReq = true; } } //=============================================== // Ocpp Check Backup Error Code //=============================================== void Chk_Ocpp_Backup_ErrorCode(int gun_index) { if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { if(strcmp((char *)ShmOCPP16Data->StatusNotification[gun_index].ErrorCode, "") == EQUAL) { if(strcmp((char *)_BackupStatusNotification[gun_index].ErrorCode, "") != EQUAL) { strcpy((char *)ShmOCPP16Data->StatusNotification[gun_index].ErrorCode, (char *)_BackupStatusNotification[gun_index].ErrorCode); strcpy((char *)ShmOCPP16Data->StatusNotification[gun_index].VendorErrorCode, (char *)_BackupStatusNotification[gun_index].VendorErrorCode); } } } if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { } } //=============================================== // Ocpp Reserve Now //=============================================== bool Is_Ocpp_ReserveNowReq(int gun_index) { if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { return ShmOCPP16Data->CsMsg.bits[gun_index].ReserveNowReq == YES ? true : false; } if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { return ShmOCPP20Data->CsMsg.bits[gun_index].ReserveNowReq == YES ? true : false; } return false; } void Clean_Ocpp_ReserveNowReq(int gun_index) { if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { ShmOCPP16Data->CsMsg.bits[gun_index].ReserveNowReq = false; return; } if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { ShmOCPP20Data->CsMsg.bits[gun_index].ReserveNowReq = false; return; } } int Get_Ocpp_ReserveNowId(int gun_index) { if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { return ShmOCPP16Data->ReserveNow[gun_index].ReservationId; } if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { return ShmOCPP20Data->ReserveNow[gun_index].id; } return 0; } void Set_Ocpp_ReserveNowConf(int gun_index) { if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { ShmOCPP16Data->CsMsg.bits [gun_index].ReserveNowConf = true; return; } if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { ShmOCPP20Data->CsMsg.bits [gun_index].ReserveNowConf = true; return; } } void Get_Ocpp_ReserveNowExpiryDate(int gun_index, char *date) { if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { strcpy(date, (char *)ShmOCPP16Data->ReserveNow[gun_index].ExpiryDate); return; } if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { strcpy(date, (char *)ShmOCPP20Data->ReserveNow[gun_index].expiryDateTime); return; } strcpy(date, ""); return; } bool Is_Ocpp_ReserveNowExpired(int gun_index) { bool _expired = true; char _expiryDate[128]; Get_Ocpp_ReserveNowExpiryDate(gun_index, _expiryDate); _expired = CheckTimeOut(_expiryDate); return _expired; } void Get_Ocpp_ReserveNowIdTag(int gun_index, char *idTag) { if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { strcpy(idTag, (char *)ShmOCPP16Data->ReserveNow[gun_index].IdTag); return; } if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { strcpy(idTag, (char *)ShmOCPP20Data->ReserveNow[gun_index].idToken.idToken); return; } strcpy(idTag, ""); return; } bool Is_Ocpp_ReserveNowIdTag(uint8_t gun_index, char *authIdTag) { char ReserveIdTag[32]; Get_Ocpp_ReserveNowIdTag(gun_index, ReserveIdTag); return strcmp(ReserveIdTag, authIdTag) == EQUAL ? true : false; } //=============================================== // Ocpp Cancel Reservation //=============================================== bool Is_Ocpp_CancelReservationReq(int gun_index) { if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { return ShmOCPP16Data->CsMsg.bits[gun_index].CancelReservationReq == YES ? true : false; } if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { return ShmOCPP20Data->CsMsg.bits[gun_index].CancelReservationReq == YES ? true : false; } return false; } void Clean_Ocpp_CancelReservationReq(int gun_index) { if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { ShmOCPP16Data->CsMsg.bits[gun_index].CancelReservationReq = false; return; } if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { ShmOCPP20Data->CsMsg.bits[gun_index].CancelReservationReq = false; return; } } void Set_Ocpp_CancelReservationConf(int gun_index) { if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { ShmOCPP16Data->CsMsg.bits [gun_index].CancelReservationConf = true; return; } if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { ShmOCPP20Data->CsMsg.bits [gun_index].CancelReservationConf = true; return; } } //=============================================== // Ocpp Change Availability //=============================================== bool Is_Ocpp_ChangeAvailabilityReq(int gun_index) { if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { return ShmOCPP16Data->CsMsg.bits[gun_index].ChangeAvailabilityReq == YES ? true : false; } if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { return ShmOCPP20Data->CsMsg.bits[gun_index].ChangeAvailabilityReq == YES ? true : false; } return false; } void Clean_Ocpp_ChangeAvailabilityReq(int gun_index) { if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { ShmOCPP16Data->CsMsg.bits[gun_index].ChangeAvailabilityReq = false; return; } if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { ShmOCPP20Data->CsMsg.bits[gun_index].ChangeAvailabilityReq = false; return; } } bool Chk_Ocpp_Availability_Type(int gun_index, char *type) { if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { return strcmp((char *)ShmOCPP16Data->ChangeAvailability[gun_index].Type, type) == EQUAL ? true : false; } if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { return strcmp((char *)ShmOCPP20Data->ChangeAvailability[gun_index].operationalStatus, type) == EQUAL ? true : false; } return false; } //=============================================== // Ocpp Unlock Connector //=============================================== bool Is_Ocpp_UnlockConnectorReq(int gun_index) { if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { return ShmOCPP16Data->CsMsg.bits[gun_index].UnlockConnectorReq == YES ? true : false; } if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { return ShmOCPP20Data->CsMsg.bits[gun_index].UnlockConnectorReq == YES ? true : false; } return false; } void Clean_Ocpp_UnlockConnectorReq(int gun_index) { if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { ShmOCPP16Data->CsMsg.bits[gun_index].UnlockConnectorReq = false; return; } if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { ShmOCPP20Data->CsMsg.bits[gun_index].UnlockConnectorReq = false; return; } } void Set_Ocpp_UnlockConnectorConf(int gun_index) { if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { strcpy((char *)ShmOCPP16Data->UnlockConnector[gun_index].ResponseStatus, "Unlocked"); ShmOCPP16Data->CsMsg.bits [gun_index].UnlockConnectorConf = true; return; } if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { strcpy((char *)ShmOCPP20Data->UnlockConnector[gun_index].Response_status, "Unlocked"); ShmOCPP20Data->CsMsg.bits [gun_index].UnlockConnectorConf = true; return; } } //=============================================== // Ocpp Remote Start //=============================================== bool Is_Ocpp_RemoteStartReq(int gun_index) { if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { return ShmOCPP16Data->CsMsg.bits[gun_index].RemoteStartTransactionReq == YES ? true : false; } if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { return ShmOCPP20Data->CsMsg.bits[gun_index].RequestStartTransactionReq == YES ? true : false; } return false; } void Clean_Ocpp_RemoteStartReq(int gun_index) { if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { ShmOCPP16Data->CsMsg.bits[gun_index].RemoteStartTransactionReq = false; return; } if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { ShmOCPP20Data->CsMsg.bits[gun_index].RequestStartTransactionReq = false; return; } } void Get_Ocpp_RemoteStartIdTag(int gun_index, char *idTag) { if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { strcpy(idTag, (char *)&ShmOCPP16Data->RemoteStartTransaction[gun_index].IdTag[0]); return; } if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { strcpy(idTag, (char *)&ShmOCPP20Data->RequestStartTransaction[gun_index].idToken.idToken[0]); return; } strcpy(idTag, ""); } //=============================================== // Ocpp Remote Stop //=============================================== bool Is_Ocpp_RemoteStopReq(int gun_index) { if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { return ShmOCPP16Data->CsMsg.bits[gun_index].RemoteStopTransactionReq == YES ? true : false; } if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { return ShmOCPP20Data->CsMsg.bits[gun_index].RequestStopTransactionReq == YES ? true : false; } return false; } void Clean_Ocpp_RemoteStopReq(int gun_index) { if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { ShmOCPP16Data->CsMsg.bits[gun_index].RemoteStopTransactionReq = false; return; } if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { ShmOCPP20Data->CsMsg.bits[gun_index].RequestStopTransactionReq = false; return; } } //=============================================== // Ocpp StopReason //=============================================== void Set_Ocpp_StopReason(int gun_index, char *reason) { if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { if(strcmp((char *)ShmOCPP16Data->StopTransaction[gun_index].StopReason, "") == EQUAL) { strcpy((char *)ShmOCPP16Data->StopTransaction[gun_index].StopReason, reason); } } if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { if(strcmp((char *)ShmOCPP20Data->TransactionEvent[gun_index].transactionInfo.stoppedReason, "" ) == EQUAL) { strcpy((char *)ShmOCPP20Data->TransactionEvent[gun_index].transactionInfo.stoppedReason, reason); } } // Maintain server if(strcmp((char *)&ShmSysConfigAndInfo->SysConfig.MaintainServerURL, "") != EQUAL) { memcpy(ShmOCPP16DataPH->StopTransaction[gun_index].StopReason, ShmOCPP16Data->StopTransaction[gun_index].StopReason, ARRAY_SIZE(ShmOCPP16Data->StopTransaction[gun_index].StopReason)); } } void Get_Ocpp_StopReason(int gun_index, char *reason) { if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { strcpy(reason, (char *)ShmOCPP16Data->StopTransaction[gun_index].StopReason); return; } if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { strcpy(reason, (char *)ShmOCPP20Data->TransactionEvent[gun_index].transactionInfo.stoppedReason); return; } strcpy(reason, ""); } void Clean_Ocpp_StopReason(int gun_index) { if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { strcpy((char *)ShmOCPP16Data->StopTransaction[gun_index].StopReason, ""); } if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { strcpy((char *)ShmOCPP20Data->TransactionEvent[gun_index].transactionInfo.stoppedReason, ""); } // Maintain server if(strcmp((char *)&ShmSysConfigAndInfo->SysConfig.MaintainServerURL, "") != EQUAL) { strcpy((char *)ShmOCPP16DataPH->StopTransaction[gun_index].StopReason, ""); } } //=============================================== // Ocpp StatusNotification ErrorCode //=============================================== void Set_Ocpp_StatusNotificationErrorCode(int gun_index, char *errCode) { if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { strcpy((char *)ShmOCPP16Data->StatusNotification[gun_index].ErrorCode, errCode); return; } if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { return; } } bool Is_Ocpp_StatusNotificationErrorCode(int gun_index, char *errCode) { if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { return strcmp((char *)ShmOCPP16Data->StatusNotification[gun_index].ErrorCode, errCode) == EQUAL ? true : false; } if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { return strcmp((char *)_BackupStatusNotification[gun_index].ErrorCode, errCode) == EQUAL ? true : false; } return false; } //=============================================== // Ocpp StatusNotification VendorErrorCode //=============================================== void Set_Ocpp_StatusNotificationVendorCode(int gun_index, char *vendorCode) { if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { strcpy((char *)ShmOCPP16Data->StatusNotification[gun_index].VendorErrorCode, vendorCode); return; } if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { return; } } bool Is_Ocpp_StatusNotificationVendorCode(int gun_index, char *vendorCode) { if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { return strcmp((char *)ShmOCPP16Data->StatusNotification[gun_index].VendorErrorCode, vendorCode) == EQUAL ? true : false; } if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { return strcmp((char *)_BackupStatusNotification[gun_index].VendorErrorCode, vendorCode) == EQUAL ? true : false; } return false; } //=============================================== // Ocpp ChargingProfileConf //=============================================== bool Is_Ocpp_ChargingProfileConf(int gun_index) { if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { return ShmOCPP16Data->CSUMsg.bits[gun_index].ChargingProfileConf == YES ? true : false; } if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { return ShmOCPP20Data->CSUMsg.bits[gun_index].ChargingProfileConf == YES ? true : false; } return false; } void Clean_Ocpp_ChargingProfileConf(int gun_index) { if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { ShmOCPP16Data->CSUMsg.bits[gun_index].ChargingProfileConf = NO; return; } if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { ShmOCPP20Data->CSUMsg.bits[gun_index].ChargingProfileConf = NO; return; } } //=============================================== // Ocpp ChargingProfileReq //=============================================== bool Is_Ocpp_ChargingProfileReq(int gun_index) { if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { return ShmOCPP16Data->CSUMsg.bits[gun_index].ChargingProfileReq == YES ? true : false; } if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { return ShmOCPP20Data->CSUMsg.bits[gun_index].ChargingProfileReq == YES ? true : false; } return false; } void Set_Ocpp_ChargingProfileReq(int gun_index) { if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { ShmOCPP16Data->CSUMsg.bits[gun_index].ChargingProfileReq = YES; return; } if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { ShmOCPP20Data->CSUMsg.bits[gun_index].ChargingProfileReq = YES; return; } } //=============================================== // Ocpp SmartChargingProfile ChargingProfileKind //=============================================== bool Is_Ocpp_ChargingProfileKind(int gun_index, char *kind) { if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { return strcmp((char *)ShmOCPP16Data->SmartChargingProfile[gun_index].ChargingProfileKind, kind) == EQUAL ? true : false; } if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { return strcmp((char *)ShmOCPP20Data->SmartChargingProfile [gun_index].chargingProfileKind, kind) == EQUAL ? true : false; } return false; } bool Is_Ocpp_ChargingProfileId(int gun_index) { if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { return ShmOCPP16Data->SmartChargingProfile[gun_index].ChargingProfileId == YES ? true : false; } if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { return ShmOCPP20Data->SmartChargingProfile[gun_index].id == YES ? true : false; } return false; } int Get_Ocpp_ChargingProfileStartTime(int gun_index) { if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { return GetStartScheduleTime(ShmOCPP16Data->SmartChargingProfile[gun_index].ChargingSchedule.StartSchedule); } if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { return GetStartScheduleTime(ShmOCPP20Data->SmartChargingProfile[gun_index].chargingSchedule[0].startSchedule); } return 0; } int Get_Ocpp_ChargingProfileScheduleCount(int gun_index) { if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { return ARRAY_SIZE(ShmOCPP16Data->SmartChargingProfile[gun_index].ChargingSchedule.ChargingSchedulePeriod); } if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { return ARRAY_SIZE(ShmOCPP20Data->SmartChargingProfile[gun_index].chargingSchedule[0].chargingSchedulePeriod); } return 0; } int Get_Ocpp_ChargingProfileScheduleTime(int gun_index, int schedule_index) { if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { return ShmOCPP16Data->SmartChargingProfile[gun_index].ChargingSchedule.ChargingSchedulePeriod[schedule_index].StartPeriod; } if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { return ShmOCPP20Data->SmartChargingProfile[gun_index].chargingSchedule[0].chargingSchedulePeriod[schedule_index].startPeriod; } return 0; } float Get_Ocpp_ChargingProfileScheduleLimit(int gun_index, int schedule_index) { if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { return ShmOCPP16Data->SmartChargingProfile[gun_index].ChargingSchedule.ChargingSchedulePeriod[schedule_index].Limit; } if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { return ShmOCPP20Data->SmartChargingProfile[gun_index].chargingSchedule[0].chargingSchedulePeriod[schedule_index].limit; } return 0; } int Get_Ocpp_ChargingProfileScheduleNumberPhases(int gun_index, int schedule_index) { if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { return ShmOCPP16Data->SmartChargingProfile[gun_index].ChargingSchedule.ChargingSchedulePeriod[schedule_index].NumberPhases; } if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { return ShmOCPP20Data->SmartChargingProfile[gun_index].chargingSchedule[0].chargingSchedulePeriod[schedule_index].numberPhases; } return 0; } int Get_Ocpp_ChargingProfileStartIndex(int gun_index) { int _time = 0, _scheduleTime = 0; int _maxCount = 0; float _limit = 0; int _startCount = NO_DEFINE; _time = Get_Ocpp_ChargingProfileStartTime(gun_index); _maxCount = Get_Ocpp_ChargingProfileScheduleCount(gun_index); for(int i = 0; i < _maxCount; i++) { _scheduleTime = Get_Ocpp_ChargingProfileScheduleTime(gun_index, i); if(_time >= _scheduleTime) { _limit = Get_Ocpp_ChargingProfileScheduleLimit(gun_index, i); if((i == 0 && _limit >= MIN_OUTPUT_CUR) || _limit > MIN_OUTPUT_CUR) { _startCount = i; } } } return _startCount; } //=============================================== // Ocpp MaxChargingProfile ChargingProfileKind //=============================================== bool Is_Ocpp_MaxChargingProfileKind(char *kind) { if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { return strcmp((char *)ShmOCPP16Data->MaxChargingProfile.ChargingProfileKind, kind) == EQUAL ? true : false; } if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { return strcmp((char *)ShmOCPP20Data->MaxChargingProfile.chargingProfileKind, kind) == EQUAL ? true : false; } return false; } bool Is_Ocpp_MaxChargingProfileId(void) { if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { return ShmOCPP16Data->MaxChargingProfile.ChargingProfileId == YES ? true : false; } if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { return ShmOCPP20Data->MaxChargingProfile.id == YES ? true : false; } return false; } int Get_Ocpp_MaxProfileStartTime(void) { if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { return GetStartScheduleTime(ShmOCPP16Data->MaxChargingProfile.ChargingSchedule.StartSchedule); } if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { return GetStartScheduleTime(ShmOCPP20Data->MaxChargingProfile.chargingSchedule[0].startSchedule); } return 0; } int Get_Ocpp_MaxProfileScheduleCount(void) { if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { return ARRAY_SIZE(ShmOCPP16Data->MaxChargingProfile.ChargingSchedule.ChargingSchedulePeriod); } if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { return ARRAY_SIZE(ShmOCPP20Data->MaxChargingProfile.chargingSchedule[0].chargingSchedulePeriod); } return 0; } int Get_Ocpp_MaxProfileScheduleTime(int schedule_index) { if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { return ShmOCPP16Data->MaxChargingProfile.ChargingSchedule.ChargingSchedulePeriod[schedule_index].StartPeriod; } if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { return ShmOCPP20Data->MaxChargingProfile.chargingSchedule[0].chargingSchedulePeriod[schedule_index].startPeriod; } return 0; } float Get_Ocpp_MaxProfileScheduleLimit(int schedule_index) { if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { return ShmOCPP16Data->MaxChargingProfile.ChargingSchedule.ChargingSchedulePeriod[schedule_index].Limit; } if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { return ShmOCPP20Data->MaxChargingProfile.chargingSchedule[0].chargingSchedulePeriod[schedule_index].limit; } return 0; } int Get_Ocpp_MaxProfileScheduleNumberPhases(int schedule_index) { if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { return ShmOCPP16Data->MaxChargingProfile.ChargingSchedule.ChargingSchedulePeriod[schedule_index].NumberPhases; } if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { return ShmOCPP20Data->MaxChargingProfile.chargingSchedule[0].chargingSchedulePeriod[schedule_index].limit; } return 0; } int Get_Ocpp_MaxProfileStartIndex(void) { int _time = 0, _scheduleTime = 0; int _maxCount = 0; float _limit = 0; int _startCount = NO_DEFINE; _time = Get_Ocpp_MaxProfileStartTime(); _maxCount = Get_Ocpp_MaxProfileScheduleCount(); for(int i = 0; i < _maxCount; i++) { _scheduleTime = Get_Ocpp_MaxProfileScheduleTime(i); if(_time >= _scheduleTime) { _limit = Get_Ocpp_MaxProfileScheduleLimit(i); if((i == 0 && _limit >= MIN_OUTPUT_CUR) || _limit > MIN_OUTPUT_CUR) { _startCount = i; } } } return _startCount; } //=============================================== // Ocpp isRemoteStartWaitReq //=============================================== int Is_Ocpp_RemoteStartWaitReq(void) { if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { return ShmOCPP16Data->MsMsg.bits.isRemoteStartWaitReq; } if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { return ShmOCPP20Data->MsMsg.bits.isRemoteStartWaitReq; } return 0; } //=============================================== // Ocpp SessionTarget //=============================================== void Get_Ocpp_SessionTarget(int gunIndex, struct StructSessionTarget *sessionTarget) { if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { memcpy(sessionTarget, &ShmOCPP16Data->SessionTarget[gunIndex], sizeof(struct StructSessionTarget)); } if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { memcpy(sessionTarget, &ShmOCPP20Data->SessionTarget[gunIndex], sizeof(struct StructSessionTarget)); } } //=============================================== // Ocpp OffLineMaxChargingPower //=============================================== int Get_Ocpp_OffLineMaxChargingPower(void) { // unit: W int maxChargingPower = 0; if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { maxChargingPower = atoi((char *)ShmOCPP16Data->ConfigurationTable.CoreProfile[OffLineMaxChargingPower].ItemData); } if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { maxChargingPower = atoi((char *)ShmOCPP20Data->ControllerComponentVariable[OffLineMaxChargingPower].variableAttribute[0].value); } return maxChargingPower > 0 ? maxChargingPower : 0; } //=============================================== // Ocpp OcmfData //=============================================== bool Is_Ocpp_SendOcmfDataReq(int gunIndex) { if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { return ShmOCPP16Data->OcmfData[gunIndex].SendOcmfDataReq == YES ? true : false; } if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { } return false; } void Set_Ocpp_SendOcmfDataReq(int gunIndex) { if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { ShmOCPP16Data->OcmfData[gunIndex].SendOcmfDataReq = YES; } if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { } } void Clean_Ocpp_SendOcmfDataReq(int gunIndex) { if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { ShmOCPP16Data->OcmfData[gunIndex].SendOcmfDataReq = NO; } if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { } } void Set_Ocpp_OcmfData(int gunIndex, char *key, char *ocmfInfo) { if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { strncpy((char *)ShmOCPP16Data->OcmfData[gunIndex].PublicKey, key, sizeof(ShmOCPP16Data->OcmfData[gunIndex].PublicKey)); strncpy((char *)ShmOCPP16Data->OcmfData[gunIndex].DataString, ocmfInfo, sizeof(ShmOCPP16Data->OcmfData[gunIndex].DataString)); } if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { } } //=============================================== // Set_StartIdType //=============================================== void Set_StartIdType(int gunIndex, int type) { chargingInfo[gunIndex]->StartIdType = type; } //=============================================== // DeductResult //=============================================== void Set_Deduct_UserId(int gunIndex, char *userId) { memcpy((char *)&ShmChargerInfo->DeductResultReq[gunIndex].creditNo, userId, strlen(userId)); } void Set_Deduct_TransactionId(int gunIndex, int transaction) { ShmChargerInfo->DeductResultReq[gunIndex].TransactionId = transaction; } void Clean_DeductInfo(int gunIndex) { memset(&ShmChargerInfo->DeductResultReq[gunIndex], 0x00, sizeof(DeductResultInfoData)); } bool Is_DeductResultReq(int gunIndex) { return ShmChargerInfo->DeductResultReq[gunIndex].DeductReq ? true : false; } //=============================================== // ReaderStatus //=============================================== bool Is_ReaderStatusReq(int gunIndex) { return ShmChargerInfo->ReaderStatus[gunIndex].ReaderStatusReq ? true : false; } void Clean_ReaderStatusInfo(int gunIndex) { memset(&ShmChargerInfo->ReaderStatus[gunIndex], 0x00, sizeof(DeductResultInfoData)); } //=============================================== // TransactionInfoData //=============================================== void Set_UserTransactionId(int gunIndex, int transaction) { ShmChargerInfo->UserTransaction[gunIndex].TransactionId = transaction; } void Set_UserPrice(int gunIndex, float price) { ShmChargerInfo->UserTransaction[gunIndex].UserPrice = price; } void Set_UserTotalCost(int gunIndex, float cost) { ShmChargerInfo->UserTransaction[gunIndex].TotalCost = cost; } void Set_UserAccountBalance(int gunIndex, float balance) { ShmChargerInfo->UserTransaction[gunIndex].AccountBalance = balance; } void Set_UserDiscount(int gunIndex, float discount) { ShmChargerInfo->UserTransaction[gunIndex].CostDiscount = discount; } void Clean_UserTransaction(int gunIndex) { memset(&ShmChargerInfo->UserTransaction[gunIndex], 0x00, sizeof(TransactionInfoData)); ShmChargerInfo->UserTransaction[gunIndex].AccountBalance = -65535; } void Clean_UserPriceAndReceipt(int gunIndex) { memset((char *)&ShmChargerInfo->PriceAndReceiptInfo.UserPriceString[gunIndex][0], 0x00, sizeof(ShmChargerInfo->PriceAndReceiptInfo.UserPriceString[gunIndex])); memset((char *)&ShmChargerInfo->PriceAndReceiptInfo.ReceiptUrl[gunIndex][0], 0x00, sizeof(ShmChargerInfo->PriceAndReceiptInfo.ReceiptUrl[gunIndex])); } //=============================================== // OccupancyDeductReq //=============================================== bool Is_OccupancyDeductReq(int gunIndex) { return ShmChargerInfo->AllBill.OccupancyInfo[gunIndex].OccupancyReq.bits.DeductReq ? true : false; } void Clean_OccupancyDeductReq(int gunIndex) { ShmChargerInfo->AllBill.OccupancyInfo[gunIndex].OccupancyReq.bits.DeductReq = false; } bool Is_OccupancyKeepCountingReq(int gunIndex) { return ShmChargerInfo->AllBill.OccupancyInfo[gunIndex].OccupancyReq.bits.KeepCounting ? true : false; } void Set_OccupancyKeepCountingReq(int gunIndex) { ShmChargerInfo->AllBill.OccupancyInfo[gunIndex].OccupancyReq.bits.KeepCounting = true; } void Clean_OccupancyKeepCountingReq(int gunIndex) { ShmChargerInfo->AllBill.OccupancyInfo[gunIndex].OccupancyReq.bits.KeepCounting = false; } bool Is_OccupancyFeeForceCancelReq(int gunIndex) { return ShmChargerInfo->AllBill.OccupancyInfo[gunIndex].OccupancyReq.bits.ForceCancel ? true : false; } void Set_OccupancyFeeForceCancelReq(int gunIndex) { ShmChargerInfo->AllBill.OccupancyInfo[gunIndex].OccupancyReq.bits.ForceCancel = true; } void Clean_OccupancyFeeForceCancelReq(int gunIndex) { ShmChargerInfo->AllBill.OccupancyInfo[gunIndex].OccupancyReq.bits.ForceCancel = false; } //=============================================== // Ocpp GetDiagnosticsReq //=============================================== bool Is_Ocpp_GetDiagnosticsReq(void) { if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { return ShmOCPP16Data->MsMsg.bits.GetDiagnosticsReq == YES ? true : false; } if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { } return false; } void Clean_Ocpp_GetDiagnosticsReq(void) { if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { ShmOCPP16Data->MsMsg.bits.GetDiagnosticsReq = false; } if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { } } //=============================================== // Main process //=============================================== // 檢查 Byte 中某個 Bit 的值 // _byte : 欲改變的 byte // _bit : 該 byte 的第幾個 bit unsigned char DetectBitValue(unsigned char _byte, unsigned char _bit) { return ( _byte & mask_table[_bit] ) != 0x00; } // 設定 Byte 中某個 Bit的值 // _byte : 欲改變的 byte // _bit : 該 byte 的第幾個 bit // value : 修改的值為 0 or 1 void SetBitValue(unsigned char *_byte, unsigned char _bit, unsigned char value) { if(value == 1) *_byte |= (1 << _bit); else if (value == 0) *_byte ^= (1 << _bit); } void UserScanFunction() { } unsigned char isModeChange(unsigned char gun_index) { unsigned char result = NO; if(chargingInfo[gun_index]->SystemStatus != chargingInfo[gun_index]->PreviousSystemStatus) { result = YES; chargingInfo[gun_index]->PreviousSystemStatus = chargingInfo[gun_index]->SystemStatus; } return result; } void AnnounceAccountBalance(unsigned char index, float balance) { ShmSysConfigAndInfo->SysInfo.ConnectorInfo[index].Parameter.bits.AnnounceBalance = true; ShmSysConfigAndInfo->SysInfo.ConnectorInfo[index].AccountBalance = balance; if(!ShmChargerInfo->Control.TestCtrl.bits.DisableBalance) { Set_Connector_MiscCommand(index, MISC_CONN_ACCOUNT_BALANCE); } LOG_INFO("%sAnnounce Account Balance %4.2f To Connector %d", ShmChargerInfo->Control.TestCtrl.bits.DisableBalance ? "Do Not " : "", balance, index + 1); } void FouceAnnounceAccountBalance(unsigned char index) { if(!ShmSysConfigAndInfo->SysInfo.ConnectorInfo[index].Parameter.bits.AnnounceBalance) { AnnounceAccountBalance(index, 0); } } void CleanConnectorUserIdAndPrice(unsigned char index) { if(chargingInfo[index]->SystemStatus == S_IDLE) { LOG_INFO("*********** Connector %d Clean UserId & UserPrice ***********", index + 1); memset(chargingInfo[index]->StartUserId, 0x00, 32); ShmSysConfigAndInfo->SysInfo.ConnectorInfo[index].UserPrice = 0; ShmSysConfigAndInfo->SysInfo.ConnectorInfo[index].AccountBalance = -65535; ShmSysConfigAndInfo->SysInfo.ConnectorInfo[index].Parameter.bits.AnnounceBalance = false; } } void DispenserAuthInitial(unsigned char dispenser) { LOG_INFO("*********** Dispenser %d Authorizing Initial ***********", dispenser + 1); memset(&ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[dispenser].AuthInfo, 0x00, sizeof(AuthorizingInfoData)); // clean dispenser price memset((char *)&ShmChargerInfo->PriceAndReceiptInfo.DispenserPriceString[dispenser][0], 0x00, sizeof(ShmChargerInfo->PriceAndReceiptInfo.DispenserPriceString[dispenser])); } void GunAuthInitial(unsigned char connector) { LOG_INFO("*********** Gun %d Authorizing Initial ***********", connector + 1); memset(&ShmSysConfigAndInfo->SysInfo.ConnectorInfo[connector].AuthInfo, 0x00, sizeof(AuthorizingInfoData)); } unsigned char _preGunAuthResult[GENERAL_GUN_QUANTITY]; unsigned char _preDispenserAuthResult[GENERAL_GUN_QUANTITY]; struct timespec _GunAuth_Time[GENERAL_GUN_QUANTITY]; struct timespec _DispenserAuth_Time[GENERAL_GUN_QUANTITY]; void AuthorizeTimeoutProcess(void) { int CompletedTime = 0; for(int index = 0; index < GENERAL_GUN_QUANTITY; index++) { if(ShmSysConfigAndInfo->SysInfo.ConnectorInfo[index].AuthInfo.AuthResult != _AuthResult_None) { if(_preGunAuthResult[index] != ShmSysConfigAndInfo->SysInfo.ConnectorInfo[index].AuthInfo.AuthResult) { GetClockTime(&_GunAuth_Time[index]); } if(ShmSysConfigAndInfo->SysInfo.ConnectorInfo[index].AuthInfo.AuthResult == _AuthResult_Invalid) { FouceAnnounceAccountBalance(index); } if(ShmSysConfigAndInfo->SysInfo.ConnectorInfo[index].AuthInfo.AuthResult == _AuthResult_Invalid) { if(GetTimeoutValue(_GunAuth_Time[index]) / uSEC_VAL >= AUTHORIZE_COMPLETED_TIME) { LOG_INFO("*********** Gun %d Authorizing Initial ***********", index + 1); memset(&ShmSysConfigAndInfo->SysInfo.ConnectorInfo[index].AuthInfo, 0x00, sizeof(AuthorizingInfoData)); CleanConnectorUserIdAndPrice(index); } } } _preGunAuthResult[index] = ShmSysConfigAndInfo->SysInfo.ConnectorInfo[index].AuthInfo.AuthResult; } for(int index = 0; index < GENERAL_GUN_QUANTITY; index++) { if(ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[index].AuthInfo.AuthResult != _AuthResult_None) { if(_preDispenserAuthResult[index] != ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[index].AuthInfo.AuthResult) { GetClockTime(&_DispenserAuth_Time[index]); } CompletedTime = ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[index].AuthInfo.AuthResult == _AuthResult_Valid ? (ShmChargerInfo->CabinetMiscValue.ConnectionTimeout + AUTHORIZE_COMPLETED_TIME) : AUTHORIZE_COMPLETED_TIME; if(GetTimeoutValue(_DispenserAuth_Time[index]) / uSEC_VAL >= CompletedTime) { DispenserAuthInitial(index); } } _preDispenserAuthResult[index] = ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[index].AuthInfo.AuthResult; } } BOOL IsConnectorAuthorizeSuccess(unsigned char connector) { BOOL success = false; if(ShmSysConfigAndInfo->SysInfo.ConnectorInfo[connector].AuthInfo.AuthResult == _AuthResult_Valid) { success = true; } return success; } BOOL IsAutoGunSelectionAuthorizeSuccess(unsigned char connector) { BOOL success = false; unsigned char dispenser = 0; dispenser = ShmSysConfigAndInfo->SysInfo.ConnectorInfo[connector].ParentDispensetIndex; if(ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[dispenser].AuthInfo.AuthResult == _AuthResult_Valid) { success = true; } return success; } bool CheckConnectorTypeStatus(void) { bool result = true; if (strlen((char *) ShmSysConfigAndInfo->SysConfig.ModelName) >= 14) { ShmSysConfigAndInfo->SysConfig.TotalConnectorCount = ShmChargerInfo->Control.MaxConnector; ShmChargerInfo->Control.ChargerRatingPower = ParsingRatingPower((char *)ShmSysConfigAndInfo->SysConfig.ModelName); ShmChargerInfo->Control.PsuQuantityByModel = ShmChargerInfo->Control.ChargerRatingPower / (INFY_SINGLE_PSU_POWER / 100); LOG_INFO("DC Gun Count = %d, RatingPower = %d.%d kW", ShmSysConfigAndInfo->SysConfig.TotalConnectorCount, (ShmChargerInfo->Control.ChargerRatingPower / 10), (ShmChargerInfo->Control.ChargerRatingPower % 10)); if(ShmSysConfigAndInfo->SysConfig.TotalConnectorCount == 0) { result = false; } //DO360 charging info default setting for(int i = 0; i < CONNECTOR_QUANTITY; i++) { chargingInfo[i] = &ShmSysConfigAndInfo->SysInfo.ConnectorInfo[i].GeneralChargingData; chargingInfo[i]->Index = (i < ShmSysConfigAndInfo->SysConfig.WiringInfo.MaxConnectorQuantity || i == 0) ? i : 0xFF; chargingInfo[i]->Evboard_id = 0x00; chargingInfo[i]->ReservationId = -1; chargingInfo[i]->slotsIndex = 0; chargingInfo[i]->SystemStatus = S_BOOTING; chargingInfo[i]->Type = _Type_Unknown; chargingInfo[i]->type_index = 0; chargingInfo[i]->IsAvailable = YES; } } else { // Module Name 不正確 - 告警 result = false; } return result; } void KillTaskExceptPrimary() { system("killall Module_Authorize"); system("killall Module_CabinetParallel"); system("killall Module_ChargerSelfTest"); system("killall Module_LedIndication"); system("killall Module_EvComm"); system("killall Module_InternalComm"); KillPowerModuleTask(); system("killall Module_4g &"); system("killall Module_Wifi &"); } void KillNtpd(void) { system("killall ntpd"); } void KillAllTask() { system("killall Module_Authorize"); system("killall Module_CabinetParallel"); system("killall Module_ChargerSelfTest"); system("killall Module_LedIndication"); system("killall Module_EventLogging"); system("killall Module_PrimaryComm"); system("killall Module_EvComm"); system("killall Module_LcmControl"); system("killall Module_InternalComm"); KillPowerModuleTask(); Kill_Ocpp_Service(); Kill_MaintainOcpp_Service(); system("killall Module_4g &"); system("killall Module_Wifi &"); } int TransferImageViaFTP(char *IpAddress, char *SourcePath) { int isPass = PASS; unsigned char ftpcmdbuf[256]; //Using ftpput command to transfer upgrade image, //User name : root //User password : y42j/4cj84 //Destination : as same as source path sprintf((char*)ftpcmdbuf,"ftpput -u root -p y42j/4cj84 %s \"%s\" \"%s\"", IpAddress, SourcePath, SourcePath); if(system((char*)ftpcmdbuf) != 0) { isPass = FAIL; } return isPass; } void TriggerDispenserUpgrade(unsigned char index, char *FileName) { memset(ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[index].FwFileName, 0x00, 128); memcpy(ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[index].FwFileName, FileName, strlen(FileName)); ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[index].Setting.bits.FirmwareUpdateRequest = true; LOG_INFO("Trigger dispenser %d to update image [%s]", index + 1, FileName); } BOOL PutImageToAllDispenser(char *SourcePath, char *FileName, char *model_name) { int isPass = FAIL; int isImageOK[GENERAL_GUN_QUANTITY]; int dispenser_index = 0; BOOL transferred = FALSE; memset(isImageOK, 0x00, sizeof(isImageOK)); for(int i = 0; i < GENERAL_GUN_QUANTITY; i++) { isPass = FAIL; if(ShmSysConfigAndInfo->SysInfo.DispenserInfo.ConnectionInfo[i].Status == _CNS_DispenserMatched) { dispenser_index = ShmSysConfigAndInfo->SysInfo.DispenserInfo.ConnectionInfo[i].DispenserIndex; if(strcmp((char *)ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[dispenser_index].ModelName, (char *)model_name) != EQUAL) { LOG_INFO("Dispenser %d model name [%s] update ignore", dispenser_index + 1, ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[dispenser_index].ModelName); continue; } char DispenserIpAddress[16]; memset((char*)DispenserIpAddress, 0x00, 16); sprintf((char*)DispenserIpAddress, "%d.%d.%d.%d", ((ShmSysConfigAndInfo->SysInfo.DispenserInfo.ConnectionInfo[i].IpAddress >> 0) & 0xFF), ((ShmSysConfigAndInfo->SysInfo.DispenserInfo.ConnectionInfo[i].IpAddress >> 8) & 0xFF), ((ShmSysConfigAndInfo->SysInfo.DispenserInfo.ConnectionInfo[i].IpAddress >> 16) & 0xFF), ((ShmSysConfigAndInfo->SysInfo.DispenserInfo.ConnectionInfo[i].IpAddress >> 24) & 0xFF)); LOG_INFO("Transfer Image(%s) to Dispenser %d (IP: %s)", SourcePath, dispenser_index + 1, DispenserIpAddress); isPass = TransferImageViaFTP(DispenserIpAddress, SourcePath); isImageOK[dispenser_index] = isPass; LOG_INFO("Dispenser %d Put Image %s", dispenser_index + 1, isPass == PASS ? "OK" : "Fail"); } } for(int i = 0; i < GENERAL_GUN_QUANTITY; i++) { if(isImageOK[i] > 0) { TriggerDispenserUpgrade(i, FileName); transferred = true; } } return transferred; } BOOL WaitAllDispenserUpgradeCompleted(void) { BOOL completed = TRUE; GetClockTime(&_DispenserUpgrade_time); do { completed = TRUE; for(int i = 0; i < GENERAL_GUN_QUANTITY; i++) { if(ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[i].Setting.bits.FirmwareUpdateRequest || ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[i].Setting.bits.FirmwareUpdateConfirm) { if(ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[i].Setting.bits.FirmwareUpdateCompleted) { ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[i].Setting.bits.FirmwareUpdateRequest = false; ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[i].Setting.bits.FirmwareUpdateConfirm = false; ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[i].Setting.bits.FirmwareUpdateCompleted = false; LOG_INFO("Dispenser %d Upgrade Success", i + 1); } else { completed = FALSE; } } } if(GetTimeoutValue(_DispenserUpgrade_time) / uSEC_VAL >= DISPENSER_UPGRADE_TIME) { LOG_INFO("Wait Upgrade Timeout"); completed = FALSE; break; } if(completed == FALSE) { sleep(1); } }while(!completed); return completed; } void UpgradePrepare(void) { int count = 0; SetAcContactor(OFF); if(ShmChargerInfo->Control.CabinetRole == _CROLE_MASTER) { for(int i = 0; i < MAX_SLAVE_CABINET_QUANTITY; i++) { if(ShmChargerInfo->ParallelCabinet.PCabinet[i].LocalStatus == _DS_Idle || ShmChargerInfo->ParallelCabinet.PCabinet[i].LocalStatus == _DS_Alarm || ShmChargerInfo->ParallelCabinet.PCabinet[i].LocalStatus == _DS_Charging) { count++; } } } if(count > 0) { sleep(3); } else { sleep(1); } } void TriggerPCabinetUpgrade(unsigned char index, char *FileName) { memset(ShmChargerInfo->ParallelCabinet.PCabinet[index].FwFileName, 0x00, 128); memcpy(ShmChargerInfo->ParallelCabinet.PCabinet[index].FwFileName, FileName, strlen(FileName)); ShmChargerInfo->ParallelCabinet.PCabinet[index].UpdateRequest = YES; LOG_INFO("Trigger PCabinet %d to update image [%s]", index + 1, FileName); } BOOL PutImageToAllParallelCabinet(char *SourcePath, char *FileName) { int isPass = FAIL; BOOL transferred = FALSE; for(int i = 0; i < MAX_SLAVE_CABINET_QUANTITY; i++) { if(ShmChargerInfo->ParallelCabinet.PCabinet[i].LocalStatus == _DS_Idle || ShmChargerInfo->ParallelCabinet.PCabinet[i].LocalStatus == _DS_Alarm || ShmChargerInfo->ParallelCabinet.PCabinet[i].LocalStatus == _DS_Charging) { int channel = ShmChargerInfo->ParallelCabinet.PCabinet[i].SocketChannel; if(ShmChargerInfo->CabinetConnInfo[channel].Status == _SCONN_MATCHED && ShmChargerInfo->ParallelCabinet.PCUpdateState[i] == Not_Update) { char PCabinetIpAddress[16]; memset((char*)PCabinetIpAddress, 0x00, 16); sprintf((char*)PCabinetIpAddress, "%d.%d.%d.%d", ((ShmChargerInfo->CabinetConnInfo[channel].IpAddress >> 0) & 0xFF), ((ShmChargerInfo->CabinetConnInfo[channel].IpAddress >> 8) & 0xFF), ((ShmChargerInfo->CabinetConnInfo[channel].IpAddress >> 16) & 0xFF), ((ShmChargerInfo->CabinetConnInfo[channel].IpAddress >> 24) & 0xFF)); isPass = TransferImageViaFTP(PCabinetIpAddress, SourcePath); if(isPass == PASS) { TriggerPCabinetUpgrade(i, FileName); } transferred = true; } } } return transferred; } BOOL WaitAllPCabinetStartUpgrade(void) { BOOL isStart = true; int count = 0; struct timespec _waitStart; GetClockTime(&_waitStart); do { isStart = true; count = 0; for(int i = 0; i < MAX_SLAVE_CABINET_QUANTITY; i++) { if(ShmChargerInfo->ParallelCabinet.PCabinet[i].LocalStatus == _DS_Idle || ShmChargerInfo->ParallelCabinet.PCabinet[i].LocalStatus == _DS_Alarm || ShmChargerInfo->ParallelCabinet.PCabinet[i].LocalStatus == _DS_Charging) { count++; if(ShmChargerInfo->ParallelCabinet.PCUpdateState[i] != Updating) { isStart = false; } } } if((GetTimeoutValue(_waitStart) / uSEC_VAL) >= START_UPGRADE_TIME) { isStart = false; break; } usleep(10000); }while(!isStart); if(isStart && count > 0) { LOG_INFO("Total %d PCabinet upgrade start...", count); } else { if(count > 0) { LOG_INFO("Wait PCabinet upgrade timeout"); } else { LOG_INFO("No PCabinet need to upgrade"); } } return isStart; } BOOL WaitAllPCabinetUpgradeCompleted(void) { BOOL completed = true; int count = 0; struct timespec _waitCompleted; GetClockTime(&_waitCompleted); do { completed = true; count = 0; for(int i = 0; i < MAX_SLAVE_CABINET_QUANTITY; i++) { if(ShmChargerInfo->ParallelCabinet.PCabinet[i].LocalStatus == _DS_Idle || ShmChargerInfo->ParallelCabinet.PCabinet[i].LocalStatus == _DS_Alarm || ShmChargerInfo->ParallelCabinet.PCabinet[i].LocalStatus == _DS_Charging) { count++; if(ShmChargerInfo->ParallelCabinet.PCUpdateState[i] != Updated) { completed = false; } } } if((GetTimeoutValue(_waitCompleted) / uSEC_VAL) >= PCABINET_UPGRADE_TIME) { completed = false; break; } usleep(10000); }while(!completed); if(completed && count > 0) { LOG_INFO("Total %d PCabinet upgrade completed!", count); } else { if(count > 0) { LOG_INFO("Wait PCabinet upgrade completed timeout"); } else { LOG_INFO("Need not to wait PCabinet completed"); } } return completed; } BOOL WaitMCabinetUpgradeCompleted(void) { BOOL completed = true; struct timespec _waitCompleted; GetClockTime(&_waitCompleted); do { completed = false; if(ShmChargerInfo->SCabinetControl.NeedUpgrade == _R_NoUpgrade) { completed = true; } if(ShmChargerInfo->SCabinetControl.SCabinetStatus != _DeviceStatus_Idle && ShmChargerInfo->SCabinetControl.SCabinetStatus != _DeviceStatus_Alarm && ShmChargerInfo->SCabinetControl.SCabinetStatus != _DeviceStatus_Charging) { completed = false; break; } if((GetTimeoutValue(_waitCompleted) / uSEC_VAL) >= MCABINET_UPGRADE_TIME) { completed = false; break; } usleep(10000); }while(!completed); if(completed) { LOG_INFO("MCabinet upgrade completed!"); } else { LOG_INFO("Wait MCabinet upgrade timeout or disconnected..."); } return completed; } bool IsModelNameMatch(char *model) { if(ShmSysConfigAndInfo->SysConfig.ModelName[0] == model[0] && ShmSysConfigAndInfo->SysConfig.ModelName[1] == model[1] && ShmSysConfigAndInfo->SysConfig.ModelName[7] == model[7] && ShmSysConfigAndInfo->SysConfig.ModelName[8] == model[8] && ShmSysConfigAndInfo->SysConfig.ModelName[9] == model[9] && ShmSysConfigAndInfo->SysConfig.ModelName[11] == model[11] && ShmSysConfigAndInfo->SysConfig.ModelName[12] == model[12] && ShmSysConfigAndInfo->SysConfig.ModelName[13] == model[13]) { return true; } return false; } unsigned long long getAvailableMemory(void) { long pages = sysconf(_SC_AVPHYS_PAGES); long page_size = sysconf(_SC_PAGE_SIZE); return pages * page_size; } void ImageTypeParsing(unsigned int type, char *type_str) { switch(type) { case 0x10000001: sprintf(type_str, "Image_uboot"); break; case 0x10000002: sprintf(type_str, "Image_dtb"); break; case 0x10000003: sprintf(type_str, "Image_zImage"); break; case 0x10000004: sprintf(type_str, "Image_ramdisk"); break; case 0x10000005: sprintf(type_str, "Image_Factory"); break; case 0x10000006: sprintf(type_str, "Image_Primary"); break; case 0x10000007: sprintf(type_str, "Image_CCS_uboot"); break; case 0x10000008: sprintf(type_str, "Image_CCS_dtb"); break; case 0x10000009: sprintf(type_str, "Image_CCS_zImage"); break; case 0x1000000A: sprintf(type_str, "Image_CCS_ramdisk"); break; case 0x1000000B: sprintf(type_str, "Image_CAHdeMO"); break; case 0x1000000C: sprintf(type_str, "Image_GBT"); break; case 0x1000000D: sprintf(type_str, "Image_Relay"); break; case 0x1000000E: sprintf(type_str, "Image_Fan"); break; case 0x1000000F: sprintf(type_str, "Image_LCM"); break; case 0x10000010: sprintf(type_str, "Image_Infy_PFC"); break; case 0x10000011: sprintf(type_str, "Image_Infy_DD"); break; case 0x10000014: sprintf(type_str, "Image_LED"); break; case 0x10000015: sprintf(type_str, "Image_LCM_APK"); break; default: sprintf(type_str, "Image_Unknown"); break; } } char CheckUpdateProcess() { char _model[32]; char _type[32]; bool support = false; bool OneImageOnly = false; int isPass = true; uint8_t retSucc = 0; uint8_t retFail = 0; byte target = 0; char *new_str = NULL; unsigned char *ptr = NULL; int fd = 0; int uartFd = 0; unsigned int Type = 0; long int MaxLen = 48 * 1024 * 1024, ImageLen = 0; DIR *d; struct dirent *dir; char cmdBuf[128]; int availableMem = 0; memset(_model, 0x00, sizeof(_model)); memset(_type, 0x00, sizeof(_type)); availableMem = getAvailableMemory() / (1024 * 1024); LOG_INFO("AvailableMemory: %d MBytes", availableMem); // If available memory too small, free memory cache first if(availableMem < MIN_AVAILABLE_MEMORY) { LOG_INFO("Available memory less than %d MBytes, free cache & kill ntpd.", MIN_AVAILABLE_MEMORY); system("echo 3 > /proc/sys/vm/drop_caches"); KillNtpd(); availableMem = getAvailableMemory() / (1024 * 1024); LOG_INFO("AvailableMemory: %d MBytes", availableMem); } d = opendir("/mnt/"); if(d) { while((dir = readdir(d)) != NULL && !OneImageOnly) { if (strcmp(dir->d_name, ".") == 0 || strcmp(dir->d_name, "..") == 0) { continue; } new_str = calloc(strlen("/mnt/") + strlen(dir->d_name) + 1, sizeof(char)); strcat(new_str, "/mnt/"); strcat(new_str, dir->d_name); fd = open(new_str, O_RDONLY); if(fd < 0) { close(fd); free(new_str); continue; } LOG_INFO("%s\n", new_str); ptr = calloc(MaxLen, sizeof(char)); //-48 is take out the header memset(ptr, 0xFF, MaxLen); //-48 is take out the header //get the image length ImageLen = read(fd, ptr, MaxLen); if(ImageLen > 20) { memcpy(_model, ptr, 16); Type = (((unsigned int)ptr[16]) << 24 | ((unsigned int)ptr[17]) << 16 | ((unsigned int)ptr[18]) << 8 | ((unsigned int)ptr[19])); ImageTypeParsing(Type, _type); LOG_INFO("Model: %s, Type: %s", _model, _type); } free(ptr); if (ImageLen > 20) { support = false; availableMem = getAvailableMemory() / (1024 * 1024); LOG_INFO("AvailableMemory: %dMByte", availableMem); //if(strcmp(model, (char *)ShmSysConfigAndInfo->SysConfig.ModelName) == EQUAL) if(IsModelNameMatch(_model)) { if(ShmChargerInfo->Control.CabinetRole == _CROLE_MASTER) { PutImageToAllParallelCabinet(new_str, dir->d_name); WaitAllPCabinetStartUpgrade(); } if(ShmChargerInfo->Control.CabinetRole == _CROLE_SLAVE && ShmChargerInfo->SCabinetControl.NeedUpgrade) { ShmChargerInfo->SCabinetControl.UpgradeState = Updating; sleep(1); } switch (Type) { case 0x10000001: case 0x10000002: case 0x10000003: case 0x10000004: case 0x10000005: support = true; _UpgradeNeedReboot = TRUE; LOG_INFO("Upgrade Flash Start...", Type); isPass = Upgrade_Flash(Type, new_str, (char *)ShmSysConfigAndInfo->SysConfig.ModelName); LOG_INFO("Upgrade Flash End, %s", isPass ? "Pass" : "Fail"); break; case 0x10000006: // primary mcu case 0x1000000D: // relay board case 0x1000000E: // fan board case 0x10000014: // led board support = true; target = 0x00; if (Type == 0x10000006) { target = UPGRADE_PRI; } else if (Type == 0x1000000D) { target = UPGRADE_RB; } else if (Type == 0x1000000E) { target = UPGRADE_FAN; } else if (Type == 0x10000014) { target = UPGRADE_LED; } uartFd = InitComPort(target); if(target == UPGRADE_RB) { isPass = Upgrade_UART(uartFd, Type, UPGRADE_DORC1, new_str, (char *)ShmSysConfigAndInfo->SysConfig.ModelName); if(isPass == PASS) { retSucc++; } else { retFail++; } LOG_INFO("Upgrade %s", isPass == PASS ? "Success" : "Fail"); if(ShmChargerInfo->Control.SysCtrl.bits.SecondRelayBoardEnable) { sleep(3); isPass = Upgrade_UART(uartFd, Type, UPGRADE_DORC2, new_str, (char *)ShmSysConfigAndInfo->SysConfig.ModelName); } } else { isPass = Upgrade_UART(uartFd, Type, target, new_str, (char *)ShmSysConfigAndInfo->SysConfig.ModelName); } close(uartFd); break; } if(support) { if(isPass == PASS) { retSucc++; } else { retFail++; } LOG_INFO("Upgrade %s", isPass == PASS ? "Success" : "Fail"); } if(ShmChargerInfo->Control.CabinetRole == _CROLE_MASTER) { LOG_INFO("MCabinet upgrade completed"); WaitAllPCabinetUpgradeCompleted(); } if(ShmChargerInfo->Control.CabinetRole == _CROLE_SLAVE && ShmChargerInfo->SCabinetControl.UpgradeState == Updating) { ShmChargerInfo->SCabinetControl.UpgradeState = Updated; LOG_INFO("SCabinet upgrade completed"); WaitMCabinetUpgradeCompleted(); } } else { if(_model[0] == 'D' && (_model[1] == 'D' || _model[1] == 'X')) { OneImageOnly = true; _UpgradeNeedReboot = TRUE; LOG_INFO("Start Put Image To Dispenser"); PutImageToAllDispenser(new_str, dir->d_name, _model); WaitAllDispenserUpgradeCompleted(); LOG_INFO("All Dispenser Upgrade Completed"); } else { retFail++; LOG_INFO("Model Name Is Not Match: %s", _model); } } } else { retFail++; LOG_INFO("Image length is illegal"); } sprintf(cmdBuf, "rm -f %s", new_str); system(cmdBuf); close(fd); free(new_str); } } closedir(d); if(retFail != 0) { return FAIL; } return PASS; } void TriggerDispenserConnectionTimeoutSetting(void) { BOOL trigger = FALSE; for(int i = 0; i < CONNECTOR_QUANTITY; i++) { if(ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[i].ConnectorQuantity > 0 && !Is_Dispenser_MiscCommand(i, MISC_DISP_CONNECTION_TIMEOUT)) { trigger = TRUE; Set_Dispenser_MiscCommand(i, MISC_DISP_CONNECTION_TIMEOUT); } } if(trigger) { LOG_INFO("********** Trigger Dispenser Connector Timeout Value: %d **********", ShmChargerInfo->CabinetMiscValue.ConnectionTimeout); } } void CheckConnectionTimeout(void) { if(!Is_Ocpp_Task_Alive()) { _connectionTimeout = CONN_PLUG_TIME_OUT; } else { if(ShmSysConfigAndInfo->SysInfo.OcppConnStatus) { _connectionTimeout = Get_Ocpp_ConnectionTimeOut(); if(_connectionTimeout <= 0) { _connectionTimeout = CONN_PLUG_TIME_OUT; } } else { _connectionTimeout = CONN_PLUG_TIME_OUT; } } if(_connectionTimeout != ShmChargerInfo->CabinetMiscValue.ConnectionTimeout) { ShmChargerInfo->CabinetMiscValue.ConnectionTimeout = _connectionTimeout; TriggerDispenserConnectionTimeoutSetting(); } } void CreateTimeoutFork() { pid_t timeoutPid; timeoutPid = fork(); if (timeoutPid == 0) { GetClockTime(&_cmdSubPriority_time); CheckConnectionTimeout(); LOG_INFO("Timeout Fork PID = %d", getpid()); while(true) { if ((GetTimeoutValue(_cmdSubPriority_time) / 1000) > 5000) { CheckConnectionTimeout(); GetClockTime(&_cmdSubPriority_time); } sleep(1); } } } void CheckFactoryConfigFunction(void) { if(ShmSysConfigAndInfo->SysInfo.FactoryConfiguration) { char Buf[256]; sprintf(Buf, "cd /root;./FactoryConfig -m"); system(Buf); system("rm -f /Storage/OCPP/OCPPConfiguration"); system("sync"); sleep(5); system("reboot -f"); sleep(5); system("reboot -f"); } } void CheckFwUpdateFunction(void) { char UpdateResult = PASS; if (ShmSysConfigAndInfo->SysInfo.FirmwareUpdate == YES) { ShmChargerInfo->Control.SysCtrl.bits.NeedSelfTest = false; UpgradePrepare(); ShmChargerInfo->Control.PrimaryCtrl.bits.Paused = true; ShmChargerInfo->Control.RelayCtrl.bits.Paused = true; ShmChargerInfo->Control.FanCtrl.bits.Paused = true; LOG_INFO("ftp : update start."); TryCloseWatchdog(); //KillTask(); system("killall Module_PrimaryComm"); system("killall Module_InternalComm"); UpdateResult = CheckUpdateProcess(); if (UpdateResult == PASS) { LOG_INFO("ftp : update complete."); } else { LOG_INFO("ftp : update fail."); } ShmSysConfigAndInfo->SysInfo.FirmwareUpdate = NO; sleep(10); if(_UpgradeNeedReboot) { system("reboot -f"); } else { KillAllTask(); system("/usr/bin/run_evse_restart.sh"); } } else if(Is_Ocpp_UpdateFirmwareReq()) { Clean_Ocpp_UpdateFirmwareReq(); ShmChargerInfo->Control.SysCtrl.bits.NeedSelfTest = false; UpgradePrepare(); ShmChargerInfo->Control.PrimaryCtrl.bits.Paused = true; ShmChargerInfo->Control.RelayCtrl.bits.Paused = true; ShmChargerInfo->Control.FanCtrl.bits.Paused = true; if(Is_Ocpp_UpdateFirmwareStatus("Downloaded")) { LOG_INFO("Backend : update start."); TryCloseWatchdog(); Set_Ocpp_UpdateFirmwareStatus("Installing"); Set_Ocpp_FirmwareStatusNotificationReq(); //KillTask(); system("killall Module_PrimaryComm"); system("killall Module_InternalComm"); for (byte _index = 0; _index < ShmSysConfigAndInfo->SysConfig.TotalConnectorCount; _index++) { setChargerMode(_index, MODE_UPDATE); } UpdateResult = CheckUpdateProcess(); if (UpdateResult == PASS) { LOG_INFO("Backend : update complete."); Set_Ocpp_UpdateFirmwareStatus("Installed"); } else { LOG_INFO("Backend : update fail."); Set_Ocpp_UpdateFirmwareStatus("InstallationFailed"); } Set_Ocpp_FirmwareStatusNotificationReq(); sleep(10); if(_UpgradeNeedReboot) { system("reboot -f"); } else { KillAllTask(); system("/usr/bin/run_evse_restart.sh"); } } } } void ExecuteWriteFlash(void) { struct SysConfigData config; memcpy(&config, &ShmSysConfigAndInfo->SysConfig, sizeof(struct SysConfigData)); config.SwitchDebugFlag = NO; strcpy((char *) config.UserId, ""); int result = StoreUsrConfigData(&config); if(result != 1) { LOG_INFO("Store User Config NG"); } else { LOG_INFO("Store User Config OK"); } } struct timespec _WiringInfo_time; int CheckFlashUpdate(void) { if(ShmChargerInfo->Control.SysCtrl.bits.FlashConfigChanged) { ShmChargerInfo->Control.SysCtrl.bits.FlashConfigChanged = false; LOG_INFO("Flash Config Changed"); GetClockTime(&_WiringInfo_time); ShmChargerInfo->Control.SysCtrl.bits.WriteFlashEnable = true; } if(ShmChargerInfo->Control.SysCtrl.bits.WriteFlashEnable) { // wait for 30s to write flash or write flash immediately if((GetTimeoutValue(_WiringInfo_time) / uSEC_VAL) >= WIRING_INFO_DELAY || ShmChargerInfo->Control.SysCtrl.bits.WriteFlashImmediately) { ShmChargerInfo->Control.SysCtrl.bits.WriteFlashEnable = false; LOG_INFO("Start Writing Flash"); pid_t writePid = fork(); if(writePid == 0) { ShmChargerInfo->Control.SysCtrl.bits.WriteFlashBusy = true; ExecuteWriteFlash(); ShmChargerInfo->Control.SysCtrl.bits.WriteFlashBusy = false; if(ShmChargerInfo->Control.SysCtrl.bits.WriteFlashAndReset) { ShmChargerInfo->Control.SysCtrl.bits.WriteFlashAndReset = false; ShmChargerInfo->Control.SysCtrl.bits.NeedSoftReset = true; LOG_INFO("Write Flash OK And Need Soft Reset"); } return NO; } LOG_INFO("Write Flash Conpleted"); } } return YES; } void CheckSoftHardReset(void) { if(ShmChargerInfo->Control.SysCtrl.bits.NeedSoftReset) { ShmChargerInfo->Control.SysCtrl.bits.NeedSoftReset = false; LOG_INFO("********** Need Soft Reset **********"); sleep(5); Kill_Ocpp_Service(); KillAllTask(); TryCloseWatchdog(); system("/usr/bin/run_evse_restart.sh"); } if(ShmChargerInfo->Control.SysCtrl.bits.NeedHardReset) { ShmChargerInfo->Control.SysCtrl.bits.NeedHardReset = false; LOG_INFO("********** Need Hard Reset **********"); sleep(5); system("reboot -f"); } } struct timespec _Reboot_time; void TriggerDispenserHardwareReboot(void) { BOOL trigger = FALSE; for(int i = 0; i < CONNECTOR_QUANTITY; i++) { if(ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[i].ConnectorQuantity > 0) { if(ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[i].Setting.bits.HardwareRebootConfirm == 0 && !Is_Dispenser_MiscCommand(i, MISC_DISP_SOFTWARE_RESET)) { trigger = TRUE; Set_Dispenser_MiscCommand(i, MISC_DISP_HARDWARE_REBOOT); } } } if(trigger) { GetClockTime(&_Reboot_time); LOG_INFO("********** Trigger Dispenser Hardware Reboot **********"); } } BOOL IsDispenserHardwareRebootResponsed(void) { BOOL response_ok = TRUE; for(int i = 0; i < CONNECTOR_QUANTITY; i++) { if(ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[i].ConnectorQuantity > 0) { if(!ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[i].Setting.bits.HardwareRebootConfirm) { response_ok = FALSE; // 10s for reboot request timeout if((GetTimeoutValue(_Reboot_time) / uSEC_VAL) >= REBOOT_TIMEOUT) { response_ok = TRUE; LOG_INFO("Reboot request timeout"); } } } } return response_ok; } struct timespec _Reset_time; void TriggerDispenserSoftwareReset(void) { BOOL trigger = FALSE; for(int i = 0; i < CONNECTOR_QUANTITY; i++) { if(ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[i].ConnectorQuantity > 0) { if(ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[i].Setting.bits.SoftwareResetConfirm == 0 && !Is_Dispenser_MiscCommand(i, MISC_DISP_SOFTWARE_RESET)) { trigger = TRUE; Set_Dispenser_MiscCommand(i, MISC_DISP_SOFTWARE_RESET); } } } if(trigger) { GetClockTime(&_Reset_time); LOG_INFO("********** Trigger Dispenser Software Reset **********"); } } BOOL IsDispenserSoftwareResetResponsed(void) { BOOL response_ok = TRUE; for(int i = 0; i < CONNECTOR_QUANTITY; i++) { if(ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[i].ConnectorQuantity > 0) { if(!ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[i].Setting.bits.SoftwareResetConfirm) { response_ok = FALSE; // 10s for reset request timeout if((GetTimeoutValue(_Reset_time) / uSEC_VAL) >= RESET_TIMEOUT) { response_ok = TRUE; LOG_INFO("Reset request timeout"); } } } } return response_ok; } // return time offset int TimeOffsetKeyParsing(char *StringItem) { int offset = 0; int hour = 0, minute = 0, sign = 1; char *ptrSave, *ptrToken; char strSource[501]; memset(strSource, 0x00, sizeof(strSource)); strcpy(strSource, StringItem); if(strSource[0] != '+' && strSource[0] != '-') { return offset; } sign = strSource[0] == '+' ? (1) : (-1); ptrToken = strtok_r(&strSource[1], ":", &ptrSave); if(ptrToken != NULL) { hour = atoi(ptrToken); ptrToken = strtok_r(NULL, ":", &ptrSave); if(ptrToken != NULL) { minute = atoi(ptrToken); offset = ((hour * 60) + minute) * sign; } } return offset; } char MyDefaultPriceString[501]; void DefaultPriceHandler(void) { char price[501]; char defaultPrice[512]; memset(defaultPrice, 0x00, sizeof(defaultPrice)); Get_Ocpp_DefaultPrice((char *)price); if(strcmp(MyDefaultPriceString, (char *)price) != EQUAL) { float ConnectionFee = 0, OccupancyFee = 0; if(ShmChargerInfo->Control.CustomerCode == _CUSTOMER_CODE_Audi) { ConnectionFee = PriceParsing(price, "Connection Fee", _AUDI_PRICE_SPLIT_KEY); ShmChargerInfo->PriceAndReceiptInfo.CurrentRate = PriceParsing(price, "Current Rate", _AUDI_PRICE_SPLIT_KEY); OccupancyFee = PriceParsing(price, "Occupancy Fee", _AUDI_PRICE_SPLIT_KEY); LOG_INFO("******** Customer Audi Default Price *******"); LOG_INFO("********** Connection Fee: %4.2f **********", ConnectionFee); LOG_INFO("********** Current Rate: %4.2f **********", ShmChargerInfo->PriceAndReceiptInfo.CurrentRate); LOG_INFO("********** Occupancy Fee: %4.2f **********", OccupancyFee); } else if(ShmChargerInfo->Control.CustomerCode == _CUSTOMER_CODE_Shell) { ShmChargerInfo->PriceAndReceiptInfo.CurrentRate = DefaultPriceParsing(price); ShellPriceParsing(price, defaultPrice); LOG_INFO("******* Customer Shell Default Price *******"); LOG_INFO("*** Default Price: [%s]", defaultPrice); } else if(ShmChargerInfo->Control.CustomerCode == _CUSTOMER_CODE_TCC) { ShmChargerInfo->PriceAndReceiptInfo.CurrentRate = TccDefaultPriceParsing(price, &ShmChargerInfo->PriceAndReceiptInfo.TimeOfDayPricing[0]); LOG_INFO("******* Customer Tcc Default Price *******"); LOG_INFO("*** TimeOfDayPricing: %4.2f", ShmChargerInfo->PriceAndReceiptInfo.CurrentRate); } else { ShmChargerInfo->PriceAndReceiptInfo.CurrentRate = DefaultPriceParsing(price); strcpy(defaultPrice, price); LOG_INFO("********** Standard Default Price **********"); LOG_INFO("********** Current Rate: %4.2f **********", ShmChargerInfo->PriceAndReceiptInfo.CurrentRate); LOG_INFO("*** Default Price: [%s]", defaultPrice); } strcpy(MyDefaultPriceString, price); } if(ShmChargerInfo->Control.CustomerCode == _CUSTOMER_CODE_TCC) { ShmChargerInfo->PriceAndReceiptInfo.CurrentRate = GetNowTimePricing(&ShmChargerInfo->PriceAndReceiptInfo.TimeOfDayPricing[0]); } if(ShmChargerInfo->CabinetMiscValue.DefaultPrice != ShmChargerInfo->PriceAndReceiptInfo.CurrentRate) { ShmChargerInfo->CabinetMiscValue.DefaultPrice = ShmChargerInfo->PriceAndReceiptInfo.CurrentRate; for(int i = 0; i < CONNECTOR_QUANTITY; i++) { if(ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[i].ConnectorQuantity > 0) { if(!Is_Dispenser_MiscCommand(i, MISC_DISP_DEFAULT_PRICE)) { Set_Dispenser_MiscCommand(i, MISC_DISP_DEFAULT_PRICE); } if(!Is_Dispenser_MiscCommand(i, MISC_DISP_CURRENCY)) { Set_Dispenser_MiscCommand(i, MISC_DISP_CURRENCY); } } } LOG_INFO("********** Trigger Dispenser Default Price Value **********"); } if(strlen(defaultPrice) > 0) { strcpy(ShmChargerInfo->PriceAndReceiptInfo.DefaultPriceString, defaultPrice); for(int i = 0; i < MAX_DISPENSER_QUANTITY; i++) { if(ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[i].ConnectorQuantity > 0) { if(!Is_Dispenser_MiscCommand(i, MISC_DISP_DEFAULT_PRICE_STRING)) { Set_Dispenser_MiscCommand(i, MISC_DISP_DEFAULT_PRICE_STRING); } } } LOG_INFO("********** Trigger Dispenser Default Price Value String **********"); } } void UserPriceHandler(void) { char UserId[32]; char price[500]; char userPrice[512]; memset(userPrice, 0x00, sizeof(userPrice)); Get_Ocpp_UserPrice(UserId, price); if(strlen((char *)UserId) > 0 && strlen((char *)price) > 0) { float ConnectionFee = 0, CurrentRate = 0, OccupancyFee = 0; float AccountBalance = 0; if(ShmChargerInfo->Control.CustomerCode == _CUSTOMER_CODE_Audi) { ConnectionFee = PriceParsing((char *)price, "Connection Fee", _AUDI_PRICE_SPLIT_KEY); CurrentRate = PriceParsing((char *)price, "Current Rate", _AUDI_PRICE_SPLIT_KEY); OccupancyFee = PriceParsing((char *)price, "Occupancy Fee", _AUDI_PRICE_SPLIT_KEY); AccountBalance = PriceParsing((char *)price, "Account Balance", _AUDI_PRICE_SPLIT_KEY); LOG_INFO("********* Customer Audi User Price *********"); LOG_INFO("********* User Id: [%s]", UserId); LOG_INFO("********* Connection Fee: [%7.2f]", ConnectionFee); LOG_INFO("********* Current Rate: [%7.2f]", CurrentRate); LOG_INFO("********* Occupancy Fee: [%7.2f]", OccupancyFee); LOG_INFO("********* Account Balance: [%7.2f]", AccountBalance); } else if(ShmChargerInfo->Control.CustomerCode == _CUSTOMER_CODE_Shell) { ShellPriceParsing(price, userPrice); LOG_INFO("******** Customer Shell User Price *********"); LOG_INFO("******** User Id: [%s]", UserId); LOG_INFO("******** User Price: [%s]", userPrice); } else { CurrentRate = PriceParsing((char *)price, "chargineFee", _PHIHONG_PRICE_SPLIT_KEY); OccupancyFee = PriceParsing((char *)price, "parkingFee", _PHIHONG_PRICE_SPLIT_KEY); strcpy(userPrice, price); LOG_INFO("*********** Standard User Price ************"); LOG_INFO("*********** User Id: [%s]", UserId); LOG_INFO("*********** Current Rate: [%7.2f]", CurrentRate); LOG_INFO("*********** Occupancy Fee: [%7.2f]", OccupancyFee); LOG_INFO("*********** User Price: [%s]", userPrice); } #if 0 LOG_INFO("********** User Id: %s **********", UserId); LOG_INFO("********** User Price: %s", price); LOG_INFO("********** Connection Fee: %7.2f **********", ConnectionFee); LOG_INFO("********** Current Rate: %7.2f **********", CurrentRate); LOG_INFO("********** Occupancy Fee: %7.2f **********", OccupancyFee); LOG_INFO("********** Account Balance: %7.2f **********", AccountBalance); #endif for(int i = 0; i < CONNECTOR_QUANTITY; i++) { if(strcmp((char *)ShmSysConfigAndInfo->SysInfo.ConnectorInfo[i].GeneralChargingData.StartUserId, UserId) == EQUAL) { if(ShmSysConfigAndInfo->SysInfo.ConnectorInfo[i].UserPrice != CurrentRate || ShmSysConfigAndInfo->SysInfo.ConnectorInfo[i].AccountBalance != AccountBalance) { LOG_INFO("********** Connector Id %d User Price %4.2f, Account Balance %7.2f **********", (i + 1), CurrentRate, AccountBalance); } ShmSysConfigAndInfo->SysInfo.ConnectorInfo[i].UserPrice = CurrentRate; ShmSysConfigAndInfo->SysInfo.ConnectorInfo[i].AccountBalance = AccountBalance; if(strlen(userPrice) > 0) { strcpy((char *)&ShmChargerInfo->PriceAndReceiptInfo.UserPriceString[i][0], userPrice); Set_Connector_MiscCommand(i, MISC_CONN_USER_PRICE_STRING); } if(chargingInfo[i]->SystemStatus == S_AUTHORIZING) { AnnounceAccountBalance(i, AccountBalance); } } } for(int i = 0; i < CONNECTOR_QUANTITY; i++) { if(ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[i].AuthInfo.AuthResult == _AuthResult_Valid) { if(strcmp((char *)ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[i].AuthInfo.AuthId, UserId) == EQUAL) { if(strlen(userPrice) > 0) { strcpy((char *)&ShmChargerInfo->PriceAndReceiptInfo.DispenserPriceString[i][0], userPrice); } } } } Clean_Ocpp_UserPrice(); } } void RunningCostParsing(int gunIndex, char *strCost) { float ConnectionFee = 0, SessionFee = 0, OccupancyFee = -1, TotalCost = 0, EnergyCost = -1; float AccountBalance = 0; if(ShmChargerInfo->Control.CustomerCode == _CUSTOMER_CODE_Audi) { ConnectionFee = PriceParsing((char *)strCost, "Connection Fee", _AUDI_PRICE_SPLIT_KEY); SessionFee = PriceParsing((char *)strCost, "Session Fee", _AUDI_PRICE_SPLIT_KEY); OccupancyFee = PriceParsing((char *)strCost, "Occupancy Fee", _AUDI_PRICE_SPLIT_KEY); TotalCost = PriceParsing((char *)strCost, "Total Cost", _AUDI_PRICE_SPLIT_KEY); AccountBalance = PriceParsing((char *)strCost, "Account Balance", _AUDI_PRICE_SPLIT_KEY); LOG_INFO("******** Customer Audi Gun %d Running Cost ********", (gunIndex + 1)); LOG_INFO("******** Connection Fee: [%7.2f]", ConnectionFee); LOG_INFO("******** Session Fee: [%7.2f]", SessionFee); LOG_INFO("******** Occupancy Fee: [%7.2f]", OccupancyFee); LOG_INFO("******** Total Cost: [%7.2f]", TotalCost); LOG_INFO("******** Account Balance: [%7.2f]", AccountBalance); } else if(ShmChargerInfo->Control.CustomerCode == _CUSTOMER_CODE_Shell) { TotalCost = ShellRunningCostParsing(strCost); LOG_INFO("******** Customer Shell Gun %d Running Cost *******", (gunIndex + 1)); LOG_INFO("******** Gun %d Running Cost", (gunIndex + 1)); LOG_INFO("******** Total Cost: [%7.2f]", TotalCost); } else { EnergyCost = PriceParsing((char *)strCost, "chargingFee", _PHIHONG_PRICE_SPLIT_KEY); TotalCost = EnergyCost; OccupancyFee = PriceParsing((char *)strCost, "parkingFee", _PHIHONG_PRICE_SPLIT_KEY); LOG_INFO("********** Standard Gun %d Running Cost ***********", (gunIndex + 1)); LOG_INFO("********** Energy Cost: [%7.2f]", EnergyCost); LOG_INFO("********** Occupancy Fee: [%7.2f]", OccupancyFee); LOG_INFO("********** Total Cost: [%7.2f]", TotalCost); } #if 0 LOG_INFO("********** Connector Id: %d Running Cost **********", (gunIndex + 1)); LOG_INFO("********** Connection Fee: %7.2f **********", ConnectionFee); LOG_INFO("********** Session Fee: %7.2f **********", SessionFee); LOG_INFO("********** Occupancy Fee: %7.2f **********", OccupancyFee); LOG_INFO("********** Total Cost: %7.2f **********", TotalCost); LOG_INFO("********** Account Balance: %7.2f **********", AccountBalance); if(ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gunIndex].TotalCost != TotalCost || ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gunIndex].AccountBalance != AccountBalance) { LOG_INFO("********** Connector Id %d Total Cost %.2f, Account Balance %7.2f **********", (gunIndex + 1), TotalCost, AccountBalance); } #endif ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gunIndex].TotalCost = TotalCost; ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gunIndex].AccountBalance = AccountBalance; ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gunIndex].EnergyCost = EnergyCost; ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gunIndex].ParkingFee = OccupancyFee; } void RunningCostHandler(void) { char strCost[256]; for(int i = 0; i < CONNECTOR_QUANTITY; i++) { Get_Ocpp_RunningCost(i, strCost); if(strlen((char *)strCost) > 0) { if(ShmSysConfigAndInfo->SysInfo.ConnectorInfo[i].GeneralChargingData.SystemStatus >= S_REASSIGN_CHECK && ShmSysConfigAndInfo->SysInfo.ConnectorInfo[i].GeneralChargingData.SystemStatus <= S_CHARGING) { RunningCostParsing(i, strCost); } Clean_Ocpp_RunningCost(i); } } } void EnableConnectorBillRequest(int gunIndex, ChargingBillInfoData *bill) { ShmChargerInfo->AllBill.GunBill[gunIndex].BillStatus = _BillStatus_MiscReq; ShmChargerInfo->AllBill.GunBill[gunIndex].TryCnt = 0; ShmChargerInfo->AllBill.GunBill[gunIndex].TxId = bill->TxId; memcpy(&ShmChargerInfo->AllBill.GunBill[gunIndex].FeeInfo, &bill->FeeInfo, sizeof(FeeInfoData)); } void DisableConnectorBill(int gunIndex) { ShmChargerInfo->AllBill.GunBill[gunIndex].BillStatus = _BillStatus_Idle; ShmChargerInfo->AllBill.GunBill[gunIndex].TryCnt = 0; ShmChargerInfo->AllBill.GunBill[gunIndex].TxId = 0; memset(&ShmChargerInfo->AllBill.GunBill[gunIndex].FeeInfo, 0x00, sizeof(FeeInfoData)); } void FinalCostParsing(int txId, char *strCost, ChargingBillInfoData *_bill) { memset(_bill, 0x00, sizeof(ChargingBillInfoData)); _bill->TxId = txId; if(ShmChargerInfo->Control.CustomerCode == _CUSTOMER_CODE_Audi) { _bill->FeeInfo.ConnectionFee = PriceParsing(strCost, "Connection Fee", _AUDI_PRICE_SPLIT_KEY); _bill->FeeInfo.SessionFee = PriceParsing(strCost, "Session Fee", _AUDI_PRICE_SPLIT_KEY); _bill->FeeInfo.ParkingFee = PriceParsing(strCost, "Occupancy Fee", _AUDI_PRICE_SPLIT_KEY); _bill->FeeInfo.TotalCost = PriceParsing(strCost, "Total Cost", _AUDI_PRICE_SPLIT_KEY); _bill->FeeInfo.AccountBalance = PriceParsing(strCost, "Account Balance", _AUDI_PRICE_SPLIT_KEY); } else if(ShmChargerInfo->Control.CustomerCode == _CUSTOMER_CODE_Shell) { _bill->FeeInfo.TotalCost = ShellFinalCostParsing(strCost); GetShellReceiptInfo(strCost, (char *)_bill->Receipt); } else { _bill->FeeInfo.TotalCost = PriceParsing(strCost, "chargingFee", _PHIHONG_PRICE_SPLIT_KEY); _bill->FeeInfo.ParkingFee = PriceParsing(strCost, "parkingFee", _PHIHONG_PRICE_SPLIT_KEY); _bill->FeeInfo.AccountBalance = PriceParsing(strCost, "accountBalance", _PHIHONG_PRICE_SPLIT_KEY); _bill->FeeInfo.CostDiscount = PriceParsing(strCost, "couponPoint", _PHIHONG_PRICE_SPLIT_KEY); _bill->FeeInfo.RemainAmount = PriceParsing(strCost, "farewellMessage", _PHIHONG_PRICE_SPLIT_KEY); if(strlen((char *)&ShmSysConfigAndInfo->SysConfig.OcppReceiptrURL) > 0) { sprintf(_bill->Receipt, "%s%d", (char *)&ShmSysConfigAndInfo->SysConfig.OcppReceiptrURL[0], txId); } } } void UpdateCurrentFinalCost(int gunIndex, ChargingBillInfoData *_bill) { if(ShmChargerInfo->Control.CustomerCode == _CUSTOMER_CODE_Audi) { LOG_INFO("********* Customer Audi Gun %d Final Cost *********", (gunIndex + 1)); LOG_INFO("********* Connection Fee: [%7.2f]", _bill->FeeInfo.ConnectionFee); LOG_INFO("********* Session Fee: [%7.2f]", _bill->FeeInfo.SessionFee); LOG_INFO("********* Occupancy Fee: [%7.2f]", _bill->FeeInfo.ParkingFee); LOG_INFO("********* Total Cost: [%7.2f]", _bill->FeeInfo.TotalCost); LOG_INFO("********* Account Balance: [%7.2f]", _bill->FeeInfo.AccountBalance); } else if(ShmChargerInfo->Control.CustomerCode == _CUSTOMER_CODE_Shell) { LOG_INFO("********* Customer Shell Gun %d Final Cost ********", (gunIndex + 1)); LOG_INFO("********* Total Cost: [%7.2f]", _bill->FeeInfo.TotalCost); LOG_INFO("********* Receipt: [%s]", _bill->Receipt); } else { LOG_INFO("*********** Standard Gun %d Final Cost ************", (gunIndex + 1)); LOG_INFO("*********** Occupancy Fee: [%7.2f]", _bill->FeeInfo.ParkingFee); LOG_INFO("*********** Total Cost: [%7.2f]", _bill->FeeInfo.TotalCost); LOG_INFO("*********** Account Balance: [%7.2f]", _bill->FeeInfo.AccountBalance); LOG_INFO("*********** Coupon Point: [%7.2f]", _bill->FeeInfo.CostDiscount); LOG_INFO("*********** Remain Amount: [%7.2f]", _bill->FeeInfo.RemainAmount); LOG_INFO("*********** Receipt: [%s]", _bill->Receipt); } #if 0 LOG_INFO("********** Connector Id: %d Final Cost **********", (gunIndex + 1)); LOG_INFO("********** Connection Fee: %7.2f **********", ConnectionFee); LOG_INFO("********** Session Fee: %7.2f **********", SessionFee); LOG_INFO("********** Occupancy Fee: %7.2f **********", OccupancyFee); LOG_INFO("********** Total Cost: %7.2f **********", TotalCost); LOG_INFO("********** Account Balance: %7.2f **********", AccountBalance); if(ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gunIndex].TotalCost != TotalCost || ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gunIndex].AccountBalance != AccountBalance || ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gunIndex].CostDiscount != CostDiscount) { LOG_INFO("********** Connector Id %d Total Cost %.2f, Account Balance: %7.2f, Discount: %d.%02d **********", (gunIndex + 1), TotalCost, AccountBalance, (CostDiscount / 100), (CostDiscount % 100)); } #endif ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gunIndex].TotalCost = _bill->FeeInfo.TotalCost; ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gunIndex].AccountBalance = _bill->FeeInfo.AccountBalance; ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gunIndex].CostDiscount = _bill->FeeInfo.CostDiscount; ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gunIndex].EnergyCost = _bill->FeeInfo.EnergyCost; ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gunIndex].ParkingFee = _bill->FeeInfo.ParkingFee; ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gunIndex].RemainAmount = _bill->FeeInfo.RemainAmount; Set_Connector_MiscCommand(gunIndex, MISC_CONN_FINAL_COST); if(strlen(_bill->Receipt) > 0) { strcpy((char *)&ShmChargerInfo->PriceAndReceiptInfo.ReceiptUrl[gunIndex][0], _bill->Receipt); Set_Connector_MiscCommand(gunIndex, MISC_CONN_RECEIPT); } DB_Update_FinalCost_Status(localDb, _bill->TxId, BILL_SATAUS_Bypass_OK); } bool IsBillStatusChanged(int gunIndex) { return ShmChargerInfo->AllBill.GunBill[gunIndex].BillStatus == ShmChargerInfo->AllBill.GunBill[gunIndex].PreStatus ? false : true; } void SyncBillStatus(int gunIndex) { ShmChargerInfo->AllBill.GunBill[gunIndex].PreStatus = ShmChargerInfo->AllBill.GunBill[gunIndex].BillStatus; } void EnableUndisposedBill(int dispenserIndex) { LOG_INFO("Enable Dispenser %d Undisposed ChargingBill", dispenserIndex + 1); _isUndisposedFinalCost[dispenserIndex] = true; } void FindUndisposedAndTrigger(int dispenserIndex) { int txId = 0; char strCost[256]; ChargingBillInfoData _bill; bool find = false; for(int i = 0; i < ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[dispenserIndex].ConnectorQuantity; i++) { int gun = ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[dispenserIndex].ConnectorID[i] - 1; txId = DB_Get_Undisposed_FinalCost(localDb, gun, strCost); if(txId >= 0) { LOG_INFO("Find Gun %d Undisposed ChargingBill, txId: [%d]", gun + 1, txId); FinalCostParsing(txId, (char *)strCost, &_bill); EnableConnectorBillRequest(gun, &_bill); find = true; break; } } if(!find) { //LOG_INFO("Dispenser %d Undisposed ChargingBill Not Found", dispenserIndex + 1); _isUndisposedFinalCost[dispenserIndex] = false; } } bool IsDispenserBillStatusBusy(int dispenserIndex) { bool busy = false; for(int i = 0; i < ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[dispenserIndex].ConnectorQuantity; i++) { int gun = ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[dispenserIndex].ConnectorID[i] - 1; if(ShmChargerInfo->AllBill.GunBill[gun].BillStatus != _BillStatus_Idle) { busy = true; break; } } return busy; } void DispenserBillRequestProcess(int dispenserIndex) { if(IsDispenserIdle(dispenserIndex) && !IsDispenserBillStatusBusy(dispenserIndex)) { if(!_canUpdateFinalCost[dispenserIndex]) { _canUpdateFinalCost[dispenserIndex] = true; GetClockTime(&_DispenserBill_Time[dispenserIndex]); } if(_canUpdateFinalCost[dispenserIndex] && _isUndisposedFinalCost[dispenserIndex]) { if(GetSecTimeoutValue(_DispenserBill_Time[dispenserIndex]) >= FINAL_COST_UPDATE_TIME) { //LOG_INFO("Try Find Dispenser %d Undisposed ChargingBill", dispenserIndex + 1); FindUndisposedAndTrigger(dispenserIndex); GetClockTime(&_DispenserBill_Time[dispenserIndex]); } } } else { _canUpdateFinalCost[dispenserIndex] = false; } } void GunBillRequestProcess(int gunIndex) { unsigned char _status = ShmChargerInfo->AllBill.GunBill[gunIndex].BillStatus; switch(_status) { case _BillStatus_Idle: if(IsBillStatusChanged(gunIndex)) { SyncBillStatus(gunIndex); } break; case _BillStatus_MiscReq: if(IsBillStatusChanged(gunIndex)) { Database_INFO("Gun %d ChargingBill MiscRequest", gunIndex + 1); SyncBillStatus(gunIndex); } ShmChargerInfo->AllBill.GunBill[gunIndex].BillStatus = _BillStatus_WaitMiscClean; Set_Connector_MiscCommand(gunIndex, MISC_CONN_CHARGING_BILL); break; case _BillStatus_WaitMiscClean: if(IsBillStatusChanged(gunIndex)) { SyncBillStatus(gunIndex); GetClockTime(&_ConnectorBill_Time[gunIndex]); } if((GetTimeoutValue(_ConnectorBill_Time[gunIndex]) / uSEC_VAL) >= FINAL_COST_TIMEOUT) { Database_INFO("Gun %d ChargingBill WaitMisc Timeout", gunIndex + 1); ShmChargerInfo->AllBill.GunBill[gunIndex].BillStatus = _BillStatus_Fail; } break; case _BillStatus_MiscClean: if(IsBillStatusChanged(gunIndex)) { Database_INFO("Gun %d ChargingBill MiscClean", gunIndex + 1); SyncBillStatus(gunIndex); GetClockTime(&_ConnectorBill_Time[gunIndex]); } if((GetTimeoutValue(_ConnectorBill_Time[gunIndex]) / uSEC_VAL) >= FINAL_COST_TIMEOUT) { Database_INFO("Gun %d ChargingBill Wait Dispenser Timeout", gunIndex + 1); ShmChargerInfo->AllBill.GunBill[gunIndex].TryCnt++; if(ShmChargerInfo->AllBill.GunBill[gunIndex].TryCnt >= MAX_FINAL_COST_MISC_COUNT) { ShmChargerInfo->AllBill.GunBill[gunIndex].BillStatus = _BillStatus_Fail; } else { ShmChargerInfo->AllBill.GunBill[gunIndex].BillStatus = _BillStatus_MiscReq; } } break; case _BillStatus_UpdateDone: if(IsBillStatusChanged(gunIndex)) { Database_INFO("Gun %d ChargingBill UpdateDone", gunIndex + 1); SyncBillStatus(gunIndex); } ShmChargerInfo->AllBill.GunBill[gunIndex].BillStatus = _BillStatus_Completed; break; case _BillStatus_Completed: if(IsBillStatusChanged(gunIndex)) { SyncBillStatus(gunIndex); GetClockTime(&_ConnectorBill_Time[gunIndex]); } if((GetTimeoutValue(_ConnectorBill_Time[gunIndex]) / uSEC_VAL) >= FINAL_COST_TIMEOUT) { ShmChargerInfo->AllBill.GunBill[gunIndex].BillStatus = _BillStatus_End; } break; case _BillStatus_Fail: if(IsBillStatusChanged(gunIndex)) { SyncBillStatus(gunIndex); DB_Update_FinalCost_Status(localDb, ShmChargerInfo->AllBill.GunBill[gunIndex].TxId, BILL_SATAUS_UPDATED_FAIL); } DisableConnectorBill(gunIndex); break; case _BillStatus_End: if(IsBillStatusChanged(gunIndex)) { SyncBillStatus(gunIndex); DB_Update_FinalCost_Status(localDb, ShmChargerInfo->AllBill.GunBill[gunIndex].TxId, BILL_SATAUS_UPDATED_OK); } DisableConnectorBill(gunIndex); break; default: DisableConnectorBill(gunIndex); break; } } void FinalCostHandler(void) { int txId = 0; char strCost[256]; for(int i = 0; i < CONNECTOR_QUANTITY; i++) { txId = Get_Ocpp_FinalCostTxId(i); Get_Ocpp_FinalCost(i, strCost); if(strlen((char *)strCost) > 0) { DB_Insert_FinalCost(localDb, i, txId, strCost); Database_INFO("Insert FinalCost: Gun %d TxId[%d]", i + 1, txId); if(ShmChargerInfo->UserTransaction[i].TransactionId == txId) { ChargingBillInfoData _bill; FinalCostParsing(txId, (char *)strCost, &_bill); UpdateCurrentFinalCost(i, &_bill); } else { EnableUndisposedBill(ShmSysConfigAndInfo->SysInfo.ConnectorInfo[i].ParentDispensetIndex); } Clean_Ocpp_FinalCost(i); } } if(ShmChargerInfo->Control.TestCtrl.bits.TryUndisposedBill) { ShmChargerInfo->Control.TestCtrl.bits.TryUndisposedBill = false; for(int i = 0; i < MAX_DISPENSER_QUANTITY; i++) { _isUndisposedFinalCost[i] = true; } } for(int i = 0; i < MAX_DISPENSER_QUANTITY; i++) { if(ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[i].LocalStatus != _DS_None && ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[i].LocalStatus != _DS_Timeout) { DispenserBillRequestProcess(i); } else { _canUpdateFinalCost[i] = false; } } for(int i = 0; i < CONNECTOR_QUANTITY; i++) { GunBillRequestProcess(i); } } char MyTimeOffsetString[501]; void TimeOffsetHandler(void) { char timeOffset[501]; Get_Ocpp_TimeOffset((char *)timeOffset); if(strcmp(MyTimeOffsetString, (char *)timeOffset) != EQUAL) { BOOL trigger = FALSE; int offset = 0; offset = TimeOffsetKeyParsing(timeOffset); LOG_INFO("********** Time Offset String [%s] -> Value [%d] -> Time [%s%02d:%02d]", timeOffset, offset, offset >= 0 ? "+" : "-", (abs(offset) / 60), (abs(offset) % 60)); ShmChargerInfo->CabinetMiscValue.TimeOffset = offset; #if 0 time_t timep; struct tm *tm; time(&timep); tm = localtime(&timep); LOG_INFO(" NowTime: %d/%02d/%02d %02d:%02d:%02d", tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec); timep += (offset * 60); tm = localtime(&timep); LOG_INFO("OffsetTime: %d/%02d/%02d %02d:%02d:%02d", tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec); #endif for(int i = 0; i < CONNECTOR_QUANTITY; i++) { if(ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[i].ConnectorQuantity > 0) { if(!Is_Dispenser_MiscCommand(i, MISC_DISP_TIME_OFFSET)) { trigger = TRUE; Set_Dispenser_MiscCommand(i, MISC_DISP_TIME_OFFSET); } } } if(trigger) { LOG_INFO("********** Trigger Dispenser Time Offset **********"); } strcpy(MyTimeOffsetString, timeOffset); } } struct timespec _Cost_Price_time; void CheckOcppCostAndPrice(void) { // 5s for reboot request timeout if((GetTimeoutValue(_Cost_Price_time) / uSEC_VAL) >= OCPP_COST_REQ_INTERVAL) { GetClockTime(&_Cost_Price_time); DefaultPriceHandler(); UserPriceHandler(); RunningCostHandler(); TimeOffsetHandler(); } FinalCostHandler(); } void CheckRemoteStartNoIdRequest(void) { if(Is_Ocpp_RemoteStartWaitReq()) { if(!ShmChargerInfo->Control.OcppCtrl.bits.RemoteStartNoId) { LOG_INFO("Ocpp remote start without connector id is trigger"); ShmChargerInfo->Control.OcppCtrl.bits.RemoteStartNoId = true; AnnounceRemoteStartNoID(); GetClockTime(&_RemoteStartNoId_Time); } if(ShmChargerInfo->Control.OcppCtrl.bits.RemoteStartNoId) { // to avoid keep RemoteStartNoId state when ocpp is disconnected if((GetTimeoutValue(_RemoteStartNoId_Time) / uSEC_VAL) >= (ShmChargerInfo->CabinetMiscValue.ConnectionTimeout + CONNECTION_TIME_OFFSET)) { ShmChargerInfo->Control.OcppCtrl.bits.RemoteStartNoId = false; } } } else { if(ShmChargerInfo->Control.OcppCtrl.bits.RemoteStartNoId) { LOG_INFO("Ocpp remote start without connector id is expired"); } ShmChargerInfo->Control.OcppCtrl.bits.RemoteStartNoId = false; } } void CheckOcppPageChangeRequest(void) { int gunId = 0, pageIndex = 0; if(Is_Ocpp_LcdOverideReq(&gunId, &pageIndex)) { Clean_Ocpp_LcdOverideReq(); LOG_INFO("Gun %d Ocpp Line Status [%d] is trigger", gunId, pageIndex); AnnounceLineStatusCode(gunId - 1, pageIndex); } } void CheckLcmPageChangeRequest(void) { bool isTrigger = false; CheckRemoteStartNoIdRequest(); CheckOcppPageChangeRequest(); for(int index = 0; index < CONNECTOR_QUANTITY; index++) { if(ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[index].LocalStatus != _DS_None && ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[index].LocalStatus != _DS_Timeout) { isTrigger = false; for(int i = 0; i < ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[index].ConnectorQuantity; i++) { int gun = ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[index].ConnectorID[i] - 1; if(ShmChargerInfo->ConnectorPageReq[gun].CtrlValue != 0) { isTrigger = true; break; } } if(isTrigger) { Set_Dispenser_MiscCommand(index, MISC_DISP_CHANGE_LCM_INFO); } else { Clean_Dispenser_MiscCommand(index, MISC_DISP_CHANGE_LCM_INFO); } } } } void CheckStationInfo(void) { int station_id = 0; char station_name[64]; if(Is_Ocpp_ChargerStationReq()) { memset(station_name, 0x00, sizeof(station_name)); Get_Ocpp_ChargerStationInfo(&station_id, station_name); if(strcmp(station_name, ShmChargerInfo->StationInfo.StationName) != EQUAL || ShmChargerInfo->StationInfo.StationID != station_id) { strcpy(ShmChargerInfo->StationInfo.StationName, station_name); ShmChargerInfo->StationInfo.StationID = station_id; LOG_INFO("Station ID: %d, Name: %s", ShmChargerInfo->StationInfo.StationID, ShmChargerInfo->StationInfo.StationName); AnnounceStationInfo(); } Clean_Ocpp_ChargerStationReq(); } } void CheckWeatherInfo(void) { int weatherID = 0; float temperature = 0; char strWeather[16]; char *str_weather_type[] = {STR_WEATHER_NONE, STR_WEATHER_SUNNY, STR_WEATHER_CLOUDY, STR_WEATHER_RAIN, STR_WEATHER_THUNDERSTORM, STR_WEATHER_SNOW, STR_WEATHER_MIST}; if(Is_Ocpp_WeatherReq()) { Get_Ocpp_WeatherInfo(&weatherID, &temperature); if(weatherID != ShmChargerInfo->StationInfo.WeatherID || temperature != ShmChargerInfo->StationInfo.Temperature) { ShmChargerInfo->StationInfo.WeatherID = weatherID; ShmChargerInfo->StationInfo.Temperature = temperature; if(ShmChargerInfo->StationInfo.WeatherID <= _WEATHER_Mist) { strcpy(strWeather, str_weather_type[ShmChargerInfo->StationInfo.WeatherID]); } else { sprintf(strWeather, "%d", ShmChargerInfo->StationInfo.WeatherID); } LOG_INFO("Weather: [%s][%d], Temperature: %4.1f", strWeather, ShmChargerInfo->StationInfo.WeatherID, ShmChargerInfo->StationInfo.Temperature); AnnounceStationInfo(); } Clean_Ocpp_WeatherReq(); } } bool _WriteDeductBusy[CONNECTOR_QUANTITY] = {0}; void CheckDeductResultRequest(void) { char *str_ReaderStatus[] = {STR_DEDUCT_FAIL, STR_DEDUCT_PASS, STR_DEDUCT_CANCEL, STR_DEDUCT_PREAUTH}; char cardNo[21]; char appNo[10]; for(int i = 0; i < CONNECTOR_QUANTITY; i++) { if(Is_DeductResultReq(i)) { if(!_WriteDeductBusy[i]) { if(!Is_Ocpp_ReportCreditDeductReq() && ShmSysConfigAndInfo->SysInfo.OcppConnStatus) { _WriteDeductBusy[i] = true; //Set_Ocpp_DeductTransaction(_BackupDeductResult[i].TransactionId); //Set_Ocpp_DeductCreditNo((char *)&_BackupDeductResult[i].creditNo); //Set_Ocpp_DeductVemData(""); //Set_Ocpp_DeductAmount(((double)_BackupDeductResult[i].DeductAmount / 100)); //Set_Ocpp_DeductResult(_BackupDeductResult[i].DeductResult); //Set_Ocpp_DonateInvoice(_BackupDeductResult[i].IsDonateInvoice); if(Set_Ocpp_DeductInfo(&ShmChargerInfo->DeductResultReq[i])) { memset(cardNo, 0x00, sizeof(cardNo)); memcpy(cardNo, (char *)&ShmChargerInfo->DeductResultReq[i].creditNo[0], sizeof(ShmChargerInfo->DeductResultReq[i].creditNo)); memset(appNo, 0x00, sizeof(appNo)); memcpy(appNo, (char *)&ShmChargerInfo->DeductResultReq[i].ApprovalNumber[0], sizeof(ShmChargerInfo->DeductResultReq[i].ApprovalNumber)); Set_Ocpp_ReportCreditDeductReq(); LOG_INFO("DeductReport Gun %d TxId: %d, UserId: %s, ApprovalNo: [%s], Amount: %d.%02d, [%s], Donate: %s", i + 1, ShmChargerInfo->DeductResultReq[i].TransactionId, cardNo, appNo, (ShmChargerInfo->DeductResultReq[i].DeductAmount / 100), (ShmChargerInfo->DeductResultReq[i].DeductAmount % 100), str_ReaderStatus[ShmChargerInfo->DeductResultReq[i].DeductResult], ShmChargerInfo->DeductResultReq[i].IsDonateInvoice ? "Yes" : "No"); if(ShmChargerInfo->DeductResultReq[i].DeductResult == _Deduct_PreAuth_Pass) { memcpy(&ShmChargerInfo->ReaderStatus[i], &ShmChargerInfo->DeductResultReq[i], sizeof(DeductResultInfoData)); ShmChargerInfo->ReaderStatus[i].ReaderStatusReq = YES; } } } } else { if(!Is_Ocpp_ReportCreditDeductReq()) { Clean_DeductInfo(i); _WriteDeductBusy[i] = false; } } } else { _WriteDeductBusy[i] = false; } } } bool _WriteReDeductBusy = false; void CheckReDeductRequest(void) { char *str_ReaderStatus[] = {STR_DEDUCT_FAIL, STR_DEDUCT_PASS, STR_DEDUCT_CANCEL, STR_DEDUCT_PREAUTH}; char cardNo[21]; char appNo[10]; if(ShmChargerInfo->ReDeductReq.DeductReq) { if(!_WriteReDeductBusy) { if(!Is_Ocpp_ReportCreditDeductReq() && ShmSysConfigAndInfo->SysInfo.OcppConnStatus) { _WriteReDeductBusy = true; if(Set_Ocpp_DeductInfo(&ShmChargerInfo->ReDeductReq)) { memset(cardNo, 0x00, sizeof(cardNo)); memcpy(cardNo, (char *)&ShmChargerInfo->ReDeductReq.creditNo[0], sizeof(ShmChargerInfo->ReDeductReq.creditNo)); memset(appNo, 0x00, sizeof(appNo)); memcpy(appNo, (char *)&ShmChargerInfo->ReDeductReq.ApprovalNumber[0], sizeof(ShmChargerInfo->ReDeductReq.ApprovalNumber)); Set_Ocpp_ReportCreditDeductReq(); LOG_INFO("ReDeductReport TxId: %d, UserId: %s, ApprovalNo: [%s], Amount: %d.%02d, [%s], Donate: %s", ShmChargerInfo->ReDeductReq.TransactionId, cardNo, appNo, (ShmChargerInfo->ReDeductReq.DeductAmount / 100), (ShmChargerInfo->ReDeductReq.DeductAmount % 100), str_ReaderStatus[ShmChargerInfo->ReDeductReq.DeductResult], ShmChargerInfo->ReDeductReq.IsDonateInvoice ? "Yes" : "No"); if(ShmChargerInfo->ReDeductReq.DeductResult == _Deduct_PreAuth_Pass && ShmChargerInfo->ReDeductReq.ConnectorId != 0xFF) { int gunIndex = ShmChargerInfo->ReDeductReq.ConnectorId - 1; memcpy(&ShmChargerInfo->ReaderStatus[gunIndex], &ShmChargerInfo->ReDeductReq, sizeof(DeductResultInfoData)); ShmChargerInfo->ReaderStatus[gunIndex].ReaderStatusReq = YES; } } } } else { if(!Is_Ocpp_ReportCreditDeductReq()) { memset(&ShmChargerInfo->ReDeductReq, 0x00, sizeof(DeductResultInfoData)); _WriteReDeductBusy = false; } } } else { _WriteReDeductBusy = false; } } bool _WriteReaderStatusBusy[CONNECTOR_QUANTITY] = {0}; void CheckReaderStatusRequest(void) { char *str_ReaderStatus[] = {STR_DEDUCT_FAIL, STR_DEDUCT_PASS, STR_DEDUCT_CANCEL, STR_DEDUCT_PREAUTH}; char cardNo[21]; char appNo[10]; for(int i = 0; i < CONNECTOR_QUANTITY; i++) { if(Is_ReaderStatusReq(i)) { if(!_WriteReaderStatusBusy[i]) { if(!Is_Ocpp_TcciReaderStatusReq(i) && ShmSysConfigAndInfo->SysInfo.OcppConnStatus) { _WriteReaderStatusBusy[i] = true; if(Set_Ocpp_TcciReaderStatus(i, &ShmChargerInfo->ReaderStatus[i])) { memset(cardNo, 0x00, sizeof(cardNo)); memcpy(cardNo, (char *)&ShmChargerInfo->ReaderStatus[i].creditNo[0], sizeof(ShmChargerInfo->ReaderStatus[i].creditNo)); memset(appNo, 0x00, sizeof(appNo)); memcpy(appNo, (char *)&ShmChargerInfo->ReaderStatus[i].ApprovalNumber[0], sizeof(ShmChargerInfo->ReaderStatus[i].ApprovalNumber)); Set_Ocpp_TcciReaderStatusReq(i); LOG_INFO("StatusReport Gun %d: [%s], CreditNo: [%s], ApprovalNo: [%s]", i + 1, str_ReaderStatus[ShmChargerInfo->ReaderStatus[i].DeductResult], cardNo, appNo); } } } else { if(!Is_Ocpp_TcciReaderStatusReq(i)) { Clean_ReaderStatusInfo(i); _WriteReaderStatusBusy[i] = false; } } } else { _WriteReaderStatusBusy[i] = false; } } } void CheckOccupancyPrice(void) { float _price = 0; if(Is_Ocpp_TcciSetOccupancyPriceReq()) { _price = Get_Ocpp_TcciOccupancyPrice(); if(ShmChargerInfo->CabinetMiscValue.ParkingPrice != _price) { ShmChargerInfo->CabinetMiscValue.ParkingPrice = _price; LOG_INFO("Set OccupancyPrice: [%6.2f]", ShmChargerInfo->CabinetMiscValue.ParkingPrice); AnnounceOccupancyPrice(); } Clean_Ocpp_TcciSetOccupancyPriceReq(); } } bool IsParkingButtonStatusChanged(int gunIndex) { return ShmChargerInfo->AllBill.OccupancyInfo[gunIndex].ButtonReqStatus.MiscStatus == ShmChargerInfo->AllBill.OccupancyInfo[gunIndex].ButtonReqStatus.PreStatus ? false : true; } void SyncParkingButtonStatus(int gunIndex) { ShmChargerInfo->AllBill.OccupancyInfo[gunIndex].ButtonReqStatus.PreStatus = ShmChargerInfo->AllBill.OccupancyInfo[gunIndex].ButtonReqStatus.MiscStatus; } int OccupancyButtonSync(int gunIndex) { int _pass = FAIL; unsigned char _status = ShmChargerInfo->AllBill.OccupancyInfo[gunIndex].ButtonReqStatus.MiscStatus; switch(_status) { case _BillStatus_Idle: if(IsParkingButtonStatusChanged(gunIndex)) { memset(&ShmChargerInfo->AllBill.OccupancyInfo[gunIndex].ButtonReqStatus, 0x00, sizeof(MiscRequestStatus)); SyncParkingButtonStatus(gunIndex); } break; case _BillStatus_MiscReq: if(IsParkingButtonStatusChanged(gunIndex)) { Occupancy_INFO("Gun %d OccupancyButton [MiscRequest]", gunIndex + 1); SyncParkingButtonStatus(gunIndex); } ShmChargerInfo->AllBill.OccupancyInfo[gunIndex].ButtonReqStatus.MiscStatus = _BillStatus_WaitMiscClean; Set_Connector_MiscCommand(gunIndex, MISC_CONN_PARKING_STATUS); break; case _BillStatus_WaitMiscClean: if(IsParkingButtonStatusChanged(gunIndex)) { SyncParkingButtonStatus(gunIndex); GetClockTime(&_ParkingStatus_Time[gunIndex]); } if((GetTimeoutValue(_ParkingStatus_Time[gunIndex]) / uSEC_VAL) >= PARKING_STATUS_TIMEOUT) { Occupancy_INFO("Gun %d OccupancyButton [WaitMisc Timeout]", gunIndex + 1); ShmChargerInfo->AllBill.OccupancyInfo[gunIndex].ButtonReqStatus.MiscStatus = _BillStatus_MiscReq; } break; case _BillStatus_MiscClean: if(IsParkingButtonStatusChanged(gunIndex)) { Occupancy_INFO("Gun %d OccupancyButton [MiscClean]", gunIndex + 1); SyncParkingButtonStatus(gunIndex); GetClockTime(&_ParkingStatus_Time[gunIndex]); } if((GetTimeoutValue(_ParkingStatus_Time[gunIndex]) / uSEC_VAL) >= PARKING_STATUS_TIMEOUT) { LOG_INFO("Gun %d OccupancyButton [Wait Timeout]", gunIndex + 1); ShmChargerInfo->AllBill.OccupancyInfo[gunIndex].ButtonReqStatus.MiscStatus = _BillStatus_MiscReq; } break; case _BillStatus_UpdateDone: if(IsParkingButtonStatusChanged(gunIndex)) { Occupancy_INFO("Gun %d OccupancyButton [UpdateDone]", gunIndex + 1); SyncParkingButtonStatus(gunIndex); } ShmChargerInfo->AllBill.OccupancyInfo[gunIndex].ButtonReqStatus.MiscStatus = _BillStatus_Idle; memset(&ShmChargerInfo->AllBill.OccupancyInfo[gunIndex].ButtonReqStatus, 0x00, sizeof(MiscRequestStatus)); _pass = PASS; break; default: memset(&ShmChargerInfo->AllBill.OccupancyInfo[gunIndex].ButtonReqStatus, 0x00, sizeof(MiscRequestStatus)); break; } return _pass; } int NotifyOccupancyFeeActRequest(int gunIndex, int action) { char *str_notify_occupancy_act[] = {STR_NOTIFY_NONE, STR_GET_OCCUPANCY_FEE, STR_CANCEL_OCCUPANCY_DEDUCT, STR_CANCEL_OCCUPANCY_FEE}; if(_notifyOccupancyFeeAct[gunIndex] == _Notify_None) { if(!Is_Ocpp_TcciOccupancyFeeActReq(gunIndex)) { GetClockTime(&_GetOccupancyFee_Time[gunIndex]); Set_Ocpp_TcciOccupancyFeeAct(gunIndex, &ShmChargerInfo->AllBill.OccupancyInfo[gunIndex].OccupancyBill, action); _notifyOccupancyFeeAct[gunIndex] = action; LOG_INFO("Gun %d Set OccupancyFee Action [%s] Request", gunIndex + 1, str_notify_occupancy_act[action]); } } else { if(!Is_Ocpp_TcciOccupancyFeeActReq(gunIndex)) { if(Is_Ocpp_TcciOccupancyFeeActStatus(gunIndex, "Accepted")) { if(_notifyOccupancyFeeAct[gunIndex] == _Notify_GetOccupancyFee) { Get_Ocpp_TcciGetOccupancyFeeResponse(gunIndex, &ShmChargerInfo->AllBill.OccupancyInfo[gunIndex].OccupancyBill); LOG_INFO("Gun %d Get Occupancy Fee: [%.2f], Duration: [%d], StartTime: [%s]", gunIndex + 1, ShmChargerInfo->AllBill.OccupancyInfo[gunIndex].OccupancyBill.Fee, ShmChargerInfo->AllBill.OccupancyInfo[gunIndex].OccupancyBill.Duration, ShmChargerInfo->AllBill.OccupancyInfo[gunIndex].OccupancyBill.StartTime); } if(_notifyOccupancyFeeAct[gunIndex] == _Notify_CancelLocalDeduction) { LOG_INFO("Gun %d Occupancy Deduction Stopped", gunIndex + 1); } if(_notifyOccupancyFeeAct[gunIndex] == _Notify_CancelOccupancyFee) { LOG_INFO("Gun %d Occupancy Fee Force Clean", gunIndex + 1); } _notifyOccupancyFeeAct[gunIndex] = _Notify_None; return PASS; } else { LOG_INFO("Gun %d OccupancyFee Action [%s] Rejected", gunIndex + 1, str_notify_occupancy_act[action]); return FAIL; } } if((GetTimeoutValue(_GetOccupancyFee_Time[gunIndex]) / uSEC_VAL) >= OCCUPANCY_FEE_TIMEOUT) { // shall not reach here Clean_Ocpp_TcciNotifyOccupancyFeeActReq(gunIndex); _notifyOccupancyFeeAct[gunIndex] = _Notify_None; LOG_INFO("Gun %d OccupancyFee Action [%s] Request Timeout", gunIndex + 1, str_notify_occupancy_act[action]); return FAIL; } } return WAIT; } bool IsParkingStatusChanged(int gunIndex) { return ShmChargerInfo->AllBill.OccupancyInfo[gunIndex].Status == ShmChargerInfo->AllBill.OccupancyInfo[gunIndex].PreStatus ? false : true; } void SyncParkingStatus(int gunIndex) { ShmChargerInfo->AllBill.OccupancyInfo[gunIndex].PreStatus = ShmChargerInfo->AllBill.OccupancyInfo[gunIndex].Status; } bool Is_Occupancy_Cancel(int gunIndex) { unsigned char dispenser = 0; dispenser = ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gunIndex].ParentDispensetIndex; if((!ShmSysConfigAndInfo->SysInfo.OcppConnStatus && !ShmChargerInfo->AllBill.OccupancyInfo[gunIndex].OccupancyReq.bits.SelfReq) || ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[dispenser].LocalStatus == _DS_None || ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[dispenser].LocalStatus == _DS_Timeout) { return true; } return false; } void OccupancyRequest(int gunIndex) { int _action = 0; bool feeRequest = false; bool keepCounting = false; int res = FAIL; char _sn[37]; unsigned char _status = 0; char *str_action[] = {STR_OCCUPANCY_ACT_NONE, STR_OCCUPANCY_ACT_DISPLAY, STR_OCCUPANCY_ACT_CANCEL, STR_OCCUPANCY_ACT_PAID_OK, STR_OCCUPANCY_ACT_PAID_NG}; _status = ShmChargerInfo->AllBill.OccupancyInfo[gunIndex].Status; if(Is_Ocpp_TcciOccupancyDisplayReq(gunIndex)) { memset(_sn, 0x00, sizeof(_sn)); _action = Get_Ocpp_TcciOccupancyAction(gunIndex, sizeof(_sn) - 1, _sn); ShmChargerInfo->AllBill.OccupancyInfo[gunIndex].ActionId = _action; LOG_INFO("Gun %d OccupancyAction is [%s]", gunIndex + 1, str_action[_action]); Clean_Ocpp_TcciOccupancyDisplayReq(gunIndex); } if(ShmChargerInfo->ConnectorActReq[gunIndex].Flag.bits.ParkingFeeRequest) { feeRequest = true; ShmChargerInfo->ConnectorActReq[gunIndex].Flag.bits.ParkingFeeRequest =false; } if(Is_OccupancyKeepCountingReq(gunIndex)) { if(_status == _Parking_WaitToPay) { keepCounting = true; } else { Clean_OccupancyKeepCountingReq(gunIndex); } } if(_status != _Parking_NoOccupancy && chargingInfo[gunIndex]->SystemStatus == S_CHARGING) { if(!Is_OccupancyFeeForceCancelReq(gunIndex)) { Set_OccupancyFeeForceCancelReq(gunIndex); Occupancy_INFO("Gun %d Need Force Cancel OccupancyStatus", gunIndex + 1); } } if(Is_OccupancyFeeForceCancelReq(gunIndex)) { res = NotifyOccupancyFeeActRequest(gunIndex, _Notify_CancelOccupancyFee); if(res == PASS || res == FAIL) { ShmChargerInfo->AllBill.OccupancyInfo[gunIndex].Status = _Parking_NoOccupancy; Clean_OccupancyFeeForceCancelReq(gunIndex); return; } else { // wait response } } switch(_status) { case _Parking_NoOccupancy: if(IsParkingStatusChanged(gunIndex)) { Occupancy_INFO("Gun %d OccupancyStatus [Clean]", gunIndex + 1); memset(&ShmChargerInfo->AllBill.OccupancyInfo[gunIndex], 0x00, sizeof(OccupancyInfoData)); SyncParkingStatus(gunIndex); } if(_action == _ParkingAction_DisplayButton) { memcpy(ShmChargerInfo->AllBill.OccupancyInfo[gunIndex].OccupancyBill.Sn, _sn, sizeof(_sn)); ShmChargerInfo->AllBill.OccupancyInfo[gunIndex].Status = _Parking_SyncOccupancy; } break; case _Parking_SyncOccupancy: if(IsParkingStatusChanged(gunIndex)) { Occupancy_INFO("Gun %d OccupancyStatus [Sync]", gunIndex + 1); SyncParkingStatus(gunIndex); memset(&ShmChargerInfo->AllBill.OccupancyInfo[gunIndex].ButtonReqStatus, 0x00, sizeof(MiscRequestStatus)); ShmChargerInfo->AllBill.OccupancyInfo[gunIndex].ButtonReqStatus.MiscStatus = _BillStatus_MiscReq; } if(_action == _ParkingAction_DisplayButton) { memcpy(ShmChargerInfo->AllBill.OccupancyInfo[gunIndex].OccupancyBill.Sn, _sn, sizeof(_sn)); } else if(_action == _ParkingAction_CancelOccupancy || Is_Occupancy_Cancel(gunIndex)) { ShmChargerInfo->AllBill.OccupancyInfo[gunIndex].Status = _Parking_NoOccupancy; } else if(_action == _ParkingAction_PaidOnlineOK) { ShmChargerInfo->AllBill.OccupancyInfo[gunIndex].Status = _Parking_PaidOnlineOK; } else { if(ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gunIndex].RemoteStatus != _CRS_Preparing && ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gunIndex].RemoteStatus != _CRS_Charging) { if(OccupancyButtonSync(gunIndex) == PASS) { ShmChargerInfo->AllBill.OccupancyInfo[gunIndex].Status = _Parking_Occupied; } } } break; case _Parking_Occupied: if(IsParkingStatusChanged(gunIndex)) { Occupancy_INFO("Gun %d OccupancyStatus [Start]", gunIndex + 1); SyncParkingStatus(gunIndex); memset(&ShmChargerInfo->AllBill.OccupancyInfo[gunIndex].ButtonReqStatus, 0x00, sizeof(MiscRequestStatus)); ShmChargerInfo->AllBill.OccupancyInfo[gunIndex].ButtonReqStatus.MiscStatus = _BillStatus_MiscReq; } if(_action == _ParkingAction_DisplayButton) { memcpy(ShmChargerInfo->AllBill.OccupancyInfo[gunIndex].OccupancyBill.Sn, _sn, sizeof(_sn)); } else if(_action == _ParkingAction_CancelOccupancy || Is_Occupancy_Cancel(gunIndex)) { ShmChargerInfo->AllBill.OccupancyInfo[gunIndex].Status = _Parking_NoOccupancy; } else if(_action == _ParkingAction_PaidOnlineOK) { ShmChargerInfo->AllBill.OccupancyInfo[gunIndex].Status = _Parking_PaidOnlineOK; } else if(_action == _ParkingAction_PaidOnlineFail) { ShmChargerInfo->AllBill.OccupancyInfo[gunIndex].Status = _Parking_PaidOnlineFail; } else { if(feeRequest) { ShmChargerInfo->AllBill.OccupancyInfo[gunIndex].Status = _Parking_RequestFee; } } break; case _Parking_RequestFee: if(IsParkingStatusChanged(gunIndex)) { Occupancy_INFO("Gun %d OccupancyStatus [RequestFee]", gunIndex + 1); SyncParkingStatus(gunIndex); _notifyOccupancyFeeAct[gunIndex] = _Notify_None; GetClockTime(&_GetOccupancyFee_Time[gunIndex]); } if(_action == _ParkingAction_CancelOccupancy || Is_Occupancy_Cancel(gunIndex)) { ShmChargerInfo->AllBill.OccupancyInfo[gunIndex].Status = _Parking_NoOccupancy; } else if(_action == _ParkingAction_PaidOnlineOK) { ShmChargerInfo->AllBill.OccupancyInfo[gunIndex].Status = _Parking_PaidOnlineOK; } else if(_action == _ParkingAction_PaidOnlineFail) { ShmChargerInfo->AllBill.OccupancyInfo[gunIndex].Status = _Parking_PaidOnlineFail; } else { if(ShmChargerInfo->AllBill.OccupancyInfo[gunIndex].OccupancyReq.bits.SelfReq) { ShmChargerInfo->AllBill.OccupancyInfo[gunIndex].Status = _Parking_WaitToPay; } else { res = NotifyOccupancyFeeActRequest(gunIndex, _Notify_GetOccupancyFee); if(res == PASS) { ShmChargerInfo->AllBill.OccupancyInfo[gunIndex].Status = _Parking_WaitToPay; } else if(res == FAIL) { ShmChargerInfo->AllBill.OccupancyInfo[gunIndex].Status = _Parking_NoOccupancy; } else { // wait response } } } break; case _Parking_WaitToPay: if(IsParkingStatusChanged(gunIndex)) { Occupancy_INFO("Gun %d OccupancyStatus [WaitToPay]", gunIndex + 1); SyncParkingStatus(gunIndex); memset(&ShmChargerInfo->AllBill.OccupancyInfo[gunIndex].BillReqStatus, 0x00, sizeof(MiscRequestStatus)); _notifyOccupancyFeeAct[gunIndex] = _Notify_None; } if(_action == _ParkingAction_CancelOccupancy || Is_Occupancy_Cancel(gunIndex)) { ShmChargerInfo->AllBill.OccupancyInfo[gunIndex].Status = _Parking_NoOccupancy; } else if(_action == _ParkingAction_PaidOnlineOK) { ShmChargerInfo->AllBill.OccupancyInfo[gunIndex].Status = _Parking_PaidOnlineOK; } else if(_action == _ParkingAction_PaidOnlineFail) { ShmChargerInfo->AllBill.OccupancyInfo[gunIndex].Status = _Parking_PaidOnlineFail; } else if(keepCounting) { res = NotifyOccupancyFeeActRequest(gunIndex, _Notify_CancelLocalDeduction); if(res == PASS) { ShmChargerInfo->AllBill.OccupancyInfo[gunIndex].Status = _Parking_Occupied; Clean_OccupancyKeepCountingReq(gunIndex); } else if(res == FAIL) { ShmChargerInfo->AllBill.OccupancyInfo[gunIndex].Status = _Parking_NoOccupancy; Clean_OccupancyKeepCountingReq(gunIndex); } else { // wait response } } break; case _Parking_PaidOnlineOK: if(IsParkingStatusChanged(gunIndex)) { Occupancy_INFO("Gun %d OccupancyStatus [PaidOnlineOK]", gunIndex + 1); SyncParkingStatus(gunIndex); GetClockTime(&_GetOccupancyFee_Time[gunIndex]); } if((GetTimeoutValue(_GetOccupancyFee_Time[gunIndex]) / uSEC_VAL) >= OCCUPANCY_FEE_TIMEOUT) { LOG_INFO("Gun %d Reset OccupancyStatus via PaidOnlineOK", gunIndex + 1); ShmChargerInfo->AllBill.OccupancyInfo[gunIndex].Status = _Parking_NoOccupancy; } break; case _Parking_PaidOnlineFail: if(IsParkingStatusChanged(gunIndex)) { Occupancy_INFO("Gun %d OccupancyStatus [PaidOnlineFail]", gunIndex + 1); SyncParkingStatus(gunIndex); GetClockTime(&_GetOccupancyFee_Time[gunIndex]); } if((GetTimeoutValue(_GetOccupancyFee_Time[gunIndex]) / uSEC_VAL) >= OCCUPANCY_FEE_TIMEOUT) { LOG_INFO("Gun %d Return to Occupied via PaidOnlineFail", gunIndex + 1); ShmChargerInfo->AllBill.OccupancyInfo[gunIndex].Status = _Parking_Occupied; } break; default: DisableConnectorBill(gunIndex); break; } } void CheckOccupancyFee(void) { for(int i = 0; i < CONNECTOR_QUANTITY; i++) { OccupancyRequest(i); } } #define OCCUPANCY_DEDUCT_IDLE 0 #define OCCUPANCY_DEDUCT_REQUEST 1 unsigned char _OccupancyDeductStatus = OCCUPANCY_DEDUCT_IDLE; int _OccupancyReportGunId = 0; void CheckOccupancyDeduct(void) { char cardNo[21]; char appNo[10]; if(_OccupancyDeductStatus == OCCUPANCY_DEDUCT_IDLE) { if(!Is_Ocpp_TcciReportOccupancyDeductReq()) { for(int i = 0; i < CONNECTOR_QUANTITY; i++) { if(Is_OccupancyDeductReq(i)) { if(ShmChargerInfo->AllBill.OccupancyInfo[i].OccupancyReq.bits.SelfReq && ShmChargerInfo->AllBill.OccupancyInfo[i].Status == _Parking_WaitToPay) { ShmChargerInfo->AllBill.OccupancyInfo[i].Status = _Parking_NoOccupancy; LOG_INFO("Gun %d Occupancy Concluded!", i + 1); break; } Set_Ocpp_OccupancyDeductResult(&ShmChargerInfo->AllBill.OccupancyInfo[i].OccupancyDeduct, YES); Set_Ocpp_TcciReportOccupancyDeductReq(); _OccupancyDeductStatus = OCCUPANCY_DEDUCT_REQUEST; _OccupancyReportGunId = i + 1; Clean_OccupancyDeductReq(i); break; } } if(_OccupancyDeductStatus != OCCUPANCY_DEDUCT_IDLE) { memset(cardNo, 0x00, sizeof(cardNo)); memset(appNo, 0x00, sizeof(appNo)); memcpy(cardNo, ShmChargerInfo->AllBill.OccupancyInfo[_OccupancyReportGunId - 1].OccupancyDeduct.creditNo, sizeof(ShmChargerInfo->AllBill.OccupancyInfo[_OccupancyReportGunId - 1].OccupancyDeduct.creditNo)); memcpy(appNo, ShmChargerInfo->AllBill.OccupancyInfo[_OccupancyReportGunId - 1].OccupancyDeduct.ApprovalNumber, sizeof(ShmChargerInfo->AllBill.OccupancyInfo[_OccupancyReportGunId - 1].OccupancyDeduct.ApprovalNumber)); LOG_INFO("Gun %d Occupancy Deduct [Request] Sn: [%s], Fee: [%.2f], CreditNo: [%s], ApprovalNo: [%s]", _OccupancyReportGunId, ShmChargerInfo->AllBill.OccupancyInfo[_OccupancyReportGunId - 1].OccupancyDeduct.Sn, ShmChargerInfo->AllBill.OccupancyInfo[_OccupancyReportGunId - 1].OccupancyDeduct.Fee, cardNo, appNo); } } } else { if(!Is_Ocpp_TcciReportOccupancyDeductReq()) { if(ShmChargerInfo->AllBill.OccupancyInfo[_OccupancyReportGunId - 1].Status == _Parking_WaitToPay) { ShmChargerInfo->AllBill.OccupancyInfo[_OccupancyReportGunId - 1].Status = _Parking_NoOccupancy; LOG_INFO("Gun %d OccupancyDeduct Request Completed!", _OccupancyReportGunId); } _OccupancyDeductStatus = OCCUPANCY_DEDUCT_IDLE; } } } void CheckDiagnosticsReq(void) { bool _DiagnosticsCompleted = true; int _DispenserId = 0; char _IpAddress[32]; char cmdBuf[256] = {0}; if(Is_Ocpp_GetDiagnosticsReq() || ShmChargerInfo->Control.Diagnostics.DiagnosticsType != DIAGNOSTICS_TYPE_NONE) { // check dispenser status and set diagnostics request for(int i = 0; i < MAX_DISPENSER_QUANTITY; i++) { if(ShmSysConfigAndInfo->SysInfo.DispenserInfo.ConnectionInfo[i].Status == _CNS_DispenserMatched) { _DispenserId = ShmSysConfigAndInfo->SysInfo.DispenserInfo.ConnectionInfo[i].DispenserIndex + 1; if(!ShmChargerInfo->Control.Diagnostics.DispenserDiagnostics[_DispenserId - 1].bits.Request) { ShmChargerInfo->Control.Diagnostics.DispenserDiagnostics[_DispenserId - 1].CtrlValue = 0; sprintf((char*)_IpAddress, "%d.%d.%d.%d", ((ShmSysConfigAndInfo->SysInfo.DispenserInfo.ConnectionInfo[i].IpAddress >> 0) & 0xFF), ((ShmSysConfigAndInfo->SysInfo.DispenserInfo.ConnectionInfo[i].IpAddress >> 8) & 0xFF), ((ShmSysConfigAndInfo->SysInfo.DispenserInfo.ConnectionInfo[i].IpAddress >> 16) & 0xFF), ((ShmSysConfigAndInfo->SysInfo.DispenserInfo.ConnectionInfo[i].IpAddress >> 24) & 0xFF)); sprintf(cmdBuf, "/root/Module_Diagnostics %d %s &", _DispenserId, _IpAddress); system(cmdBuf); ShmChargerInfo->Control.Diagnostics.DispenserDiagnostics[_DispenserId - 1].bits.Request = true; } if(!_NeedDiagnostics) { GetClockTime(&_Diagnostics_Time); LOG_INFO("Dispenser Need Diagnostics!"); } _NeedDiagnostics = true; } } if(_NeedDiagnostics) { for(int i = 0; i < MAX_DISPENSER_QUANTITY; i++) { if(ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[i].LocalStatus != _DS_None && ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[i].LocalStatus != _DS_Timeout) { if(!ShmChargerInfo->Control.Diagnostics.DispenserDiagnostics[i].bits.Stop) { if(!ShmChargerInfo->Control.Diagnostics.DispenserDiagnostics[i].bits.Confirm) { if(GetSecTimeoutValue(_Diagnostics_Time) >= WAIT_DIAGNOSTICS_CONFIRM) { ShmChargerInfo->Control.Diagnostics.DispenserDiagnostics[i].bits.Stop = true; LOG_INFO("Wait Dispenser %d diagnostics confirm timeout!", i + 1); } _DiagnosticsCompleted = false; } else if(!ShmChargerInfo->Control.Diagnostics.DispenserDiagnostics[i].bits.Completed) { if(GetSecTimeoutValue(_Diagnostics_Time) >= WAIT_DIAGNOSTICS_TIMEOUT) { ShmChargerInfo->Control.Diagnostics.DispenserDiagnostics[i].bits.Stop = true; LOG_INFO("Wait Dispenser %d diagnostics completed timeout!", i + 1); } _DiagnosticsCompleted = false; } } } } } if(_DiagnosticsCompleted) { // diagnostics completed, clean ocpp GetDiagnosticsReq for(int i = 0; i < MAX_DISPENSER_QUANTITY; i++) { ShmChargerInfo->Control.Diagnostics.DispenserDiagnostics[i].CtrlValue = 0; } if(Is_Ocpp_GetDiagnosticsReq()) { Clean_Ocpp_GetDiagnosticsReq(); } if(ShmChargerInfo->Control.Diagnostics.DiagnosticsType != DIAGNOSTICS_TYPE_NONE) { ShmChargerInfo->Control.Diagnostics.DiagnosticsType = DIAGNOSTICS_TYPE_NONE; } LOG_INFO("Dispenser Diagnostics Completed!"); } } else { _NeedDiagnostics = false; } } //=============================================== // OCPP //=============================================== void CheckOcppStatus() { if (Is_Ocpp_BootNotification()) { Clean_Ocpp_BootNotification(); LOG_INFO("*********************OCPP Boot Notification****************************"); } if (Is_Ocpp_ResetReq()) { bool canReset = true; if (ShmSysConfigAndInfo->SysWarningInfo.Level != 2) { for (byte _index = 0; _index < ShmSysConfigAndInfo->SysConfig.TotalConnectorCount; _index++) { if (chargingInfo[_index]->SystemStatus != S_IDLE && chargingInfo[_index]->SystemStatus != S_RESERVATION && chargingInfo[_index]->SystemStatus != S_MAINTAIN) { canReset = false; //if (chargingInfo[_index]->SystemStatus >= S_REASSIGN && chargingInfo[_index]->SystemStatus < S_TERMINATING) //{ // ChargingTerminalProcess(_index); //} if(Chk_Ocpp_Reset_Type("Hard") || Chk_Ocpp_Reset_Type("Immediate")) { chargingInfo[_index]->ChargingStopFlag.bits.HardResetStop = true; } if(Chk_Ocpp_Reset_Type("Soft") || Chk_Ocpp_Reset_Type("OnIdle")) { chargingInfo[_index]->ChargingStopFlag.bits.SoftResetStop = true; } } } } if(canReset) { if(Chk_Ocpp_Reset_Type("Hard") || Chk_Ocpp_Reset_Type("Immediate")) { //trigger dispenser to hardware reboot TriggerDispenserHardwareReboot(); if(IsDispenserHardwareRebootResponsed()) { Clean_Ocpp_ResetReq(); LOG_INFO("****** Hard Reboot ******"); for(int i = 0; i < ShmSysConfigAndInfo->SysConfig.TotalConnectorCount; i++) { setChargerMode(i, MODE_MAINTAIN); } sleep(3); system("reboot -f"); } } if(Chk_Ocpp_Reset_Type("Soft") || Chk_Ocpp_Reset_Type("OnIdle")) { //trigger dispenser to software reset TriggerDispenserSoftwareReset(); if(IsDispenserSoftwareResetResponsed()) { Clean_Ocpp_ResetReq(); LOG_INFO("****** Soft Reboot ******"); for(int i = 0; i < ShmSysConfigAndInfo->SysConfig.TotalConnectorCount; i++) { setChargerMode(i, MODE_MAINTAIN); } sleep(3); Kill_Ocpp_Service(); KillAllTask(); TryCloseWatchdog(); system("/usr/bin/run_evse_restart.sh"); } } } } CheckOcppCostAndPrice(); CheckLcmPageChangeRequest(); CheckStationInfo(); CheckWeatherInfo(); CheckDeductResultRequest(); CheckReDeductRequest(); CheckReaderStatusRequest(); CheckOccupancyPrice(); CheckOccupancyFee(); CheckOccupancyDeduct(); CheckDiagnosticsReq(); } void CheckoutStartChargingSoc(byte gunIndex, bool force) { if(!ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gunIndex].Parameter.bits.GetStartChargingSoc) { if(chargingInfo[gunIndex]->EvBatterySoc > 0 || force) { chargingInfo[gunIndex]->EvBatteryStartSoc = chargingInfo[gunIndex]->EvBatterySoc; LOG_INFO("Gun %d StartSoc = %d", chargingInfo[gunIndex]->Index + 1, chargingInfo[gunIndex]->EvBatteryStartSoc); ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gunIndex].Parameter.bits.GetStartChargingSoc = true; } } } void UpdateChargingTimestamp(char *timestamp) { struct timeb SeqEndTime; struct tm *tm; ftime(&SeqEndTime); SeqEndTime.time = time(NULL); tm = localtime(&SeqEndTime.time); sprintf(timestamp, "%04d-%02d-%02d %02d:%02d:%02d", tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec); } void OcppStartTransaction(byte gunIndex) { if(_triggerTransaction[gunIndex]) { return; } // clean deduct info Clean_DeductInfo(gunIndex); // set deduct user id //Set_Deduct_UserId(gunIndex, (char *)&chargingInfo[gunIndex]->StartUserId); // initial start & stop datetime strcpy((char *)chargingInfo[gunIndex]->StartDateTime, "00:00:00"); strcpy((char *)chargingInfo[gunIndex]->StopDateTime, "00:00:00"); Update_PowerConsumption(gunIndex); _lsatGunMeterValue[gunIndex] = chargingInfo[gunIndex]->PowerConsumption; Set_Ocpp_StartTransactionIdTag(gunIndex, (char *)chargingInfo[gunIndex]->StartUserId); LOG_INFO("Gun %d Start Transaction IdTag = %s, MeterValue: %.4f", chargingInfo[gunIndex]->Index + 1, chargingInfo[gunIndex]->StartUserId, chargingInfo[gunIndex]->PowerConsumption); Clean_Ocpp_StartTransactionConf(gunIndex); UpdateChargingTimestamp(ShmChargerInfo->Timestamp[gunIndex].StartCharging); Set_Ocpp_StartTransactionReq(gunIndex); // set _triggerTransaction _triggerTransaction[gunIndex] = true; } void OcppStopTransaction(byte gunIndex) { if(!_triggerTransaction[gunIndex]) { return; } Update_PowerConsumption(gunIndex); _lsatGunMeterValue[gunIndex] = chargingInfo[gunIndex]->PowerConsumption; Set_Ocpp_StopTransactionId(gunIndex, (char *)chargingInfo[gunIndex]->StartUserId); LOG_INFO("Gun %d Stop Transaction IdTag = %s, StopSoc = %d, MeterValue: %.4f", chargingInfo[gunIndex]->Index + 1, chargingInfo[gunIndex]->StartUserId, chargingInfo[gunIndex]->EvBatterySoc, chargingInfo[gunIndex]->PowerConsumption); UpdateChargingTimestamp(ShmChargerInfo->Timestamp[gunIndex].StopCharging); Set_Ocpp_StopTransactionReq(gunIndex); // clean _triggerTransaction _triggerTransaction[gunIndex] = false; } bool Is_DispenserStop(byte gunIndex) { bool _isStop = false; if(ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gunIndex].RemoteStatus != _CRS_Preparing && ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gunIndex].RemoteStatus != _CRS_Charging) { _isStop = true; } return _isStop; } void ChkOcppStatus(byte gunIndex) { Chk_Ocpp_Backup_ErrorCode(gunIndex); if(Is_Ocpp_ReserveNowReq(gunIndex)) { Clean_Ocpp_ReserveNowReq(gunIndex); if(chargingInfo[gunIndex]->SystemStatus == S_IDLE && !Is_Ocpp_ReserveNowExpired(gunIndex)) { LOG_INFO("***************ChkOcppStatus: Gun %d OcppReservedStatus********************", gunIndex + 1); chargingInfo[gunIndex]->ReservationId = Get_Ocpp_ReserveNowId(gunIndex); setChargerMode(gunIndex, MODE_RESERVATION); } Set_Ocpp_ReserveNowConf(gunIndex); } if(Is_Ocpp_CancelReservationReq(gunIndex)) { Clean_Ocpp_CancelReservationReq(gunIndex); if(chargingInfo[gunIndex]->SystemStatus == S_RESERVATION) { LOG_INFO("***************ChkOcppStatus: Gun %d Cancel OcppReservedStatus********************", gunIndex + 1); chargingInfo[gunIndex]->ReservationId = -1; setChargerMode(gunIndex, MODE_IDLE); } Set_Ocpp_CancelReservationConf(gunIndex); } if (Is_Ocpp_ChangeAvailabilityReq(gunIndex) == YES) { LOG_INFO("***************ChkOcppStatus: Gun %d OcppChangeAvailability********************", gunIndex + 1); Clean_Ocpp_ChangeAvailabilityReq(gunIndex); if(Chk_Ocpp_Availability_Type(gunIndex, "Operative")) { if (isDb_ready) DB_Update_Operactive(localDb, gunIndex, true); chargingInfo[gunIndex]->IsAvailable = YES; Set_Connector_MiscCommand(gunIndex, MISC_CONN_AVAILABILITY); if (chargingInfo[gunIndex]->SystemStatus == S_IDLE || chargingInfo[gunIndex]->SystemStatus == S_RESERVATION || chargingInfo[gunIndex]->SystemStatus == S_MAINTAIN) { setChargerMode(gunIndex, MODE_IDLE); } } else if(Chk_Ocpp_Availability_Type(gunIndex, "Inoperative")) { if (isDb_ready) DB_Update_Operactive(localDb, gunIndex, false); chargingInfo[gunIndex]->IsAvailable = NO; Set_Connector_MiscCommand(gunIndex, MISC_CONN_AVAILABILITY); if (chargingInfo[gunIndex]->SystemStatus == S_IDLE || chargingInfo[gunIndex]->SystemStatus == S_RESERVATION || chargingInfo[gunIndex]->SystemStatus == S_MAINTAIN) { setChargerMode(gunIndex, MODE_MAINTAIN); } } } if (Is_Ocpp_UnlockConnectorReq(gunIndex)) { Clean_Ocpp_UnlockConnectorReq(gunIndex); if(chargingInfo[gunIndex]->SystemStatus == S_PREPARNING || chargingInfo[gunIndex]->SystemStatus == S_PREPARING_FOR_EV || chargingInfo[gunIndex]->SystemStatus == S_PREPARING_FOR_EVSE || chargingInfo[gunIndex]->SystemStatus == S_CHARGING) { // 充電中,需停止充電 Set_Ocpp_StopReason(gunIndex, "UnlockCommand"); //Set_Connector_MiscCommand(gunIndex, MISC_CONN_UNLOCK); chargingInfo[gunIndex]->ChargingStopFlag.bits.UnlockStop = true; LOG_INFO("********** OcppUnlockStop Gun %d **********", gunIndex + 1); } Set_Ocpp_UnlockConnectorConf(gunIndex); } if (Is_Ocpp_RemoteStopReq(gunIndex)) { Clean_Ocpp_RemoteStopReq(gunIndex); if(chargingInfo[gunIndex]->SystemStatus == S_PREPARNING || chargingInfo[gunIndex]->SystemStatus == S_PREPARING_FOR_EV || chargingInfo[gunIndex]->SystemStatus == S_PREPARING_FOR_EVSE || chargingInfo[gunIndex]->SystemStatus == S_CHARGING) { Set_Ocpp_StopReason(gunIndex, "Remote"); //Set_Connector_MiscCommand(gunIndex, MISC_CONN_REMOTE_STOP); chargingInfo[gunIndex]->ChargingStopFlag.bits.RemoteStop = true; LOG_INFO("********** OcppRemoteStop Gun %d **********", gunIndex + 1); } } if(Is_Ocpp_StartTransactionConf(gunIndex)) { char acceptId[128] = {0}; char status[32] = {0}; Get_Ocpp_StartTransaction_Status(gunIndex, status); Get_Ocpp_TransactionId(gunIndex, acceptId); Set_Deduct_TransactionId(gunIndex, atoi(acceptId)); Set_UserTransactionId(gunIndex, atoi(acceptId)); LOG_INFO("Gun %d OCPP Start Transaction %s, TransactionId [%s]", gunIndex + 1, status, acceptId); if(!Is_Ocpp_StartTransaction_Accepted(gunIndex)) { if(Is_Ocpp_StopOnInvalidId_Enable()) { if(Is_Invalid_StartTransactionId(gunIndex)) { chargingInfo[gunIndex]->ChargingStopFlag.bits.InvalidIdStop = true; LOG_INFO("Gun %d OCPP StopOnInvalidId", gunIndex + 1); } } LOG_INFO("Gun %d Transaction [%s] Not Accepted, %s", gunIndex + 1, acceptId, chargingInfo[gunIndex]->ChargingStopFlag.bits.InvalidIdStop > 0 ? "And Stop Charging" : "But StopOnInvalidId is Disable"); } Clean_Ocpp_StartTransactionConf(gunIndex); } } bool CheckBackendChargingTimeout(byte gunIndex) { bool result = false; if (ShmSysConfigAndInfo->SysConfig.AuthorisationMode == AUTH_MODE_ENABLE) { if (ShmSysConfigAndInfo->SysConfig.MaxChargingDuration > 0) { if (chargingInfo[gunIndex]->PresentChargedDuration >= (ShmSysConfigAndInfo->SysConfig.MaxChargingDuration * 60)) result = true; } } else if (ShmSysConfigAndInfo->SysConfig.AuthorisationMode == AUTH_MODE_DISABLE) { // 隨插即充電的要看 offline if (ShmSysConfigAndInfo->SysConfig.OfflineMaxChargeDuration > 0) { if (chargingInfo[gunIndex]->PresentChargedDuration >= (ShmSysConfigAndInfo->SysConfig.OfflineMaxChargeDuration * 60)) result = true; } } return result; } bool CheckBackendChargingEnergy(byte gunIndex) { bool result = false; if (ShmSysConfigAndInfo->SysConfig.AuthorisationMode == AUTH_MODE_ENABLE) { if (ShmSysConfigAndInfo->SysConfig.MaxChargingEnergy > 0) { if (chargingInfo[gunIndex]->PresentChargedEnergy >= ShmSysConfigAndInfo->SysConfig.MaxChargingEnergy) result = true; } } else if (ShmSysConfigAndInfo->SysConfig.AuthorisationMode == AUTH_MODE_DISABLE) { // 隨插即充電的要看 offline if (ShmSysConfigAndInfo->SysConfig.OfflineMaxChargeEnergy > 0) { if (chargingInfo[gunIndex]->PresentChargedEnergy >= (ShmSysConfigAndInfo->SysConfig.OfflineMaxChargeEnergy)) result = true; } } return result; } bool IsReachConfigMaxChargingSoc(byte gunIndex) { bool result = false; if(ShmSysConfigAndInfo->SysConfig.MaxChargingSoc > 0) { if(chargingInfo[gunIndex]->EvBatterySoc >= ShmSysConfigAndInfo->SysConfig.MaxChargingSoc) { LOG_INFO("Gun %d MaxChargingSoc: [%d%%] Stop", gunIndex + 1, ShmSysConfigAndInfo->SysConfig.MaxChargingSoc); result = true; } } return result; } bool CheckSessionTargetStop(byte gunIndex) { bool stop = false; struct StructSessionTarget target; Get_Ocpp_SessionTarget(gunIndex, &target); if(target.targetDuration > 0) { if(chargingInfo[gunIndex]->PresentChargedDuration >= (target.targetDuration * 60)) { LOG_INFO("Gun %d SessionTarget(Duration) Stop, Present: %d (sec), Target: %d (min)", gunIndex + 1, chargingInfo[gunIndex]->PresentChargedDuration, target.targetDuration); stop = true; } } if(target.targetSoc > 0) { if(chargingInfo[gunIndex]->EvBatterySoc >= target.targetSoc) { LOG_INFO("Gun %d SessionTarget(SOC) Stop, Present: %d (%%), Target: %d (%%)", gunIndex + 1, chargingInfo[gunIndex]->EvBatterySoc, target.targetSoc); stop = true; } } if(target.targetEnergy > 0) { if(chargingInfo[gunIndex]->PresentChargedEnergy >= target.targetEnergy) { LOG_INFO("Gun %d SessionTarget(Energy) Stop, Present: %8.3f (kWh), Target: %4d (kWh)", gunIndex + 1, chargingInfo[gunIndex]->PresentChargedEnergy, target.targetEnergy); stop = true; } } if(stop) { chargingInfo[gunIndex]->ChargingStopFlag.bits.SessionTargetStop = true; } return stop; } void InformOcppErrOccur(byte codeType) { char _error[25]; switch(codeType) { case 4: strcpy(_error, "InternalError"); break; case 6: strcpy(_error, "NoError"); break; case 7: strcpy(_error, "OtherError"); break; case 13: strcpy(_error, "UnderVoltage"); break; case 14: strcpy(_error, "OverVoltage"); break; } for (byte gun_index = 0; gun_index < ShmSysConfigAndInfo->SysConfig.TotalConnectorCount; gun_index++) { SetOcppErrorCode(gun_index, _error); } } void SetOcppErrorCode(unsigned char _index, char *errCode) { Set_Ocpp_StatusNotificationErrorCode(_index, errCode); strcpy((char *)_BackupStatusNotification[_index].ErrorCode, errCode); } void SetOcppVendorErrorCode(unsigned char _index, char *vendorCode) { Set_Ocpp_StatusNotificationVendorCode(_index, vendorCode); strcpy((char *)_BackupStatusNotification[_index].VendorErrorCode, vendorCode); } //=============================================== // SQLite3 related routine //=============================================== int NetworkDB_Open(sqlite3 *db) { int result = PASS; char* errMsg = NULL; char* createNerRecordSql="CREATE TABLE IF NOT EXISTS network_record(" "idx integer primary key AUTOINCREMENT, " "occurDatetime text NOT NULL, " "isInternet text NOT NULL, " "isOcppConnected text NOT NULL, " "isEth0Internet text NOT NULL, " "isMlan0Internet text NOT NULL, " "isPpp0Internet text NOT NULL, " "rssiMlan0 text NOT NULL, " "rssiPpp0 text NOT NULL" ");"; //sqlite3_config(SQLITE_CONFIG_URI, 1); if(sqlite3_open(NETWORK_DB_FILE, &db)) { result = FAIL; LOG_ERROR("Can't open database (Net) : %s", sqlite3_errmsg(db)); sqlite3_close(db); } else { LOG_INFO("Local network status record database open successfully."); if (sqlite3_exec(db, createNerRecordSql, 0, 0, &errMsg) != SQLITE_OK) { result = FAIL; LOG_ERROR("Create local network status record table error message: %s", errMsg); } else { LOG_INFO("Opened local network status record table successfully"); } sqlite3_close(db); } return result; } int DB_Open(sqlite3 *db) { int result = PASS; char* errMsg = NULL; char* createRecordSql="CREATE TABLE IF NOT EXISTS charging_record(" "idx integer primary key AUTOINCREMENT, " "reservationId text, " "transactionId text, " "startMethod text, " "userId text, " "dateTimeStart text, " "dateTimeStop text," "socStart text, " "socStop text, " "chargeEnergy text, " "stopReason text, " "connector INTEGER" ");"; char* createCfgSql="CREATE TABLE IF NOT EXISTS `config` ( " "`idx` INTEGER PRIMARY KEY AUTOINCREMENT, " "`IsAvailable` TEXT NOT NULL, " "`connector` INTEGER NOT NULL, " "`val` TEXT NOT NULL, unique(IsAvailable,connector) on conflict replace);"; char* creatererrecordSql="CREATE TABLE IF NOT EXISTS `event_record` ( " "`idx` INTEGER PRIMARY KEY AUTOINCREMENT, " "`occurDatetime` TEXT NOT NULL, " "`statusCode` TEXT NOT NULL, unique(occurDatetime,statusCode) on conflict replace);"; char* createrebootSql="CREATE TABLE IF NOT EXISTS `reboot_record` ( " "`idx` INTEGER PRIMARY KEY AUTOINCREMENT, " "`rebootDatetime` TEXT NOT NULL, " "`model_name` TEXT, " "`serial_number` TEXT, unique(rebootDatetime) on conflict replace);"; char * createconsumptionSql = "CREATE TABLE IF NOT EXISTS `power_consumption` ( " "`idx` INTEGER PRIMARY KEY AUTOINCREMENT, " "`connector` INTEGER NOT NULL, " "`val` TEXT NOT NULL, unique(connector) on conflict replace);"; char *createGunConsumptionSql = "CREATE TABLE IF NOT EXISTS `gun_consumption` ( " "`idx` INTEGER PRIMARY KEY AUTOINCREMENT, " "`connector` INTEGER NOT NULL, " "`val` TEXT NOT NULL, unique(connector) on conflict replace);"; char *createFinalCostSql = "CREATE TABLE IF NOT EXISTS `final_cost` ( " "idx integer primary key AUTOINCREMENT, " "gun text, " "transactionId text, " "occurDatetime text, " "updateDatetime text, " "description text, " "updateStatus integer" ");"; char *createOcmfRecordSql = "CREATE TABLE IF NOT EXISTS `ocmf_record` ( " "idx integer primary key AUTOINCREMENT, " "gun text, " "transactionId text, " "publicKey text, " "ocmfInfo text, " "updateStatus integer, " "occurDatetime text, " "updateDatetime text" ");"; if(sqlite3_open(DB_FILE, &db)) { result = FAIL; LOG_ERROR( "Can't open database: %s", sqlite3_errmsg(db)); sqlite3_close(db); } else { LOG_INFO( "Local charging record database open successfully."); if (sqlite3_exec(db, createRecordSql, 0, 0, &errMsg) != SQLITE_OK) { result = FAIL; LOG_ERROR( "Create local charging record table error message: %s", errMsg); } else { LOG_INFO( "Opened local charging record table successfully"); } if (sqlite3_exec(db, createCfgSql, 0, 0, &errMsg) != SQLITE_OK) { result = FAIL; LOG_ERROR( "Create local config table error message: %s", errMsg); } else { LOG_INFO( "Opened local config table successfully"); } if (sqlite3_exec(db, creatererrecordSql, 0, 0, &errMsg) != SQLITE_OK) { result = FAIL; LOG_ERROR( "Create local record table error message: %s", errMsg); } else { LOG_INFO( "Opened local record table successfully"); } if (sqlite3_exec(db, createrebootSql, 0, 0, &errMsg) != SQLITE_OK) { result = FAIL; LOG_ERROR( "Create reboot record table error message: %s", errMsg); } else { LOG_INFO( "Opened reboot record table successfully"); } if (sqlite3_exec(db, createconsumptionSql, 0, 0, &errMsg) != SQLITE_OK) { result = FAIL; LOG_ERROR( "Create power consumption record table error message: %s", errMsg); } else { LOG_INFO( "Opened power consumption record table successfully"); } if (sqlite3_exec(db, createGunConsumptionSql, 0, 0, &errMsg) != SQLITE_OK) { result = FAIL; LOG_ERROR( "Create gun consumption record table error message: %s", errMsg); } else { LOG_INFO( "Opened gun consumption record table successfully"); } if (sqlite3_exec(db, createFinalCostSql, 0, 0, &errMsg) != SQLITE_OK) { result = FAIL; LOG_ERROR( "Create final cost table error message: %s", errMsg); } else { LOG_INFO( "Opened final cost table successfully"); } if(sqlite3_exec(db, createOcmfRecordSql, 0, 0, &errMsg) != SQLITE_OK) { result = FAIL; LOG_ERROR("Create OCMF record table error message: %s", errMsg); } else { LOG_INFO("Opened OCMF record table successfully"); } sqlite3_close(db); } return result; } int DB_Insert_Record(sqlite3 *db, int gun_index) { int result = PASS; char* errMsg = NULL; char insertSql[1024]; char transactionId[128]; char reason[32]; Get_Ocpp_TransactionId(gun_index, transactionId); Get_Ocpp_StopReason(gun_index, reason); sprintf(insertSql, "insert into charging_record(reservationId, transactionId, startMethod, userId, dateTimeStart, dateTimeStop, socStart, socStop, chargeEnergy, stopReason, connector) " "values('%d', '%s', '%d', '%s', '%s', '%s', '%d', '%d', '%f', '%s', %d);", chargingInfo[gun_index]->ReservationId, transactionId, chargingInfo[gun_index]->StartMethod, chargingInfo[gun_index]->StartUserId, chargingInfo[gun_index]->StartDateTime, chargingInfo[gun_index]->StopDateTime, chargingInfo[gun_index]->EvBatteryStartSoc, chargingInfo[gun_index]->EvBatterySoc, chargingInfo[gun_index]->PresentChargedEnergy, reason, gun_index + 1); if(sqlite3_open(DB_FILE, &db)) { result = FAIL; LOG_ERROR("Can't open database: %s", sqlite3_errmsg(db)); sqlite3_close(db); } else { //LOG_INFO( "Local charging record database open successfully."); if (sqlite3_exec(db, insertSql, 0, 0, &errMsg) != SQLITE_OK) { result = FAIL; LOG_ERROR("Insert local charging record error message: %s", errMsg); } else { //LOG_INFO("Insert local charging record successfully"); } sprintf(insertSql, "delete from charging_record where idx < (select idx from charging_record order by idx desc limit 1)-2000;"); if (sqlite3_exec(db, insertSql, 0, 0, &errMsg) != SQLITE_OK) { result = FAIL; LOG_ERROR("delete local charging error message: %s", errMsg); } else { //LOG_INFO("delete local charging record successfully"); } sqlite3_close(db); } return result; } int DB_Update_Operactive(sqlite3 *db, uint8_t gun_index, uint8_t IsAvailable) { uint8_t result = false; char* errMsg = NULL; char sqlStr[1024]; srand(time(NULL)); if(sqlite3_open(DB_FILE, &db)) { result = FAIL; LOG_ERROR( "Can't open database: %s", sqlite3_errmsg(db)); sqlite3_close(db); } else { LOG_INFO( "Local charging record database open successfully (%d).", IsAvailable); sprintf(sqlStr, "insert or replace into config (IsAvailable, connector, val) values('IsAvailable', %d, %d);", gun_index, IsAvailable); LOG_INFO("sqlStr= %s", sqlStr); if (sqlite3_exec(db, sqlStr, 0, 0, &errMsg) != SQLITE_OK) { result = FAIL; LOG_INFO( "update config error message: %s", errMsg); } else { LOG_INFO("update connector-%d config item isOperactive to %d", gun_index, IsAvailable); } sqlite3_close(db); } return result; } int DB_Get_Operactive(sqlite3 *db, uint8_t gun_index) { uint8_t result = true; char* errMsg = NULL; char sqlStr[1024]; char **rs; int rows, cols; sprintf(sqlStr, "select * from config where IsAvailable='IsAvailable' and connector=%d;", gun_index); //DEBUG_INFO("sqlStr= %s\r\n", sqlStr); if(sqlite3_open(DB_FILE, &db)) { result = FAIL; LOG_ERROR( "Can't open database: %s", sqlite3_errmsg(db)); sqlite3_close(db); } else { LOG_INFO( "Local config query database open successfully."); sqlite3_get_table(db, sqlStr, &rs, &rows, &cols, &errMsg); if(rows>0) { for(int idxRow=1;idxRow<=rows;idxRow++) { if(strcmp(rs[(idxRow*cols)+3], "0") == 0) { result = false; } LOG_INFO("Query connector-%d isOperactive: %s", gun_index, rs[(idxRow*cols)+3]); } } else { LOG_INFO("Query connector-%d fail, set default value to operactive.", gun_index); } sqlite3_free_table(rs); sqlite3_close(db); } return result; } void DB_Update_LocalConsumption(sqlite3 *db, uint8_t gun_index, float value) { char* errMsg = NULL; char sqlStr[1024]; srand(time(NULL)); if(sqlite3_open(DB_FILE, &db)) { LOG_ERROR("Can't open database: %s", sqlite3_errmsg(db)); sqlite3_close(db); } else { sprintf(sqlStr, "insert or replace into power_consumption (connector, val) values(%d, %f);", gun_index, value); if (sqlite3_exec(db, sqlStr, 0, 0, &errMsg) != SQLITE_OK) { LOG_ERROR("update power_consumption error message: %s", errMsg); } else { //LOG_INFO("update connector-%d power_consumption item consumption to %f \r\n", gun_index, value); } sqlite3_close(db); } } void DB_Update_GunConsumption(sqlite3 *db, uint8_t gun_index, float value) { char* errMsg = NULL; char sqlStr[1024]; srand(time(NULL)); if(sqlite3_open(DB_FILE, &db)) { LOG_ERROR("Can't open database: %s", sqlite3_errmsg(db)); sqlite3_close(db); } else { sprintf(sqlStr, "insert or replace into gun_consumption (connector, val) values(%d, %f);", gun_index, value); if (sqlite3_exec(db, sqlStr, 0, 0, &errMsg) != SQLITE_OK) { LOG_ERROR("update gun_consumption error message: %s", errMsg); } else { //LOG_INFO("update connector-%d power_consumption item consumption to %f \r\n", gun_index, value); } sqlite3_close(db); } } float DB_Get_LocalConsumption(sqlite3 *db, uint8_t gun_index) { float result = 0; char* errMsg = NULL; char sqlStr[1024]; char **rs; int rows, cols; sprintf(sqlStr, "select * from power_consumption where connector=%d;", gun_index); if (sqlite3_open(DB_FILE, &db)) { result = FAIL; LOG_ERROR("Can't open database: %s", sqlite3_errmsg(db)); sqlite3_close(db); } else { //LOG_INFO("Local config query database open successfully."); sqlite3_get_table(db, sqlStr, &rs, &rows, &cols, &errMsg); if (rows > 0) { for (int idxRow = 1; idxRow <= rows; idxRow++) { result = atof(rs[(idxRow * cols) + 2]); } } else { LOG_INFO("Query connector-%d fail, set default value to consumption.", gun_index); } sqlite3_free_table(rs); sqlite3_close(db); } return result; } float DB_Get_GunConsumption(sqlite3 *db, uint8_t gun_index) { float result = 0; char* errMsg = NULL; char sqlStr[1024]; char **rs; int rows, cols; sprintf(sqlStr, "select * from gun_consumption where connector=%d;", gun_index); if (sqlite3_open(DB_FILE, &db)) { result = FAIL; LOG_ERROR("Can't open database: %s", sqlite3_errmsg(db)); sqlite3_close(db); } else { //LOG_INFO("Local config query database open successfully."); sqlite3_get_table(db, sqlStr, &rs, &rows, &cols, &errMsg); if (rows > 0) { for (int idxRow = 1; idxRow <= rows; idxRow++) { result = atof(rs[(idxRow * cols) + 2]); } } else { LOG_INFO("Query gun %d fail, set -1 to gun consumption.", gun_index + 1); result = -1; } sqlite3_free_table(rs); sqlite3_close(db); } return result; } float Get_PowerConsumption(uint8_t gun_index) { float value = 0; //value = ShmChargerInfo->MeterValue[gun_index].GunConsumption >= 0 ? // ShmChargerInfo->MeterValue[gun_index].GunConsumption : ShmChargerInfo->MeterValue[gun_index].LocalConsumption; if(ShmChargerInfo->MeterValue[gun_index].GunConsumption >= 0) { if(!_useGunMeterValue[gun_index]) { LOG_INFO("***** Gun %d Use GunMeterValue *****", gun_index + 1); } _useGunMeterValue[gun_index] = true; value = ShmChargerInfo->MeterValue[gun_index].GunConsumption; } else { value = ShmChargerInfo->MeterValue[gun_index].LocalConsumption; } return value; } void Update_PowerConsumption(uint8_t gun_index) { chargingInfo[gun_index]->PowerConsumption = Get_PowerConsumption(gun_index); } int DB_Insert_FinalCost(sqlite3 *db, uint8_t gun_index, int txId, char *description) { char timeBuf[32]; int result = PASS; char* errMsg = NULL; char insertSql[1024]; getNowDatetime((unsigned char *)timeBuf); sprintf(insertSql, "insert into final_cost(gun, transactionId, occurDatetime, updateDatetime, description, updateStatus) " "values('%d', '%d', '%s', '%s', '%s', '%d');", gun_index + 1, txId, timeBuf, "", description, BILL_SATAUS_UNDISPOSED); if(sqlite3_open(DB_FILE, &db)) { result = FAIL; LOG_ERROR("Can't open database: %s", sqlite3_errmsg(db)); sqlite3_close(db); } else { //LOG_INFO("FinalCost database open successfully."); if (sqlite3_exec(db, insertSql, 0, 0, &errMsg) != SQLITE_OK) { result = FAIL; LOG_ERROR("Insert final_cost error message: %s", errMsg); } else { //LOG_INFO("Insert final_cost successfully"); } sprintf(insertSql, "delete from final_cost where idx < (select idx from final_cost order by idx desc limit 1)-2000;"); if (sqlite3_exec(db, insertSql, 0, 0, &errMsg) != SQLITE_OK) { result = FAIL; LOG_ERROR("delete final_cost error message: %s", errMsg); } else { //LOG_INFO("delete final_cost successfully"); } sqlite3_close(db); } return result; } int DB_Update_FinalCost_Status(sqlite3 *db, int txId, int status) { char timeBuf[32]; int result = PASS; char* errMsg = NULL; char updateSql[1024]; getNowDatetime((unsigned char *)timeBuf); sprintf(updateSql, "update final_cost set updateStatus = %d, updateDatetime = '%s' where transactionId = '%d';", status, timeBuf, txId); if(sqlite3_open(DB_FILE, &db)) { result = FAIL; LOG_ERROR("Can't open database: %s", sqlite3_errmsg(db)); sqlite3_close(db); } else { if(sqlite3_exec(db, updateSql, 0, 0, &errMsg) != SQLITE_OK) { LOG_ERROR("update final_cost status error message: %s", errMsg); result = FAIL; } else { //LOG_INFO("update final_cost txId[%d] status %d ok", txId, status); } sqlite3_close(db); } return result; } int DB_Get_Undisposed_FinalCost(sqlite3 *db, int gunIndex, char *costString) { int txId = -1; char **rs; int rows, cols; char* errMsg = NULL; char sqlString[1024]; sprintf(sqlString, "select * from final_cost where updateStatus = -1 and gun = '%d' order by idx asc limit 1;", gunIndex + 1); if(sqlite3_open(DB_FILE, &db)) { LOG_ERROR("Can't open database: %s", sqlite3_errmsg(db)); sqlite3_close(db); } else { sqlite3_get_table(db, sqlString, &rs, &rows, &cols, &errMsg); if(rows > 0) { for(int idxRow = 1; idxRow <= rows; idxRow++) { txId = atoi(rs[(idxRow * cols) + 2]); strcpy(costString, rs[(idxRow * cols) + 5]); } } sqlite3_free_table(rs); sqlite3_close(db); } return txId; } void CheckInProgress(uint8_t gun_index) { if((ShmChargerInfo->Connector[gun_index].Status > S_IDLE && ShmChargerInfo->Connector[gun_index].Status <= S_FAULT) || (ShmChargerInfo->Connector[gun_index].Status >= S_CCS_PRECHARGE_ST0 && ShmChargerInfo->Connector[gun_index].Status <= S_CCS_PRECHARGE_ST1)) { if(chargingInfo[gun_index]->InProgress == NO) { LOG_INFO("Gun %d In Progress", gun_index + 1); } chargingInfo[gun_index]->InProgress = YES; } else { if(chargingInfo[gun_index]->InProgress == YES) { LOG_INFO("Gun %d Real Idle", gun_index + 1); } chargingInfo[gun_index]->InProgress = NO; } } void CheckDebugMode(uint8_t gun_index) { if(ShmChargerInfo->Control.RelayCtrl.bits.AbnormalRelay) { if(chargingInfo[gun_index]->SystemStatus != S_DEBUG) { setChargerMode(gun_index, MODE_DEBUG); } } } int DB_Reboot_Record(sqlite3 *db) { int result = PASS; char* errMsg = NULL; char insertSql[256]; sprintf(insertSql, "insert into reboot_record(rebootDatetime, model_name, serial_number) values(CURRENT_TIMESTAMP, '%s', '%s');", (char *)ShmSysConfigAndInfo->SysConfig.ModelName, (char *)ShmSysConfigAndInfo->SysConfig.SerialNumber); if(sqlite3_open(DB_FILE, &db)) { result = FAIL; LOG_ERROR("Can't open database: %s", sqlite3_errmsg(db)); sqlite3_close(db); } else { LOG_INFO("Local charging record database open successfully."); if (sqlite3_exec(db, insertSql, 0, 0, &errMsg) != SQLITE_OK) { result = FAIL; LOG_ERROR("Insert reboot record error message: %s", errMsg); } else { //LOG_INFO("Insert reboot record successfully"); } sprintf(insertSql, "delete from reboot_record where idx < (select idx from reboot_record order by idx desc limit 1)-2000;"); if (sqlite3_exec(db, insertSql, 0, 0, &errMsg) != SQLITE_OK) { result = FAIL; LOG_ERROR("delete reboot record error message: %s", errMsg); } else { //LOG_INFO("delete reboot record successfully"); } sqlite3_close(db); } return result; } int DB_Insert_Ocmf(sqlite3 *db, int gun_index, char *txId, char *ocmfKey, char *ocmfInfo) { char timeBuf[32]; int result = PASS; char* errMsg = NULL; char insertSql[3072]; getNowDatetime((unsigned char *)timeBuf); sprintf(insertSql, "insert into ocmf_record(gun, transactionId, publicKey, ocmfInfo, updateStatus, occurDatetime, updateDatetime) " "values('%d', '%s', '%s', '%s', '%d', '%s', '%s');", gun_index + 1, txId, ocmfKey, ocmfInfo, OCMF_SATAUS_INSERTED, timeBuf, ""); if(sqlite3_open(DB_FILE, &db)) { result = FAIL; LOG_ERROR("Can't open database: %s", sqlite3_errmsg(db)); sqlite3_close(db); } else { //LOG_INFO("OCMF database open successfully."); if (sqlite3_exec(db, insertSql, 0, 0, &errMsg) != SQLITE_OK) { result = FAIL; LOG_ERROR("Insert ocmf_record error message: %s", errMsg); } else { //LOG_INFO("Insert ocmf_record successfully"); } sprintf(insertSql, "delete from ocmf_record where idx < (select idx from ocmf_record order by idx desc limit 1)-2000;"); if (sqlite3_exec(db, insertSql, 0, 0, &errMsg) != SQLITE_OK) { result = FAIL; LOG_ERROR("delete ocmf_record error message: %s", errMsg); } else { //LOG_INFO("delete ocmf_record successfully"); } sqlite3_close(db); } return result; } int DB_Update_Ocmf_Status(sqlite3 *db, char *txId, int status) { char timeBuf[32]; int result = PASS; char* errMsg = NULL; char updateSql[1024]; getNowDatetime((unsigned char *)timeBuf); sprintf(updateSql, "update ocmf_record set updateStatus = %d, updateDatetime = '%s' where transactionId = '%s';", status, timeBuf, txId); if(sqlite3_open(DB_FILE, &db)) { result = FAIL; LOG_ERROR("Can't open database: %s", sqlite3_errmsg(db)); sqlite3_close(db); } else { if(sqlite3_exec(db, updateSql, 0, 0, &errMsg) != SQLITE_OK) { LOG_ERROR("update updateStatus status error message: %s", errMsg); result = FAIL; } else { //LOG_INFO("update updateStatus txId[%s] status %d ok", txId, status); } sqlite3_close(db); } return result; } // return YES if exist undisposed ocmf int DB_Get_Undisposed_Ocmf(sqlite3 *db, int *gunIndex, char *txId, char *ocmfKey, char *ocmfInfo) { char **rs; int rows, cols; char* errMsg = NULL; char sqlString[1024]; int result = NO; sprintf(sqlString, "select * from ocmf_record where updateStatus = 0 order by idx asc limit 1;"); if(sqlite3_open(DB_FILE, &db)) { LOG_ERROR("Can't open database: %s", sqlite3_errmsg(db)); sqlite3_close(db); } else { sqlite3_get_table(db, sqlString, &rs, &rows, &cols, &errMsg); if(rows > 0) { for(int idxRow = 1; idxRow <= rows; idxRow++) { *gunIndex = atoi(rs[(idxRow * cols + 1)]) - 1; strncpy(txId, rs[(idxRow * cols) + 2], 36); strncpy(ocmfKey, rs[(idxRow * cols) + 3], 200); strcpy(ocmfInfo, rs[(idxRow * cols) + 4]); } result = YES; } sqlite3_free_table(rs); sqlite3_close(db); } return result; } void DB_TryAddRebootRecordColumn(sqlite3 *db) { char **rs; int rows, cols; char* errMsg = NULL; char sqlString[1024]; int result = 0; strcpy(sqlString, "select count(*) from pragma_table_info('reboot_record') where name = 'model_name';"); if(sqlite3_open(DB_FILE, &db)) { LOG_ERROR("Can't open database: %s", sqlite3_errmsg(db)); sqlite3_close(db); } else { sqlite3_get_table(db, sqlString, &rs, &rows, &cols, &errMsg); if(rows > 0) { for(int idxRow = 1; idxRow <= rows; idxRow++) { result = atoi(rs[(idxRow * cols) + 0]); } } sqlite3_free_table(rs); if(result == 0) { strcpy(sqlString, "ALTER TABLE 'reboot_record' ADD COLUMN 'model_name' TEXT;"); if(sqlite3_exec(db, sqlString, 0, 0, &errMsg) != SQLITE_OK) { result = FAIL; LOG_ERROR("reboot_record add column 'model_name' error message: %s", errMsg); } else { LOG_INFO("reboot_record ADD COLUMN 'model_name' successfully"); } strcpy(sqlString, "ALTER TABLE 'reboot_record' ADD COLUMN 'serial_number' TEXT;"); if(sqlite3_exec(db, sqlString, 0, 0, &errMsg) != SQLITE_OK) { result = FAIL; LOG_ERROR("reboot_record add column 'serial_number' error message: %s", errMsg); } else { LOG_INFO("reboot_record ADD COLUMN 'serial_number' successfully"); } } sqlite3_close(db); } } void DB_TryAddChargingRecordColumn(sqlite3 *db) { char **rs; int rows, cols; char* errMsg = NULL; char sqlString[1024]; int result = 0; strcpy(sqlString, "select count(*) from pragma_table_info('charging_record') where name = 'connector';"); if(sqlite3_open(DB_FILE, &db)) { LOG_ERROR("Can't open database: %s", sqlite3_errmsg(db)); sqlite3_close(db); } else { sqlite3_get_table(db, sqlString, &rs, &rows, &cols, &errMsg); if(rows > 0) { for(int idxRow = 1; idxRow <= rows; idxRow++) { result = atoi(rs[(idxRow * cols) + 0]); } } sqlite3_free_table(rs); if(result == 0) { strcpy(sqlString, "ALTER TABLE 'charging_record' ADD COLUMN 'connector' INTEGER;"); if(sqlite3_exec(db, sqlString, 0, 0, &errMsg) != SQLITE_OK) { result = FAIL; LOG_ERROR("charging_record add column connector error message: %s", errMsg); } else { LOG_INFO("charging_record ADD COLUMN connector successfully"); } } sqlite3_close(db); } } //=============================================== // Config process //=============================================== void AddPlugInTimes(byte gunIndex) { if (chargingInfo[gunIndex]->Type == _Type_Chademo) ShmSysConfigAndInfo->SysConfig.ChademoPlugInTimes += 1; else if(chargingInfo[gunIndex]->Type == _Type_CCS_2) ShmSysConfigAndInfo->SysConfig.Ccs2PlugInTimes += 1; else if(chargingInfo[gunIndex]->Type == _Type_GB) ShmSysConfigAndInfo->SysConfig.GbPlugInTimes += 1; } void ChangeStartOrStopDateTime(byte isStart, byte gunIndex) { char cmdBuf[32]; struct timeb csuTime; struct tm *tmCSU; ftime(&csuTime); tmCSU = localtime(&csuTime.time); sprintf(cmdBuf, "%04d-%02d-%02d %02d:%02d:%02d", tmCSU->tm_year + 1900, tmCSU->tm_mon + 1, tmCSU->tm_mday, tmCSU->tm_hour, tmCSU->tm_min, tmCSU->tm_sec); if (isStart) strcpy((char *)chargingInfo[gunIndex]->StartDateTime, cmdBuf); else strcpy((char *)chargingInfo[gunIndex]->StopDateTime, cmdBuf); } void zipLogFiles() { const char* logPath = "/Storage/SystemLog"; // 獲取目錄 DIR* pDir = opendir(logPath); if (pDir != NULL) { struct timeb csuTime; struct tm *tmCSU; ftime(&csuTime); tmCSU = localtime(&csuTime.time); // LOG_INFO("Time : %04d-%02d-%02d %02d:%02d:%02d \n", tmCSU->tm_year + 1900, // tmCSU->tm_mon + 1, tmCSU->tm_mday, tmCSU->tm_hour, tmCSU->tm_min, // tmCSU->tm_sec); // Read items inside the folder struct dirent* pEntry = NULL; while ((pEntry = readdir(pDir)) != NULL) { if (strcmp(pEntry->d_name, ".") != 0 && strcmp(pEntry->d_name, "..") != 0 && strncmp(pEntry->d_name, "[", 1) == 0 && strstr(pEntry->d_name, "tar") < 0) { char yearC[5]; unsigned short year = 0; char monthC[3]; unsigned short month = 0; yearC[4] = '\0'; strncpy(yearC, pEntry->d_name + 1, 4); monthC[2] = '\0'; strncpy(monthC, pEntry->d_name + 6, 2); year = atoi(yearC); month = atoi(monthC); if (year != 0) { if (year < tmCSU->tm_year + 1900 || (year >= tmCSU->tm_year + 1900 && month < tmCSU->tm_mon + 1)) { LOG_INFO("tar file name : %s", pEntry->d_name); char file[256]; memset(file, 0x00, sizeof(file)); strcat(file, "tar zcvf "); strcat(file, logPath); strncat(file, "/", 1); strcat(file, pEntry->d_name); strcat(file, ".tar"); strncat(file, " ", 1); strcat(file, logPath); strncat(file, "/", 1); strcat(file, pEntry->d_name); LOG_INFO("zip = %s \n", file); system(file); } } } } } // Close folder closedir(pDir); } void StopProcessingLoop() { for (;;) { CheckFactoryConfigFunction(); CheckFwUpdateFunction(); if (ShmSysConfigAndInfo->SysWarningInfo.Level == 2) { ChkPrimaryStatus(); if (ShmSysConfigAndInfo->SysWarningInfo.Level == 0) { LOG_INFO("Soft reboot for retry self-tets (Primary)."); KillAllTask(); sleep(3); TryCloseWatchdog(); system("/usr/bin/run_evse_restart.sh"); return; } } if(Is_Ocpp_ResetReq()) { if(Chk_Ocpp_Reset_Type("Hard") || Chk_Ocpp_Reset_Type("Immediate")) { ShmChargerInfo->Control.SysCtrl.bits.NeedHardReset = true; } if(Chk_Ocpp_Reset_Type("Soft") || Chk_Ocpp_Reset_Type("OnIdle")) { ShmChargerInfo->Control.SysCtrl.bits.NeedSoftReset = true; } } CheckSoftHardReset(); sleep(1); } } void CreateWatchdog(void) { wtdFd = InitWatchDog(); if(wtdFd < 0) { LOG_INFO("Watchdog Initial Fail"); ShmStatusCodeData->AlarmCode.AlarmEvents.bits.CsuInitFailed = 1; } else { LOG_INFO("Watchdog Initial Success"); } } void TryCloseWatchdog(void) { if(wtdFd > 0) { write(wtdFd, "V", 1); close(wtdFd); } } void TryFeedWatchdog(void) { if(wtdFd > 0) { write(wtdFd, "a", 1); } } bool IsParallelCabinetIdle(void) { bool result = true; if(ShmChargerInfo->Control.CabinetRole == _CROLE_SLAVE) { result = false; } return result; } bool IsStandbyEnable(void) { bool result = true; if(ShmChargerInfo->Control.CustomizedInfo.Flag.bits.StandbyTimeDisableForTcc) { time_t timep; struct tm *tm; time(&timep); timep += (ShmChargerInfo->CabinetMiscValue.TimeOffset * 60); tm = localtime(&timep); if(tm->tm_hour >= 0 && tm->tm_hour < 8) { if(!_isStandbyEnable) { LOG_INFO("[TCC]Customer Enable Standby Function This Time[%02d:%02d:%02d], Offset[%d]", tm->tm_hour, tm->tm_min, tm->tm_sec, ShmChargerInfo->CabinetMiscValue.TimeOffset); } _isStandbyEnable = true; result = true; } else { if(_isStandbyEnable) { LOG_INFO("[TCC]Customer Disable Standby Function This Time[%02d:%02d:%02d], Offset[%d]", tm->tm_hour, tm->tm_min, tm->tm_sec, ShmChargerInfo->CabinetMiscValue.TimeOffset); } _isStandbyEnable = false; result = false; } } if(ShmChargerInfo->Control.CustomizedInfo.Flag.bits.StandbyTimeDisable) { result = false; } return result; } bool IsGunIdle(int gunIndex, int idleType) { bool idle = true; if(chargingInfo[gunIndex]->SystemStatus == S_IDLE && chargingInfo[gunIndex]->ConnectorPlugIn && idleType == GUN_IDLE_TYPE_WHOLE) { idle = false; } else if (chargingInfo[gunIndex]->SystemStatus != S_IDLE && chargingInfo[gunIndex]->SystemStatus != S_RESERVATION && chargingInfo[gunIndex]->SystemStatus != S_FAULT && chargingInfo[gunIndex]->SystemStatus != S_MAINTAIN) { idle = false; } return idle; } bool IsDispenserIdle(int dispenserIndex) { bool dispenserIdle = true; for(int i = 0; i < ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[dispenserIndex].ConnectorQuantity; i++) { int gun = ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[dispenserIndex].ConnectorID[i] - 1; if(!IsGunIdle(gun, GUN_IDLE_TYPE_NORMAL)) { dispenserIdle = false; break; } } return dispenserIdle; } bool IsConnectorWholeIdle(void) { bool result = true; for (byte count = 0; count < ShmSysConfigAndInfo->SysConfig.TotalConnectorCount; count++) { if(!IsGunIdle(count, GUN_IDLE_TYPE_WHOLE)) { result = false; break; } } return result; } bool IsUpgradeAvailable(void) { bool result = true; for(int count = 0; count < ShmSysConfigAndInfo->SysConfig.TotalConnectorCount; count++) { if(!IsGunIdle(count, GUN_IDLE_TYPE_NORMAL)) { result = false; break; } } return result; } void ClearAlarmCodeWhenAcOff() { if (!ShmSysConfigAndInfo->SysInfo.AcContactorStatus) { ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuNoResource = NO; } } //========================================== // Check task processing //========================================== void CheckTask() { if(ShmSysConfigAndInfo->SysConfig.ModelName[10] == 'T' || ShmSysConfigAndInfo->SysConfig.ModelName[10] == 'D') { if(ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomEnabled == YES) { if(system("pidof -s Module_4g > /dev/null") != 0 && ShmChargerInfo->Control.SysCtrl.bits.Wifi4gResetEnable == false) { LOG_ERROR("Module_4g not running, restart it."); system("/root/Module_4g &"); } } } if(ShmSysConfigAndInfo->SysConfig.ModelName[10] == 'W' || ShmSysConfigAndInfo->SysConfig.ModelName[10] == 'D') { if(ShmSysConfigAndInfo->SysConfig.AthInterface.WifiMode != _SYS_WIFI_MODE_DISABLE) { if(system("pidof -s Module_Wifi > /dev/null") != 0 && ShmChargerInfo->Control.SysCtrl.bits.Wifi4gResetEnable == false) { LOG_ERROR("Module_Wifi not running, restart it."); system("/root/Module_Wifi &"); } } } if(ShmChargerInfo->Control.CabinetRole != _CROLE_SLAVE && strcmp((char *)ShmSysConfigAndInfo->SysConfig.OcppServerURL, "") != EQUAL && strcmp((char *)ShmSysConfigAndInfo->SysConfig.ChargeBoxId, "") != EQUAL) { ShmChargerInfo->Control.SysCtrl.bits.BackendEnable = true; if((time((time_t*)NULL) - Get_Ocpp_procDogTime()) > 180) { LOG_ERROR("OcppBackend watch dog timeout task restart."); Clean_Ocpp_procDogTime(); Kill_Ocpp_Service(); } if(!Is_Ocpp_Task_Alive()) { LOG_ERROR("OcppBackend not running, restart it."); Run_Ocpp_Service(); } } else { ShmChargerInfo->Control.SysCtrl.bits.BackendEnable = false; } if(ShmChargerInfo->Control.CabinetRole != _CROLE_SLAVE && strcmp((char *)ShmSysConfigAndInfo->SysConfig.MaintainServerURL, "") != EQUAL) { if(!Is_MaintainOcpp_Task_Alive()) { LOG_ERROR("Maintain Backend not running, restart it."); Run_MaintainOcpp_Service(); } } if(system("pidof -s Module_ProduceUtils > /dev/null") != 0) { LOG_ERROR("Module_ProduceUtils not running, restart it."); system ("/root/Module_ProduceUtils &"); } if(system("pidof -s Module_EvComm > /dev/null") != 0) { LOG_ERROR("Module_EvComm not running, restart it."); system ("/root/Module_EvComm &"); } if(system("pidof -s Module_InternalComm > /dev/null") != 0) { LOG_ERROR("Module_InternalComm not running, restart it."); system ("/root/Module_InternalComm &"); //ShmChargerInfo->Control.SysCtrl.bits.NeedSoftReset = true; } if(!Is_WebServer_Alive()) { LOG_ERROR("lighttpd not running, restart it."); Run_WebServer_Service(); } if(ShmSysConfigAndInfo->SysConfig.isEnableLocalPowerSharing > _SYS_POWER_SHARING_MODE_DISABLE) { if(!Is_LocalPowerSharing_Alive()) { LOG_ERROR("Module_PowerSharing not running, restart it."); Run_LocalPowerSharing_Service(); } } } void InitialDHCP() { char tmpbuf[256]; memset(tmpbuf,0,256); system("pgrep -f \"udhcpc -i eth0\" | xargs kill"); sprintf(tmpbuf, "/sbin/udhcpc -i eth0 -x hostname:CSU3_%s -s /root/dhcp_script/eth0.script > /dev/null &", ShmSysConfigAndInfo->SysConfig.SystemId); system(tmpbuf); } void InitialDispenserDhcpServerConfig(void) { system("echo 'start 192.168.100.10' > /etc/udhcpd_eth1.conf"); system("echo 'end 192.168.100.20' >> /etc/udhcpd_eth1.conf"); system("echo 'interface eth1' >> /etc/udhcpd_eth1.conf"); system("echo 'opt dns 8.8.8.8' >> /etc/udhcpd_eth1.conf"); system("echo 'option subnet 255.255.255.0' >> /etc/udhcpd_eth1.conf"); system("echo 'opt router 192.168.100.1' >> /etc/udhcpd_eth1.conf"); system("echo 'option domain local' >> /etc/udhcpd_eth1.conf"); system("echo 'option lease 86400' >> /etc/udhcpd_eth1.conf"); usleep(1000); } void StartDispenserDhcpServer(void) { system("pgrep -f \"udhcpd /etc/udhcpd_eth1.conf\" | xargs kill"); system("/usr/sbin/udhcpd /etc/udhcpd_eth1.conf > /dev/null &"); } //========================================== // Check Smart Charging Profile //========================================== void Ocpp_ProfileReq_Cmd(byte gunIndex) { if(!Is_Ocpp_ChargingProfileConf(gunIndex)) { if(!Is_Ocpp_ChargingProfileReq(gunIndex)) { Set_Ocpp_ChargingProfileReq(gunIndex); } } } int GetStartScheduleTime(unsigned char *time) { int result = -1; struct tm tmScheduleStart; struct timeb tbScheduleStart; if((sscanf((char *)time, "%4d-%2d-%2dT%2d:%2d:%2d", &tmScheduleStart.tm_year, &tmScheduleStart.tm_mon, &tmScheduleStart.tm_mday, &tmScheduleStart.tm_hour, &tmScheduleStart.tm_min, &tmScheduleStart.tm_sec) == 6)) { tmScheduleStart.tm_year -= 1900; tmScheduleStart.tm_mon -= 1; tbScheduleStart.time = mktime(&tmScheduleStart); tbScheduleStart.millitm = 0; result = DiffTimebWithNow(tbScheduleStart) / 1000; } return result; } void Ocpp_ChargingProfile_Process(byte _index) { int _startCount = NO_DEFINE; int _maxCount = 0; float _limit = 0; int _numberPhases = 0; if(Is_Ocpp_ChargingProfileKind(_index, "Absolute") && Is_Ocpp_ChargingProfileId(_index)) { _maxCount = Get_Ocpp_ChargingProfileScheduleCount(_index); _startCount = Get_Ocpp_ChargingProfileStartIndex(_index); if(_startCount < _maxCount) { _limit = Get_Ocpp_ChargingProfileScheduleLimit(_index, _startCount); _numberPhases = Get_Ocpp_ChargingProfileScheduleNumberPhases(_index, _startCount); chargingInfo[_index]->ChargingProfilePower = _limit * AC_OUTPUT_VOL * _numberPhases; if(chargingInfo[_index]->EvBatterytargetVoltage > 0 && (int)chargingInfo[_index]->PresentChargingVoltage > 0) { chargingInfo[_index]->ChargingProfileCurrent = (chargingInfo[_index]->ChargingProfilePower / chargingInfo[_index]->PresentChargingVoltage) * 10; } else { chargingInfo[_index]->ChargingProfileCurrent = -1; } } else { chargingInfo[_index]->ChargingProfilePower = -1; chargingInfo[_index]->ChargingProfileCurrent = -1; } } else { chargingInfo[_index]->ChargingProfilePower = -1; chargingInfo[_index]->ChargingProfileCurrent = -1; } if((int)_lastProfilePower[_index] != (int)chargingInfo[_index]->ChargingProfilePower || (int)_lastProfileCurrent[_index] != (int)chargingInfo[_index]->ChargingProfileCurrent) { _limit = Get_Ocpp_ChargingProfileScheduleLimit(_index, _startCount); LOG_INFO("Gun %d Get Profile - Index = %d, Limit = %f", _index + 1, _startCount, _limit); LOG_INFO("Max: %d kW, Gun %d ChargingProfile Power = %d, Current = %d", ShmSysConfigAndInfo->SysInfo.MaxChargingProfilePower == -1 ? (int)ShmSysConfigAndInfo->SysInfo.MaxChargingProfilePower : ((int)ShmSysConfigAndInfo->SysInfo.MaxChargingProfilePower / 1000), _index + 1, (int)chargingInfo[_index]->ChargingProfilePower, (int)chargingInfo[_index]->ChargingProfileCurrent); } _lastProfilePower[_index] = chargingInfo[_index]->ChargingProfilePower; _lastProfileCurrent[_index] = chargingInfo[_index]->ChargingProfileCurrent; } void Ocpp_MaxChargingProfile_Process(void) { int _startCount = NO_DEFINE; int _maxCount = 0; float _limit = 0; int _numberPhases = 0; if(Is_Ocpp_MaxChargingProfileKind("Absolute") && Is_Ocpp_MaxChargingProfileId()) { _maxCount = Get_Ocpp_MaxProfileScheduleCount(); _startCount = Get_Ocpp_MaxProfileStartIndex(); if(_startCount < _maxCount) { _limit = Get_Ocpp_MaxProfileScheduleLimit(_startCount); _numberPhases = Get_Ocpp_MaxProfileScheduleNumberPhases(_startCount); ShmSysConfigAndInfo->SysInfo.MaxChargingProfilePower = _limit * AC_OUTPUT_VOL * _numberPhases; } else { ShmSysConfigAndInfo->SysInfo.MaxChargingProfilePower = -1; } } else { ShmSysConfigAndInfo->SysInfo.MaxChargingProfilePower = -1; } if((int)_lastMaxProfilePower != (int)ShmSysConfigAndInfo->SysInfo.MaxChargingProfilePower) { _limit = Get_Ocpp_MaxProfileScheduleLimit(_startCount); LOG_INFO("Charger Get Max Profile - Index = %d, Limit = %f", _startCount, _limit); LOG_INFO("Charger Max Profile Power = %d", (int)ShmSysConfigAndInfo->SysInfo.MaxChargingProfilePower); } _lastMaxProfilePower = ShmSysConfigAndInfo->SysInfo.MaxChargingProfilePower; } void CheckSmartChargeProfile(byte _index) { if(Is_Ocpp_ChargingProfileConf(_index)) { Clean_Ocpp_ChargingProfileConf(_index); Ocpp_MaxChargingProfile_Process(); Ocpp_ChargingProfile_Process(_index); } } void GetLocalPowerLimit(byte gunIndex) { if(ShmSysConfigAndInfo->SysConfig.isEnableLocalPowerSharing > _SYS_POWER_SHARING_MODE_DISABLE) { if(ShmSysConfigAndInfo->SysInfo.localSharingInfo.isConnectedSharingServer) { float _localLimitPower = ShmSysConfigAndInfo->SysInfo.localSharingInfo.AvailableShargingCurrent[gunIndex] * AC_OUTPUT_VOL; if(chargingInfo[gunIndex]->EvBatterytargetVoltage > 0 && (int)chargingInfo[gunIndex]->PresentChargingVoltage > 0) { chargingInfo[gunIndex]->LocalPowerLimitCurrent = _localLimitPower / chargingInfo[gunIndex]->PresentChargingVoltage; } else { chargingInfo[gunIndex]->LocalPowerLimitCurrent = -1; } } else { chargingInfo[gunIndex]->LocalPowerLimitCurrent = 0; } } else { chargingInfo[gunIndex]->LocalPowerLimitCurrent = -1; } } void TheEndCharging(byte gun_index) { chargingInfo[gun_index]->isRemoteStart = NO; if(strlen((char *)&ShmSysConfigAndInfo->SysConfig.OcppReceiptrURL) > 0 && ShmChargerInfo->UserTransaction[gun_index].TransactionId > 0) { char receiptString[512]; sprintf(receiptString, "%s%d", (char *)&ShmSysConfigAndInfo->SysConfig.OcppReceiptrURL[0], ShmChargerInfo->UserTransaction[gun_index].TransactionId); strcpy((char *)&ShmChargerInfo->PriceAndReceiptInfo.ReceiptUrl[gun_index][0], receiptString); Set_Connector_MiscCommand(gun_index, MISC_CONN_RECEIPT); LOG_INFO("Gun %d ReceiptrURL: [%s]", gun_index + 1, receiptString); } ChangeStartOrStopDateTime(NO, gun_index); DB_Insert_Record(localDb, gun_index); } void UpdateErrorCodeToOcpp(byte index) { //printf("ConnectorAlarmCode = %s \n", chargingInfo[index]->ConnectorAlarmCode); if (strcmp((char *)chargingInfo[index]->ConnectorAlarmCode, "") != EQUAL) { SetOcppErrorCode(index, "InternalError"); SetOcppVendorErrorCode(index, (char *)chargingInfo[index]->ConnectorAlarmCode); } else if (strcmp((char *)chargingInfo[index]->EvConnAlarmCode, "") != EQUAL) { SetOcppErrorCode(index, "OtherError"); SetOcppVendorErrorCode(index, (char *)chargingInfo[index]->EvConnAlarmCode); } } void CheckMiscCommandRequirement(void) { BOOL NeedAnnouncement = FALSE; unsigned char connector = 0; if(ShmSysConfigAndInfo->SysInfo.FirmwareUpdate != YES) { for(int i = 0; i < CONNECTOR_QUANTITY; i++) { NeedAnnouncement = FALSE; if(ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[i].LocalStatus != _DS_None && ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[i].LocalStatus != _DS_Timeout) { if(ShmChargerInfo->DispenserMiscReq[i].CtrlValue != 0) { NeedAnnouncement = TRUE; } for(int j = 0; j < ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[i].ConnectorQuantity; j++) { connector = ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[i].ConnectorID[j] - 1; if(ShmChargerInfo->ConnectorMiscReq[connector].CtrlValue != 0) { NeedAnnouncement = TRUE; } } if(ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[i].Setting.bits.MiscNeedAnnouncement != NeedAnnouncement) { if(NeedAnnouncement) { //LOG_INFO("********** Dispenser %d Misc Command Need Announcement **********", i + 1); } else { //LOG_INFO("********** Dispenser %d Misc Command Announced **********", i + 1); } } } ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[i].Setting.bits.MiscNeedAnnouncement = NeedAnnouncement; } } } void CheckDispenserVersionUpdateRequirement(void) { } bool IsReadyParalleling(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; } void SetParallelingStart(void) { for(int i = 0; i < CONNECTOR_QUANTITY; i++) { if(chargingInfo[i]->SystemStatus == S_IDLE) { setChargerMode(i, MODE_MAINTAIN); } } ShmChargerInfo->ParallelCabinet.ParallelStatus = _Parallel_Wait; } void SetParallelingDone(void) { unsigned short totalPow = 0; totalPow = GetTotalParallelCabinetPower(); if(totalPow != ShmChargerInfo->ParallelCabinet.TotalParallelPower) { LOG_INFO("Total Parallel Cabinet Power: %d.%d kW", (totalPow / 10), (totalPow % 10)); } ShmChargerInfo->ParallelCabinet.TotalParallelPower = totalPow; ShmChargerInfo->ParallelCabinet.ParallelStatus = _Parallel_None; } void SetPCabinetOutputRelay(unsigned char index, unsigned char OnOff) { unsigned char relay = 0; if(ShmChargerInfo->Control.CabinetRole == _CROLE_MASTER) { for(int i = 0; i < CONNECTOR_QUANTITY; i++) { if(ShmChargerInfo->ParallelCabinet.PCabinet[i].LocalStatus == _DS_Idle && ShmChargerInfo->ParallelCabinet.PCabinet[i].ParallelConfirm) { relay = OnOff == YES ? YES : NO; if(ShmChargerInfo->ParallelCabinet.PCabinet[index].OutputRelaySetting[index] != relay) { LOG_INFO("Set Parallel Cabinet Gun %d Output Relay %s", index + 1, relay == YES ? "ON" : "OFF"); } ShmChargerInfo->ParallelCabinet.PCabinet[i].OutputRelaySetting[index] = relay; } } } } void SetParallelCabinetAcContactor(unsigned char OnOff) { for(int i = 0; i < CONNECTOR_QUANTITY; i++) { if(ShmChargerInfo->ParallelCabinet.PCabinet[i].LocalStatus == _DS_Idle && ShmChargerInfo->ParallelCabinet.PCabinet[i].ParallelConfirm) { ShmChargerInfo->ParallelCabinet.PCabinet[i].AcContactorSetting = OnOff == YES ? YES : NO; } } } unsigned short GetTotalParallelCabinetPower(void) { unsigned short power = 0, slavePow = 0; if(ShmChargerInfo->Control.CabinetRole == _CROLE_MASTER) { for(int i = 0; i < MAX_SLAVE_CABINET_QUANTITY; i++) { if(ShmChargerInfo->ParallelCabinet.PCabinet[i].LocalStatus == _DS_Idle || ShmChargerInfo->ParallelCabinet.PCabinet[i].LocalStatus == _DS_Alarm || ShmChargerInfo->ParallelCabinet.PCabinet[i].LocalStatus == _DS_Charging) { slavePow = ParsingRatingPower((char *)ShmChargerInfo->ParallelCabinet.PCabinet[i].ModelName); power += slavePow; } } } return power; } unsigned char preParallelStatus = 0; void MCabinetParallelingProcess(void) { bool PsuReInitial = false; unsigned char status = 0; if(ShmChargerInfo->Control.CabinetRole == _CROLE_MASTER) { if(IsReadyParalleling()) { for(int i = 0; i < CONNECTOR_QUANTITY; i++) { if(ShmChargerInfo->ParallelCabinet.PCabinet[i].ParallelRequest) { ShmChargerInfo->ParallelCabinet.PCabinet[i].ParallelRequest = false; ShmChargerInfo->ParallelCabinet.PCabinet[i].ParallelConfirm = true; PsuReInitial = true; } } if(PsuReInitial) { SetParallelingStart(); } } status = ShmChargerInfo->ParallelCabinet.ParallelStatus; switch(status) { case _Parallel_None: if(preParallelStatus != status) { LOG_INFO("MCabinet Parallel Status [None]"); GetClockTime(&_Parallel_Time); } unsigned short totalPow = 0; totalPow = GetTotalParallelCabinetPower(); if(totalPow != ShmChargerInfo->ParallelCabinet.TotalParallelPower) { LOG_INFO("Total Parallel Cabinet Power: %d.%d kW", (totalPow / 10), (totalPow % 10)); } ShmChargerInfo->ParallelCabinet.TotalParallelPower = totalPow; break; case _Parallel_Wait: if(preParallelStatus != status) { LOG_INFO("MCabinet Parallel Status [Wait]"); SetAcContactor(OFF); SetParallelCabinetAcContactor(OFF); for(int i = 0; i < CONNECTOR_QUANTITY; i++) { SetPCabinetOutputRelay(i, OFF); } GetClockTime(&_Parallel_Time); } if((GetTimeoutValue(_Parallel_Time) / uSEC_VAL) >= PARALLEL_WAIT_TIME) { ShmChargerInfo->ParallelCabinet.ParallelStatus = _Parallel_Working; } break; case _Parallel_Working: if(preParallelStatus != status) { LOG_INFO("MCabinet Parallel Status [Working]"); SetAcContactor(ON); SetParallelCabinetAcContactor(ON); GetClockTime(&_Parallel_Time); } if(ShmPsuData->Work_Step == _WORK_CHARGING) { ShmChargerInfo->ParallelCabinet.ParallelStatus = _Parallel_Done; } break; case _Parallel_Done: if(preParallelStatus != status) { LOG_INFO("MCabinet Parallel Status [Done]"); GetClockTime(&_Parallel_Time); } if((GetTimeoutValue(_Parallel_Time) / uSEC_VAL) >= PARALLEL_WAIT_TIME) { SetParallelingDone(); } break; } preParallelStatus = status; } } void SCabinetControllProcess(void) { if(ShmChargerInfo->Control.CabinetRole == _CROLE_SLAVE) { if(ShmChargerInfo->SCabinetControl.SAcContactor) { SetAcContactor(ON); } else { SetAcContactor(OFF); } unsigned short _parallelRelay = 0; for(int i = 0; i < GENERAL_GUN_QUANTITY; i++) { _parallelRelay = ShmChargerInfo->SCabinetControl.SParallelRelay[i] > 0 ? (1 < i) : 0; } if(_parallelRelay != ShmChargerInfo->PsuGrouping.ParallelRelayConfig.CtrlValue) { LOG_INFO("SCabinet Set Parallel Relay %X -> %X", ShmChargerInfo->PsuGrouping.ParallelRelayConfig.CtrlValue, _parallelRelay); } ShmChargerInfo->PsuGrouping.ParallelRelayConfig.CtrlValue = _parallelRelay; } } void CheckConnectorDisconnectionRecovery(unsigned char connector) { unsigned char dispenser = 0; dispenser = ShmSysConfigAndInfo->SysInfo.ConnectorInfo[connector].ParentDispensetIndex; if(ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[dispenser].LocalStatus != _DS_Timeout) { LOG_INFO("Connector %d Disconnection Recovery", connector + 1); ShmSysConfigAndInfo->SysInfo.ConnectorInfo[connector].Parameter.bits.Disconnection = false; } } bool ConnectorRequestToCharging(unsigned char connector) { unsigned char role = 0; bool done = false; role = ShmPsuGrouping->GroupCollection[connector].Role; switch(role) { case _GROLE_IDLE: if(!ShmPsuGrouping->GroupCollection[connector].GroupCtrl.bits.ChargingRequest) { LOG_INFO("Request Gun %d To Start Charging", connector + 1); } ShmPsuGrouping->GroupCollection[connector].GroupCtrl.bits.ChargingRequest = true; break; case _GROLE_MASTER: done = true; break; case _GROLE_SLAVE: if(!ShmPsuGrouping->GroupCollection[connector].GroupCtrl.bits.SlaveChargingRequest) { LOG_INFO("Gun %d Wait For Re-Grouping", connector + 1); } ShmPsuGrouping->GroupCollection[connector].GroupCtrl.bits.SlaveChargingRequest = true; break; case _GROLE_REQUEST_TO_CHARGING: done = true; break; default: break; } return done; } bool IsConnectorGroupingCompleted(unsigned char connector) { unsigned char role = 0; bool completed = false; role = ShmPsuGrouping->GroupCollection[connector].Role; switch(role) { case _GROLE_MASTER: completed = true; break; default: break; } return completed; } void SelfTestFailReason(void) { char reason[50]; memset(reason, 0x00, sizeof(reason)); if(ShmStatusCodeData->AlarmCode.AlarmEvents.bits.EmergencyStopTrip) { StatusCodeCompose(reason, "042251"); } else if(ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PrimaryStestFail || ShmStatusCodeData->AlarmCode.AlarmEvents.bits.RelayboardStestFail || ShmStatusCodeData->AlarmCode.AlarmEvents.bits.FanboardStestFail) { if(ShmStatusCodeData->AlarmCode.AlarmEvents.bits.RelayboardStestFail) { StatusCodeCompose(reason, "042280"); } if(ShmStatusCodeData->AlarmCode.AlarmEvents.bits.FanboardStestFail) { StatusCodeCompose(reason, "042281"); } if(ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PrimaryStestFail) { StatusCodeCompose(reason, "042282"); } } else if(ShmStatusCodeData->AlarmCode.AlarmEvents.bits.AcContactStestFail || ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuModuleStestFail) { if(ShmStatusCodeData->AlarmCode.AlarmEvents.bits.AcContactStestFail) { StatusCodeCompose(reason, "042285"); } if(ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuModuleStestFail) { StatusCodeCompose(reason, "042286"); } } else { StatusCodeCompose(reason, "Self Test Fail"); } for (byte gun_index = 0; gun_index < ShmSysConfigAndInfo->SysConfig.TotalConnectorCount; gun_index++) { SetOcppErrorCode(gun_index, "InternalError"); SetOcppVendorErrorCode(gun_index, reason); setChargerMode(gun_index, MODE_MAINTAIN); } } bool IsAvailableBackToIdle(int gun_index) { if(_plugInHold[gun_index] == false && (ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gun_index].Enable == false || chargingInfo[gun_index]->ConnectorPlugIn == false)) { _plugInHold[gun_index] = true; GetClockTime(&_PlugInHold_Time[gun_index]); LOG_INFO ("Gun %d Plug In Hold Delay", gun_index + 1); } if(ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gun_index].RemoteStatus == _CRS_Idle || ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gun_index].Enable == false || (!chargingInfo[gun_index]->ConnectorPlugIn && ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuFailureAlarm) || isResetStopChargeFlag(gun_index) == YES) { if(!_plugInHold[gun_index]) { _plugInHold[gun_index] = true; GetClockTime(&_PlugInHold_Time[gun_index]); LOG_INFO ("Force Gun %d Plug In Hold Delay", gun_index + 1); } if((GetTimeoutValue(_PlugInHold_Time[gun_index]) / uSEC_VAL) >= PLUG_IN_HOLD_TIME) { return true; } } return false; } void CheckGunAvailable(void) { if(!ShmChargerInfo->Control.SysCtrl.bits.PsuInit) { if(ShmChargerInfo->Control.PsuCtrl.bits.SelfTestOK) { for(int i = 0; i < GENERAL_GUN_QUANTITY; i++) { if(ShmPsuData->PsuGroup[i].GroupPresentPsuQuantity > 0) { ShmChargerInfo->Control.GunAvailable[i] = YES; } } ShmChargerInfo->Control.SysCtrl.bits.PsuInit = true; } } } int presentChargedEnergyClear(unsigned char gun_index) { int result = FAIL; chargingInfo[gun_index]->PresentChargedEnergy = 0; memset(chargingInfo[gun_index]->presentChargedEnergyPeriod, 0x00, ARRAY_SIZE(chargingInfo[gun_index]->presentChargedEnergyPeriod) * sizeof(float)); result = PASS; return result; } float presentChargedEnergyTotal(unsigned char gun_index) { float result = 0.0f; for(int idx = 0; idx < ARRAY_SIZE(chargingInfo[gun_index]->presentChargedEnergyPeriod); idx++) { result += chargingInfo[gun_index]->presentChargedEnergyPeriod[idx]; } return result; } int presentChargedEnergyUpdate(unsigned char gun_index, float kwh) { int result = FAIL; time_t CurrentTime; struct tm *tm; CurrentTime = time(NULL); tm=localtime(&CurrentTime); chargingInfo[gun_index]->presentChargedEnergyPeriod[tm->tm_hour] += kwh; return result; } void ChargedEnergySummation(unsigned char gun_index) { unsigned long time = 0; time = GetSecTimeoutValue(_ChargedEnergy_Time[gun_index]); if(time >= (chargingInfo[gun_index]->PresentChargedDuration + ENERAGY_INTERVAL)) { chargingInfo[gun_index]->PresentChargedDuration++; float changedEnergy = 0; float _meterEnergy = 0; float _calChangingEnergy = (chargingInfo[gun_index]->PresentChargingPower) / 3600; if(ShmChargerInfo->MeterValue[gun_index].GunConsumption >= 0) { if(ShmChargerInfo->MeterValue[gun_index].GunConsumption >= _lsatGunMeterValue[gun_index]) { _meterEnergy = ShmChargerInfo->MeterValue[gun_index].GunConsumption - _lsatGunMeterValue[gun_index]; } else { _meterEnergy = 0; } changedEnergy = _meterEnergy; _lsatGunMeterValue[gun_index] = ShmChargerInfo->MeterValue[gun_index].GunConsumption; } else { changedEnergy = _calChangingEnergy; } if(ShmSysConfigAndInfo->SysConfig.BillingData.isBilling) { chargingInfo[gun_index]->ChargingFee += changedEnergy * ShmSysConfigAndInfo->SysConfig.BillingData.Cur_fee; } presentChargedEnergyUpdate(gun_index, changedEnergy); chargingInfo[gun_index]->PresentChargedEnergy += changedEnergy; ShmChargerInfo->MeterValue[gun_index].LocalConsumption += changedEnergy; } } void ChkConnectorAction(void) { for(int i = 0; i < CONNECTOR_QUANTITY; i++) { if(ShmChargerInfo->ConnectorActReq[i].Flag.bits.ChargingCancel) { if(ShmChargerInfo->AllBill.OccupancyInfo[i].Status != _Parking_WaitToPay) { LOG_INFO("Gun %d Charging Canceled", i + 1); Clean_Ocpp_TcciSerialNo(i); } else { LOG_INFO("Gun %d Occupancy Keep Counting", i + 1); Set_OccupancyKeepCountingReq(i); } ShmChargerInfo->ConnectorActReq[i].Flag.bits.ChargingCancel = false; } } } void Update_DispenserAvailability(int dispenserIndex) { for(int i = 0; i < ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[dispenserIndex].ConnectorQuantity; i++) { int gun = ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[dispenserIndex].ConnectorID[i] - 1; Set_Connector_MiscCommand(gun, MISC_CONN_AVAILABILITY); } } void InitialDataBaseValue(void) { // Local DB if(DB_Open(localDb) != PASS) { LOG_INFO("DB_Open fail."); isDb_ready = false; } else { isDb_ready = true; DB_TryAddRebootRecordColumn(localDb); DB_TryAddChargingRecordColumn(localDb); for(int _index = 0; _index < ShmSysConfigAndInfo->SysConfig.TotalConnectorCount; _index++) { chargingInfo[_index]->IsAvailable = DB_Get_Operactive(localDb, _index); LOG_INFO("Gun %d IsAvailable Initial: [%s]", _index + 1, chargingInfo[_index]->IsAvailable == YES ? "Enable" : "Disable"); } for(int _index = 0; _index < ShmSysConfigAndInfo->SysConfig.TotalConnectorCount; _index++) { ShmChargerInfo->MeterValue[_index].LocalConsumption = DB_Get_LocalConsumption(localDb, _index); LOG_INFO("Local Gun %d Consumption Initial: [%.4f kWh]", _index + 1, ShmChargerInfo->MeterValue[_index].LocalConsumption); } for(int _index = 0; _index < ShmSysConfigAndInfo->SysConfig.TotalConnectorCount; _index++) { ShmChargerInfo->MeterValue[_index].GunConsumption = DB_Get_GunConsumption(localDb, _index); LOG_INFO("Remote Gun %d Consumption Initial: [%.4f kWh]", _index + 1, ShmChargerInfo->MeterValue[_index].GunConsumption); } for(int _index = 0; _index < ShmSysConfigAndInfo->SysConfig.TotalConnectorCount; _index++) { Update_PowerConsumption(_index); LOG_INFO("Gun %d Power Consumption Initial: [%.4f kWh]", _index + 1, chargingInfo[_index]->PowerConsumption); } DB_Reboot_Record(localDb); } if (NetworkDB_Open(networkDb) != PASS) { LOG_ERROR("NetworkDB_Open fail."); } } float CalculateMaxOutputRatio(int gunIndex) { float ratio = 0; int inUsingCnt = 0; for(int i = 0; i < GENERAL_GUN_QUANTITY; i++) { if(ShmChargerInfo->PsuGrouping.GroupCollection[i].Role == _GROLE_MASTER) { inUsingCnt += ShmChargerInfo->PsuGrouping.GroupCollection[i].GunPsuQuantity; } } if(inUsingCnt != 0) { ratio = ShmChargerInfo->PsuGrouping.GroupCollection[gunIndex].Role == _GROLE_MASTER ? ((float)ShmChargerInfo->PsuGrouping.GroupCollection[gunIndex].GunPsuQuantity / inUsingCnt) : 0; } ShmChargerInfo->PsuGrouping.GroupCollection[gunIndex].MaxOutputRatio = ratio; return ratio; } // return unit: 0.1kW unsigned short GetModelNameLimitPower(int gunIndex) { unsigned short limitPower = 0; float fPower = 0; if(ShmChargerInfo->PsuGrouping.GroupCollection[gunIndex].MaxOutputRatio != 0 && ShmChargerInfo->Control.ChargerRatingPower != 0) { fPower = (float)ShmChargerInfo->Control.ChargerRatingPower / 10; if(ShmChargerInfo->Control.CabinetRole == _CROLE_MASTER) { fPower += (float)ShmChargerInfo->ParallelCabinet.TotalParallelPower / 10; } fPower = fPower * ShmChargerInfo->PsuGrouping.GroupCollection[gunIndex].MaxOutputRatio; limitPower = (unsigned short)(fPower * 10); } return limitPower; } void GetWebPageConfigPowerLimit(int gunIndex) { unsigned short limitPower = 0; float fPower = 0; if(ShmChargerInfo->PsuGrouping.GroupCollection[gunIndex].MaxOutputRatio != 0 && ShmSysConfigAndInfo->SysConfig.MaxChargingPower != 0) { fPower = (float)ShmSysConfigAndInfo->SysConfig.MaxChargingPower; fPower = fPower * ShmChargerInfo->PsuGrouping.GroupCollection[gunIndex].MaxOutputRatio; limitPower = (unsigned short)(fPower * 10); } ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gunIndex].MaxTotalChargingPower = limitPower; } void GetWebPageConfigCurrentLimit(int gunIndex) { unsigned short limitCurrent = 0; float fCurrent = 0; if(ShmChargerInfo->PsuGrouping.GroupCollection[gunIndex].MaxOutputRatio != 0 && ShmSysConfigAndInfo->SysConfig.MaxChargingCurrent != 0) { fCurrent = (float)ShmSysConfigAndInfo->SysConfig.MaxChargingCurrent; fCurrent = fCurrent * ShmChargerInfo->PsuGrouping.GroupCollection[gunIndex].MaxOutputRatio; limitCurrent = (unsigned short)(fCurrent * 10); } ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gunIndex].MaxTotalChargingCurrent = limitCurrent; } void GetOffLineMaxChargingPowerLimit(int gunIndex) { unsigned short limitPower = 0; float fPower = 0; if(ShmChargerInfo->PsuGrouping.GroupCollection[gunIndex].MaxOutputRatio != 0 && ShmChargerInfo->OutputLimit.Offline_MaxChargingPower != 0 && ShmStatusCodeData->InfoCode.InfoEvents.bits.BackendDisconnectedViaEthernet == YES) { fPower = ShmChargerInfo->OutputLimit.Offline_MaxChargingPower / 1000; fPower = fPower * ShmChargerInfo->PsuGrouping.GroupCollection[gunIndex].MaxOutputRatio; limitPower = (unsigned short)(fPower * 10); } ShmChargerInfo->OutputLimit.GunOfflineMaxPower[gunIndex] = limitPower * 100; } void GetMaxChargingProfileLimit(int gunIndex) { unsigned short limitPower = 0, limitCurrent = 0; float fPower = 0; // max charging profile if(ShmChargerInfo->PsuGrouping.GroupCollection[gunIndex].MaxOutputRatio != 0 && ShmSysConfigAndInfo->SysInfo.MaxChargingProfilePower >= 0) { fPower = ShmSysConfigAndInfo->SysInfo.MaxChargingProfilePower / 1000; fPower = fPower * ShmChargerInfo->PsuGrouping.GroupCollection[gunIndex].MaxOutputRatio; limitPower = (unsigned short)(fPower * 10); if (chargingInfo[gunIndex]->EvBatterytargetVoltage > 0 && (int)chargingInfo[gunIndex]->PresentChargingVoltage > 0) { limitCurrent = (limitPower * 100 / chargingInfo[gunIndex]->PresentChargingVoltage) * 10; } } ShmChargerInfo->OutputLimit.GunMaxProfilePower[gunIndex] = limitPower * 100; ShmChargerInfo->OutputLimit.GunMaxProfileCurrent[gunIndex] = limitCurrent; } void GetMaxChargingLimit(int gunIndex) { GetWebPageConfigPowerLimit(gunIndex); GetWebPageConfigCurrentLimit(gunIndex); GetOffLineMaxChargingPowerLimit(gunIndex); GetMaxChargingProfileLimit(gunIndex); } void GetGunOtpDerating(int gunIndex) { if(ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gunIndex].GeneralChargingData.deratingByConnOtp.isNeedDerating && chargingInfo[gunIndex]->SystemStatus > S_IDLE && chargingInfo[gunIndex]->SystemStatus <= S_CHARGING) { struct DERATING_BY_OTP *_derating; _derating = &ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gunIndex].GeneralChargingData.deratingByConnOtp; if(_derating->deratingIndex < GUN_DERATING_COUNT) { int _connectorTemp = (int)chargingInfo[gunIndex]->ConnectorTemp - 60; int _chillerTemp = (int)chargingInfo[gunIndex]->ChillerTemp - 60; if(_connectorTemp >= GunDeratingTemp[_derating->deratingIndex] && chargingInfo[gunIndex]->ConnectorTemp != 0xFF && _derating->deratingTargetCurrent[_derating->deratingIndex + 1] > 0) { LOG_INFO("Gun %d GunTemp %d is Derating(%d) to %d A", gunIndex + 1, _connectorTemp, GunDeratingTemp[_derating->deratingIndex], ((int)_derating->deratingTargetCurrent[_derating->deratingIndex + 1] / 10)); _derating->deratingIndex++; } else if(_chillerTemp >= GunDeratingTemp[_derating->deratingIndex] && chargingInfo[gunIndex]->ChillerTemp != 0xFF && _derating->deratingTargetCurrent[_derating->deratingIndex + 1] > 0) { LOG_INFO("Gun %d ChillerTemp %d is Derating(%d) to %d A", gunIndex + 1, _chillerTemp, GunDeratingTemp[_derating->deratingIndex], ((int)_derating->deratingTargetCurrent[_derating->deratingIndex + 1] / 10)); _derating->deratingIndex++; } } if(chargingInfo[gunIndex]->ConnectorTemp != 0xFF || chargingInfo[gunIndex]->ChillerTemp != 0xFF) { ShmChargerInfo->OutputLimit.GunOtpMaxCurrent[gunIndex] = (int)_derating->deratingTargetCurrent[_derating->deratingIndex]; ShmChargerInfo->OutputLimit.GunOtpMaxPower[gunIndex] = 0; } else { ShmChargerInfo->OutputLimit.GunOtpMaxCurrent[gunIndex] = 0; ShmChargerInfo->OutputLimit.GunOtpMaxPower[gunIndex] = 0; } } else { ShmChargerInfo->OutputLimit.GunOtpMaxCurrent[gunIndex] = 0; ShmChargerInfo->OutputLimit.GunOtpMaxPower[gunIndex] = 0; } } void CalculateGunAbsMaxPower(int gunIndex) { int maxValue = 0; maxValue = (int)GetModelNameLimitPower(gunIndex); ShmChargerInfo->OutputLimit.GunAbsoluteMaxPower[gunIndex] = maxValue != 0 ? (maxValue * 100) : 0; } void CalculateGunAbsMaxVoltage(int gunIndex) { int maxValue = 0; maxValue = (int)ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gunIndex].RemoteMaxPhysicalVoltage; ShmChargerInfo->OutputLimit.GunAbsoluteMaxVoltage[gunIndex] = maxValue; } void CalculateGunAbsMaxCurrent(int gunIndex) { int maxValue = 0; maxValue = (int)ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gunIndex].RemoteMaxPhysicalCurrent; ShmChargerInfo->OutputLimit.GunAbsoluteMaxCurrent[gunIndex] = maxValue; } void RestrictChargingCapability(int gunIndex, unsigned short *power, unsigned short *voltage, unsigned short *current) { unsigned short limitPower = 0; int _limitPowerResult = 0; int _limitVoltageResult = 0; int _limitCurrentResult = 0; _limitPowerResult = ShmPsuData->SystemAvailablePower; _limitVoltageResult = MAX_OUTPUT_VOLTAGE; _limitCurrentResult = ShmPsuData->SystemAvailableCurrent; if(ShmChargerInfo->OutputLimit.GunAbsoluteMaxPower[gunIndex] != 0) { limitPower = ShmChargerInfo->OutputLimit.GunAbsoluteMaxPower[gunIndex] / 100; if(limitPower != 0 && _limitPowerResult > limitPower) { _limitPowerResult = limitPower; } } if(ShmChargerInfo->OutputLimit.GunAbsoluteMaxVoltage[gunIndex] != 0 && _limitVoltageResult > ShmChargerInfo->OutputLimit.GunAbsoluteMaxVoltage[gunIndex]) { _limitVoltageResult = ShmChargerInfo->OutputLimit.GunAbsoluteMaxVoltage[gunIndex]; } if(ShmChargerInfo->OutputLimit.GunAbsoluteMaxCurrent[gunIndex] != 0 && _limitCurrentResult > ShmChargerInfo->OutputLimit.GunAbsoluteMaxCurrent[gunIndex]) { _limitCurrentResult = ShmChargerInfo->OutputLimit.GunAbsoluteMaxCurrent[gunIndex]; } // restrict from WebPageConfig power if(ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gunIndex].MaxTotalChargingPower != 0) { if(_limitPowerResult > ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gunIndex].MaxTotalChargingPower) { _limitPowerResult = ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gunIndex].MaxTotalChargingPower; } } // restrict from WebPageConfig current if(ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gunIndex].MaxTotalChargingCurrent != 0) { if(_limitCurrentResult > ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gunIndex].MaxTotalChargingCurrent) { _limitCurrentResult = ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gunIndex].MaxTotalChargingCurrent; } } // restrict from Offline_MaxChargingPower if(ShmChargerInfo->OutputLimit.GunOfflineMaxPower[gunIndex] != 0) { limitPower = ShmChargerInfo->OutputLimit.GunOfflineMaxPower[gunIndex] / 100; if(limitPower != 0 && _limitPowerResult > limitPower) { _limitPowerResult = limitPower; } } // restrict from MaxChargingProfile if(ShmChargerInfo->OutputLimit.GunMaxProfilePower[gunIndex] != 0) { limitPower = ShmChargerInfo->OutputLimit.GunMaxProfilePower[gunIndex] / 100; if(limitPower != 0 && _limitPowerResult > limitPower) { _limitPowerResult = limitPower; } } // restrict from MaxChargingProfile if(ShmChargerInfo->OutputLimit.GunMaxProfileCurrent[gunIndex] != 0) { if(_limitCurrentResult > ShmChargerInfo->OutputLimit.GunMaxProfileCurrent[gunIndex]) { _limitCurrentResult = ShmChargerInfo->OutputLimit.GunMaxProfileCurrent[gunIndex]; } } // restrict from ChargingProfile if((chargingInfo[gunIndex]->SystemStatus >= S_PREPARING_FOR_EVSE && chargingInfo[gunIndex]->SystemStatus <= S_CHARGING) || (chargingInfo[gunIndex]->SystemStatus >= S_CCS_PRECHARGE_ST0 && chargingInfo[gunIndex]->SystemStatus <= S_CCS_PRECHARGE_ST1)) { if(chargingInfo[gunIndex]->ChargingProfilePower >= 0 && _limitPowerResult > ((int)chargingInfo[gunIndex]->ChargingProfilePower / 100)) { _limitPowerResult = (int)chargingInfo[gunIndex]->ChargingProfilePower / 100; } if(chargingInfo[gunIndex]->ChargingProfileCurrent >= 0 && _limitCurrentResult > (int)chargingInfo[gunIndex]->ChargingProfileCurrent) { _limitCurrentResult = (int)chargingInfo[gunIndex]->ChargingProfileCurrent; } } // restrict from local power limit if(ShmSysConfigAndInfo->SysConfig.isEnableLocalPowerSharing > _SYS_POWER_SHARING_MODE_DISABLE) { if(chargingInfo[gunIndex]->LocalPowerLimitCurrent >= 0 && _limitCurrentResult > (int)(chargingInfo[gunIndex]->LocalPowerLimitCurrent * 10)) { _limitCurrentResult = (int)(chargingInfo[gunIndex]->LocalPowerLimitCurrent * 10); } } // restrict after otp if(ShmChargerInfo->OutputLimit.GunOtpMaxPower[gunIndex] != 0) { limitPower = ShmChargerInfo->OutputLimit.GunOtpMaxPower[gunIndex] / 100; if(limitPower != 0 && _limitPowerResult > limitPower) { _limitPowerResult = limitPower; } } // restrict after otp if(ShmChargerInfo->OutputLimit.GunOtpMaxCurrent[gunIndex] != 0 && _limitCurrentResult > ShmChargerInfo->OutputLimit.GunOtpMaxCurrent[gunIndex]) { _limitCurrentResult = ShmChargerInfo->OutputLimit.GunOtpMaxCurrent[gunIndex]; } ShmChargerInfo->OutputLimit.GunLimitPower[gunIndex] = _limitPowerResult; ShmChargerInfo->OutputLimit.GunLimitVoltage[gunIndex] = _limitVoltageResult; ShmChargerInfo->OutputLimit.GunLimitCurrent[gunIndex] = _limitCurrentResult; if(_limitPowerResult != 0 && *power > _limitPowerResult) { *power = _limitPowerResult; } if(_limitVoltageResult != 0 && *voltage > _limitVoltageResult) { *voltage = _limitVoltageResult; } if(_limitCurrentResult != 0 && *current > _limitCurrentResult) { *current = _limitCurrentResult; } } void UpdateChargingCapability(void) { unsigned short voltage = 0, current = 0, power = 0; ShmChargerInfo->OutputLimit.Offline_MaxChargingPower = Get_Ocpp_OffLineMaxChargingPower(); for(int i = 0; i < MAX_GUN_QUANTITY; i++) { voltage = (unsigned short)ShmSysConfigAndInfo->SysInfo.ConnectorInfo[i].GeneralChargingData.MaximumChargingVoltage; current = (unsigned short)ShmSysConfigAndInfo->SysInfo.ConnectorInfo[i].GeneralChargingData.AvailableChargingCurrent; power = (unsigned short)ShmSysConfigAndInfo->SysInfo.ConnectorInfo[i].GeneralChargingData.AvailableChargingPower; CalculateGunAbsMaxPower(i); CalculateGunAbsMaxVoltage(i); CalculateGunAbsMaxCurrent(i); CalculateMaxOutputRatio(i); GetMaxChargingLimit(i); GetLocalPowerLimit(i); GetGunOtpDerating(i); RestrictChargingCapability(i, &power, &voltage, ¤t); ShmSysConfigAndInfo->SysInfo.ConnectorInfo[i].CapabilityVoltage = voltage; ShmSysConfigAndInfo->SysInfo.ConnectorInfo[i].CapabilityCurrent = current; ShmSysConfigAndInfo->SysInfo.ConnectorInfo[i].CapabilityPower = power; } } void GunErrorCollection(void) { bool _PsuNoResource = false; for(int i = 0; i < MAX_GUN_QUANTITY; i++) { if(ShmPsuData->Work_Step == INITIAL_START) { ShmChargerInfo->GunError[i].ErrFlag.bits.PsuGroupNoResource = false; } else { if(ShmChargerInfo->GunError[i].ErrFlag.bits.PsuGroupNoResource) { _PsuNoResource = true; } } } ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuNoResource = _PsuNoResource; } void UpdateGunPresentChargingPower(int gunIndex) { if(ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gunIndex].Enable) { chargingInfo[gunIndex]->PresentChargingPower = (((float)((ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gunIndex].RemoteChargingVoltage) * (ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gunIndex].RemoteChargingCurrent))) / 1000 / 100); } else { chargingInfo[gunIndex]->PresentChargingPower = ((float)((chargingInfo[gunIndex]->PresentChargingVoltage) * (chargingInfo[gunIndex]->PresentChargingCurrent)) / 1000); } } void CheckPsuLostQuantity(void) { if(ShmPsuData->Work_Step == _WORK_CHARGING) { if(ShmChargerInfo->Control.PsuQuantityByModel == ShmPsuData->SystemPresentPsuQuantity) { ShmStatusCodeData->InfoCode.InfoEvents.bits.PsuQuantityNotMatch = false; ShmSysConfigAndInfo->SysInfo.PsuLostQuantity = 0; } else { ShmSysConfigAndInfo->SysInfo.PsuLostQuantity = ShmChargerInfo->Control.PsuQuantityByModel > ShmPsuData->SystemPresentPsuQuantity ? (ShmChargerInfo->Control.PsuQuantityByModel - ShmPsuData->SystemPresentPsuQuantity) : 0; if(!ShmStatusCodeData->InfoCode.InfoEvents.bits.PsuQuantityNotMatch || _psuLostQuantity != ShmSysConfigAndInfo->SysInfo.PsuLostQuantity) { LOG_INFO("Psu Quantity is %d, it should be %d, Psu Lost: %d", ShmPsuData->SystemPresentPsuQuantity, ShmChargerInfo->Control.PsuQuantityByModel, ShmSysConfigAndInfo->SysInfo.PsuLostQuantity); } ShmStatusCodeData->InfoCode.InfoEvents.bits.PsuQuantityNotMatch = true; _psuLostQuantity = ShmSysConfigAndInfo->SysInfo.PsuLostQuantity; } } } void CheckOcmfHandler(void) { bool _newOcmf = false; int _ocmfLength = 0; int _gunIndex = 0; char _txId[37]; char _ocmfKey[201]; char _ocmfInfo[2048]; // check new ocmf info for(int i = 0; i < MAX_GUN_QUANTITY; i++) { if(ShmChargerInfo->OcmfInfo.GunOcmf[i].OcmfFlag.bits.OcmfReceived) { _newOcmf = false; char fileName[256] = {0}; sprintf(fileName, "/mnt/Gun_%d_%s_OCMF", i + 1, ShmChargerInfo->OcmfInfo.GunOcmf[i].OcmfTxId); if(access(fileName, F_OK) != -1) { _newOcmf = true; } if(_newOcmf) { int fd = 0; fd = open(fileName, O_RDONLY); if(fd < 0) { LOG_INFO("Gun %d TxId[%s] OCMF file [%s] open fail", i + 1, ShmChargerInfo->OcmfInfo.GunOcmf[i].OcmfTxId, fileName); } else { memset(_txId, 0x00, sizeof(_txId)); memset(_ocmfKey, 0x00, sizeof(_ocmfKey)); memset(_ocmfInfo, 0x00, sizeof(_ocmfInfo)); //-48 is take out the header _ocmfLength = read(fd, _ocmfInfo, sizeof(_ocmfInfo) - 1); close(fd); memcpy(_txId, ShmChargerInfo->OcmfInfo.GunOcmf[i].OcmfTxId, sizeof(ShmChargerInfo->OcmfInfo.GunOcmf[i].OcmfTxId)); memcpy(_ocmfKey, ShmChargerInfo->OcmfInfo.GunOcmf[i].PublicKey, sizeof(ShmChargerInfo->OcmfInfo.GunOcmf[i].PublicKey)); DB_Insert_Ocmf(localDb, i, _txId, _ocmfKey, _ocmfInfo); ShmChargerInfo->OcmfInfo.SysOcmfFlag.bits.OcmfPending = true; char cmdBuf[256] = {0}; sprintf(cmdBuf, "rm -f %s", fileName); system(cmdBuf); LOG_INFO("Gun %d TxId[%s] insert OCMF info ok, length: %d", i + 1, ShmChargerInfo->OcmfInfo.GunOcmf[i].OcmfTxId, _ocmfLength); } } else { LOG_INFO("Gun %d TxId[%s] OCMF info [%s] access fail", i + 1, ShmChargerInfo->OcmfInfo.GunOcmf[i].OcmfTxId, fileName); } memset(ShmChargerInfo->OcmfInfo.GunOcmf[i].OcmfTxId, 0x00, sizeof(ShmChargerInfo->OcmfInfo.GunOcmf[i].OcmfTxId)); memset(ShmChargerInfo->OcmfInfo.GunOcmf[i].PublicKey, 0x00, sizeof(ShmChargerInfo->OcmfInfo.GunOcmf[i].PublicKey)); ShmChargerInfo->OcmfInfo.GunOcmf[i].OcmfFlag.bits.OcmfReceived = false; } } // try to find ocmf pending in database if(ShmChargerInfo->OcmfInfo.SysOcmfFlag.bits.OcmfPending && !ShmChargerInfo->OcmfInfo.SysOcmfFlag.bits.OcmfNeedUpload) { _gunIndex = 0; memset(_txId, 0x00, sizeof(_txId)); memset(_ocmfKey, 0x00, sizeof(_ocmfKey)); memset(_ocmfInfo, 0x00, sizeof(_ocmfInfo)); ShmChargerInfo->OcmfInfo.SysOcmfIndex = 0; memset(ShmChargerInfo->OcmfInfo.SysOcmfTxId, 0x00, sizeof(ShmChargerInfo->OcmfInfo.SysOcmfTxId)); memset(ShmChargerInfo->OcmfInfo.SysOcmfPublicKey, 0x00, sizeof(ShmChargerInfo->OcmfInfo.SysOcmfPublicKey)); memset(ShmChargerInfo->OcmfInfo.SysOcmfInfo, 0x00, sizeof(ShmChargerInfo->OcmfInfo.SysOcmfInfo)); if(DB_Get_Undisposed_Ocmf(localDb, &_gunIndex, _txId, _ocmfKey, _ocmfInfo)) { ShmChargerInfo->OcmfInfo.SysOcmfIndex = _gunIndex; memcpy(ShmChargerInfo->OcmfInfo.SysOcmfTxId, _txId, sizeof(ShmChargerInfo->OcmfInfo.SysOcmfTxId)); memcpy(ShmChargerInfo->OcmfInfo.SysOcmfPublicKey, _ocmfKey, sizeof(ShmChargerInfo->OcmfInfo.SysOcmfPublicKey)); memcpy(ShmChargerInfo->OcmfInfo.SysOcmfInfo, _ocmfInfo, sizeof(ShmChargerInfo->OcmfInfo.SysOcmfInfo)); ShmChargerInfo->OcmfInfo.SysOcmfFlag.bits.OcmfNeedUpload = true; ShmChargerInfo->OcmfInfo.SysOcmfFlag.bits.OcmfUploading = false; LOG_INFO("Gun %d TxId[%s] OCMF info need upload", _gunIndex + 1, _txId); } else { LOG_INFO("There is no ocmf info pending"); ShmChargerInfo->OcmfInfo.SysOcmfFlag.CtrlValue = 0; } } // try to upload ocmf to backend if(ShmChargerInfo->OcmfInfo.SysOcmfFlag.bits.OcmfNeedUpload) { if(ShmSysConfigAndInfo->SysInfo.OcppConnStatus) { if(!ShmChargerInfo->OcmfInfo.SysOcmfFlag.bits.OcmfUploading) { if(!Is_Ocpp_SendOcmfDataReq(ShmChargerInfo->OcmfInfo.SysOcmfIndex)) { Set_Ocpp_OcmfData(ShmChargerInfo->OcmfInfo.SysOcmfIndex, ShmChargerInfo->OcmfInfo.SysOcmfPublicKey, ShmChargerInfo->OcmfInfo.SysOcmfInfo); Set_Ocpp_SendOcmfDataReq(ShmChargerInfo->OcmfInfo.SysOcmfIndex); LOG_INFO("Set Gun %d TxId[%s] update OCMF request", ShmChargerInfo->OcmfInfo.SysOcmfIndex + 1, ShmChargerInfo->OcmfInfo.SysOcmfTxId); ShmChargerInfo->OcmfInfo.SysOcmfFlag.bits.OcmfUploading = true; } } else { if(!Is_Ocpp_SendOcmfDataReq(ShmChargerInfo->OcmfInfo.SysOcmfIndex)) { DB_Update_Ocmf_Status(localDb, ShmChargerInfo->OcmfInfo.SysOcmfTxId, OCMF_SATAUS_UPDATED_OK); LOG_INFO("Gun %d TxId[%s] update OCMF info to backend ok", ShmChargerInfo->OcmfInfo.SysOcmfIndex + 1, ShmChargerInfo->OcmfInfo.SysOcmfTxId); ShmChargerInfo->OcmfInfo.SysOcmfFlag.bits.OcmfNeedUpload = false; ShmChargerInfo->OcmfInfo.SysOcmfFlag.bits.OcmfUploading = false; } } } else { if(ShmChargerInfo->OcmfInfo.SysOcmfFlag.bits.OcmfUploading) { Clean_Ocpp_SendOcmfDataReq(ShmChargerInfo->OcmfInfo.SysOcmfIndex); LOG_INFO("Backend disconnected, Gun %d TxId[%s] ocmf will update later", ShmChargerInfo->OcmfInfo.SysOcmfIndex + 1, ShmChargerInfo->OcmfInfo.SysOcmfTxId); } ShmChargerInfo->OcmfInfo.SysOcmfFlag.bits.OcmfUploading = false; } } } int main(void) { unsigned long time = 0; int _dispenser = 0; _isStandbyEnable = true; if(CreateShareMemory() == 0) { #ifdef SystemLogMessage LOG_ERROR("CreatShareMemory NG"); #endif if(ShmStatusCodeData!=NULL) { ShmStatusCodeData->AlarmCode.AlarmEvents.bits.FailToCreateShareMemory = 1; } sleep(5); system("reboot -f"); sleep(5); system("reboot -f"); } LOG_INFO("\n"); LOG_INFO("===== Boot and Initialization start ====="); LOG_INFO("Main Fork PID = %d", getpid()); if (!InitialSystemDefaultConfig()) { LOG_INFO("InitialSystemDefaultConfig NG"); StopProcessingLoop(); } LOG_INFO("ModelName: [%s], SN: [%s], SW Version: [%s][%s]", ShmSysConfigAndInfo->SysConfig.ModelName, ShmSysConfigAndInfo->SysConfig.SerialNumber, fwVersion, subVersion); LOG_INFO("InitialShareMemoryInfo"); InitialShareMemoryInfo(); LOG_INFO("ChargerType (IEC or UL) = %d", ShmSysConfigAndInfo->SysInfo.ChargerType); if(!InitialChargerSetting()) { isModelNameMatch = false; } Initialization(); InitialDataBaseValue(); LOG_INFO("Spawn all Task."); SpawnTask(); if (!isModelNameMatch) { LOG_INFO("Module Name & HW info none match."); ShmStatusCodeData->AlarmCode.AlarmEvents.bits.ModelNameNoneMatchStestFail = YES; // Module Name 與硬體對應不正確 LOG_ERROR("Module Name & HW info none match."); sleep(3); KillAllTask(); StopProcessingLoop(); } LOG_INFO("Module Name & HW info correct. Initialize......."); CreateTimeoutFork(); SelfTestRun(); while(ShmSysConfigAndInfo->SysInfo.BootingStatus != BOOT_COMPLETE) { sleep(1); } if(ShmSysConfigAndInfo->SysInfo.SelfTestSeq != _STEST_COMPLETE) { sleep(1); SelfTestFailReason(); } else { for (byte gun_index = 0; gun_index < ShmSysConfigAndInfo->SysConfig.TotalConnectorCount; gun_index++) { setChargerMode(gun_index, MODE_IDLE); if(ShmPsuData->PsuGroup[gun_index].GroupPresentPsuQuantity > 0 || !ShmChargerInfo->Control.PsuCtrl.bits.SelfTestOK) { ShmChargerInfo->Control.GunAvailable[gun_index] = YES; } } } if(ShmChargerInfo->Control.CabinetRole != _CROLE_SLAVE) { SetAcContactor(ON); SpawnOcppService(); SpawnMaintainOcppService(); } else { InitSlaveCabinetEthernet(); for (byte gun_index = 0; gun_index < ShmSysConfigAndInfo->SysConfig.TotalConnectorCount; gun_index++) { setChargerMode(gun_index, MODE_MAINTAIN); } } sleep(1); CreateWatchdog(); // Main loop LOG_INFO("%s \n", ShmSysConfigAndInfo->SysInfo.SelfTestSeq == _STEST_COMPLETE ? "****************************Main Loop**********************************" : "********************** SelfTest Fail **********************"); GetClockTime(&_cmdMainPriority_time); ShmChargerInfo->OcmfInfo.SysOcmfFlag.bits.OcmfPending = true; for (;;) { CheckGunAvailable(); CheckOcppStatus(); ChkPrimaryStatus(); ChkPsuStatus(); PsuFailureResume(); ChkConnectorAction(); if(IsUpgradeAvailable()) { CheckFactoryConfigFunction(); CheckFwUpdateFunction(); } if(CheckFlashUpdate() != YES) { // return fork process return 0; } CheckSoftHardReset(); StandbyCheck(); AuthorizeTimeoutProcess(); // check ocmf request CheckOcmfHandler(); // 當 AC 沒有搭上時,清除一些錯誤碼 //ClearAlarmCodeWhenAcOff(); if ((GetTimeoutValue(_cmdMainPriority_time) / uSEC_VAL) > MAIN_PRIORITY_INTERVAL) { CheckTask(); for (byte _index = 0; _index < ShmSysConfigAndInfo->SysConfig.TotalConnectorCount; _index++) { if((chargingInfo[_index]->SystemStatus >= S_PREPARING_FOR_EVSE && chargingInfo[_index]->SystemStatus <= S_CHARGING) || (chargingInfo[_index]->SystemStatus >= S_CCS_PRECHARGE_ST0 && chargingInfo[_index]->SystemStatus <= S_CCS_PRECHARGE_ST1)) { if (chargingInfo[_index]->SystemStatus == S_CHARGING && _ocppProfileChkFlag[_index] == 12) { Ocpp_ProfileReq_Cmd(_index); gunOutputVol[_index] = chargingInfo[_index]->PresentChargingVoltage; _ocppProfileChkFlag[_index] = 0; } else if (chargingInfo[_index]->SystemStatus != S_CHARGING) { Ocpp_ProfileReq_Cmd(_index); _ocppProfileChkFlag[_index] = 0; } else { _ocppProfileChkFlag[_index]++; } } if (chargingInfo[_index]->SystemStatus >= SYS_MODE_CHARGING && chargingInfo[_index]->SystemStatus <= SYS_MODE_ALARM) { DB_Update_LocalConsumption(localDb, _index, ShmChargerInfo->MeterValue[_index].LocalConsumption); if(ShmChargerInfo->MeterValue[_index].GunConsumption >= 0) { DB_Update_GunConsumption(localDb, _index, ShmChargerInfo->MeterValue[_index].GunConsumption); } } } CheckPsuLostQuantity(); GetClockTime(&_cmdMainPriority_time); } CheckMiscCommandRequirement(); CheckDispenserVersionUpdateRequirement(); MCabinetParallelingProcess(); SCabinetControllProcess(); UpdateChargingCapability(); GunErrorCollection(); for (byte gun_index = 0; gun_index < ShmSysConfigAndInfo->SysConfig.TotalConnectorCount; gun_index++) { //CheckGpioInStatus(); CheckErrorOccurStatus(gun_index); ChkOcppStatus(gun_index); if((chargingInfo[gun_index]->SystemStatus >= S_PREPARING_FOR_EVSE && chargingInfo[gun_index]->SystemStatus <= S_CHARGING) || (chargingInfo[gun_index]->SystemStatus >= S_CCS_PRECHARGE_ST0 && chargingInfo[gun_index]->SystemStatus <= S_CCS_PRECHARGE_ST1)) { if(chargingInfo[gun_index]->SystemStatus == S_CHARGING) { // 進充電後,如果輸出電壓落差大於 10V 則直接繼續看 ChargingProfile if (chargingInfo[gun_index]->PresentChargingVoltage >= gunOutputVol[gun_index] + 10 || chargingInfo[gun_index]->PresentChargingVoltage <= gunOutputVol[gun_index] - 10) { _ocppProfileChkFlag[gun_index] = 12; gunOutputVol[gun_index] = chargingInfo[gun_index]->PresentChargingVoltage; } } } CheckSmartChargeProfile(gun_index); Update_PowerConsumption(gun_index); CheckInProgress(gun_index); CheckDebugMode(gun_index); //LOG_INFO("index = %d, ErrorCode = %s \n", gun_index, ShmOCPP16Data->StatusNotification[gun_index].ErrorCode); switch(chargingInfo[gun_index]->SystemStatus) { case S_MAINTAIN: if(isModeChange(gun_index)) { if(ShmChargerInfo->Control.CabinetRole == _CROLE_SLAVE) { LOG_INFO("================== Slave Cabinet %d ==================", ShmChargerInfo->Control.CabinetSwitch - 1); } LOG_INFO("================== S_MAINTAIN (%x) ================== \n", gun_index + 1); Set_Connector_MiscCommand(gun_index, MISC_CONN_AVAILABILITY); GetClockTime(&_SystemStatus_Time[gun_index]); } time = GetSecTimeoutValue(_SystemStatus_Time[gun_index]); if(ShmSysConfigAndInfo->SysInfo.BootingStatus != BOOT_COMPLETE || ShmSysConfigAndInfo->SysInfo.SelfTestSeq != _STEST_COMPLETE || ShmChargerInfo->Control.CabinetRole == _CROLE_SLAVE) { break; } if(chargingInfo[gun_index]->IsAvailable == YES && ShmChargerInfo->Control.GunAvailable[gun_index] == YES && ShmChargerInfo->ParallelCabinet.ParallelStatus == _Parallel_None) { if(time >= MAINTAIN_RECOVERY_TIME) { Set_Connector_MiscCommand(gun_index, MISC_CONN_AVAILABILITY); setChargerMode(gun_index, MODE_IDLE); } } break; case S_RESERVATION: if(isModeChange(gun_index)) { LOG_INFO("================== S_RESERVATION (%x) ================== \n", gun_index + 1); char expiryDate[128]; Get_Ocpp_ReserveNowExpiryDate(gun_index, expiryDate); Get_Ocpp_ReserveNowIdTag(gun_index, &ShmChargerInfo->Control.ResevedIdTag[gun_index][0]); Set_Connector_MiscCommand(gun_index, MISC_CONN_RESERVATION); LOG_INFO("****** Reservation IdTag: [%s], Expiry: [%s]", &ShmChargerInfo->Control.ResevedIdTag[gun_index][0], expiryDate); GetClockTime(&_SystemStatus_Time[gun_index]); } if(chargingInfo[gun_index]->ConnectorPlugIn) { SetAcContactor(ON); } if (ShmSysConfigAndInfo->SysWarningInfo.Level == 2 || ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gun_index].RemoteStatus == _CRS_Alarm || ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gun_index].Parameter.bits.FaultStatusRequest || ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gun_index].Parameter.bits.Disconnection) { UpdateErrorCodeToOcpp(gun_index); setChargerMode(gun_index, MODE_FAULT); continue; } if(Is_Ocpp_ReserveNowExpired(gun_index)) { chargingInfo[gun_index]->ReservationId = -1; LOG_INFO("Gun %d reservation is expired...", gun_index + 1); setChargerMode(gun_index, MODE_IDLE); } else { if(IsConnectorAuthorizeSuccess(gun_index)) { if(ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gun_index].AuthInfo.AuthType == _AuthType_RemoteStart) { LOG_INFO("Gun %d remote start reserve charging", gun_index + 1); } else if(ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gun_index].AuthInfo.AuthType == _AuthType_RFID) { LOG_INFO("Gun %d swipe rfid start reserve charging", gun_index + 1); } setChargerMode(gun_index, MODE_AUTHORIZING); } else if(IsAutoGunSelectionAuthorizeSuccess(gun_index)) { _dispenser = ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gun_index].ParentDispensetIndex; if(Is_Ocpp_ReserveNowIdTag(gun_index, (char *)ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[_dispenser].AuthInfo.AuthId)) { SetAcContactor(ON); if(chargingInfo[gun_index]->ConnectorPlugIn && ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gun_index].RemoteStatus == _CRS_Preparing) { strcpy((char *)chargingInfo[gun_index]->StartUserId, (char *)ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[_dispenser].AuthInfo.AuthId); LOG_INFO("Gun %d reserve Auto Selection, CardNumber = %s", gun_index + 1, chargingInfo[gun_index]->StartUserId); if(strlen((char *)&ShmChargerInfo->PriceAndReceiptInfo.DispenserPriceString[_dispenser][0]) > 0) { strcpy((char *)&ShmChargerInfo->PriceAndReceiptInfo.UserPriceString[gun_index], (char *)&ShmChargerInfo->PriceAndReceiptInfo.DispenserPriceString[_dispenser][0]); Set_Connector_MiscCommand(gun_index, MISC_CONN_USER_PRICE_STRING); } DispenserAuthInitial(_dispenser); setChargerMode(gun_index, MODE_REASSIGN_CHECK); } } } else { if(chargingInfo[gun_index]->ReservationId == -1) { LOG_INFO("Gun %d reservation is clean", gun_index + 1); setChargerMode(gun_index, MODE_IDLE); } } } break; case S_IDLE: case S_FAULT: { // clean PermissionRequest flag ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gun_index].Parameter.bits.PermissionRequest = false; ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gun_index].Parameter.bits.PsuReleasable = true; if(isModeChange(gun_index)) { if (chargingInfo[gun_index]->SystemStatus == S_IDLE) { LOG_INFO("================== S_IDLE (%x) ================== \n", gun_index + 1); chargingInfo[gun_index]->ReservationId = -1; _triggerTransaction[gun_index] = false; _plugInHold[gun_index] = false; chargingInfo[gun_index]->PresentChargedDuration = 0; chargingInfo[gun_index]->RemainChargingDuration = 0; strcpy((char *)chargingInfo[gun_index]->StartDateTime, ""); strcpy((char *)chargingInfo[gun_index]->StopDateTime, ""); strcpy((char *)chargingInfo[gun_index]->StartUserId, ""); memset(ShmChargerInfo->Timestamp[gun_index].StartCharging, 0x00, sizeof(ShmChargerInfo->Timestamp[gun_index].StartCharging)); memset(ShmChargerInfo->Timestamp[gun_index].StopCharging, 0x00, sizeof(ShmChargerInfo->Timestamp[gun_index].StopCharging)); Clean_Ocpp_StopReason(gun_index); ReleaseAlarmCode(gun_index); // clean connector information ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gun_index].RemoteChargingVoltage = 0; ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gun_index].RemoteChargingCurrent = 0; ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gun_index].RemoteRemainChargingDuration = 0; ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gun_index].RemoteSoc = 0; ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gun_index].UserPrice = 0; ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gun_index].TotalCost = 0; ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gun_index].AccountBalance = -65535; ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gun_index].CostDiscount = 0; ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gun_index].RemainAmount = 0; ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gun_index].EnergyCost = -1; ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gun_index].ParkingFee = -1; ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gun_index].Parameter.bits.AnnounceBalance = false; ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gun_index].Parameter.bits.GetStartChargingSoc = false; memset(&ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gun_index].AuthInfo, 0x00, sizeof(AuthorizingInfoData)); ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gun_index].Parameter.bits.StartWaitPlug = false; ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gun_index].Parameter.bits.NeedCleanAuthorizeInfo = false; ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gun_index].Parameter.bits.OutputLimitEnable = false; ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gun_index].GeneralChargingData.deratingByConnOtp.deratingIndex = 0; chargingInfo[gun_index]->EvBatterytargetVoltage = 0; chargingInfo[gun_index]->EvBatterytargetCurrent = 0; chargingInfo[gun_index]->EvBatteryMaxVoltage = 0; chargingInfo[gun_index]->EvBatterySoc = 0; ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gun_index].RemoteTargetVoltage = 0; ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gun_index].RemoteTargetCurrent = 0; // clean RemoteStart & RemoteStop flag Clean_Connector_MiscCommand(gun_index, MISC_CONN_REMOTE_START); Clean_Connector_MiscCommand(gun_index, MISC_CONN_REMOTE_STOP); Clean_Connector_MiscCommand(gun_index, MISC_CONN_UNLOCK); ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gun_index].Parameter.bits.RemoteStartConfirm = false; ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gun_index].Parameter.bits.RemoteStopConfirm = false; ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gun_index].Parameter.bits.UnlockStopConfirm = false; ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gun_index].Parameter.bits.NormalStopRequest = false; ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gun_index].Parameter.bits.AlarmStopRequest = false; ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gun_index].Parameter.bits.FaultStatusRequest = false; ShmChargerInfo->GunError[gun_index].ErrFlag.ErrorValue = 0; memset(chargingInfo[gun_index]->ConnectorAlarmCode, 0x00, sizeof(chargingInfo[gun_index]->ConnectorAlarmCode)); Clean_Ocpp_RunningCost(gun_index); Clean_Ocpp_FinalCost(gun_index); Clean_DeductInfo(gun_index); Clean_Ocpp_TcciSerialNo(gun_index); Clean_UserTransaction(gun_index); Clean_UserPriceAndReceipt(gun_index); presentChargedEnergyClear(gun_index); chargingInfo[gun_index]->PresentChargingPower = 0; ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gun_index].MaxTotalChargingPower = 0; ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gun_index].MaxTotalChargingCurrent = 0; chargingInfo[gun_index]->ChargingProfilePower = -1; chargingInfo[gun_index]->ChargingProfileCurrent = -1; if(ShmChargerInfo->Control.FCharging[gun_index].FCtrl.bits.WebApiTrigger) { ShmChargerInfo->Control.FCharging[gun_index].FCtrl.bits.EnableForceCharging = false; ShmChargerInfo->Control.FCharging[gun_index].FCtrl.bits.WebApiTrigger = false; // reset dispenser availability Update_DispenserAvailability(ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gun_index].ParentDispensetIndex); } // clean force charging info memset(&ShmChargerInfo->Control.FCharging[gun_index], 0x00, sizeof(ForceCharging)); } else if (chargingInfo[gun_index]->SystemStatus == S_FAULT) { LOG_INFO("================== S_FAULT (%x) ================== \n", gun_index + 1); } GetClockTime(&_SystemStatus_Time[gun_index]); } if (chargingInfo[gun_index]->IsAvailable == NO || ShmChargerInfo->Control.GunAvailable[gun_index] == NO) { setChargerMode(gun_index, MODE_MAINTAIN); continue; } if (ShmSysConfigAndInfo->SysWarningInfo.Level == 2 || ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gun_index].RemoteStatus == _CRS_Alarm || ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gun_index].Parameter.bits.FaultStatusRequest || ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gun_index].Parameter.bits.Disconnection) { if(ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gun_index].Parameter.bits.FaultStatusRequest) { if(strncmp((char *)chargingInfo[gun_index]->ConnectorAlarmCode, "", 6) == EQUAL) { memcpy(chargingInfo[gun_index]->ConnectorAlarmCode, ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gun_index].RemotenAlarmCode, 6); } } ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gun_index].Parameter.bits.FaultStatusRequest = false; if(ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gun_index].Parameter.bits.Disconnection) { if(strncmp((char *)chargingInfo[gun_index]->ConnectorAlarmCode, "", 6) == EQUAL) { memcpy(chargingInfo[gun_index]->ConnectorAlarmCode, "042304", 6); LOG_INFO("Connector %d Disconnect Occur", gun_index + 1); } } if(chargingInfo[gun_index]->SystemStatus != S_FAULT) { UpdateErrorCodeToOcpp(gun_index); setChargerMode(gun_index, MODE_FAULT); } else { if(ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gun_index].Parameter.bits.Disconnection) { CheckConnectorDisconnectionRecovery(gun_index); } } } else { if (chargingInfo[gun_index]->SystemStatus == S_FAULT) { time = GetSecTimeoutValue(_SystemStatus_Time[gun_index]); if(time >= FAULT_RELEASE_TIME) { ReleaseAlarmCode(gun_index); setChargerMode(gun_index, MODE_IDLE); } break; } // clean stop charge flag chargingInfo[gun_index]->StopChargeFlag = false; chargingInfo[gun_index]->ChargingStopFlag.ChargingStopValue = 0; if(chargingInfo[gun_index]->ConnectorPlugIn || ShmChargerInfo->Control.CustomizedInfo.Flag.bits.StandbyTimeDisable) { SetAcContactor(ON); } { // Idle 正常程序起點 // 判斷是否有啟用檢查插槍 if(IsConnectorAuthorizeSuccess(gun_index)) { if(chargingInfo[gun_index]->IsAvailable && chargingInfo[gun_index]->SystemStatus == S_IDLE) { if(ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gun_index].AuthInfo.AuthType == _AuthType_RemoteStart) { LOG_INFO("Gun %d remote start charging", gun_index + 1); Clean_Ocpp_TcciCreditInfo(gun_index); } else if(ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gun_index].AuthInfo.AuthType == _AuthType_RFID) { LOG_INFO("Gun %d swipe rfid start charging", gun_index + 1); } Set_StartIdType(gun_index, ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gun_index].AuthInfo.AuthIdType); setChargerMode(gun_index, MODE_AUTHORIZING); continue; } } else if(IsAutoGunSelectionAuthorizeSuccess(gun_index)) { SetAcContactor(ON); if(chargingInfo[gun_index]->IsAvailable && chargingInfo[gun_index]->SystemStatus == S_IDLE && chargingInfo[gun_index]->ConnectorPlugIn && ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gun_index].RemoteStatus == _CRS_Preparing) { _dispenser = ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gun_index].ParentDispensetIndex; strcpy((char *)chargingInfo[gun_index]->StartUserId, (char *)ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[_dispenser].AuthInfo.AuthId); LOG_INFO("Gun %d Auto Selection, CardNumber = %s", gun_index + 1, chargingInfo[gun_index]->StartUserId); if(strlen((char *)&ShmChargerInfo->PriceAndReceiptInfo.DispenserPriceString[_dispenser][0]) > 0) { strcpy((char *)&ShmChargerInfo->PriceAndReceiptInfo.UserPriceString[gun_index], (char *)&ShmChargerInfo->PriceAndReceiptInfo.DispenserPriceString[_dispenser][0]); Set_Connector_MiscCommand(gun_index, MISC_CONN_USER_PRICE_STRING); } Set_StartIdType(gun_index, ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[_dispenser].AuthInfo.AuthIdType); DispenserAuthInitial(ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gun_index].ParentDispensetIndex); setChargerMode(gun_index, MODE_REASSIGN_CHECK); continue; } } // only for test & debug purpose else if(ShmChargerInfo->Control.FCharging[gun_index].FCtrl.bits.EnableForceCharging && ShmChargerInfo->Control.FCharging[gun_index].FCtrl.bits.StartForceCharging) { ShmChargerInfo->Control.FCharging[gun_index].FCtrl.bits.StartForceCharging = false; strcpy((char *)chargingInfo[gun_index]->StartUserId, "ChargingTest"); LOG_INFO("Gun %d Start Force Charging%s", gun_index + 1, ShmChargerInfo->Control.FCharging[gun_index].FCtrl.bits.WebApiTrigger > 0 ? ", Triggered by WebAPI" : ""); if(ShmChargerInfo->Control.TestCtrl.bits.FChargingReleaseExtend) { ShmChargerInfo->Control.FCharging[gun_index].FCtrl.bits.EnableReleaseAndExtend = true; LOG_INFO("Gun %d Enable ReleaseAndExtend At Force Charging", gun_index + 1); } if(ShmChargerInfo->Control.FCharging[gun_index].FCtrl.bits.WebApiTrigger) { LOG_INFO("Set Dispenser %d Inoperative", ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gun_index].ParentDispensetIndex + 1); Update_DispenserAvailability(ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gun_index].ParentDispensetIndex); } Set_StartIdType(gun_index, _Type_Local); setChargerMode(gun_index, MODE_REASSIGN_CHECK); continue; } else { } } // Idle 正常程序終點 } } break; case S_AUTHORIZING: if(isModeChange(gun_index)) { LOG_INFO("================== S_AUTHORIZING (%x) ================== \n", gun_index + 1); ShmSysConfigAndInfo->SysInfo.SystemPage = _LCM_NONE; if (ShmSysConfigAndInfo->SysInfo.OrderCharging != NO_DEFINE) ShmSysConfigAndInfo->SysInfo.OrderCharging = NO_DEFINE; //StopSystemTimeoutDet(); ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gun_index].Parameter.bits.PsuReleasable = false; ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gun_index].Parameter.bits.NeedCleanAuthorizeInfo = false; SetAcContactor(ON); GetClockTime(&_ConnectorAuthorizing_Time[gun_index]); } if(!_triggerTransaction[gun_index] && ShmChargerInfo->Control.CustomerCode == _CUSTOMER_CODE_TCC && ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gun_index].AuthInfo.AuthType == _AuthType_RemoteStart) { if(GetTimeoutValue(_ConnectorAuthorizing_Time[gun_index]) / uSEC_VAL >= STARTTRANSATION_TIME) { OcppStartTransaction(gun_index); } } if(GetTimeoutValue(_ConnectorAuthorizing_Time[gun_index]) / uSEC_VAL >= FORCE_BALANCE_TIME) { FouceAnnounceAccountBalance(gun_index); } if(ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gun_index].Parameter.bits.RemoteStartConfirm) { // sync with dispenser ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gun_index].Parameter.bits.RemoteStartConfirm = false; GetClockTime(&_ConnectorAuthorizing_Time[gun_index]); LOG_INFO("Sync with Gun %d through remote start", gun_index + 1); FouceAnnounceAccountBalance(gun_index); } if(ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gun_index].Parameter.bits.SwipeRfidConfirm) { // sync with dispenser ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gun_index].Parameter.bits.SwipeRfidConfirm = false; GetClockTime(&_ConnectorAuthorizing_Time[gun_index]); LOG_INFO("Sync with Connector %d through swipe rfid", gun_index + 1); } if(GetTimeoutValue(_ConnectorAuthorizing_Time[gun_index]) / uSEC_VAL >= ShmChargerInfo->CabinetMiscValue.ConnectionTimeout) { if(!chargingInfo[gun_index]->ConnectorPlugIn) { LOG_INFO("*********** Gun %d Plug In Timeout ***********", gun_index + 1); } else { LOG_INFO("*********** Gun %d Preparing State Timeout ***********", gun_index + 1); } OcppStopTransaction(gun_index); setChargerMode(gun_index, MODE_IDLE); } else { if(chargingInfo[gun_index]->ConnectorPlugIn && ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gun_index].RemoteStatus == _CRS_Preparing) { AddPlugInTimes(gun_index); LOG_INFO("Gun %d CardNumber = [%s]", gun_index + 1, chargingInfo[gun_index]->StartUserId); setChargerMode(gun_index, MODE_REASSIGN_CHECK); GunAuthInitial(gun_index); } else if(ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gun_index].Parameter.bits.NeedCleanAuthorizeInfo) { ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gun_index].Parameter.bits.StartWaitPlug = false; ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gun_index].Parameter.bits.NeedCleanAuthorizeInfo = false; LOG_INFO("*********** Gun %d User Stop Plug In ***********", gun_index + 1); OcppStopTransaction(gun_index); setChargerMode(gun_index, MODE_IDLE); } else if(isEvBoardStopChargeFlag(gun_index) == YES) { LOG_INFO("********** Gun %d Alarm Stop (S_AUTHORIZING) **********", gun_index + 1); Set_Ocpp_StopReason(gun_index, "Local"); ChargingAlarmProcess(gun_index); } else if(isNormalStopChargeFlag(gun_index) == YES) { LOG_INFO("********** Gun %d Normal Stop (S_AUTHORIZING) **********", gun_index + 1); Set_Ocpp_StopReason(gun_index, "EVDisconnected"); ChargingTerminalProcess(gun_index); } } break; case S_REASSIGN_CHECK: { if (isModeChange(gun_index)) { LOG_INFO("================== S_REASSIGN_CHECK (%x) ================== \n", gun_index + 1); ShmSysConfigAndInfo->SysInfo.SystemPage = _LCM_NONE; if (ShmSysConfigAndInfo->SysInfo.OrderCharging != NO_DEFINE) ShmSysConfigAndInfo->SysInfo.OrderCharging = NO_DEFINE; //StopSystemTimeoutDet(); ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gun_index].Parameter.bits.PsuReleasable = false; ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gun_index].MaxOutputEnergy = ShmSysConfigAndInfo->SysConfig.MaxChargingEnergy; ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gun_index].MaxOutputDuration = ShmSysConfigAndInfo->SysConfig.MaxChargingDuration; LOG_INFO("Max Total Current %d A, Max Total Power %d kW, Total Energy %d kWh, Total Duration %d", ShmSysConfigAndInfo->SysConfig.MaxChargingCurrent, ShmSysConfigAndInfo->SysConfig.MaxChargingPower, ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gun_index].MaxOutputEnergy, ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gun_index].MaxOutputDuration); SetAcContactor(ON); SetPCabinetOutputRelay(gun_index, ON); GetClockTime(&_SystemStatus_Time[gun_index]); } time = GetTimeoutValue(_SystemStatus_Time[gun_index]) / uSEC_VAL; if(ConnectorRequestToCharging(gun_index)) { setChargerMode(gun_index, MODE_REASSIGN); } else if(time >= WAIT_REASSIGN_TIME) { if(ShmPsuData->Work_Step != _WORK_CHARGING) { LOG_INFO("Gun %d Wait PSU Work Step Timeout", gun_index + 1); } else { LOG_INFO("Gun %d Request Charging Timeout", gun_index + 1); } ShmChargerInfo->GunError[gun_index].ErrFlag.bits.PsuGroupNoResource = true; if(strncmp((char *)chargingInfo[gun_index]->ConnectorAlarmCode, "", 6) == EQUAL) { memcpy(chargingInfo[gun_index]->ConnectorAlarmCode, "042279", 6); LOG_INFO("Gun %d No Psu Resource", gun_index + 1); } Set_Ocpp_StopReason(gun_index, "Local"); ChargingAlarmProcess(gun_index); //setChargerMode(gun_index, MODE_IDLE); } } break; case S_REASSIGN: { if (isModeChange(gun_index)) { LOG_INFO("================== S_REASSIGN (%x) ================== \n", gun_index + 1); //gettimeofday(&_toAverage_time, NULL); GetClockTime(&_SystemStatus_Time[gun_index]); } time = GetTimeoutValue(_SystemStatus_Time[gun_index]) / uSEC_VAL; if(IsConnectorGroupingCompleted(gun_index)) { setChargerMode(gun_index, MODE_PRECHARGE); } else if(time >= MAX_REQUEST_CHARGING_TIME) { LOG_INFO("Gun %d Grouping Timeout", gun_index + 1); setChargerMode(gun_index, MODE_IDLE); } } break; case S_PREPARNING: { if (isModeChange(gun_index)) { LOG_INFO("================== S_PREPARNING (%x) ================== \n", gun_index + 1); //StopGunInfoTimeoutDet(gun_index); //StartGunInfoTimeoutDet(gun_index, Timeout_Preparing); SetAcContactor(ON); GetClockTime(&_SystemStatus_Time[gun_index]); } UpdateGunPresentChargingPower(gun_index); time = GetTimeoutValue(_SystemStatus_Time[gun_index]) / uSEC_VAL; if ((chargingInfo[gun_index]->AvailableChargingPower > 10) && time >= MIN_WAIT_PREPARNING_TIME) { setChargerMode(gun_index, MODE_PREPARE_FOR_EV); break;; } if (isEvBoardStopChargeFlag(gun_index) == YES) { // 板端或後臺要求停止 LOG_INFO("********** Gun %d Alarm Stop (S_PREPARNING) **********", gun_index + 1); Set_Ocpp_StopReason(gun_index, "Local"); ChargingAlarmProcess(gun_index); } else if(isNormalStopChargeFlag(gun_index) == YES) { LOG_INFO("********** Gun %d Normal Stop (S_PREPARNING) %s**********", gun_index + 1, chargingInfo[gun_index]->ChargingStopFlag.bits.ManualStop ? "(ManualStop)" : ""); Set_Ocpp_StopReason(gun_index, "EVDisconnected"); ChargingTerminalProcess(gun_index); } else if(isResetStopChargeFlag(gun_index) == YES) { LOG_INFO("********** Gun %d Reset Stop (S_PREPARNING) %s**********", gun_index + 1, chargingInfo[gun_index]->ChargingStopFlag.bits.HardResetStop ? "(Hard)" : "(Soft)"); char *reason[16]; strcpy((char *)&reason[0], chargingInfo[gun_index]->ChargingStopFlag.bits.HardResetStop ? "HardReset" : "SoftReset"); Set_Ocpp_StopReason(gun_index, (char *)&reason[0]); ChargingTerminalProcess(gun_index); } else if(isBackendStopFlag(gun_index)) { LOG_INFO("********** Gun %d Backend Stop (S_PREPARNING) **********", gun_index + 1); Set_Ocpp_StopReason(gun_index, "Other"); ChargingTerminalProcess(gun_index); } if(time > GUN_PREPARE_TIMEOUT) { LOG_INFO("********** Gun %d PrepareTimeout **********", gun_index + 1); ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuNoResource = YES; if(strncmp((char *)chargingInfo[gun_index]->ConnectorAlarmCode, "", 6) == EQUAL) { memcpy(chargingInfo[gun_index]->ConnectorAlarmCode, "012279", 6); LOG_INFO("Gun %d No Psu Resource", gun_index + 1); } Set_Ocpp_StopReason(gun_index, "Local"); ChargingAlarmProcess(gun_index); } } break; case S_PREPARING_FOR_EV: // 等待車端的通訊 (EV 小板),待車端回報後,開始樁端的測試 { if (isModeChange(gun_index)) { LOG_INFO("================== S_PREPARING_FOR_EV (%x) ================== \n", gun_index + 1); //strcpy((char *)ShmSysConfigAndInfo->SysConfig.UserId, ""); //StopGunInfoTimeoutDet(gun_index); //StartGunInfoTimeoutDet(gun_index, Timeout_EvChargingDet); GetClockTime(&_SystemStatus_Time[gun_index]); } UpdateGunPresentChargingPower(gun_index); time = GetTimeoutValue(_SystemStatus_Time[gun_index]) / uSEC_VAL; if(ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gun_index].Parameter.bits.PermissionRequest) { setChargerMode(gun_index, MODE_PREPARE_FOR_EVSE); } // only for test & debug purpose else if(ShmChargerInfo->Control.FCharging[gun_index].FCtrl.bits.EnableForceCharging) { LOG_INFO("Gun %d [Force Charging] S_PREPARING_FOR_EV OK", gun_index + 1); ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gun_index].Parameter.bits.PermissionRequest = true; } if (isEvBoardStopChargeFlag(gun_index) == YES) { // 板端或後臺要求停止 LOG_INFO("********** Gun %d Alarm Stop (S_PREPARING_FOR_EV) **********", gun_index + 1); Set_Ocpp_StopReason(gun_index, "Local"); ChargingAlarmProcess(gun_index); } else if(isNormalStopChargeFlag(gun_index) == YES) { LOG_INFO("********** Gun %d Normal Stop (S_PREPARING_FOR_EV) %s**********", gun_index + 1, chargingInfo[gun_index]->ChargingStopFlag.bits.ManualStop ? "(ManualStop)" : ""); Set_Ocpp_StopReason(gun_index, "EVDisconnected"); ChargingTerminalProcess(gun_index); } else if(isResetStopChargeFlag(gun_index) == YES) { LOG_INFO("********** Gun %d Reset Stop (S_PREPARING_FOR_EV) %s**********", gun_index + 1, chargingInfo[gun_index]->ChargingStopFlag.bits.HardResetStop ? "(Hard)" : "(Soft)"); char *reason[16]; strcpy((char *)&reason[0], chargingInfo[gun_index]->ChargingStopFlag.bits.HardResetStop ? "HardReset" : "SoftReset"); Set_Ocpp_StopReason(gun_index, (char *)&reason[0]); ChargingTerminalProcess(gun_index); } else if(isBackendStopFlag(gun_index)) { LOG_INFO("********** Gun %d Backend Stop (S_PREPARING_FOR_EV) **********", gun_index + 1); Set_Ocpp_StopReason(gun_index, "Other"); ChargingTerminalProcess(gun_index); } if(time >= GUN_EV_WAIT_TIMEOUT) { LOG_INFO("********** Gun %d Wait Dispenser Timeout **********", gun_index + 1); ChargingTerminalProcess(gun_index); } } break; case S_PREPARING_FOR_EVSE: // 等待 RB 通訊及測試,並將狀態回報, CSU 確認 Pass 後,開始進入充電 { if (isModeChange(gun_index)) { LOG_INFO("================== S_PREPARING_FOR_EVSE (%x) ================== \n", gun_index + 1); GetClockTime(&_SystemStatus_Time[gun_index]); #ifdef STARTTRANSATION_IMMEDIATELY OcppStartTransaction(gun_index); #endif } CheckoutStartChargingSoc(gun_index, NO); UpdateGunPresentChargingPower(gun_index); time = GetTimeoutValue(_SystemStatus_Time[gun_index]) / uSEC_VAL; // only for test & debug purpose if(ShmChargerInfo->Control.FCharging[gun_index].FCtrl.bits.EnableForceCharging) { if(time >= FORCE_CHARGING_CMD_DELAY) { float voltage = (float)ShmChargerInfo->Control.FCharging[gun_index].FTargetVoltage / 10; float current = (float)ShmChargerInfo->Control.FCharging[gun_index].FTargetCurrent / 10; if(chargingInfo[gun_index]->EvBatterytargetVoltage != voltage || chargingInfo[gun_index]->EvBatterytargetCurrent != current) { LOG_INFO("Gun %d Set Force Charging Voltage %4d V, Current: %4d A", gun_index + 1, (int)voltage, (int)current); } chargingInfo[gun_index]->EvBatterytargetVoltage = voltage; chargingInfo[gun_index]->EvBatterytargetCurrent = current; } } if(ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gun_index].RemoteStatus == _CRS_Charging) { setChargerMode(gun_index, MODE_CHARGING); } // only for test & debug purpose else if(ShmChargerInfo->Control.FCharging[gun_index].FCtrl.bits.EnableForceCharging) { if(time >= FORCE_CHARGING_WAIT_EVSE) { LOG_INFO("Gun %d [Charging Simulation] S_PREPARING_FOR_EVSE OK", gun_index + 1); setChargerMode(gun_index, MODE_CHARGING); } } if (isEvBoardStopChargeFlag(gun_index) == YES) { // 板端或後臺要求停止 LOG_INFO("********** Gun %d Alarm Stop (S_PREPARING_FOR_EVSE) **********", gun_index + 1); Set_Ocpp_StopReason(gun_index, "Local"); ChargingAlarmProcess(gun_index); } else if(isNormalStopChargeFlag(gun_index) == YES) { LOG_INFO("********** Gun %d Normal Stop (S_PREPARING_FOR_EVSE) %s**********", gun_index + 1, chargingInfo[gun_index]->ChargingStopFlag.bits.ManualStop ? "(ManualStop)" : ""); Set_Ocpp_StopReason(gun_index, "EVDisconnected"); ChargingTerminalProcess(gun_index); } else if(isResetStopChargeFlag(gun_index) == YES) { LOG_INFO("********** Gun %d Reset Stop (S_PREPARING_FOR_EVSE) %s**********", gun_index + 1, chargingInfo[gun_index]->ChargingStopFlag.bits.HardResetStop ? "(Hard)" : "(Soft)"); char *reason[16]; strcpy((char *)&reason[0], chargingInfo[gun_index]->ChargingStopFlag.bits.HardResetStop ? "HardReset" : "SoftReset"); Set_Ocpp_StopReason(gun_index, (char *)&reason[0]); ChargingTerminalProcess(gun_index); } else if(isInvalidIdStopFlag(gun_index) == YES) { LOG_INFO("********** Gun %d InvalidId Stop (S_PREPARING_FOR_EVSE) **********", gun_index + 1); Set_Ocpp_StopReason(gun_index, "DeAuthorized"); ChargingTerminalProcess(gun_index); } else if(isBackendStopFlag(gun_index)) { LOG_INFO("********** Gun %d Backend Stop (S_PREPARING_FOR_EVSE) **********", gun_index + 1); Set_Ocpp_StopReason(gun_index, "Other"); ChargingTerminalProcess(gun_index); } if(time >= GUN_EV_WAIT_TIMEOUT) { LOG_INFO("********** Gun %d GFD timeout **********", gun_index + 1); ChargingTerminalProcess(gun_index); } } break; case S_CHARGING: // 剛進入充電狀態,等待 EV 小板要求的輸出電流後開始輸出 { if (isModeChange(gun_index)) { LOG_INFO("================== S_CHARGING (%x) ================== \n", gun_index + 1); //StopGunInfoTimeoutDet(gun_index); GetClockTime(&_SystemStatus_Time[gun_index]); GetClockTime(&_ChargedEnergy_Time[gun_index]); CheckoutStartChargingSoc(gun_index, YES); chargingInfo[gun_index]->PresentChargedDuration = 0; ChangeStartOrStopDateTime(YES, gun_index); #ifndef STARTTRANSATION_IMMEDIATELY OcppStartTransaction(gun_index); #endif } // only for test & debug purpose if(ShmChargerInfo->Control.FCharging[gun_index].FCtrl.bits.EnableForceCharging) { float voltage = (float)ShmChargerInfo->Control.FCharging[gun_index].FTargetVoltage / 10; float current = (float)ShmChargerInfo->Control.FCharging[gun_index].FTargetCurrent / 10; if(chargingInfo[gun_index]->EvBatterytargetVoltage != voltage || chargingInfo[gun_index]->EvBatterytargetCurrent != current) { LOG_INFO("Gun %d Set Force Charging Voltage %4d V, Current: %4d A", gun_index + 1, (int)voltage, (int)current); } chargingInfo[gun_index]->EvBatterytargetVoltage = voltage; chargingInfo[gun_index]->EvBatterytargetCurrent = current; } // 計算 Power //chargingInfo[gun_index]->PresentChargingPower = ((float)((chargingInfo[gun_index]->PresentChargingVoltage) * (chargingInfo[gun_index]->PresentChargingCurrent)) / 1000); //chargingInfo[gun_index]->PresentChargingPower = (((float)((ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gun_index].RemoteChargingVoltage) * (ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gun_index].RemoteChargingCurrent))) / 1000 / 100); UpdateGunPresentChargingPower(gun_index); ChargedEnergySummation(gun_index); CheckSessionTargetStop(gun_index); if (isEvBoardStopChargeFlag(gun_index)) { LOG_INFO("********** Gun %d Alarm Stop (S_CHARGING) **********", gun_index + 1); Set_Ocpp_StopReason(gun_index, "Local"); ChargingAlarmProcess(gun_index); } else if(isNormalStopChargeFlag(gun_index) == YES) { LOG_INFO("********** Gun %d Normal Stop (S_CHARGING) %s**********", gun_index + 1, chargingInfo[gun_index]->ChargingStopFlag.bits.ManualStop ? "(ManualStop)" : ""); Set_Ocpp_StopReason(gun_index, "EVDisconnected"); ChargingTerminalProcess(gun_index); } else if(isResetStopChargeFlag(gun_index) == YES) { LOG_INFO("********** Gun %d Reset Stop (S_CHARGING) %s**********", gun_index + 1, chargingInfo[gun_index]->ChargingStopFlag.bits.HardResetStop ? "(Hard)" : "(Soft)"); char *reason[16]; strcpy((char *)&reason[0], chargingInfo[gun_index]->ChargingStopFlag.bits.HardResetStop ? "HardReset" : "SoftReset"); Set_Ocpp_StopReason(gun_index, (char *)&reason[0]); ChargingTerminalProcess(gun_index); } else if(isInvalidIdStopFlag(gun_index) == YES) { LOG_INFO("********** Gun %d InvalidId Stop (S_CHARGING) **********", gun_index + 1); Set_Ocpp_StopReason(gun_index, "DeAuthorized"); ChargingTerminalProcess(gun_index); } else if(CheckBackendChargingTimeout(gun_index) || CheckBackendChargingEnergy(gun_index) || IsReachConfigMaxChargingSoc(gun_index)) { LOG_INFO("********** Gun %d Backend Condition Stop (S_CHARGING) **********", gun_index + 1); ChargingTerminalProcess(gun_index); } else if(isSessionTargetStopFlag(gun_index) == YES) { LOG_INFO("********** Gun %d SessionTarget Stop (S_CHARGING) **********", gun_index + 1); Set_Ocpp_StopReason(gun_index, "Other"); ChargingTerminalProcess(gun_index); } else if(isBackendStopFlag(gun_index)) { LOG_INFO("********** Gun %d Backend Stop (S_CHARGING) **********", gun_index + 1); Set_Ocpp_StopReason(gun_index, "Other"); ChargingTerminalProcess(gun_index); } } break; case S_ALARM: case S_TERMINATING: { if (isModeChange(gun_index)) { Set_Ocpp_StopReason(gun_index, "Other"); if (chargingInfo[gun_index]->SystemStatus == S_ALARM) { LOG_INFO("================== S_ALARM (%x) ================== \n", gun_index + 1); UpdateErrorCodeToOcpp(gun_index); TheEndCharging(gun_index); } else { LOG_INFO("================== S_TERMINATING (%x) ================== \n", gun_index + 1); } //StopGunInfoTimeoutDet(gun_index); GetClockTime(&_SystemStatus_Time[gun_index]); } UpdateGunPresentChargingPower(gun_index); time = GetTimeoutValue(_SystemStatus_Time[gun_index]) / uSEC_VAL; if((Is_DispenserStop(gun_index) && time >= STOP_TARTTRANSATION_DELAY) || time >= WAIT_DISPENSER_STOP_TIMEOUT) { OcppStopTransaction(gun_index); } else { ChargedEnergySummation(gun_index); } if (chargingInfo[gun_index]->SystemStatus == S_ALARM) { if(time >= GUN_COMP_WAIT_TIMEOUT) { if(!ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gun_index].Parameter.bits.PsuReleasable) { LOG_INFO ("********** Gun %d psu is releasable **********\n", gun_index + 1); ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gun_index].Parameter.bits.PsuReleasable = true; } } if(IsAvailableBackToIdle(gun_index) == YES && ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gun_index].Parameter.bits.PsuReleasable) { ReleaseAlarmCode(gun_index); setChargerMode(gun_index, MODE_IDLE); } } else { setChargerMode(gun_index, MODE_COMPLETE); } } break; case S_COMPLETE: { if (isModeChange(gun_index)) { LOG_INFO("================== S_COMPLETE (%x) ================== \n", gun_index + 1); TheEndCharging(gun_index); GetClockTime(&_SystemStatus_Time[gun_index]); } UpdateGunPresentChargingPower(gun_index); time = GetTimeoutValue(_SystemStatus_Time[gun_index]) / uSEC_VAL; if((Is_DispenserStop(gun_index) && time >= STOP_TARTTRANSATION_DELAY) || time >= WAIT_DISPENSER_STOP_TIMEOUT) { OcppStopTransaction(gun_index); } else { ChargedEnergySummation(gun_index); } if(time >= GUN_COMP_WAIT_TIMEOUT) { if(!ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gun_index].Parameter.bits.PsuReleasable) { LOG_INFO ("********** Gun %d psu is releasable **********", gun_index + 1); ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gun_index].Parameter.bits.PsuReleasable = true; } } if(IsAvailableBackToIdle(gun_index) == YES && ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gun_index].Parameter.bits.PsuReleasable) { setChargerMode(gun_index, MODE_IDLE); } } break; case S_CCS_PRECHARGE_ST0: if (isModeChange(gun_index)) { LOG_INFO("CCS Precharge Processing 1....................%x \n", gun_index); //StopGunInfoTimeoutDet(gun_index); //StartGunInfoTimeoutDet(gun_index, Timeout_ForCcsPrechargeDet); } break; case S_CCS_PRECHARGE_ST1: if (isModeChange(gun_index)) { LOG_INFO("CCS Precharge Processing 2....................%x \n", gun_index); } break; case S_DEBUG: if (isModeChange(gun_index)) { LOG_INFO("================== S_DEBUG (%x) ================== \n", gun_index + 1); } if(!ShmChargerInfo->Control.RelayCtrl.bits.AbnormalRelay && !ShmChargerInfo->Control.FanCtrl.bits.AbnormalFan) { setChargerMode(gun_index, MODE_IDLE); } break; } } TryFeedWatchdog(); usleep(whileLoopTime); } return FAIL; }