|
@@ -8,6 +8,7 @@ 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;
|
|
@@ -20,6 +21,7 @@ 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
|
|
@@ -62,11 +64,56 @@ namespace EVCB_OCPP.WSServer.Message
|
|
|
|
|
|
}
|
|
|
|
|
|
+ public class ID_GetOccupancyFee
|
|
|
+ {
|
|
|
+ public int ConnectorId { set; get; }
|
|
|
+
|
|
|
+ public string occupancySN { set; get; }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 1. Get occupancy fee info. 2. Cancel local deduction
|
|
|
+ /// </summary>
|
|
|
+ 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<MessageResult> ExecuteCoreRequest(Actions action, ClientData session, IRequest request)
|
|
|
{
|
|
|
Stopwatch watch = new Stopwatch();
|
|
@@ -83,6 +130,7 @@ namespace EVCB_OCPP.WSServer.Message
|
|
|
case Actions.DataTransfer:
|
|
|
{
|
|
|
DataTransferRequest _request = request as DataTransferRequest;
|
|
|
+
|
|
|
var confirm = new DataTransferConfirmation() { status = DataTransferStatus.UnknownMessageId };
|
|
|
|
|
|
if (_request.messageId == "ID_CreditDeductResult")
|
|
@@ -144,6 +192,178 @@ namespace EVCB_OCPP.WSServer.Message
|
|
|
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<string>(), jo["timestamp"].Value<string>());
|
|
|
+
|
|
|
+ confirm.status = DataTransferStatus.Accepted;
|
|
|
+ }
|
|
|
+ if (_request.messageId == "ID_OccupancyFeeAct")
|
|
|
+ {
|
|
|
+ var getOccupancyFee = JsonConvert.DeserializeObject<ID_GetOccupancyFee>(_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<string, string>()
|
|
|
+ {
|
|
|
+ { "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<CPOOuterResponse>(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<string>();
|
|
|
+
|
|
|
+ }
|
|
|
+ if (jo.ContainsKey("OccupancyDuration"))
|
|
|
+ {
|
|
|
+ occupancyFeeResult.duration = jo["OccupancyDuration"].Value<int>();
|
|
|
+ }
|
|
|
+
|
|
|
+ if (jo.ContainsKey("OccupancyFee"))
|
|
|
+ {
|
|
|
+ occupancyFeeResult.occupancyFee = jo["OccupancyFee"].Value<decimal>();
|
|
|
+ }
|
|
|
+
|
|
|
+ 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<string, string>()
|
|
|
+ {
|
|
|
+ { "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<CPOOuterResponse>(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<string, string>()
|
|
|
+ {
|
|
|
+ { "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<CPOOuterResponse>(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<ID_OccupancyFeeResult>(_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<string, string>()
|
|
|
+ {
|
|
|
+ { "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;
|
|
|
}
|
|
@@ -262,6 +482,27 @@ namespace EVCB_OCPP.WSServer.Message
|
|
|
|
|
|
if (_request.status == Packet.Messages.SubTypes.ChargePointStatus.Faulted)
|
|
|
{
|
|
|
+ var alarmCond = GlobalConfig.GetAlarmNotification_Cond();
|
|
|
+
|
|
|
+ if (!string.IsNullOrEmpty(_request.vendorErrorCode) && alarmCond.Contains(_request.vendorErrorCode))
|
|
|
+ {
|
|
|
+ List<string> 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()
|
|
|
{
|
|
@@ -273,6 +514,8 @@ namespace EVCB_OCPP.WSServer.Message
|
|
|
VendorErrorCode = string.IsNullOrEmpty(_request.vendorErrorCode) ? string.Empty : _request.vendorErrorCode,
|
|
|
|
|
|
});
|
|
|
+
|
|
|
+
|
|
|
}
|
|
|
|
|
|
var confirm = new StatusNotificationConfirmation() { };
|
|
@@ -292,7 +535,6 @@ namespace EVCB_OCPP.WSServer.Message
|
|
|
{
|
|
|
|
|
|
MeterValuesRequest _request = request as MeterValuesRequest;
|
|
|
- decimal energy_kwh = 0;
|
|
|
|
|
|
if (_request.meterValue.Count > 0)
|
|
|
{
|
|
@@ -302,60 +544,12 @@ namespace EVCB_OCPP.WSServer.Message
|
|
|
{
|
|
|
foreach (var item in _request.meterValue)
|
|
|
{
|
|
|
- int registerCount = item.sampledValue.Where(x => x.measurand == Measurand.Energy_Active_Import_Interval).ToList().Count;
|
|
|
- if (registerCount > 0)
|
|
|
- {
|
|
|
- registerCount = 0;
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- registerCount = item.sampledValue.Where(x => x.measurand == Measurand.Energy_Active_Import_Register).ToList().Count;
|
|
|
- }
|
|
|
|
|
|
- if (registerCount > 0)
|
|
|
- {
|
|
|
- string voltage_text = item.sampledValue.Where(x => x.measurand == Measurand.Voltage).Select(x => x.value).FirstOrDefault();
|
|
|
- decimal voltage = decimal.Parse(voltage_text);
|
|
|
- string current_text = item.sampledValue.Where(x => x.measurand == Measurand.Current_Import).Select(x => x.value).FirstOrDefault();
|
|
|
- decimal current = decimal.Parse(current_text);
|
|
|
- decimal meterStart = 0;
|
|
|
- string energyRegister_text = item.sampledValue.Where(x => x.measurand == Measurand.Energy_Active_Import_Register).Select(x => x.value).FirstOrDefault();
|
|
|
- decimal energyRegister = decimal.Parse(energyRegister_text);
|
|
|
- using (var maindb = new MainDBContext())
|
|
|
- {
|
|
|
- meterStart = maindb.TransactionRecord.Where(x => x.Id == _request.transactionId.Value).Select(x => x.MeterStart).FirstOrDefault();
|
|
|
- }
|
|
|
|
|
|
- item.sampledValue.Add(new SampledValue()
|
|
|
- {
|
|
|
- context = ReadingContext.Sample_Periodic,
|
|
|
- format = ValueFormat.Raw,
|
|
|
- location = Location.Outlet,
|
|
|
- phase = Phase.L1_N,
|
|
|
- unit = UnitOfMeasure.kWh,
|
|
|
- measurand = Measurand.Energy_Active_Import_Interval,
|
|
|
- value = decimal.Divide(decimal.Subtract(energyRegister, meterStart), (decimal)1000).ToString()
|
|
|
- });
|
|
|
- item.sampledValue.Add(new SampledValue()
|
|
|
- {
|
|
|
- context = ReadingContext.Sample_Periodic,
|
|
|
- format = ValueFormat.Raw,
|
|
|
- location = Location.Outlet,
|
|
|
- phase = Phase.L1_N,
|
|
|
- unit = UnitOfMeasure.kW,
|
|
|
- measurand = Measurand.Power_Active_Import,
|
|
|
- value = decimal.Divide(decimal.Multiply(voltage, current), (decimal)1000).ToString()
|
|
|
- });
|
|
|
- }
|
|
|
foreach (var sampleVaule in item.sampledValue)
|
|
|
{
|
|
|
decimal value = Convert.ToDecimal(sampleVaule.value);
|
|
|
|
|
|
- if (sampleVaule.context == ReadingContext.Sample_Periodic && sampleVaule.measurand == Measurand.Energy_Active_Import_Interval)
|
|
|
- {
|
|
|
- energy_kwh = sampleVaule.unit == UnitOfMeasure.Wh ? Decimal.Divide(value, 1000) : value;
|
|
|
- }
|
|
|
-
|
|
|
string sp = "[dbo].[uspInsertMeterValueRecord] @ChargeBoxId," +
|
|
|
"@ConnectorId,@Value,@CreatedOn,@ContextId,@FormatId,@MeasurandId,@PhaseId,@LocationId,@UnitId,@TransactionId";
|
|
|
|
|
@@ -532,109 +726,110 @@ namespace EVCB_OCPP.WSServer.Message
|
|
|
_idTagInfo = new IdTagInfo() { expiryDate = DateTime.UtcNow.AddDays(1), status = AuthorizationStatus.Accepted };
|
|
|
}
|
|
|
|
|
|
-
|
|
|
-
|
|
|
- using (var db = new MainDBContext())
|
|
|
+ try
|
|
|
{
|
|
|
- var transaction = db.TransactionRecord.Where(x => x.Id == _request.transactionId
|
|
|
- && x.ChargeBoxId == session.ChargeBoxId).FirstOrDefault();
|
|
|
-
|
|
|
- //遠傳太久以前的停止充電 直接拒絕 避免電樁持續重送~~~~~~~
|
|
|
- if (_request.timestamp < new DateTime(2021, 11, 1))
|
|
|
+ using (var db = new MainDBContext())
|
|
|
{
|
|
|
- var confirm = new StopTransactionConfirmation()
|
|
|
+ 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))
|
|
|
{
|
|
|
- idTagInfo = new IdTagInfo()
|
|
|
+ var confirm = new StopTransactionConfirmation()
|
|
|
{
|
|
|
- status = AuthorizationStatus.Invalid
|
|
|
- }
|
|
|
-
|
|
|
- };
|
|
|
-
|
|
|
- result.Message = confirm;
|
|
|
- result.Success = true;
|
|
|
- return result;
|
|
|
- }
|
|
|
-
|
|
|
+ idTagInfo = new IdTagInfo()
|
|
|
+ {
|
|
|
+ status = AuthorizationStatus.Invalid
|
|
|
+ }
|
|
|
|
|
|
- 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 (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;
|
|
|
|
|
|
- if (session.IsBilling)
|
|
|
- {
|
|
|
- db.ServerMessage.Add(new ServerMessage()
|
|
|
+ await db.SaveChangesAsync();
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ if (session.IsBilling)
|
|
|
{
|
|
|
- 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.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();
|
|
|
- }
|
|
|
+ db.SaveChanges();
|
|
|
+ }
|
|
|
|
|
|
- result.Message = confirm;
|
|
|
- result.Success = true;
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
+ result.Message = confirm;
|
|
|
+ result.Success = true;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
|
|
|
- result.Exception = new Exception("Can't find transactionId " + _request.transactionId);
|
|
|
+ result.Exception = new Exception("Can't find transactionId " + _request.transactionId);
|
|
|
|
|
|
+ }
|
|
|
}
|
|
|
- }
|
|
|
|
|
|
- if (_request.transactionData != null)
|
|
|
- {
|
|
|
- if (_request.transactionData.Count > 0)
|
|
|
+ if (_request.transactionData != null)
|
|
|
{
|
|
|
- using (var _meterDb = new MeterValueDBContext())
|
|
|
+ if (_request.transactionData.Count > 0)
|
|
|
{
|
|
|
- foreach (var item in _request.transactionData)
|
|
|
+ using (var _meterDb = new MeterValueDBContext())
|
|
|
{
|
|
|
- foreach (var sampleVaule in item.sampledValue)
|
|
|
+ foreach (var item in _request.transactionData)
|
|
|
{
|
|
|
- decimal value = Convert.ToDecimal(sampleVaule.value);
|
|
|
+ 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";
|
|
|
+ string sp = "[dbo].[uspInsertMeterValueRecord] @ChargeBoxId," +
|
|
|
+ "@ConnectorId,@Value,@CreatedOn,@ContextId,@FormatId,@MeasurandId,@PhaseId,@LocationId,@UnitId,@TransactionId";
|
|
|
|
|
|
- List<SqlParameter> parameter = new List<SqlParameter>
|
|
|
+ List<SqlParameter> parameter = new List<SqlParameter>
|
|
|
{
|
|
|
new SqlParameter("ChargeBoxId",session.ChargeBoxId),
|
|
|
new SqlParameter("ConnectorId", (byte)_ConnectorId),
|
|
@@ -650,14 +845,24 @@ namespace EVCB_OCPP.WSServer.Message
|
|
|
};
|
|
|
|
|
|
|
|
|
- _meterDb.Database.ExecuteSqlCommand(sp, parameter.ToArray());
|
|
|
+ _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;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
|
|
|
|
|
|
}
|
|
@@ -710,7 +915,7 @@ namespace EVCB_OCPP.WSServer.Message
|
|
|
return result;
|
|
|
}
|
|
|
|
|
|
- internal MessageResult ExecuteCoreConfirm(Actions action, ClientData session, IConfirmation confirm, string requestId)
|
|
|
+ async internal Task<MessageResult> ExecuteCoreConfirm(Actions action, ClientData session, IConfirmation confirm, string requestId)
|
|
|
{
|
|
|
MessageResult result = new MessageResult() { Success = true };
|
|
|
|
|
@@ -763,6 +968,32 @@ namespace EVCB_OCPP.WSServer.Message
|
|
|
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<SqlParameter> parameter = new List<SqlParameter>
|
|
|
+ {
|
|
|
+ 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<List<ChargingPrice>>(feedto.Fee.Split('|')[0]);
|
|
@@ -835,8 +1066,8 @@ namespace EVCB_OCPP.WSServer.Message
|
|
|
chargingCost = DollarRounding(chargingCost, session.Currency);
|
|
|
}
|
|
|
|
|
|
- // 計算停車費
|
|
|
- var parkingFee = decimal.Parse(feedto.Fee.Split('&')[1]);
|
|
|
+ // 計算停車費 台泥不適用此停車費模式
|
|
|
+ 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;
|
|
@@ -928,15 +1159,70 @@ namespace EVCB_OCPP.WSServer.Message
|
|
|
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<string, string>()
|
|
|
+ {
|
|
|
+ { "PartnerId",session.CustomerId.ToString()}
|
|
|
+
|
|
|
+ }, request, GlobalConfig.TCC_SALTKEY);
|
|
|
+
|
|
|
+ var _httpResult = JsonConvert.DeserializeObject<CPOOuterResponse>(response.Response);
|
|
|
+ if (!string.IsNullOrEmpty(_httpResult.Data))
|
|
|
+ {
|
|
|
+ JObject jo = JObject.Parse(_httpResult.Data);
|
|
|
+ if (jo.ContainsKey("discountAmount"))
|
|
|
+ {
|
|
|
+ discountFee = jo["discountAmount"].Value<decimal>();
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ if (jo.ContainsKey("chargingAmount"))
|
|
|
+ {
|
|
|
+ chargingAmount = jo["chargingAmount"].Value<decimal>();
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ if (jo.ContainsKey("actualAmount"))
|
|
|
+ {
|
|
|
+ actualFee = jo["actualAmount"].Value<decimal>();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ #endregion
|
|
|
+
|
|
|
+
|
|
|
db.ServerMessage.Add(new ServerMessage()
|
|
|
{
|
|
|
ChargeBoxId = session.ChargeBoxId,
|
|
@@ -954,17 +1240,15 @@ namespace EVCB_OCPP.WSServer.Message
|
|
|
description = JsonConvert.SerializeObject(new
|
|
|
{
|
|
|
chargedEnergy = chargedEnergy,
|
|
|
- chargingFee = chargingCost,
|
|
|
+ chargingFee = actualFee.HasValue ? actualFee : chargingCost,
|
|
|
parkTime = (int)stoptime.Subtract(starttime).TotalSeconds,
|
|
|
parkingFee = parkingCost,
|
|
|
currency = currency,
|
|
|
- couponPoint = 0,
|
|
|
accountBalance = accountBalance - tx.Cost
|
|
|
- })
|
|
|
+ }, GlobalConfig.JSONSERIALIZER_FORMAT)
|
|
|
})
|
|
|
|
|
|
- },
|
|
|
- new JsonSerializerSettings() { NullValueHandling = NullValueHandling.Ignore, Formatting = Formatting.None }),
|
|
|
+ }, GlobalConfig.JSONSERIALIZER_FORMAT),
|
|
|
SerialNo = Guid.NewGuid().ToString(),
|
|
|
InMessage = string.Empty
|
|
|
|