using Dapper;
using EVCB_OCPP.Domain;
using EVCB_OCPP.Domain.Models.Database;
using EVCB_OCPP.Packet.Features;
using EVCB_OCPP.Packet.Messages;
using EVCB_OCPP.Packet.Messages.Core;
using EVCB_OCPP.Packet.Messages.SubTypes;
using EVCB_OCPP.WSServer.Dto;
using EVCB_OCPP.WSServer.Service;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using NLog;
using OCPPPackage.Profiles;
using OCPPServer.Protocol;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Data.Entity;
using System.Data.SqlClient;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Net;
using System.Threading.Tasks;
namespace EVCB_OCPP.WSServer.Message
{
public class ID_CreditDeductResult
{
public int txId { set; get; }
public string creditNo { set; get; }
public bool deductResult { set; get; }
public bool isDonateInvoice { set; get; }
public decimal amount { set; get; }
public string approvalNo { set; get; }
}
public class ID_ReaderStatus
{
public int ConnectorId { set; get; }
public string creditNo { set; get; }
public string SerialNo { set; get; }
public int readerStatus { set; get; }
public string VEMData { set; get; }
public DateTime Timestamp { set; get; }
}
public class ID_GetOccupancyFee
{
public int ConnectorId { set; get; }
public string occupancySN { set; get; }
///
/// 1. Get occupancy fee info. 2. Cancel local deduction
///
public int Action { set; get; }
}
public class ID_GetOccupancyFeeResult
{
public string msgId { set; get; }
public int ConnectorId { set; get; }
public string occupancySN { set; get; }
public string startTime { set; get; }
public int? duration { set; get; }
public decimal? occupancyFee { set; get; }
}
public class ID_OccupancyFeeResult
{
public string occupancySN { set; get; }
public string creditNo { set; get; }
public bool deductResult { set; get; }
public decimal amount { set; get; }
public string approvalNo { set; get; }
}
internal partial class ProfileHandler
{
static private ILogger logger = NLog.LogManager.GetCurrentClassLogger();
string webConnectionString = ConfigurationManager.ConnectionStrings["WebDBContext"].ConnectionString;
private OuterHttpClient httpClient = new OuterHttpClient();
private SMSService smsService = new SMSService();
async internal Task ExecuteCoreRequest(Actions action, ClientData session, IRequest request)
{
Stopwatch watch = new Stopwatch();
if (action == Actions.Heartbeat)
{
watch.Start();
}
MessageResult result = new MessageResult() { Success = false };
try
{
switch (action)
{
case Actions.DataTransfer:
{
DataTransferRequest _request = request as DataTransferRequest;
var confirm = new DataTransferConfirmation() { status = DataTransferStatus.UnknownMessageId };
if (_request.messageId == "ID_CreditDeductResult")
{
var creditDeductResult = JsonConvert.DeserializeObject(_request.data);
if (session.CustomerId == new Guid("009E603C-79CD-4620-A2B8-D9349C0E8AD8"))
{
var report = new
{
ChargeBoxId = session.ChargeBoxId,
IsDonateInvoice = creditDeductResult.isDonateInvoice,
CreditNo = creditDeductResult.creditNo,
DeductResult = creditDeductResult.deductResult,
SessionId = creditDeductResult.txId,
ApprovalNo = creditDeductResult.approvalNo,
TotalCost = creditDeductResult.amount,
};
var response = await httpClient.Post(GlobalConfig.TCC_API_URL + "prepare_issue_invoice", new Dictionary()
{
{ "PartnerId",session.CustomerId.ToString()}
}, report, GlobalConfig.TCC_SALTKEY);
logger.Debug(JsonConvert.SerializeObject(response));
}
confirm.status = DataTransferStatus.Accepted;
confirm.data = JsonConvert.SerializeObject(new { txId = creditDeductResult.txId, creditNo = creditDeductResult.creditNo, msgId = _request.messageId });
}
if (_request.messageId == "ID_ReaderStatus")
{
if (session.CustomerId == new Guid("009E603C-79CD-4620-A2B8-D9349C0E8AD8"))
{
var preauth_status = JsonConvert.DeserializeObject(_request.data);
var report = new
{
ChargeBoxId = session.ChargeBoxId,
ConnectorId = preauth_status.ConnectorId,
CreditNo = preauth_status.creditNo,
ReaderStatus = preauth_status.readerStatus,
SerialNo = preauth_status.SerialNo,
VEMData = preauth_status.VEMData,
Timestamp = preauth_status.Timestamp
};
var response = await httpClient.Post(GlobalConfig.TCC_API_URL + "preauth_status", new Dictionary()
{
{ "PartnerId",session.CustomerId.ToString()}
}, report, GlobalConfig.TCC_SALTKEY);
confirm.status = DataTransferStatus.Accepted;
confirm.data = JsonConvert.SerializeObject(new { msgId = "ID_ReaderStatus", ConnectorId = preauth_status.ConnectorId });
}
}
if (_request.messageId == "ConnectorUnplugged")
{
logger.Debug("ConnectorUnplugged");
JObject jo = JObject.Parse(_request.data);
var businessService = BusinessServiceFactory.CreateBusinessService(session.CustomerId.ToString());
await businessService.NotifyConnectorUnplugged(session.ChargeBoxId, jo["idTx"].Value(), jo["timestamp"].Value());
confirm.status = DataTransferStatus.Accepted;
}
if (_request.messageId == "ID_OccupancyFeeAct")
{
var getOccupancyFee = JsonConvert.DeserializeObject(_request.data);
ID_GetOccupancyFeeResult occupancyFeeResult = new ID_GetOccupancyFeeResult()
{
msgId = _request.messageId,
ConnectorId = getOccupancyFee.ConnectorId,
occupancySN = getOccupancyFee.occupancySN
};
if(getOccupancyFee.Action==1)
{
var report = new
{
ChargeBoxId = session.ChargeBoxId,
occupancySN = getOccupancyFee.occupancySN
};
var response = await httpClient.Post(GlobalConfig.TCC_API_URL + "occupancy_payment", new Dictionary()
{
{ "PartnerId",session.CustomerId.ToString()}
}, report, GlobalConfig.TCC_SALTKEY);
if (!response.Success)
{
confirm.status = DataTransferStatus.Rejected;
confirm.data = JsonConvert.SerializeObject(occupancyFeeResult);
}
else
{
var _httpResult = JsonConvert.DeserializeObject(response.Response);
if (_httpResult.StatusCode != 1000)
{
confirm.status = DataTransferStatus.Rejected;
confirm.data = JsonConvert.SerializeObject(occupancyFeeResult);
}
else
{
confirm.status = DataTransferStatus.Accepted;
JObject jo = JObject.Parse(_httpResult.Data);
if (jo.ContainsKey("ChargeEndTime"))
{
occupancyFeeResult.startTime = jo["ChargeEndTime"].Value();
}
if (jo.ContainsKey("OccupancyDuration"))
{
occupancyFeeResult.duration = jo["OccupancyDuration"].Value();
}
if (jo.ContainsKey("OccupancyFee"))
{
occupancyFeeResult.occupancyFee = jo["OccupancyFee"].Value();
}
confirm.data = JsonConvert.SerializeObject(occupancyFeeResult);
}
}
}
else if (getOccupancyFee.Action == 2)
{
var report = new
{
ChargeBoxId = session.ChargeBoxId,
occupancySN = getOccupancyFee.occupancySN
};
var response = await httpClient.Post(GlobalConfig.TCC_API_URL + "resume_occupancy", new Dictionary()
{
{ "PartnerId",session.CustomerId.ToString()}
}, report, GlobalConfig.TCC_SALTKEY);
if (!response.Success)
{
confirm.status = DataTransferStatus.Rejected;
confirm.data = JsonConvert.SerializeObject(occupancyFeeResult, GlobalConfig.JSONSERIALIZER_FORMAT);
}
else
{
var _httpResult = JsonConvert.DeserializeObject(response.Response);
if (_httpResult.StatusCode != 1000)
{
confirm.status = DataTransferStatus.Rejected;
confirm.data = JsonConvert.SerializeObject(occupancyFeeResult, GlobalConfig.JSONSERIALIZER_FORMAT);
}
else
{
confirm.status = DataTransferStatus.Accepted;
confirm.data = JsonConvert.SerializeObject(occupancyFeeResult,GlobalConfig.JSONSERIALIZER_FORMAT);
}
}
}
else
{
var report = new
{
ChargeBoxId = session.ChargeBoxId,
occupancySN = getOccupancyFee.occupancySN
};
var response = await httpClient.Post(GlobalConfig.TCC_API_URL + "writeoff_occupancy", new Dictionary()
{
{ "PartnerId",session.CustomerId.ToString()}
}, report, GlobalConfig.TCC_SALTKEY);
if (!response.Success)
{
confirm.status = DataTransferStatus.Rejected;
confirm.data = JsonConvert.SerializeObject(occupancyFeeResult, GlobalConfig.JSONSERIALIZER_FORMAT);
}
else
{
var _httpResult = JsonConvert.DeserializeObject(response.Response);
if (_httpResult.StatusCode != 1000)
{
confirm.status = DataTransferStatus.Rejected;
confirm.data = JsonConvert.SerializeObject(occupancyFeeResult, GlobalConfig.JSONSERIALIZER_FORMAT);
}
else
{
confirm.status = DataTransferStatus.Accepted;
confirm.data = JsonConvert.SerializeObject(occupancyFeeResult, GlobalConfig.JSONSERIALIZER_FORMAT);
}
}
}
}
if (_request.messageId == "ID_OccupancyDeductResult")
{
var occupancyFeeResult = JsonConvert.DeserializeObject(_request.data);
var report = new
{
OccupancySN = occupancyFeeResult.occupancySN,
CreditNo = occupancyFeeResult.creditNo,
DeductResult = occupancyFeeResult.deductResult,
Amount = occupancyFeeResult.amount,
ApprovalNo = occupancyFeeResult.approvalNo
};
var response = await httpClient.Post(GlobalConfig.TCC_API_URL + "occupancyfee_result", new Dictionary()
{
{ "PartnerId",session.CustomerId.ToString()}
}, report, GlobalConfig.TCC_SALTKEY);
logger.Debug(JsonConvert.SerializeObject(response));
confirm.status = DataTransferStatus.Accepted;
confirm.data = JsonConvert.SerializeObject(new { msgId = _request.messageId, occupancySN = occupancyFeeResult.occupancySN });
}
result.Message = confirm;
result.Success = true;
}
break;
case Actions.BootNotification:
{
BootNotificationRequest _request = request as BootNotificationRequest;
int heartbeat_interval = GlobalConfig.GetHEARTBEAT_INTERVAL();
using (var db = new MainDBContext())
{
var _machine = db.Machine.Where(x => x.ChargeBoxId == session.ChargeBoxId).FirstOrDefault();
_machine.ChargeBoxSerialNumber = string.IsNullOrEmpty(_request.chargeBoxSerialNumber) ? string.Empty : _request.chargeBoxSerialNumber;
_machine.ChargePointSerialNumber = string.IsNullOrEmpty(_request.chargePointSerialNumber) ? string.Empty : _request.chargePointSerialNumber;
_machine.ChargePointModel = string.IsNullOrEmpty(_request.chargePointModel) ? string.Empty : _request.chargePointModel;
_machine.ChargePointVendor = string.IsNullOrEmpty(_request.chargePointVendor) ? string.Empty : _request.chargePointVendor;
_machine.FW_CurrentVersion = string.IsNullOrEmpty(_request.firmwareVersion) ? string.Empty : _request.firmwareVersion;
//_machine.Iccid = string.IsNullOrEmpty(_request.iccid) ? string.Empty : _request.iccid;
_machine.Iccid = DateTime.UtcNow.ToString("yy-MM-dd HH:mm");
_machine.Imsi = string.IsNullOrEmpty(_request.imsi) ? string.Empty : _request.imsi;
_machine.MeterSerialNumber = string.IsNullOrEmpty(_request.meterSerialNumber) ? string.Empty : _request.meterSerialNumber;
_machine.MeterType = string.IsNullOrEmpty(_request.meterType) ? string.Empty : _request.meterType;
db.SaveChanges();
var configVaule = db.MachineConfiguration.Where(x => x.ChargeBoxId == session.ChargeBoxId && x.ConfigureName == StandardConfiguration.HeartbeatInterval)
.Select(x => x.ConfigureSetting).FirstOrDefault();
if (configVaule != null)
{
int.TryParse(configVaule, out heartbeat_interval);
}
}
var confirm = new BootNotificationConfirmation() { currentTime = DateTime.UtcNow, interval = session.IsPending ? heartbeat_interval : 5, status = session.IsPending ? Packet.Messages.SubTypes.RegistrationStatus.Accepted : RegistrationStatus.Pending };
session.IsPending = !session.IsPending;
result.Message = confirm;
result.Success = true;
}
break;
case Actions.StatusNotification:
{
//只保留最新上報狀況
StatusNotificationRequest _request = request as StatusNotificationRequest;
int preStatus = 0;
using (var db = new MainDBContext())
{
var _oldStatus = db.ConnectorStatus.Where(x => x.ChargeBoxId == session.ChargeBoxId
&& x.ConnectorId == _request.connectorId).AsNoTracking().FirstOrDefault();
if (_oldStatus != null && (_request.status != (ChargePointStatus)_oldStatus.Status || _request.status == ChargePointStatus.Faulted))
{
preStatus = _oldStatus.Status;
db.Configuration.AutoDetectChangesEnabled = false;
db.Configuration.ValidateOnSaveEnabled = false;
db.ConnectorStatus.Attach(_oldStatus);
_oldStatus.CreatedOn = _request.timestamp.HasValue ? _request.timestamp.Value : DateTime.UtcNow;
_oldStatus.Status = (int)_request.status;
_oldStatus.ChargePointErrorCodeId = (int)_request.errorCode;
_oldStatus.ErrorInfo = string.IsNullOrEmpty(_request.info) ? string.Empty : _request.info;
_oldStatus.VendorId = string.IsNullOrEmpty(_request.vendorId) ? string.Empty : _request.vendorId;
_oldStatus.VendorErrorCode = string.IsNullOrEmpty(_request.vendorErrorCode) ? string.Empty : _request.vendorErrorCode;
db.Entry(_oldStatus).Property(x => x.CreatedOn).IsModified = true;
db.Entry(_oldStatus).Property(x => x.Status).IsModified = true;
db.Entry(_oldStatus).Property(x => x.ChargePointErrorCodeId).IsModified = true;
db.Entry(_oldStatus).Property(x => x.ErrorInfo).IsModified = true;
db.Entry(_oldStatus).Property(x => x.VendorId).IsModified = true;
db.Entry(_oldStatus).Property(x => x.VendorErrorCode).IsModified = true;
}
if (_oldStatus == null)
{
var _currentStatus = new Domain.Models.Database.ConnectorStatus()
{
ChargeBoxId = session.ChargeBoxId,
ConnectorId = (byte)_request.connectorId,
CreatedOn = _request.timestamp.HasValue ? _request.timestamp.Value : DateTime.UtcNow,
Status = (int)_request.status,
ChargePointErrorCodeId = (int)_request.errorCode,
ErrorInfo = string.IsNullOrEmpty(_request.info) ? string.Empty : _request.info,
VendorId = string.IsNullOrEmpty(_request.vendorId) ? string.Empty : _request.vendorId,
VendorErrorCode = string.IsNullOrEmpty(_request.vendorErrorCode) ? string.Empty : _request.vendorErrorCode,
Id = Guid.NewGuid().ToString()
};
db.ConnectorStatus.Add(_currentStatus);
}
if (_request.status == Packet.Messages.SubTypes.ChargePointStatus.Faulted)
{
db.MachineError.Add(new MachineError()
{
ConnectorId = (byte)_request.connectorId,
CreatedOn = _request.timestamp.HasValue ? _request.timestamp.Value : DateTime.UtcNow,
Status = (int)_request.status,
ChargeBoxId = session.ChargeBoxId,
ErrorCodeId = (int)_request.errorCode,
ErrorInfo = string.IsNullOrEmpty(_request.info) ? string.Empty : _request.info,
PreStatus = _oldStatus == null ? -1 : preStatus,
VendorErrorCode = string.IsNullOrEmpty(_request.vendorErrorCode) ? string.Empty : _request.vendorErrorCode,
VendorId = string.IsNullOrEmpty(_request.vendorId) ? string.Empty : _request.vendorId
});
}
db.SaveChanges();
}
if (_request.status == Packet.Messages.SubTypes.ChargePointStatus.Faulted)
{
var alarmCond = GlobalConfig.GetAlarmNotification_Cond();
if (!string.IsNullOrEmpty(_request.vendorErrorCode) && alarmCond.Contains(_request.vendorErrorCode))
{
List sendlist = GlobalConfig.GetSMS_Receivers().Split(',').ToList();
foreach (var item in sendlist)
{
string message = string.Format("[{0}告警-{1}]\r\n{2} -{3}\r\n時間:{4}\r\n", session.StationName, _request.vendorErrorCode, session.ChargeBoxId,
_request.connectorId, DateTime.UtcNow.AddHours(8).ToString("yyyy/MM/dd HH:mm:ss"));
string errorMsg = string.Empty;
errorMsg = await smsService.SendMessage(item, message);
if (!string.IsNullOrEmpty(errorMsg))
{
logger.Error("Send SMS " + message);
logger.Error("Send SMS Error " + errorMsg);
}
}
}
var businessService = BusinessServiceFactory.CreateBusinessService(session.CustomerId.ToString());
var notification = businessService.NotifyFaultStatus(new ErrorDetails()
{
ChargeBoxId = session.ChargeBoxId,
ConnectorId = _request.connectorId,
ErrorCode = _request.errorCode,
Info = string.IsNullOrEmpty(_request.info) ? string.Empty : _request.info,
OCcuredOn = _request.timestamp ?? DateTime.UtcNow,
VendorErrorCode = string.IsNullOrEmpty(_request.vendorErrorCode) ? string.Empty : _request.vendorErrorCode,
});
}
var confirm = new StatusNotificationConfirmation() { };
result.Message = confirm;
result.Success = true;
}
break;
case Actions.Heartbeat:
{
var confirm = new HeartbeatConfirmation() { currentTime = DateTime.UtcNow };
result.Message = confirm;
result.Success = true;
}
break;
case Actions.MeterValues:
{
MeterValuesRequest _request = request as MeterValuesRequest;
if (_request.meterValue.Count > 0)
{
using (var db = new MeterValueDBContext())
{
foreach (var item in _request.meterValue)
{
foreach (var sampleVaule in item.sampledValue)
{
decimal value = Convert.ToDecimal(sampleVaule.value);
string sp = "[dbo].[uspInsertMeterValueRecord] @ChargeBoxId," +
"@ConnectorId,@Value,@CreatedOn,@ContextId,@FormatId,@MeasurandId,@PhaseId,@LocationId,@UnitId,@TransactionId";
List parameter = new List
{
new SqlParameter("ChargeBoxId",session.ChargeBoxId),
new SqlParameter("ConnectorId", (byte)_request.connectorId),
new SqlParameter("Value",value),
new SqlParameter("CreatedOn",item.timestamp),
new SqlParameter("ContextId",sampleVaule.context.HasValue ? (int)sampleVaule.context : 0),
new SqlParameter("FormatId",sampleVaule.format.HasValue ? (int)sampleVaule.format : 0),
new SqlParameter("MeasurandId",sampleVaule.measurand.HasValue ? (int)sampleVaule.measurand : 0),
new SqlParameter("PhaseId",sampleVaule.phase.HasValue ? (int)sampleVaule.phase : 0),
new SqlParameter("LocationId",sampleVaule.location.HasValue ? (int)sampleVaule.location : 0),
new SqlParameter("UnitId",sampleVaule.unit.HasValue ? (int)sampleVaule.unit : 0),
new SqlParameter("TransactionId",_request.transactionId.HasValue?_request.transactionId:-1),
};
db.Database.ExecuteSqlCommand(sp, parameter.ToArray());
}
}
}
}
// if (energy_kwh > 0)
{
try
{
if (session.IsBilling)
if (session.IsBilling)
{
using (var db = new MainDBContext())
{
db.ServerMessage.Add(new ServerMessage()
{
ChargeBoxId = session.ChargeBoxId,
CreatedBy = "Server",
CreatedOn = DateTime.UtcNow,
OutAction = Actions.DataTransfer.ToString(),
OutRequest = JsonConvert.SerializeObject(
new DataTransferRequest()
{
messageId = "ID_TxEnergy",
vendorId = "Phihong Technology",
data = JsonConvert.SerializeObject(new { txId = _request.transactionId, ConnectorId = _request.connectorId })
},
new JsonSerializerSettings() { NullValueHandling = NullValueHandling.Ignore, Formatting = Formatting.None }),
SerialNo = Guid.NewGuid().ToString(),
InMessage = string.Empty
});
db.SaveChanges();
}
}
}
catch (Exception ex)
{
Console.WriteLine(string.Format("{0} :{1}", session.ChargeBoxId + " RunningCost", ex.Message));
}
}
var confirm = new MeterValuesConfirmation() { };
result.Message = confirm;
result.Success = true;
}
break;
case Actions.StartTransaction:
{
StartTransactionRequest _request = request as StartTransactionRequest;
int _transactionId = -1;
var businessService = BusinessServiceFactory.CreateBusinessService(session.CustomerId.ToString());
var _idTagInfo = _request.idTag == "Backend" ? new IdTagInfo() { expiryDate = DateTime.UtcNow.AddDays(1), status = AuthorizationStatus.Accepted } : await businessService.Authorize(session.ChargeBoxId, _request.idTag);
//特例****飛宏客戶旗下的電樁,若遇到Portal沒回應的狀況 ~允許充電
if (session.CustomerId.ToString().ToUpper() == "8456AED9-6DD9-4BF3-A94C-9F5DCB9506F7" && _idTagInfo.status == AuthorizationStatus.ConcurrentTx)
{
_idTagInfo = new IdTagInfo() { expiryDate = DateTime.UtcNow.AddDays(1), status = AuthorizationStatus.Accepted };
}
string accountBalance = "0";
if (session.CustomerId.ToString().ToUpper() == "10C7F5BD-C89A-4E2A-8611-B617E0B41A73")
{
using (SqlConnection conn = new SqlConnection(webConnectionString))
{
var parameters = new DynamicParameters();
parameters.Add("@IdTag", _request.idTag, DbType.String, ParameterDirection.Input);
string strSql = "select parentIdTag from [dbo].[LocalListDetail] where ListId = 27 and IdTag=@IdTag; ";
accountBalance = conn.ExecuteScalar(strSql, parameters);
}
}
using (var db = new MainDBContext())
{
var _CustomerId = db.Machine.Where(x => x.ChargeBoxId == session.ChargeBoxId).Include(x => x.Customer).
Select(x => x.CustomerId).FirstOrDefault();
var _existedTx = db.TransactionRecord.Where(x => x.CustomerId == _CustomerId && x.ChargeBoxId == session.ChargeBoxId
&& x.ConnectorId == _request.connectorId && x.StartTime == _request.timestamp).Select(C => new { C.Id }).AsNoTracking().FirstOrDefault();
TransactionRecord _newTransaction = new TransactionRecord();
if (_existedTx == null)
{
_newTransaction = new TransactionRecord()
{
ChargeBoxId = session.ChargeBoxId,
ConnectorId = (byte)_request.connectorId,
CreatedOn = DateTime.UtcNow,
StartIdTag = _request.idTag,
MeterStart = _request.meterStart,
CustomerId = _CustomerId,
StartTime = _request.timestamp.ToUniversalTime(),
ReservationId = _request.reservationId.HasValue ? _request.reservationId.Value : 0,
};
_newTransaction.Fee = !session.IsBilling ? string.Empty : session.BillingMethod == 1 ? JsonConvert.SerializeObject(session.ChargingPrices) : session.ChargingFeebyHour.ToString();
_newTransaction.Fee += !session.IsBilling ? string.Empty : "|+" + accountBalance + "+" + "&" + session.ParkingFee + "&|" + session.Currency;
db.TransactionRecord.Add(_newTransaction);
db.SaveChanges();
_transactionId = _newTransaction.Id;
logger.Info("***************************************************** ");
logger.Info(string.Format("{0} :TransactionId {1} ", session.ChargeBoxId, _newTransaction.Id));
logger.Info("***************************************************** ");
}
else
{
_transactionId = _existedTx.Id;
logger.Error("Duplication ***************************************************** " + _existedTx.Id);
}
}
var confirm = new StartTransactionConfirmation()
{
idTagInfo = _idTagInfo,
transactionId = _transactionId
};
result.Message = confirm;
result.Success = true;
}
break;
case Actions.StopTransaction:
{
StopTransactionRequest _request = request as StopTransactionRequest;
int _ConnectorId = 0;
var businessService = BusinessServiceFactory.CreateBusinessService(session.CustomerId.ToString());
//特例****飛宏客戶旗下的電樁,若遇到Portal沒回應的狀況 ~允許充電
var _idTagInfo = string.IsNullOrEmpty(_request.idTag) ? null : (_request.idTag == "Backend" ? new IdTagInfo() { expiryDate = DateTime.UtcNow.AddDays(1), status = AuthorizationStatus.Accepted } : await businessService.Authorize(session.ChargeBoxId, _request.idTag));
if (session.CustomerId.ToString().ToUpper() == "8456AED9-6DD9-4BF3-A94C-9F5DCB9506F7" && _idTagInfo != null && _idTagInfo.status == AuthorizationStatus.ConcurrentTx)
{
_idTagInfo = new IdTagInfo() { expiryDate = DateTime.UtcNow.AddDays(1), status = AuthorizationStatus.Accepted };
}
try
{
using (var db = new MainDBContext())
{
var transaction = db.TransactionRecord.Where(x => x.Id == _request.transactionId
&& x.ChargeBoxId == session.ChargeBoxId).FirstOrDefault();
// throw new Exception("123");
//遠傳太久以前的停止充電 直接拒絕 避免電樁持續重送~~~~~~~
if (_request.timestamp < new DateTime(2021, 11, 1))
{
var confirm = new StopTransactionConfirmation()
{
idTagInfo = new IdTagInfo()
{
status = AuthorizationStatus.Invalid
}
};
result.Message = confirm;
result.Success = true;
return result;
}
if (transaction != null)
{
var confirm = new StopTransactionConfirmation()
{
idTagInfo = _idTagInfo
};
//Avoid rewrite transaction data
if (transaction.StopTime != GlobalConfig.DefaultNullTime)
{
result.Message = confirm;
result.Success = true;
return result;
}
_ConnectorId = transaction.ConnectorId;
transaction.MeterStop = _request.meterStop;
transaction.StopTime = _request.timestamp.ToUniversalTime();
transaction.StopReasonId = _request.reason.HasValue ? (int)_request.reason.Value : 0;
transaction.StopIdTag = _request.idTag;
transaction.Receipt = string.Empty;
transaction.Cost = session.IsBilling ? -1 : 0;
await db.SaveChangesAsync();
if (session.IsBilling)
{
db.ServerMessage.Add(new ServerMessage()
{
ChargeBoxId = session.ChargeBoxId,
CreatedBy = "Server",
CreatedOn = DateTime.UtcNow,
OutAction = Actions.DataTransfer.ToString(),
OutRequest = JsonConvert.SerializeObject(
new DataTransferRequest()
{
messageId = "ID_TxEnergy",
vendorId = "Phihong Technology",
data = JsonConvert.SerializeObject(new { txId = _request.transactionId, ConnectorId = transaction.ConnectorId })
},
new JsonSerializerSettings() { NullValueHandling = NullValueHandling.Ignore, Formatting = Formatting.None }),
SerialNo = Guid.NewGuid().ToString(),
InMessage = string.Empty
});
db.SaveChanges();
}
result.Message = confirm;
result.Success = true;
}
else
{
result.Exception = new Exception("Can't find transactionId " + _request.transactionId);
}
}
if (_request.transactionData != null)
{
if (_request.transactionData.Count > 0)
{
using (var _meterDb = new MeterValueDBContext())
{
foreach (var item in _request.transactionData)
{
foreach (var sampleVaule in item.sampledValue)
{
decimal value = Convert.ToDecimal(sampleVaule.value);
string sp = "[dbo].[uspInsertMeterValueRecord] @ChargeBoxId," +
"@ConnectorId,@Value,@CreatedOn,@ContextId,@FormatId,@MeasurandId,@PhaseId,@LocationId,@UnitId,@TransactionId";
List parameter = new List
{
new SqlParameter("ChargeBoxId",session.ChargeBoxId),
new SqlParameter("ConnectorId", (byte)_ConnectorId),
new SqlParameter("Value",value),
new SqlParameter("CreatedOn",item.timestamp),
new SqlParameter("ContextId",sampleVaule.context.HasValue ? (int)sampleVaule.context : 0),
new SqlParameter("FormatId",sampleVaule.format.HasValue ? (int)sampleVaule.format : 0),
new SqlParameter("MeasurandId",sampleVaule.measurand.HasValue ? (int)sampleVaule.measurand : 0),
new SqlParameter("PhaseId",sampleVaule.phase.HasValue ? (int)sampleVaule.phase : 0),
new SqlParameter("LocationId",sampleVaule.location.HasValue ? (int)sampleVaule.location : 0),
new SqlParameter("UnitId",sampleVaule.unit.HasValue ? (int)sampleVaule.unit : 0),
new SqlParameter("TransactionId",_request.transactionId),
};
_meterDb.Database.ExecuteSqlCommand(sp, parameter.ToArray());
}
}
}
}
}
}
catch (Exception ex)
{
result.Exception = new Exception("TransactionId " + _request.transactionId + " " + ex.Message);
result.CallErrorMsg = "Reject Response Message";
result.Success = false;
// return result;
}
}
break;
case Actions.Authorize:
{
AuthorizeRequest _request = request as AuthorizeRequest;
//特例****飛宏客戶旗下的電樁,若遇到Portal沒回應的狀況 ~允許充電
var businessService = BusinessServiceFactory.CreateBusinessService(session.CustomerId.ToString());
var confirm = new AuthorizeConfirmation()
{
idTagInfo = _request.idTag == "Backend" ? new IdTagInfo() { expiryDate = DateTime.UtcNow.AddDays(1), status = AuthorizationStatus.Accepted } : await businessService.Authorize(session.ChargeBoxId, _request.idTag)
};
if (session.CustomerId.ToString().ToUpper() == "8456AED9-6DD9-4BF3-A94C-9F5DCB9506F7" && confirm.idTagInfo.status == AuthorizationStatus.ConcurrentTx)
{
confirm.idTagInfo = new IdTagInfo() { expiryDate = DateTime.UtcNow.AddDays(1), status = AuthorizationStatus.Accepted };
}
result.Message = confirm;
result.Success = true;
}
break;
default:
{
Console.WriteLine(string.Format("Not Implement {0} Logic(ExecuteCoreRequest)", request.GetType().ToString().Replace("OCPPPackage.Messages.Core.", "")));
}
break;
}
}
catch (Exception ex)
{
logger.Fatal(string.Format("chargeBoxId:{0} {1}", session.ChargeBoxId, action));
logger.Fatal(string.Format("Data {0}", request.ToString()));
logger.Fatal(string.Format("Error {0}", ex.ToString()));
result.Exception = ex;
}
if (action == Actions.Heartbeat)
{
watch.Stop();
if (watch.ElapsedMilliseconds / 1000 > 3)
{
logger.Error("Processing Hearbeat costs " + watch.ElapsedMilliseconds / 1000 + " seconds");
}
}
return result;
}
async internal Task ExecuteCoreConfirm(Actions action, ClientData session, IConfirmation confirm, string requestId)
{
MessageResult result = new MessageResult() { Success = true };
try
{
switch (action)
{
case Actions.DataTransfer:
{
DataTransferConfirmation _confirm = confirm as DataTransferConfirmation;
DataTransferRequest _request = _confirm.GetRequest() as DataTransferRequest;
using (var db = new MainDBContext())
{
var operation = db.MachineOperateRecord.Where(x => x.SerialNo == requestId &&
x.ChargeBoxId == session.ChargeBoxId && x.Status == 0).FirstOrDefault();
if (operation != null)
{
operation.FinishedOn = DateTime.UtcNow;
operation.Status = 1;//電樁有回覆
operation.EVSE_Status = (int)_confirm.status;
operation.EVSE_Value = string.IsNullOrEmpty(_confirm.data) ? "" : _confirm.data;
db.SaveChanges();
}
if (_request.messageId == "ID_FirmwareVersion")
{
var machine = new Machine() { Id = session.MachineId };
if (machine != null)
{
db.Configuration.AutoDetectChangesEnabled = false;
db.Configuration.ValidateOnSaveEnabled = false;
db.Machine.Attach(machine);
machine.BoardVersions = _confirm.data;
db.Entry(machine).Property(x => x.BoardVersions).IsModified = true;
db.SaveChanges();
}
}
if (_request.messageId == "ID_TxEnergy")
{
if (_confirm.status == DataTransferStatus.Accepted)
{
string receipt = string.Empty;
List bill = new List();
List chargingPrices = new List();
var txEnergy = JsonConvert.DeserializeObject(_confirm.data);
var feedto = db.TransactionRecord.Where(x => x.Id == txEnergy.TxId).Select(x => new { Id = x.Id, ConnectorId = x.ConnectorId, Fee = x.Fee, StopTime = x.StopTime, StartTime = x.StartTime }).FirstOrDefault();
decimal chargedEnergy = 0m;
if (feedto == null || string.IsNullOrEmpty(feedto.Fee)) return result;
string currency = feedto.Fee.Substring(feedto.Fee.Length - 3);
decimal chargingCost = 0;
using (var meterdb = new MeterValueDBContext())
{
string sp = "[dbo].[uspInsertMeterValueRecord] @ChargeBoxId," +
"@ConnectorId,@Value,@CreatedOn,@ContextId,@FormatId,@MeasurandId,@PhaseId,@LocationId,@UnitId,@TransactionId";
List parameter = new List
{
new SqlParameter("ChargeBoxId",session.ChargeBoxId),
new SqlParameter("ConnectorId", (byte)feedto.ConnectorId),
new SqlParameter("Value",txEnergy.PeriodEnergy.Sum(x=>x.Value)),
new SqlParameter("CreatedOn",DateTime.UtcNow),
new SqlParameter("ContextId",(int)ReadingContext.Sample_Periodic),
new SqlParameter("FormatId",(int)ValueFormat.Raw),
new SqlParameter("MeasurandId",(int)Measurand.TotalEnergy),
new SqlParameter("PhaseId", -1),
new SqlParameter("LocationId", -1),
new SqlParameter("UnitId", (int)UnitOfMeasure.kWh),
new SqlParameter("TransactionId",feedto.Id),
};
meterdb.Database.ExecuteSqlCommand(sp, parameter.ToArray());
}
if (feedto.Fee.Length > 58)
{
chargingPrices = JsonConvert.DeserializeObject>(feedto.Fee.Split('|')[0]);
foreach (var item in txEnergy.PeriodEnergy)
{
DateTime dt = new DateTime(2021, 01, 01, int.Parse(item.Key), 0, 0, DateTimeKind.Utc);
string startTime = dt.ToString("hh:mm tt", new CultureInfo("en-us"));
decimal perfee = 0;
//小數點無條件捨去到第4位
var periodEnergy = (decimal)((int)Decimal.Multiply(item.Value, 10000) / (double)10000);
chargedEnergy += periodEnergy;
if (chargingPrices.Count == 1)
{
perfee = Decimal.Multiply(periodEnergy, chargingPrices[0].Fee);
if (bill.Count == 0)
{
bill.Add(new ChargingBill()
{
StartTime = "12:00 AM",
EndTime = "11:59 PM",
Fee = chargingPrices[0].Fee
});
}
bill[0].PeriodEnergy += periodEnergy;
}
else
{
var price = chargingPrices.Where(x => x.StartTime == startTime).FirstOrDefault();
perfee = Decimal.Multiply(periodEnergy, price.Fee);
bill.Add(new ChargingBill()
{
StartTime = price.StartTime,
EndTime = price.EndTime,
PeriodEnergy = periodEnergy,
Fee = price.Fee,
});
}
if (bill.Count > 0)
{
bill[bill.Count - 1].Total += DollarRounding(perfee, session.Currency);
chargingCost += bill[bill.Count - 1].Total;
if (bill.Count == 1)
{
bill[bill.Count - 1].Total = DollarRounding(Decimal.Multiply(bill[0].PeriodEnergy, bill[0].Fee), session.Currency);
chargingCost = bill[bill.Count - 1].Total;
}
}
}
}
else
{
//以小時計費
foreach (var item in txEnergy.PeriodEnergy)
{ //小數點無條件捨去到第4位
var periodEnergy = (decimal)((int)Decimal.Multiply(item.Value, 10000) / (double)10000);
chargedEnergy += periodEnergy;
}
var fee = decimal.Parse(feedto.Fee.Split('|')[0]);
var charging_stoptime = feedto.StopTime == GlobalConfig.DefaultNullTime ? DateTime.Parse(DateTime.UtcNow.ToString("yyyy/MM/dd HH:mm")) : DateTime.Parse(feedto.StopTime.ToString("yyyy/MM/dd HH:mm"));
var charging_starttime = DateTime.Parse(feedto.StartTime.ToString("yyyy/MM/dd HH:mm"));
chargingCost = Decimal.Multiply((decimal)charging_stoptime.Subtract(charging_starttime).TotalHours, fee);
chargingCost = DollarRounding(chargingCost, session.Currency);
}
// 計算停車費 台泥不適用此停車費模式
var parkingFee = 0;// decimal.Parse(feedto.Fee.Split('&')[1]);
var stoptime = feedto.StopTime == GlobalConfig.DefaultNullTime ? DateTime.Parse(DateTime.UtcNow.ToString("yyyy/MM/dd HH:mm")) : DateTime.Parse(feedto.StopTime.ToString("yyyy/MM/dd HH:mm"));
var starttime = DateTime.Parse(feedto.StartTime.ToString("yyyy/MM/dd HH:mm"));
var totalHours = stoptime.Subtract(starttime).TotalHours;
var parkingCost = Decimal.Multiply((decimal)totalHours, parkingFee);
parkingCost = DollarRounding(parkingCost, session.Currency);
if (feedto.StopTime != GlobalConfig.DefaultNullTime)
{
decimal accountBalance = 0;
decimal.TryParse(feedto.Fee.Split('+')[1], out accountBalance);
var tx = db.TransactionRecord.Where(x => x.Id == txEnergy.TxId).FirstOrDefault();
if (tx == null)
{
Console.WriteLine("Tx is empty");
return result;
}
if (tx.UploadedtoTTIA) return result;
var startTime = new DateTime(tx.StartTime.Year, tx.StartTime.Month, tx.StartTime.Day, tx.StartTime.Hour, 0, 0);
List confirmbill = new List();
receipt = string.Format("({0} )Energy:", chargedEnergy);
while (startTime < tx.StopTime)
{
if (bill.Count == 1)
{
confirmbill = bill;
receipt += string.Format("| {0} - {1}:| {2} kWh @ ${3}/kWh=${4}", tx.StartTime.ToString("hh:mm tt", new CultureInfo("en-us")), tx.StopTime.ToString("hh:mm tt", new CultureInfo("en-us")),
confirmbill[0].PeriodEnergy.ToString("0.0000"), bill[0].Fee, bill[0].Total);
break;
}
if (bill.Count == 0)
{
receipt += string.Format("| {0} - {1} @ ${2}/hr=${3}", feedto.StartTime.ToString("hh:mm tt", new CultureInfo("en-us")),
feedto.StopTime.ToString("hh:mm tt", new CultureInfo("en-us")), feedto.Fee.Split('|')[0], chargingCost);
break;
}
if (bill.Count > 1)
{
var time = startTime.ToString("hh:mm tt", new CultureInfo("en-us"));
var tt = bill.Where(x => x.StartTime == time).FirstOrDefault();
confirmbill.Add(tt);
if (confirmbill.Count == 1)
{
confirmbill[0].StartTime = tx.StartTime.ToString("hh:mm tt", new CultureInfo("en-us"));
}
var stopTimeText = tx.StopTime.ToString("hh:mm tt", new CultureInfo("en-us"));
if (confirmbill[confirmbill.Count - 1].StartTime.Contains(stopTimeText.Split(' ')[1]))
{
var subHourText = (int.Parse(stopTimeText.Split(':')[0])).ToString();
subHourText = subHourText.Length == 1 ? "0" + subHourText : subHourText;
if (confirmbill[confirmbill.Count - 1].StartTime.Contains(subHourText))
{
confirmbill[confirmbill.Count - 1].EndTime = stopTimeText;
}
}
receipt += string.Format("| {0} - {1}:| {2} kWh @ ${3}/kWh=${4}", confirmbill[confirmbill.Count - 1].StartTime, confirmbill[confirmbill.Count - 1].EndTime,
confirmbill[confirmbill.Count - 1].PeriodEnergy.ToString("0.0000"), confirmbill[confirmbill.Count - 1].Fee, confirmbill[confirmbill.Count - 1].Total);
if (confirmbill.Count == 24) break;
}
startTime = startTime.AddHours(1);
}
if (session.CustomerId == new Guid("009E603C-79CD-4620-A2B8-D9349C0E8AD8"))
{
chargingCost = confirmbill.Count > 0 ? confirmbill.Sum(x => x.Total) : chargingCost;
chargingCost = chargedEnergy == 0 ? 0 : (chargingCost + parkingCost < 1 ? 1 : chargingCost); //台泥最低一元
receipt += string.Format("|Total Energy Fee : ${0}", chargingCost);
receipt += string.Format("|Parking Fee: | {0} - {1} @ ${2}/hr=${3}", feedto.StartTime.ToString("hh:mm tt", new CultureInfo("en-us")),
feedto.StopTime.ToString("hh:mm tt", new CultureInfo("en-us")), parkingFee, parkingCost);
tx.Cost = chargingCost + parkingCost;
}
else
{
chargingCost = confirmbill.Count > 0 ? confirmbill.Sum(x => x.Total) : chargingCost;
receipt += string.Format("|Total Energy Fee : ${0}", chargingCost);
receipt += string.Format("|Parking Fee: | {0} - {1} @ ${2}/hr=${3}", feedto.StartTime.ToString("hh:mm tt", new CultureInfo("en-us")),
feedto.StopTime.ToString("hh:mm tt", new CultureInfo("en-us")), parkingFee, parkingCost);
tx.Cost = chargingCost + parkingCost;
}
tx.StopTransactionReportedOn = DateTime.UtcNow;
tx.Receipt = receipt;
tx.UploadedtoTTIA = true;
db.Configuration.AutoDetectChangesEnabled = false;
db.Configuration.ValidateOnSaveEnabled = false;
db.TransactionRecord.Attach(tx);
db.Entry(tx).Property(x => x.StopTransactionReportedOn).IsModified = true;
db.Entry(tx).Property(x => x.Cost).IsModified = true;
db.Entry(tx).Property(x => x.Receipt).IsModified = true;
db.Entry(tx).Property(x => x.UploadedtoTTIA).IsModified = true;
#region 同步發送充電結束通知
decimal? discountFee = null;//折扣金額
decimal? chargingAmount = null;//充電抵用金使用金額
decimal? actualFee = null; //實際付款金額
var request = new
{
ChargeBoxId = tx.ChargeBoxId,
ConnectorId = tx.ConnectorId,
SessionId = tx.Id,
MeterStart = tx.MeterStart,
MeterStop = tx.MeterStop,
IdTag = tx.StartIdTag,
StartTime = tx.StartTime.ToString(GlobalConfig.UTC_DATETIMEFORMAT),
StopTime = tx.StopTime.ToString(GlobalConfig.UTC_DATETIMEFORMAT),
StopReason = tx.StopReasonId < 1 ? "Unknown" : (tx.StopReasonId > 12 ? "Unknown" : ((Reason)tx.StopReasonId).ToString()),
Receipt = tx.Receipt,
TotalCost = tx.Cost,
Fee = tx.Fee
};
var response = await httpClient.Post(GlobalConfig.TCC_API_URL + "completed_session", new Dictionary()
{
{ "PartnerId",session.CustomerId.ToString()}
}, request, GlobalConfig.TCC_SALTKEY);
var _httpResult = JsonConvert.DeserializeObject(response.Response);
if (!string.IsNullOrEmpty(_httpResult.Data))
{
JObject jo = JObject.Parse(_httpResult.Data);
if (jo.ContainsKey("discountAmount"))
{
discountFee = jo["discountAmount"].Value();
}
if (jo.ContainsKey("chargingAmount"))
{
chargingAmount = jo["chargingAmount"].Value();
}
if (jo.ContainsKey("actualAmount"))
{
actualFee = jo["actualAmount"].Value();
}
}
#endregion
db.ServerMessage.Add(new ServerMessage()
{
ChargeBoxId = session.ChargeBoxId,
CreatedBy = "Server",
CreatedOn = DateTime.UtcNow,
OutAction = Actions.DataTransfer.ToString(),
OutRequest = JsonConvert.SerializeObject(
new DataTransferRequest()
{
messageId = "FinalCost",
vendorId = "Phihong Technology",
data = JsonConvert.SerializeObject(new
{
txId = txEnergy.TxId,
description = JsonConvert.SerializeObject(new
{
chargedEnergy = chargedEnergy,
chargingFee = actualFee.HasValue ? actualFee : chargingCost,
parkTime = (int)stoptime.Subtract(starttime).TotalSeconds,
parkingFee = parkingCost,
currency = currency,
accountBalance = accountBalance - tx.Cost
}, GlobalConfig.JSONSERIALIZER_FORMAT)
})
}, GlobalConfig.JSONSERIALIZER_FORMAT),
SerialNo = Guid.NewGuid().ToString(),
InMessage = string.Empty
}); ;
db.SaveChanges();
using (var meterdb = new MeterValueDBContext())
{
string sp = "[dbo].[uspInsertMeterValueRecord] @ChargeBoxId," +
"@ConnectorId,@Value,@CreatedOn,@ContextId,@FormatId,@MeasurandId,@PhaseId,@LocationId,@UnitId,@TransactionId";
List parameter = new List
{
new SqlParameter("ChargeBoxId",session.ChargeBoxId),
new SqlParameter("ConnectorId", (byte)feedto.ConnectorId),
new SqlParameter("Value",chargingCost),
new SqlParameter("CreatedOn",DateTime.UtcNow),
new SqlParameter("ContextId",(int)ReadingContext.Sample_Periodic),
new SqlParameter("FormatId",(int)ValueFormat.Raw),
new SqlParameter("MeasurandId",(int)Measurand.TotalCost),
new SqlParameter("PhaseId", -1),
new SqlParameter("LocationId", -1),
new SqlParameter("UnitId", -1),
new SqlParameter("TransactionId",feedto.Id),
};
meterdb.Database.ExecuteSqlCommand(sp, parameter.ToArray());
}
using (SqlConnection conn = new SqlConnection(webConnectionString))
{
var parameters = new DynamicParameters();
parameters.Add("@IdTag", tx.StartIdTag, DbType.String, ParameterDirection.Input);
parameters.Add("@parentIdTag", accountBalance - tx.Cost, DbType.String, ParameterDirection.Input);
string strSql = "update [dbo].[LocalListDetail] set parentIdTag =@parentIdTag where ListId = 27 and IdTag=@IdTag; ";
conn.Execute(strSql, parameters);
}
if (tx.CustomerId == Guid.Parse("10C7F5BD-C89A-4E2A-8611-B617E0B41A73"))
{
var mail_response = new OuterHttpClient().PostFormDataAsync("http://ocpp.phihong.com.tw/CDFA/" + tx.Id, new Dictionary()
{
{ "email","2"},
{ "to","wonderj@phihongusa.com;jessica_tseng@phihong.com.tw"}
//{ "to","jessica_tseng@phihong.com.tw"}
}, null);
Console.WriteLine(JsonConvert.SerializeObject(mail_response));
}
}
else
{
db.ServerMessage.Add(new ServerMessage()
{
ChargeBoxId = session.ChargeBoxId,
CreatedBy = "Server",
CreatedOn = DateTime.UtcNow,
OutAction = Actions.DataTransfer.ToString(),
OutRequest = JsonConvert.SerializeObject(
new DataTransferRequest()
{
messageId = "RunningCost",
vendorId = "Phihong Technology",
data = JsonConvert.SerializeObject(new
{
txId = txEnergy.TxId,
description = JsonConvert.SerializeObject(new
{
chargedEnergy = chargedEnergy,
chargingFee = chargingCost,
parkTime = (int)stoptime.Subtract(starttime).TotalSeconds,
parkingFee = parkingCost,
currency = currency
})
})
},
new JsonSerializerSettings() { NullValueHandling = NullValueHandling.Ignore, Formatting = Formatting.None }),
SerialNo = Guid.NewGuid().ToString(),
InMessage = string.Empty
}); ;
db.SaveChanges();
using (var meterdb = new MeterValueDBContext())
{
string sp = "[dbo].[uspInsertMeterValueRecord] @ChargeBoxId," +
"@ConnectorId,@Value,@CreatedOn,@ContextId,@FormatId,@MeasurandId,@PhaseId,@LocationId,@UnitId,@TransactionId";
List parameter = new List
{
new SqlParameter("ChargeBoxId",session.ChargeBoxId),
new SqlParameter("ConnectorId", (byte)feedto.ConnectorId),
new SqlParameter("Value",chargingCost),
new SqlParameter("CreatedOn",DateTime.UtcNow),
new SqlParameter("ContextId",(int)ReadingContext.Sample_Periodic),
new SqlParameter("FormatId",(int)ValueFormat.Raw),
new SqlParameter("MeasurandId",(int)Measurand.ChargingCost),
new SqlParameter("PhaseId", -1),
new SqlParameter("LocationId", -1),
new SqlParameter("UnitId", -1),
new SqlParameter("TransactionId",feedto.Id),
};
meterdb.Database.ExecuteSqlCommand(sp, parameter.ToArray());
}
}
}
}
if (_request.messageId == "ID_GetTxUserInfo")
{
var txUserInfo = JsonConvert.DeserializeObject(_confirm.data);
if (session.CustomerId == new Guid("009E603C-79CD-4620-A2B8-D9349C0E8AD8"))
{
var request = new
{
ChargeBoxId = session.ChargeBoxId,
ConnectorId = txUserInfo.ConnectorId,
SessionId = txUserInfo.TxId,
SerialNo = txUserInfo.SerialNo,
StartTime = txUserInfo.StartTime.ToString(GlobalConfig.UTC_DATETIMEFORMAT),
VEMData = txUserInfo.VEMData
};
var response = httpClient.Post(GlobalConfig.TCC_API_URL + "start_session", new Dictionary()
{
{ "PartnerId",session.CustomerId.ToString()}
}, request, GlobalConfig.TCC_SALTKEY);
logger.Debug(JsonConvert.SerializeObject(response));
}
}
}
}
break;
case Actions.ChangeAvailability:
{
ChangeAvailabilityConfirmation _confirm = confirm as ChangeAvailabilityConfirmation;
ChangeAvailabilityRequest _request = _confirm.GetRequest() as ChangeAvailabilityRequest;
using (var db = new MainDBContext())
{
var operation = db.MachineOperateRecord.Where(x => x.SerialNo == requestId &&
x.ChargeBoxId == session.ChargeBoxId && x.Status == 0).FirstOrDefault();
if (operation != null)
{
operation.FinishedOn = DateTime.UtcNow;
operation.Status = 1;//電樁有回覆
operation.EVSE_Status = (int)_confirm.status;
operation.EVSE_Value = _confirm.status.ToString();
db.SaveChanges();
}
}
}
break;
case Actions.ClearCache:
{
ClearCacheConfirmation _confirm = confirm as ClearCacheConfirmation;
ClearCacheRequest _request = _confirm.GetRequest() as ClearCacheRequest;
using (var db = new MainDBContext())
{
var operation = db.MachineOperateRecord.Where(x => x.SerialNo == requestId &&
x.ChargeBoxId == session.ChargeBoxId && x.Status == 0).FirstOrDefault();
if (operation != null)
{
operation.FinishedOn = DateTime.UtcNow;
operation.Status = 1;//電樁有回覆
operation.EVSE_Status = (int)_confirm.status;
operation.EVSE_Value = _confirm.status.ToString();
db.SaveChanges();
}
}
}
break;
case Actions.RemoteStartTransaction:
{
RemoteStartTransactionConfirmation _confirm = confirm as RemoteStartTransactionConfirmation;
RemoteStartTransactionRequest _request = _confirm.GetRequest() as RemoteStartTransactionRequest;
using (var db = new MainDBContext())
{
var operation = db.MachineOperateRecord.Where(x => x.SerialNo == requestId &&
x.ChargeBoxId == session.ChargeBoxId && x.Status == 0).FirstOrDefault();
if (operation != null)
{
operation.FinishedOn = DateTime.UtcNow;
operation.Status = 1;//電樁有回覆
operation.EVSE_Status = (int)_confirm.status;
operation.EVSE_Value = _confirm.status.ToString();
db.SaveChanges();
}
}
}
break;
case Actions.RemoteStopTransaction:
{
RemoteStopTransactionConfirmation _confirm = confirm as RemoteStopTransactionConfirmation;
RemoteStopTransactionRequest _request = _confirm.GetRequest() as RemoteStopTransactionRequest;
using (var db = new MainDBContext())
{
var operation = db.MachineOperateRecord.Where(x => x.SerialNo == requestId &&
x.ChargeBoxId == session.ChargeBoxId && x.Status == 0).FirstOrDefault();
if (operation != null)
{
operation.FinishedOn = DateTime.UtcNow;
operation.Status = 1;//電樁有回覆
operation.EVSE_Status = (int)_confirm.status;
operation.EVSE_Value = _confirm.status.ToString();
db.SaveChanges();
}
}
}
break;
case Actions.Reset:
{
ResetConfirmation _confirm = confirm as ResetConfirmation;
ResetRequest _request = _confirm.GetRequest() as ResetRequest;
using (var db = new MainDBContext())
{
var operation = db.MachineOperateRecord.Where(x => x.SerialNo == requestId &&
x.ChargeBoxId == session.ChargeBoxId && x.Status == 0).FirstOrDefault();
if (operation != null)
{
operation.FinishedOn = DateTime.UtcNow;
operation.Status = 1;//電樁有回覆
operation.EVSE_Status = (int)_confirm.status;
operation.EVSE_Value = _confirm.status.ToString();
db.SaveChanges();
}
}
}
break;
case Actions.ChangeConfiguration:
{
ChangeConfigurationConfirmation _confirm = confirm as ChangeConfigurationConfirmation;
ChangeConfigurationRequest _request = _confirm.GetRequest() as ChangeConfigurationRequest;
using (var db = new MainDBContext())
{
var operation = db.MachineOperateRecord.Where(x => x.SerialNo == requestId &&
x.ChargeBoxId == session.ChargeBoxId && x.Status == 0).FirstOrDefault();
if (operation != null)
{
operation.FinishedOn = DateTime.UtcNow;
operation.Status = 1;//電樁有回覆
operation.EVSE_Status = (int)_confirm.status;
operation.EVSE_Value = _confirm.status.ToString();
}
if (_confirm.status == Packet.Messages.SubTypes.ConfigurationStatus.Accepted || _confirm.status == Packet.Messages.SubTypes.ConfigurationStatus.RebootRequired)
{
var configure = db.MachineConfiguration.Where(x => x.ChargeBoxId == session.ChargeBoxId).ToList();
var foundConfig = configure.Find(x => x.ConfigureName == _request.key);
if (foundConfig != null)
{
foundConfig.ReadOnly = false;
foundConfig.ConfigureSetting = _request.value;
}
else
{
db.MachineConfiguration.Add(new MachineConfiguration()
{
ChargeBoxId = session.ChargeBoxId,
ConfigureName = _request.key,
ReadOnly = false,
ConfigureSetting = _request.value
});
}
}
db.SaveChanges();
}
}
break;
case Actions.GetConfiguration:
{
try
{
GetConfigurationConfirmation _confirm = confirm as GetConfigurationConfirmation;
// GetConfigurationRequest _request = _confirm.GetRequest() as GetConfigurationRequest;
using (var db = new MainDBContext())
{
var configure = db.MachineConfiguration.Where(x => x.ChargeBoxId == session.ChargeBoxId).ToList();
if (_confirm.configurationKey != null)
{
foreach (var item in _confirm.configurationKey)
{
string oldValue = string.Empty;
if (item.key == null)
{
Console.WriteLine("*********************");
}
var foundConfig = configure.Find(x => x.ConfigureName == item.key);
if (foundConfig != null)
{
if (foundConfig.ConfigureName == null)
{
Console.WriteLine("*********************");
}
if (foundConfig.ConfigureName == "SecurityProfile")
{
oldValue = foundConfig.ConfigureSetting;
}
foundConfig.ReadOnly = item.IsReadOnly;
foundConfig.ConfigureSetting = string.IsNullOrEmpty(item.value) ? string.Empty : item.value;
}
else
{
db.MachineConfiguration.Add(new MachineConfiguration()
{
ChargeBoxId = session.ChargeBoxId,
ConfigureName = item.key,
ReadOnly = item.IsReadOnly,
ConfigureSetting = string.IsNullOrEmpty(item.value) ? string.Empty : item.value,
Exists = true
});
}
}
}
if (_confirm.unknownKey != null)
{
foreach (var item in _confirm.unknownKey)
{
var foundConfig = configure.Find(x => x.ConfigureName == item);
if (foundConfig != null)
{
foundConfig.ReadOnly = true;
foundConfig.ConfigureSetting = string.Empty;
foundConfig.Exists = false;
}
else
{
db.MachineConfiguration.Add(new MachineConfiguration()
{
ChargeBoxId = session.ChargeBoxId,
ConfigureName = item
});
}
}
}
var operation = db.MachineOperateRecord.Where(x => x.SerialNo == requestId &&
x.ChargeBoxId == session.ChargeBoxId && x.Status == 0).FirstOrDefault();
if (operation != null)
{
operation.FinishedOn = DateTime.UtcNow;
operation.Status = 1;//電樁有回覆
operation.EVSE_Status = 1;
operation.EVSE_Value = JsonConvert.SerializeObject(_confirm.configurationKey, Formatting.None);
}
db.SaveChanges();
}
}
catch (Exception ex)
{
logger.Error(ex.ToString());
}
}
break;
case Actions.UnlockConnector:
{
UnlockConnectorConfirmation _confirm = confirm as UnlockConnectorConfirmation;
UnlockConnectorRequest _request = _confirm.GetRequest() as UnlockConnectorRequest;
using (var db = new MainDBContext())
{
var operation = db.MachineOperateRecord.Where(x => x.SerialNo == requestId &&
x.ChargeBoxId == session.ChargeBoxId && x.Status == 0).FirstOrDefault();
if (operation != null)
{
operation.FinishedOn = DateTime.UtcNow;
operation.Status = 1;//電樁有回覆
operation.EVSE_Status = (int)_confirm.status;
operation.EVSE_Value = _confirm.status.ToString();
db.SaveChanges();
}
}
}
break;
default:
{
Console.WriteLine(string.Format("Not Implement {0} Logic(ExecuteCoreConfirm)", confirm.GetType().ToString().Replace("OCPPPackage.Messages.Core.", "")));
}
break;
}
}
catch (Exception ex)
{
logger.Debug("123 " + action + " " + ex.ToString());
}
return result;
}
internal MessageResult ReceivedCoreError(Actions action, string errorMsg, ClientData session, string requestId)
{
MessageResult result = new MessageResult() { Success = true };
switch (action)
{
case Actions.ChangeAvailability:
case Actions.ChangeConfiguration:
case Actions.ClearCache:
case Actions.RemoteStartTransaction:
case Actions.RemoteStopTransaction:
case Actions.Reset:
case Actions.GetConfiguration:
case Actions.UnlockConnector:
case Actions.DataTransfer:
{
if (action == Actions.DataTransfer)
{
logger.Debug(string.Format("DataTransfer Error {0}: {1}", session.ChargeBoxId, requestId));
}
using (var db = new MainDBContext())
{
var operation = db.MachineOperateRecord.Where(x => x.SerialNo == requestId &&
x.ChargeBoxId == session.ChargeBoxId && x.Status == 0).FirstOrDefault();
if (operation != null)
{
operation.FinishedOn = DateTime.UtcNow;
operation.Status = 1;//電樁有回覆
operation.EVSE_Status = (int)255;//錯誤
operation.EVSE_Value = errorMsg;
db.SaveChanges();
}
}
}
break;
default:
{
Console.WriteLine(string.Format("Not Implement {0} Logic(ReceivedCoreError)", action));
}
break;
}
return result;
}
///
/// 依據幣值處理4捨5入
///
///
///
///
private decimal DollarRounding(decimal money, string currency)
{
if (currency == "USD" || currency == "EUR")
{
//0.4867
if ((double)((int)(money * 100) + 0.5) <= (double)(money * 100))
{
//money = Decimal.Add(money, (decimal)0.01);//0.4967
}
money = Math.Round(money, 2, MidpointRounding.AwayFromZero);
money = Decimal.Parse(money.ToString("0.00"));
}
else
{
if ((double)((int)(money) + 0.5) <= (double)money)
{
// money = (int) money + 1;
}
money = Math.Round(money, 0, MidpointRounding.AwayFromZero);
money = Decimal.Parse(money.ToString("0"));
}
return money;
}
}
}