#include /*標準輸入輸出定義*/ #include /*標準函數庫定義*/ #include #include #include #include //------------------------------------------------------------------------------ int opcc_chk_reserve_expired(byte gun_index) { int result = NO; struct tm expiredDate; struct timeb expiredTime; if (ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { if (sscanf((char *) ShmOCPP16Data->ReserveNow[gun_index].ExpiryDate, "%4d-%2d-%2dT%2d:%2d:%2d", &expiredDate.tm_year, &expiredDate.tm_mon, &expiredDate.tm_mday, &expiredDate.tm_hour, &expiredDate.tm_min, &expiredDate.tm_sec) == 6) { expiredDate.tm_year -= 1900; expiredDate.tm_mon -= 1; expiredTime.time = mktime(&expiredDate); if (!CheckTimeOut(expiredTime)) { result = YES; } } } else if (ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { if (sscanf((char *) ShmOCPP20Data->ReserveNow[gun_index].expiryDateTime, "%4d-%2d-%2dT%2d:%2d:%2d", &expiredDate.tm_year, &expiredDate.tm_mon, &expiredDate.tm_mday, &expiredDate.tm_hour, &expiredDate.tm_min, &expiredDate.tm_sec) == 6) { expiredDate.tm_year -= 1900; expiredDate.tm_mon -= 1; expiredTime.time = mktime(&expiredDate); if (!CheckTimeOut(expiredTime)) { result = YES; } } } return result; } //=============================================== // OCPP routine //=============================================== void ocpp_process_start() { if (ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { system("/root/OcppBackend &"); } else if (ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { system("/root/OcppBackend20 &"); } } void ocpp_auto_response_BootNotification() { if (ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { if (ShmOCPP16Data->SpMsg.bits.BootNotificationConf == YES) { ShmOCPP16Data->SpMsg.bits.BootNotificationConf = NO; } } else if (ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { if (ShmOCPP20Data->SpMsg.bits.BootNotificationConf == YES) { ShmOCPP20Data->SpMsg.bits.BootNotificationConf = NO; } } } bool ocpp_is_resPass_StartTransationConf(byte gun_index) { bool result = false; if (ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { result = ShmOCPP16Data->CpMsg.bits[gun_index].StartTransactionConf; } else if (ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { result = ShmOCPP20Data->CpMsg.bits[gun_index].TransactionEventConf; } return result; } void ocpp_auto_response_StartTransationConf(byte gun_index) { if (ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { if (ShmOCPP16Data->CpMsg.bits[gun_index].StartTransactionConf) { ShmOCPP16Data->CpMsg.bits[gun_index].StartTransactionConf = NO; } } else if (ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { if (ShmOCPP20Data->CpMsg.bits[gun_index].TransactionEventConf) { ShmOCPP20Data->CpMsg.bits[gun_index].TransactionEventConf = NO; } } } void ocpp_auto_response_ReserveConf(byte gun_index) { if (ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { ShmOCPP16Data->CsMsg.bits[gun_index].ReserveNowConf = YES; } else if (ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { ShmOCPP20Data->CsMsg.bits[gun_index].ReserveNowConf = YES; } } bool ocpp_chk_authrization_cmd() { char buf2[16] = ""; memset(buf2, 0, ARRAY_SIZE(buf2)); if (ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { sprintf(buf2, "%s", ShmOCPP16Data->Authorize.ResponseIdTagInfo.Status); } else if (ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { sprintf(buf2, "%s", ShmOCPP20Data->Authorize.Response_idTokenInfo.status); } // 因為無法得知實際的長度,所以只能用搜尋的方式 if (strcmp(buf2, "Accepted") == EQUAL) { return true; } return false; } bool opcc_sub_get_reset_req() { bool result = false; if (ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { result = ShmOCPP16Data->MsMsg.bits.ResetReq; } else if (ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { result = ShmOCPP20Data->MsMsg.bits.ResetReq; } return result; } void ocpp_sub_run_reset(bool canReset) { if (ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { if (canReset && strcmp((char *)ShmOCPP16Data->Reset.Type, "Hard") == EQUAL) { DEBUG_ERROR_MSG("****** Hard Reboot ****** \n"); sprintf((char *)ShmOCPP16Data->Reset.ResponseStatus, "Accepted"); ShmOCPP16Data->MsMsg.bits.ResetReq = NO; ShmOCPP16Data->MsMsg.bits.ResetConf = YES; sleep(3); system("reboot -f"); } else if (canReset && strcmp((char *)ShmOCPP16Data->Reset.Type, "Soft") == EQUAL) { DEBUG_ERROR_MSG("****** Soft Reboot ****** \n"); sprintf((char *)ShmOCPP16Data->Reset.ResponseStatus, "Accepted"); ShmOCPP16Data->MsMsg.bits.ResetReq = NO; ShmOCPP16Data->MsMsg.bits.ResetConf = YES; sleep(3); KillAllTask(); system("/usr/bin/run_evse_restart.sh"); } } else if (ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { if (canReset && strcmp((char *)ShmOCPP20Data->Reset.type, "Immediate") == EQUAL) { DEBUG_ERROR_MSG("****** Hard Reboot ****** \n"); sprintf((char *)ShmOCPP20Data->Reset.Response_status, "Accepted"); ShmOCPP20Data->MsMsg.bits.ResetReq = NO; ShmOCPP20Data->MsMsg.bits.ResetConf = YES; sleep(3); system("reboot -f"); } else if (canReset && strcmp((char *)ShmOCPP20Data->Reset.type, "OnIdle") == EQUAL) { DEBUG_ERROR_MSG("****** Soft Reboot ****** \n"); sprintf((char *)ShmOCPP20Data->Reset.Response_status, "Accepted"); ShmOCPP20Data->MsMsg.bits.ResetReq = NO; ShmOCPP20Data->MsMsg.bits.ResetConf = YES; sleep(3); KillAllTask(); system("/usr/bin/run_evse_restart.sh"); } } } void ocpp_chk_reset_cmd() { if (opcc_sub_get_reset_req()) { 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) { // Reset 系統先停止充電 ChargingTerminalProcess(_index); } } } } if (canReset) { // Reset -> change status to maintain. for (byte _index = 0; _index < ShmSysConfigAndInfo->SysConfig.TotalConnectorCount; _index++) { setChargerMode(_index, MODE_MAINTAIN); } ChangeLcmByIndex(_LCM_FIX); } ocpp_sub_run_reset(canReset); } } void ocpp_chk_reserved_cmd(byte gunIndex) { if (ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { if (chargingInfo[gunIndex]->SystemStatus == S_IDLE && ShmOCPP16Data->CsMsg.bits[gunIndex].ReserveNowReq == YES) { ShmOCPP16Data->CsMsg.bits[gunIndex].ReserveNowReq = NO; if (opcc_chk_reserve_expired(gunIndex)) { PRINTF_FUNC("***************ChkOcppStatus : OcppReservedStatus******************** \n"); DEBUG_ERROR_MSG("***************ChkOcppStatus : OcppReservedStatus******************** \n"); chargingInfo[gunIndex]->ReservationId = ShmOCPP16Data->ReserveNow[gunIndex].ReservationId; chargingInfo[gunIndex]->SystemStatus = S_RESERVATION; } ShmOCPP16Data->CsMsg.bits[gunIndex].ReserveNowConf = YES; } if (chargingInfo[gunIndex]->SystemStatus == S_RESERVATION && ShmOCPP16Data->CsMsg.bits[gunIndex].CancelReservationReq == YES) { ShmOCPP16Data->CsMsg.bits[gunIndex].CancelReservationReq = NO; if (opcc_chk_reserve_expired(gunIndex)) { PRINTF_FUNC("***************ChkOcppStatus : Cancel OcppReservedStatus******************** \n"); DEBUG_ERROR_MSG("***************ChkOcppStatus : Cancel OcppReservedStatus******************** \n"); chargingInfo[gunIndex]->ReservationId = 0; chargingInfo[gunIndex]->SystemStatus = S_IDLE; } ShmOCPP16Data->CsMsg.bits[gunIndex].CancelReservationConf = YES; } } else if (ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { if (chargingInfo[gunIndex]->SystemStatus == S_IDLE && ShmOCPP20Data->CsMsg.bits[gunIndex].ReserveNowReq == YES) { ShmOCPP20Data->CsMsg.bits[gunIndex].ReserveNowReq = NO; if (opcc_chk_reserve_expired(gunIndex)) { PRINTF_FUNC("***************ChkOcppStatus : OcppReservedStatus******************** \n"); DEBUG_ERROR_MSG("***************ChkOcppStatus : OcppReservedStatus******************** \n"); chargingInfo[gunIndex]->ReservationId = ShmOCPP20Data->ReserveNow[gunIndex].id; chargingInfo[gunIndex]->SystemStatus = S_RESERVATION; } ShmOCPP20Data->CsMsg.bits[gunIndex].ReserveNowConf = YES; } if (chargingInfo[gunIndex]->SystemStatus == S_RESERVATION && ShmOCPP20Data->CsMsg.bits[gunIndex].CancelReservationReq == YES) { ShmOCPP20Data->CsMsg.bits[gunIndex].CancelReservationReq = NO; if (opcc_chk_reserve_expired(gunIndex)) { PRINTF_FUNC("***************ChkOcppStatus : Cancel OcppReservedStatus******************** \n"); DEBUG_ERROR_MSG("***************ChkOcppStatus : Cancel OcppReservedStatus******************** \n"); chargingInfo[gunIndex]->ReservationId = 0; chargingInfo[gunIndex]->SystemStatus = S_IDLE; } ShmOCPP20Data->CsMsg.bits[gunIndex].CancelReservationConf = YES; } } } void ocpp_chk_availability_cmd(byte gunIndex) { byte type = 0; // 0 : none, 1 : operative, 2 inoperative if (ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { if (ShmOCPP16Data->CsMsg.bits[gunIndex].ChangeAvailabilityReq == YES) { PRINTF_FUNC("***************ChkOcppStatus : OcppChangeAvailability******************** \n"); DEBUG_ERROR_MSG("***************ChkOcppStatus : OcppChangeAvailability******************** \n"); ShmOCPP16Data->CsMsg.bits[gunIndex].ChangeAvailabilityReq = NO; if (strcmp((char *)ShmOCPP16Data->ChangeAvailability[gunIndex].Type, "Operative") == EQUAL) { if (isDb_ready) { DB_Update_Operactive(localDb, gunIndex, true); } type = 1; } else if (strcmp((char *)ShmOCPP16Data->ChangeAvailability[gunIndex].Type, "Inoperative") == EQUAL) { if (isDb_ready) { DB_Update_Operactive(localDb, gunIndex, false); } type = 2; } } } else if (ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { if (ShmOCPP20Data->CsMsg.bits[gunIndex].ChangeAvailabilityReq == YES) { PRINTF_FUNC("***************ChkOcppStatus : OcppChangeAvailability******************** \n"); DEBUG_ERROR_MSG("***************ChkOcppStatus : OcppChangeAvailability******************** \n"); ShmOCPP20Data->CsMsg.bits[gunIndex].ChangeAvailabilityReq = NO; if (strcmp((char *)ShmOCPP20Data->ChangeAvailability[gunIndex].operationalStatus, "Operative") == EQUAL) { if (isDb_ready) { DB_Update_Operactive(localDb, gunIndex, true); } type = 1; } else if (strcmp((char *)ShmOCPP20Data->ChangeAvailability[gunIndex].operationalStatus, "Inoperative") == EQUAL) { if (isDb_ready) { DB_Update_Operactive(localDb, gunIndex, false); } type = 2; } } } if (type == 1) { chargingInfo[gunIndex]->IsAvailable = YES; if (chargingInfo[gunIndex]->SystemStatus == S_IDLE || chargingInfo[gunIndex]->SystemStatus == S_RESERVATION || chargingInfo[gunIndex]->SystemStatus == S_MAINTAIN) { setChargerMode(gunIndex, MODE_IDLE); } } else if (type == 2) { chargingInfo[gunIndex]->IsAvailable = NO; if (chargingInfo[gunIndex]->SystemStatus == S_IDLE || chargingInfo[gunIndex]->SystemStatus == S_RESERVATION || chargingInfo[gunIndex]->SystemStatus == S_MAINTAIN) { setChargerMode(gunIndex, MODE_MAINTAIN); } } } void ocpp_chk_unlock_cmd(byte gunIndex) { if (ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { if (ShmOCPP16Data->CsMsg.bits[gunIndex].UnlockConnectorReq == YES) { ShmOCPP16Data->CsMsg.bits[gunIndex].UnlockConnectorReq = NO; if (chargingInfo[gunIndex]->SystemStatus >= S_REASSIGN_CHECK && chargingInfo[gunIndex]->SystemStatus <= S_CHARGING) { // Unlocked - 充電中,需停止充電 strcpy((char *)ShmOCPP16Data->StopTransaction[gunIndex].StopReason, "UnlockCommand"); ChargingTerminalProcess(gunIndex); } strcpy((char *)ShmOCPP16Data->UnlockConnector[gunIndex].ResponseStatus, "Unlocked"); ShmOCPP16Data->CsMsg.bits[gunIndex].UnlockConnectorConf = YES; } } else if (ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { if (ShmOCPP20Data->CsMsg.bits[gunIndex].UnlockConnectorReq == YES) { ShmOCPP20Data->CsMsg.bits[gunIndex].UnlockConnectorReq = NO; if (chargingInfo[gunIndex]->SystemStatus >= S_REASSIGN_CHECK && chargingInfo[gunIndex]->SystemStatus <= S_CHARGING) { // Unlocked - 充電中,需停止充電 strcpy((char *)ShmOCPP20Data->TransactionEvent[gunIndex].transactionInfo.stoppedReason, "UnlockCommand"); ChargingTerminalProcess(gunIndex); } strcpy((char *)ShmOCPP20Data->UnlockConnector[gunIndex].Response_status, "Unlocked"); ShmOCPP20Data->CsMsg.bits[gunIndex].UnlockConnectorConf = YES; } } } bool ocpp_chk_remoteStop_cmd(byte gunIndex) { byte acDirIndex = ShmSysConfigAndInfo->SysConfig.AcConnectorCount; // 有 AC 槍的話 if (acDirIndex > 0 && gunIndex > 0) { gunIndex += acDirIndex; } bool result = false; if (ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { result = ShmOCPP16Data->CsMsg.bits[gunIndex].RemoteStopTransactionReq; } else if (ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { result = ShmOCPP20Data->CsMsg.bits[gunIndex].RequestStopTransactionReq; } if (result) { DEBUG_INFO_MSG("Remote Stop by OCPP (%d) \n", gunIndex); if (ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { strcpy((char *)ShmOCPP16Data->StopTransaction[gunIndex].StopReason, "Remote"); ShmOCPP16Data->CsMsg.bits[gunIndex].RemoteStopTransactionReq = NO; } else if (ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { strcpy((char *)ShmOCPP20Data->TransactionEvent[gunIndex].transactionInfo.stoppedReason, "Remote"); ShmOCPP20Data->CsMsg.bits[gunIndex].RequestStopTransactionReq = NO; } } return result; } bool ocpp_sub_get_remote_start_transaction_req(byte gun_index) { bool result = false; if (ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { result = ShmOCPP16Data->CsMsg.bits[gun_index].RemoteStartTransactionReq; } else if (ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { result = ShmOCPP20Data->CsMsg.bits[gun_index].RequestStartTransactionReq; } if (result) { strcpy((char *)ShmOCPP16Data->StartTransaction[gun_index].IdTag, (char *)ShmOCPP16Data->RemoteStartTransaction[gun_index].IdTag); } return result; } void ocpp_sub_set_remote_start_transaction_req(byte gunIndex, bool result) { if (ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { ShmOCPP16Data->CsMsg.bits[gunIndex].RemoteStartTransactionReq = result; } else if (ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { ShmOCPP20Data->CsMsg.bits[gunIndex].RequestStartTransactionReq = result; } } void ocpp_chk_remoteStart_cmd() { if (ShmSysConfigAndInfo->SysConfig.OfflinePolicy == _OFFLINE_POLICY_NO_CHARGING) {} else if (!isDetectPlugin()) { // 如果有 AC 槍,則固定是第 2 把槍,所以索引固定為 1 byte acDirIndex = ShmSysConfigAndInfo->SysConfig.AcConnectorCount; for (byte ac_index = 0; ac_index < ShmSysConfigAndInfo->SysConfig.AcConnectorCount; ac_index++) { if (ocpp_sub_get_remote_start_transaction_req(acDirIndex)) { if (ac_chargingInfo[ac_index]->SystemStatus == S_IDLE || ac_chargingInfo[ac_index]->SystemStatus == S_RESERVATION) { ac_chargingInfo[ac_index]->RemoteStartFlag = YES; ShmSysConfigAndInfo->SysInfo.OrderCharging = YES; //ShmSysConfigAndInfo->SysInfo.OrderCharging = DEFAULT_AC_INDEX; //ShmOCPP16Data->CsMsg.bits[ShmSysConfigAndInfo->SysConfig.TotalConnectorCount + ac_index].RemoteStartTransactionReq = NO; DetectPluginStart(ac_index); return; } ocpp_sub_set_remote_start_transaction_req(acDirIndex, NO); } } byte threeGunIndex = 0; byte dcIndex = 0; bool isGunUsingStatus = false; byte scheduleIndex = 0; for (byte _index = 0; _index < ShmSysConfigAndInfo->SysConfig.TotalConnectorCount; _index++) { // 如果有 AC 槍,且 DC 槍也有兩把 if (acDirIndex == 1 && _index == 1) { threeGunIndex = 1; } if (ocpp_sub_get_remote_start_transaction_req(_index + threeGunIndex)) { dcIndex = _index; } if (chargingInfo[_index]->SystemStatus != S_IDLE) { isGunUsingStatus = true; } if (chargingInfo[_index]->schedule.isTriggerStart) { scheduleIndex = _index; } } // 如果是雙槍單模,只認閒置狀態的槍,如果有預約~ 則預約也算被使用 if (isGunUsingStatus && ShmSysConfigAndInfo->SysInfo.IsAlternatvieConf) { if (dcIndex == 0) { threeGunIndex = 0; } ocpp_sub_set_remote_start_transaction_req(dcIndex + threeGunIndex, NO); return; } if (dcIndex == 0) { threeGunIndex = 0; } if (ocpp_sub_get_remote_start_transaction_req(dcIndex + threeGunIndex)) { if (chargingInfo[dcIndex]->SystemStatus == S_IDLE || chargingInfo[dcIndex]->SystemStatus == S_RESERVATION) { chargingInfo[dcIndex]->RemoteStartFlag = YES; ShmSysConfigAndInfo->SysInfo.OrderCharging = YES; //ShmSysConfigAndInfo->SysInfo.OrderCharging = gun_index; DetectPluginStart(dcIndex); } ocpp_sub_set_remote_start_transaction_req(dcIndex + threeGunIndex, NO); } else if (chargingInfo[scheduleIndex]->schedule.isTriggerStart) { if (chargingInfo[scheduleIndex]->SystemStatus == S_IDLE || chargingInfo[scheduleIndex]->SystemStatus == S_RESERVATION) { chargingInfo[scheduleIndex]->RemoteStartFlag = YES; ShmSysConfigAndInfo->SysInfo.OrderCharging = YES; DetectPluginStart(scheduleIndex); } chargingInfo[scheduleIndex]->schedule.isTriggerStart = NO; } } } void ocpp_chk_update_cmd() { if (ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { if (ShmOCPP16Data->MsMsg.bits.UpdateFirmwareReq == YES) { ShmOCPP16Data->MsMsg.bits.UpdateFirmwareReq = NO; if (strcmp((char *)ShmOCPP16Data->FirmwareStatusNotification.Status, "Downloaded") == EQUAL) { DEBUG_INFO_MSG("Backend : update start. \n"); sleep(2); strcpy((char *)ShmOCPP16Data->FirmwareStatusNotification.Status, ""); strcpy((char *)ShmOCPP16Data->FirmwareStatusNotification.Status, "Installing"); ShmOCPP16Data->SpMsg.bits.FirmwareStatusNotificationReq = YES; KillTask(); for (byte _index = 0; _index < ShmSysConfigAndInfo->SysConfig.TotalConnectorCount; _index++) { setChargerMode(_index, MODE_UPDATE); } for (byte _index = 0; _index < ShmSysConfigAndInfo->SysConfig.AcConnectorCount; _index++) { ac_chargingInfo[_index]->SystemStatus = MODE_UPDATE; } byte updateResult = CheckUpdateProcess(); if (updateResult == PASS) { DEBUG_INFO_MSG("Backend : update complete. \n"); strcpy((char *)ShmOCPP16Data->FirmwareStatusNotification.Status, "Installed"); } else if (updateResult == MODELNAME_FAIL) { DEBUG_INFO_MSG("Backend : model name is none match. \n"); strcpy((char *)ShmOCPP16Data->FirmwareStatusNotification.Status, "InstallationFailed"); ShmOCPP16Data->SpMsg.bits.FirmwareStatusNotificationReq = YES; sleep(5); KillAllTask(); system("/usr/bin/run_evse_restart.sh"); return; } else { DEBUG_INFO_MSG("Backend : update fail. \n"); strcpy((char *)ShmOCPP16Data->FirmwareStatusNotification.Status, "InstallationFailed"); } strcpy((char *)ShmOCPP16Data->FirmwareStatusNotification.Status, "Installed"); ShmOCPP16Data->SpMsg.bits.FirmwareStatusNotificationReq = YES; sleep(5); system("reboot -f"); } } } else if (ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { if (ShmOCPP20Data->MsMsg.bits.UpdateFirmwareReq == YES) { ShmOCPP20Data->MsMsg.bits.UpdateFirmwareReq = NO; if (strcmp((char *)ShmOCPP20Data->FirmwareStatusNotification.status, "Downloaded") == EQUAL) { DEBUG_INFO_MSG("Backend : update start. \n"); sleep(2); strcpy((char *)ShmOCPP20Data->FirmwareStatusNotification.status, ""); strcpy((char *)ShmOCPP20Data->FirmwareStatusNotification.status, "Installing"); ShmOCPP20Data->SpMsg.bits.FirmwareStatusNotificationReq = YES; KillTask(); for (byte _index = 0; _index < ShmSysConfigAndInfo->SysConfig.TotalConnectorCount; _index++) { setChargerMode(_index, MODE_UPDATE); } for (byte _index = 0; _index < ShmSysConfigAndInfo->SysConfig.AcConnectorCount; _index++) { ac_chargingInfo[_index]->SystemStatus = MODE_UPDATE; } byte updateResult = CheckUpdateProcess(); if (updateResult == PASS) { DEBUG_INFO_MSG("Backend : update complete. \n"); strcpy((char *)ShmOCPP20Data->FirmwareStatusNotification.status, "Installed"); } else if (updateResult == MODELNAME_FAIL) { DEBUG_INFO_MSG("Backend : model name is none match. \n"); strcpy((char *)ShmOCPP20Data->FirmwareStatusNotification.status, "InstallationFailed"); ShmOCPP20Data->SpMsg.bits.FirmwareStatusNotificationReq = YES; sleep(5); KillAllTask(); system("/usr/bin/run_evse_restart.sh"); return; } else { DEBUG_INFO_MSG("Backend : update fail. \n"); strcpy((char *)ShmOCPP20Data->FirmwareStatusNotification.status, "InstallationFailed"); } strcpy((char *)ShmOCPP20Data->FirmwareStatusNotification.status, "Installed"); ShmOCPP20Data->SpMsg.bits.FirmwareStatusNotificationReq = YES; sleep(5); system("reboot -f"); } } } } bool ocpp_chk_invalid_id_cmd(byte gunIndex) { if (ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { if (strstr((char *) ShmOCPP16Data->ConfigurationTable.CoreProfile[StopTransactionOnInvalidId].ItemData, "TRUE")) { if (strcmp((char *)ShmOCPP16Data->StartTransaction[gunIndex].ResponseIdTagInfo.Status, "Blocked") == EQUAL || strcmp((char *)ShmOCPP16Data->StartTransaction[gunIndex].ResponseIdTagInfo.Status, "Expired") == EQUAL || strcmp((char *)ShmOCPP16Data->StartTransaction[gunIndex].ResponseIdTagInfo.Status, "Invalid") == EQUAL) { return true; } } } else if (ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { if (strstr((char *) ShmOCPP20Data->ControllerComponentVariable[TxCtrlr_StopTxOnInvalidId].variableAttribute[0].value, "TRUE")) { if (strcmp((char *)ShmOCPP20Data->TransactionEvent[gunIndex].Response_idTokenInfo.status, "Blocked") == EQUAL || strcmp((char *)ShmOCPP20Data->TransactionEvent[gunIndex].Response_idTokenInfo.status, "Expired") == EQUAL || strcmp((char *)ShmOCPP20Data->TransactionEvent[gunIndex].Response_idTokenInfo.status, "Invalid") == EQUAL || strcmp((char *)ShmOCPP20Data->TransactionEvent[gunIndex].Response_idTokenInfo.status, "NoCredit") == EQUAL || strcmp((char *)ShmOCPP20Data->TransactionEvent[gunIndex].Response_idTokenInfo.status, "NotAllowedTypeEVSE") == EQUAL || strcmp((char *)ShmOCPP20Data->TransactionEvent[gunIndex].Response_idTokenInfo.status, "NotAtThisLocation") == EQUAL || strcmp((char *)ShmOCPP20Data->TransactionEvent[gunIndex].Response_idTokenInfo.status, "NotAtThisTime") == EQUAL || strcmp((char *)ShmOCPP20Data->TransactionEvent[gunIndex].Response_idTokenInfo.status, "Unknown") == EQUAL) { return true; } } } return false; } bool ocpp_chk_profileConf_cmd(byte _index) { if (ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { if (ShmOCPP16Data->CSUMsg.bits[_index].ChargingProfileConf == YES) { ShmOCPP16Data->CSUMsg.bits[_index].ChargingProfileConf = NO; return true; } } else if (ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { if (ShmOCPP20Data->CSUMsg.bits[_index].ChargingProfileConf == YES) { ShmOCPP20Data->CSUMsg.bits[_index].ChargingProfileConf = NO; return true; } } return false; } void ocpp_lift_profileReq_cmd(byte gunIndex) { if (ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { if (ShmOCPP16Data->CSUMsg.bits[gunIndex].ChargingProfileConf == NO) { if (ShmOCPP16Data->CSUMsg.bits[gunIndex].ChargingProfileReq == NO) { ShmOCPP16Data->CSUMsg.bits[gunIndex].ChargingProfileReq = YES; } } } else if (ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { if (ShmOCPP20Data->CSUMsg.bits[gunIndex].ChargingProfileConf == NO) { if (ShmOCPP20Data->CSUMsg.bits[gunIndex].ChargingProfileReq == NO) { ShmOCPP20Data->CSUMsg.bits[gunIndex].ChargingProfileReq = YES; } } } } void ocpp_set_startTransation_cmd(byte gunIndex) { byte _OcppGunIndex = gunIndex; // 如果有 AC 槍,而現在是 DC 第二把槍進入充電 if (ShmSysConfigAndInfo->SysConfig.AcConnectorCount == 1 && gunIndex == 1) { _OcppGunIndex = 2; } if (ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { if (strcmp((char *)chargingInfo[gunIndex]->StartUserId, "") == EQUAL) { strcpy((char *)ShmOCPP16Data->StartTransaction[_OcppGunIndex].IdTag, (char *)ShmOCPP16Data->StartTransaction[_OcppGunIndex].IdTag); } else { strcpy((char *)ShmOCPP16Data->StartTransaction[_OcppGunIndex].IdTag, (char *)chargingInfo[gunIndex]->StartUserId); } PRINTF_FUNC("IdTag = %s \n", ShmOCPP16Data->StartTransaction[_OcppGunIndex].IdTag); ShmOCPP16Data->CpMsg.bits[_OcppGunIndex].StartTransactionReq = YES; } else if (ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { if (strcmp((char *)chargingInfo[gunIndex]->StartUserId, "") == EQUAL) { strcpy((char *)ShmOCPP20Data->TransactionEvent[_OcppGunIndex].idToken.idToken, (char *)ShmOCPP20Data->TransactionEvent[_OcppGunIndex].idToken.idToken); } else { strcpy((char *)ShmOCPP20Data->TransactionEvent[_OcppGunIndex].idToken.idToken, (char *)chargingInfo[gunIndex]->StartUserId); } PRINTF_FUNC("IdTag = %s \n", ShmOCPP20Data->TransactionEvent[_OcppGunIndex].idToken.idToken); ShmOCPP20Data->CpMsg.bits[_OcppGunIndex].TransactionEventReq = YES; } } void ocpp_set_stopTransation_cmd(byte gunIndex) { byte _OcppGunIndex = gunIndex; // 如果有 AC 槍,而現在是 DC 第二把槍進入充電 if (ShmSysConfigAndInfo->SysConfig.AcConnectorCount == 1 && gunIndex == 1) { _OcppGunIndex = 2; } if (ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { if (strcmp((char *)chargingInfo[gunIndex]->StartUserId, "") == EQUAL) { strcpy((char *)ShmOCPP16Data->StopTransaction[_OcppGunIndex].IdTag, (char *)ShmOCPP16Data->StopTransaction[_OcppGunIndex].IdTag); } else { strcpy((char *)ShmOCPP16Data->StopTransaction[_OcppGunIndex].IdTag, (char *)chargingInfo[gunIndex]->StartUserId); } PRINTF_FUNC("IdTag = %s \n", ShmOCPP16Data->StopTransaction[_OcppGunIndex].IdTag); ShmOCPP16Data->CpMsg.bits[_OcppGunIndex].StopTransactionReq = YES; } else if (ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { if (strcmp((char *)chargingInfo[gunIndex]->StartUserId, "") == EQUAL) { strcpy((char *)ShmOCPP20Data->TransactionEvent[_OcppGunIndex].idToken.idToken, (char *)ShmOCPP20Data->TransactionEvent[_OcppGunIndex].idToken.idToken); } else { strcpy((char *)ShmOCPP20Data->TransactionEvent[_OcppGunIndex].idToken.idToken, (char *)chargingInfo[gunIndex]->StartUserId); } PRINTF_FUNC("IdTag = %s \n", ShmOCPP20Data->TransactionEvent[_OcppGunIndex].idToken.idToken); ShmOCPP20Data->CpMsg.bits[_OcppGunIndex].TransactionEventReq = YES; } } void ocpp_set_errorCode_cmd(byte gunIndex, char *errString) { if (ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { strcpy((char *)ShmOCPP16Data->StatusNotification[gunIndex].ErrorCode, errString); } else if (ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { } } void ocpp_set_stopReason_by_cmd(byte gunIndex, char *reason) { if (ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { if (strcmp((char *)ShmOCPP16Data->StopTransaction[gunIndex].StopReason, "") == EQUAL) { strcpy((char *)ShmOCPP16Data->StopTransaction[gunIndex].StopReason, reason); } } else if (ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { if (strcmp((char *)ShmOCPP20Data->TransactionEvent[gunIndex].transactionInfo.stoppedReason, "") == EQUAL) { strcpy((char *)ShmOCPP20Data->TransactionEvent[gunIndex].transactionInfo.stoppedReason, reason); } } } void ocpp_set_authorizeReq_cmd(byte value) { if (ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { ShmOCPP16Data->SpMsg.bits.AuthorizeReq = value; } else if (ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { ShmOCPP20Data->SpMsg.bits.AuthorizeReq = value; } } void ocpp_set_authorizeConf_cmd(byte value) { if (ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { ShmOCPP16Data->SpMsg.bits.AuthorizeConf = value; } else if (ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { ShmOCPP20Data->SpMsg.bits.AuthorizeConf = value; } } void ocpp_set_errCode_cmd(byte gunIndex) { if (ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { if (strcmp((char *)chargingInfo[gunIndex]->ConnectorAlarmCode, "") != EQUAL) { strcpy((char *)ShmOCPP16Data->StatusNotification[gunIndex].ErrorCode, "InternalError"); strcpy((char *)ShmOCPP16Data->StatusNotification[gunIndex].VendorErrorCode, (char *)chargingInfo[gunIndex]->ConnectorAlarmCode); } else if (strcmp((char *)chargingInfo[gunIndex]->EvConnAlarmCode, "") != EQUAL) { strcpy((char *)ShmOCPP16Data->StatusNotification[gunIndex].ErrorCode, "OtherError"); strcpy((char *)ShmOCPP16Data->StatusNotification[gunIndex].VendorErrorCode, (char *)chargingInfo[gunIndex]->EvConnAlarmCode); } } else if (ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { } } void ocpp_clear_errorCode_cmd(byte gunIndex) { if (ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { if (strcmp((char *)ShmOCPP16Data->StatusNotification[gunIndex].ErrorCode, "NoError") != EQUAL) { strcpy((char *)ShmOCPP16Data->StatusNotification[gunIndex].ErrorCode, "NoError"); } if (strcmp((char *)ShmOCPP16Data->StatusNotification[gunIndex].VendorErrorCode, "") != EQUAL) { strcpy((char *)ShmOCPP16Data->StatusNotification[gunIndex].VendorErrorCode, ""); } } else if (ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { } } void ocpp_clear_idTag_cmd(byte gun_index) { if (ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { strcpy((char *)ShmOCPP16Data->StartTransaction[gun_index].ResponseIdTagInfo.Status, ""); } else if (ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { strcpy((char *)ShmOCPP20Data->TransactionEvent[gun_index].Response_idTokenInfo.status, ""); } } void ocpp_clear_stopReason(byte gun_index) { if (ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { strcpy((char *)ShmOCPP16Data->StopTransaction[gun_index].StopReason, ""); } else if (ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { strcpy((char *)ShmOCPP20Data->TransactionEvent[gun_index].transactionInfo.stoppedReason, ""); } } unsigned short _ocpp_get_connect_timeout() { uint16_t result = (TIMEOUT_SPEC_HANDSHAKING / 1000); if (ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { if (strcmp((char *)ShmOCPP16Data->ConfigurationTable.CoreProfile[ConnectionTimeOut].ItemData, "") != 0) { result = atoi((char *)ShmOCPP16Data->ConfigurationTable.CoreProfile[ConnectionTimeOut].ItemData); } } else if (ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { if (strcmp((char *)ShmOCPP20Data->ControllerComponentVariable[TxCtrlr_EVConnectionTimeOut].variableAttribute[0].value, "") != 0) { result = atoi((char *)ShmOCPP20Data->ControllerComponentVariable[TxCtrlr_EVConnectionTimeOut].variableAttribute[0].value); } } return result; } bool _ocpp_get_disconnect_policy() { bool result = false; if (ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { if (strcmp((char *)ShmOCPP16Data->ConfigurationTable.CoreProfile[AllowOfflineTxForUnknownId].ItemData, "TRUE") == EQUAL && strcmp((char *)ShmOCPP16Data->ConfigurationTable.CoreProfile[LocalAuthorizeOffline].ItemData, "TRUE") == EQUAL) { result = true; } } else if (ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { if (strcmp((char *)ShmOCPP20Data->ControllerComponentVariable[LocalAuthorizeOffline].variableAttribute[0].value, "") == EQUAL && strcmp((char *)ShmOCPP20Data->ControllerComponentVariable[AuthCtrlr_LocalAuthorizeOffline].variableAttribute[0].value, "") == EQUAL) { result = true; } } return result; } bool ocpp_get_authorize_conf() { if (ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { return ShmOCPP16Data->SpMsg.bits.AuthorizeConf; } else if (ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { return ShmOCPP20Data->SpMsg.bits.AuthorizeConf; } return false; } bool ocpp_get_startTransation_req(byte gunIndex) { bool result = false; // 如果有 AC 槍,而現在是 DC 第二把槍進入充電 if (ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { result = ShmOCPP16Data->CpMsg.bits[gunIndex].StartTransactionReq; } else if (ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { result = ShmOCPP20Data->CpMsg.bits[gunIndex].TransactionEventReq; } return result; } void ocpp_chargingProfile_process(byte _index) { int _time = 0; int _startCount = NO_DEFINE; int _maxCount = 0; if (ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16) { if (strcmp((char *)ShmOCPP16Data->SmartChargingProfile[_index].ChargingProfileKind, "Absolute") == EQUAL && ShmOCPP16Data->SmartChargingProfile[_index].ChargingProfileId == YES) { _time = GetStartScheduleTime(ShmOCPP16Data->SmartChargingProfile[_index].ChargingSchedule.StartSchedule); _maxCount = ARRAY_SIZE(ShmOCPP16Data->SmartChargingProfile[_index].ChargingSchedule.ChargingSchedulePeriod); _startCount = NO_DEFINE; for (byte _count = 0; _count < _maxCount; _count++) { // 預設最小輸出電流 (MIN_OUTPUT_CUR) A if (_time >= ShmOCPP16Data->SmartChargingProfile[_index].ChargingSchedule.ChargingSchedulePeriod[_count].StartPeriod) { if ((_count == 0 && ShmOCPP16Data->SmartChargingProfile[_index].ChargingSchedule.ChargingSchedulePeriod[_count].Limit >= MIN_OUTPUT_CUR) || ShmOCPP16Data->SmartChargingProfile[_index].ChargingSchedule.ChargingSchedulePeriod[_count].Limit > MIN_OUTPUT_CUR) { _startCount = _count; } } } PRINTF_FUNC("Gun_%d, Get Profile - Profile Index = %d \n", _index, _startCount); if (_startCount < _maxCount) { PRINTF_FUNC("Profile Limit = %f \n", ShmOCPP16Data->SmartChargingProfile[_index].ChargingSchedule.ChargingSchedulePeriod[_startCount].Limit); chargingInfo[_index]->ChargingProfilePower = ShmOCPP16Data->SmartChargingProfile[_index].ChargingSchedule.ChargingSchedulePeriod[_startCount].Limit * AC_OUTPUT_VOL * ShmOCPP16Data->SmartChargingProfile[_index].ChargingSchedule.ChargingSchedulePeriod[_startCount].NumberPhases; if (chargingInfo[_index]->EvBatterytargetVoltage > 0 && chargingInfo[_index]->PresentChargingVoltage > 0) { chargingInfo[_index]->ChargingProfileCurrent = (chargingInfo[_index]->ChargingProfilePower / chargingInfo[_index]->PresentChargingVoltage) * 10; } else { chargingInfo[_index]->ChargingProfileCurrent = 0; } } else { chargingInfo[_index]->ChargingProfilePower = -1; chargingInfo[_index]->ChargingProfileCurrent = -1; } } else { chargingInfo[_index]->ChargingProfilePower = -1; chargingInfo[_index]->ChargingProfileCurrent = -1; } } else if (ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20) { if (strcmp((char *)ShmOCPP20Data->SmartChargingProfile[_index].chargingProfileKind, "Absolute") == EQUAL && ShmOCPP20Data->SmartChargingProfile[_index].id == YES) { _time = GetStartScheduleTime(ShmOCPP20Data->SmartChargingProfile[_index].chargingSchedule[0].startSchedule); _maxCount = ARRAY_SIZE(ShmOCPP20Data->SmartChargingProfile[_index].chargingSchedule[0].chargingSchedulePeriod); _startCount = NO_DEFINE; for (byte _count = 0; _count < _maxCount; _count++) { // 預設最小輸出電流 (MIN_OUTPUT_CUR) A if (_time >= ShmOCPP20Data->SmartChargingProfile[_index].chargingSchedule[0].chargingSchedulePeriod[_count].startPeriod) { if ((_count == 0 && ShmOCPP20Data->SmartChargingProfile[_index].chargingSchedule[0].chargingSchedulePeriod[_count].limit >= MIN_OUTPUT_CUR) || ShmOCPP20Data->SmartChargingProfile[_index].chargingSchedule[0].chargingSchedulePeriod[_count].limit > MIN_OUTPUT_CUR) { _startCount = _count; } } } PRINTF_FUNC("Gun_%d, Get Profile - Profile Index = %d \n", _index, _startCount); if (_startCount < _maxCount) { PRINTF_FUNC("Profile Limit = %f \n", ShmOCPP20Data->SmartChargingProfile[_index].chargingSchedule[0].chargingSchedulePeriod[_startCount].limit); chargingInfo[_index]->ChargingProfilePower = ShmOCPP20Data->SmartChargingProfile[_index].chargingSchedule[0].chargingSchedulePeriod[_startCount].limit * AC_OUTPUT_VOL; if (chargingInfo[_index]->EvBatterytargetVoltage > 0 && chargingInfo[_index]->PresentChargingVoltage > 0) { chargingInfo[_index]->ChargingProfileCurrent = (chargingInfo[_index]->ChargingProfilePower / chargingInfo[_index]->PresentChargingVoltage) * 10; } else { chargingInfo[_index]->ChargingProfileCurrent = 0; } } else { chargingInfo[_index]->ChargingProfilePower = -1; chargingInfo[_index]->ChargingProfileCurrent = -1; } } else { chargingInfo[_index]->ChargingProfilePower = -1; chargingInfo[_index]->ChargingProfileCurrent = -1; } } else { chargingInfo[_index]->ChargingProfilePower = -1; chargingInfo[_index]->ChargingProfileCurrent = -1; } PRINTF_FUNC("Profile : ChargingProfilePower = %f \n", chargingInfo[_index]->ChargingProfilePower); PRINTF_FUNC("Profile : ChargingProfileCurrent = %f \n", chargingInfo[_index]->ChargingProfileCurrent); }