using Evcb.Domain.Model; using Evcb.Repository; using Evcb.Service; using Evcb.Service.Helpers; using Evcb.Service.Service.Common; using Newtonsoft.Json; using NLog; using OCPP_Packet.Packet.DataTransfer; using OCPP_Packet.Packet.Status; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace OCPPServer.Service { public class WebSocketCommandService : Service { private ILogger logger = NLog.LogManager.GetCurrentClassLogger(); private readonly IRepository _chargingRecordStatusRepo; private readonly IRepository _machineGunRepo; private readonly IRepository _chargingRecordRepo; private readonly IRepository _chargingRecordReportRepo; private readonly IRepository _meRepo; private readonly IRepository _memberChargingRepo; public WebSocketCommandService(IUnitOfWork uow) : base(uow) { _uow = uow; _chargingRecordRepo = _uow.Repository(); _machineGunRepo = _uow.Repository(); _chargingRecordStatusRepo = _uow.Repository(); _chargingRecordReportRepo = _uow.Repository(); _meRepo = _uow.Repository(); _memberChargingRepo = _uow.Repository(); } public ProcessStatusPacketResult Process1104(ChargingRecordStatus value) { ProcessStatusPacketResult result = new ProcessStatusPacketResult() { StartChargingType = -1 }; var gun = _machineGunRepo.Query(c => c.GunSerNo == value.GunSerNo && c.Machine.Id == value.MachineId).Include(c => c.Machine).Include(c => c.Machine.Customer).Select().FirstOrDefault(); value.CreatedOn = DateTime.Now; logger.Trace(value.MachineCustomId + "進入104處理"); if (gun != null) { //舊的充電序號 Guid oldGuid = Guid.Empty; //狀態改變,更換序號 if ((gun.Status == 2 || gun.Status == 3) && (value.Status == 2 || value.Status == 3)) { //2跟3算同一個狀態 For AC,不更換序號 } else if (gun.Status != value.Status) { oldGuid = gun.ChargingSerNo; gun.ChargingSerNo = Guid.NewGuid(); } //從正準備開始充電轉換到充電進行中,新增一筆充電紀錄 //if (((gun.Status == 1 || gun.Status == 0) && value.Status == 2) || ((gun.Status == 1 || gun.Status == 0) && value.Status == 3)) if (value.Status == 2) { //DateTime sDate = value.StartChargingDateTime.Value.AddMilliseconds(-1); //DateTime eDate = value.StartChargingDateTime.Value.AddMilliseconds(3); ChargingRecord nObj = _chargingRecordRepo.Query( // c => c.StartChargingDateTime >= sDate //&& c.StartChargingDateTime <= eDate c => c.StartChargingDateTime == value.StartChargingDateTime.Value && c.GunSerNo == value.GunSerNo && c.MachineId == gun.MachineId).Select().FirstOrDefault(); //沒有該筆充電序才去產生帳單紀錄 if (nObj == null && value.StartChargingDateTime.HasValue) { gun.ChargingSerNo = Guid.NewGuid(); nObj = new ChargingRecord() { StartChargingDateTime = value.StartChargingDateTime.Value, StartWith = value.StartWith, GunSerNo = gun.GunSerNo, MachineId = gun.Machine.Id, MachineCustomId = gun.Machine.CustomId, ChargingSerNo = gun.ChargingSerNo, ChargingStrategy = value.ChargingStrategy, ChargingStrategyParam = (int)value.ChargingStrategyParam, CreatedOn = DateTime.Now }; _chargingRecordRepo.Add(nObj); logger.Trace(gun.Machine.CustomId + "開始充電轉換到充電進行中"); logger.Trace("nObj:" + JsonConvert.SerializeObject(nObj)); logger.Trace("value:" + JsonConvert.SerializeObject(value)); //如果每筆記錄都要回報 if (gun.Machine.Customer.AutoCreateReportRecord) { //如果是卡片充電的話 if (value.StartWith == 1) { logger.Trace("卡片充電:"); ChargingRecordReport rr = new ChargingRecordReport() { StartChargingDateTime = value.StartChargingDateTime.Value, MachineId = nObj.MachineId, MachineCustomId = nObj.MachineCustomId, CardNum = value.ReservationCardNum, StartWith = value.StartWith, ChargingSerNo = nObj.ChargingSerNo, CustomerId = gun.Machine.CustomerId, GunSerNo = value.GunSerNo, //ChargeStrategy = 2, ChargeStrategy = value.ChargingStrategy, ChargeStrategyParam = value.CardBalanceBeforeCharging, CreatedOn = DateTime.Now, }; logger.Trace("rr:" + JsonConvert.SerializeObject(rr)); _chargingRecordReportRepo.Add(rr); result.StartChargingType = 0; result.ChargingSerNo = rr.ChargingSerNo; result.Result = 12; } } } } //發出一個新的告警,就紀錄到table中 if (value.Status == 6) { var hasSameError = _uow.Repository().Query(c => c.MachineId == value.MachineId && c.GunSerNo == gun.GunSerNo).Select().OrderByDescending(c => c.CreatedOn).FirstOrDefault(); MachineError me = new MachineError { CreatedOn = DateTime.Now, MachineId = gun.MachineId, PreStatus = gun.Status, Status = value.Status, ErrorCode = value.Warning, GunSerNo = gun.GunSerNo }; if (gun.Status != 6) { // Gun previous status is other status if (hasSameError != null) { if (((value.Warning == hasSameError.ErrorCode) && ((value.CreatedOn - hasSameError.CreatedOn).Value.TotalMinutes > 3)) || (value.Warning != hasSameError.ErrorCode)) { _meRepo.Add(me); NoticeError(me); } } else { _meRepo.Add(me); NoticeError(me); } } else { // Gun previous status is alarm status if (value.Warning != hasSameError.ErrorCode) { _meRepo.Add(me); NoticeError(me); } //logger.Trace("value.CreatedOn - hasSameError.CreatedOn=" + (value.CreatedOn - hasSameError.CreatedOn).Value.TotalMinutes.ToString()); } } ////從充電中,切換狀態到充電結束 //if (gun.Status == 2 && value.Status == 3) //{ // var chargingRecordObj = _chargingRecordRepo.Query(c => c.ChargingSerNo == oldGuid).Select().FirstOrDefault(); // chargingRecordObj.EndChargingDateTime = DateTime.Now; // _chargingRecordRepo.Update(chargingRecordObj); //} gun.Status = value.Status; value.ChargingSerNo = gun.ChargingSerNo; //value.CreatedOn = DateTime.Now; _chargingRecordStatusRepo.Add(value); _uow.SaveChanges(); return result; } else { throw new ApplicationException("wrong guns!"); } } private IResult NoticeError(MachineError error) { IResult result = new Result(); try { string description = "None"; var machineRepo = _uow.Repository(); var machine = machineRepo.Query(c => c.Id == error.MachineId).Include(c => c.Customer).Select().FirstOrDefault(); var accountRepo = _uow.Repository(); var account = accountRepo.Query(c => c.CustomerId == machine.CustomerId).Select().FirstOrDefault(); var errorRepo = _uow.Repository(); var errorMsg = errorRepo.Query(c => c.Code == error.ErrorCode).Select().FirstOrDefault(); if (errorMsg != null) { if (errorMsg.AC == machine.AC) { description = errorMsg.Description; } } if (!string.IsNullOrEmpty(account.Email)) { string[] emailgroup = account.Email.Split(','); string subject = string.Format("客户: {0} 飞宏电桩号: {1} 客户电桩号: {2} 错误代码:{3}", machine.Customer.CustomerDesc, machine.CustomId, machine.PartnerPoleId, error.ErrorCode); string detail = string.Format("[时间点: {0}] 飞宏电桩号: {1} 客户电桩号: {2},枪号 : {3},错误代码: {4} 说明: {5}", error.CreatedOn, machine.CustomId, machine.PartnerPoleId, Convert.ToChar(65 + error.GunSerNo), error.ErrorCode, description); string body = string.Format("详细讯息: {2} ", machine.PartnerPoleId, error.ErrorCode, detail); foreach (var email in emailgroup) { DispatchMessageHelper.SendMail(email, subject, body); } } result.Success = true; return result; } catch (Exception ex) { logger.Error(ex); result.Exception = ex; result.Success = false; return result; } } /// /// 處理經緯度 /// /// 電樁Id /// Location command /// public IResult ProcessLocation(string customId, Location value) { IResult result = new Result(); double radius = 0.005d; try { var machineRepo = _uow.Repository(); var _chargerStationRepo = _uow.Repository(); var machine = machineRepo.Query(c => c.CustomId == customId).Select().FirstOrDefault(); var stations = _chargerStationRepo.Query(c => c.CustomerId == machine.CustomerId).Select().ToList(); //Mapping 充電樁的位置 以資料庫列表中充電樁站點為圓心,判斷上報的充電樁位置是否在附近 //以0.005d為半徑 超出者預設 0 //double KeyX = 0d, KeyY = 0d; bool isNearAnyStation = false; foreach (var station in stations) { double YDist = Convert.ToDouble(station.Latitude - Convert.ToDecimal(value.latitude)); double XDist = Convert.ToDouble(station.Longitude - Convert.ToDecimal(value.longitude)); if (Math.Pow(XDist, 2d) + Math.Pow(YDist, 2d) <= Math.Pow(radius, 2d)) { isNearAnyStation = true; if (machine.Location != station.Id) { machine.Location = station.Id; } } } if (!isNearAnyStation & machine.Location != 0) { machine.Location = 0; } _uow.SaveChanges(); result.Success = true; return result; } catch (Exception ex) { logger.Error(ex); result.Exception = ex; result.Success = false; return result; } } /// /// 處理BMS訊息 /// /// 電樁Id /// ChargingGunBMS command /// public IResult ProcessChargingGunBMS(string machineId, ChargingGunBMS cmd) { IResult result = new Result(); var _machineGunRepo = _uow.Repository(); var _chargingRecordBMSRepo = _uow.Repository(); try { var chargingSerNo = _machineGunRepo.Query(x => x.MachineId == machineId && x.GunSerNo == cmd.connectorId && x.Status != 0).Select(x => x.ChargingSerNo).FirstOrDefault(); if (chargingSerNo == null) chargingSerNo = Guid.Empty; _chargingRecordBMSRepo.Add(new ChargingRecordBMS() { MachineId = machineId, MachineCustomId = _repository.Query(x => x.Id == machineId).Select(x => x.PartnerPoleId).FirstOrDefault(), GunSerNo = Convert.ToByte(cmd.connectorId-1), ChargingSerNo = chargingSerNo == null ? Guid.Empty : chargingSerNo, Status = Convert.ToByte(cmd.status), CarConnection = Convert.ToByte(cmd.carConnectionStatus), BRMBMS_ProtocolVersion = cmd.brm_bmsVersion, BR_BatteryType = Convert.ToByte(cmd.br_BatteryType), BRM_CarBattery_SystemRatedCurrent = Convert.ToDecimal(cmd.brm_BatterySystemRatedcapacity), BRM_CarBattery_SystemRatedVoltage = Convert.ToDecimal(cmd.brm_BatterySystemRatedVoltage), BRM_BatteryManufacturer = cmd.brm_BatteryManufacturer, BRM_BatteryGroupSN = cmd.brm_BatteryNumber, BRM_BatteryGroupProductionDate = cmd.brm_ProductionDate, BRM_BatteryGroupChargingTimes = cmd.brm_BatteryChargeTimes, BRM_BatteryGroupPropertyRight = Convert.ToByte(cmd.brm_BatteryPropertySign), BRM_Reserve = Convert.ToByte(cmd.brm_Reserved), BRM_VIN = cmd.brm_Vin, BRMBMS_SoftwareVersion = cmd.brm_bmsSoftwareVersion, BCP_SingleBatteryAllowChargeMaxVoltage = Convert.ToDecimal(cmd.bcp_SingleBatteryHightestChargeVoltage), BCP_AllowChargeMaxCurrent = Convert.ToDecimal(cmd.bcp_HightestChargeCurrent), BCP_BatteryFlagTotalEnergy = Convert.ToDecimal(cmd.bcp_BatteryLabelingTotalEnergy), BCP_AllowChargeMaxTotalVoltage = Convert.ToDecimal(cmd.bcp_HightestChargeVoltage), BCP_AllowHighestTemperature = cmd.bcp_HightestTemperature, BCP_CarBatterySOC = Convert.ToDecimal(cmd.bcp_VehiclePowerBatteryChargeState), BCP_CarBatteryCurrentBatteryVoltage = Convert.ToDecimal(cmd.bcp_VehicleBatteryCurrentVoltage), BROBMS_IsReadyCharge = Convert.ToByte((cmd.bro_bms_ChargeReadyStatus == ChargeReadyStatus.NotReady) ? 0x00 : ((cmd.bro_bms_ChargeReadyStatus == ChargeReadyStatus.Ready) ? 0xAA : 0xFF)), BCL_Voltage = Convert.ToDecimal(cmd.bcl_DemandVoltage), BCL_Current = Convert.ToDecimal(cmd.bcl_DemandCurrent), BCL_ChargeMode = Convert.ToByte(cmd.bcl_ChargeMode), BCS_ChargeVotageMeasurement = Convert.ToDecimal(cmd.bcs_ChargeVoltageMeasurement), BCS_ChargeCurrentMeasurement = Convert.ToDecimal(cmd.bcs_ChargeCurrentMeasurement), BCS_SingleBatteryMaxVoltage = Convert.ToDecimal(cmd.bcs_HightestSingleBatteryVoltage), BCS_SingleBatteryGroupNumber = cmd.bcs_HightestSingleBatteryNumber, BCS_CurrentSOC = Convert.ToByte(cmd.bcs_CurrentSOC), RemainingChargeMins = cmd.remainingChargeTime, BSM_SingleBatteryMaxVoltageNumber = cmd.bsm_HightestSingleBatteryVoltageNumber, BSM_BatteryHighestTemperature = cmd.bsm_HightestBatteryTemperature, BSM_HighestTemperatureCheckPointNumber = cmd.bsm_HightestTemperatureDetectionPointNumber, BSM_BatteryLowestTemperature = cmd.bsm_LowestBatteryTemperature, BSM_LowestTemperatureCheckPointNumber = cmd.bsm_LowestTemperatureDetectionPointNumber, BSM_SingleBatteryVoltageStatus = Convert.ToByte((cmd.bsm_SingleBatteryVoltageStatus == BMSStatusAType.Normal) ? 0x00 : ((cmd.bsm_SingleBatteryVoltageStatus == BMSStatusAType.TooHigh) ? 0x01 : 0x10)), BSM_CarBatterySOCStatus = Convert.ToByte((cmd.bsm_VehicleBatterySOCStatus == BMSStatusAType.Normal) ? 0x00: ((cmd.bsm_VehicleBatterySOCStatus == BMSStatusAType.TooHigh) ? 0x01 : 0x10)), BSM_BatteryChargineCurrentStatus = Convert.ToByte((cmd.bsm_BatteryChargeCurrentStatus == BMSStatusBType.Normal) ? 0x00 : ((cmd.bsm_BatteryChargeCurrentStatus == BMSStatusBType.TooHigh) ? 0x01 : 0x10)), BSM_BatteryTemperatureTooHigh = Convert.ToByte((cmd.bsm_BatteryTemperatureStatus == BMSStatusBType.Normal) ? 0x00 : ((cmd.bsm_BatteryTemperatureStatus == BMSStatusBType.TooHigh) ? 0x01 : 0x10)), BSM_BatteryInsulationStatus = Convert.ToByte((cmd.bsm_BatteryInsulationStatus == BMSStatusBType.Normal) ? 0x00 : ((cmd.bsm_BatteryInsulationStatus == BMSStatusBType.TooHigh) ? 0x01 : 0x10)), BSM_BatteryOutputConnectionStatus = Convert.ToByte((cmd.bsm_BatteryOutputConnectorConnectionStatus == BMSStatusBType.Normal) ? 0x00 : ((cmd.bsm_BatteryOutputConnectorConnectionStatus == BMSStatusBType.TooHigh) ? 0x01 : 0x10)), BSM_AllowCharge = Convert.ToByte((cmd.bsm_IsAllowedCharge == false) ? 0x00 : 0x01), BSTBMS_SOCGoal = Convert.ToByte((cmd.bst_bms_IsAchievedSOCTargetStatus == BMSStatusCType.Below) ? 0x00 : ((cmd.bst_bms_IsAchievedSOCTargetStatus == BMSStatusCType.Standard) ? 0x01 : 0x10)), BSTBMS_TotalVotageSetting = Convert.ToByte((cmd.bst_bms_IsAchievedSettingTotalVoltageStatus == BMSStatusCType.Below) ? 0x00 : ((cmd.bst_bms_IsAchievedSettingTotalVoltageStatus == BMSStatusCType.Standard) ? 0x01 : 0x10)), BST_SingleVotageSetting = Convert.ToByte((cmd.bst_IsAchievedSettingSingleVoltageStatus == BMSStatusCType.Below) ? 0x00 : ((cmd.bst_IsAchievedSettingSingleVoltageStatus == BMSStatusCType.Standard) ? 0x01 : 0x10)), BST_ChargerActiveStop = Convert.ToByte((cmd.bst_chargerAutoTerminationStatus == ChargerAutoTerminationStatus.Normal) ? 0x00 : ((cmd.bst_chargerAutoTerminationStatus == ChargerAutoTerminationStatus.ChargerIsTerminated) ? 0x01 : 0x10)), BST_InsulationError = Convert.ToByte((cmd.bst_InsulationFaultStatus == BMSStatusDType.Normal) ? 0x00 : ((cmd.bst_InsulationFaultStatus == BMSStatusDType.Fault) ? 0x01 : 0x10)), BST_OutputConnectionOverTemperatureError = Convert.ToByte((cmd.bst_OutputConnectorTemperatureStatus == BMSStatusDType.Normal) ? 0x00 : ((cmd.bst_OutputConnectorTemperatureStatus == BMSStatusDType.Fault) ? 0x01 : 0x10)), BSTBMSComponent_OutputConnectionOverTemperatureError = Convert.ToByte((cmd.bst_bms_OutputConnectorTemperatureStatus == BMSStatusDType.Normal) ? 0x00 : ((cmd.bst_bms_OutputConnectorTemperatureStatus == BMSStatusDType.Fault) ? 0x01 : 0x10)), BST_ChargeConnectionError = Convert.ToByte((cmd.bst_chargerConnectorStatus == BMSStatusBType.Normal) ? 0x00 : ((cmd.bst_chargerConnectorStatus == BMSStatusBType.TooHigh) ? 0x01 : 0x10)), BST_BatteryGroupOverTemperatureError = Convert.ToByte((cmd.bst_BatteryTemperatureStatus == BMSStatusBType.Normal) ? 0x00 : ((cmd.bst_BatteryTemperatureStatus == BMSStatusBType.TooHigh) ? 0x01 : 0x10)), BST_HighVoltageRelayError = Convert.ToByte((cmd.bst_HighVoltageRelayStatus == BMSStatusBType.Normal) ? 0x00 : ((cmd.bst_HighVoltageRelayStatus == BMSStatusBType.TooHigh) ? 0x01 : 0x10)), BST_Checkponit2VoltageCheckError = Convert.ToByte((cmd.bst_DetectionPoint2Voltage == BMSStatusBType.Normal) ? 0x00 : ((cmd.bst_DetectionPoint2Voltage == BMSStatusBType.TooHigh) ? 0x01 : 0x10)), BST_OtherError = Convert.ToByte((cmd.bst_Other == BMSStatusBType.Normal) ? 0x00 : ((cmd.bst_Other == BMSStatusBType.TooHigh) ? 0x01 : 0x10)), BST_OverCurrent = Convert.ToByte((cmd.bst_Current == BMSStatusBType.Normal) ? 0x00 : ((cmd.bst_Current == BMSStatusBType.TooHigh) ? 0x01 : 0x10)), BST_VoltageError = Convert.ToByte((cmd.bst_Voltage == BMSStatusBType.Normal) ? 0x00 : ((cmd.bst_Voltage == BMSStatusBType.TooHigh) ? 0x01 : 0x10)), BSD_StopSOC = Convert.ToByte(cmd.bsd_EndSOC), BSD_SingleBatteryLowestVoltage = Convert.ToDecimal(cmd.bsd_SingleBatteryLowestVoltage), BSD_SingleBatteryHighestVoltage = Convert.ToDecimal(cmd.bsd_SingleBatteryHightestVoltage), BSD_BatteryLowestTemperature = cmd.bsd_BatteryLowestTemperature, BSD_BatteryHighestTemperature = cmd.bsd_BatteryHightestTemperature, BEM_ReceivedSPN2560_0x00 = Convert.ToByte((cmd.bem_ReceivedSPN2560_00_Status == BMSStatusEType.Normal) ? 0x00 : ((cmd.bem_ReceivedSPN2560_00_Status == BMSStatusEType.TimeOut) ? 0x01 : 0x10)), BEM_ReceivedSPN2560_0xAA = Convert.ToByte((cmd.bem_ReceivedSPN2560_aa_Status == BMSStatusEType.Normal) ? 0x00 : ((cmd.bem_ReceivedSPN2560_aa_Status == BMSStatusEType.TimeOut) ? 0x01 : 0x10)), BEM_ReceivedSyncAndMaxOutputPower_Timeout = Convert.ToByte((cmd.bem_ReceivedTimeSyncAndMaxOutputStatus == BMSStatusEType.Normal) ? 0x00 : ((cmd.bem_ReceivedTimeSyncAndMaxOutputStatus == BMSStatusEType.TimeOut) ? 0x01 : 0x10)), BEM_ReceivedReadyCharge_Timeout = Convert.ToByte((cmd.bem_ReceivedReadyMessageStatus == BMSStatusEType.Normal) ? 0x00 : ((cmd.bem_ReceivedReadyMessageStatus == BMSStatusEType.TimeOut) ? 0x01 : 0x10)), BEM_ReceivedChargerStatus_Timeout = Convert.ToByte((cmd.bem_ReceivedStatusMessageStatus == BMSStatusEType.Normal) ? 0x00 : ((cmd.bem_ReceivedStatusMessageStatus == BMSStatusEType.TimeOut) ? 0x01 : 0x10)), BEM_ReceivedChargerStopCharge_Timeout = Convert.ToByte((cmd.bem_ReceivedStopMessageStatus == BMSStatusEType.Normal) ? 0x00 : ((cmd.bem_ReceivedStopMessageStatus == BMSStatusEType.TimeOut) ? 0x01 : 0x10)), BEM_ReceivedChargerChargeStatistics_Timeout = Convert.ToByte((cmd.bem_ReceivedStatisticsMessageStatus == BMSStatusEType.Normal) ? 0x00 : ((cmd.bem_ReceivedStatisticsMessageStatus == BMSStatusEType.TimeOut) ? 0x01 : 0x10)), BEM_Other = Convert.ToByte(cmd.bem_Other), CreateOn = DateTime.Now }); _uow.SaveChanges(); result.Success = true; } catch (Exception ex) { result.Exception = ex; result.Message = ex.Message; } return result; } /// /// 處理ChargeComplete /// /// ChargeComplete command /// 電樁樁號 /// public IResult ProcessChargeComplete(ChargeComplete value, string MachineCustomId) { IResult result = new Result(); var _chargingRecordRepo = _uow.Repository(); var crrRepo = _uow.Repository(); var machineRepo = _uow.Repository(); try { var machine = machineRepo.Query(c => c.CustomId == MachineCustomId).Select().FirstOrDefault(); var chargingTransaction = _uow.Repository().Query(c => c.TransactionId == value.transactionId).Select().FirstOrDefault(); if(chargingTransaction == null) { result.Success = false; result.Message = "No Transaction Id"; return result; } var record = _chargingRecordRepo.Query(c => c.Id == chargingTransaction.ChargingRecordId).Select().FirstOrDefault(); //沒有資料就補上去 bool isNew = false; if (record == null) { record = new ChargingRecord(); record.MachineId = machine.Id; record.MachineCustomId = machine.CustomId; record.GunSerNo = (byte)(value.connectorId-1); record.ChargingSerNo = Guid.NewGuid(); record.StartChargingDateTime = value.startChargingDateTime;//value.startChargingDateTime.ToLocalTime(); record.EndChargingDateTime = value.chargeCompleteDateTime;//value.chargeCompleteDateTime.ToLocalTime(); record.CreatedOn = DateTime.Now; isNew = true; } #region Mapper record.CumulativeKwh = (decimal)value.cumulativeKwh; record.KwhBeforeCharging = (decimal)value.beforeChargingKwh; record.KwhAfterCharging = (decimal)value.chargeCompleteKwh; record.ElectricBill = Decimal.Multiply((decimal)value.cumulativeKwh, machine.PricePerKWH);//(decimal)value.electricBill; record.FeeAmount = Decimal.Multiply((decimal)value.cumulativeKwh, machine.FeePerKWH);//(decimal)value.feeAmount; record.SumOfMoney = record.ElectricBill + record.FeeAmount; record.StopChargingReason = (int)value.reason; record.StartWith = (byte)value.startWith; record.StartSoc = (byte)value.startChargingSOC; record.StartChargingType = (byte)value.startChargingType; record.PayOffline = (byte)(value.isPayOffline ? 1 : 0); record.EndSoc = (byte)value.chargeCompleteSOC; record.ChargingStrategyParam = (int)value.chargingStrategyParameter; record.ChargingStrategy = (byte)value.chargingStrategy; record.CarNum = value.licensePlateNumber; record.CardVIN = value.vinCode; record.CardBalanceBeforeCharging = (decimal)value.cardBalanceBeforeCharging; record.CardBalanceAfterCharging = (decimal)value.cardBalanceAfterCharging; record.Time1 = (decimal)value.sectionKwh[0]; record.Time2 = (decimal)value.sectionKwh[1]; record.Time3 = (decimal)value.sectionKwh[2]; record.Time4 = (decimal)value.sectionKwh[3]; record.Time5 = (decimal)value.sectionKwh[4]; record.Time6 = (decimal)value.sectionKwh[5]; record.Time7 = (decimal)value.sectionKwh[6]; record.Time8 = (decimal)value.sectionKwh[7]; record.Time9 = (decimal)value.sectionKwh[8]; record.Time10 = (decimal)value.sectionKwh[9]; record.Time11 = (decimal)value.sectionKwh[10]; record.Time12 = (decimal)value.sectionKwh[11]; record.Time13 = (decimal)value.sectionKwh[12]; record.Time14 = (decimal)value.sectionKwh[13]; record.Time15 = (decimal)value.sectionKwh[14]; record.Time16 = (decimal)value.sectionKwh[15]; record.Time17 = (decimal)value.sectionKwh[16]; record.Time18 = (decimal)value.sectionKwh[17]; record.Time19 = (decimal)value.sectionKwh[18]; record.Time20 = (decimal)value.sectionKwh[19]; record.Time21 = (decimal)value.sectionKwh[20]; record.Time22 = (decimal)value.sectionKwh[21]; record.Time23 = (decimal)value.sectionKwh[22]; record.Time24 = (decimal)value.sectionKwh[23]; record.Time25 = (decimal)value.sectionKwh[24]; record.Time26 = (decimal)value.sectionKwh[25]; record.Time27 = (decimal)value.sectionKwh[26]; record.Time28 = (decimal)value.sectionKwh[27]; record.Time29 = (decimal)value.sectionKwh[28]; record.Time30 = (decimal)value.sectionKwh[29]; record.Time31 = (decimal)value.sectionKwh[30]; record.Time32 = (decimal)value.sectionKwh[31]; record.Time33 = (decimal)value.sectionKwh[32]; record.Time34 = (decimal)value.sectionKwh[33]; record.Time35 = (decimal)value.sectionKwh[34]; record.Time36 = (decimal)value.sectionKwh[35]; record.Time37 = (decimal)value.sectionKwh[36]; record.Time38 = (decimal)value.sectionKwh[37]; record.Time39 = (decimal)value.sectionKwh[38]; record.Time40 = (decimal)value.sectionKwh[39]; record.Time41 = (decimal)value.sectionKwh[40]; record.Time42 = (decimal)value.sectionKwh[41]; record.Time43 = (decimal)value.sectionKwh[42]; record.Time44 = (decimal)value.sectionKwh[43]; record.Time45 = (decimal)value.sectionKwh[44]; record.Time46 = (decimal)value.sectionKwh[45]; record.Time47 = (decimal)value.sectionKwh[46]; record.Time48 = (decimal)value.sectionKwh[47]; record.ClientStartChargingDateTime = value.startChargingDateTime;//value.startChargingDateTime.ToLocalTime(); record.ClientEndChargingDateTime = value.chargeCompleteDateTime;//value.chargeCompleteDateTime.ToLocalTime(); if (value.startWith == StartWith.Member) { var membertb = _memberChargingRepo.Query(c => c.SelfDefinedId == value.idTag).Select().FirstOrDefault(); if (membertb != null) { //會員 record.MemberId = membertb.MemberChargingId.ToString(); } } else if ((value.startWith == StartWith.CardNumber) || (value.startWith == StartWith.Unknown)) { record.CardNum = value.idTag; } #endregion Mapper if (isNew) _chargingRecordRepo.Add(record); else _chargingRecordRepo.Update(record); //處理傳送給客戶api的紀錄 var report = crrRepo.Query(c => c.ChargingSerNo == record.ChargingSerNo).Select().FirstOrDefault(); if (report == null) { report = new ChargingRecordReport(); report.CreatedOn = DateTime.Now; report.StartChargingDateTime = record.StartChargingDateTime; report.ChargingSerNo = record.ChargingSerNo; report.CustomerId = machine.CustomerId; report.GunSerNo = record.GunSerNo; report.MachineCustomId = machine.CustomId; report.MachineId = machine.Id; report.MemberId = record.MemberId; report.CardNum = record.CardNum; report.StartWith = record.StartWith; report.Time1 = record.Time1; report.Time2 = record.Time2; report.Time3 = record.Time3; report.Time4 = record.Time4; report.Time5 = record.Time5; report.Time6 = record.Time6; report.Time7 = record.Time7; report.Time8 = record.Time8; report.Time9 = record.Time9; report.Time10 = record.Time10; report.Time11 = record.Time11; report.Time12 = record.Time12; report.Time13 = record.Time13; report.Time14 = record.Time14; report.Time15 = record.Time15; report.Time16 = record.Time16; report.Time17 = record.Time17; report.Time18 = record.Time18; report.Time19 = record.Time19; report.Time20 = record.Time20; report.Time21 = record.Time21; report.Time22 = record.Time22; report.Time23 = record.Time23; report.Time24 = record.Time24; report.Time25 = record.Time25; report.Time26 = record.Time26; report.Time27 = record.Time27; report.Time28 = record.Time28; report.Time29 = record.Time29; report.Time30 = record.Time30; report.Time31 = record.Time31; report.Time32 = record.Time32; report.Time33 = record.Time33; report.Time34 = record.Time34; report.Time35 = record.Time35; report.Time36 = record.Time36; report.Time37 = record.Time37; report.Time38 = record.Time38; report.Time39 = record.Time39; report.Time40 = record.Time40; report.Time41 = record.Time41; report.Time42 = record.Time42; report.Time43 = record.Time43; report.Time44 = record.Time44; report.Time45 = record.Time45; report.Time46 = record.Time46; report.Time47 = record.Time47; report.Time48 = record.Time48; report.ChargeStrategy = record.ChargingStrategy; report.ChargeStrategyParam = record.ChargingStrategyParam; report.SumOfMoney = record.SumOfMoney; report.FeeAmount = record.FeeAmount; report.ElectricBill = record.ElectricBill; report.StartChargingDateTime = record.ClientStartChargingDateTime; report.EndChargingDateTime = record.ClientEndChargingDateTime; report.CumulativeKwh = record.CumulativeKwh; var ts = report.EndChargingDateTime - report.StartChargingDateTime; report.TotalUsedTime = Convert.ToInt32(ts.Value.TotalSeconds); report.CarNum = record.CarNum; report.StartSoc = record.StartSoc; report.EndSoc = record.EndSoc; report.KwhBeforeCharging = record.KwhBeforeCharging; report.KwhAfterCharging = record.KwhAfterCharging; report.CardBalanceBeforeCharging = record.CardBalanceBeforeCharging; report.CardBalanceAfterCharging = record.CardBalanceAfterCharging; report.PayOffline = record.PayOffline; report.CardVIN = record.CardVIN; report.StartChargingType = record.StartChargingType; report.StopChargingReason = record.StopChargingReason; report.UpdatedOn = DateTime.Now; crrRepo.Add(report); } else { report.MemberId = record.MemberId; report.CardNum = record.CardNum; report.StartWith = record.StartWith; report.Time1 = record.Time1; report.Time2 = record.Time2; report.Time3 = record.Time3; report.Time4 = record.Time4; report.Time5 = record.Time5; report.Time6 = record.Time6; report.Time7 = record.Time7; report.Time8 = record.Time8; report.Time9 = record.Time9; report.Time10 = record.Time10; report.Time11 = record.Time11; report.Time12 = record.Time12; report.Time13 = record.Time13; report.Time14 = record.Time14; report.Time15 = record.Time15; report.Time16 = record.Time16; report.Time17 = record.Time17; report.Time18 = record.Time18; report.Time19 = record.Time19; report.Time20 = record.Time20; report.Time21 = record.Time21; report.Time22 = record.Time22; report.Time23 = record.Time23; report.Time24 = record.Time24; report.Time25 = record.Time25; report.Time26 = record.Time26; report.Time27 = record.Time27; report.Time28 = record.Time28; report.Time29 = record.Time29; report.Time30 = record.Time30; report.Time31 = record.Time31; report.Time32 = record.Time32; report.Time33 = record.Time33; report.Time34 = record.Time34; report.Time35 = record.Time35; report.Time36 = record.Time36; report.Time37 = record.Time37; report.Time38 = record.Time38; report.Time39 = record.Time39; report.Time40 = record.Time40; report.Time41 = record.Time41; report.Time42 = record.Time42; report.Time43 = record.Time43; report.Time44 = record.Time44; report.Time45 = record.Time45; report.Time46 = record.Time46; report.Time47 = record.Time47; report.Time48 = record.Time48; report.CumulativeKwh = record.CumulativeKwh; report.EndChargingDateTime = record.ClientEndChargingDateTime; report.StartChargingDateTime = record.ClientStartChargingDateTime; report.FeeAmount = record.FeeAmount; report.ElectricBill = record.ElectricBill; report.SumOfMoney = record.SumOfMoney; var ts = report.EndChargingDateTime - report.StartChargingDateTime; report.TotalUsedTime = Convert.ToInt32(ts.Value.TotalSeconds); report.CarNum = record.CarNum; report.StartSoc = record.StartSoc; report.EndSoc = record.EndSoc; report.KwhBeforeCharging = record.KwhBeforeCharging; report.KwhAfterCharging = record.KwhAfterCharging; report.CardBalanceBeforeCharging = record.CardBalanceBeforeCharging; report.CardBalanceAfterCharging = record.CardBalanceAfterCharging; report.PayOffline = record.PayOffline; report.CardVIN = record.CardVIN; report.StartChargingType = record.StartChargingType; report.StopChargingReason = record.StopChargingReason; report.UpdatedOn = DateTime.Now; } WarnChargeIsAbnormal(record); _uow.SaveChanges(); result.Success = true; return result; } catch (Exception ex) { logger.Error(ex); result.Exception = ex; result.Success = false; return result; } } /// /// 通知Email /// /// 電樁Id /// 主旨 /// 內文 /// private IResult NoticeEmail(string machineId, string subject, string body) { IResult result = new Result(); try { var machineRepo = _uow.Repository(); var machine = machineRepo.Query(c => c.Id == machineId).Include(c => c.Customer).Select().FirstOrDefault(); var accountRepo = _uow.Repository(); var account = accountRepo.Query(c => c.CustomerId == machine.CustomerId).Select().FirstOrDefault(); if (!string.IsNullOrEmpty(account.Email)) { string[] emailgroup = account.Email.Split(','); string _subject = string.Format("[{0}] 客户: {1} 飞宏电桩号: {2} 客户电桩号: {3} ", subject, machine.Customer.CustomerDesc, machine.CustomId, machine.PartnerPoleId); foreach (var email in emailgroup) { DispatchMessageHelper.SendMail(email, _subject, body); } } result.Success = true; return result; } catch (Exception ex) { logger.Error(ex); result.Exception = ex; result.Success = false; return result; } } /// /// 警告充電量異常 /// /// private IResult WarnChargeIsAbnormal(ChargingRecord record) { IResult result = new Result(); try { //設定條件-充電時間超過 1800秒 -總充電量小於 0.5kw - StartWith != 2 if (record.CumulativeKwh < Convert.ToDecimal(0.5) && record.ClientEndChargingDateTime.HasValue && record.ClientStartChargingDateTime.HasValue && record.StartWith != 2) { var totalSeconds = record.ClientEndChargingDateTime.Value.Subtract(record.ClientStartChargingDateTime.Value).TotalSeconds; if (totalSeconds > 1800d) { string body = string.Format("详细讯息: 充电序:{0} 充电开始时间:{1} 充电结束时间: {2} 充电秒数:{3} 充电度数:{4}", record.ChargingSerNo, record.ClientStartChargingDateTime.HasValue ? record.ClientStartChargingDateTime.Value.ToString("yyyy-MM-dd HH:mm:ss") : "None", record.ClientEndChargingDateTime.HasValue ? record.ClientEndChargingDateTime.Value.ToString("yyyy-MM-dd HH:mm:ss") : "None", totalSeconds, record.CumulativeKwh); NoticeEmail(record.MachineId, "充电量异常通知", body); } } result.Success = true; return result; } catch (Exception ex) { logger.Error(ex); result.Success = false; result.Exception = ex; result.Message = ex.Message; return result; } } } }