瀏覽代碼

1.切出V1 V2 版API,V2版 對外API支援判斷電樁是走ocpp16 ocpp20 功能

Jessica Tseng 2 年之前
父節點
當前提交
de40cb5ba2

+ 7 - 0
EVCB_OCPP.WEBAPI/App_Start/WebApiConfig.cs

@@ -30,6 +30,13 @@ namespace EVCB_OCPP.WEBAPI
                 routeTemplate: "api/v1/{controller}/{id}",
                 defaults: new { id = RouteParameter.Optional }
             );
+
+
+            config.Routes.MapHttpRoute(
+              name: "Version2",
+              routeTemplate: "api/v2/{controller}/{id}",
+              defaults: new { id = RouteParameter.Optional }
+          );
         }
     }
 }

+ 43 - 250
EVCB_OCPP.WEBAPI/Controllers/Version1/CPOController.cs

@@ -298,9 +298,9 @@ namespace EVCB_OCPP.WEBAPI.Controllers.Version1
                     }
                     else
                     {
-                        result.StatusCode = (int)CPO_StatusCode.Success;
-                        result.StatusMessage = CPO_StatusMessage.Success;
-                        statusCode = HttpStatusCode.OK;
+                        result.StatusCode = _innerResult.ErrorCode;
+                        result.StatusMessage = _innerResult.Message;
+                        statusCode = HttpStatusCode.BadRequest;
                     }
 
 
@@ -376,16 +376,16 @@ namespace EVCB_OCPP.WEBAPI.Controllers.Version1
                 else
                 {
 
-                    if (_innerResult.ErrorCode == (int)CPO_StatusCode.CHARGEBOXID_ISNT_EXIST_OR_OFFLINE)
+                    if (_innerResult.ErrorCode == (int)CPO_StatusCode.UnexpectedError)
                     {
-                        result.StatusMessage = CPO_StatusMessage.ERROR_MSG_CHARGEBOXID_ISNT_EXIST_OR_OFFLINE;
-                        result.StatusCode = (int)CPO_StatusCode.CHARGEBOXID_ISNT_EXIST_OR_OFFLINE;
-                        statusCode = HttpStatusCode.OK;
+                        result.StatusCode = _innerResult.ErrorCode;
+                        result.StatusMessage = CPO_StatusMessage.ERROR_MSG_INNERSERVICE_ERROR;
+                        statusCode = HttpStatusCode.BadRequest;
                     }
                     else
                     {
                         result.StatusCode = _innerResult.ErrorCode;
-                        result.StatusMessage = CPO_StatusMessage.ERROR_MSG_INNERSERVICE_ERROR;
+                        result.StatusMessage = _innerResult.Message;
                         statusCode = HttpStatusCode.BadRequest;
                     }
                 }
@@ -452,17 +452,16 @@ namespace EVCB_OCPP.WEBAPI.Controllers.Version1
                 }
                 else
                 {
-
-                    if (_innerResult.ErrorCode == (int)CPO_StatusCode.CHARGEBOXID_ISNT_EXIST_OR_OFFLINE)
+                    if (_innerResult.ErrorCode == (int)CPO_StatusCode.UnexpectedError)
                     {
-                        result.StatusMessage = CPO_StatusMessage.ERROR_MSG_CHARGEBOXID_ISNT_EXIST_OR_OFFLINE;
-                        result.StatusCode = (int)CPO_StatusCode.CHARGEBOXID_ISNT_EXIST_OR_OFFLINE;
-                        statusCode = HttpStatusCode.OK;
-                    }
+                        result.StatusCode = _innerResult.ErrorCode;
+                        result.StatusMessage = CPO_StatusMessage.ERROR_MSG_INNERSERVICE_ERROR;
+                        statusCode = HttpStatusCode.BadRequest;
+                    }                        
                     else
                     {
                         result.StatusCode = _innerResult.ErrorCode;
-                        result.StatusMessage = CPO_StatusMessage.ERROR_MSG_INNERSERVICE_ERROR;
+                        result.StatusMessage = _innerResult.Message;
                         statusCode = HttpStatusCode.BadRequest;
                     }
                 }
@@ -482,7 +481,7 @@ namespace EVCB_OCPP.WEBAPI.Controllers.Version1
         [Route("commands/chargingprofiles")]
         [ResponseType(typeof(CPOOuterResponse))]
         [HttpGet]
-        async public Task<HttpResponseMessage> GetActiveChargingProfile(string ChargeBoxId, int ConnectorId, int Duration)
+        async public Task<HttpResponseMessage> GetActiveChargingProfile(string ChargeBoxId, int ConnectorId, int Duration, int ChargingRateUnit = -1)
         {
             var result = new CPOOuterResponse();
             HttpStatusCode statusCode = HttpStatusCode.InternalServerError;
@@ -508,9 +507,9 @@ namespace EVCB_OCPP.WEBAPI.Controllers.Version1
 
                 string[] parts = Request.RequestUri.ToString().Split('/');
 
-                string urlformat = "{0}//{1}/api/v1/ocpp16/compositeschedule?ChargeBoxId={2}&ConnectorId={3}&Duration={4}";
+                string urlformat = "{0}//{1}/api/v1/ocpp16/compositeschedule?ChargeBoxId={2}&ConnectorId={3}&Duration={4}&ChargingRateUnit={5}";
 
-                var _innerResult = await _client.Get(string.Format(urlformat, parts[0], parts[2], ChargeBoxId, ConnectorId, Duration), new Dictionary<string, string>()
+                var _innerResult = await _client.Get(string.Format(urlformat, parts[0], parts[2], ChargeBoxId, ConnectorId, Duration, ChargingRateUnit), new Dictionary<string, string>()
                         {
                             { "PartnerId",_CustomerId}
 
@@ -529,16 +528,16 @@ namespace EVCB_OCPP.WEBAPI.Controllers.Version1
                 }
                 else
                 {
-                    if (_innerResult.ErrorCode == (int)CPO_StatusCode.CHARGEBOXID_ISNT_EXIST_OR_OFFLINE)
+                    if (_innerResult.ErrorCode == (int)CPO_StatusCode.UnexpectedError)
                     {
-                        result.StatusMessage = CPO_StatusMessage.ERROR_MSG_CHARGEBOXID_ISNT_EXIST_OR_OFFLINE;
-                        result.StatusCode = (int)CPO_StatusCode.CHARGEBOXID_ISNT_EXIST_OR_OFFLINE;
-                        statusCode = HttpStatusCode.OK;
+                        result.StatusCode = _innerResult.ErrorCode;
+                        result.StatusMessage = CPO_StatusMessage.ERROR_MSG_INNERSERVICE_ERROR;
+                        statusCode = HttpStatusCode.BadRequest;
                     }
                     else
                     {
                         result.StatusCode = _innerResult.ErrorCode;
-                        result.StatusMessage = CPO_StatusMessage.ERROR_MSG_INNERSERVICE_ERROR;
+                        result.StatusMessage = _innerResult.Message;
                         statusCode = HttpStatusCode.BadRequest;
                     }
 
@@ -607,16 +606,16 @@ namespace EVCB_OCPP.WEBAPI.Controllers.Version1
                 else
                 {
 
-                    if (_innerResult.ErrorCode == (int)CPO_StatusCode.CHARGEBOXID_ISNT_EXIST_OR_OFFLINE)
+                    if (_innerResult.ErrorCode == (int)CPO_StatusCode.UnexpectedError)
                     {
-                        result.StatusMessage = CPO_StatusMessage.ERROR_MSG_CHARGEBOXID_ISNT_EXIST_OR_OFFLINE;
-                        result.StatusCode = (int)CPO_StatusCode.CHARGEBOXID_ISNT_EXIST_OR_OFFLINE;
-                        statusCode = HttpStatusCode.OK;
+                        result.StatusCode = _innerResult.ErrorCode;
+                        result.StatusMessage = CPO_StatusMessage.ERROR_MSG_INNERSERVICE_ERROR;
+                        statusCode = HttpStatusCode.BadRequest;
                     }
                     else
                     {
                         result.StatusCode = _innerResult.ErrorCode;
-                        result.StatusMessage = CPO_StatusMessage.ERROR_MSG_INNERSERVICE_ERROR;
+                        result.StatusMessage = _innerResult.Message;
                         statusCode = HttpStatusCode.BadRequest;
                     }
                 }
@@ -691,16 +690,16 @@ namespace EVCB_OCPP.WEBAPI.Controllers.Version1
                 else
                 {
 
-                    if (_innerResult.ErrorCode == (int)CPO_StatusCode.CHARGEBOXID_ISNT_EXIST_OR_OFFLINE)
+                    if (_innerResult.ErrorCode == (int)CPO_StatusCode.UnexpectedError)
                     {
-                        result.StatusMessage = CPO_StatusMessage.ERROR_MSG_CHARGEBOXID_ISNT_EXIST_OR_OFFLINE;
-                        result.StatusCode = (int)CPO_StatusCode.CHARGEBOXID_ISNT_EXIST_OR_OFFLINE;
-                        statusCode = HttpStatusCode.OK;
+                        result.StatusCode = _innerResult.ErrorCode;
+                        result.StatusMessage = CPO_StatusMessage.ERROR_MSG_INNERSERVICE_ERROR;
+                        statusCode = HttpStatusCode.BadRequest;
                     }
                     else
                     {
                         result.StatusCode = _innerResult.ErrorCode;
-                        result.StatusMessage = CPO_StatusMessage.ERROR_MSG_INNERSERVICE_ERROR;
+                        result.StatusMessage = _innerResult.Message;
                         statusCode = HttpStatusCode.BadRequest;
                     }
                 }
@@ -770,16 +769,16 @@ namespace EVCB_OCPP.WEBAPI.Controllers.Version1
                 else
                 {
 
-                    if (_innerResult.ErrorCode == (int)CPO_StatusCode.CHARGEBOXID_ISNT_EXIST_OR_OFFLINE)
+                    if (_innerResult.ErrorCode == (int)CPO_StatusCode.UnexpectedError)
                     {
-                        result.StatusMessage = CPO_StatusMessage.ERROR_MSG_CHARGEBOXID_ISNT_EXIST_OR_OFFLINE;
-                        result.StatusCode = (int)CPO_StatusCode.CHARGEBOXID_ISNT_EXIST_OR_OFFLINE;
-                        statusCode = HttpStatusCode.OK;
+                        result.StatusCode = _innerResult.ErrorCode;
+                        result.StatusMessage = CPO_StatusMessage.ERROR_MSG_INNERSERVICE_ERROR;
+                        statusCode = HttpStatusCode.BadRequest;
                     }
                     else
                     {
                         result.StatusCode = _innerResult.ErrorCode;
-                        result.StatusMessage = CPO_StatusMessage.ERROR_MSG_INNERSERVICE_ERROR;
+                        result.StatusMessage = _innerResult.Message;
                         statusCode = HttpStatusCode.BadRequest;
                     }
                 }
@@ -850,16 +849,16 @@ namespace EVCB_OCPP.WEBAPI.Controllers.Version1
                 else
                 {
 
-                    if (_innerResult.ErrorCode == (int)CPO_StatusCode.CHARGEBOXID_ISNT_EXIST_OR_OFFLINE)
+                    if (_innerResult.ErrorCode == (int)CPO_StatusCode.UnexpectedError)
                     {
-                        result.StatusMessage = CPO_StatusMessage.ERROR_MSG_CHARGEBOXID_ISNT_EXIST_OR_OFFLINE;
-                        result.StatusCode = (int)CPO_StatusCode.CHARGEBOXID_ISNT_EXIST_OR_OFFLINE;
-                        statusCode = HttpStatusCode.OK;
+                        result.StatusCode = _innerResult.ErrorCode;
+                        result.StatusMessage = CPO_StatusMessage.ERROR_MSG_INNERSERVICE_ERROR;
+                        statusCode = HttpStatusCode.BadRequest;
                     }
                     else
                     {
                         result.StatusCode = _innerResult.ErrorCode;
-                        result.StatusMessage = CPO_StatusMessage.ERROR_MSG_INNERSERVICE_ERROR;
+                        result.StatusMessage = _innerResult.Message;
                         statusCode = HttpStatusCode.BadRequest;
                     }
                 }
@@ -1582,213 +1581,7 @@ namespace EVCB_OCPP.WEBAPI.Controllers.Version1
             }
 
             return Request.CreateResponse(statusCode, result);
-        }
-
-        #region CDFA
-        [Route("commands/defaulprice")]
-        [ResponseType(typeof(CPOOuterResponse))]
-        [HttpPost]
-        async public Task<HttpResponseMessage> ChargePointDefaultPrice(string ChargeBoxId, [FromBody] ChargePointDefaultPriceRequest request)
-        {
-            var result = new CPOOuterResponse();
-            HttpStatusCode statusCode = HttpStatusCode.InternalServerError;
-            var _innerData = new { Result = CommandResponseType.Rejected.ToString(), Timeout = 60 };
-            try
-            {
-                string _CustomerId = string.Empty;
-
-                if (!ContainsChargePoint(ChargeBoxId, out _CustomerId))
-                {
-                    // 沒槍~ 沒得充...                   
-                    result.StatusMessage = CPO_StatusMessage.ERROR_MSG_CHARGEBOXID_DOESNT_EXIST;
-                    result.StatusCode = (int)CPO_StatusCode.CHARGEBOXID_ISNT_EXIST_OR_OFFLINE;
-                    result.Data = JsonConvert.SerializeObject(_innerData, EVCBConfiguration.JSONSERIALIZER_FORMAT);
-                    statusCode = HttpStatusCode.BadRequest;
-                    return Request.CreateResponse(statusCode, result);
-                }
-
-
-                ChargePointService chargePointService = new ChargePointService();
-
-                if (!chargePointService.IsOnline(ChargeBoxId))
-                {
-
-                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Code = 2101, Message = EVCBConfiguration.ERROR_MSG_CHARGEBOXID_ISNT_EXIST_OR_OFFLINE });
-                }
-                //create reqest
-                var _request = new DataTransferRequest()
-                {
-                    messageId = "DefaultPrice",
-                    vendorId = "Phihong Technology",
-                    data = request.DefaultPrice
-                };
-
-                string uuid = Guid.NewGuid().ToString();
-                if (!AddCommandtoServer(ChargeBoxId, uuid, _request))
-                {
-                    throw new Exception("Write Command Fail!!");
-                }
-
-                result.SerialNo = uuid;
-                result.Data = JsonConvert.SerializeObject(new { Result = CommandResponseType.Accepted.ToString(), Timeout = 60 });
-                await Task.Delay(10);
-
-            }
-            catch (Exception ex)
-            {
-                result.Data = JsonConvert.SerializeObject(_innerData);
-                result.ErrorDetail = ex.ToString();
-                result.StatusMessage = CPO_StatusMessage.ERROR_MSG_UNEXPECTEDERROR;
-                result.StatusCode = (int)CPO_StatusCode.UnexpectedError;
-                return Request.CreateResponse(statusCode, result);
-            }
-
-            return Request.CreateResponse(statusCode, result);
-        }
-
-
-        [Route("commands/userprice")]
-        [ResponseType(typeof(CPOOuterResponse))]
-        [HttpPost]
-        async public Task<HttpResponseMessage> UserPrice(string ChargeBoxId, [FromBody] UserPriceRequest request)
-        {
-            var result = new CPOOuterResponse();
-            HttpStatusCode statusCode = HttpStatusCode.InternalServerError;
-            var _innerData = new { Result = CommandResponseType.Rejected.ToString(), Timeout = 60 };
-            try
-            {
-                string _CustomerId = string.Empty;
-
-                if (!ContainsChargePoint(ChargeBoxId, out _CustomerId))
-                {
-                    // 沒槍~ 沒得充...                   
-                    result.StatusMessage = CPO_StatusMessage.ERROR_MSG_CHARGEBOXID_DOESNT_EXIST;
-                    result.StatusCode = (int)CPO_StatusCode.CHARGEBOXID_ISNT_EXIST_OR_OFFLINE;
-                    result.Data = JsonConvert.SerializeObject(_innerData, EVCBConfiguration.JSONSERIALIZER_FORMAT);
-                    statusCode = HttpStatusCode.BadRequest;
-                    return Request.CreateResponse(statusCode, result);
-                }
-
-
-                ChargePointService chargePointService = new ChargePointService();
-
-                if (!chargePointService.IsOnline(ChargeBoxId))
-                {
-
-                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Code = 2101, Message = EVCBConfiguration.ERROR_MSG_CHARGEBOXID_ISNT_EXIST_OR_OFFLINE });
-                }
-                //create reqest
-                var _request = new DataTransferRequest()
-                {
-                    messageId = "SetUserPrice",
-                    vendorId = "Phihong Technology",
-                    data = JsonConvert.SerializeObject(request)
-                };
-
-                string uuid = Guid.NewGuid().ToString();
-                if (!AddCommandtoServer(ChargeBoxId, uuid, _request))
-                {
-                    throw new Exception("Write Command Fail!!");
-                }
-
-                result.SerialNo = uuid;
-                result.Data = JsonConvert.SerializeObject(new { Result = CommandResponseType.Accepted.ToString(), Timeout = 60 });
-                await Task.Delay(10);
-
-            }
-            catch (Exception ex)
-            {
-                result.Data = JsonConvert.SerializeObject(_innerData);
-                result.ErrorDetail = ex.ToString();
-                result.StatusMessage = CPO_StatusMessage.ERROR_MSG_UNEXPECTEDERROR;
-                result.StatusCode = (int)CPO_StatusCode.UnexpectedError;
-                return Request.CreateResponse(statusCode, result);
-            }
-
-            return Request.CreateResponse(statusCode, result);
-        }
-
-        [Route("commands/finalcost")]
-        [ResponseType(typeof(CPOOuterResponse))]
-        [HttpPost]
-        async public Task<HttpResponseMessage> FinalCost(string ChargeBoxId, [FromBody] FinalCostRequest request)
-        {
-            var result = new CPOOuterResponse();
-            HttpStatusCode statusCode = HttpStatusCode.InternalServerError;
-            var _innerData = new { Result = CommandResponseType.Rejected.ToString(), Timeout = 60 };
-            try
-            {
-                string _CustomerId = string.Empty;
-
-                if (!ContainsChargePoint(ChargeBoxId, out _CustomerId))
-                {
-                    // 沒槍~ 沒得充...                   
-                    result.StatusMessage = CPO_StatusMessage.ERROR_MSG_CHARGEBOXID_DOESNT_EXIST;
-                    result.StatusCode = (int)CPO_StatusCode.CHARGEBOXID_ISNT_EXIST_OR_OFFLINE;
-                    result.Data = JsonConvert.SerializeObject(_innerData, EVCBConfiguration.JSONSERIALIZER_FORMAT);
-                    statusCode = HttpStatusCode.BadRequest;
-                    return Request.CreateResponse(statusCode, result);
-                }
-
-
-                ChargePointService chargePointService = new ChargePointService();
-
-                if (!chargePointService.IsOnline(ChargeBoxId))
-                {
-
-                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Code = 2101, Message = EVCBConfiguration.ERROR_MSG_CHARGEBOXID_ISNT_EXIST_OR_OFFLINE });
-                }
-
-                string text = JsonConvert.SerializeObject(request).Replace("SessionId", "txId");
-                //create reqest
-                var _request = new DataTransferRequest()
-                {
-                    messageId = "DefaultPrice",
-                    vendorId = "Phihong Technology",
-                    data = text
-                };
-
-                string uuid = Guid.NewGuid().ToString();
-                if (!AddCommandtoServer(ChargeBoxId, uuid, _request))
-                {
-                    throw new Exception("Write Command Fail!!");
-                }
-
-                result.SerialNo = uuid;
-                result.Data = JsonConvert.SerializeObject(new { Result = CommandResponseType.Accepted.ToString(), Timeout = 60 });
-                await Task.Delay(10);
-
-            }
-            catch (Exception ex)
-            {
-                result.Data = JsonConvert.SerializeObject(_innerData);
-                result.ErrorDetail = ex.ToString();
-                result.StatusMessage = CPO_StatusMessage.ERROR_MSG_UNEXPECTEDERROR;
-                result.StatusCode = (int)CPO_StatusCode.UnexpectedError;
-                return Request.CreateResponse(statusCode, result);
-            }
-
-            return Request.CreateResponse(statusCode, result);
-        }
-        #endregion
-
-
-        private bool AddCommandtoServer(string chargeBoxId, string uuid, IRequest request)
-        {
-            bool result = false;
-            try
-            {
-                ServerTriggerService service = new ServerTriggerService();
-                service.AddMessage(chargeBoxId, uuid, request);
-                result = true;
-            }
-            catch (Exception ex)
-            {
-                ;
-            }
-
-            return result;
-        }
+        }  
 
         private string GetStatisticChargeBoxIds(List<string> chargeBoxIds)
         {

+ 1193 - 0
EVCB_OCPP.WEBAPI/Controllers/Version2/V2_CPOController.cs

@@ -0,0 +1,1193 @@
+using Dapper;
+using EVCB_OCPP.Packet.Messages.SubTypes;
+using EVCB_OCPP.WEBAPI.Handlers;
+using EVCB_OCPP.WEBAPI.Models;
+using EVCB_OCPP.WEBAPI.Models.WebAPI;
+using EVCB_OCPP.WEBAPI.Models.WebAPI.Dto;
+using EVCB_OCPP.WEBAPI.Services;
+using EVCB_OCPP.WEBAPI.Services.Integration;
+using Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.Configuration;
+using System.Data;
+using System.Data.SqlClient;
+using System.Linq;
+using System.Net;
+using System.Net.Http;
+using System.Threading.Tasks;
+using System.Web;
+using System.Web.Http;
+using System.Web.Http.Description;
+using ChargingStationService = EVCB_OCPP.WEBAPI.Services.Integration.ChargingStationService;
+using CommandType = EVCB_OCPP.WEBAPI.Models.WebAPI.Dto.CommandType;
+using IChargePointService = EVCB_OCPP.WEBAPI.Services.Integration.IChargePointService;
+
+namespace EVCB_OCPP.WEBAPI.Controllers.Version2
+{    
+
+    [ApiExplorerSettings(IgnoreApi = false)]
+    [RoutePrefix("api/v2/cpo")]
+    [CPOAuthentication]
+    public class V2_CPOController : ApiController
+    {
+        [Route("information")]
+        [ResponseType(typeof(CPOOuterResponse))]
+        [HttpGet]
+        public HttpResponseMessage BasicInformationofEVSEs(int? Limit = -1, int StationId = -1, string ChargeBoxId = "", DateTime? DateFrom = null, DateTime? DateTo = null, int? Offset = 0)
+        {
+
+            var result = new CPOOuterResponse();
+            HttpStatusCode statusCode = HttpStatusCode.InternalServerError;
+            try
+            {
+
+
+                if (Request.Headers.Contains(EVCBConfiguration.Header_PartnerId))
+                {
+                    var _customerId = Request.Headers.GetValues(EVCBConfiguration.Header_PartnerId).First();
+
+                    var _innerResponse = new { EVSEs = new List<EVSE>() };
+                    ChargingStationService _stationService = new ChargingStationService();
+
+                    if (StationId > -1)
+                    {
+                        if (_stationService.ContainsStation(_customerId, StationId))
+                        {
+                            if (DateTo.HasValue)
+                            {
+                                if (!DateFrom.HasValue)
+                                {
+
+                                    result.StatusMessage = CPO_StatusMessage.ERROR_MSG_PARAMETER_OUTOFRANGE_INCORRECT;
+                                    result.StatusCode = (int)CPO_StatusCode.PARAMETER_OUTOFRANGE_INCORRECT;
+                                    statusCode = HttpStatusCode.BadRequest;
+                                    return Request.CreateResponse(statusCode, result);
+                                }
+                            }
+                            _innerResponse = new { EVSEs = _stationService.GetEVSEsbyStationId(StationId, DateFrom, DateTo, Offset.Value, Limit == -1 ? 1000 : Limit.Value) };
+
+
+                        }
+                    }
+                    else
+                    {
+                        IChargePointService _service = null;
+                        if (GetChargePointOCPPProtocol(ChargeBoxId) == OCPPProtocolType.OCPP16)
+                        {
+                            _service = new ChargePoint16Service();
+                        }
+                        else
+                        {
+                            _service = new ChargePoint201Service();
+                        }
+                        _innerResponse = new { EVSEs = new List<EVSE>() };
+                        _innerResponse.EVSEs.Add(_service.GetEVSEsbyChargeBoxId(ChargeBoxId, DateFrom, DateTo));
+
+
+                    }
+
+                    result.Data = JsonConvert.SerializeObject(_innerResponse, EVCBConfiguration.JSONSERIALIZER_FORMAT);
+                    result.StatusCode = (int)CPO_StatusCode.Success;
+                    result.StatusMessage = CPO_StatusMessage.Success;
+                    statusCode = HttpStatusCode.OK;
+
+                }
+                return Request.CreateResponse(statusCode, result);
+            }
+            catch (Exception ex)
+            {
+                result.ErrorDetail = ex.ToString();
+                result.StatusMessage = CPO_StatusMessage.ERROR_MSG_UNEXPECTEDERROR;
+                result.StatusCode = (int)CPO_StatusCode.UnexpectedError;
+                return Request.CreateResponse(statusCode, result);
+            }
+
+
+        }
+
+        [Route("contact_information")]
+        [ResponseType(typeof(CPOOuterResponse))]
+        [HttpGet]
+        public HttpResponseMessage ContactInformation()
+        {
+            var result = new CPOOuterResponse();
+            HttpStatusCode statusCode = HttpStatusCode.InternalServerError;
+            try
+            {
+                if (Request.Headers.Contains(EVCBConfiguration.Header_PartnerId))
+                {
+                    var customerId = Request.Headers.GetValues(EVCBConfiguration.Header_PartnerId).First();
+                    string mainConnectionString = ConfigurationManager.ConnectionStrings["MainDBContext"].ConnectionString;
+                    var parameters = new DynamicParameters();
+                    parameters.Add("@CustomerId", customerId, DbType.String, ParameterDirection.Input);
+                    string hotline = string.Empty;
+                    using (SqlConnection conn = new SqlConnection(mainConnectionString))
+                    {
+                        string strSql = "SELECT [Hotline]  FROM [dbo].[Customer] where Id=@CustomerId; ";
+                        hotline = conn.ExecuteScalar<string>(strSql, parameters);
+                    }
+                    result.Data = JsonConvert.SerializeObject(new { Info = hotline }, EVCBConfiguration.JSONSERIALIZER_FORMAT);
+                    result.StatusCode = (int)CPO_StatusCode.Success;
+                    result.StatusMessage = CPO_StatusMessage.Success;
+                    statusCode = HttpStatusCode.OK;
+                }
+                result.StatusCode = (int)CPO_StatusCode.Success;
+                result.StatusMessage = CPO_StatusMessage.Success;
+
+
+                statusCode = HttpStatusCode.OK;
+                return Request.CreateResponse(statusCode, result);
+
+            }
+            catch (Exception ex)
+            {
+                result.ErrorDetail = ex.ToString();
+                result.StatusMessage = CPO_StatusMessage.ERROR_MSG_UNEXPECTEDERROR;
+                result.StatusCode = (int)CPO_StatusCode.UnexpectedError;
+                return Request.CreateResponse(statusCode, result);
+            }
+
+        }
+
+        [Route("stationInfo")]
+        [ResponseType(typeof(CPOOuterResponse))]
+        [HttpGet]
+        public HttpResponseMessage StationInfo(string ChargeBoxId)
+        {
+            var result = new CPOOuterResponse();
+            HttpStatusCode statusCode = HttpStatusCode.InternalServerError;
+
+            try
+            {
+                ChargingStationService service = new ChargingStationService();
+
+                var _innerData = service.GetInfobyChargeBoxId(ChargeBoxId);
+
+                if (_innerData == null)
+                {
+                    result.StatusCode = (int)CPO_StatusCode.CANT_FOUND_DATA;
+                    result.StatusMessage = CPO_StatusMessage.ERROR_MSG_CANT_FIND_SESSIONDETAIL;
+                    statusCode = HttpStatusCode.NotFound;
+                    return Request.CreateResponse(statusCode, result);
+                }
+
+                result.Data = JsonConvert.SerializeObject(_innerData, EVCBConfiguration.JSONSERIALIZER_FORMAT);
+                result.StatusCode = (int)CPO_StatusCode.Success;
+                result.StatusMessage = CPO_StatusMessage.Success;
+                statusCode = HttpStatusCode.OK;
+                return Request.CreateResponse(statusCode, result);
+            }
+            catch (Exception ex)
+            {
+                result.ErrorDetail = ex.ToString();
+                result.StatusMessage = CPO_StatusMessage.ERROR_MSG_UNEXPECTEDERROR;
+                result.StatusCode = (int)CPO_StatusCode.UnexpectedError;
+                return Request.CreateResponse(statusCode, result);
+            }
+
+        }
+
+        [Route("version")]
+        [ResponseType(typeof(CPOOuterResponse))]
+        [HttpGet]
+        public HttpResponseMessage Version(string ChargeBoxId)
+        {
+            var result = new CPOOuterResponse();
+            HttpStatusCode statusCode = HttpStatusCode.InternalServerError;
+
+            try
+            {
+                IChargePointService _service = null;
+                if (GetChargePointOCPPProtocol(ChargeBoxId) == OCPPProtocolType.OCPP16)
+                {
+                    _service = new ChargePoint16Service();
+                }
+                else
+                {
+                    _service = new ChargePoint201Service();
+                }
+
+                result.Data = _service.GetVersionbyChargeBoxId(ChargeBoxId);
+                result.StatusCode = (int)CPO_StatusCode.Success;
+                result.StatusMessage = CPO_StatusMessage.Success;
+                statusCode = HttpStatusCode.OK;
+            }
+            catch (Exception ex)
+            {
+                result.ErrorDetail = ex.ToString();
+                result.StatusMessage = CPO_StatusMessage.ERROR_MSG_UNEXPECTEDERROR;
+                result.StatusCode = (int)CPO_StatusCode.UnexpectedError;
+                return Request.CreateResponse(statusCode, result);
+            }
+
+            return Request.CreateResponse(statusCode, result);
+
+        }
+
+        [Route("station")]
+        [ResponseType(typeof(CPOOuterResponse))]
+        [HttpGet]
+        public HttpResponseMessage Station()
+        {
+            var result = new CPOOuterResponse();
+            HttpStatusCode statusCode = HttpStatusCode.InternalServerError;
+            try
+            {
+                if (Request.Headers.Contains(EVCBConfiguration.Header_PartnerId))
+                {
+                    var _customerId = Request.Headers.GetValues(EVCBConfiguration.Header_PartnerId).First();
+                    ChargingStationService _service = new ChargingStationService();
+                    var _innerResponse = new { Stations = _service.GetStationsbyCustomerId(_customerId) };
+                    result.Data = JsonConvert.SerializeObject(_innerResponse, EVCBConfiguration.JSONSERIALIZER_FORMAT);
+                    result.StatusCode = (int)CPO_StatusCode.Success;
+                    result.StatusMessage = CPO_StatusMessage.Success;
+                    statusCode = HttpStatusCode.OK;
+                }
+                return Request.CreateResponse(statusCode, result);
+            }
+            catch (Exception ex)
+            {
+                result.ErrorDetail = ex.ToString();
+                result.StatusMessage = CPO_StatusMessage.ERROR_MSG_UNEXPECTEDERROR;
+                result.StatusCode = (int)CPO_StatusCode.UnexpectedError;
+                return Request.CreateResponse(statusCode, result);
+            }
+
+
+        }
+
+
+        [Route("commands/start_session")]
+        [ResponseType(typeof(CPOOuterResponse))]
+        [HttpPost]
+        async public Task<HttpResponseMessage> StartSession([FromBody] StartSessionRequest request)
+        {
+
+            var result = new CPOOuterResponse();
+            HttpStatusCode statusCode = HttpStatusCode.InternalServerError;
+            var _innerData = new { Result = CommandResponseType.Rejected.ToString(), Timeout = 60 };
+            try
+            {
+                string _CustomerId = string.Empty;
+
+                if (!ContainsChargePoint(request.ChargeBoxId, out _CustomerId))
+                {
+                    // 沒槍~ 沒得充...                   
+                    result.StatusMessage = CPO_StatusMessage.ERROR_MSG_CHARGEBOXID_DOESNT_EXIST;
+                    result.StatusCode = (int)CPO_StatusCode.CHARGEBOXID_ISNT_EXIST_OR_OFFLINE;
+                    result.Data = JsonConvert.SerializeObject(_innerData, EVCBConfiguration.JSONSERIALIZER_FORMAT);
+                    statusCode = HttpStatusCode.BadRequest;
+                    return Request.CreateResponse(statusCode, result);
+                }
+
+                IChargePointService _service = null;
+                if (GetChargePointOCPPProtocol(request.ChargeBoxId) == OCPPProtocolType.OCPP16)
+                {
+                    _service = new ChargePoint16Service();
+                }
+                else
+                {
+                    _service = new ChargePoint201Service();
+                }
+
+                if (!string.IsNullOrEmpty(request.ChargeBoxId) && request.ChargeBoxId.Length <= 25
+                   && _service.GetNumberofConnectors(request.ChargeBoxId) <= request.ConnectorId && request.ConnectorId > 0
+                    && !string.IsNullOrEmpty(request.Token) && request.Token.Length <= 20)
+                {
+
+                    InternalHttpClient _client = new InternalHttpClient();
+                    CustomerService _customer = new CustomerService();
+
+                    //trigger to charge
+                    var _request = new Models.WebAPI.StartTransactionRequest()
+                    {
+                        ConnectorId = request.ConnectorId,
+                        IdTag = request.Token
+                    };
+
+                    string[] parts = Request.RequestUri.ToString().Split('/');
+                    string urlformat = "{0}//{1}/api/v1/ocpp{2}/transaction?ChargeBoxId={3}";
+
+                    var _innerResult = await _client.Post(string.Format(urlformat, parts[0], parts[2],
+                        GetChargePointOCPPProtocol(request.ChargeBoxId) == OCPPProtocolType.OCPP16 ? "16" : "20", request.ChargeBoxId), new Dictionary<string, string>()
+                        {
+                            { "PartnerId",_CustomerId}
+
+                        }, _request, _customer.GetAPIKey(new Guid(_CustomerId)));
+
+
+                    _innerData = new { Result = string.IsNullOrEmpty(_innerResult.SerialNo) ? CommandResponseType.Rejected.ToString() : CommandResponseType.Accepted.ToString(), Timeout = 60 };
+                    result = GetErrorDescription(_innerResult);
+                    result.Data = JsonConvert.SerializeObject(_innerData, EVCBConfiguration.JSONSERIALIZER_FORMAT);
+
+                    if (_innerResult.Status == HttpStatusCode.InternalServerError)
+                    {
+
+                        result.StatusCode = _innerResult.ErrorCode;
+                        result.StatusMessage = CPO_StatusMessage.ERROR_MSG_INNERSERVICE_ERROR;
+                        statusCode = HttpStatusCode.InternalServerError;
+                    }
+                    else
+                    {
+                        result.SerialNo = _innerResult.SerialNo;
+                        result.StatusCode = _innerResult.ErrorCode;
+                        result.StatusMessage = _innerResult.Message;
+                        statusCode = HttpStatusCode.OK;
+                    }
+
+                }
+                else
+                {
+                    // 參數不符合定義
+                    result.StatusMessage = CPO_StatusMessage.ERROR_MSG_PARAMETER_OUTOFRANGE_INCORRECT;
+                    result.StatusCode = (int)CPO_StatusCode.PARAMETER_OUTOFRANGE_INCORRECT;
+                    result.Data = JsonConvert.SerializeObject(_innerData, EVCBConfiguration.JSONSERIALIZER_FORMAT);
+                    statusCode = HttpStatusCode.BadRequest;
+                }
+
+
+                return Request.CreateResponse(statusCode, result);
+            }
+            catch (Exception ex)
+            {
+                result.ErrorDetail = ex.ToString();
+                result.StatusMessage = CPO_StatusMessage.ERROR_MSG_UNEXPECTEDERROR;
+                result.StatusCode = (int)CPO_StatusCode.UnexpectedError;
+                return Request.CreateResponse(statusCode, result);
+            }
+
+
+        }
+
+
+        [Route("commands/stop_session")]
+        [ResponseType(typeof(CPOOuterResponse))]
+        [HttpPost]
+        async public Task<HttpResponseMessage> StopSession(string ChargeBoxId, int SessionId)
+        {
+            var result = new CPOOuterResponse();
+            HttpStatusCode statusCode = HttpStatusCode.InternalServerError;
+            var _innerData = new { Result = CommandResponseType.Rejected.ToString(), Timeout = 60 };
+            try
+            {
+                string _CustomerId = string.Empty;
+
+                if (!ContainsChargePoint(ChargeBoxId, out _CustomerId))
+                {
+                    // 沒槍~ 沒得充...                   
+                    result.StatusMessage = CPO_StatusMessage.ERROR_MSG_CHARGEBOXID_DOESNT_EXIST;
+                    result.StatusCode = (int)CPO_StatusCode.CHARGEBOXID_ISNT_EXIST_OR_OFFLINE;
+                    result.Data = JsonConvert.SerializeObject(_innerData, EVCBConfiguration.JSONSERIALIZER_FORMAT);
+                    statusCode = HttpStatusCode.BadRequest;
+                    return Request.CreateResponse(statusCode, result);
+                }
+
+                InternalHttpClient _client = new InternalHttpClient();
+                CustomerService _customer = new CustomerService();
+
+                string[] parts = Request.RequestUri.ToString().Split('/');
+
+                string urlformat = "{0}//{1}/api/v1/ocpp{2}/transaction?ChargeBoxId={3}&TransactionId={4}";
+
+                var _innerResult = await _client.Put(string.Format(urlformat, parts[0], parts[2], GetChargePointOCPPProtocol(ChargeBoxId) == OCPPProtocolType.OCPP16 ? "16" : "20", ChargeBoxId, SessionId), new Dictionary<string, string>()
+                        {
+                            { "PartnerId",_CustomerId}
+
+                        }, null, _customer.GetAPIKey(new Guid(_CustomerId)));
+
+
+                _innerData = new { Result = string.IsNullOrEmpty(_innerResult.SerialNo) ? CommandResponseType.Rejected.ToString() : CommandResponseType.Accepted.ToString(), Timeout = 60 };
+                result = GetErrorDescription(_innerResult);
+                result.Data = JsonConvert.SerializeObject(_innerData, EVCBConfiguration.JSONSERIALIZER_FORMAT);
+                if (_innerResult.Success)
+                {
+                    result.SerialNo = _innerResult.SerialNo;
+                    result.StatusCode = (int)CPO_StatusCode.Success;
+                    result.StatusMessage = CPO_StatusMessage.Success;
+                    statusCode = HttpStatusCode.OK;
+                }
+                else
+                {
+                    if (_innerResult.ErrorCode == (int)CPO_StatusCode.UnexpectedError)
+                    {
+                        result.StatusCode = _innerResult.ErrorCode;
+                        result.StatusMessage = CPO_StatusMessage.ERROR_MSG_INNERSERVICE_ERROR;
+                        statusCode = HttpStatusCode.BadRequest;
+                    }
+                    else
+                    {
+                        result.StatusCode = _innerResult.ErrorCode;
+                        result.StatusMessage = _innerResult.Message;
+                        statusCode = HttpStatusCode.BadRequest;
+                    }
+                }
+
+
+            }
+            catch (Exception ex)
+            {
+                result.ErrorDetail = ex.ToString();
+                result.StatusMessage = CPO_StatusMessage.ERROR_MSG_UNEXPECTEDERROR;
+                result.StatusCode = (int)CPO_StatusCode.UnexpectedError;
+                return Request.CreateResponse(statusCode, result);
+            }
+
+            return Request.CreateResponse(statusCode, result);
+        }
+
+        [Route("commands/reserve_now")]
+        [ResponseType(typeof(CPOOuterResponse))]
+        [HttpPost]
+        async public Task<HttpResponseMessage> ReserveNow([FromBody] ReserveNowRequest request)
+        {
+            var result = new CPOOuterResponse();
+            HttpStatusCode statusCode = HttpStatusCode.InternalServerError;
+            var _innerData = new { Result = CommandResponseType.Rejected.ToString(), Timeout = 60 };
+            try
+            {
+                string _CustomerId = string.Empty;
+
+                if (!ContainsChargePoint(request.ChargeBoxId, out _CustomerId))
+                {
+                    // 沒槍~ 沒得充...                   
+                    result.StatusMessage = CPO_StatusMessage.ERROR_MSG_CHARGEBOXID_DOESNT_EXIST;
+                    result.StatusCode = (int)CPO_StatusCode.CHARGEBOXID_ISNT_EXIST_OR_OFFLINE;
+                    result.Data = JsonConvert.SerializeObject(_innerData, EVCBConfiguration.JSONSERIALIZER_FORMAT);
+                    statusCode = HttpStatusCode.BadRequest;
+                    return Request.CreateResponse(statusCode, result);
+                }
+
+
+                InternalHttpClient _client = new InternalHttpClient();
+                CustomerService _customer = new CustomerService();
+
+                string[] parts = Request.RequestUri.ToString().Split('/');
+                string urlformat = "{0}//{1}/api/v1/ocpp{2}/reservation?ChargeBoxId={3}";
+
+                var _innerRequest = new ReserveRequest()
+                {
+                    ConnectorId = request.ConnectorId,
+                    IdTag = request.Token,
+                    ReservationId = request.ReservationId,
+                    ExpiryDate = request.ExpiryDate.ToString(EVCBConfiguration.UTC_DATETIMEFORMAT)
+                };
+
+                var _innerResult = await _client.Post(string.Format(urlformat, parts[0], parts[2],
+                    GetChargePointOCPPProtocol(request.ChargeBoxId) == OCPPProtocolType.OCPP16 ? "16" : "20", request.ChargeBoxId), new Dictionary<string, string>()
+                        {
+                            { "PartnerId",_CustomerId}
+
+                        }, _innerRequest, _customer.GetAPIKey(new Guid(_CustomerId)));
+
+
+                _innerData = new { Result = string.IsNullOrEmpty(_innerResult.SerialNo) ? CommandResponseType.Rejected.ToString() : CommandResponseType.Accepted.ToString(), Timeout = 60 };
+                result = GetErrorDescription(_innerResult);
+                result.Data = JsonConvert.SerializeObject(_innerData, EVCBConfiguration.JSONSERIALIZER_FORMAT);
+                if (_innerResult.Success)
+                {
+                    result.SerialNo = _innerResult.SerialNo;
+                    result.StatusCode = (int)CPO_StatusCode.Success;
+                    result.StatusMessage = CPO_StatusMessage.Success;
+                    statusCode = HttpStatusCode.OK;
+                }
+                else
+                {
+
+                    if (_innerResult.ErrorCode == (int)CPO_StatusCode.UnexpectedError)
+                    {
+                        result.StatusCode = _innerResult.ErrorCode;
+                        result.StatusMessage = CPO_StatusMessage.ERROR_MSG_INNERSERVICE_ERROR;
+                        statusCode = HttpStatusCode.BadRequest;
+                    }
+                    else
+                    {
+                        result.StatusCode = _innerResult.ErrorCode;
+                        result.StatusMessage = _innerResult.Message;
+                        statusCode = HttpStatusCode.BadRequest;
+                    }
+                }
+            }
+            catch (Exception ex)
+            {
+                result.ErrorDetail = ex.ToString();
+                result.StatusMessage = CPO_StatusMessage.ERROR_MSG_UNEXPECTEDERROR;
+                result.StatusCode = (int)CPO_StatusCode.UnexpectedError;
+                return Request.CreateResponse(statusCode, result);
+            }
+
+            return Request.CreateResponse(statusCode, result);
+        }
+
+        [Route("commands/cancel_reservation")]
+        [ResponseType(typeof(CPOOuterResponse))]
+        [HttpDelete]
+        async public Task<HttpResponseMessage> CancelReservation(string ChargeBoxId, int ReservationId)
+        {
+            var result = new CPOOuterResponse();
+            HttpStatusCode statusCode = HttpStatusCode.InternalServerError;
+            var _innerData = new { Result = CommandResponseType.Rejected.ToString(), Timeout = 60 };
+            try
+            {
+                string _CustomerId = string.Empty;
+
+                if (!ContainsChargePoint(ChargeBoxId, out _CustomerId))
+                {
+                    // 沒槍~ 沒得充...                   
+                    result.StatusMessage = CPO_StatusMessage.ERROR_MSG_CHARGEBOXID_DOESNT_EXIST;
+                    result.StatusCode = (int)CPO_StatusCode.CHARGEBOXID_ISNT_EXIST_OR_OFFLINE;
+                    result.Data = JsonConvert.SerializeObject(_innerData, EVCBConfiguration.JSONSERIALIZER_FORMAT);
+                    statusCode = HttpStatusCode.BadRequest;
+                    return Request.CreateResponse(statusCode, result);
+                }
+
+
+                InternalHttpClient _client = new InternalHttpClient();
+                CustomerService _customer = new CustomerService();
+
+
+                string[] parts = Request.RequestUri.ToString().Split('/');
+
+                string urlformat = "{0}//{1}/api/v1/ocpp{2}/reservation?ChargeBoxId={3}&ReservationId={4}";
+
+                var _innerResult = await _client.Delete(string.Format(urlformat, parts[0], parts[2],
+                    GetChargePointOCPPProtocol(ChargeBoxId) == OCPPProtocolType.OCPP16 ? "16" : "20", ChargeBoxId, ReservationId), new Dictionary<string, string>()
+                        {
+                            { "PartnerId",_CustomerId}
+
+                        }, _customer.GetAPIKey(new Guid(_CustomerId)));
+
+
+                _innerData = new { Result = string.IsNullOrEmpty(_innerResult.SerialNo) ? CommandResponseType.Rejected.ToString() : CommandResponseType.Accepted.ToString(), Timeout = 60 };
+                result = GetErrorDescription(_innerResult);
+                result.Data = JsonConvert.SerializeObject(_innerData, EVCBConfiguration.JSONSERIALIZER_FORMAT);
+                if (_innerResult.Success)
+                {
+                    result.SerialNo = _innerResult.SerialNo;
+                    result.StatusCode = (int)CPO_StatusCode.Success;
+                    result.StatusMessage = CPO_StatusMessage.Success;
+                    statusCode = HttpStatusCode.OK;
+                }
+                else
+                {
+
+                    if (_innerResult.ErrorCode == (int)CPO_StatusCode.UnexpectedError)
+                    {
+                        result.StatusCode = _innerResult.ErrorCode;
+                        result.StatusMessage = CPO_StatusMessage.ERROR_MSG_INNERSERVICE_ERROR;
+                        statusCode = HttpStatusCode.BadRequest;
+                    }
+                    else
+                    {
+                        result.StatusCode = _innerResult.ErrorCode;
+                        result.StatusMessage = _innerResult.Message;
+                        statusCode = HttpStatusCode.BadRequest;
+                    }
+                }
+            }
+            catch (Exception ex)
+            {
+                result.ErrorDetail = ex.ToString();
+                result.StatusMessage = CPO_StatusMessage.ERROR_MSG_UNEXPECTEDERROR;
+                result.StatusCode = (int)CPO_StatusCode.UnexpectedError;
+                return Request.CreateResponse(statusCode, result);
+            }
+
+            return Request.CreateResponse(statusCode, result);
+        }
+
+        [Route("commands/set_locallist")]
+        [ResponseType(typeof(CPOOuterResponse))]
+        [HttpPost]
+        async public Task<HttpResponseMessage> SendLocalList(string ChargeBoxId, [FromBody] LocalListRequest request)
+        {
+            var result = new CPOOuterResponse();
+            HttpStatusCode statusCode = HttpStatusCode.InternalServerError;
+            var _innerData = new { Result = CommandResponseType.Rejected.ToString(), Timeout = 60 };
+            try
+            {
+                string _CustomerId = string.Empty;
+
+                if (!ContainsChargePoint(ChargeBoxId, out _CustomerId))
+                {
+                    // 沒槍~ 沒得充...                   
+                    result.StatusMessage = CPO_StatusMessage.ERROR_MSG_CHARGEBOXID_DOESNT_EXIST;
+                    result.StatusCode = (int)CPO_StatusCode.CHARGEBOXID_ISNT_EXIST_OR_OFFLINE;
+                    result.Data = JsonConvert.SerializeObject(_innerData, EVCBConfiguration.JSONSERIALIZER_FORMAT);
+                    statusCode = HttpStatusCode.BadRequest;
+                    return Request.CreateResponse(statusCode, result);
+                }
+
+
+                InternalHttpClient _client = new InternalHttpClient();
+                CustomerService _customer = new CustomerService();
+
+
+
+                string[] parts = Request.RequestUri.ToString().Split('/');
+
+                string urlformat = "{0}//{1}/api/v1/ocpp{2}/locallist?ChargeBoxId={3}";
+
+
+                var _innerResult = await _client.Post(string.Format(urlformat, parts[0], parts[2],
+                    GetChargePointOCPPProtocol(ChargeBoxId) == OCPPProtocolType.OCPP16 ? "16" : "20", ChargeBoxId), new Dictionary<string, string>()
+                        {
+                            { "PartnerId",_CustomerId}
+
+                        }, request, _customer.GetAPIKey(new Guid(_CustomerId)));
+
+
+                _innerData = new { Result = string.IsNullOrEmpty(_innerResult.SerialNo) ? CommandResponseType.Rejected.ToString() : CommandResponseType.Accepted.ToString(), Timeout = 60 };
+                result = GetErrorDescription(_innerResult);
+                result.Data = JsonConvert.SerializeObject(_innerData, EVCBConfiguration.JSONSERIALIZER_FORMAT);
+                if (_innerResult.Success)
+                {
+                    result.SerialNo = _innerResult.SerialNo;
+                    result.StatusCode = (int)CPO_StatusCode.Success;
+                    result.StatusMessage = CPO_StatusMessage.Success;
+                    statusCode = HttpStatusCode.OK;
+                }
+                else
+                {
+
+                    if (_innerResult.ErrorCode == (int)CPO_StatusCode.UnexpectedError)
+                    {
+                        result.StatusCode = _innerResult.ErrorCode;
+                        result.StatusMessage = CPO_StatusMessage.ERROR_MSG_INNERSERVICE_ERROR;
+                        statusCode = HttpStatusCode.BadRequest;
+                    }
+                    else
+                    {
+                        result.StatusCode = _innerResult.ErrorCode;
+                        result.StatusMessage = _innerResult.Message;
+                        statusCode = HttpStatusCode.BadRequest;
+                    }
+                }
+            }
+            catch (Exception ex)
+            {
+                result.ErrorDetail = ex.ToString();
+                result.StatusMessage = CPO_StatusMessage.ERROR_MSG_UNEXPECTEDERROR;
+                result.StatusCode = (int)CPO_StatusCode.UnexpectedError;
+                return Request.CreateResponse(statusCode, result);
+            }
+
+            return Request.CreateResponse(statusCode, result);
+        }
+
+        [Route("commands/locallistversion")]
+        [ResponseType(typeof(CPOOuterResponse))]
+        [HttpGet]
+        async public Task<HttpResponseMessage> GetLocalListVersion(string ChargeBoxId)
+        {
+            var result = new CPOOuterResponse();
+            HttpStatusCode statusCode = HttpStatusCode.InternalServerError;
+            var _innerData = new { Result = CommandResponseType.Rejected.ToString(), Timeout = 60 };
+            try
+            {
+                string _CustomerId = string.Empty;
+
+                if (!ContainsChargePoint(ChargeBoxId, out _CustomerId))
+                {
+                    // 沒槍~ 沒得充...                   
+                    result.StatusMessage = CPO_StatusMessage.ERROR_MSG_CHARGEBOXID_DOESNT_EXIST;
+                    result.StatusCode = (int)CPO_StatusCode.CHARGEBOXID_ISNT_EXIST_OR_OFFLINE;
+                    result.Data = JsonConvert.SerializeObject(_innerData, EVCBConfiguration.JSONSERIALIZER_FORMAT);
+                    statusCode = HttpStatusCode.BadRequest;
+                    return Request.CreateResponse(statusCode, result);
+                }
+
+
+                InternalHttpClient _client = new InternalHttpClient();
+                CustomerService _customer = new CustomerService();
+
+
+
+                string[] parts = Request.RequestUri.ToString().Split('/');
+
+                string urlformat = "{0}//{1}/api/v1/ocpp{2}/locallistversion?ChargeBoxId={3}";
+
+                var _innerResult = await _client.Get(string.Format(urlformat, parts[0], parts[2], GetChargePointOCPPProtocol(ChargeBoxId) == OCPPProtocolType.OCPP16 ? "16" : "20",
+                    ChargeBoxId), new Dictionary<string, string>()
+                        {
+                            { "PartnerId",_CustomerId}
+
+                        }, _customer.GetAPIKey(new Guid(_CustomerId)));
+
+
+                _innerData = new { Result = string.IsNullOrEmpty(_innerResult.SerialNo) ? CommandResponseType.Rejected.ToString() : CommandResponseType.Accepted.ToString(), Timeout = 60 };
+                result = GetErrorDescription(_innerResult);
+                result.Data = JsonConvert.SerializeObject(_innerData, EVCBConfiguration.JSONSERIALIZER_FORMAT);
+                if (_innerResult.Success)
+                {
+                    result.SerialNo = _innerResult.SerialNo;
+                    result.StatusCode = (int)CPO_StatusCode.Success;
+                    result.StatusMessage = CPO_StatusMessage.Success;
+                    statusCode = HttpStatusCode.OK;
+                }
+                else
+                {
+
+                    if (_innerResult.ErrorCode == (int)CPO_StatusCode.UnexpectedError)
+                    {
+                        result.StatusCode = _innerResult.ErrorCode;
+                        result.StatusMessage = CPO_StatusMessage.ERROR_MSG_INNERSERVICE_ERROR;
+                        statusCode = HttpStatusCode.BadRequest;
+                    }
+                    else
+                    {
+                        result.StatusCode = _innerResult.ErrorCode;
+                        result.StatusMessage = _innerResult.Message;
+                        statusCode = HttpStatusCode.BadRequest;
+                    }
+                }
+
+                statusCode = HttpStatusCode.OK;
+            }
+            catch (Exception ex)
+            {
+                result.ErrorDetail = ex.ToString();
+                result.StatusMessage = CPO_StatusMessage.ERROR_MSG_UNEXPECTEDERROR;
+                result.StatusCode = (int)CPO_StatusCode.UnexpectedError;
+                return Request.CreateResponse(statusCode, result);
+            }
+
+            return Request.CreateResponse(statusCode, result);
+        }
+
+        [Route("commands/results")]
+        [ResponseType(typeof(CPOOuterResponse))]
+        [HttpGet]
+        async public Task<HttpResponseMessage> ExecutionofCmdSearch(string ChargeBoxId, CommandType? commandType, string SerialNo)
+        {
+            var result = new CPOOuterResponse();
+            HttpStatusCode statusCode = HttpStatusCode.InternalServerError;
+
+            try
+            {
+                string _CustomerId = string.Empty;
+
+                if (!ContainsChargePoint(ChargeBoxId, out _CustomerId))
+                {
+                    // 沒槍~ 沒得充...                   
+                    result.StatusMessage = CPO_StatusMessage.ERROR_MSG_CHARGEBOXID_DOESNT_EXIST;
+                    result.StatusCode = (int)CPO_StatusCode.CHARGEBOXID_ISNT_EXIST_OR_OFFLINE;
+                    statusCode = HttpStatusCode.BadRequest;
+                    return Request.CreateResponse(statusCode, result);
+                }
+
+                InternalHttpClient _client = new InternalHttpClient();
+                CustomerService _customer = new CustomerService();
+
+                int? orderNo = (int?)null;
+
+                switch (commandType.Value)
+                {
+                    case CommandType.CancelReservation:
+                        {
+                            orderNo = 4;
+                        }
+                        break;
+                    case CommandType.ClearChargingProfile:
+                        {
+                            orderNo = 6;
+                        }
+                        break;
+                    case CommandType.GetAcitveChargingProfile:
+                        {
+                            orderNo = 7;
+                        }
+                        break;
+                    case CommandType.GetLocalListVersion:
+                        {
+                            orderNo = 9;
+                        }
+                        break;
+                    case CommandType.Start_Session:
+                        {
+                            orderNo = 10;
+                        }
+                        break;
+                    case CommandType.Stop_Session:
+                        {
+                            orderNo = 11;
+                        }
+                        break;
+                    case CommandType.Reserve_Now:
+                        {
+                            orderNo = 12;
+                        }
+                        break;
+                    case CommandType.SetLocalList:
+                        {
+                            orderNo = 14;
+                        }
+                        break;
+                    case CommandType.SetChargingProfile:
+                        {
+                            orderNo = 15;
+                        }
+                        break;
+                    default:
+                        {
+                            orderNo = 18;
+                        }
+                        break;
+                }
+
+                string[] parts = Request.RequestUri.ToString().Split('/');
+
+                string urlformat = "{0}//{1}/api/v1/ocpp{2}/command?ChargeBoxId={3}{4}&SerialNo={5}";
+
+
+                var _innerResult = await _client.Get(string.Format(urlformat, parts[0], parts[2], GetChargePointOCPPProtocol(ChargeBoxId) == OCPPProtocolType.OCPP16 ? "16" : "20",
+                    ChargeBoxId, orderNo.HasValue ? "&OrderNo=" + orderNo.Value : "", SerialNo), new Dictionary<string, string>()
+                        {
+                            { "PartnerId",_CustomerId}
+
+                        }, _customer.GetAPIKey(new Guid(_CustomerId)));
+
+
+                result = GetErrorDescription(_innerResult);
+
+                if (_innerResult.Success)
+                {
+                    ComandExecution _execution = JsonConvert.DeserializeObject<ComandExecution>(_innerResult.Message);
+
+                    CommandResultType? _cmdResult = (CommandResultType?)null;
+
+                    switch (_execution.Code)
+                    {
+                        case 1:
+                            {
+                                _cmdResult = CommandResultType.Accepted;
+                            }
+                            break;
+                        case 9:
+                            {
+                                _cmdResult = CommandResultType.Notsupported;
+                            }
+                            break;
+                        case 10:
+                            {
+                                _cmdResult = CommandResultType.Unknown;
+                            }
+                            break;
+                        case 26:
+                            {
+                                _cmdResult = CommandResultType.Occupied;
+                            }
+                            break;
+                        case 31:
+                            {
+                                _cmdResult = CommandResultType.Rejected;
+                            }
+                            break;
+                        case 32:
+                            {
+                                _cmdResult = CommandResultType.Failed;
+                            }
+                            break;
+                        case 254:
+                            {
+                                _cmdResult = CommandResultType.EVSE_ERROR;
+                            }
+                            break;
+                        default:
+                            {
+                                if (_execution.Detail == "Timeout") _cmdResult = CommandResultType.Timeout;
+                                if (_execution.Detail == "Waited") _cmdResult = CommandResultType.Waited;
+
+                            }
+                            break;
+
+
+                    }
+
+
+                    if (!_cmdResult.HasValue)
+                    {
+                        result.StatusCode = (int)CPO_StatusCode.CANT_FOUND_DATA;
+                        result.StatusMessage = CPO_StatusMessage.ERROR_MSG_CANT_FIND_RESULT;
+                        statusCode = HttpStatusCode.NotFound;
+                    }
+                    else
+                    {
+                        var _innerData = new { Result = _cmdResult.Value.ToString(), Message = _execution.Detail };
+                        result.Data = JsonConvert.SerializeObject(_innerData, EVCBConfiguration.JSONSERIALIZER_FORMAT);
+                        result.SerialNo = _innerResult.SerialNo;
+                        result.StatusCode = (int)CPO_StatusCode.Success;
+                        result.StatusMessage = CPO_StatusMessage.Success;
+                        statusCode = HttpStatusCode.OK;
+                    }
+
+                }
+
+
+            }
+            catch (Exception ex)
+            {
+                result.ErrorDetail = ex.ToString();
+                result.StatusMessage = CPO_StatusMessage.ERROR_MSG_UNEXPECTEDERROR;
+                result.StatusCode = (int)CPO_StatusCode.UnexpectedError;
+                return Request.CreateResponse(statusCode, result);
+            }
+
+            return Request.CreateResponse(statusCode, result);
+        }
+
+        [Route("activesession")]
+        [ResponseType(typeof(CPOOuterResponse))]
+        [HttpGet]
+        public HttpResponseMessage ActiveSession(string ChargeBoxId, string SessionId = "", string IdTag = "")
+        {
+            var result = new CPOOuterResponse();
+            HttpStatusCode statusCode = HttpStatusCode.InternalServerError;
+
+            try
+            {
+                string _CustomerId = string.Empty;
+
+                if (!ContainsChargePoint(ChargeBoxId, out _CustomerId))
+                {
+                    // 沒槍~ 沒得充...                   
+                    result.StatusMessage = CPO_StatusMessage.ERROR_MSG_CHARGEBOXID_DOESNT_EXIST;
+                    result.StatusCode = (int)CPO_StatusCode.CHARGEBOXID_ISNT_EXIST_OR_OFFLINE;
+                    statusCode = HttpStatusCode.BadRequest;
+                    return Request.CreateResponse(statusCode, result);
+                }
+
+                // query meter value
+                IChargePointService _service = null;
+                if (GetChargePointOCPPProtocol(ChargeBoxId) == OCPPProtocolType.OCPP16)
+                {
+                    _service = new ChargePoint16Service();
+                }
+                else
+                {
+                    _service = new ChargePoint201Service();
+                }
+                var transactionDatas = _service.GetActiveSessionInfo(ChargeBoxId, new List<Measurand>()
+                {  Measurand.Voltage,
+                   Measurand.Current_Import,
+                   Measurand.SoC,
+                   Measurand.Power_Active_Import,
+                   Measurand.Energy_Active_Import_Interval,
+                   Measurand.ChargingCost
+                }, SessionId, IdTag);
+
+                if (transactionDatas == null)
+                {
+                    result.StatusCode = (int)CPO_StatusCode.CANT_FOUND_DATA;
+                    result.StatusMessage = CPO_StatusMessage.ERROR_MSG_CANT_FIND_RESULT;
+                    statusCode = HttpStatusCode.NotFound;
+                }
+                else
+                {
+                    List<ActiveSession> _innerData = new List<ActiveSession>();
+
+                    foreach (var transactionData in transactionDatas)
+                    {
+                        string currencyText = transactionData.Fee.Split('|')[1];
+
+                        _innerData.Add(new ActiveSession()
+                        {
+
+                            ChargeBoxId = ChargeBoxId,
+                            SessionId = transactionData.Id,
+                            ElaspedTime = (int)DateTime.UtcNow.Subtract(transactionData.StartTime).TotalMinutes,
+                            ConnectorId = transactionData.ConnectorId,
+                            IdTag = transactionData.StartIdTag,
+                            Power = transactionData.MeterValues == null ? "0" : transactionData.MeterValues.Where(x => x.Measurand == Packet.Messages.SubTypes.Measurand.Power_Active_Import).Select(x => x.Value).FirstOrDefault(),
+                            Power_Format = transactionData.MeterValues == null ? UnitOfMeasure.W.ToString() : transactionData.MeterValues.Where(x => x.Measurand == Packet.Messages.SubTypes.Measurand.Power_Active_Import).Select(x => x.Unit.ToString()).FirstOrDefault(),
+                            Current = transactionData.MeterValues == null ? "0" : transactionData.MeterValues.Where(x => x.Measurand == Packet.Messages.SubTypes.Measurand.Current_Import).Select(x => x.Value).FirstOrDefault(),
+                            Current_Format = transactionData.MeterValues == null ? UnitOfMeasure.A.ToString() : transactionData.MeterValues.Where(x => x.Measurand == Packet.Messages.SubTypes.Measurand.Current_Import).Select(x => x.Unit.ToString()).FirstOrDefault(),
+                            Energy = transactionData.MeterValues == null ? "0" : transactionData.MeterValues.Where(x => x.Measurand == Packet.Messages.SubTypes.Measurand.Energy_Active_Import_Interval).Select(x => x.Value).FirstOrDefault(),
+                            Energy_Format = transactionData.MeterValues == null ? UnitOfMeasure.Wh.ToString() : transactionData.MeterValues.Where(x => x.Measurand == Packet.Messages.SubTypes.Measurand.Energy_Active_Import_Interval).Select(x => x.Unit.ToString()).FirstOrDefault(),
+                            Voltage = transactionData.MeterValues == null ? "0" : transactionData.MeterValues.Where(x => x.Measurand == Packet.Messages.SubTypes.Measurand.Voltage).Select(x => x.Value).FirstOrDefault(),
+                            Voltage_Format = transactionData.MeterValues == null ? UnitOfMeasure.V.ToString() : transactionData.MeterValues.Where(x => x.Measurand == Packet.Messages.SubTypes.Measurand.Voltage).Select(x => x.Unit.ToString()).FirstOrDefault(),
+                            SOC = transactionData.MeterValues == null ? "0" : transactionData.MeterValues.Where(x => x.Measurand == Packet.Messages.SubTypes.Measurand.SoC).Select(x => x.Unit.ToString()).FirstOrDefault() == null ? null : transactionData.MeterValues.Where(x => x.Measurand == Packet.Messages.SubTypes.Measurand.SoC).Select(x => x.Value).FirstOrDefault(),
+                            SOC_Format = transactionData.MeterValues == null ? UnitOfMeasure.Percent.ToString() : transactionData.MeterValues.Where(x => x.Measurand == Packet.Messages.SubTypes.Measurand.SoC).Select(x => x.Unit.ToString()).FirstOrDefault(),
+                            CurrentCost = transactionData.MeterValues == null ? "0" : transactionData.MeterValues.Where(x => x.Measurand == Packet.Messages.SubTypes.Measurand.ChargingCost).Select(x => x.Value).FirstOrDefault(),
+                            Currency = currencyText
+                        });
+                        decimal energy = decimal.Parse(_innerData[_innerData.Count - 1].Energy);
+                        energy = _innerData[_innerData.Count - 1].Energy_Format == UnitOfMeasure.Wh.ToString() ? Decimal.Divide(energy, 1000) : energy;
+
+
+
+                    }
+                    result.Data = JsonConvert.SerializeObject(_innerData, EVCBConfiguration.JSONSERIALIZER_FORMAT);
+                    result.StatusCode = (int)CPO_StatusCode.Success;
+                    result.StatusMessage = CPO_StatusMessage.Success;
+                    statusCode = HttpStatusCode.OK;
+
+                }
+
+                return Request.CreateResponse(statusCode, result);
+            }
+            catch (Exception ex)
+            {
+                result.ErrorDetail = ex.ToString();
+                result.StatusMessage = CPO_StatusMessage.ERROR_MSG_UNEXPECTEDERROR;
+                result.StatusCode = (int)CPO_StatusCode.UnexpectedError;
+                return Request.CreateResponse(statusCode, result);
+            }
+
+        }
+
+        [Route("completedsession")]
+        [ResponseType(typeof(CPOOuterResponse))]
+        [HttpGet]
+        public HttpResponseMessage CompletedSession(string ChargeBoxId, string SessionId = "", string IdTag = "", string StartTime = "", string StopTime = "")
+        {
+            var result = new CPOOuterResponse();
+            HttpStatusCode statusCode = HttpStatusCode.InternalServerError;
+
+            try
+            {
+                string _CustomerId = string.Empty;
+
+                if (!ContainsChargePoint(ChargeBoxId, out _CustomerId))
+                {
+                    // 沒槍~ 沒得充...                   
+                    result.StatusMessage = CPO_StatusMessage.ERROR_MSG_CHARGEBOXID_DOESNT_EXIST;
+                    result.StatusCode = (int)CPO_StatusCode.CHARGEBOXID_ISNT_EXIST_OR_OFFLINE;
+                    statusCode = HttpStatusCode.BadRequest;
+                    return Request.CreateResponse(statusCode, result);
+                }
+
+                DateTime startDt = string.IsNullOrEmpty(StartTime) ? new DateTime(1991, 1, 1) : DateTime.Parse(StartTime);
+                DateTime stopDt = string.IsNullOrEmpty(StopTime) ? new DateTime(1991, 1, 1) : DateTime.Parse(StopTime);
+                // query meter value
+                IChargePointService _service = null;
+                if (GetChargePointOCPPProtocol(ChargeBoxId) == OCPPProtocolType.OCPP16)
+                {
+                    _service = new ChargePoint16Service();
+                }
+                else
+                {
+                    _service = new ChargePoint201Service();
+                }
+                var _innerData = _service.GetSessionDetail(ChargeBoxId, SessionId, IdTag, startDt, stopDt);
+
+                if (_innerData == null)
+                {
+                    result.StatusCode = (int)CPO_StatusCode.CANT_FOUND_DATA;
+                    result.StatusMessage = CPO_StatusMessage.ERROR_MSG_CANT_FIND_SESSIONDETAIL;
+                    statusCode = HttpStatusCode.NotFound;
+                    return Request.CreateResponse(statusCode, result);
+                }
+
+                result.Data = JsonConvert.SerializeObject(_innerData, EVCBConfiguration.JSONSERIALIZER_FORMAT);
+                result.StatusCode = (int)CPO_StatusCode.Success;
+                result.StatusMessage = CPO_StatusMessage.Success;
+                statusCode = HttpStatusCode.OK;
+                return Request.CreateResponse(statusCode, result);
+            }
+            catch (Exception ex)
+            {
+                result.ErrorDetail = ex.ToString();
+                result.StatusMessage = CPO_StatusMessage.ERROR_MSG_UNEXPECTEDERROR;
+                result.StatusCode = (int)CPO_StatusCode.UnexpectedError;
+                return Request.CreateResponse(statusCode, result);
+            }
+
+        }
+
+
+
+        #region private method
+
+        private bool ContainsChargePoint(string chargeBoxId, out string customerId)
+        {
+            customerId = string.Empty;
+
+            if (!Request.Headers.Contains(EVCBConfiguration.Header_PartnerId)) return false;
+
+            customerId = Request.Headers.GetValues(EVCBConfiguration.Header_PartnerId).First();
+
+            ChargePoint201Service _service201 = new ChargePoint201Service();
+            ChargePoint16Service _service16 = new ChargePoint16Service();
+
+
+            return _service16.ContainsChargePoint(chargeBoxId, customerId) ? true : _service201.ContainsChargePoint(chargeBoxId, customerId) ? true : false;
+
+        }
+
+
+        private OCPPProtocolType GetChargePointOCPPProtocol(string chargeBoxId)
+        {
+            ChargePoint201Service _service201 = new ChargePoint201Service();
+            ChargePoint16Service _service16 = new ChargePoint16Service();
+
+            return _service201.GetMachineUpdatedOn(chargeBoxId) > _service16.GetMachineUpdatedOn(chargeBoxId)
+                ? OCPPProtocolType.OCPP201 : OCPPProtocolType.OCPP16;
+
+        }
+
+        private CPOOuterResponse GetErrorDescription(InternalHttpResult innerResponse)
+        {
+            CPOOuterResponse result = new CPOOuterResponse();
+
+            result.ErrorDetail = innerResponse.Exception == null ? null : innerResponse.Exception.ToString();
+
+            if (innerResponse.Status != HttpStatusCode.Accepted)
+            {
+                switch (innerResponse.ErrorCode)
+                {
+                    #region Authorization
+                    case 2000:
+                        {
+                            result.StatusCode = innerResponse.ErrorCode;
+                            result.StatusMessage = string.Format("{0}-{1}", "InnerService", "Authorize Unexpected Error");
+                            result.ErrorDetail = result.StatusMessage;
+                        }
+                        break;
+                    case 2001:
+                    case 2002:
+                    case 2003:
+                        {
+                            result.StatusCode = innerResponse.ErrorCode;
+                            result.StatusMessage = string.Format("{0}-{1}", "InnerService", innerResponse.Message);
+                        }
+                        break;
+
+                    #endregion
+                    case 2100:
+                    case 2101:
+                    case 2102:
+                    case 2103:
+                    case 2104:
+                    case 2105:
+                    case 2106:
+                        {
+                            result.StatusCode = innerResponse.ErrorCode;
+                            result.StatusMessage = innerResponse.Message;
+                        }
+                        break;
+                    case 2999:
+                        {
+                            result.StatusCode = innerResponse.ErrorCode;
+                            result.StatusMessage = string.Format("{0}-{1}", "InnerService", "Unexpected Error");
+                            result.ErrorDetail = result.StatusMessage;
+                        }
+                        break;
+                    default:
+                        {
+                            result.StatusCode = 2998;
+                            result.StatusMessage = CPO_StatusMessage.ERROR_MSG_CANT_FIND_ERRORCODE;
+                        }
+                        break;
+                }
+            }
+
+            return result;
+
+
+        }
+
+
+        #endregion
+    }
+}

+ 1791 - 0
EVCB_OCPP.WEBAPI/Controllers/Version2/ocpp16/OCPP16_CPOController.cs

@@ -0,0 +1,1791 @@
+using EVCB_OCPP.WEBAPI.Handlers;
+using EVCB_OCPP.WEBAPI.Models.WebAPI;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Net;
+using System.Net.Http;
+using System.Web.Http;
+using System.Web.Http.Description;
+using Newtonsoft.Json;
+using System.Threading.Tasks;
+using EVCB_OCPP.WEBAPI.Models.WebAPI.Dto;
+using System.Net.Http.Headers;
+using EVCB_OCPP.Packet.Messages.SubTypes;
+using System.Security.Cryptography.X509Certificates;
+using OCPPPackage.Profiles;
+using EVCB_OCPP.Packet.Messages.Core;
+using EVCB_OCPP.Packet.Messages;
+using EVCB_OCPP.WEBAPI.Services.Integration;
+using EVCB_OCPP.WEBAPI.Services;
+using ChargingStationService = EVCB_OCPP.WEBAPI.Services.Integration.ChargingStationService;
+using ServerTriggerService = EVCB_OCPP.WEBAPI.Services.Integration.ServerTriggerService;
+
+namespace EVCB_OCPP.WEBAPI.Controllers.Version2.ocpp16
+{
+    [ApiExplorerSettings(IgnoreApi = false)]
+    [RoutePrefix("api/v2/cpo16")]
+    [CPOAuthentication]
+    public class OCPP16_CPOController : ApiController
+    {
+        private HttpClientService service = new HttpClientService();
+
+        private bool ContainsChargePoint(string chargeBoxId, out string customerId)
+        {
+
+            customerId = string.Empty;
+
+            if (!Request.Headers.Contains(EVCBConfiguration.Header_PartnerId)) return false;
+
+            customerId = Request.Headers.GetValues(EVCBConfiguration.Header_PartnerId).First();
+
+            ChargePoint16Service _service = new ChargePoint16Service();
+            return _service.ContainsChargePoint(chargeBoxId, customerId);
+
+        }
+
+
+
+        [Route("station")]
+        [ResponseType(typeof(CPOOuterResponse))]
+        [HttpGet]
+        public HttpResponseMessage Station()
+        {
+            var result = new CPOOuterResponse();
+            HttpStatusCode statusCode = HttpStatusCode.InternalServerError;
+            try
+            {
+                if (Request.Headers.Contains(EVCBConfiguration.Header_PartnerId))
+                {
+                    var _customerId = Request.Headers.GetValues(EVCBConfiguration.Header_PartnerId).First();
+                    ChargingStationService _service = new ChargingStationService();
+                    var _innerResponse = new { Stations = _service.GetStationsbyCustomerId(_customerId) };
+                    result.Data = JsonConvert.SerializeObject(_innerResponse, EVCBConfiguration.JSONSERIALIZER_FORMAT);
+                    result.StatusCode = (int)CPO_StatusCode.Success;
+                    result.StatusMessage = CPO_StatusMessage.Success;
+                    statusCode = HttpStatusCode.OK;
+                }
+                return Request.CreateResponse(statusCode, result);
+            }
+            catch (Exception ex)
+            {
+                result.ErrorDetail = ex.ToString();
+                result.StatusMessage = CPO_StatusMessage.ERROR_MSG_UNEXPECTEDERROR;
+                result.StatusCode = (int)CPO_StatusCode.UnexpectedError;
+                return Request.CreateResponse(statusCode, result);
+            }
+
+
+        }
+
+        [Route("information")]
+        [ResponseType(typeof(CPOOuterResponse))]
+        [HttpGet]
+        public HttpResponseMessage BasicInformationofEVSEs(int? Limit=-1, int StationId = -1, string ChargeBoxId = "", DateTime? DateFrom = null, DateTime? DateTo = null, int? Offset = 0)
+        {
+
+            var result = new CPOOuterResponse();
+            HttpStatusCode statusCode = HttpStatusCode.InternalServerError;
+            try
+            {
+                ChargePoint16Service _CPService = new ChargePoint16Service();
+                var tt = _CPService.GetLastUpdatedTimebyMachineId("0da4f4a6-a952-46f0-b2f3-696385a9a56a");
+                if (Request.Headers.Contains(EVCBConfiguration.Header_PartnerId))
+                {
+                    var _customerId = Request.Headers.GetValues(EVCBConfiguration.Header_PartnerId).First();
+
+                    var _innerResponse = new { EVSEs = new List<EVSE>() };
+                    ChargingStationService _stationService = new ChargingStationService();
+
+                    if (StationId > -1)
+                    {
+                        if (_stationService.ContainsStation(_customerId, StationId))
+                        {
+                            if (DateTo.HasValue)
+                            {
+                                if (!DateFrom.HasValue)
+                                {
+
+                                    result.StatusMessage = CPO_StatusMessage.ERROR_MSG_PARAMETER_OUTOFRANGE_INCORRECT;
+                                    result.StatusCode = (int)CPO_StatusCode.PARAMETER_OUTOFRANGE_INCORRECT;
+                                    statusCode = HttpStatusCode.BadRequest;
+                                    return Request.CreateResponse(statusCode, result);
+                                }
+                            }
+                            _innerResponse = new { EVSEs = _stationService.GetEVSEsbyStationId(StationId, DateFrom, DateTo, Offset.Value, Limit==-1? 1000: Limit.Value) };
+
+
+                        }
+                    }
+                    else
+                    {
+                        _innerResponse = new { EVSEs = new List<EVSE>() };
+                        _innerResponse.EVSEs.Add(_CPService.GetEVSEsbyChargeBoxId(ChargeBoxId, DateFrom, DateTo));
+
+
+                    }
+
+                    result.Data = JsonConvert.SerializeObject(_innerResponse, EVCBConfiguration.JSONSERIALIZER_FORMAT);
+                    result.StatusCode = (int)CPO_StatusCode.Success;
+                    result.StatusMessage = CPO_StatusMessage.Success;
+                    statusCode = HttpStatusCode.OK;
+
+                }
+                return Request.CreateResponse(statusCode, result);
+            }
+            catch (Exception ex)
+            {
+                result.ErrorDetail = ex.ToString();
+                result.StatusMessage = CPO_StatusMessage.ERROR_MSG_UNEXPECTEDERROR;
+                result.StatusCode = (int)CPO_StatusCode.UnexpectedError;
+                return Request.CreateResponse(statusCode, result);
+            }
+
+
+        }
+
+
+
+        [Route("commands/start_session")]
+        [ResponseType(typeof(CPOOuterResponse))]
+        [HttpPost]
+        async public Task<HttpResponseMessage> StartSession([FromBody] StartSessionRequest request)
+        {
+
+            var result = new CPOOuterResponse();
+            HttpStatusCode statusCode = HttpStatusCode.InternalServerError;
+            var _innerData = new { Result = CommandResponseType.Rejected.ToString(), Timeout = 60 };
+            try
+            {
+                string _CustomerId = string.Empty;
+
+                if (!ContainsChargePoint(request.ChargeBoxId, out _CustomerId))
+                {
+                    // 沒槍~ 沒得充...                   
+                    result.StatusMessage = CPO_StatusMessage.ERROR_MSG_CHARGEBOXID_DOESNT_EXIST;
+                    result.StatusCode = (int)CPO_StatusCode.CHARGEBOXID_ISNT_EXIST_OR_OFFLINE;
+                    result.Data = JsonConvert.SerializeObject(_innerData, EVCBConfiguration.JSONSERIALIZER_FORMAT);
+                    statusCode = HttpStatusCode.BadRequest;
+                    return Request.CreateResponse(statusCode, result);
+                }
+
+                ChargePoint16Service _CPService = new ChargePoint16Service();
+
+                if (!string.IsNullOrEmpty(request.ChargeBoxId) && request.ChargeBoxId.Length <= 25
+                   && _CPService.GetNumberofConnectors(request.ChargeBoxId) >= request.ConnectorId && request.ConnectorId > 0
+                    && !string.IsNullOrEmpty(request.Token) && request.Token.Length <= 20)
+                {
+
+                    InternalHttpClient _client = new InternalHttpClient();
+                    CustomerService _customer = new CustomerService();
+
+                    //trigger to charge
+                    var _request = new Models.WebAPI.StartTransactionRequest()
+                    {
+                        ConnectorId = request.ConnectorId,
+                        IdTag = request.Token
+                    };
+
+                    string[] parts = Request.RequestUri.ToString().Split('/');
+                    string urlformat = "{0}//{1}/api/v1/ocpp16/transaction?ChargeBoxId={3}";
+
+                    var _innerResult = await _client.Post(string.Format(urlformat, parts[0], parts[2], Request.RequestUri.Port, request.ChargeBoxId), new Dictionary<string, string>()
+                        {
+                            { "PartnerId",_CustomerId}
+
+                        }, _request, _customer.GetAPIKey(new Guid(_CustomerId)));
+
+
+                    _innerData = new { Result = string.IsNullOrEmpty(_innerResult.SerialNo) ? CommandResponseType.Rejected.ToString() : CommandResponseType.Accepted.ToString(), Timeout = 60 };
+                    result = GetErrorDescription(_innerResult);
+                    result.Data = JsonConvert.SerializeObject(_innerData, EVCBConfiguration.JSONSERIALIZER_FORMAT);
+
+                    if (_innerResult.Status == HttpStatusCode.InternalServerError)
+                    {
+
+                        result.StatusCode = _innerResult.ErrorCode;
+                        result.StatusMessage = CPO_StatusMessage.ERROR_MSG_INNERSERVICE_ERROR;
+                        statusCode = HttpStatusCode.InternalServerError;
+                    }
+                    else
+                    {
+                        result.SerialNo = _innerResult.SerialNo;
+                        result.StatusCode = _innerResult.ErrorCode;
+                        result.StatusMessage = _innerResult.Message;
+                        statusCode = HttpStatusCode.OK;
+
+                    }
+
+
+
+                }
+                else
+                {
+                    // 參數不符合定義
+                    result.StatusMessage = CPO_StatusMessage.ERROR_MSG_PARAMETER_OUTOFRANGE_INCORRECT;
+                    result.StatusCode = (int)CPO_StatusCode.PARAMETER_OUTOFRANGE_INCORRECT;
+                    result.Data = JsonConvert.SerializeObject(_innerData, EVCBConfiguration.JSONSERIALIZER_FORMAT);
+                    statusCode = HttpStatusCode.BadRequest;
+                }
+
+
+                return Request.CreateResponse(statusCode, result);
+            }
+            catch (Exception ex)
+            {
+                result.ErrorDetail = ex.ToString();
+                result.StatusMessage = CPO_StatusMessage.ERROR_MSG_UNEXPECTEDERROR;
+                result.StatusCode = (int)CPO_StatusCode.UnexpectedError;
+                return Request.CreateResponse(statusCode, result);
+            }
+
+
+        }
+
+
+        [Route("commands/stop_session")]
+        [ResponseType(typeof(CPOOuterResponse))]
+        [HttpPost]
+        async public Task<HttpResponseMessage> StopSession(string ChargeBoxId, int SessionId)
+        {
+            var result = new CPOOuterResponse();
+            HttpStatusCode statusCode = HttpStatusCode.InternalServerError;
+            var _innerData = new { Result = CommandResponseType.Rejected.ToString(), Timeout = 60 };
+            try
+            {
+                string _CustomerId = string.Empty;
+
+                if (!ContainsChargePoint(ChargeBoxId, out _CustomerId))
+                {
+                    // 沒槍~ 沒得充...                   
+                    result.StatusMessage = CPO_StatusMessage.ERROR_MSG_CHARGEBOXID_DOESNT_EXIST;
+                    result.StatusCode = (int)CPO_StatusCode.CHARGEBOXID_ISNT_EXIST_OR_OFFLINE;
+                    result.Data = JsonConvert.SerializeObject(_innerData, EVCBConfiguration.JSONSERIALIZER_FORMAT);
+                    statusCode = HttpStatusCode.BadRequest;
+                    return Request.CreateResponse(statusCode, result);
+                }
+
+
+                InternalHttpClient _client = new InternalHttpClient();
+                CustomerService _customer = new CustomerService();
+
+                string[] parts = Request.RequestUri.ToString().Split('/');
+
+                string urlformat = "{0}//{1}/api/v1/ocpp16/transaction?ChargeBoxId={2}&TransactionId={3}";
+
+                var _innerResult = await _client.Put(string.Format(urlformat, parts[0], parts[2], ChargeBoxId, SessionId), new Dictionary<string, string>()
+                        {
+                            { "PartnerId",_CustomerId}
+
+                        }, null, _customer.GetAPIKey(new Guid(_CustomerId)));
+
+
+                _innerData = new { Result = string.IsNullOrEmpty(_innerResult.SerialNo) ? CommandResponseType.Rejected.ToString() : CommandResponseType.Accepted.ToString(), Timeout = 60 };
+                result = GetErrorDescription(_innerResult);
+                result.Data = JsonConvert.SerializeObject(_innerData, EVCBConfiguration.JSONSERIALIZER_FORMAT);
+                if (_innerResult.Status == HttpStatusCode.InternalServerError)
+                {
+
+                    result.StatusCode = _innerResult.ErrorCode;
+                    result.StatusMessage = CPO_StatusMessage.ERROR_MSG_INNERSERVICE_ERROR;
+                    statusCode = HttpStatusCode.InternalServerError;
+                }
+                else
+                {
+                    result.SerialNo = _innerResult.SerialNo;
+                    result.StatusCode = _innerResult.ErrorCode;
+                    result.StatusMessage = _innerResult.Message;
+                    statusCode = HttpStatusCode.OK;
+
+                }
+
+
+            }
+            catch (Exception ex)
+            {
+                result.ErrorDetail = ex.ToString();
+                result.StatusMessage = CPO_StatusMessage.ERROR_MSG_UNEXPECTEDERROR;
+                result.StatusCode = (int)CPO_StatusCode.UnexpectedError;
+                return Request.CreateResponse(statusCode, result);
+            }
+
+            return Request.CreateResponse(statusCode, result);
+        }
+
+        [Route("commands/reserve_now")]
+        [ResponseType(typeof(CPOOuterResponse))]
+        [HttpPost]
+        async public Task<HttpResponseMessage> ReserveNow([FromBody] ReserveNowRequest request)
+        {
+            var result = new CPOOuterResponse();
+            HttpStatusCode statusCode = HttpStatusCode.InternalServerError;
+            var _innerData = new { Result = CommandResponseType.Rejected.ToString(), Timeout = 60 };
+            try
+            {
+                string _CustomerId = string.Empty;
+
+                if (!ContainsChargePoint(request.ChargeBoxId, out _CustomerId))
+                {
+                    // 沒槍~ 沒得充...                   
+                    result.StatusMessage = CPO_StatusMessage.ERROR_MSG_CHARGEBOXID_DOESNT_EXIST;
+                    result.StatusCode = (int)CPO_StatusCode.CHARGEBOXID_ISNT_EXIST_OR_OFFLINE;
+                    result.Data = JsonConvert.SerializeObject(_innerData, EVCBConfiguration.JSONSERIALIZER_FORMAT);
+                    statusCode = HttpStatusCode.BadRequest;
+                    return Request.CreateResponse(statusCode, result);
+                }
+
+
+                InternalHttpClient _client = new InternalHttpClient();
+                CustomerService _customer = new CustomerService();
+
+                string[] parts = Request.RequestUri.ToString().Split('/');
+                string urlformat = "{0}//{1}/api/v1/ocpp16/reservation?ChargeBoxId={2}";
+
+                var _innerRequest = new ReserveRequest()
+                {
+                    ConnectorId = request.ConnectorId,
+                    IdTag = request.Token,
+                    ReservationId = request.ReservationId,
+                    ExpiryDate = request.ExpiryDate.ToString(EVCBConfiguration.UTC_DATETIMEFORMAT)
+                };
+
+                var _innerResult = await _client.Post(string.Format(urlformat, parts[0], parts[2], request.ChargeBoxId), new Dictionary<string, string>()
+                        {
+                            { "PartnerId",_CustomerId}
+
+                        }, _innerRequest, _customer.GetAPIKey(new Guid(_CustomerId)));
+
+
+                _innerData = new { Result = string.IsNullOrEmpty(_innerResult.SerialNo) ? CommandResponseType.Rejected.ToString() : CommandResponseType.Accepted.ToString(), Timeout = 60 };
+                result = GetErrorDescription(_innerResult);
+                result.Data = JsonConvert.SerializeObject(_innerData, EVCBConfiguration.JSONSERIALIZER_FORMAT);
+                if (_innerResult.Status == HttpStatusCode.InternalServerError)
+                {
+
+                    result.StatusCode = _innerResult.ErrorCode;
+                    result.StatusMessage = CPO_StatusMessage.ERROR_MSG_INNERSERVICE_ERROR;
+                    statusCode = HttpStatusCode.InternalServerError;
+                }
+                else
+                {
+                    result.SerialNo = _innerResult.SerialNo;
+                    result.StatusCode = _innerResult.ErrorCode;
+                    result.StatusMessage = _innerResult.Message;
+                    statusCode = HttpStatusCode.OK;
+
+                }
+            }
+            catch (Exception ex)
+            {
+                result.ErrorDetail = ex.ToString();
+                result.StatusMessage = CPO_StatusMessage.ERROR_MSG_UNEXPECTEDERROR;
+                result.StatusCode = (int)CPO_StatusCode.UnexpectedError;
+                return Request.CreateResponse(statusCode, result);
+            }
+
+            return Request.CreateResponse(statusCode, result);
+        }
+
+
+        [Route("commands/cancel_reservation")]
+        [ResponseType(typeof(CPOOuterResponse))]
+        [HttpPost]
+        async public Task<HttpResponseMessage> CancelReservation(string ChargeBoxId, int ReservationId)
+        {
+            var result = new CPOOuterResponse();
+            HttpStatusCode statusCode = HttpStatusCode.InternalServerError;
+            var _innerData = new { Result = CommandResponseType.Rejected.ToString(), Timeout = 60 };
+            try
+            {
+                string _CustomerId = string.Empty;
+
+                if (!ContainsChargePoint(ChargeBoxId, out _CustomerId))
+                {
+                    // 沒槍~ 沒得充...                   
+                    result.StatusMessage = CPO_StatusMessage.ERROR_MSG_CHARGEBOXID_DOESNT_EXIST;
+                    result.StatusCode = (int)CPO_StatusCode.CHARGEBOXID_ISNT_EXIST_OR_OFFLINE;
+                    result.Data = JsonConvert.SerializeObject(_innerData, EVCBConfiguration.JSONSERIALIZER_FORMAT);
+                    statusCode = HttpStatusCode.BadRequest;
+                    return Request.CreateResponse(statusCode, result);
+                }
+
+
+                InternalHttpClient _client = new InternalHttpClient();
+                CustomerService _customer = new CustomerService();
+
+
+                string[] parts = Request.RequestUri.ToString().Split('/');
+
+                string urlformat = "{0}//{1}/api/v1/ocpp16/reservation?ChargeBoxId={2}&ReservationId={3}";
+
+                var _innerResult = await _client.Delete(string.Format(urlformat, parts[0], parts[2], ChargeBoxId, ReservationId), new Dictionary<string, string>()
+                        {
+                            { "PartnerId",_CustomerId}
+
+                        }, _customer.GetAPIKey(new Guid(_CustomerId)));
+
+
+                _innerData = new { Result = string.IsNullOrEmpty(_innerResult.SerialNo) ? CommandResponseType.Rejected.ToString() : CommandResponseType.Accepted.ToString(), Timeout = 60 };
+                result = GetErrorDescription(_innerResult);
+                result.Data = JsonConvert.SerializeObject(_innerData, EVCBConfiguration.JSONSERIALIZER_FORMAT);
+                if (_innerResult.Success)
+                {
+                    result.SerialNo = _innerResult.SerialNo;
+                    result.StatusCode = (int)CPO_StatusCode.Success;
+                    result.StatusMessage = CPO_StatusMessage.Success;
+                    statusCode = HttpStatusCode.OK;
+                }
+                else
+                {
+
+                    result.StatusCode = _innerResult.ErrorCode;
+                    result.StatusMessage = CPO_StatusMessage.ERROR_MSG_INNERSERVICE_ERROR;
+                    statusCode = HttpStatusCode.BadRequest;
+                }
+            }
+            catch (Exception ex)
+            {
+                result.ErrorDetail = ex.ToString();
+                result.StatusMessage = CPO_StatusMessage.ERROR_MSG_UNEXPECTEDERROR;
+                result.StatusCode = (int)CPO_StatusCode.UnexpectedError;
+                return Request.CreateResponse(statusCode, result);
+            }
+
+            return Request.CreateResponse(statusCode, result);
+        }
+
+
+        [Route("commands/chargingprofiles")]
+        [ResponseType(typeof(CPOOuterResponse))]
+        [HttpGet]
+        async public Task<HttpResponseMessage> GetActiveChargingPorfile(string ChargeBoxId, int ConnectorId, int Duration)
+        {
+            var result = new CPOOuterResponse();
+            HttpStatusCode statusCode = HttpStatusCode.InternalServerError;
+            var _innerData = new { Result = CommandResponseType.Rejected.ToString(), Timeout = 60 };
+            try
+            {
+                string _CustomerId = string.Empty;
+
+                if (!ContainsChargePoint(ChargeBoxId, out _CustomerId))
+                {
+                    // 沒槍~ 沒得充...                   
+                    result.StatusMessage = CPO_StatusMessage.ERROR_MSG_CHARGEBOXID_DOESNT_EXIST;
+                    result.StatusCode = (int)CPO_StatusCode.CHARGEBOXID_ISNT_EXIST_OR_OFFLINE;
+                    result.Data = JsonConvert.SerializeObject(_innerData, EVCBConfiguration.JSONSERIALIZER_FORMAT);
+                    statusCode = HttpStatusCode.BadRequest;
+                    return Request.CreateResponse(statusCode, result);
+                }
+
+
+                InternalHttpClient _client = new InternalHttpClient();
+                CustomerService _customer = new CustomerService();
+
+
+                string[] parts = Request.RequestUri.ToString().Split('/');
+
+                string urlformat = "{0}//{1}/api/v1/ocpp16/compositeschedule?ChargeBoxId={2}&ConnectorId={3}&Duration={4}";
+
+                var _innerResult = await _client.Get(string.Format(urlformat, parts[0], parts[2], ChargeBoxId, ConnectorId, Duration), new Dictionary<string, string>()
+                        {
+                            { "PartnerId",_CustomerId}
+
+                        }, _customer.GetAPIKey(new Guid(_CustomerId)));
+
+
+                _innerData = new { Result = string.IsNullOrEmpty(_innerResult.SerialNo) ? CommandResponseType.Rejected.ToString() : CommandResponseType.Accepted.ToString(), Timeout = 60 };
+                result = GetErrorDescription(_innerResult);
+                result.Data = JsonConvert.SerializeObject(_innerData, EVCBConfiguration.JSONSERIALIZER_FORMAT);
+                if (_innerResult.Success)
+                {
+                    result.SerialNo = _innerResult.SerialNo;
+                    result.StatusCode = (int)CPO_StatusCode.Success;
+                    result.StatusMessage = CPO_StatusMessage.Success;
+                    statusCode = HttpStatusCode.OK;
+                }
+                else
+                {
+
+                    result.StatusCode = _innerResult.ErrorCode;
+                    result.StatusMessage = CPO_StatusMessage.ERROR_MSG_INNERSERVICE_ERROR;
+                    statusCode = HttpStatusCode.BadRequest;
+                }
+            }
+            catch (Exception ex)
+            {
+                result.ErrorDetail = ex.ToString();
+                result.StatusMessage = CPO_StatusMessage.ERROR_MSG_UNEXPECTEDERROR;
+                result.StatusCode = (int)CPO_StatusCode.UnexpectedError;
+                return Request.CreateResponse(statusCode, result);
+            }
+
+            return Request.CreateResponse(statusCode, result);
+        }
+
+        [Route("commands/chargingprofiles")]
+        [ResponseType(typeof(CPOOuterResponse))]
+        [HttpPut]
+        async public Task<HttpResponseMessage> SetChargingProfile(string ChargeBoxId, [FromBody] ChargingProfileRequest request)
+        {
+            var result = new CPOOuterResponse();
+            HttpStatusCode statusCode = HttpStatusCode.InternalServerError;
+            var _innerData = new { Result = CommandResponseType.Rejected.ToString(), Timeout = 60 };
+            try
+            {
+                string _CustomerId = string.Empty;
+
+                if (!ContainsChargePoint(ChargeBoxId, out _CustomerId))
+                {
+                    // 沒槍~ 沒得充...                   
+                    result.StatusMessage = CPO_StatusMessage.ERROR_MSG_CHARGEBOXID_DOESNT_EXIST;
+                    result.StatusCode = (int)CPO_StatusCode.CHARGEBOXID_ISNT_EXIST_OR_OFFLINE;
+                    result.Data = JsonConvert.SerializeObject(_innerData, EVCBConfiguration.JSONSERIALIZER_FORMAT);
+                    statusCode = HttpStatusCode.BadRequest;
+                    return Request.CreateResponse(statusCode, result);
+                }
+
+
+
+                InternalHttpClient _client = new InternalHttpClient();
+                CustomerService _customer = new CustomerService();
+
+
+                string[] parts = Request.RequestUri.ToString().Split('/');
+
+                string urlformat = "{0}//{1}/api/v1/ocpp16/chargingprofile?ChargeBoxId={2}";
+
+                var _innerResult = await _client.Post(string.Format(urlformat, parts[0], parts[2], ChargeBoxId), new Dictionary<string, string>()
+                        {
+                            { "PartnerId",_CustomerId}
+
+                        }, request, _customer.GetAPIKey(new Guid(_CustomerId)));
+
+
+                _innerData = new { Result = string.IsNullOrEmpty(_innerResult.SerialNo) ? CommandResponseType.Rejected.ToString() : CommandResponseType.Accepted.ToString(), Timeout = 60 };
+                result = GetErrorDescription(_innerResult);
+                result.Data = JsonConvert.SerializeObject(_innerData, EVCBConfiguration.JSONSERIALIZER_FORMAT);
+                if (_innerResult.Success)
+                {
+                    result.SerialNo = _innerResult.SerialNo;
+                    result.StatusCode = (int)CPO_StatusCode.Success;
+                    result.StatusMessage = CPO_StatusMessage.Success;
+                    statusCode = HttpStatusCode.OK;
+                }
+                else
+                {
+
+                    result.StatusCode = _innerResult.ErrorCode;
+                    result.StatusMessage = CPO_StatusMessage.ERROR_MSG_INNERSERVICE_ERROR;
+                    statusCode = HttpStatusCode.BadRequest;
+                }
+                ChargePoint16Service chargePointService = new ChargePoint16Service();
+
+                if (!chargePointService.IsOnline(ChargeBoxId))
+                {
+                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Code = 2101, Message = EVCBConfiguration.ERROR_MSG_CHARGEBOXID_ISNT_EXIST_OR_OFFLINE });
+                }
+
+
+            }
+            catch (Exception ex)
+            {
+                result.ErrorDetail = ex.ToString();
+                result.StatusMessage = CPO_StatusMessage.ERROR_MSG_UNEXPECTEDERROR;
+                result.StatusCode = (int)CPO_StatusCode.UnexpectedError;
+                return Request.CreateResponse(statusCode, result);
+            }
+
+            return Request.CreateResponse(statusCode, result);
+        }
+
+        [Route("commands/chargingprofiles")]
+        [ResponseType(typeof(CPOOuterResponse))]
+        [HttpDelete]
+        async public Task<HttpResponseMessage> ClearChargingPorfile(string ChargeBoxId, int ChargeProfileId = -1)
+        {
+            var result = new CPOOuterResponse();
+            HttpStatusCode statusCode = HttpStatusCode.InternalServerError;
+            var _innerData = new { Result = CommandResponseType.Rejected.ToString(), Timeout = 60 };
+            try
+            {
+                string _CustomerId = string.Empty;
+
+                if (!ContainsChargePoint(ChargeBoxId, out _CustomerId))
+                {
+                    // 沒槍~ 沒得充...                   
+                    result.StatusMessage = CPO_StatusMessage.ERROR_MSG_CHARGEBOXID_DOESNT_EXIST;
+                    result.StatusCode = (int)CPO_StatusCode.CHARGEBOXID_ISNT_EXIST_OR_OFFLINE;
+                    result.Data = JsonConvert.SerializeObject(_innerData, EVCBConfiguration.JSONSERIALIZER_FORMAT);
+                    statusCode = HttpStatusCode.BadRequest;
+                    return Request.CreateResponse(statusCode, result);
+                }
+
+
+                InternalHttpClient _client = new InternalHttpClient();
+                CustomerService _customer = new CustomerService();
+
+
+                string[] parts = Request.RequestUri.ToString().Split('/');
+
+                string urlformat = "{0}//{1}/api/v1/ocpp16/chargingprofile?ChargeBoxId={2}{3}";
+
+                var _innerResult = await _client.Delete(string.Format(urlformat, parts[0], parts[2], ChargeBoxId, ChargeProfileId == -1 ? "" : "&Id=" + ChargeProfileId), new Dictionary<string, string>()
+                        {
+                            { "PartnerId",_CustomerId}
+
+                        }, _customer.GetAPIKey(new Guid(_CustomerId)));
+
+
+                _innerData = new { Result = string.IsNullOrEmpty(_innerResult.SerialNo) ? CommandResponseType.Rejected.ToString() : CommandResponseType.Accepted.ToString(), Timeout = 60 };
+                result = GetErrorDescription(_innerResult);
+                result.Data = JsonConvert.SerializeObject(_innerData, EVCBConfiguration.JSONSERIALIZER_FORMAT);
+                if (_innerResult.Success)
+                {
+                    result.SerialNo = _innerResult.SerialNo;
+                    result.StatusCode = (int)CPO_StatusCode.Success;
+                    result.StatusMessage = CPO_StatusMessage.Success;
+                    statusCode = HttpStatusCode.OK;
+                }
+                else
+                {
+
+                    result.StatusCode = _innerResult.ErrorCode;
+                    result.StatusMessage = CPO_StatusMessage.ERROR_MSG_INNERSERVICE_ERROR;
+                    statusCode = HttpStatusCode.BadRequest;
+                }
+            }
+            catch (Exception ex)
+            {
+                result.ErrorDetail = ex.ToString();
+                result.StatusMessage = CPO_StatusMessage.ERROR_MSG_UNEXPECTEDERROR;
+                result.StatusCode = (int)CPO_StatusCode.UnexpectedError;
+                return Request.CreateResponse(statusCode, result);
+            }
+
+            return Request.CreateResponse(statusCode, result);
+        }
+
+        [Route("commands/set_locallist")]
+        [ResponseType(typeof(CPOOuterResponse))]
+        [HttpPost]
+        async public Task<HttpResponseMessage> SendLocalList(string ChargeBoxId, [FromBody] LocalListRequest request)
+        {
+            var result = new CPOOuterResponse();
+            HttpStatusCode statusCode = HttpStatusCode.InternalServerError;
+            var _innerData = new { Result = CommandResponseType.Rejected.ToString(), Timeout = 60 };
+            try
+            {
+                string _CustomerId = string.Empty;
+
+                if (!ContainsChargePoint(ChargeBoxId, out _CustomerId))
+                {
+                    // 沒槍~ 沒得充...                   
+                    result.StatusMessage = CPO_StatusMessage.ERROR_MSG_CHARGEBOXID_DOESNT_EXIST;
+                    result.StatusCode = (int)CPO_StatusCode.CHARGEBOXID_ISNT_EXIST_OR_OFFLINE;
+                    result.Data = JsonConvert.SerializeObject(_innerData, EVCBConfiguration.JSONSERIALIZER_FORMAT);
+                    statusCode = HttpStatusCode.BadRequest;
+                    return Request.CreateResponse(statusCode, result);
+                }
+
+
+                InternalHttpClient _client = new InternalHttpClient();
+                CustomerService _customer = new CustomerService();
+
+
+
+                string[] parts = Request.RequestUri.ToString().Split('/');
+
+                string urlformat = "{0}//{1}/api/v1/ocpp16/locallist?ChargeBoxId={2}";
+
+
+
+                var _innerResult = await _client.Post(string.Format(urlformat, parts[0], parts[2], ChargeBoxId), new Dictionary<string, string>()
+                        {
+                            { "PartnerId",_CustomerId}
+
+                        }, request, _customer.GetAPIKey(new Guid(_CustomerId)));
+
+
+                _innerData = new { Result = string.IsNullOrEmpty(_innerResult.SerialNo) ? CommandResponseType.Rejected.ToString() : CommandResponseType.Accepted.ToString(), Timeout = 60 };
+                result = GetErrorDescription(_innerResult);
+                result.Data = JsonConvert.SerializeObject(_innerData, EVCBConfiguration.JSONSERIALIZER_FORMAT);
+                if (_innerResult.Success)
+                {
+                    result.SerialNo = _innerResult.SerialNo;
+                    result.StatusCode = (int)CPO_StatusCode.Success;
+                    result.StatusMessage = CPO_StatusMessage.Success;
+                    statusCode = HttpStatusCode.OK;
+                }
+                else
+                {
+
+                    result.StatusCode = _innerResult.ErrorCode;
+                    result.StatusMessage = CPO_StatusMessage.ERROR_MSG_INNERSERVICE_ERROR;
+                    statusCode = HttpStatusCode.BadRequest;
+                }
+            }
+            catch (Exception ex)
+            {
+                result.ErrorDetail = ex.ToString();
+                result.StatusMessage = CPO_StatusMessage.ERROR_MSG_UNEXPECTEDERROR;
+                result.StatusCode = (int)CPO_StatusCode.UnexpectedError;
+                return Request.CreateResponse(statusCode, result);
+            }
+
+            return Request.CreateResponse(statusCode, result);
+        }
+
+
+        [Route("commands/locallistversion")]
+        [ResponseType(typeof(CPOOuterResponse))]
+        [HttpGet]
+        async public Task<HttpResponseMessage> GetLocalListVersion(string ChargeBoxId)
+        {
+            var result = new CPOOuterResponse();
+            HttpStatusCode statusCode = HttpStatusCode.InternalServerError;
+            var _innerData = new { Result = CommandResponseType.Rejected.ToString(), Timeout = 60 };
+            try
+            {
+                string _CustomerId = string.Empty;
+
+                if (!ContainsChargePoint(ChargeBoxId, out _CustomerId))
+                {
+                    // 沒槍~ 沒得充...                   
+                    result.StatusMessage = CPO_StatusMessage.ERROR_MSG_CHARGEBOXID_DOESNT_EXIST;
+                    result.StatusCode = (int)CPO_StatusCode.CHARGEBOXID_ISNT_EXIST_OR_OFFLINE;
+                    result.Data = JsonConvert.SerializeObject(_innerData, EVCBConfiguration.JSONSERIALIZER_FORMAT);
+                    statusCode = HttpStatusCode.BadRequest;
+                    return Request.CreateResponse(statusCode, result);
+                }
+
+
+                InternalHttpClient _client = new InternalHttpClient();
+                CustomerService _customer = new CustomerService();
+
+
+
+                string[] parts = Request.RequestUri.ToString().Split('/');
+
+                string urlformat = "{0}//{1}/api/v1/ocpp16/locallistversion?ChargeBoxId={2}";
+
+
+
+                var _innerResult = await _client.Get(string.Format(urlformat, parts[0], parts[2], ChargeBoxId), new Dictionary<string, string>()
+                        {
+                            { "PartnerId",_CustomerId}
+
+                        }, _customer.GetAPIKey(new Guid(_CustomerId)));
+
+
+                _innerData = new { Result = string.IsNullOrEmpty(_innerResult.SerialNo) ? CommandResponseType.Rejected.ToString() : CommandResponseType.Accepted.ToString(), Timeout = 60 };
+                result = GetErrorDescription(_innerResult);
+                result.Data = JsonConvert.SerializeObject(_innerData, EVCBConfiguration.JSONSERIALIZER_FORMAT);
+                if (_innerResult.Success)
+                {
+                    result.SerialNo = _innerResult.SerialNo;
+                    result.StatusCode = (int)CPO_StatusCode.Success;
+                    result.StatusMessage = CPO_StatusMessage.Success;
+                    statusCode = HttpStatusCode.OK;
+                }
+                else
+                {
+
+                    result.StatusCode = _innerResult.ErrorCode;
+                    result.StatusMessage = CPO_StatusMessage.ERROR_MSG_INNERSERVICE_ERROR;
+                    statusCode = HttpStatusCode.BadRequest;
+                }
+
+                statusCode = HttpStatusCode.OK;
+            }
+            catch (Exception ex)
+            {
+                result.ErrorDetail = ex.ToString();
+                result.StatusMessage = CPO_StatusMessage.ERROR_MSG_UNEXPECTEDERROR;
+                result.StatusCode = (int)CPO_StatusCode.UnexpectedError;
+                return Request.CreateResponse(statusCode, result);
+            }
+
+            return Request.CreateResponse(statusCode, result);
+        }
+
+
+        [Route("commands/results")]
+        [ResponseType(typeof(CPOOuterResponse))]
+        [HttpGet]
+        async public Task<HttpResponseMessage> ExecutionofCmdSearch(string ChargeBoxId, CommandType? commandType, string SerialNo)
+        {
+            var result = new CPOOuterResponse();
+            HttpStatusCode statusCode = HttpStatusCode.InternalServerError;
+
+            try
+            {
+                string _CustomerId = string.Empty;
+
+                if (!ContainsChargePoint(ChargeBoxId, out _CustomerId))
+                {
+                    // 沒槍~ 沒得充...                   
+                    result.StatusMessage = CPO_StatusMessage.ERROR_MSG_CHARGEBOXID_DOESNT_EXIST;
+                    result.StatusCode = (int)CPO_StatusCode.CHARGEBOXID_ISNT_EXIST_OR_OFFLINE;
+                    statusCode = HttpStatusCode.BadRequest;
+                    return Request.CreateResponse(statusCode, result);
+                }
+
+
+                InternalHttpClient _client = new InternalHttpClient();
+                CustomerService _customer = new CustomerService();
+
+                int? orderNo = (int?)null;
+
+                switch (commandType.Value)
+                {
+                    case CommandType.CancelReservation:
+                        {
+                            orderNo = 4;
+                        }
+                        break;
+                    case CommandType.ClearChargingProfile:
+                        {
+                            orderNo = 6;
+                        }
+                        break;
+                    case CommandType.GetAcitveChargingProfile:
+                        {
+                            orderNo = 7;
+                        }
+                        break;
+                    case CommandType.GetLocalListVersion:
+                        {
+                            orderNo = 9;
+                        }
+                        break;
+                    case CommandType.Start_Session:
+                        {
+                            orderNo = 10;
+                        }
+                        break;
+                    case CommandType.Stop_Session:
+                        {
+                            orderNo = 11;
+                        }
+                        break;
+                    case CommandType.Reserve_Now:
+                        {
+                            orderNo = 12;
+                        }
+                        break;
+                    case CommandType.SetLocalList:
+                        {
+                            orderNo = 14;
+                        }
+                        break;
+                    case CommandType.SetChargingProfile:
+                        {
+                            orderNo = 15;
+                        }
+                        break;
+                    default:
+                        {
+                            orderNo = 18;
+                        }
+                        break;
+
+
+                }
+
+
+                string[] parts = Request.RequestUri.ToString().Split('/');
+
+                string urlformat = "{0}//{1}/api/v1/ocpp16/command?ChargeBoxId={2}{3}&SerialNo={4}";
+
+
+                var _innerResult = await _client.Get(string.Format(urlformat, parts[0], parts[2], ChargeBoxId, orderNo.HasValue ? "&OrderNo=" + orderNo.Value : "", SerialNo), new Dictionary<string, string>()
+                        {
+                            { "PartnerId",_CustomerId}
+
+                        }, _customer.GetAPIKey(new Guid(_CustomerId)));
+
+
+                result = GetErrorDescription(_innerResult);
+
+                if (_innerResult.Success)
+                {
+                    ComandExecution _execution = JsonConvert.DeserializeObject<ComandExecution>(_innerResult.Message);
+
+                    CommandResultType? _cmdResult = (CommandResultType?)null;
+
+                    switch (_execution.Code)
+                    {
+                        case 1:
+                            {
+                                _cmdResult = CommandResultType.Accepted;
+                            }
+                            break;
+                        case 9:
+                            {
+                                _cmdResult = CommandResultType.Notsupported;
+                            }
+                            break;
+                        case 10:
+                            {
+                                _cmdResult = CommandResultType.Unknown;
+                            }
+                            break;
+                        case 26:
+                            {
+                                _cmdResult = CommandResultType.Occupied;
+                            }
+                            break;
+                        case 31:
+                            {
+                                _cmdResult = CommandResultType.Rejected;
+                            }
+                            break;
+                        case 32:
+                            {
+                                _cmdResult = CommandResultType.Failed;
+                            }
+                            break;
+                        case 254:
+                            {
+                                _cmdResult = CommandResultType.EVSE_ERROR;
+                            }
+                            break;
+                        default:
+                            {
+                                if (_execution.Detail == "Timeout") _cmdResult = CommandResultType.Timeout;
+                                if (_execution.Detail == "Waited") _cmdResult = CommandResultType.Waited;
+
+                            }
+                            break;
+
+
+                    }
+
+
+                    if (!_cmdResult.HasValue)
+                    {
+                        result.StatusCode = (int)CPO_StatusCode.CANT_FOUND_DATA;
+                        result.StatusMessage = CPO_StatusMessage.ERROR_MSG_CANT_FIND_RESULT;
+                        statusCode = HttpStatusCode.NotFound;
+                    }
+                    else
+                    {
+                        var _innerData = new { Result = _cmdResult.Value.ToString(), Message = _execution.Detail };
+                        result.Data = JsonConvert.SerializeObject(_innerData, EVCBConfiguration.JSONSERIALIZER_FORMAT);
+                        result.SerialNo = _innerResult.SerialNo;
+                        result.StatusCode = (int)CPO_StatusCode.Success;
+                        result.StatusMessage = CPO_StatusMessage.Success;
+                        statusCode = HttpStatusCode.OK;
+                    }
+
+                }
+
+
+            }
+            catch (Exception ex)
+            {
+                result.ErrorDetail = ex.ToString();
+                result.StatusMessage = CPO_StatusMessage.ERROR_MSG_UNEXPECTEDERROR;
+                result.StatusCode = (int)CPO_StatusCode.UnexpectedError;
+                return Request.CreateResponse(statusCode, result);
+            }
+
+            return Request.CreateResponse(statusCode, result);
+        }
+
+
+        [Route("version")]
+        [ResponseType(typeof(CPOOuterResponse))]
+        [HttpGet]
+        public HttpResponseMessage Version(string ChargeBoxId)
+        {
+            var result = new CPOOuterResponse();
+            HttpStatusCode statusCode = HttpStatusCode.InternalServerError;
+
+            try
+            {
+                ChargePoint16Service _service = new ChargePoint16Service();
+                string version = _service.GetVersionbyChargeBoxId(ChargeBoxId);
+
+                result.Data = version;
+                result.StatusCode = (int)CPO_StatusCode.Success;
+                result.StatusMessage = CPO_StatusMessage.Success;
+                statusCode = HttpStatusCode.OK;
+            }
+            catch (Exception ex)
+            {
+                result.ErrorDetail = ex.ToString();
+                result.StatusMessage = CPO_StatusMessage.ERROR_MSG_UNEXPECTEDERROR;
+                result.StatusCode = (int)CPO_StatusCode.UnexpectedError;
+                return Request.CreateResponse(statusCode, result);
+            }
+
+            return Request.CreateResponse(statusCode, result);
+
+        }
+
+
+        [Route("activesession")]
+        [ResponseType(typeof(CPOOuterResponse))]
+        [HttpGet]
+        public HttpResponseMessage ActiveSession(string ChargeBoxId, string SessionId = "", string IdTag = "")
+        {
+            var result = new CPOOuterResponse();
+            HttpStatusCode statusCode = HttpStatusCode.InternalServerError;
+
+            try
+            {
+                string _CustomerId = string.Empty;
+
+                if (!ContainsChargePoint(ChargeBoxId, out _CustomerId))
+                {
+                    // 沒槍~ 沒得充...                   
+                    result.StatusMessage = CPO_StatusMessage.ERROR_MSG_CHARGEBOXID_DOESNT_EXIST;
+                    result.StatusCode = (int)CPO_StatusCode.CHARGEBOXID_ISNT_EXIST_OR_OFFLINE;
+                    statusCode = HttpStatusCode.BadRequest;
+                    return Request.CreateResponse(statusCode, result);
+                }
+
+                // query meter value
+                ChargePoint16Service _service = new ChargePoint16Service();
+                var transactionDatas = _service.GetActiveSessionInfo(ChargeBoxId, new List<Packet.Messages.SubTypes.Measurand>()
+                {   Packet.Messages.SubTypes.Measurand.Voltage,
+                    Packet.Messages.SubTypes.Measurand.Current_Import,
+                    Packet.Messages.SubTypes.Measurand.SoC,
+                    Packet.Messages.SubTypes.Measurand.Power_Active_Import,
+                    Packet.Messages.SubTypes.Measurand.Energy_Active_Import_Interval
+                }, SessionId, IdTag);
+
+                if (transactionDatas == null)
+                {
+                    result.StatusCode = (int)CPO_StatusCode.CANT_FOUND_DATA;
+                    result.StatusMessage = CPO_StatusMessage.ERROR_MSG_CANT_FIND_RESULT;
+                    statusCode = HttpStatusCode.NotFound;
+                }
+                else
+                {
+                    List<ActiveSession> _innerData = new List<ActiveSession>();
+
+                    foreach (var transactionData in transactionDatas)
+                    {
+
+
+                        _innerData.Add(new ActiveSession()
+                        {
+                            ChargeBoxId = ChargeBoxId,
+                            SessionId = transactionData.Id,
+                            ElaspedTime = (int)DateTime.UtcNow.Subtract(transactionData.StartTime).TotalMinutes,
+                            ConnectorId = transactionData.ConnectorId,
+                            IdTag = transactionData.StartIdTag,
+                            Power = transactionData.MeterValues == null ? "0" : transactionData.MeterValues.Where(x => x.Measurand == Packet.Messages.SubTypes.Measurand.Power_Active_Import).Select(x => x.Value).FirstOrDefault(),
+                            Power_Format = transactionData.MeterValues == null ? UnitOfMeasure.W.ToString() : transactionData.MeterValues.Where(x => x.Measurand == Packet.Messages.SubTypes.Measurand.Power_Active_Import).Select(x => x.Unit.ToString()).FirstOrDefault(),
+                            Current = transactionData.MeterValues == null ? "0" : transactionData.MeterValues.Where(x => x.Measurand == Packet.Messages.SubTypes.Measurand.Current_Import).Select(x => x.Value).FirstOrDefault(),
+                            Current_Format = transactionData.MeterValues == null ? UnitOfMeasure.A.ToString() : transactionData.MeterValues.Where(x => x.Measurand == Packet.Messages.SubTypes.Measurand.Current_Import).Select(x => x.Unit.ToString()).FirstOrDefault(),
+                            Energy = transactionData.MeterValues == null ? "0" : transactionData.MeterValues.Where(x => x.Measurand == Packet.Messages.SubTypes.Measurand.Energy_Active_Import_Interval).Select(x => x.Value).FirstOrDefault(),
+                            Energy_Format = transactionData.MeterValues == null ? UnitOfMeasure.Wh.ToString() : transactionData.MeterValues.Where(x => x.Measurand == Packet.Messages.SubTypes.Measurand.Energy_Active_Import_Interval).Select(x => x.Unit.ToString()).FirstOrDefault(),
+                            Voltage = transactionData.MeterValues == null ? "0" : transactionData.MeterValues.Where(x => x.Measurand == Packet.Messages.SubTypes.Measurand.Voltage).Select(x => x.Value).FirstOrDefault(),
+                            Voltage_Format = transactionData.MeterValues == null ? UnitOfMeasure.V.ToString() : transactionData.MeterValues.Where(x => x.Measurand == Packet.Messages.SubTypes.Measurand.Voltage).Select(x => x.Unit.ToString()).FirstOrDefault(),
+                            SOC = transactionData.MeterValues == null ? "0" : transactionData.MeterValues.Where(x => x.Measurand == Packet.Messages.SubTypes.Measurand.SoC).Select(x => x.Unit.ToString()).FirstOrDefault() == null ? null : transactionData.MeterValues.Where(x => x.Measurand == Packet.Messages.SubTypes.Measurand.SoC).Select(x => x.Value).FirstOrDefault(),
+                            SOC_Format = transactionData.MeterValues == null ? UnitOfMeasure.Percent.ToString() : transactionData.MeterValues.Where(x => x.Measurand == Packet.Messages.SubTypes.Measurand.SoC).Select(x => x.Unit.ToString()).FirstOrDefault(),
+                        });
+
+                    }
+                    var _innerResponse = new { Sessions = _innerData };
+                    result.Data = JsonConvert.SerializeObject(_innerResponse, EVCBConfiguration.JSONSERIALIZER_FORMAT);
+
+                    result.StatusCode = (int)CPO_StatusCode.Success;
+                    result.StatusMessage = CPO_StatusMessage.Success;
+                    statusCode = HttpStatusCode.OK;
+
+                }
+
+                return Request.CreateResponse(statusCode, result);
+            }
+            catch (Exception ex)
+            {
+                result.ErrorDetail = ex.ToString();
+                result.StatusMessage = CPO_StatusMessage.ERROR_MSG_UNEXPECTEDERROR;
+                result.StatusCode = (int)CPO_StatusCode.UnexpectedError;
+                return Request.CreateResponse(statusCode, result);
+            }
+
+        }
+
+
+        [Route("completedsession")]
+        [ResponseType(typeof(CPOOuterResponse))]
+        [HttpGet]
+        public HttpResponseMessage CompletedSession(string ChargeBoxId, string SessionId = "", string IdTag = "", string StartTime = "", string StopTime = "")
+        {
+            var result = new CPOOuterResponse();
+            HttpStatusCode statusCode = HttpStatusCode.InternalServerError;
+
+            try
+            {
+                string _CustomerId = string.Empty;
+
+                if (!ContainsChargePoint(ChargeBoxId, out _CustomerId))
+                {
+                    // 沒槍~ 沒得充...                   
+                    result.StatusMessage = CPO_StatusMessage.ERROR_MSG_CHARGEBOXID_DOESNT_EXIST;
+                    result.StatusCode = (int)CPO_StatusCode.CHARGEBOXID_ISNT_EXIST_OR_OFFLINE;
+                    statusCode = HttpStatusCode.BadRequest;
+                    return Request.CreateResponse(statusCode, result);
+                }
+
+                DateTime startDt = string.IsNullOrEmpty(StartTime) ? new DateTime(1991, 1, 1) : DateTime.Parse(StartTime);
+                DateTime stopDt = string.IsNullOrEmpty(StopTime) ? new DateTime(1991, 1, 1) : DateTime.Parse(StopTime);
+                // query meter value
+                ChargePoint16Service _service = new ChargePoint16Service();
+                var _innerData = _service.GetSessionDetail(ChargeBoxId, SessionId, IdTag, startDt, stopDt);
+
+                if (_innerData == null)
+                {
+                    result.StatusCode = (int)CPO_StatusCode.CANT_FOUND_DATA;
+                    result.StatusMessage = CPO_StatusMessage.ERROR_MSG_CANT_FIND_SESSIONDETAIL;
+                    statusCode = HttpStatusCode.NotFound;
+                    return Request.CreateResponse(statusCode, result);
+                }
+                var _innerResponse = new { SessionDetails = _innerData };
+                result.Data = JsonConvert.SerializeObject(_innerResponse, EVCBConfiguration.JSONSERIALIZER_FORMAT);
+
+                result.StatusCode = (int)CPO_StatusCode.Success;
+                result.StatusMessage = CPO_StatusMessage.Success;
+                statusCode = HttpStatusCode.OK;
+                return Request.CreateResponse(statusCode, result);
+            }
+            catch (Exception ex)
+            {
+                result.ErrorDetail = ex.ToString();
+                result.StatusMessage = CPO_StatusMessage.ERROR_MSG_UNEXPECTEDERROR;
+                result.StatusCode = (int)CPO_StatusCode.UnexpectedError;
+                return Request.CreateResponse(statusCode, result);
+            }
+
+        }
+
+
+        [Route("statistics/charging_sessions")]
+        [ResponseType(typeof(CPOOuterResponse))]
+        [HttpPost]
+        async public Task<HttpResponseMessage> ChargingSessionsStatistics([FromBody] StatisticsRequest request)
+        {
+            var result = new CPOOuterResponse();
+            HttpStatusCode statusCode = HttpStatusCode.InternalServerError;
+            var _innerData = new { Result = CommandResponseType.Rejected.ToString(), Timeout = 60 };
+            try
+            {
+
+                InternalHttpClient _client = new InternalHttpClient();
+                CustomerService _customer = new CustomerService();
+
+                string url = System.Web.Configuration.WebConfigurationManager.AppSettings["StatisticsAPI"] + 1;
+                string chargeBoxIds = GetStatisticChargeBoxIds(request.ChargeBoxIds);
+
+                HttpClientService service = new HttpClientService();
+
+                Dictionary<string, string> postData = new Dictionary<string, string>()
+                {
+                  { "ChargeBoxId", chargeBoxIds },
+                  { "Type", request.Type.ToString() },
+                  { "StartDate",request.DateFrom.ToString(EVCBConfiguration.DATETIMEFORMAT)},
+                  { "EndDate",request.DateTo.ToString(EVCBConfiguration.DATETIMEFORMAT)}
+
+                };
+                var _innerresult = await service.PostFormDataAsync(url, postData, null);
+
+
+                if (_innerresult.StatusCode == HttpStatusCode.OK)
+                {
+                    _innerresult.Response = _innerresult.Response.Replace("item", "Title");
+                    _innerresult.Response = _innerresult.Response.Replace("Data", "Count");
+                    result.Data = _innerresult.Response;
+                    result.StatusCode = (int)CPO_StatusCode.Success;
+                    result.StatusMessage = CPO_StatusMessage.Success;
+                    statusCode = HttpStatusCode.OK;
+                }
+                else
+                {
+                    result.StatusCode = (int)CPO_StatusCode.CANT_FOUND_DATA;
+                    result.StatusMessage = CPO_StatusMessage.ERROR_MSG_INNERSERVICE_ERROR;
+                    statusCode = HttpStatusCode.BadRequest;
+                }
+            }
+            catch (Exception ex)
+            {
+                result.ErrorDetail = ex.ToString();
+                result.StatusMessage = CPO_StatusMessage.ERROR_MSG_UNEXPECTEDERROR;
+                result.StatusCode = (int)CPO_StatusCode.UnexpectedError;
+                return Request.CreateResponse(statusCode, result);
+            }
+
+            return Request.CreateResponse(statusCode, result);
+        }
+
+        [Route("statistics/energy_delivered")]
+        [ResponseType(typeof(CPOOuterResponse))]
+        [HttpPost]
+        async public Task<HttpResponseMessage> Energy_Delivered([FromBody] StatisticsRequest request)
+        {
+            var result = new CPOOuterResponse();
+            HttpStatusCode statusCode = HttpStatusCode.InternalServerError;
+            var _innerData = new { Result = CommandResponseType.Rejected.ToString(), Timeout = 60 };
+            try
+            {
+
+                InternalHttpClient _client = new InternalHttpClient();
+                CustomerService _customer = new CustomerService();
+
+                string url = System.Web.Configuration.WebConfigurationManager.AppSettings["StatisticsAPI"] + 2;
+                string chargeBoxIds = GetStatisticChargeBoxIds(request.ChargeBoxIds);
+
+                HttpClientService service = new HttpClientService();
+
+                Dictionary<string, string> postData = new Dictionary<string, string>()
+                {
+                  { "ChargeBoxId",chargeBoxIds },
+                  { "Type", request.Type.ToString() },
+                  { "StartDate",request.DateFrom.ToString(EVCBConfiguration.DATETIMEFORMAT)},
+                  { "EndDate",request.DateTo.ToString(EVCBConfiguration.DATETIMEFORMAT)}
+
+                };
+                var _innerresult = await service.PostFormDataAsync(url, postData, null);
+
+
+                if (_innerresult.StatusCode == HttpStatusCode.OK)
+                {
+                    _innerresult.Response = _innerresult.Response.Replace("item", "Title");
+                    _innerresult.Response = _innerresult.Response.Replace("Data", "DeliveredEnergy");
+                    result.Data = _innerresult.Response;
+                    result.StatusCode = (int)CPO_StatusCode.Success;
+                    result.StatusMessage = CPO_StatusMessage.Success;
+                    statusCode = HttpStatusCode.OK;
+                }
+                else
+                {
+                    result.StatusCode = (int)CPO_StatusCode.CANT_FOUND_DATA;
+                    result.StatusMessage = CPO_StatusMessage.ERROR_MSG_INNERSERVICE_ERROR;
+                    statusCode = HttpStatusCode.BadRequest;
+                }
+            }
+            catch (Exception ex)
+            {
+                result.ErrorDetail = ex.ToString();
+                result.StatusMessage = CPO_StatusMessage.ERROR_MSG_UNEXPECTEDERROR;
+                result.StatusCode = (int)CPO_StatusCode.UnexpectedError;
+                return Request.CreateResponse(statusCode, result);
+            }
+
+            return Request.CreateResponse(statusCode, result);
+        }
+
+        [Route("statistics/time_of_use")]
+        [ResponseType(typeof(CPOOuterResponse))]
+        [HttpPost]
+        async public Task<HttpResponseMessage> Time_of_Use([FromBody] StatisticsRequest request)
+        {
+            var result = new CPOOuterResponse();
+            HttpStatusCode statusCode = HttpStatusCode.InternalServerError;
+            var _innerData = new { Result = CommandResponseType.Rejected.ToString(), Timeout = 60 };
+            try
+            {
+
+                InternalHttpClient _client = new InternalHttpClient();
+                CustomerService _customer = new CustomerService();
+
+                string url = System.Web.Configuration.WebConfigurationManager.AppSettings["StatisticsAPI"] + 3;
+                string chargeBoxIds = GetStatisticChargeBoxIds(request.ChargeBoxIds);
+
+                HttpClientService service = new HttpClientService();
+
+                Dictionary<string, string> postData = new Dictionary<string, string>()
+                {
+                  { "ChargeBoxId",chargeBoxIds },
+                  { "StartDate",request.DateFrom.ToString(EVCBConfiguration.DATETIMEFORMAT)},
+                  { "EndDate",request.DateTo.ToString(EVCBConfiguration.DATETIMEFORMAT)}
+
+                };
+                var _innerresult = await service.PostFormDataAsync(url, postData, null);
+
+
+                if (_innerresult.StatusCode == HttpStatusCode.OK)
+                {
+                    _innerresult.Response = _innerresult.Response.Replace("item", "Title");
+                    _innerresult.Response = _innerresult.Response.Replace("data", "Count");
+                    _innerresult.Response = _innerresult.Response.Replace("data2", "DeliveredEnergy");
+                    result.Data = _innerresult.Response;
+                    result.StatusCode = (int)CPO_StatusCode.Success;
+                    result.StatusMessage = CPO_StatusMessage.Success;
+                    statusCode = HttpStatusCode.OK;
+                }
+                else
+                {
+                    result.StatusCode = (int)CPO_StatusCode.CANT_FOUND_DATA;
+                    result.StatusMessage = CPO_StatusMessage.ERROR_MSG_INNERSERVICE_ERROR;
+                    statusCode = HttpStatusCode.BadRequest;
+                }
+            }
+            catch (Exception ex)
+            {
+                result.ErrorDetail = ex.ToString();
+                result.StatusMessage = CPO_StatusMessage.ERROR_MSG_UNEXPECTEDERROR;
+                result.StatusCode = (int)CPO_StatusCode.UnexpectedError;
+                return Request.CreateResponse(statusCode, result);
+            }
+
+            return Request.CreateResponse(statusCode, result);
+        }
+
+        [Route("statistics/peak_load")]
+        [ResponseType(typeof(CPOOuterResponse))]
+        [HttpPost]
+        async public Task<HttpResponseMessage> Peak_Load([FromBody] StatisticsRequest request)
+        {
+            var result = new CPOOuterResponse();
+            HttpStatusCode statusCode = HttpStatusCode.InternalServerError;
+            var _innerData = new { Result = CommandResponseType.Rejected.ToString(), Timeout = 60 };
+            try
+            {
+
+                InternalHttpClient _client = new InternalHttpClient();
+                CustomerService _customer = new CustomerService();
+
+                string url = System.Web.Configuration.WebConfigurationManager.AppSettings["StatisticsAPI"] + 4;
+                string chargeBoxIds = GetStatisticChargeBoxIds(request.ChargeBoxIds);
+
+                HttpClientService service = new HttpClientService();
+
+                Dictionary<string, string> postData = new Dictionary<string, string>()
+                {
+                  { "ChargeBoxId", chargeBoxIds },
+                  { "StartDate",request.DateFrom.ToString(EVCBConfiguration.DATETIMEFORMAT)},
+                  { "EndDate",request.DateTo.ToString(EVCBConfiguration.DATETIMEFORMAT)}
+
+                };
+                var _innerresult = await service.PostFormDataAsync(url, postData, null);
+
+
+                if (_innerresult.StatusCode == HttpStatusCode.OK)
+                {
+                    _innerresult.Response = _innerresult.Response.Replace("item", "Title");
+                    _innerresult.Response = _innerresult.Response.Replace("data", "DeliveredEnergy");
+                    result.Data = _innerresult.Response;
+                    result.StatusCode = (int)CPO_StatusCode.Success;
+                    result.StatusMessage = CPO_StatusMessage.Success;
+                    statusCode = HttpStatusCode.OK;
+                }
+                else
+                {
+                    result.StatusCode = (int)CPO_StatusCode.CANT_FOUND_DATA;
+                    result.StatusMessage = CPO_StatusMessage.ERROR_MSG_INNERSERVICE_ERROR;
+                    statusCode = HttpStatusCode.BadRequest;
+                }
+            }
+            catch (Exception ex)
+            {
+                result.ErrorDetail = ex.ToString();
+                result.StatusMessage = CPO_StatusMessage.ERROR_MSG_UNEXPECTEDERROR;
+                result.StatusCode = (int)CPO_StatusCode.UnexpectedError;
+                return Request.CreateResponse(statusCode, result);
+            }
+
+            return Request.CreateResponse(statusCode, result);
+        }
+
+        [Route("statistics/sessions")]
+        [ResponseType(typeof(CPOOuterResponse))]
+        [HttpPost]
+        async public Task<HttpResponseMessage> Sessions([FromBody] StatisticsRequest request)
+        {
+            var result = new CPOOuterResponse();
+            HttpStatusCode statusCode = HttpStatusCode.InternalServerError;
+            var _innerData = new { Result = CommandResponseType.Rejected.ToString(), Timeout = 60 };
+            try
+            {
+
+                InternalHttpClient _client = new InternalHttpClient();
+                CustomerService _customer = new CustomerService();
+
+                string url = System.Web.Configuration.WebConfigurationManager.AppSettings["StatisticsAPI"] + 6;
+                string chargeBoxIds = GetStatisticChargeBoxIds(request.ChargeBoxIds);
+
+                HttpClientService service = new HttpClientService();
+
+                Dictionary<string, string> postData = new Dictionary<string, string>()
+                {
+                  { "ChargeBoxId", chargeBoxIds },
+                  { "StartDate",request.DateFrom.ToString(EVCBConfiguration.DATETIMEFORMAT)},
+                  { "EndDate",request.DateTo.ToString(EVCBConfiguration.DATETIMEFORMAT)}
+
+                };
+                var _innerresult = await service.PostFormDataAsync(url, postData, null);
+
+
+                if (_innerresult.StatusCode == HttpStatusCode.OK)
+                {
+                    string titles = "\"Title\":[\"ChargeBox Id\",\"Connector Id\",\"Session Id\",\"DateFrom\",\"DateTo\",\"Duration(sec)\",\"Energy(kWh)\",\"Stop Reason\"],";
+
+                    _innerresult.Response = _innerresult.Response.Replace("data", "Session");
+                    _innerresult.Response = _innerresult.Response.Insert(1, titles);
+                    result.Data = _innerresult.Response;
+                    result.StatusCode = (int)CPO_StatusCode.Success;
+                    result.StatusMessage = CPO_StatusMessage.Success;
+                    statusCode = HttpStatusCode.OK;
+                }
+                else
+                {
+                    result.StatusCode = (int)CPO_StatusCode.CANT_FOUND_DATA;
+                    result.StatusMessage = CPO_StatusMessage.ERROR_MSG_INNERSERVICE_ERROR;
+                    statusCode = HttpStatusCode.BadRequest;
+                }
+            }
+            catch (Exception ex)
+            {
+                result.ErrorDetail = ex.ToString();
+                result.StatusMessage = CPO_StatusMessage.ERROR_MSG_UNEXPECTEDERROR;
+                result.StatusCode = (int)CPO_StatusCode.UnexpectedError;
+                return Request.CreateResponse(statusCode, result);
+            }
+
+            return Request.CreateResponse(statusCode, result);
+        }
+
+        [Route("statistics/fault")]
+        [ResponseType(typeof(CPOOuterResponse))]
+        [HttpPost]
+        async public Task<HttpResponseMessage> Fault([FromBody] StatisticsRequest request)
+        {
+            var result = new CPOOuterResponse();
+            HttpStatusCode statusCode = HttpStatusCode.InternalServerError;
+            var _innerData = new { Result = CommandResponseType.Rejected.ToString(), Timeout = 60 };
+            try
+            {
+
+                InternalHttpClient _client = new InternalHttpClient();
+                CustomerService _customer = new CustomerService();
+
+                string url = System.Web.Configuration.WebConfigurationManager.AppSettings["StatisticsAPI"] + 5;
+                string chargeBoxIds = GetStatisticChargeBoxIds(request.ChargeBoxIds);
+
+                HttpClientService service = new HttpClientService();
+
+                Dictionary<string, string> postData = new Dictionary<string, string>()
+                {
+                  { "ChargeBoxId", chargeBoxIds},
+                  { "StartDate",request.DateFrom.ToString(EVCBConfiguration.DATETIMEFORMAT)},
+                  { "EndDate",request.DateTo.ToString(EVCBConfiguration.DATETIMEFORMAT)}
+
+                };
+                var _innerresult = await service.PostFormDataAsync(url, postData, null);
+
+
+                if (_innerresult.StatusCode == HttpStatusCode.OK)
+                {
+                    _innerresult.Response = _innerresult.Response.Replace("item", "Title");
+                    _innerresult.Response = _innerresult.Response.Replace("data", "Count");
+                    _innerresult.Response = _innerresult.Response.Replace("data2", "CumulativePercentage");
+                    result.Data = _innerresult.Response;
+                    result.StatusCode = (int)CPO_StatusCode.Success;
+                    result.StatusMessage = CPO_StatusMessage.Success;
+                    statusCode = HttpStatusCode.OK;
+                }
+                else
+                {
+                    result.StatusCode = (int)CPO_StatusCode.CANT_FOUND_DATA;
+                    result.StatusMessage = CPO_StatusMessage.ERROR_MSG_INNERSERVICE_ERROR;
+                    statusCode = HttpStatusCode.BadRequest;
+                }
+            }
+            catch (Exception ex)
+            {
+                result.ErrorDetail = ex.ToString();
+                result.StatusMessage = CPO_StatusMessage.ERROR_MSG_UNEXPECTEDERROR;
+                result.StatusCode = (int)CPO_StatusCode.UnexpectedError;
+                return Request.CreateResponse(statusCode, result);
+            }
+
+            return Request.CreateResponse(statusCode, result);
+        }
+
+        #region CDFA
+        [Route("commands/defaulprice")]
+        [ResponseType(typeof(CPOOuterResponse))]
+        [HttpPost]
+        async public Task<HttpResponseMessage> ChargePointDefaultPrice(string ChargeBoxId, [FromBody] ChargePointDefaultPriceRequest request)
+        {
+            var result = new CPOOuterResponse();
+            HttpStatusCode statusCode = HttpStatusCode.InternalServerError;
+            var _innerData = new { Result = CommandResponseType.Rejected.ToString(), Timeout = 60 };
+            try
+            {
+                string _CustomerId = string.Empty;
+
+                if (!ContainsChargePoint(ChargeBoxId, out _CustomerId))
+                {
+                    // 沒槍~ 沒得充...                   
+                    result.StatusMessage = CPO_StatusMessage.ERROR_MSG_CHARGEBOXID_DOESNT_EXIST;
+                    result.StatusCode = (int)CPO_StatusCode.CHARGEBOXID_ISNT_EXIST_OR_OFFLINE;
+                    result.Data = JsonConvert.SerializeObject(_innerData, EVCBConfiguration.JSONSERIALIZER_FORMAT);
+                    statusCode = HttpStatusCode.BadRequest;
+                    return Request.CreateResponse(statusCode, result);
+                }
+
+
+                ChargePoint16Service chargePointService = new ChargePoint16Service();
+
+                if (!chargePointService.IsOnline(ChargeBoxId))
+                {
+
+                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Code = 2101, Message = EVCBConfiguration.ERROR_MSG_CHARGEBOXID_ISNT_EXIST_OR_OFFLINE });
+                }
+                //create reqest
+                var _request = new DataTransferRequest()
+                {
+                    messageId = "DefaultPrice",
+                    vendorId = "Phihong Technology",
+                    data = request.DefaultPrice
+                };
+
+                string uuid = Guid.NewGuid().ToString();
+                if (!AddCommandtoServer(ChargeBoxId, uuid, _request))
+                {
+                    throw new Exception("Write Command Fail!!");
+                }
+
+                result.SerialNo = uuid;
+                result.Data = JsonConvert.SerializeObject(new { Result = CommandResponseType.Accepted.ToString(), Timeout = 60 });
+                await Task.Delay(10);
+
+            }
+            catch (Exception ex)
+            {
+                result.Data = JsonConvert.SerializeObject(_innerData);
+                result.ErrorDetail = ex.ToString();
+                result.StatusMessage = CPO_StatusMessage.ERROR_MSG_UNEXPECTEDERROR;
+                result.StatusCode = (int)CPO_StatusCode.UnexpectedError;
+                return Request.CreateResponse(statusCode, result);
+            }
+
+            return Request.CreateResponse(statusCode, result);
+        }
+
+
+        [Route("commands/userprice")]
+        [ResponseType(typeof(CPOOuterResponse))]
+        [HttpPost]
+        async public Task<HttpResponseMessage> UserPrice(string ChargeBoxId, [FromBody] UserPriceRequest request)
+        {
+            var result = new CPOOuterResponse();
+            HttpStatusCode statusCode = HttpStatusCode.InternalServerError;
+            var _innerData = new { Result = CommandResponseType.Rejected.ToString(), Timeout = 60 };
+            try
+            {
+                string _CustomerId = string.Empty;
+
+                if (!ContainsChargePoint(ChargeBoxId, out _CustomerId))
+                {
+                    // 沒槍~ 沒得充...                   
+                    result.StatusMessage = CPO_StatusMessage.ERROR_MSG_CHARGEBOXID_DOESNT_EXIST;
+                    result.StatusCode = (int)CPO_StatusCode.CHARGEBOXID_ISNT_EXIST_OR_OFFLINE;
+                    result.Data = JsonConvert.SerializeObject(_innerData, EVCBConfiguration.JSONSERIALIZER_FORMAT);
+                    statusCode = HttpStatusCode.BadRequest;
+                    return Request.CreateResponse(statusCode, result);
+                }
+
+
+                ChargePoint16Service chargePointService = new ChargePoint16Service();
+
+                if (!chargePointService.IsOnline(ChargeBoxId))
+                {
+
+                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Code = 2101, Message = EVCBConfiguration.ERROR_MSG_CHARGEBOXID_ISNT_EXIST_OR_OFFLINE });
+                }
+                //create reqest
+                var _request = new DataTransferRequest()
+                {
+                    messageId = "SetUserPrice",
+                    vendorId = "Phihong Technology",
+                    data = JsonConvert.SerializeObject(request)
+                };
+
+                string uuid = Guid.NewGuid().ToString();
+                if (!AddCommandtoServer(ChargeBoxId, uuid, _request))
+                {
+                    throw new Exception("Write Command Fail!!");
+                }
+
+                result.SerialNo = uuid;
+                result.Data = JsonConvert.SerializeObject(new { Result = CommandResponseType.Accepted.ToString(), Timeout = 60 });
+                await Task.Delay(10);
+
+            }
+            catch (Exception ex)
+            {
+                result.Data = JsonConvert.SerializeObject(_innerData);
+                result.ErrorDetail = ex.ToString();
+                result.StatusMessage = CPO_StatusMessage.ERROR_MSG_UNEXPECTEDERROR;
+                result.StatusCode = (int)CPO_StatusCode.UnexpectedError;
+                return Request.CreateResponse(statusCode, result);
+            }
+
+            return Request.CreateResponse(statusCode, result);
+        }
+
+        [Route("commands/finalcost")]
+        [ResponseType(typeof(CPOOuterResponse))]
+        [HttpPost]
+        async public Task<HttpResponseMessage> FinalCost(string ChargeBoxId, [FromBody] FinalCostRequest request)
+        {
+            var result = new CPOOuterResponse();
+            HttpStatusCode statusCode = HttpStatusCode.InternalServerError;
+            var _innerData = new { Result = CommandResponseType.Rejected.ToString(), Timeout = 60 };
+            try
+            {
+                string _CustomerId = string.Empty;
+
+                if (!ContainsChargePoint(ChargeBoxId, out _CustomerId))
+                {
+                    // 沒槍~ 沒得充...                   
+                    result.StatusMessage = CPO_StatusMessage.ERROR_MSG_CHARGEBOXID_DOESNT_EXIST;
+                    result.StatusCode = (int)CPO_StatusCode.CHARGEBOXID_ISNT_EXIST_OR_OFFLINE;
+                    result.Data = JsonConvert.SerializeObject(_innerData, EVCBConfiguration.JSONSERIALIZER_FORMAT);
+                    statusCode = HttpStatusCode.BadRequest;
+                    return Request.CreateResponse(statusCode, result);
+                }
+
+
+                ChargePoint16Service chargePointService = new ChargePoint16Service();
+
+                if (!chargePointService.IsOnline(ChargeBoxId))
+                {
+
+                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Code = 2101, Message = EVCBConfiguration.ERROR_MSG_CHARGEBOXID_ISNT_EXIST_OR_OFFLINE });
+                }
+
+                string text = JsonConvert.SerializeObject(request).Replace("SessionId", "txId");
+                //create reqest
+                var _request = new DataTransferRequest()
+                {
+                    messageId = "DefaultPrice",
+                    vendorId = "Phihong Technology",
+                    data = text
+                };
+
+                string uuid = Guid.NewGuid().ToString();
+                if (!AddCommandtoServer(ChargeBoxId, uuid, _request))
+                {
+                    throw new Exception("Write Command Fail!!");
+                }
+
+                result.SerialNo = uuid;
+                result.Data = JsonConvert.SerializeObject(new { Result = CommandResponseType.Accepted.ToString(), Timeout = 60 });
+                await Task.Delay(10);
+
+            }
+            catch (Exception ex)
+            {
+                result.Data = JsonConvert.SerializeObject(_innerData);
+                result.ErrorDetail = ex.ToString();
+                result.StatusMessage = CPO_StatusMessage.ERROR_MSG_UNEXPECTEDERROR;
+                result.StatusCode = (int)CPO_StatusCode.UnexpectedError;
+                return Request.CreateResponse(statusCode, result);
+            }
+
+            return Request.CreateResponse(statusCode, result);
+        }
+        #endregion
+
+
+        private bool AddCommandtoServer(string chargeBoxId, string uuid, IRequest request)
+        {
+            bool result = false;
+            try
+            {
+                ServerTriggerService service = new ServerTriggerService();
+                service.AddMessage(chargeBoxId, uuid, request);
+                result = true;
+            }
+            catch (Exception ex)
+            {
+                ;
+            }
+
+            return result;
+        }
+
+        private string GetStatisticChargeBoxIds(List<string> chargeBoxIds)
+        {
+            string result = JsonConvert.SerializeObject(chargeBoxIds, Formatting.None).Replace("\"", "'");
+            result = result.Replace("[", "");
+            result = result.Replace("]", "");
+
+            return result;
+        }
+
+
+        private CPOOuterResponse GetErrorDescription(InternalHttpResult innerResponse)
+        {
+            CPOOuterResponse result = new CPOOuterResponse();
+
+            result.ErrorDetail = innerResponse.Exception == null ? null : innerResponse.Exception.ToString();
+
+            if (innerResponse.Status != HttpStatusCode.Accepted)
+            {
+                switch (innerResponse.ErrorCode)
+                {
+                    #region Authorization
+                    case 2000:
+                        {
+                            result.StatusCode = innerResponse.ErrorCode;
+                            result.StatusMessage = string.Format("{0}-{1}", "InnerService", "Authorize Unexpected Error");
+                            result.ErrorDetail = result.StatusMessage;
+                        }
+                        break;
+                    case 2001:
+                    case 2002:
+                    case 2003:
+                        {
+                            result.StatusCode = innerResponse.ErrorCode;
+                            result.StatusMessage = string.Format("{0}-{1}", "InnerService", innerResponse.Message);
+                        }
+                        break;
+
+                    #endregion
+                    case 2100:
+                    case 2101:
+                    case 2102:
+                    case 2103:
+                    case 2104:
+                    case 2105:
+                    case 2106:
+                        {
+                            result.StatusCode = innerResponse.ErrorCode;
+                            result.StatusMessage = innerResponse.Message;
+                        }
+                        break;
+                    case 2999:
+                        {
+                            result.StatusCode = innerResponse.ErrorCode;
+                            result.StatusMessage = string.Format("{0}-{1}", "InnerService", "Unexpected Error");
+                            result.ErrorDetail = result.StatusMessage;
+                        }
+                        break;
+                    default:
+                        {
+                            result.StatusCode = 2998;
+                            result.StatusMessage = CPO_StatusMessage.ERROR_MSG_CANT_FIND_ERRORCODE;
+                        }
+                        break;
+                }
+            }
+
+            return result;
+
+
+        }
+
+
+
+
+    }
+}

+ 1335 - 0
EVCB_OCPP.WEBAPI/Controllers/Version2/ocpp16/OCPP16_InternalController.cs

@@ -0,0 +1,1335 @@
+using EVCB_OCPP.Packet.Messages;
+using EVCB_OCPP.Packet.Messages.Core;
+using EVCB_OCPP.Packet.Messages.FirmwareManagement;
+using EVCB_OCPP.Packet.Messages.LocalAuthListManagement;
+using EVCB_OCPP.Packet.Messages.RemoteTrigger;
+using EVCB_OCPP.Packet.Messages.Reservation;
+using EVCB_OCPP.Packet.Messages.SmartCharging;
+using EVCB_OCPP.Packet.Messages.SubTypes;
+using EVCB_OCPP.WEBAPI.Handlers;
+using EVCB_OCPP.WEBAPI.Models.WebAPI;
+using EVCB_OCPP.WEBAPI.Services;
+using EVCB_OCPP.WEBAPI.Services.Integration;
+using Newtonsoft.Json;
+using Newtonsoft.Json.Linq;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Linq;
+using System.Net;
+using System.Net.Http;
+using System.Web.Http;
+using System.Web.Http.Description;
+using Internal_Actions = EVCB_OCPP.WEBAPI.Services.Integration.Internal_Actions;
+using ServerTriggerService = EVCB_OCPP.WEBAPI.Services.Integration.ServerTriggerService;
+using StartTransactionRequest = EVCB_OCPP.WEBAPI.Models.WebAPI.StartTransactionRequest;
+
+namespace EVCB_OCPP.WEBAPI.Controllers.Version2.ocpp16
+{
+    [ApiExplorerSettings(IgnoreApi = false)]
+    [RoutePrefix("api/v2/ocpp16")]
+    [InernalAuthentication]
+    public class OCPP16_InternalController : ApiController
+    {
+
+        [Route("command")]
+        [ResponseType(typeof(ErrorResponse))]
+        [ResponseType(typeof(InternalGenericResponse))]
+        [HttpGet]
+        public HttpResponseMessage CommandofExecution(int OrderNo, string SerialNo, string ChargeBoxId)
+        {
+
+            var result = new InternalGenericResponse();
+            HttpStatusCode statusCode = HttpStatusCode.InternalServerError;
+            try
+            {
+
+                ChargePoint16Service chargePointService = new ChargePoint16Service();
+
+                if (!IsValidEnum<Internal_Actions>(OrderNo) || string.IsNullOrEmpty(ChargeBoxId))
+                {
+                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Code = 2100, Message = EVCBConfiguration.ERROR_MSG_PARAMETER_OUTOFRANGE_INCORRECT });
+                }
+
+                if (!chargePointService.Exists(ChargeBoxId))
+                {
+                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Code = 2101, Message = EVCBConfiguration.ERROR_MSG_CHARGEBOXID_ISNT_EXIST_OR_OFFLINE });
+                }
+
+                ServerTriggerService triggerService = new ServerTriggerService();
+                var excution = triggerService.GetExecution(SerialNo, (Internal_Actions)OrderNo, ChargeBoxId);
+
+                if (excution == null)
+                {
+                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Code = 2102, Message = EVCBConfiguration.ERROR_MSG_DATA_NOTFOUND });
+                }
+
+                result.Message = JsonConvert.SerializeObject(excution, EVCBConfiguration.JSONSERIALIZER_FORMAT);
+                statusCode = HttpStatusCode.OK;
+
+            }
+            catch (Exception ex)
+            {
+
+                return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse()
+                {
+                    Code = 2999,
+                    Message = EVCBConfiguration.ERROR_MSG_UNEXPECTEDERROR,
+                    ErrorDetail = string.Format(EVCBConfiguration.ERRORMESSAGE_FORMAT, "CommandofExecution", ex.ToString())
+                });
+            }
+
+            return Request.CreateResponse(statusCode, result);
+        }
+
+        [Route("availability")]
+        [ResponseType(typeof(ErrorResponse))]
+        [ResponseType(typeof(InternalGenericResponse))]
+        [HttpPut]
+        public HttpResponseMessage Availability(string ChargeBoxId, [FromBody]AvailiabilityRequest Availiability)
+        {
+            string uuid = Guid.NewGuid().ToString();
+            var result = new InternalGenericResponse();
+            HttpStatusCode statusCode = HttpStatusCode.InternalServerError;
+            try
+            {
+
+                ChargePoint16Service chargePointService = new ChargePoint16Service();
+
+                if (!chargePointService.IsOnline(ChargeBoxId))
+                {
+
+                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Code = 2101, Message = EVCBConfiguration.ERROR_MSG_CHARGEBOXID_ISNT_EXIST_OR_OFFLINE });
+                }
+
+                //check parameter
+                if (Availiability == null ||
+                    !(Availiability.ConnectorId >= 0) ||
+                    !(Availiability.AvailabilityType > 0 && Availiability.AvailabilityType < 3))
+                {
+
+                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Code = 2100, Message = EVCBConfiguration.ERROR_MSG_PARAMETER_OUTOFRANGE_INCORRECT });
+                }
+
+                //create reqest
+
+                var request = new ChangeAvailabilityRequest()
+                {
+                    connectorId = Availiability.ConnectorId,
+                    type = (EVCB_OCPP.Packet.Messages.SubTypes.AvailabilityType)Availiability.AvailabilityType
+                };
+
+
+                if (!AddCommandtoServer(ChargeBoxId, uuid, request))
+                {
+                    throw new Exception("Write Command Fail!!");
+                }
+
+                statusCode = HttpStatusCode.OK;
+                result.SerialNo = uuid;
+
+            }
+            catch (Exception ex)
+            {
+
+                return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse()
+                {
+                    Code = 2999,
+                    Message = EVCBConfiguration.ERROR_MSG_UNEXPECTEDERROR,
+                    ErrorDetail = string.Format(EVCBConfiguration.ERRORMESSAGE_FORMAT, "Availability", ex.ToString())
+
+                });
+            }
+
+            return Request.CreateResponse(statusCode, result);
+        }
+
+
+        [Route("configuration")]
+        [ResponseType(typeof(ErrorResponse))]
+        [ResponseType(typeof(InternalGenericResponse))]
+        [HttpPut]
+        public HttpResponseMessage ChargeBoxConfiguration(string ChargeBoxId, [FromBody]SingleConfigurationRequest SingleConfiguration)
+        {
+            string uuid = Guid.NewGuid().ToString();
+            var result = new InternalGenericResponse();
+            HttpStatusCode statusCode = HttpStatusCode.InternalServerError;
+            try
+            {
+                //Does charge exist ? 
+                ChargePoint16Service chargePointService = new ChargePoint16Service();
+
+
+                if (!chargePointService.IsOnline(ChargeBoxId))
+                {
+
+                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Code = 2101, Message = EVCBConfiguration.ERROR_MSG_CHARGEBOXID_ISNT_EXIST_OR_OFFLINE });
+                }
+
+                //check parameter
+                if (SingleConfiguration == null ||
+                    (string.IsNullOrEmpty(SingleConfiguration.Key) || string.IsNullOrEmpty(SingleConfiguration.Value)))
+                {
+
+                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Code = 2100, Message = EVCBConfiguration.ERROR_MSG_PARAMETER_OUTOFRANGE_INCORRECT });
+                }
+
+                //create reqest
+                var request = new ChangeConfigurationRequest()
+                {
+                    key = SingleConfiguration.Key,
+                    value = SingleConfiguration.Value
+                };
+
+
+                if (!AddCommandtoServer(ChargeBoxId, uuid, request))
+                {
+                    throw new Exception("Write Command Fail!!");
+                }
+
+                statusCode = HttpStatusCode.OK;
+                result.SerialNo = uuid;
+            }
+            catch (Exception ex)
+            {
+
+                return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse()
+                {
+                    Code = 2999,
+                    Message = EVCBConfiguration.ERROR_MSG_UNEXPECTEDERROR,
+                    ErrorDetail = string.Format(EVCBConfiguration.ERRORMESSAGE_FORMAT, "ChangeConfiguration", ex.ToString())
+
+                });
+            }
+
+            return Request.CreateResponse(statusCode, result);
+        }
+
+        [Route("configuration")]
+        [ResponseType(typeof(ErrorResponse))]
+        [ResponseType(typeof(InternalGenericResponse))]
+        [HttpGet]
+        public HttpResponseMessage ChargeBoxConfiguration(string ChargeBoxId, string Keys)
+        {
+            string uuid = Guid.NewGuid().ToString();
+            var result = new InternalGenericResponse();
+            HttpStatusCode statusCode = HttpStatusCode.InternalServerError;
+            try
+            {
+
+                //Does charge exist ? 
+                ChargePoint16Service chargePointService = new ChargePoint16Service();
+
+                if (!chargePointService.IsOnline(ChargeBoxId))
+                {
+
+                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Code = 2101, Message = EVCBConfiguration.ERROR_MSG_CHARGEBOXID_ISNT_EXIST_OR_OFFLINE });
+                }
+
+                //check parameter
+                if (string.IsNullOrEmpty(Keys) || Keys.Split('/').Count() > 20)
+                {
+
+                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Code = 2100, Message = EVCBConfiguration.ERROR_MSG_PARAMETER_OUTOFRANGE_INCORRECT });
+                }
+
+                //create reqest
+                var request = new GetConfigurationRequest()
+                {
+                    key = Keys.Split('/').ToList()
+                };
+
+
+                if (!AddCommandtoServer(ChargeBoxId, uuid, request))
+                {
+                    throw new Exception("Write Command Fail!!");
+                }
+
+                statusCode = HttpStatusCode.OK;
+                result.SerialNo = uuid;
+            }
+            catch (Exception ex)
+            {
+
+                return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse()
+                {
+                    Code = 2999,
+                    Message = EVCBConfiguration.ERROR_MSG_UNEXPECTEDERROR,
+                    ErrorDetail = string.Format(EVCBConfiguration.ERRORMESSAGE_FORMAT, "GetConfiguration", ex.ToString())
+
+                });
+            }
+
+            return Request.CreateResponse(statusCode, result);
+        }
+
+        [Route("diagnostics")]
+        [ResponseType(typeof(ErrorResponse))]
+        [ResponseType(typeof(InternalGenericResponse))]
+        [HttpGet]
+        public HttpResponseMessage Diagnostics(string ChargeBoxId, Uri Location, int Retries = -1, int RetryInterval = -1, string StartTime = null, string StopTime = null)
+        {
+            string uuid = Guid.NewGuid().ToString();
+            var result = new InternalGenericResponse();
+            HttpStatusCode statusCode = HttpStatusCode.InternalServerError;
+            try
+            {
+                //Does charge exist ? 
+                ChargePoint16Service chargePointService = new ChargePoint16Service();
+
+
+                if (!chargePointService.IsOnline(ChargeBoxId))
+                {
+
+                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Code = 2101, Message = EVCBConfiguration.ERROR_MSG_CHARGEBOXID_ISNT_EXIST_OR_OFFLINE });
+                }
+
+                //check parameter
+                DateTime vaildtime = new DateTime();
+                if (!Location.IsWellFormedOriginalString()
+                    || (!string.IsNullOrEmpty(StartTime) && !DateTime.TryParse(StartTime, out vaildtime))
+                    || (!string.IsNullOrEmpty(StopTime) && !DateTime.TryParse(StopTime, out vaildtime)))
+                {
+
+                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Code = 2100, Message = EVCBConfiguration.ERROR_MSG_PARAMETER_OUTOFRANGE_INCORRECT });
+                }
+
+                //create reqest
+                var request = new GetDiagnosticsRequest()
+                {
+                    location = Location,
+                    retries = Retries == -1 ? (int?)null : Retries,
+                    retryInterval = RetryInterval == -1 ? (int?)null : RetryInterval,
+                    startTime = StartTime == null ? (DateTime?)null : DateTime.SpecifyKind(DateTime.Parse(StartTime), DateTimeKind.Utc),
+                    stopTime = StopTime == null ? (DateTime?)null : DateTime.SpecifyKind(DateTime.Parse(StopTime), DateTimeKind.Utc)
+
+                };
+
+                if (!AddCommandtoServer(ChargeBoxId, uuid, request))
+                {
+                    throw new Exception("Write Command Fail!!");
+                }
+
+                statusCode = HttpStatusCode.OK;
+                result.SerialNo = uuid;
+
+            }
+            catch (Exception ex)
+            {
+
+                return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse()
+                {
+                    Code = 2999,
+                    Message = EVCBConfiguration.ERROR_MSG_UNEXPECTEDERROR,
+                    ErrorDetail = string.Format(EVCBConfiguration.ERRORMESSAGE_FORMAT, "GetDiagonostics", ex.ToString())
+
+                });
+            }
+
+            return Request.CreateResponse(statusCode, result);
+        }
+
+
+        [Route("locallistversion")]
+        [ResponseType(typeof(ErrorResponse))]
+        [ResponseType(typeof(InternalGenericResponse))]
+        [HttpGet]
+        public HttpResponseMessage Locallistversion(string ChargeBoxId)
+        {
+            string uuid = Guid.NewGuid().ToString();
+            var result = new InternalGenericResponse();
+            HttpStatusCode statusCode = HttpStatusCode.InternalServerError;
+            try
+            {
+
+                ChargePoint16Service chargePointService = new ChargePoint16Service();
+
+                if (!chargePointService.IsOnline(ChargeBoxId))
+                {
+
+                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Code = 2101, Message = EVCBConfiguration.ERROR_MSG_CHARGEBOXID_ISNT_EXIST_OR_OFFLINE });
+                }
+
+                if (!AddCommandtoServer(ChargeBoxId, uuid, new GetLocalListVersionRequest()))
+                {
+                    throw new Exception("Write Command Fail!!");
+                }
+
+                statusCode = HttpStatusCode.OK;
+                result.SerialNo = uuid;
+
+            }
+            catch (Exception ex)
+            {
+                return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse()
+                {
+                    Code = 2999,
+                    Message = EVCBConfiguration.ERROR_MSG_UNEXPECTEDERROR,
+                    ErrorDetail = string.Format(EVCBConfiguration.ERRORMESSAGE_FORMAT, "GetLocallistversion", ex.ToString())
+
+                });
+
+
+            }
+
+            return Request.CreateResponse(statusCode, result);
+        }
+
+        [Route("transaction")]
+        [ResponseType(typeof(ErrorResponse))]
+        [ResponseType(typeof(InternalGenericResponse))]
+        [HttpPost]
+        public HttpResponseMessage StartTransaction(string ChargeBoxId, [FromBody]StartTransactionRequest StartTransaction)
+        {
+            string uuid = Guid.NewGuid().ToString();
+            var result = new InternalGenericResponse();
+            HttpStatusCode statusCode = HttpStatusCode.InternalServerError;
+            try
+            {
+                ChargePoint16Service chargePointService = new ChargePoint16Service();
+
+                if (!chargePointService.IsOnline(ChargeBoxId))
+                {
+
+                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Code = 2101, Message = EVCBConfiguration.ERROR_MSG_CHARGEBOXID_ISNT_EXIST_OR_OFFLINE });
+                }
+
+                //check parameter
+
+
+                if (StartTransaction == null || !StartTransaction.ConnectorId.HasValue
+                    || (StartTransaction.ConnectorId.HasValue && (chargePointService.GetNumberofConnectors(ChargeBoxId) < StartTransaction.ConnectorId || StartTransaction.ConnectorId < 0)) || string.IsNullOrEmpty(StartTransaction.IdTag) || StartTransaction.IdTag.Length > 20)
+                {
+                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Code = 2100, Message = EVCBConfiguration.ERROR_MSG_PARAMETER_OUTOFRANGE_INCORRECT });
+                }
+
+                if (StartTransaction.ChargingProfile != null)
+                {
+                    bool isvaild = true;
+                    if (!IsValidEnum<ChargingProfileKindType>((int)StartTransaction.ChargingProfile.chargingProfileKind))
+                    {
+                        isvaild = false;
+                    }
+                    else if (StartTransaction.ChargingProfile.recurrencyKind.HasValue && !IsValidEnum<RecurrencyKindType>((int)StartTransaction.ChargingProfile.recurrencyKind))
+                    {
+                        isvaild = false;
+                    }
+                    else if (StartTransaction.ChargingProfile.chargingSchedule != null && !IsValidEnum<ChargingRateUnitType>((int)StartTransaction.ChargingProfile.chargingSchedule.chargingRateUnit))
+                    {
+                        isvaild = false;
+                    }
+                    else
+                    {
+
+                        //do nothing
+                    }
+                    if (!isvaild)
+                    {
+                        return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Code = 2100, Message = EVCBConfiguration.ERROR_MSG_PARAMETER_OUTOFRANGE_INCORRECT });
+
+                    }
+
+                }
+
+                var currentStatus = chargePointService.GetChargePointCurrentSatus(ChargeBoxId, StartTransaction.ConnectorId.Value).Value;
+
+                if (StartTransaction.ConnectorId.HasValue && chargePointService.GetChargePointCurrentSatus(ChargeBoxId, StartTransaction.ConnectorId.Value).HasValue &&
+                    (currentStatus != ChargePointStatus.Available && currentStatus != ChargePointStatus.Reserved && currentStatus != ChargePointStatus.Preparing ))
+                {
+                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Code = 2103, Message = EVCBConfiguration.ERROR_MSG_CONNECTOR_ISNOT_AVAILIABLE_MODE });
+                }
+                else
+                {
+                    var _request = new RemoteStartTransactionRequest()
+                    {
+                        connectorId = StartTransaction.ConnectorId,
+                        idTag = StartTransaction.IdTag,
+                        chargingProfile = StartTransaction.ChargingProfile == null ? null :
+                         new csChargingProfiles()
+                         {
+                             chargingProfileId = StartTransaction.ChargingProfile.chargingProfileId,
+                             stackLevel = StartTransaction.ChargingProfile.stackLevel,
+                             chargingProfilePurpose = ChargingProfilePurposeType.TxProfile,
+                             chargingProfileKind = StartTransaction.ChargingProfile.chargingProfileKind,
+                             recurrencyKind = StartTransaction.ChargingProfile.recurrencyKind,
+                             validFrom = StartTransaction.ChargingProfile.validFrom == null ? (DateTime?)null : DateTime.SpecifyKind(StartTransaction.ChargingProfile.validFrom.Value, DateTimeKind.Utc),
+                             validTo = StartTransaction.ChargingProfile.validTo == null ? (DateTime?)null : DateTime.SpecifyKind(StartTransaction.ChargingProfile.validTo.Value, DateTimeKind.Utc),
+                             chargingSchedule = new ChargingSchedule()
+                             {
+                                 chargingRateUnit = StartTransaction.ChargingProfile.chargingSchedule.chargingRateUnit,
+                                 chargingSchedulePeriod = StartTransaction.ChargingProfile.chargingSchedule.chargingSchedulePeriod,
+                                 duration = StartTransaction.ChargingProfile.chargingSchedule.duration,
+                                 minChargingRate = StartTransaction.ChargingProfile.chargingSchedule.minChargingRate,
+                                 startSchedule = StartTransaction.ChargingProfile.chargingSchedule.startSchedule == null ? (DateTime?)null : DateTime.SpecifyKind(StartTransaction.ChargingProfile.chargingSchedule.startSchedule.Value, DateTimeKind.Utc)
+                             }
+                         }
+
+                    };
+
+
+                    if (!AddCommandtoServer(ChargeBoxId, uuid, _request))
+                    {
+                        throw new Exception("Write Command Fail!!");
+                    }
+                }
+
+                statusCode = HttpStatusCode.OK;
+                result.SerialNo = uuid;
+
+            }
+            catch (Exception ex)
+            {
+                return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse()
+                {
+                    Code = 2999,
+                    Message = EVCBConfiguration.ERROR_MSG_UNEXPECTEDERROR,
+                    ErrorDetail = string.Format(EVCBConfiguration.ERRORMESSAGE_FORMAT, "StartTransaction", ex.ToString())
+
+                });
+
+            }
+
+            return Request.CreateResponse(statusCode, result);
+        }
+
+        [Route("transaction")]
+        [ResponseType(typeof(ErrorResponse))]
+        [ResponseType(typeof(InternalGenericResponse))]
+        [HttpPut]
+        public HttpResponseMessage StopTransaction(string ChargeBoxId, int TransactionId)
+        {
+            string uuid = Guid.NewGuid().ToString();
+            var result = new InternalGenericResponse();
+            HttpStatusCode statusCode = HttpStatusCode.InternalServerError;
+            try
+            {
+                ChargePoint16Service chargePointService = new ChargePoint16Service();
+
+                if (!chargePointService.IsOnline(ChargeBoxId))
+                {
+
+                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Code = 2101, Message = EVCBConfiguration.ERROR_MSG_CHARGEBOXID_ISNT_EXIST_OR_OFFLINE });
+                }
+
+                var _ConnectorId = chargePointService.GetConnectorwithOngoingTransaction(ChargeBoxId, TransactionId);
+
+                if (_ConnectorId == -1)
+                {
+                    // 充完電 & 這個充電序不存在
+                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Code = 2106, Message = EVCBConfiguration.ERROR_MSG_TX_FINISHED_OR_NOTFOUND });
+                }
+
+                var _ConnectorStatus = chargePointService.GetChargePointCurrentSatus(ChargeBoxId, _ConnectorId);
+
+                if (!(_ConnectorStatus.HasValue && _ConnectorStatus == ChargePointStatus.Charging || _ConnectorStatus == ChargePointStatus.SuspendedEVSE || _ConnectorStatus == ChargePointStatus.SuspendedEV))
+                {
+
+                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Code = 2105, Message = EVCBConfiguration.ERROR_MSG_CONNECTOR_ISNOT_CHARGING_MODE });
+                }
+                else
+                {
+                    if (chargePointService.IsTransactionRunning(ChargeBoxId, TransactionId))
+                    {
+                        var _request = new RemoteStopTransactionRequest()
+                        {
+                            transactionId = TransactionId
+                        };
+
+                        //下發停止
+                        if (!AddCommandtoServer(ChargeBoxId, uuid, _request))
+                        {
+                            throw new Exception("Write Command Fail!!");
+                        }
+                    }
+                    else
+                    {
+                        return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Code = 2104, Message = EVCBConfiguration.ERROR_MSG_SESSION_WAS_FINISHED });
+                    }
+                }
+
+                statusCode = HttpStatusCode.OK;
+                result.SerialNo = uuid;
+                return Request.CreateResponse(statusCode, result);
+
+            }
+            catch (Exception ex)
+            {
+                return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse()
+                {
+                    Code = 2999,
+                    Message = EVCBConfiguration.ERROR_MSG_UNEXPECTEDERROR,
+                    ErrorDetail = string.Format(EVCBConfiguration.ERRORMESSAGE_FORMAT, "StopTransaction", ex.ToString())
+
+                });
+
+
+            }
+
+
+        }
+
+        [Route("reservation")]
+        [ResponseType(typeof(ErrorResponse))]
+        [ResponseType(typeof(InternalGenericResponse))]
+        [HttpPost]
+        public HttpResponseMessage ReserveNow(string ChargeBoxId, [FromBody] ReserveRequest ReserveNow)
+        {
+            string uuid = Guid.NewGuid().ToString();
+            var result = new InternalGenericResponse();
+            HttpStatusCode statusCode = HttpStatusCode.InternalServerError;
+            try
+            {
+                ChargePoint16Service chargePointService = new ChargePoint16Service();
+
+                if (!chargePointService.IsOnline(ChargeBoxId))
+                {
+                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Code = 2101, Message = EVCBConfiguration.ERROR_MSG_CHARGEBOXID_ISNT_EXIST_OR_OFFLINE });
+                }
+
+
+                DateTime expiryDate = new DateTime();
+                //check parameter
+                if (ReserveNow == null ||
+                    !(ReserveNow.ConnectorId >= 0) ||
+                    string.IsNullOrEmpty(ReserveNow.IdTag) ||
+                    ReserveNow.ReservationId == -1 ||
+                    !DateTime.TryParse(ReserveNow.ExpiryDate, out expiryDate))
+                {
+
+                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Code = 2100, Message = EVCBConfiguration.ERROR_MSG_PARAMETER_OUTOFRANGE_INCORRECT });
+                }
+
+                expiryDate = DateTime.SpecifyKind(DateTime.Parse(ReserveNow.ExpiryDate), DateTimeKind.Utc);
+
+                if (DateTime.Compare(DateTime.UtcNow, expiryDate) >= 0)
+                {
+                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Code = 2100, Message = EVCBConfiguration.ERROR_MSG_PARAMETER_OUTOFRANGE_INCORRECT });
+                }
+
+                var connectorStatus = chargePointService.GetChargePointCurrentSatus(ChargeBoxId, ReserveNow.ConnectorId);
+
+                if (connectorStatus.HasValue && (connectorStatus.Value == ChargePointStatus.Available || connectorStatus.Value == ChargePointStatus.Preparing))
+                {
+                    //create reqest
+
+                    var request = new ReserveNowRequest()
+                    {
+                        connectorId = ReserveNow.ConnectorId,
+                        expiryDate = expiryDate,
+                        idTag = ReserveNow.IdTag,
+                        reservationId = ReserveNow.ReservationId,
+                        parentIdTag = ReserveNow.ParentIdTag
+
+                    };
+
+
+                    if (!AddCommandtoServer(ChargeBoxId, uuid, request))
+                    {
+                        throw new Exception("Write Command Fail!!");
+                    }
+
+                    statusCode = HttpStatusCode.OK;
+                    result.SerialNo = uuid;
+                }
+                else
+                {
+                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Code = 2103, Message = EVCBConfiguration.ERROR_MSG_CONNECTOR_ISNOT_AVAILIABLE_MODE });
+                }
+
+
+
+            }
+            catch (Exception ex)
+            {
+                return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse()
+                {
+                    Code = 2999,
+                    Message = EVCBConfiguration.ERROR_MSG_UNEXPECTEDERROR,
+                    ErrorDetail = string.Format(EVCBConfiguration.ERRORMESSAGE_FORMAT, "ReserveNow", ex.ToString())
+
+                });
+
+
+
+            }
+
+            return Request.CreateResponse(statusCode, result);
+        }
+
+        [Route("reservation")]
+        [ResponseType(typeof(ErrorResponse))]
+        [ResponseType(typeof(InternalGenericResponse))]
+        [HttpDelete]
+        public HttpResponseMessage CancelResrvation(string ChargeBoxId, int ReservationId)
+        {
+            string uuid = Guid.NewGuid().ToString();
+            var result = new InternalGenericResponse();
+            HttpStatusCode statusCode = HttpStatusCode.InternalServerError;
+            try
+            {
+                ChargePoint16Service chargePointService = new ChargePoint16Service();
+
+                if (!chargePointService.IsOnline(ChargeBoxId))
+                {
+
+                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Code = 2101, Message = EVCBConfiguration.ERROR_MSG_CHARGEBOXID_ISNT_EXIST_OR_OFFLINE });
+                }
+
+                var connectorStatus = chargePointService.GetChargePointCurrentSatus(ChargeBoxId, 0);
+
+                if (connectorStatus.HasValue && connectorStatus.Value == ChargePointStatus.Available)
+                {
+                    //create reqest
+
+                    var request = new CancelReservationRequest()
+                    {
+                        reservationId = ReservationId
+
+                    };
+
+                    if (!AddCommandtoServer(ChargeBoxId, uuid, request))
+                    {
+                        throw new Exception("Write Command Fail!!");
+                    }
+
+                    statusCode = HttpStatusCode.OK;
+                    result.SerialNo = uuid;
+                }
+                else
+                {
+                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Code = 2103, Message = EVCBConfiguration.ERROR_MSG_CONNECTOR_ISNOT_AVAILIABLE_MODE });
+                }
+
+
+            }
+            catch (Exception ex)
+            {
+                return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse()
+                {
+                    Code = 2999,
+                    Message = EVCBConfiguration.ERROR_MSG_UNEXPECTEDERROR,
+                    ErrorDetail = string.Format(EVCBConfiguration.ERRORMESSAGE_FORMAT, "CancelResrvation", ex.ToString())
+
+                });
+
+            }
+
+            return Request.CreateResponse(statusCode, result);
+        }
+
+        [Route("reset")]
+        [ResponseType(typeof(ErrorResponse))]
+        [ResponseType(typeof(InternalGenericResponse))]
+        [HttpPost]
+        public HttpResponseMessage Reset(string ChargeBoxId, int ResetType)
+        {
+            string uuid = Guid.NewGuid().ToString();
+            var result = new InternalGenericResponse();
+            HttpStatusCode statusCode = HttpStatusCode.InternalServerError;
+            try
+            {
+                ChargePoint16Service chargePointService = new ChargePoint16Service();
+
+                if (!chargePointService.IsOnline(ChargeBoxId))
+                {
+
+                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Code = 2101, Message = EVCBConfiguration.ERROR_MSG_CHARGEBOXID_ISNT_EXIST_OR_OFFLINE });
+                }
+
+                var connectorStatus = chargePointService.GetChargePointCurrentSatus(ChargeBoxId, 0);
+
+                if (connectorStatus.HasValue && connectorStatus.Value == ChargePointStatus.Available)
+                {
+                    //create reqest
+
+                    var request = new ResetRequest()
+                    {
+                        type = (Packet.Messages.SubTypes.ResetType)ResetType
+
+                    };
+
+                    if (!AddCommandtoServer(ChargeBoxId, uuid, request))
+                    {
+                        throw new Exception("Write Command Fail!!");
+                    }
+
+                    statusCode = HttpStatusCode.OK;
+                    result.SerialNo = uuid;
+                }
+                else
+                {
+                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Code = 2103, Message = EVCBConfiguration.ERROR_MSG_CONNECTOR_ISNOT_AVAILIABLE_MODE });
+                }
+
+
+            }
+            catch (Exception ex)
+            {
+                return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse()
+                {
+                    Code = 2999,
+                    Message = EVCBConfiguration.ERROR_MSG_UNEXPECTEDERROR,
+                    ErrorDetail = string.Format(EVCBConfiguration.ERRORMESSAGE_FORMAT, "Reset", ex.ToString())
+
+                });
+
+            }
+
+            return Request.CreateResponse(statusCode, result);
+        }
+
+        [Route("locallist")]
+        [ResponseType(typeof(ErrorResponse))]
+        [ResponseType(typeof(InternalGenericResponse))]
+        [HttpPost]
+        public HttpResponseMessage SendLocalList(string ChargeBoxId, [FromBody]LocalListRequest LocalList)
+        {
+            string uuid = Guid.NewGuid().ToString();
+            var result = new InternalGenericResponse();
+            HttpStatusCode statusCode = HttpStatusCode.InternalServerError;
+            try
+            {
+                ChargePoint16Service chargePointService = new ChargePoint16Service();
+
+                if (!chargePointService.IsOnline(ChargeBoxId))
+                {
+
+                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Code = 2101, Message = EVCBConfiguration.ERROR_MSG_CHARGEBOXID_ISNT_EXIST_OR_OFFLINE });
+                }
+
+                //check parameter
+                if (LocalList == null ||
+                    !IsValidEnum<UpdateType>((int)LocalList.UpdateType) || LocalList.LocalAuthorizationList == null
+                    || (LocalList.LocalAuthorizationList != null && LocalList.LocalAuthorizationList.Count == 0))
+                {
+
+                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Code = 2100, Message = EVCBConfiguration.ERROR_MSG_PARAMETER_OUTOFRANGE_INCORRECT });
+                }
+
+                bool badRequest = false;
+                List<AuthorizationData> localAuthorizationList = new List<AuthorizationData>();
+                for (int i = 0; i < LocalList.LocalAuthorizationList.Count; i++)
+                {
+                    if (string.IsNullOrEmpty(LocalList.LocalAuthorizationList[i].IdTag))
+                        badRequest = true;
+
+                    if (LocalList.LocalAuthorizationList[i].IdTagInfo != null && !IsValidEnum<AuthorizationStatus>((int)LocalList.LocalAuthorizationList[i].IdTagInfo.Status))
+                        badRequest = true;
+
+                    if (badRequest)
+                    {
+                        return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Code = 2100, Message = EVCBConfiguration.ERROR_MSG_PARAMETER_OUTOFRANGE_INCORRECT });
+                    }
+                    localAuthorizationList.Add(new AuthorizationData()
+                    {
+                        idTag = LocalList.LocalAuthorizationList[i].IdTag,
+                        idTagInfo = LocalList.LocalAuthorizationList[i].IdTagInfo == null ? null :
+                              new IdTagInfo()
+                              {
+                                  expiryDate = LocalList.LocalAuthorizationList[i].IdTagInfo.ExpiryDate,
+                                  parentIdTag = LocalList.LocalAuthorizationList[i].IdTagInfo.ParentIdTag,
+                                  status = (AuthorizationStatus)LocalList.LocalAuthorizationList[i].IdTagInfo.Status
+                              }
+                    });
+                }
+
+                var request = new SendLocalListRequest()
+                {
+                    listVersion = LocalList.ListVersion,
+                    updateType = (UpdateType)LocalList.UpdateType,
+                    localAuthorizationList = localAuthorizationList
+
+                };
+
+                if (!AddCommandtoServer(ChargeBoxId, uuid, request))
+                {
+                    throw new Exception("Write Command Fail!!");
+                }
+
+                statusCode = HttpStatusCode.OK;
+                result.SerialNo = uuid;
+            }
+            catch (Exception ex)
+            {
+                return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse()
+                {
+                    Code = 2999,
+                    Message = EVCBConfiguration.ERROR_MSG_UNEXPECTEDERROR,
+                    ErrorDetail = string.Format(EVCBConfiguration.ERRORMESSAGE_FORMAT, "SendLocalList", ex.ToString())
+
+                });
+
+            }
+
+            return Request.CreateResponse(statusCode, result);
+        }
+
+        [Route("datatransfer")]
+        [ResponseType(typeof(ErrorResponse))]
+        [ResponseType(typeof(InternalGenericResponse))]
+        [HttpPost]
+        public HttpResponseMessage SendDataTransfer(string ChargeBoxId, string VenderId, [FromBody]string Data, string MessageId = "")
+        {
+            string uuid = Guid.NewGuid().ToString();
+            var result = new InternalGenericResponse();
+            HttpStatusCode statusCode = HttpStatusCode.InternalServerError;
+            try
+            {
+                if (string.IsNullOrEmpty(ChargeBoxId) || string.IsNullOrEmpty(VenderId))
+                {
+                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Code = 2100, Message = EVCBConfiguration.ERROR_MSG_PARAMETER_OUTOFRANGE_INCORRECT });
+                }
+                ChargePoint16Service chargePointService = new ChargePoint16Service();
+
+                if (!chargePointService.IsOnline(ChargeBoxId))
+                {
+                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Code = 2101, Message = EVCBConfiguration.ERROR_MSG_CHARGEBOXID_ISNT_EXIST_OR_OFFLINE });
+                }
+
+                var request = new DataTransferRequest()
+                {
+                    data = Data,
+                    messageId = MessageId,
+                    vendorId = VenderId
+                };
+
+                if (!AddCommandtoServer(ChargeBoxId, uuid, request))
+                {
+                    throw new Exception("Write Command Fail!!");
+                }
+
+
+                statusCode = HttpStatusCode.OK;
+                result.SerialNo = uuid;
+            }
+            catch (Exception ex)
+            {
+                return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse()
+                {
+                    Code = 2999,
+                    Message = EVCBConfiguration.ERROR_MSG_UNEXPECTEDERROR,
+                    ErrorDetail = string.Format(EVCBConfiguration.ERRORMESSAGE_FORMAT, "SendDataTransfer", ex.ToString())
+
+                });
+
+            }
+
+            return Request.CreateResponse(statusCode, result);
+        }
+
+
+        [Route("cache")]
+        [ResponseType(typeof(ErrorResponse))]
+        [ResponseType(typeof(InternalGenericResponse))]
+        [HttpDelete]
+        public HttpResponseMessage ClearCache(string ChargeBoxId)
+        {
+            string uuid = Guid.NewGuid().ToString();
+            var result = new InternalGenericResponse();
+            HttpStatusCode statusCode = HttpStatusCode.InternalServerError;
+            try
+            {
+                ChargePoint16Service chargePointService = new ChargePoint16Service();
+
+                if (!chargePointService.IsOnline(ChargeBoxId))
+                {
+
+                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Code = 2101, Message = EVCBConfiguration.ERROR_MSG_CHARGEBOXID_ISNT_EXIST_OR_OFFLINE });
+                }
+
+                var connectorStatus = chargePointService.GetChargePointCurrentSatus(ChargeBoxId, 0);
+
+                if (connectorStatus.HasValue && connectorStatus.Value == ChargePointStatus.Available)
+                {
+
+                    if (!AddCommandtoServer(ChargeBoxId, uuid, new ClearCacheRequest()))
+                    {
+                        throw new Exception("Write Command Fail!!");
+                    }
+
+                    statusCode = HttpStatusCode.OK;
+                    result.SerialNo = uuid;
+                }
+                else
+                {
+                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Code = 2103, Message = EVCBConfiguration.ERROR_MSG_CONNECTOR_ISNOT_AVAILIABLE_MODE });
+                }
+
+
+            }
+            catch (Exception ex)
+            {
+                return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse()
+                {
+                    Code = 2999,
+                    Message = EVCBConfiguration.ERROR_MSG_UNEXPECTEDERROR,
+                    ErrorDetail = string.Format(EVCBConfiguration.ERRORMESSAGE_FORMAT, "ClearCache", ex.ToString())
+
+                });
+
+            }
+
+            return Request.CreateResponse(statusCode, result);
+        }
+
+        [Route("chargingprofile")]
+        [ResponseType(typeof(ErrorResponse))]
+        [ResponseType(typeof(InternalGenericResponse))]
+        [HttpPost]
+        public HttpResponseMessage SetChargingProfile(string ChargeBoxId, [FromBody]ChargingProfileRequest ChargingProfile)
+        {
+
+
+            string uuid = Guid.NewGuid().ToString();
+            var result = new InternalGenericResponse();
+            HttpStatusCode statusCode = HttpStatusCode.InternalServerError;
+            try
+            {
+                ChargePoint16Service chargePointService = new ChargePoint16Service();
+
+                if (!chargePointService.IsOnline(ChargeBoxId))
+                {
+
+                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Code = 2101, Message = EVCBConfiguration.ERROR_MSG_CHARGEBOXID_ISNT_EXIST_OR_OFFLINE });
+                }
+
+                //check parameter
+                if (ChargingProfile == null ||
+                    ChargingProfile.connectorId < 0 ||
+                  !(ChargingProfile.ChargingProfile != null && IsValidEnum<ChargingProfileKindType>((int)ChargingProfile.ChargingProfile.chargingProfileKind)) ||
+                  !(ChargingProfile.ChargingProfile != null && ChargingProfile.ChargingProfile.recurrencyKind.HasValue && IsValidEnum<RecurrencyKindType>((int)ChargingProfile.ChargingProfile.recurrencyKind)) ||
+                  !(ChargingProfile.ChargingProfile != null && ChargingProfile.ChargingProfile.recurrencyKind.HasValue && IsValidEnum<RecurrencyKindType>((int)ChargingProfile.ChargingProfile.recurrencyKind)) ||
+                  !(ChargingProfile.ChargingProfile != null && IsValidEnum<ChargingProfilePurposeType>((int)ChargingProfile.ChargingProfile.chargingProfilePurpose)) ||
+                  !(ChargingProfile.ChargingProfile != null && ChargingProfile.ChargingProfile.chargingSchedule != null && IsValidEnum<ChargingRateUnitType>((int)ChargingProfile.ChargingProfile.chargingSchedule.chargingRateUnit)))
+                {
+                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Code = 2100, Message = EVCBConfiguration.ERROR_MSG_PARAMETER_OUTOFRANGE_INCORRECT });
+                }
+
+                if (ChargingProfile.ChargingProfile.chargingSchedule.chargingSchedulePeriod.Count == 0)
+                {
+                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Code = 2100, Message = EVCBConfiguration.ERROR_MSG_PARAMETER_OUTOFRANGE_INCORRECT });
+                }
+
+                var request = new SetChargingProfileRequest()
+                {
+                    connectorId = ChargingProfile.connectorId,
+                    csChargingProfiles = new csChargingProfiles()
+                    {
+                        chargingProfileId = ChargingProfile.ChargingProfile.chargingProfileId,
+                        chargingProfileKind = ChargingProfile.ChargingProfile.chargingProfileKind,
+                        chargingProfilePurpose = ChargingProfile.ChargingProfile.chargingProfilePurpose,
+                        recurrencyKind = ChargingProfile.ChargingProfile.recurrencyKind,
+                        stackLevel = ChargingProfile.ChargingProfile.stackLevel,
+                        transactionId = ChargingProfile.ChargingProfile.TransactionId,
+                        validFrom = ChargingProfile.ChargingProfile.validFrom == null ? (DateTime?)null : DateTime.SpecifyKind(ChargingProfile.ChargingProfile.validFrom.Value, DateTimeKind.Utc),
+                        validTo = ChargingProfile.ChargingProfile.validTo == null ? (DateTime?)null : DateTime.SpecifyKind(ChargingProfile.ChargingProfile.validTo.Value, DateTimeKind.Utc),
+                        chargingSchedule = new ChargingSchedule()
+                        {
+                            chargingRateUnit = ChargingProfile.ChargingProfile.chargingSchedule.chargingRateUnit,
+                            chargingSchedulePeriod = ChargingProfile.ChargingProfile.chargingSchedule.chargingSchedulePeriod,
+                            duration = ChargingProfile.ChargingProfile.chargingSchedule.duration,
+                            minChargingRate = ChargingProfile.ChargingProfile.chargingSchedule.minChargingRate,
+                            startSchedule = ChargingProfile.ChargingProfile.chargingSchedule.startSchedule == null ? (DateTime?)null : DateTime.SpecifyKind(ChargingProfile.ChargingProfile.chargingSchedule.startSchedule.Value, DateTimeKind.Utc)
+                        }
+                    }
+                };
+
+
+                if (!AddCommandtoServer(ChargeBoxId, uuid, request))
+                {
+                    throw new Exception("Write Command Fail!!");
+                }
+
+
+                statusCode = HttpStatusCode.OK;
+                result.SerialNo = uuid;
+
+            }
+            catch (Exception ex)
+            {
+
+                return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse()
+                {
+                    Code = 2999,
+                    Message = EVCBConfiguration.ERROR_MSG_UNEXPECTEDERROR,
+                    ErrorDetail = string.Format(EVCBConfiguration.ERRORMESSAGE_FORMAT, "SetChargingProfile", ex.ToString())
+
+                });
+            }
+
+            return Request.CreateResponse(statusCode, result);
+        }
+
+        [Route("chargingprofile")]
+        [ResponseType(typeof(ErrorResponse))]
+        [ResponseType(typeof(InternalGenericResponse))]
+        [HttpDelete]
+        public HttpResponseMessage ClearChargingProfile(string ChargeBoxId, int Id = -1, int ConnectorId = -1, int ChargingProfilePurpose = -1, int StackLevel = -1)
+        {
+            string uuid = Guid.NewGuid().ToString();
+            var result = new InternalGenericResponse();
+            HttpStatusCode statusCode = HttpStatusCode.InternalServerError;
+            try
+            {
+                ChargePoint16Service chargePointService = new ChargePoint16Service();
+
+                if (!chargePointService.IsOnline(ChargeBoxId))
+                {
+
+                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Code = 2101, Message = EVCBConfiguration.ERROR_MSG_CHARGEBOXID_ISNT_EXIST_OR_OFFLINE });
+                }
+
+                var connectorStatus = chargePointService.GetChargePointCurrentSatus(ChargeBoxId, 0);
+
+                if (connectorStatus.HasValue && connectorStatus.Value == ChargePointStatus.Available)
+                {
+
+                    var request = new ClearChargingProfileRequest()
+                    {
+                        chargingProfilePurpose = ChargingProfilePurpose == -1 ? (ChargingProfilePurposeType?)null : (ChargingProfilePurposeType)ChargingProfilePurpose,
+                        connectorId = ConnectorId == -1 ? (int?)null : (int)ConnectorId,
+                        id = Id == -1 ? (int?)null : (int)ChargingProfilePurpose,
+                        stackLevel = StackLevel == -1 ? (int?)null : (int)StackLevel
+                    };
+
+                    if (!AddCommandtoServer(ChargeBoxId, uuid, request))
+                    {
+                        throw new Exception("Write Command Fail!!");
+                    }
+
+                    statusCode = HttpStatusCode.OK;
+                    result.SerialNo = uuid;
+                }
+                else
+                {
+                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Code = 2103, Message = EVCBConfiguration.ERROR_MSG_CONNECTOR_ISNOT_AVAILIABLE_MODE });
+                }
+
+
+            }
+            catch (Exception ex)
+            {
+
+
+                return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse()
+                {
+                    Code = 2999,
+                    Message = EVCBConfiguration.ERROR_MSG_UNEXPECTEDERROR,
+                    ErrorDetail = string.Format(EVCBConfiguration.ERRORMESSAGE_FORMAT, "ClearChargingProfile", ex.ToString())
+
+                });
+            }
+
+            return Request.CreateResponse(statusCode, result);
+        }
+
+        [Route("trigger")]
+        [ResponseType(typeof(ErrorResponse))]
+        [ResponseType(typeof(InternalGenericResponse))]
+        [HttpPost]
+        public HttpResponseMessage TriggerMessage(string ChargeBoxId, [FromBody] TriggerRequest triggerMessage)
+        {
+            string uuid = Guid.NewGuid().ToString();
+            var result = new InternalGenericResponse();
+            HttpStatusCode statusCode = HttpStatusCode.InternalServerError;
+            try
+            {
+                ChargePoint16Service chargePointService = new ChargePoint16Service();
+
+                if (!chargePointService.IsOnline(ChargeBoxId))
+                {
+
+                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Code = 2101, Message = EVCBConfiguration.ERROR_MSG_CHARGEBOXID_ISNT_EXIST_OR_OFFLINE });
+                }
+
+                //check parameter
+                if (triggerMessage == null || !(triggerMessage.TriggerType >= 1 && triggerMessage.TriggerType <= (int)MessageTrigger.StatusNotification))
+                {
+
+                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Code = 2100, Message = EVCBConfiguration.ERROR_MSG_PARAMETER_OUTOFRANGE_INCORRECT });
+                }
+
+                //create reqest
+
+                var request = new TriggerMessageRequest()
+                {
+                    connectorId = triggerMessage.ConnectorId == -1 ? (int?)null : triggerMessage.ConnectorId,
+                    requestedMessage = (MessageTrigger)triggerMessage.TriggerType
+                };
+
+
+                if (!AddCommandtoServer(ChargeBoxId, uuid, request))
+                {
+                    throw new Exception("Write Command Fail!!");
+                }
+
+                statusCode = HttpStatusCode.OK;
+                result.SerialNo = uuid;
+
+            }
+            catch (Exception ex)
+            {
+                return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse()
+                {
+                    Code = 2999,
+                    Message = EVCBConfiguration.ERROR_MSG_UNEXPECTEDERROR,
+                    ErrorDetail = string.Format(EVCBConfiguration.ERRORMESSAGE_FORMAT, "TriggerMessage", ex.ToString())
+
+                });
+
+            }
+
+            return Request.CreateResponse(statusCode, result);
+        }
+
+        [Route("unlockconnector")]
+        [ResponseType(typeof(ErrorResponse))]
+        [ResponseType(typeof(InternalGenericResponse))]
+        [HttpPost]
+        public HttpResponseMessage UnlockConnector(string ChargeBoxId, int ConnectorId)
+        {
+            string uuid = Guid.NewGuid().ToString();
+            var result = new InternalGenericResponse();
+            HttpStatusCode statusCode = HttpStatusCode.InternalServerError;
+            try
+            {
+                ChargePoint16Service chargePointService = new ChargePoint16Service();
+
+                if (!chargePointService.IsOnline(ChargeBoxId))
+                {
+
+                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Code = 2101, Message = EVCBConfiguration.ERROR_MSG_CHARGEBOXID_ISNT_EXIST_OR_OFFLINE });
+                }
+
+                //check parameter
+                if (ConnectorId < 0)
+                {
+
+                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Code = 2100, Message = EVCBConfiguration.ERROR_MSG_PARAMETER_OUTOFRANGE_INCORRECT });
+                }
+
+                //create reqest
+
+                var request = new UnlockConnectorRequest()
+                {
+                    connectorId = ConnectorId
+                };
+
+
+                if (!AddCommandtoServer(ChargeBoxId, uuid, request))
+                {
+                    throw new Exception("Write Command Fail!!");
+                }
+
+                statusCode = HttpStatusCode.OK;
+                result.SerialNo = uuid;
+
+            }
+            catch (Exception ex)
+            {
+                return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse()
+                {
+                    Code = 2999,
+                    Message = EVCBConfiguration.ERROR_MSG_UNEXPECTEDERROR,
+                    ErrorDetail = string.Format(EVCBConfiguration.ERRORMESSAGE_FORMAT, "UnlockConnector", ex.ToString())
+
+                });
+
+
+            }
+
+            return Request.CreateResponse(statusCode, result);
+        }
+
+
+        [Route("compositeschedule")]
+        [ResponseType(typeof(ErrorResponse))]
+        [ResponseType(typeof(InternalGenericResponse))]
+        [HttpGet]
+        public HttpResponseMessage CompositeSchedule(string ChargeBoxId, int ConnectorId, int Duration, int ChargingRateUnit = -1)
+        {
+            string uuid = Guid.NewGuid().ToString();
+            var result = new InternalGenericResponse();
+            HttpStatusCode statusCode = HttpStatusCode.InternalServerError;
+            try
+            {
+
+                ChargePoint16Service chargePointService = new ChargePoint16Service();
+
+                if (!chargePointService.IsOnline(ChargeBoxId))
+                {
+
+                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Code = 2101, Message = EVCBConfiguration.ERROR_MSG_CHARGEBOXID_ISNT_EXIST_OR_OFFLINE });
+                }
+
+                //check parameter
+                if (!(ConnectorId >= 0) || !(Duration > 0))
+                {
+
+                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Code = 2100, Message = EVCBConfiguration.ERROR_MSG_PARAMETER_OUTOFRANGE_INCORRECT });
+                }
+
+                if ((ChargingRateUnit != -1 && (ChargingRateUnit <= 0 || ChargingRateUnit >= 3)))
+                {
+                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Code = 2100, Message = EVCBConfiguration.ERROR_MSG_PARAMETER_OUTOFRANGE_INCORRECT });
+                }
+
+                var request = new GetCompositeScheduleRequest()
+                {
+                    connectorId = ConnectorId,
+                    duration = Duration,
+                    chargingRateUnit = ChargingRateUnit > 0 ? (ChargingRateUnitType)ChargingRateUnit : (ChargingRateUnitType?)null
+                };
+
+                if (!AddCommandtoServer(ChargeBoxId, uuid, request))
+                {
+                    throw new Exception("Write Command Fail!!");
+                }
+
+                statusCode = HttpStatusCode.OK;
+                result.SerialNo = uuid;
+
+            }
+            catch (Exception ex)
+            {
+                return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse()
+                {
+                    Code = 2999,
+                    Message = EVCBConfiguration.ERROR_MSG_UNEXPECTEDERROR,
+                    ErrorDetail = string.Format(EVCBConfiguration.ERRORMESSAGE_FORMAT, "CompositeSchedule", ex.ToString())
+
+                });
+
+            }
+
+            return Request.CreateResponse(statusCode, result);
+        }
+
+
+        private bool AddCommandtoServer(string chargeBoxId, string uuid, IRequest request)
+        {
+            bool result = false;
+            try
+            {
+                ServerTriggerService service = new ServerTriggerService();
+                service.AddMessage(chargeBoxId, uuid, request);
+                result = true;
+            }
+            catch (Exception ex)
+            {
+                ;
+            }
+
+            return result;
+        }
+
+
+        private bool IsValidEnum<TEnum>(int enumValue)
+        {
+
+            return Enum.IsDefined(typeof(TEnum), enumValue);
+
+        }
+
+    }
+}

+ 348 - 0
EVCB_OCPP.WEBAPI/Controllers/Version2/ocpp201/OCPP201_CPOController.cs

@@ -0,0 +1,348 @@
+using Dapper;
+using EVCB_OCPP.Packet.Messages.SubTypes;
+using EVCB_OCPP.WEBAPI.Handlers;
+using EVCB_OCPP.WEBAPI.Models.WebAPI;
+using EVCB_OCPP.WEBAPI.Models.WebAPI.Dto;
+using EVCB_OCPP.WEBAPI.Services;
+using EVCB_OCPP.WEBAPI.Services.Integration;
+using EVCB_OCPP20.Packet.Messages;
+using Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.Configuration;
+using System.Data;
+using System.Data.SqlClient;
+using System.Linq;
+using System.Net;
+using System.Net.Http;
+using System.Threading.Tasks;
+using System.Web.Http;
+using System.Web.Http.Description;
+using CommandType = EVCB_OCPP.WEBAPI.Models.WebAPI.Dto.CommandType;
+using ReserveNowRequest = EVCB_OCPP.WEBAPI.Models.WebAPI.Dto.ReserveNowRequest;
+using ServerTriggerService = EVCB_OCPP.WEBAPI.Services.Integration.ServerTriggerService;
+
+namespace EVCB_OCPP.WEBAPI.Controllers.Version2.ocpp201
+{
+    [ApiExplorerSettings(IgnoreApi = false)]
+    [RoutePrefix("api/v2/cpo201")]
+    [CPOAuthentication]
+    public class OCPP201_CPOController : ApiController
+    {
+        private HttpClientService service = new HttpClientService();
+
+        private bool ContainsChargePoint(string chargeBoxId, out string customerId)
+        {
+            customerId = string.Empty;
+
+            if (!Request.Headers.Contains(EVCBConfiguration.Header_PartnerId)) return false;
+
+            customerId = Request.Headers.GetValues(EVCBConfiguration.Header_PartnerId).First();
+
+            ChargePoint201Service _service = new ChargePoint201Service();
+            return _service.ContainsChargePoint(chargeBoxId, customerId);
+
+        }
+      
+        [Route("commands/chargingprofiles")]
+        [ResponseType(typeof(CPOOuterResponse))]
+        [HttpPut]
+        async public Task<HttpResponseMessage> SetChargingProfile(string ChargeBoxId, [FromBody] ChargingProfileRequest request)
+        {
+            var result = new CPOOuterResponse();
+            HttpStatusCode statusCode = HttpStatusCode.InternalServerError;
+            var _innerData = new { Result = CommandResponseType.Rejected.ToString(), Timeout = 60 };
+            try
+            {
+                string _CustomerId = string.Empty;
+
+                if (!ContainsChargePoint(ChargeBoxId, out _CustomerId))
+                {
+                    // 沒槍~ 沒得充...                   
+                    result.StatusMessage = CPO_StatusMessage.ERROR_MSG_CHARGEBOXID_DOESNT_EXIST;
+                    result.StatusCode = (int)CPO_StatusCode.CHARGEBOXID_ISNT_EXIST_OR_OFFLINE;
+                    result.Data = JsonConvert.SerializeObject(_innerData, EVCBConfiguration.JSONSERIALIZER_FORMAT);
+                    statusCode = HttpStatusCode.BadRequest;
+                    return Request.CreateResponse(statusCode, result);
+                }
+
+
+
+                InternalHttpClient _client = new InternalHttpClient();
+                CustomerService _customer = new CustomerService();
+
+
+                string[] parts = Request.RequestUri.ToString().Split('/');
+
+                string urlformat = "{0}//{1}/api/v1/ocpp20/chargingprofile?ChargeBoxId={2}";
+
+                var _innerResult = await _client.Post(string.Format(urlformat, parts[0], parts[2], ChargeBoxId), new Dictionary<string, string>()
+                        {
+                            { "PartnerId",_CustomerId}
+
+                        }, request, _customer.GetAPIKey(new Guid(_CustomerId)));
+
+
+                _innerData = new { Result = string.IsNullOrEmpty(_innerResult.SerialNo) ? CommandResponseType.Rejected.ToString() : CommandResponseType.Accepted.ToString(), Timeout = 60 };
+                result = GetErrorDescription(_innerResult);
+                result.Data = JsonConvert.SerializeObject(_innerData, EVCBConfiguration.JSONSERIALIZER_FORMAT);
+                if (_innerResult.Success)
+                {
+                    result.SerialNo = _innerResult.SerialNo;
+                    result.StatusCode = (int)CPO_StatusCode.Success;
+                    result.StatusMessage = CPO_StatusMessage.Success;
+                    statusCode = HttpStatusCode.OK;
+                }
+                else
+                {
+
+                    result.StatusCode = _innerResult.ErrorCode;
+                    result.StatusMessage = CPO_StatusMessage.ERROR_MSG_INNERSERVICE_ERROR;
+                    statusCode = HttpStatusCode.BadRequest;
+                }
+                ChargePoint201Service ChargePoint201Service = new ChargePoint201Service();
+
+                if (!ChargePoint201Service.IsOnline(ChargeBoxId))
+                {
+                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Code = 2101, Message = EVCBConfiguration.ERROR_MSG_CHARGEBOXID_ISNT_EXIST_OR_OFFLINE });
+                }
+
+
+            }
+            catch (Exception ex)
+            {
+                result.ErrorDetail = ex.ToString();
+                result.StatusMessage = CPO_StatusMessage.ERROR_MSG_UNEXPECTEDERROR;
+                result.StatusCode = (int)CPO_StatusCode.UnexpectedError;
+                return Request.CreateResponse(statusCode, result);
+            }
+
+            return Request.CreateResponse(statusCode, result);
+        }
+
+
+
+        [Route("commands/chargingprofiles")]
+        [ResponseType(typeof(CPOOuterResponse))]
+        [HttpDelete]
+        async public Task<HttpResponseMessage> ClearChargingPorfile(string ChargeBoxId, int ChargeProfileId = -1)
+        {
+            var result = new CPOOuterResponse();
+            HttpStatusCode statusCode = HttpStatusCode.InternalServerError;
+            var _innerData = new { Result = CommandResponseType.Rejected.ToString(), Timeout = 60 };
+            try
+            {
+                string _CustomerId = string.Empty;
+
+                if (!ContainsChargePoint(ChargeBoxId, out _CustomerId))
+                {
+                    // 沒槍~ 沒得充...                   
+                    result.StatusMessage = CPO_StatusMessage.ERROR_MSG_CHARGEBOXID_DOESNT_EXIST;
+                    result.StatusCode = (int)CPO_StatusCode.CHARGEBOXID_ISNT_EXIST_OR_OFFLINE;
+                    result.Data = JsonConvert.SerializeObject(_innerData, EVCBConfiguration.JSONSERIALIZER_FORMAT);
+                    statusCode = HttpStatusCode.BadRequest;
+                    return Request.CreateResponse(statusCode, result);
+                }
+
+
+                InternalHttpClient _client = new InternalHttpClient();
+                CustomerService _customer = new CustomerService();
+
+
+                string[] parts = Request.RequestUri.ToString().Split('/');
+
+                string urlformat = "{0}//{1}/api/v1/ocpp20/chargingprofile?ChargeBoxId={2}{3}";
+
+                var _innerResult = await _client.Delete(string.Format(urlformat, parts[0], parts[2], ChargeBoxId, ChargeProfileId == -1 ? "" : "&Id=" + ChargeProfileId), new Dictionary<string, string>()
+                        {
+                            { "PartnerId",_CustomerId}
+
+                        }, _customer.GetAPIKey(new Guid(_CustomerId)));
+
+
+                _innerData = new { Result = string.IsNullOrEmpty(_innerResult.SerialNo) ? CommandResponseType.Rejected.ToString() : CommandResponseType.Accepted.ToString(), Timeout = 60 };
+                result = GetErrorDescription(_innerResult);
+                result.Data = JsonConvert.SerializeObject(_innerData, EVCBConfiguration.JSONSERIALIZER_FORMAT);
+                if (_innerResult.Success)
+                {
+                    result.SerialNo = _innerResult.SerialNo;
+                    result.StatusCode = (int)CPO_StatusCode.Success;
+                    result.StatusMessage = CPO_StatusMessage.Success;
+                    statusCode = HttpStatusCode.OK;
+                }
+                else
+                {
+
+                    result.StatusCode = _innerResult.ErrorCode;
+                    result.StatusMessage = CPO_StatusMessage.ERROR_MSG_INNERSERVICE_ERROR;
+                    statusCode = HttpStatusCode.BadRequest;
+                }
+            }
+            catch (Exception ex)
+            {
+                result.ErrorDetail = ex.ToString();
+                result.StatusMessage = CPO_StatusMessage.ERROR_MSG_UNEXPECTEDERROR;
+                result.StatusCode = (int)CPO_StatusCode.UnexpectedError;
+                return Request.CreateResponse(statusCode, result);
+            }
+
+            return Request.CreateResponse(statusCode, result);
+        }
+
+        [Route("commands/max_limit")]
+        [ResponseType(typeof(CPOOuterResponse))]
+        [HttpDelete]
+        async public Task<HttpResponseMessage> SetMaxLimit(string ChargeBoxId, int MaxCharginCurrent = 0, int MaxCharginPower = 0, int MaxChargingEnergy = 0)
+        {
+            var result = new CPOOuterResponse();
+            HttpStatusCode statusCode = HttpStatusCode.InternalServerError;
+            var _innerData = new { Result = CommandResponseType.Rejected.ToString(), Timeout = 60 };
+            try
+            {
+                string _CustomerId = string.Empty;
+
+                if (!ContainsChargePoint(ChargeBoxId, out _CustomerId))
+                {
+                    // 沒槍~ 沒得充...                   
+                    result.StatusMessage = CPO_StatusMessage.ERROR_MSG_CHARGEBOXID_DOESNT_EXIST;
+                    result.StatusCode = (int)CPO_StatusCode.CHARGEBOXID_ISNT_EXIST_OR_OFFLINE;
+                    result.Data = JsonConvert.SerializeObject(_innerData, EVCBConfiguration.JSONSERIALIZER_FORMAT);
+                    statusCode = HttpStatusCode.BadRequest;
+                    return Request.CreateResponse(statusCode, result);
+                }
+
+
+                InternalHttpClient _client = new InternalHttpClient();
+                CustomerService _customer = new CustomerService();
+
+
+                string[] parts = Request.RequestUri.ToString().Split('/');
+
+                string urlformat = "{0}//{1}/api/v1/ocpp20/datatransfer?ChargeBoxId={2}{3}";
+
+                var _innerResult = await _client.Post(string.Format(urlformat, parts[0], parts[2], ChargeBoxId, "&MessageId=ID_CpConfiguration"), new Dictionary<string, string>()
+                        {
+                            { "PartnerId",_CustomerId}
+
+                        }, JsonConvert.SerializeObject(new
+                        {
+                            OfflinePolicy = 0,
+                            OfflineMaxChargeEnergy = 0,
+                            MaxChargingCurrent = MaxCharginCurrent,
+                            MaxChargingDuration = 0,
+                            MaxChargingEnergy = MaxChargingEnergy,
+                            MaxChargingPower = MaxCharginPower,
+
+                        }), _customer.GetAPIKey(new Guid(_CustomerId)));
+
+
+                _innerData = new { Result = string.IsNullOrEmpty(_innerResult.SerialNo) ? CommandResponseType.Rejected.ToString() : CommandResponseType.Accepted.ToString(), Timeout = 60 };
+                result = GetErrorDescription(_innerResult);
+                result.Data = JsonConvert.SerializeObject(_innerData, EVCBConfiguration.JSONSERIALIZER_FORMAT);
+                if (_innerResult.Success)
+                {
+                    result.SerialNo = _innerResult.SerialNo;
+                    result.StatusCode = (int)CPO_StatusCode.Success;
+                    result.StatusMessage = CPO_StatusMessage.Success;
+                    statusCode = HttpStatusCode.OK;
+                }
+                else
+                {
+
+                    result.StatusCode = _innerResult.ErrorCode;
+                    result.StatusMessage = CPO_StatusMessage.ERROR_MSG_INNERSERVICE_ERROR;
+                    statusCode = HttpStatusCode.BadRequest;
+                }
+            }
+            catch (Exception ex)
+            {
+                result.ErrorDetail = ex.ToString();
+                result.StatusMessage = CPO_StatusMessage.ERROR_MSG_UNEXPECTEDERROR;
+                result.StatusCode = (int)CPO_StatusCode.UnexpectedError;
+                return Request.CreateResponse(statusCode, result);
+            }
+
+            return Request.CreateResponse(statusCode, result);
+        }
+         
+        private bool AddCommandtoServer(string chargeBoxId, string uuid, IRequest request)
+        {
+            bool result = false;
+            try
+            {
+                ServerTriggerService service = new ServerTriggerService();
+                service.AddMessage(chargeBoxId, uuid, request);
+                result = true;
+            }
+            catch (Exception ex)
+            {
+                ;
+            }
+
+            return result;
+        }
+
+
+        private CPOOuterResponse GetErrorDescription(InternalHttpResult innerResponse)
+        {
+            CPOOuterResponse result = new CPOOuterResponse();
+
+            result.ErrorDetail = innerResponse.Exception == null ? null : innerResponse.Exception.ToString();
+
+            if (innerResponse.Status != HttpStatusCode.Accepted)
+            {
+                switch (innerResponse.ErrorCode)
+                {
+                    #region Authorization
+                    case 2000:
+                        {
+                            result.StatusCode = innerResponse.ErrorCode;
+                            result.StatusMessage = string.Format("{0}-{1}", "InnerService", "Authorize Unexpected Error");
+                            result.ErrorDetail = result.StatusMessage;
+                        }
+                        break;
+                    case 2001:
+                    case 2002:
+                    case 2003:
+                        {
+                            result.StatusCode = innerResponse.ErrorCode;
+                            result.StatusMessage = string.Format("{0}-{1}", "InnerService", innerResponse.Message);
+                        }
+                        break;
+
+                    #endregion
+                    case 2100:
+                    case 2101:
+                    case 2102:
+                    case 2103:
+                    case 2104:
+                    case 2105:
+                    case 2106:
+                        {
+                            result.StatusCode = innerResponse.ErrorCode;
+                            result.StatusMessage = innerResponse.Message;
+                        }
+                        break;
+                    case 2999:
+                        {
+                            result.StatusCode = innerResponse.ErrorCode;
+                            result.StatusMessage = string.Format("{0}-{1}", "InnerService", "Unexpected Error");
+                            result.ErrorDetail = result.StatusMessage;
+                        }
+                        break;
+                    default:
+                        {
+                            result.StatusCode = 2998;
+                            result.StatusMessage = CPO_StatusMessage.ERROR_MSG_CANT_FIND_ERRORCODE;
+                        }
+                        break;
+                }
+            }
+
+            return result;
+
+
+        }
+
+    }
+}

+ 1229 - 0
EVCB_OCPP.WEBAPI/Controllers/Version2/ocpp201/OCPP201_InternalController.cs

@@ -0,0 +1,1229 @@
+using EVCB_OCPP20.Packet.Messages;
+using EVCB_OCPP.WEBAPI.Handlers;
+using EVCB_OCPP.WEBAPI.Models.WebAPI;
+using EVCB_OCPP.WEBAPI.Services.Integration;
+using Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Net;
+using System.Net.Http;
+using System.Web.Http;
+using System.Web.Http.Description;
+using StartTransactionRequest = EVCB_OCPP.WEBAPI.Models.WebAPI.StartTransactionRequest;
+using EVCB_OCPP20.Packet.DataTypes;
+using EVCB_OCPP20.Packet.DataTypes.EnumTypes;
+using EVCB_OCPP.Packet.Messages.SubTypes;
+
+namespace EVCB_OCPP.WEBAPI.Controllers.Version2.ocpp201
+{
+    [ApiExplorerSettings(IgnoreApi = false)]
+    [RoutePrefix("api/v2/ocpp20")]
+    [InernalAuthentication]
+    public class OCPP201_InternalController : ApiController
+    {
+        [Route("command")]
+        [ResponseType(typeof(ErrorResponse))]
+        [ResponseType(typeof(InternalGenericResponse))]
+        [HttpGet]
+        public HttpResponseMessage CommandofExecution(int OrderNo, string SerialNo, string ChargeBoxId)
+        {
+
+            var result = new InternalGenericResponse();
+            HttpStatusCode statusCode = HttpStatusCode.InternalServerError;
+            try
+            {
+
+                ChargePoint201Service ChargePoint201Service = new ChargePoint201Service();
+
+                if (!IsValidEnum<Internal_Actions>(OrderNo) || string.IsNullOrEmpty(ChargeBoxId))
+                {
+                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Code = 2100, Message = EVCBConfiguration.ERROR_MSG_PARAMETER_OUTOFRANGE_INCORRECT });
+                }
+
+                if (!ChargePoint201Service.Exists(ChargeBoxId))
+                {
+                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Code = 2101, Message = EVCBConfiguration.ERROR_MSG_CHARGEBOXID_ISNT_EXIST_OR_OFFLINE });
+                }
+
+                ServerTriggerService triggerService = new ServerTriggerService();
+                var excution = triggerService.GetExecution_ocpp201(SerialNo, (Internal_Actions)OrderNo, ChargeBoxId);
+
+                if (excution == null)
+                {
+                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Code = 2102, Message = EVCBConfiguration.ERROR_MSG_DATA_NOTFOUND });
+                }
+
+                result.Message = JsonConvert.SerializeObject(excution, EVCBConfiguration.JSONSERIALIZER_FORMAT);
+                statusCode = HttpStatusCode.OK;
+
+            }
+            catch (Exception ex)
+            {
+
+                return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse()
+                {
+                    Code = 2999,
+                    Message = EVCBConfiguration.ERROR_MSG_UNEXPECTEDERROR,
+                    ErrorDetail = string.Format(EVCBConfiguration.ERRORMESSAGE_FORMAT, "CommandofExecution", ex.ToString())
+                });
+            }
+
+            return Request.CreateResponse(statusCode, result);
+        }
+
+        [Route("availability")]
+        [ResponseType(typeof(ErrorResponse))]
+        [ResponseType(typeof(InternalGenericResponse))]
+        [HttpPut]
+        public HttpResponseMessage Availability(string ChargeBoxId, [FromBody] AvailiabilityRequest Availiability)
+        {
+            string uuid = Guid.NewGuid().ToString();
+            var result = new InternalGenericResponse();
+            HttpStatusCode statusCode = HttpStatusCode.InternalServerError;
+            try
+            {
+
+                ChargePoint201Service ChargePoint201Service = new ChargePoint201Service();
+
+                if (!ChargePoint201Service.IsOnline(ChargeBoxId))
+                {
+
+                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Code = 2101, Message = EVCBConfiguration.ERROR_MSG_CHARGEBOXID_ISNT_EXIST_OR_OFFLINE });
+                }
+
+                //check parameter
+                if (Availiability == null ||
+                    !(Availiability.ConnectorId >= 0) ||
+                    !(Availiability.AvailabilityType > 0 && Availiability.AvailabilityType < 3))
+                {
+
+                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Code = 2100, Message = EVCBConfiguration.ERROR_MSG_PARAMETER_OUTOFRANGE_INCORRECT });
+                }
+
+                //create reqest
+
+                var request = new ChangeAvailabilityRequest()
+                {
+                    Evse = Availiability.ConnectorId == 0 ? null : new EVSEType() { ConnectorId = Availiability.ConnectorId, Id = Availiability.ConnectorId },
+                    OperationalStatus = (EVCB_OCPP20.Packet.DataTypes.EnumTypes.OperationalStatusEnumType)Availiability.AvailabilityType
+
+                };
+
+
+                if (!AddCommandtoServer(ChargeBoxId, uuid, request))
+                {
+                    throw new Exception("Write Command Fail!!");
+                }
+
+                statusCode = HttpStatusCode.OK;
+                result.SerialNo = uuid;
+
+            }
+            catch (Exception ex)
+            {
+
+                return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse()
+                {
+                    Code = 2999,
+                    Message = EVCBConfiguration.ERROR_MSG_UNEXPECTEDERROR,
+                    ErrorDetail = string.Format(EVCBConfiguration.ERRORMESSAGE_FORMAT, "Availability", ex.ToString())
+
+                });
+            }
+
+            return Request.CreateResponse(statusCode, result);
+        }
+
+
+
+
+        [Route("diagnostics")]
+        [ResponseType(typeof(ErrorResponse))]
+        [ResponseType(typeof(InternalGenericResponse))]
+        [HttpGet]
+        public HttpResponseMessage Diagnostics(string ChargeBoxId, Uri Location, int Retries = -1, int RetryInterval = -1, string StartTime = null, string StopTime = null)
+        {
+            string uuid = Guid.NewGuid().ToString();
+            var result = new InternalGenericResponse();
+            HttpStatusCode statusCode = HttpStatusCode.InternalServerError;
+            try
+            {
+                //Does charge exist ? 
+                ChargePoint201Service ChargePoint201Service = new ChargePoint201Service();
+
+
+                if (!ChargePoint201Service.IsOnline(ChargeBoxId))
+                {
+
+                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Code = 2101, Message = EVCBConfiguration.ERROR_MSG_CHARGEBOXID_ISNT_EXIST_OR_OFFLINE });
+                }
+
+                //check parameter
+                DateTime vaildtime = new DateTime();
+                if (!Location.IsWellFormedOriginalString()
+                    || (!string.IsNullOrEmpty(StartTime) && !DateTime.TryParse(StartTime, out vaildtime))
+                    || (!string.IsNullOrEmpty(StopTime) && !DateTime.TryParse(StopTime, out vaildtime)))
+                {
+
+                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Code = 2100, Message = EVCBConfiguration.ERROR_MSG_PARAMETER_OUTOFRANGE_INCORRECT });
+                }
+
+                //create reqest
+                var request = new GetLogRequest()
+                {
+                    Log = new EVCB_OCPP20.Packet.DataTypes.LogParametersType()
+                    {
+                        RemoteLocation = Location.ToString(),
+                        OldestTimestamp = StartTime == null ? (DateTime?)null : DateTime.SpecifyKind(DateTime.Parse(StartTime), DateTimeKind.Utc),
+                        LatestTimestamp = StopTime == null ? (DateTime?)null : DateTime.SpecifyKind(DateTime.Parse(StopTime), DateTimeKind.Utc)
+                    },
+                    Retries = Retries == -1 ? (int?)null : Retries,
+                    RetryInterval = RetryInterval == -1 ? (int?)null : RetryInterval,
+
+                };
+
+                if (!AddCommandtoServer(ChargeBoxId, uuid, request))
+                {
+                    throw new Exception("Write Command Fail!!");
+                }
+
+                statusCode = HttpStatusCode.OK;
+                result.SerialNo = uuid;
+
+            }
+            catch (Exception ex)
+            {
+
+                return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse()
+                {
+                    Code = 2999,
+                    Message = EVCBConfiguration.ERROR_MSG_UNEXPECTEDERROR,
+                    ErrorDetail = string.Format(EVCBConfiguration.ERRORMESSAGE_FORMAT, "GetDiagonostics", ex.ToString())
+
+                });
+            }
+
+            return Request.CreateResponse(statusCode, result);
+        }
+
+
+
+
+        [Route("transaction")]
+        [ResponseType(typeof(ErrorResponse))]
+        [ResponseType(typeof(InternalGenericResponse))]
+        [HttpPost]
+        public HttpResponseMessage StartTransaction(string ChargeBoxId, [FromBody] StartTransactionRequest StartTransaction)
+        {
+            string uuid = Guid.NewGuid().ToString();
+            var result = new InternalGenericResponse();
+            HttpStatusCode statusCode = HttpStatusCode.InternalServerError;
+            try
+            {
+                ChargePoint201Service ChargePoint201Service = new ChargePoint201Service();
+
+                if (!ChargePoint201Service.IsOnline(ChargeBoxId))
+                {
+
+                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Code = 2101, Message = EVCBConfiguration.ERROR_MSG_CHARGEBOXID_ISNT_EXIST_OR_OFFLINE });
+                }
+
+                //check parameter
+
+
+                if (StartTransaction == null || !StartTransaction.ConnectorId.HasValue
+                    || (StartTransaction.ConnectorId.HasValue && (ChargePoint201Service.GetNumberofConnectors(ChargeBoxId) < StartTransaction.ConnectorId || StartTransaction.ConnectorId < 0)) || string.IsNullOrEmpty(StartTransaction.IdTag) || StartTransaction.IdTag.Length > 20)
+                {
+                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Code = 2100, Message = EVCBConfiguration.ERROR_MSG_PARAMETER_OUTOFRANGE_INCORRECT });
+                }
+
+                if (StartTransaction.ChargingProfile != null)
+                {
+                    bool isvaild = true;
+                    if (!IsValidEnum<Packet.Messages.SubTypes.ChargingProfileKindType>((int)StartTransaction.ChargingProfile.chargingProfileKind))
+                    {
+                        isvaild = false;
+                    }
+                    else if (StartTransaction.ChargingProfile.recurrencyKind.HasValue && !IsValidEnum<Packet.Messages.SubTypes.RecurrencyKindType>((int)StartTransaction.ChargingProfile.recurrencyKind))
+                    {
+                        isvaild = false;
+                    }
+                    else if (StartTransaction.ChargingProfile.chargingSchedule != null && !IsValidEnum<Packet.Messages.SubTypes.ChargingRateUnitType>((int)StartTransaction.ChargingProfile.chargingSchedule.chargingRateUnit))
+                    {
+                        isvaild = false;
+                    }
+                    else
+                    {
+
+                        //do nothing
+                    }
+                    if (!isvaild)
+                    {
+                        return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Code = 2100, Message = EVCBConfiguration.ERROR_MSG_PARAMETER_OUTOFRANGE_INCORRECT });
+
+                    }
+
+                }
+
+                var currentStatus = ChargePoint201Service.GetChargePointCurrentSatus(ChargeBoxId, StartTransaction.ConnectorId.Value).Value;
+
+                if (StartTransaction.ConnectorId.HasValue && ChargePoint201Service.GetChargePointCurrentSatus(ChargeBoxId, StartTransaction.ConnectorId.Value).HasValue &&
+                    (currentStatus != Packet.Messages.SubTypes.ChargePointStatus.Available && 
+                    currentStatus != Packet.Messages.SubTypes.ChargePointStatus.Reserved && currentStatus != Packet.Messages.SubTypes.ChargePointStatus.Preparing))
+                {
+                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Code = 2103, Message = EVCBConfiguration.ERROR_MSG_CONNECTOR_ISNOT_AVAILIABLE_MODE });
+                }
+                else
+                {
+                    var _request = new RequestStartTransactionRequest()
+                    {
+                        EvseId = StartTransaction.ConnectorId,
+                        IdToken = new IdTokenType() { IdToken = StartTransaction.IdTag, Type = EVCB_OCPP20.Packet.DataTypes.EnumTypes.IdTokenEnumType.Central },
+                        RemoteStartId = (int)DateTime.UtcNow.AddYears(-100).Ticks,
+                        ChargingProfile = StartTransaction.ChargingProfile == null ? null :
+                        new ChargingProfileType()
+                        {
+                            Id = StartTransaction.ChargingProfile.chargingProfileId,
+                            ChargingProfileKind = (EVCB_OCPP20.Packet.DataTypes.EnumTypes.ChargingProfileKindEnumType)(int)StartTransaction.ChargingProfile.chargingProfileKind,
+                            ChargingProfilePurpose = EVCB_OCPP20.Packet.DataTypes.EnumTypes.ChargingProfilePurposeEnumType.TxProfile,
+                            RecurrencyKind = (EVCB_OCPP20.Packet.DataTypes.EnumTypes.RecurrencyKindEnumType)(int)StartTransaction.ChargingProfile.recurrencyKind,
+                            StackLevel = StartTransaction.ChargingProfile.stackLevel,
+                            ValidFrom = StartTransaction.ChargingProfile.validFrom == null ? (DateTime?)null : DateTime.SpecifyKind(StartTransaction.ChargingProfile.validFrom.Value, DateTimeKind.Utc),
+                            ValidTo = StartTransaction.ChargingProfile.validTo == null ? (DateTime?)null : DateTime.SpecifyKind(StartTransaction.ChargingProfile.validTo.Value, DateTimeKind.Utc),
+                            ChargingSchedule = new ChargingScheduleType()
+                            {
+
+                                Id = StartTransaction.ChargingProfile.chargingProfileId,
+                                ChargingRateUnit = (EVCB_OCPP20.Packet.DataTypes.EnumTypes.ChargingRateUnitEnumType)(int)StartTransaction.ChargingProfile.chargingSchedule.chargingRateUnit,
+                                Duration = StartTransaction.ChargingProfile.chargingSchedule.duration,
+                                MinChargingRate = StartTransaction.ChargingProfile.chargingSchedule.minChargingRate,
+                                StartSchedule = StartTransaction.ChargingProfile.chargingSchedule.startSchedule == null ? (DateTime?)null : DateTime.SpecifyKind(StartTransaction.ChargingProfile.chargingSchedule.startSchedule.Value, DateTimeKind.Utc)
+
+                            }
+
+                        }
+
+                    };
+
+                    if (StartTransaction.ChargingProfile != null)
+                    {
+                        List<ChargingSchedulePeriodType> schedulePeriod = new List<ChargingSchedulePeriodType>();
+
+                        foreach (var item in StartTransaction.ChargingProfile.chargingSchedule.chargingSchedulePeriod)
+                        {
+                            schedulePeriod.Add(new ChargingSchedulePeriodType()
+                            {
+                                Limit = item.limit,
+                                StartPeriod = item.startPeriod,
+                                NumberPhases = item.numberPhases
+
+                            });
+                        }
+                        _request.ChargingProfile.ChargingSchedule.ChargingSchedulePeriod = schedulePeriod;
+                    }
+
+
+                    if (!AddCommandtoServer(ChargeBoxId, uuid, _request))
+                    {
+                        throw new Exception("Write Command Fail!!");
+                    }
+                }
+
+                statusCode = HttpStatusCode.OK;
+                result.SerialNo = uuid;
+
+            }
+            catch (Exception ex)
+            {
+                return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse()
+                {
+                    Code = 2999,
+                    Message = EVCBConfiguration.ERROR_MSG_UNEXPECTEDERROR,
+                    ErrorDetail = string.Format(EVCBConfiguration.ERRORMESSAGE_FORMAT, "StartTransaction", ex.ToString())
+
+                });
+
+            }
+
+            return Request.CreateResponse(statusCode, result);
+        }
+
+        [Route("transaction")]
+        [ResponseType(typeof(ErrorResponse))]
+        [ResponseType(typeof(InternalGenericResponse))]
+        [HttpPut]
+        public HttpResponseMessage StopTransaction(string ChargeBoxId, string TransactionId)
+        {
+            string uuid = Guid.NewGuid().ToString();
+            var result = new InternalGenericResponse();
+            HttpStatusCode statusCode = HttpStatusCode.InternalServerError;
+            try
+            {
+                ChargePoint201Service ChargePoint201Service = new ChargePoint201Service();
+
+                if (!ChargePoint201Service.IsOnline(ChargeBoxId))
+                {
+
+                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Code = 2101, Message = EVCBConfiguration.ERROR_MSG_CHARGEBOXID_ISNT_EXIST_OR_OFFLINE });
+                }
+
+                var _ConnectorId = ChargePoint201Service.GetConnectorwithOngoingTransaction(ChargeBoxId, TransactionId);
+
+                if (_ConnectorId == -1)
+                {
+                    // 充完電 & 這個充電序不存在
+                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Code = 2106, Message = EVCBConfiguration.ERROR_MSG_TX_FINISHED_OR_NOTFOUND });
+                }
+
+                var _ConnectorStatus = ChargePoint201Service.GetChargePointCurrentSatus(ChargeBoxId, _ConnectorId);
+
+                if (!(_ConnectorStatus.HasValue && _ConnectorStatus == ChargePointStatus.Charging))
+                {
+
+                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Code = 2105, Message = EVCBConfiguration.ERROR_MSG_CONNECTOR_ISNOT_CHARGING_MODE });
+                }
+                else
+                {
+                    if (ChargePoint201Service.IsTransactionRunning(ChargeBoxId, TransactionId))
+                    {
+                        var _request = new RequestStopTransactionRequest()
+                        {
+                            TransactionId = TransactionId
+                        };
+
+                        //下發停止
+                        if (!AddCommandtoServer(ChargeBoxId, uuid, _request))
+                        {
+                            throw new Exception("Write Command Fail!!");
+                        }
+                    }
+                    else
+                    {
+                        return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Code = 2104, Message = EVCBConfiguration.ERROR_MSG_SESSION_WAS_FINISHED });
+                    }
+                }
+
+                statusCode = HttpStatusCode.OK;
+                result.SerialNo = uuid;
+                return Request.CreateResponse(statusCode, result);
+
+            }
+            catch (Exception ex)
+            {
+                return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse()
+                {
+                    Code = 2999,
+                    Message = EVCBConfiguration.ERROR_MSG_UNEXPECTEDERROR,
+                    ErrorDetail = string.Format(EVCBConfiguration.ERRORMESSAGE_FORMAT, "StopTransaction", ex.ToString())
+
+                });
+
+
+            }
+
+
+        }
+
+        [Route("reservation")]
+        [ResponseType(typeof(ErrorResponse))]
+        [ResponseType(typeof(InternalGenericResponse))]
+        [HttpPost]
+        public HttpResponseMessage ReserveNow(string ChargeBoxId, [FromBody] ReserveRequest ReserveNow)
+        {
+            string uuid = Guid.NewGuid().ToString();
+            var result = new InternalGenericResponse();
+            HttpStatusCode statusCode = HttpStatusCode.InternalServerError;
+            try
+            {
+                ChargePoint201Service ChargePoint201Service = new ChargePoint201Service();
+
+                if (!ChargePoint201Service.IsOnline(ChargeBoxId))
+                {
+                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Code = 2101, Message = EVCBConfiguration.ERROR_MSG_CHARGEBOXID_ISNT_EXIST_OR_OFFLINE });
+                }
+
+
+                DateTime expiryDate = new DateTime();
+                //check parameter
+                if (ReserveNow == null ||
+                    !(ReserveNow.ConnectorId >= 0) ||
+                    string.IsNullOrEmpty(ReserveNow.IdTag) ||
+                    ReserveNow.ReservationId == -1 ||
+                    !DateTime.TryParse(ReserveNow.ExpiryDate, out expiryDate))
+                {
+
+                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Code = 2100, Message = EVCBConfiguration.ERROR_MSG_PARAMETER_OUTOFRANGE_INCORRECT });
+                }
+
+                expiryDate = DateTime.SpecifyKind(DateTime.Parse(ReserveNow.ExpiryDate), DateTimeKind.Utc);
+
+                if (DateTime.Compare(DateTime.UtcNow, expiryDate) >= 0)
+                {
+                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Code = 2100, Message = EVCBConfiguration.ERROR_MSG_PARAMETER_OUTOFRANGE_INCORRECT });
+                }
+
+                var connectorStatus = ChargePoint201Service.GetChargePointCurrentSatus(ChargeBoxId, ReserveNow.ConnectorId);
+
+                if (connectorStatus.HasValue && (connectorStatus.Value == Packet.Messages.SubTypes.ChargePointStatus.Available || connectorStatus.Value == ChargePointStatus.Preparing))
+                {
+
+                    var request = new ReserveNowRequest()
+                    {
+                        EvseId = ReserveNow.ConnectorId,
+                        ExpiryDateTime = expiryDate,
+                        IdToken = new IdTokenType() { IdToken = ReserveNow.IdTag, Type = EVCB_OCPP20.Packet.DataTypes.EnumTypes.IdTokenEnumType.Central },
+                        Id = ReserveNow.ReservationId,
+                        GroupIdToken = string.IsNullOrEmpty(ReserveNow.ParentIdTag) ? null : new IdTokenType() { IdToken = ReserveNow.ParentIdTag, Type = EVCB_OCPP20.Packet.DataTypes.EnumTypes.IdTokenEnumType.Central }
+
+                    };
+
+
+                    if (!AddCommandtoServer(ChargeBoxId, uuid, request))
+                    {
+                        throw new Exception("Write Command Fail!!");
+                    }
+
+                    statusCode = HttpStatusCode.OK;
+                    result.SerialNo = uuid;
+                }
+                else
+                {
+                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Code = 2103, Message = EVCBConfiguration.ERROR_MSG_CONNECTOR_ISNOT_AVAILIABLE_MODE });
+                }
+
+
+
+            }
+            catch (Exception ex)
+            {
+                return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse()
+                {
+                    Code = 2999,
+                    Message = EVCBConfiguration.ERROR_MSG_UNEXPECTEDERROR,
+                    ErrorDetail = string.Format(EVCBConfiguration.ERRORMESSAGE_FORMAT, "ReserveNow", ex.ToString())
+
+                });
+
+
+
+            }
+
+            return Request.CreateResponse(statusCode, result);
+        }
+
+        [Route("reservation")]
+        [ResponseType(typeof(ErrorResponse))]
+        [ResponseType(typeof(InternalGenericResponse))]
+        [HttpDelete]
+        public HttpResponseMessage CancelResrvation(string ChargeBoxId, int ReservationId)
+        {
+            string uuid = Guid.NewGuid().ToString();
+            var result = new InternalGenericResponse();
+            HttpStatusCode statusCode = HttpStatusCode.InternalServerError;
+            try
+            {
+                ChargePoint201Service ChargePoint201Service = new ChargePoint201Service();
+
+                if (!ChargePoint201Service.IsOnline(ChargeBoxId))
+                {
+
+                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Code = 2101, Message = EVCBConfiguration.ERROR_MSG_CHARGEBOXID_ISNT_EXIST_OR_OFFLINE });
+                }
+
+                var connectorStatus = ChargePoint201Service.GetChargePointCurrentSatus(ChargeBoxId, 0);
+
+                if (connectorStatus.HasValue && connectorStatus.Value == ChargePointStatus.Available)
+                {
+                    //create reqest
+
+                    var request = new CancelReservationRequest()
+                    {
+                        ReservationId = ReservationId
+
+                    };
+
+                    if (!AddCommandtoServer(ChargeBoxId, uuid, request))
+                    {
+                        throw new Exception("Write Command Fail!!");
+                    }
+
+                    statusCode = HttpStatusCode.OK;
+                    result.SerialNo = uuid;
+                }
+                else
+                {
+                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Code = 2103, Message = EVCBConfiguration.ERROR_MSG_CONNECTOR_ISNOT_AVAILIABLE_MODE });
+                }
+
+
+            }
+            catch (Exception ex)
+            {
+                return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse()
+                {
+                    Code = 2999,
+                    Message = EVCBConfiguration.ERROR_MSG_UNEXPECTEDERROR,
+                    ErrorDetail = string.Format(EVCBConfiguration.ERRORMESSAGE_FORMAT, "CancelResrvation", ex.ToString())
+
+                });
+
+            }
+
+            return Request.CreateResponse(statusCode, result);
+        }
+
+        /// <summary>
+        /// ResetEnumType 定義與1.6不同
+        /// </summary>
+        /// <param name="ChargeBoxId"></param>
+        /// <param name="ResetType"></param>
+        /// <returns></returns>
+        [Route("reset")]
+        [ResponseType(typeof(ErrorResponse))]
+        [ResponseType(typeof(InternalGenericResponse))]
+        [HttpPost]
+        public HttpResponseMessage Reset(string ChargeBoxId, int ResetType)
+        {
+            string uuid = Guid.NewGuid().ToString();
+            var result = new InternalGenericResponse();
+            HttpStatusCode statusCode = HttpStatusCode.InternalServerError;
+            try
+            {
+                ChargePoint201Service ChargePoint201Service = new ChargePoint201Service();
+
+                if (!ChargePoint201Service.IsOnline(ChargeBoxId))
+                {
+
+                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Code = 2101, Message = EVCBConfiguration.ERROR_MSG_CHARGEBOXID_ISNT_EXIST_OR_OFFLINE });
+                }
+
+                var connectorStatus = ChargePoint201Service.GetChargePointCurrentSatus(ChargeBoxId, 0);
+
+                if (connectorStatus.HasValue && connectorStatus.Value == ChargePointStatus.Available)
+                {
+                    //create reqest
+
+                    var request = new ResetRequest()
+                    {
+                        Type = (EVCB_OCPP20.Packet.DataTypes.EnumTypes.ResetEnumType)ResetType
+
+                    };
+
+                    if (!AddCommandtoServer(ChargeBoxId, uuid, request))
+                    {
+                        throw new Exception("Write Command Fail!!");
+                    }
+
+                    statusCode = HttpStatusCode.OK;
+                    result.SerialNo = uuid;
+                }
+                else
+                {
+                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Code = 2103, Message = EVCBConfiguration.ERROR_MSG_CONNECTOR_ISNOT_AVAILIABLE_MODE });
+                }
+
+
+            }
+            catch (Exception ex)
+            {
+                return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse()
+                {
+                    Code = 2999,
+                    Message = EVCBConfiguration.ERROR_MSG_UNEXPECTEDERROR,
+                    ErrorDetail = string.Format(EVCBConfiguration.ERRORMESSAGE_FORMAT, "Reset", ex.ToString())
+
+                });
+
+            }
+
+            return Request.CreateResponse(statusCode, result);
+        }
+
+
+
+        [Route("datatransfer")]
+        [ResponseType(typeof(ErrorResponse))]
+        [ResponseType(typeof(InternalGenericResponse))]
+        [HttpPost]
+        public HttpResponseMessage SendDataTransfer(string ChargeBoxId, string VenderId, [FromBody] string Data, string MessageId = "")
+        {
+            string uuid = Guid.NewGuid().ToString();
+            var result = new InternalGenericResponse();
+            HttpStatusCode statusCode = HttpStatusCode.InternalServerError;
+            try
+            {
+                if (string.IsNullOrEmpty(ChargeBoxId) || string.IsNullOrEmpty(VenderId))
+                {
+                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Code = 2100, Message = EVCBConfiguration.ERROR_MSG_PARAMETER_OUTOFRANGE_INCORRECT });
+                }
+                ChargePoint201Service ChargePoint201Service = new ChargePoint201Service();
+
+                if (!ChargePoint201Service.IsOnline(ChargeBoxId))
+                {
+                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Code = 2101, Message = EVCBConfiguration.ERROR_MSG_CHARGEBOXID_ISNT_EXIST_OR_OFFLINE });
+                }
+
+                var request = new DataTransferRequest()
+                {
+                    Data = Data,
+                    MessageId = MessageId,
+                    VendorId = VenderId
+                };
+
+                if (!AddCommandtoServer(ChargeBoxId, uuid, request))
+                {
+                    throw new Exception("Write Command Fail!!");
+                }
+
+
+                statusCode = HttpStatusCode.OK;
+                result.SerialNo = uuid;
+            }
+            catch (Exception ex)
+            {
+                return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse()
+                {
+                    Code = 2999,
+                    Message = EVCBConfiguration.ERROR_MSG_UNEXPECTEDERROR,
+                    ErrorDetail = string.Format(EVCBConfiguration.ERRORMESSAGE_FORMAT, "SendDataTransfer", ex.ToString())
+
+                });
+
+            }
+
+            return Request.CreateResponse(statusCode, result);
+        }
+
+
+        [Route("cache")]
+        [ResponseType(typeof(ErrorResponse))]
+        [ResponseType(typeof(InternalGenericResponse))]
+        [HttpDelete]
+        public HttpResponseMessage ClearCache(string ChargeBoxId)
+        {
+            string uuid = Guid.NewGuid().ToString();
+            var result = new InternalGenericResponse();
+            HttpStatusCode statusCode = HttpStatusCode.InternalServerError;
+            try
+            {
+                ChargePoint201Service ChargePoint201Service = new ChargePoint201Service();
+
+                if (!ChargePoint201Service.IsOnline(ChargeBoxId))
+                {
+
+                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Code = 2101, Message = EVCBConfiguration.ERROR_MSG_CHARGEBOXID_ISNT_EXIST_OR_OFFLINE });
+                }
+
+                var connectorStatus = ChargePoint201Service.GetChargePointCurrentSatus(ChargeBoxId, 0);
+
+                if (connectorStatus.HasValue && connectorStatus.Value == ChargePointStatus.Available)
+                {
+
+                    if (!AddCommandtoServer(ChargeBoxId, uuid, new ClearCacheRequest()))
+                    {
+                        throw new Exception("Write Command Fail!!");
+                    }
+
+                    statusCode = HttpStatusCode.OK;
+                    result.SerialNo = uuid;
+                }
+                else
+                {
+                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Code = 2103, Message = EVCBConfiguration.ERROR_MSG_CONNECTOR_ISNOT_AVAILIABLE_MODE });
+                }
+
+
+            }
+            catch (Exception ex)
+            {
+                return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse()
+                {
+                    Code = 2999,
+                    Message = EVCBConfiguration.ERROR_MSG_UNEXPECTEDERROR,
+                    ErrorDetail = string.Format(EVCBConfiguration.ERRORMESSAGE_FORMAT, "ClearCache", ex.ToString())
+
+                });
+
+            }
+
+            return Request.CreateResponse(statusCode, result);
+        }
+
+        /// <summary>
+        /// ChargingProfilePurposeEnumType 沒有Mapping
+        /// </summary>
+        /// <param name="ChargeBoxId"></param>
+        /// <param name="ChargingProfile"></param>
+        /// <returns></returns>
+        [Route("chargingprofile")]
+        [ResponseType(typeof(ErrorResponse))]
+        [ResponseType(typeof(InternalGenericResponse))]
+        [HttpPost]
+        public HttpResponseMessage SetChargingProfile(string ChargeBoxId, [FromBody] ChargingProfileRequest ChargingProfile)
+        {
+
+
+            string uuid = Guid.NewGuid().ToString();
+            var result = new InternalGenericResponse();
+            HttpStatusCode statusCode = HttpStatusCode.InternalServerError;
+            try
+            {
+                ChargePoint201Service ChargePoint201Service = new ChargePoint201Service();
+
+                if (!ChargePoint201Service.IsOnline(ChargeBoxId))
+                {
+
+                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Code = 2101, Message = EVCBConfiguration.ERROR_MSG_CHARGEBOXID_ISNT_EXIST_OR_OFFLINE });
+                }
+
+                //check parameter
+                if (ChargingProfile == null ||
+                    ChargingProfile.connectorId < 0 ||
+                  !(ChargingProfile.ChargingProfile != null && IsValidEnum<ChargingProfileKindType>((int)ChargingProfile.ChargingProfile.chargingProfileKind)) ||
+                  !(ChargingProfile.ChargingProfile != null && ChargingProfile.ChargingProfile.recurrencyKind.HasValue && IsValidEnum<RecurrencyKindType>((int)ChargingProfile.ChargingProfile.recurrencyKind)) ||
+                  !(ChargingProfile.ChargingProfile != null && ChargingProfile.ChargingProfile.recurrencyKind.HasValue && IsValidEnum<RecurrencyKindType>((int)ChargingProfile.ChargingProfile.recurrencyKind)) ||
+                  !(ChargingProfile.ChargingProfile != null && IsValidEnum<ChargingProfilePurposeType>((int)ChargingProfile.ChargingProfile.chargingProfilePurpose)) ||
+                  !(ChargingProfile.ChargingProfile != null && ChargingProfile.ChargingProfile.chargingSchedule != null && IsValidEnum<ChargingRateUnitType>((int)ChargingProfile.ChargingProfile.chargingSchedule.chargingRateUnit)))
+                {
+                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Code = 2100, Message = EVCBConfiguration.ERROR_MSG_PARAMETER_OUTOFRANGE_INCORRECT });
+                }
+
+                if (ChargingProfile.ChargingProfile.chargingSchedule.chargingSchedulePeriod.Count == 0)
+                {
+                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Code = 2100, Message = EVCBConfiguration.ERROR_MSG_PARAMETER_OUTOFRANGE_INCORRECT });
+                }
+
+
+                var request = new SetChargingProfileRequest()
+                {
+                    EvseId = ChargingProfile.connectorId,
+                    ChargingProfile = new ChargingProfileType()
+                    {
+                        Id = ChargingProfile.ChargingProfile.chargingProfileId,
+                        ChargingProfileKind = (EVCB_OCPP20.Packet.DataTypes.EnumTypes.ChargingProfileKindEnumType)(int)ChargingProfile.ChargingProfile.chargingProfileKind,
+                        ChargingProfilePurpose = (EVCB_OCPP20.Packet.DataTypes.EnumTypes.ChargingProfilePurposeEnumType)(int)ChargingProfile.ChargingProfile.chargingProfilePurpose + 1,
+                        RecurrencyKind = (EVCB_OCPP20.Packet.DataTypes.EnumTypes.RecurrencyKindEnumType)(int)ChargingProfile.ChargingProfile.recurrencyKind,
+                        StackLevel = ChargingProfile.ChargingProfile.stackLevel,
+                        TransactionId = ChargingProfile.ChargingProfile.TransactionId.Value.ToString(),
+                        ValidFrom = ChargingProfile.ChargingProfile.validFrom == null ? (DateTime?)null : DateTime.SpecifyKind(ChargingProfile.ChargingProfile.validFrom.Value, DateTimeKind.Utc),
+                        ValidTo = ChargingProfile.ChargingProfile.validTo == null ? (DateTime?)null : DateTime.SpecifyKind(ChargingProfile.ChargingProfile.validTo.Value, DateTimeKind.Utc),
+                        ChargingSchedule = new ChargingScheduleType()
+                        {
+
+                            Id = ChargingProfile.ChargingProfile.chargingProfileId,
+                            ChargingRateUnit = (EVCB_OCPP20.Packet.DataTypes.EnumTypes.ChargingRateUnitEnumType)(int)ChargingProfile.ChargingProfile.chargingSchedule.chargingRateUnit,
+                            Duration = ChargingProfile.ChargingProfile.chargingSchedule.duration,
+                            MinChargingRate = ChargingProfile.ChargingProfile.chargingSchedule.minChargingRate,
+                            StartSchedule = ChargingProfile.ChargingProfile.chargingSchedule.startSchedule == null ? (DateTime?)null : DateTime.SpecifyKind(ChargingProfile.ChargingProfile.chargingSchedule.startSchedule.Value, DateTimeKind.Utc)
+
+                        }
+
+                    }
+                };
+
+                if (ChargingProfile.ChargingProfile.chargingSchedule.chargingSchedulePeriod != null)
+                {
+                    List<ChargingSchedulePeriodType> schedulePeriod = new List<ChargingSchedulePeriodType>();
+
+                    foreach (var item in ChargingProfile.ChargingProfile.chargingSchedule.chargingSchedulePeriod)
+                    {
+                        schedulePeriod.Add(new ChargingSchedulePeriodType()
+                        {
+                            Limit = item.limit,
+                            StartPeriod = item.startPeriod,
+                            NumberPhases = item.numberPhases
+
+                        });
+                    }
+                    request.ChargingProfile.ChargingSchedule.ChargingSchedulePeriod = schedulePeriod;
+                }
+
+
+
+                if (!AddCommandtoServer(ChargeBoxId, uuid, request))
+                {
+                    throw new Exception("Write Command Fail!!");
+                }
+
+
+                statusCode = HttpStatusCode.OK;
+                result.SerialNo = uuid;
+
+            }
+            catch (Exception ex)
+            {
+
+                return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse()
+                {
+                    Code = 2999,
+                    Message = EVCBConfiguration.ERROR_MSG_UNEXPECTEDERROR,
+                    ErrorDetail = string.Format(EVCBConfiguration.ERRORMESSAGE_FORMAT, "SetChargingProfile", ex.ToString())
+
+                });
+            }
+
+            return Request.CreateResponse(statusCode, result);
+        }
+
+        [Route("chargingprofile")]
+        [ResponseType(typeof(ErrorResponse))]
+        [ResponseType(typeof(InternalGenericResponse))]
+        [HttpDelete]
+        public HttpResponseMessage ClearChargingProfile(string ChargeBoxId, int Id = -1, int ConnectorId = -1, int ChargingProfilePurpose = -1, int StackLevel = -1)
+        {
+            string uuid = Guid.NewGuid().ToString();
+            var result = new InternalGenericResponse();
+            HttpStatusCode statusCode = HttpStatusCode.InternalServerError;
+            try
+            {
+                ChargePoint201Service ChargePoint201Service = new ChargePoint201Service();
+
+                if (!ChargePoint201Service.IsOnline(ChargeBoxId))
+                {
+
+                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Code = 2101, Message = EVCBConfiguration.ERROR_MSG_CHARGEBOXID_ISNT_EXIST_OR_OFFLINE });
+                }
+
+                var connectorStatus = ChargePoint201Service.GetChargePointCurrentSatus(ChargeBoxId, 0);
+
+                if (connectorStatus.HasValue && connectorStatus.Value == ChargePointStatus.Available)
+                {
+
+                    var request = new ClearChargingProfileRequest()
+                    {
+                        ChargingProfileCriteria = new ClearChargingProfileType()
+                        {
+                            ChargingProfilePurpose = (EVCB_OCPP20.Packet.DataTypes.EnumTypes.ChargingProfilePurposeEnumType)(int)ChargingProfilePurpose + 1,
+                            EvseId = ConnectorId == -1 ? (int?)null : (int)ConnectorId,
+                            StackLevel = StackLevel == -1 ? (int?)null : (int)StackLevel,
+
+                        },
+                        ChargingProfileId = Id == -1 ? (int?)null : Id,
+
+                    };
+
+                    if (!AddCommandtoServer(ChargeBoxId, uuid, request))
+                    {
+                        throw new Exception("Write Command Fail!!");
+                    }
+
+                    statusCode = HttpStatusCode.OK;
+                    result.SerialNo = uuid;
+                }
+                else
+                {
+                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Code = 2103, Message = EVCBConfiguration.ERROR_MSG_CONNECTOR_ISNOT_AVAILIABLE_MODE });
+                }
+
+
+            }
+            catch (Exception ex)
+            {
+
+
+                return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse()
+                {
+                    Code = 2999,
+                    Message = EVCBConfiguration.ERROR_MSG_UNEXPECTEDERROR,
+                    ErrorDetail = string.Format(EVCBConfiguration.ERRORMESSAGE_FORMAT, "ClearChargingProfile", ex.ToString())
+
+                });
+            }
+
+            return Request.CreateResponse(statusCode, result);
+        }
+
+        /// <summary>
+        /// Trigger EnumType 沒有Mapping 
+        /// </summary>
+        /// <param name="ChargeBoxId"></param>
+        /// <param name="triggerMessage"></param>
+        /// <returns></returns>
+        [Route("trigger")]
+        [ResponseType(typeof(ErrorResponse))]
+        [ResponseType(typeof(InternalGenericResponse))]
+        [HttpPost]
+        public HttpResponseMessage TriggerMessage(string ChargeBoxId, [FromBody] TriggerRequest triggerMessage)
+        {
+            string uuid = Guid.NewGuid().ToString();
+            var result = new InternalGenericResponse();
+            HttpStatusCode statusCode = HttpStatusCode.InternalServerError;
+            try
+            {
+                ChargePoint201Service ChargePoint201Service = new ChargePoint201Service();
+
+                if (!ChargePoint201Service.IsOnline(ChargeBoxId))
+                {
+
+                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Code = 2101, Message = EVCBConfiguration.ERROR_MSG_CHARGEBOXID_ISNT_EXIST_OR_OFFLINE });
+                }
+
+                //check parameter
+                if (triggerMessage == null || !(triggerMessage.TriggerType >= 1 && triggerMessage.TriggerType <= (int)Packet.Messages.SubTypes.MessageTrigger.StatusNotification))
+                {
+
+                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Code = 2100, Message = EVCBConfiguration.ERROR_MSG_PARAMETER_OUTOFRANGE_INCORRECT });
+                }
+
+                //create reqest
+
+                var request = new TriggerMessageRequest()
+                {
+                    Evse = triggerMessage.ConnectorId == -1 ? null : new EVSEType() { Id = triggerMessage.ConnectorId, ConnectorId = triggerMessage.ConnectorId },
+                    RequestedMessage = (EVCB_OCPP20.Packet.DataTypes.EnumTypes.MessageTriggerEnumType)triggerMessage.TriggerType
+                };
+
+
+                if (!AddCommandtoServer(ChargeBoxId, uuid, request))
+                {
+                    throw new Exception("Write Command Fail!!");
+                }
+
+                statusCode = HttpStatusCode.OK;
+                result.SerialNo = uuid;
+
+            }
+            catch (Exception ex)
+            {
+                return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse()
+                {
+                    Code = 2999,
+                    Message = EVCBConfiguration.ERROR_MSG_UNEXPECTEDERROR,
+                    ErrorDetail = string.Format(EVCBConfiguration.ERRORMESSAGE_FORMAT, "TriggerMessage", ex.ToString())
+
+                });
+
+            }
+
+            return Request.CreateResponse(statusCode, result);
+        }
+
+        [Route("unlockconnector")]
+        [ResponseType(typeof(ErrorResponse))]
+        [ResponseType(typeof(InternalGenericResponse))]
+        [HttpPost]
+        public HttpResponseMessage UnlockConnector(string ChargeBoxId, int ConnectorId)
+        {
+            string uuid = Guid.NewGuid().ToString();
+            var result = new InternalGenericResponse();
+            HttpStatusCode statusCode = HttpStatusCode.InternalServerError;
+            try
+            {
+                ChargePoint201Service ChargePoint201Service = new ChargePoint201Service();
+
+                if (!ChargePoint201Service.IsOnline(ChargeBoxId))
+                {
+
+                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Code = 2101, Message = EVCBConfiguration.ERROR_MSG_CHARGEBOXID_ISNT_EXIST_OR_OFFLINE });
+                }
+
+                //check parameter
+                if (ConnectorId < 0)
+                {
+
+                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Code = 2100, Message = EVCBConfiguration.ERROR_MSG_PARAMETER_OUTOFRANGE_INCORRECT });
+                }
+
+                //create reqest
+
+                var request = new UnlockConnectorRequest()
+                {
+                    ConnectorId = ConnectorId,
+                    EvseId = ConnectorId,
+                };
+
+
+                if (!AddCommandtoServer(ChargeBoxId, uuid, request))
+                {
+                    throw new Exception("Write Command Fail!!");
+                }
+
+                statusCode = HttpStatusCode.OK;
+                result.SerialNo = uuid;
+
+            }
+            catch (Exception ex)
+            {
+                return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse()
+                {
+                    Code = 2999,
+                    Message = EVCBConfiguration.ERROR_MSG_UNEXPECTEDERROR,
+                    ErrorDetail = string.Format(EVCBConfiguration.ERRORMESSAGE_FORMAT, "UnlockConnector", ex.ToString())
+
+                });
+
+
+            }
+
+            return Request.CreateResponse(statusCode, result);
+        }
+
+        [Route("locallist")]
+        [ResponseType(typeof(ErrorResponse))]
+        [ResponseType(typeof(InternalGenericResponse))]
+        [HttpPost]
+        public HttpResponseMessage SendLocalList(string ChargeBoxId, [FromBody] LocalListRequest LocalList)
+        {
+            string uuid = Guid.NewGuid().ToString();
+            var result = new InternalGenericResponse();
+            HttpStatusCode statusCode = HttpStatusCode.InternalServerError;
+            try
+            {
+                ChargePoint16Service chargePointService = new ChargePoint16Service();
+
+                if (!chargePointService.IsOnline(ChargeBoxId))
+                {
+
+                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Code = 2101, Message = EVCBConfiguration.ERROR_MSG_CHARGEBOXID_ISNT_EXIST_OR_OFFLINE });
+                }
+
+                //check parameter
+                if (LocalList == null ||
+                    !IsValidEnum<Packet.Messages.SubTypes.UpdateType>((int)LocalList.UpdateType) || LocalList.LocalAuthorizationList == null
+                    || (LocalList.LocalAuthorizationList != null && LocalList.LocalAuthorizationList.Count == 0))
+                {
+
+                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Code = 2100, Message = EVCBConfiguration.ERROR_MSG_PARAMETER_OUTOFRANGE_INCORRECT });
+                }
+
+                bool badRequest = false;
+                List<EVCB_OCPP20.Packet.DataTypes.AuthorizationData> localAuthorizationList = new List<EVCB_OCPP20.Packet.DataTypes.AuthorizationData>();
+                for (int i = 0; i < LocalList.LocalAuthorizationList.Count; i++)
+                {
+                    if (string.IsNullOrEmpty(LocalList.LocalAuthorizationList[i].IdTag))
+                        badRequest = true;
+
+                    if (LocalList.LocalAuthorizationList[i].IdTagInfo != null && !IsValidEnum<AuthorizationStatusEnumType>((int)LocalList.LocalAuthorizationList[i].IdTagInfo.Status))
+                        badRequest = true;
+
+                    if (badRequest)
+                    {
+                        return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Code = 2100, Message = EVCBConfiguration.ERROR_MSG_PARAMETER_OUTOFRANGE_INCORRECT });
+                    }
+                    localAuthorizationList.Add(new EVCB_OCPP20.Packet.DataTypes.AuthorizationData()
+                    {
+                        IdToken = new IdTokenType()
+                        {
+                            IdToken = LocalList.LocalAuthorizationList[i].IdTag,
+                            Type = IdTokenEnumType.ISO15693
+                        },
+                        IdTokenInfo = LocalList.LocalAuthorizationList[i].IdTagInfo == null ? null : new IdTokenInfoType()
+                        {
+
+                            CacheExpiryDateTime = LocalList.LocalAuthorizationList[i].IdTagInfo.ExpiryDate,
+                            GroupIdToken = new GroupIdTokenType()
+                            {
+                                IdToken = LocalList.LocalAuthorizationList[i].IdTagInfo.ParentIdTag,
+                                Type = IdTokenEnumType.ISO15693
+                            },
+                            Status = (AuthorizationStatusEnumType)LocalList.LocalAuthorizationList[i].IdTagInfo.Status
+                        }
+
+                    });
+                }
+
+                var request = new SendLocalListRequest()
+                {
+
+                    VersionNumber = LocalList.ListVersion,
+                    UpdateType = (EVCB_OCPP20.Packet.DataTypes.EnumTypes.UpdateEnumType)LocalList.UpdateType,
+                    LocalAuthorizationList = localAuthorizationList
+
+                };
+
+                if (!AddCommandtoServer(ChargeBoxId, uuid, request))
+                {
+                    throw new Exception("Write Command Fail!!");
+                }
+
+                statusCode = HttpStatusCode.OK;
+                result.SerialNo = uuid;
+            }
+            catch (Exception ex)
+            {
+                return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse()
+                {
+                    Code = 2999,
+                    Message = EVCBConfiguration.ERROR_MSG_UNEXPECTEDERROR,
+                    ErrorDetail = string.Format(EVCBConfiguration.ERRORMESSAGE_FORMAT, "SendLocalList", ex.ToString())
+
+                });
+
+            }
+
+            return Request.CreateResponse(statusCode, result);
+        }
+
+        [Route("locallistversion")]
+        [ResponseType(typeof(ErrorResponse))]
+        [ResponseType(typeof(InternalGenericResponse))]
+        [HttpGet]
+        public HttpResponseMessage Locallistversion(string ChargeBoxId)
+        {
+            string uuid = Guid.NewGuid().ToString();
+            var result = new InternalGenericResponse();
+            HttpStatusCode statusCode = HttpStatusCode.InternalServerError;
+            try
+            {
+
+                ChargePoint201Service chargePointService = new ChargePoint201Service();
+
+                if (!chargePointService.IsOnline(ChargeBoxId))
+                {
+
+                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Code = 2101, Message = EVCBConfiguration.ERROR_MSG_CHARGEBOXID_ISNT_EXIST_OR_OFFLINE });
+                }
+
+                if (!AddCommandtoServer(ChargeBoxId, uuid, new GetLocalListVersionRequest()))
+                {
+                    throw new Exception("Write Command Fail!!");
+                }
+
+                statusCode = HttpStatusCode.OK;
+                result.SerialNo = uuid;
+
+            }
+            catch (Exception ex)
+            {
+                return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse()
+                {
+                    Code = 2999,
+                    Message = EVCBConfiguration.ERROR_MSG_UNEXPECTEDERROR,
+                    ErrorDetail = string.Format(EVCBConfiguration.ERRORMESSAGE_FORMAT, "GetLocallistversion", ex.ToString())
+
+                });
+
+
+            }
+
+            return Request.CreateResponse(statusCode, result);
+        }
+
+
+        private bool AddCommandtoServer(string chargeBoxId, string uuid, IRequest request)
+        {
+            bool result = false;
+            try
+            {
+                ServerTriggerService service = new ServerTriggerService();
+                service.AddMessage(chargeBoxId, uuid, request);
+                result = true;
+            }
+            catch (Exception ex)
+            {
+                ;
+            }
+
+            return result;
+        }
+
+
+        private bool IsValidEnum<TEnum>(int enumValue)
+        {
+
+            return Enum.IsDefined(typeof(TEnum), enumValue);
+
+        }
+    }
+}

二進制
EVCB_OCPP.WEBAPI/Dll/EVCB_OCPP20.Packet.dll


+ 15 - 0
EVCB_OCPP.WEBAPI/EVCB_OCPP.WEBAPI.csproj

@@ -52,6 +52,10 @@
       <SpecificVersion>False</SpecificVersion>
       <HintPath>Dll\EVCB_OCPP.Packet.dll</HintPath>
     </Reference>
+    <Reference Include="EVCB_OCPP20.Packet, Version=0.1.0.0, Culture=neutral, processorArchitecture=MSIL">
+      <SpecificVersion>False</SpecificVersion>
+      <HintPath>Dll\EVCB_OCPP20.Packet.dll</HintPath>
+    </Reference>
     <Reference Include="Microsoft.Bcl.AsyncInterfaces, Version=1.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
       <HintPath>..\packages\Microsoft.Bcl.AsyncInterfaces.1.1.0\lib\net461\Microsoft.Bcl.AsyncInterfaces.dll</HintPath>
     </Reference>
@@ -224,6 +228,11 @@
     <Compile Include="Controllers\HomeController.cs" />
     <Compile Include="Controllers\Version1\CPOController.cs" />
     <Compile Include="Controllers\Version1\InternalController.cs" />
+    <Compile Include="Controllers\Version2\ocpp16\OCPP16_CPOController.cs" />
+    <Compile Include="Controllers\Version2\ocpp16\OCPP16_InternalController.cs" />
+    <Compile Include="Controllers\Version2\ocpp201\OCPP201_CPOController.cs" />
+    <Compile Include="Controllers\Version2\ocpp201\OCPP201_InternalController.cs" />
+    <Compile Include="Controllers\Version2\V2_CPOController.cs" />
     <Compile Include="Global.asax.cs">
       <DependentUpon>Global.asax</DependentUpon>
     </Compile>
@@ -237,6 +246,7 @@
     <Compile Include="Models\ApiLogEntry.cs" />
     <Compile Include="Models\ConnectorMeterValue.cs" />
     <Compile Include="Models\ConnectorMeterValueModel.cs" />
+    <Compile Include="Models\OCPPProtocolType.cs" />
     <Compile Include="Models\SessionDetail.cs" />
     <Compile Include="Models\TransactionRecordModel.cs" />
     <Compile Include="Models\WebAPI\AvailiabilityRequest.cs" />
@@ -275,6 +285,10 @@
     <Compile Include="Services\ChargePointService.cs" />
     <Compile Include="Services\CustomerService.cs" />
     <Compile Include="Services\HttpClientService.cs" />
+    <Compile Include="Services\Integration\ChargePoint16Service.cs" />
+    <Compile Include="Services\Integration\ChargePoint201Service.cs" />
+    <Compile Include="Services\Integration\ChargingStationService.cs" />
+    <Compile Include="Services\Integration\ServerTriggerService.cs" />
     <Compile Include="Services\InternalHttpClient.cs" />
     <Compile Include="Services\ServerTriggerService.cs" />
     <Compile Include="Services\ChargingStationService.cs" />
@@ -286,6 +300,7 @@
     <Content Include="Content\bootstrap.css" />
     <Content Include="Content\bootstrap.min.css" />
     <Content Include="Dll\EVCB_OCPP.Packet.dll" />
+    <Content Include="Dll\EVCB_OCPP20.Packet.dll" />
     <Content Include="favicon.ico" />
     <Content Include="fonts\glyphicons-halflings-regular.svg" />
     <Content Include="Global.asax" />

+ 14 - 0
EVCB_OCPP.WEBAPI/Models/OCPPProtocolType.cs

@@ -0,0 +1,14 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Web;
+
+namespace EVCB_OCPP.WEBAPI.Models
+{
+    public enum OCPPProtocolType
+    {
+        Unknown = 0,
+        OCPP16,
+        OCPP201
+    }
+}

+ 10 - 2
EVCB_OCPP.WEBAPI/Models/SessionDetail.cs

@@ -8,7 +8,10 @@ namespace EVCB_OCPP.WEBAPI.Models
 {
     public class SessionDetail
     {
-     
+
+        public string SessionId { set; get; }
+
+
         public string ChargeBoxId { get; set; }
 
 
@@ -43,6 +46,11 @@ namespace EVCB_OCPP.WEBAPI.Models
         /// <summary>
         /// 停止原因
         /// </summary>
-        public Reason StopReason { set; get; }
+        public string StopReason { set; get; }
+
+
+        public decimal TotalCost { set; get; }
+
+        public string Currency { set; get; }
     }
 }

+ 11 - 1
EVCB_OCPP.WEBAPI/Models/TransactionRecordModel.cs

@@ -53,6 +53,11 @@ namespace EVCB_OCPP.WEBAPI.Models
         /// </summary>
         public int ReservationId { set; get; }
 
+        /// <summary>
+        /// 停止原因
+        /// </summary>
+        public string StopReason { set; get; }
+
         /// <summary>
         /// 停止原因No
         /// </summary>
@@ -67,7 +72,12 @@ namespace EVCB_OCPP.WEBAPI.Models
         /// 結束meter
         /// </summary>
         public decimal MeterStop { get; set; }
-       
+
+        public decimal Cost { set; get; }
+
+        public string Fee { set; get; }
+
+
 
 
        

+ 3 - 0
EVCB_OCPP.WEBAPI/Models/WebAPI/Dto/ConnectorStatus.cs

@@ -13,6 +13,9 @@ namespace EVCB_OCPP.WEBAPI.Models.WebAPI.Dto
         public int Status { set; get; }
 
 
+        public string ChargingState { set; get; }
+
+
         /// <summary>
         /// errorCode
         /// </summary>

+ 1 - 1
EVCB_OCPP.WEBAPI/Models/WebAPI/Dto/Machine.cs

@@ -68,7 +68,7 @@ namespace EVCB_OCPP.WEBAPI.Models.WebAPI.Dto
 
         public string ChargePointModel { set; get; }
 
-        
+        public string ModelName { set; get; }
 
 
     }

+ 1 - 1
EVCB_OCPP.WEBAPI/Properties/AssemblyInfo.cs

@@ -33,4 +33,4 @@ using System.Runtime.InteropServices;
 // 指定為預設值:
 [assembly: AssemblyVersion("0.1.0.0")]
 [assembly: AssemblyFileVersion("0.1.0.0")]
-[assembly: AssemblyInformationalVersion("eadecfa")]
+[assembly: AssemblyInformationalVersion("5f2d7fc")]

+ 1 - 1
EVCB_OCPP.WEBAPI/Services/ChargePointService.cs

@@ -477,7 +477,7 @@ namespace EVCB_OCPP.WEBAPI.Services
                         MeterStop = item.MeterStop,
                         StartTime = item.StartTime.ToString(EVCBConfiguration.UTC_DATETIMEFORMAT),
                         StopTime = item.StopTime.ToString(EVCBConfiguration.UTC_DATETIMEFORMAT),
-                        StopReason = item.StopReasonId < 1 ? Reason.Local : (Reason)item.StopReasonId
+                        StopReason = item.StopReasonId < 1 ? Reason.Local.ToString() : ((Reason)item.StopReasonId).ToString()
                     });
 
                 }

+ 596 - 0
EVCB_OCPP.WEBAPI/Services/Integration/ChargePoint16Service.cs

@@ -0,0 +1,596 @@
+using Dapper;
+using EVCB_OCPP.Packet.Messages.SubTypes;
+using EVCB_OCPP.WEBAPI.Models;
+using EVCB_OCPP.WEBAPI.Models.WebAPI;
+using EVCB_OCPP.WEBAPI.Models.WebAPI.Dto;
+using System;
+using System.Collections.Generic;
+using System.Configuration;
+using System.Data;
+using System.Data.SqlClient;
+using System.Linq;
+using System.Web;
+
+namespace EVCB_OCPP.WEBAPI.Services.Integration
+{
+    public interface IChargePointService
+    {
+        int GetNumberofConnectors(string chargeBoxId);
+
+        string GetVersionbyChargeBoxId(string chargeBoxId);
+
+        List<TransasctionData> GetActiveSessionInfo(string chargeBoxId, List<Measurand> requiredMeasurands, string sessionId = "", string idTag = "");
+
+        List<SessionDetail> GetSessionDetail(string chargeBoxId, string sessionId, string idTag, DateTime startTime, DateTime stopTime);
+
+        EVSE GetEVSEsbyChargeBoxId(string chargeboxid, DateTime? dateFrom, DateTime? dateTo);
+
+    }
+
+
+    public class ChargePoint16Service : IChargePointService
+    {
+        string mainConnectionString = ConfigurationManager.ConnectionStrings["MainDBContext"].ConnectionString;
+        string meterConnectionString = ConfigurationManager.ConnectionStrings["MeterValueDBContext"].ConnectionString;
+
+        public DateTime GetLastUpdatedTimebyMachineId(string machineId)
+        {
+            DateTime lastUpdatedOn = DateTime.UtcNow;
+            using (SqlConnection conn = new SqlConnection(mainConnectionString))
+            {
+                var parameters = new DynamicParameters();
+
+                parameters.Add("@MachineId", machineId, DbType.String, ParameterDirection.Input);
+                parameters.Add("@LastUpdatedTime", lastUpdatedOn, DbType.DateTime, ParameterDirection.Output);
+                conn.Execute("GetBasicInfoLastUpdatedTimeById", parameters, commandType: System.Data.CommandType.StoredProcedure);
+                DateTime? time = null;
+                try
+                {
+                    time = parameters.Get<DateTime>("@LastUpdatedTime");
+
+                }
+                catch (Exception ex)
+                {
+                    time = DateTime.UtcNow;
+                }
+
+
+                lastUpdatedOn = DateTime.SpecifyKind(time.Value, DateTimeKind.Utc);
+
+
+            }
+
+            return lastUpdatedOn;
+
+        }
+
+
+        public string GetMachineIdbyChargeBoxId(string chargeBoxId)
+        {
+            string machineId = string.Empty;
+            using (SqlConnection conn = new SqlConnection(mainConnectionString))
+            {
+                var parameters = new DynamicParameters();
+                parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input);
+                string strSql = "Select Id from [dbo].[Machine] where ChargeBoxId=@ChargeBoxId and IsDelete=0; ";
+                machineId = conn.Query<string>(strSql, parameters).FirstOrDefault();
+
+            }
+
+            return machineId;
+
+        }
+
+        public DateTime GetMachineUpdatedOn(string chargeBoxId)
+        {
+            DateTime dt = new DateTime();
+            string machineId = string.Empty;
+            using (SqlConnection conn = new SqlConnection(mainConnectionString))
+            {
+                var parameters = new DynamicParameters();
+                parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input);
+                string strSql = "Select HeartbeatUpdatedOn from [dbo].[Machine] where ChargeBoxId=@ChargeBoxId and IsDelete=0; ";
+                dt = conn.Query<DateTime>(strSql, parameters).FirstOrDefault();
+
+            }
+
+            return dt;
+
+        }
+
+
+        public string GetVersionbyChargeBoxId(string chargeBoxId)
+        {
+            string version = string.Empty;
+            using (SqlConnection conn = new SqlConnection(mainConnectionString))
+            {
+                var parameters = new DynamicParameters();
+                parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input);
+                string strSql = "Select BoardVersions from [dbo].[Machine] where ChargeBoxId=@ChargeBoxId and IsDelete=0; ";
+                version = conn.Query<string>(strSql, parameters).FirstOrDefault();
+            }
+            return version;
+        }
+
+        public EVSE GetEVSEsbyChargeBoxId(string chargeboxid, DateTime? dateFrom, DateTime? dateTo)
+        {
+            string machineId = GetMachineIdbyChargeBoxId(chargeboxid);
+            ChargePoint16Service _CPService = new ChargePoint16Service();
+
+            var _machineUpdateOn = _CPService.GetLastUpdatedTimebyMachineId(machineId);
+
+            var _machine = _CPService.GetBasicInfobyId(machineId);
+            _machine.LastUpdated = _machineUpdateOn;
+
+
+            return _machine;
+        }
+
+
+        public EVSE GetBasicInfobyId(string machineId)
+        {
+            EVSE cp = new EVSE();
+            Machine _machine = new Machine();
+            using (SqlConnection conn = new SqlConnection(mainConnectionString))
+            {
+                var parameters = new DynamicParameters();
+                parameters.Add("@Id", machineId, DbType.String, ParameterDirection.Input);
+                string strSql = "Select ChargeBoxId,ChargePointSerialNumber,ChargePointModel,RatedPower,Online,OfflineOn ,GunAmt,Latitude,Longitude,ConnectorType from [dbo].[Machine] where Id=@Id and IsDelete=0; ";
+                _machine = conn.Query<Machine>(strSql, parameters).FirstOrDefault();
+            }
+            if (_machine != null)
+            {
+                cp.ChargeBoxSystemID = _machine.ChargePointModel + _machine.ChargePointSerialNumber;
+                cp.ChargeBoxId = _machine.ChargeBoxId;
+                cp.NumberofConnectors = _machine.GunAmt;
+                cp.RatedPower = _machine.RatedPower;
+                cp.Status = _machine.Online ? Status.Available : Status.Offline;
+                cp.LastUpdated = _machine.CreatedOn > _machine.OfflineOn ? _machine.CreatedOn : _machine.OfflineOn;
+                cp.Coordinates = new GeoLocation() { Latitude = _machine.Latitude, Longitude = _machine.Longitude };
+                cp.Connectors = new List<Connector>();
+                var _Connectors = GetConnectorStatus(_machine.ChargeBoxId);
+                for (int i = 1; i <= _machine.GunAmt; i++)
+                {
+                    var _RefConnector = _Connectors.Where(x => x.ConnectorId == i).FirstOrDefault();
+                    cp.Connectors.Add(new Connector()
+                    {
+                        ConnectorId = _RefConnector == null ? i : _RefConnector.ConnectorId,
+                        Status = cp.Status == Status.Offline ? Status.Offline : _RefConnector == null ? Status.Unknown : ConvertConnectorStatus(_RefConnector.Status),
+                        ConnectorType = ConvertConnectorType(int.Parse(_machine.ConnectorType.Split(',')[i - 1])),
+                        FaultMessage = ((ChargePointErrorCode)_RefConnector.ChargePointErrorCodeId).ToString() + (string.IsNullOrEmpty(_RefConnector.VendorErrorCode) ? "" : "-" + _RefConnector.VendorErrorCode)
+
+                    });
+                }
+            }
+            return _machine == null ? null : cp;
+        }
+
+
+
+
+        public List<ConnectorStatus> GetConnectorStatus(string chargeBoxId)
+        {
+
+            List<ConnectorStatus> _Connectors = new List<ConnectorStatus>();
+            using (SqlConnection conn = new SqlConnection(mainConnectionString))
+            {
+                var parameters = new DynamicParameters();
+                parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input);
+                string strSql = "Select ConnectorId,Status,ChargePointErrorCodeId,VendorErrorCode from [dbo].[ConnectorStatus] where ChargeBoxId=@ChargeBoxId order by  ConnectorId; ";
+                _Connectors = conn.Query<ConnectorStatus>(strSql, parameters).SkipWhile(x => x.ConnectorId == 0).ToList();
+            }
+
+
+
+            return _Connectors;
+        }
+
+
+        public int GetNumberofConnectors(string chargeBoxId)
+        {
+            int count = 0;
+
+            if (string.IsNullOrEmpty(chargeBoxId)) return -1;
+            if (Exists(chargeBoxId))
+            {
+                var parameters = new DynamicParameters();
+                parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input);
+                using (SqlConnection conn = new SqlConnection(mainConnectionString))
+                {
+                    string strSql = "Select GunAmt from [dbo].[Machine] where ChargeBoxId=@ChargeBoxId  and IsDelete=0; ";
+                    count = conn.ExecuteScalarAsync<int>(strSql, parameters, null, EVCBConfiguration.DB_DefaultConnectionTimeout).Result;
+                }
+
+            }
+            return count;
+        }
+
+        public bool Exists(string chargeBoxId)
+        {
+            bool exists = false;
+
+            if (string.IsNullOrEmpty(chargeBoxId)) return exists;
+            var parameters = new DynamicParameters();
+            parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input);
+            using (SqlConnection conn = new SqlConnection(mainConnectionString))
+            {
+                string strSql = "Select count(*) from [dbo].[Machine] where ChargeBoxId=@ChargeBoxId  and IsDelete=0; ";
+                exists = conn.ExecuteScalar<bool>(strSql, parameters, null, EVCBConfiguration.DB_DefaultConnectionTimeout);
+            }
+            return exists;
+        }
+
+        public int GetConnectorwithOngoingTransaction(string chargeBoxId, int transactionId)
+        {
+            int connectorId = -1;
+
+            if (string.IsNullOrEmpty(chargeBoxId)) return connectorId;
+
+            var parameters = new DynamicParameters();
+            parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input);
+            parameters.Add("@TransactionId", transactionId, DbType.Int32, ParameterDirection.Input);
+            using (SqlConnection conn = new SqlConnection(mainConnectionString))
+            {
+                string strSql = "Select ConnectorId from [dbo].[TransactionRecord] where ChargeBoxId=@ChargeBoxId and Id= @TransactionId and StopTime='1991/01/01'; ";
+                connectorId = conn.Query<Int32>(strSql, parameters).FirstOrDefault();
+            }
+
+            return connectorId;
+        }
+
+
+
+
+        public bool IsTransactionRunning(string chargeBoxId, int transactionId)
+        {
+            bool exists = false;
+
+            if (string.IsNullOrEmpty(chargeBoxId)) return exists;
+
+            var parameters = new DynamicParameters();
+            parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input);
+            parameters.Add("@TransactionId", transactionId, DbType.Int32, ParameterDirection.Input);
+            using (SqlConnection conn = new SqlConnection(mainConnectionString))
+            {
+                string strSql = "Select Id from [dbo].[TransactionRecord] where ChargeBoxId=@ChargeBoxId and Id= @TransactionId and StopTime='1991/01/01'; ";
+                int id = conn.Query<Int32>(strSql, parameters).FirstOrDefault();
+                exists = id > 0 ? true : false;
+            }
+            return exists;
+        }
+
+        /// <summary>
+        /// 取得電樁或充電槍的狀態 
+        /// </summary>
+        /// <param name="chargeBoxId">Charge Box Id</param>
+        /// <param name="connectorId">充電槍號(0代表樁/槍號從1開始)</param>
+        /// <returns>依據OCPP狀態回覆 NULL表示離線</returns>
+        public ChargePointStatus? GetChargePointCurrentSatus(string chargeBoxId, int connectorId = 0)
+        {
+            ChargePointStatus? _status = null;
+
+            if (string.IsNullOrEmpty(chargeBoxId)) return _status;
+
+            var parameters = new DynamicParameters();
+            parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input);
+            parameters.Add("@ConnectorId", connectorId, DbType.Int32, ParameterDirection.Input);
+
+            using (SqlConnection conn = new SqlConnection(mainConnectionString))
+            {
+                string strSql = "Select online from [dbo].[Machine] where ChargeBoxId=@ChargeBoxId  and IsDelete=0; ";
+                bool online = conn.ExecuteScalar<bool>(strSql, parameters, null, EVCBConfiguration.DB_DefaultConnectionTimeout);
+
+                if (online)
+                {
+                    string connectorStrSql = "Select Status from [dbo].[ConnectorStatus] where ChargeBoxId=@ChargeBoxId and ConnectorId=@ConnectorId; ";
+
+                    int _statusfromdb = conn.Query<Int32>(connectorStrSql, parameters).FirstOrDefault();
+
+                    _status = (_statusfromdb <= 0 && connectorId == 0) ? ChargePointStatus.Available : (_statusfromdb <= 0 ? ((ChargePointStatus?)null) : ((ChargePointStatus)_statusfromdb));
+
+                }
+
+            }
+
+            return _status;
+        }
+
+        public bool IsOnline(string chargeBoxId)
+        {
+            bool online = false;
+
+            if (string.IsNullOrEmpty(chargeBoxId)) return online;
+
+            var parameters = new DynamicParameters();
+            parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input);
+
+
+            using (SqlConnection conn = new SqlConnection(mainConnectionString))
+            {
+                string strSql = "Select online from [dbo].[Machine] where ChargeBoxId=@ChargeBoxId  and IsDelete=0; ";
+                online = conn.ExecuteScalar<bool>(strSql, parameters, null, EVCBConfiguration.DB_DefaultConnectionTimeout);
+            }
+
+            return online;
+        }
+
+
+        public bool ContainsChargePoint(string chargeBoxId, string customerId)
+        {
+            bool existed = false;
+
+            if (string.IsNullOrEmpty(chargeBoxId)) return existed;
+
+            var parameters = new DynamicParameters();
+            parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input);
+            parameters.Add("@CustomerId", customerId, DbType.String, ParameterDirection.Input);
+
+
+            using (SqlConnection conn = new SqlConnection(mainConnectionString))
+            {
+                string strSql = "Select Count(*) from [dbo].[Machine] where ChargeBoxId=@ChargeBoxId and CustomerId=@CustomerId  and IsDelete=0; ";
+                existed = conn.ExecuteScalar<bool>(strSql, parameters, null, EVCBConfiguration.DB_DefaultConnectionTimeout);
+            }
+
+            return existed;
+        }
+
+        public List<TransasctionData> GetActiveSessionInfo(string chargeBoxId, List<Measurand> requiredMeasurands, string sessionId = "", string idTag = "")
+        {
+            List<ConnectorMeterValue> meterValues = new List<ConnectorMeterValue>();
+            ConnectorMeterValueModel meterModel = null;
+            List<TransasctionData> transactionDatas = null;
+            if (string.IsNullOrEmpty(chargeBoxId)) return transactionDatas;
+
+
+            try
+            {
+                var parameters = new DynamicParameters();
+                parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input);
+
+
+                using (SqlConnection conn = new SqlConnection(mainConnectionString))
+                {
+                    string date = DateTime.UtcNow.ToString("yyMMdd");
+                    string strSql = string.Empty;
+                    if (string.IsNullOrEmpty(sessionId) && string.IsNullOrEmpty(idTag))
+                    {
+                        strSql = "Select Id, ConnectorId, StartTime,Fee, StartIdTag from TransactionRecord " +
+                            "where StopTime = '1991-01-01 00:00:00.000' and ChargeBoxId = @ChargeBoxId and StartTime in (select  max(StartTime) from[TransactionRecord] where StopTime = '1991-01-01 00:00:00.000' and ChargeBoxId = @ChargeBoxId group by ConnectorId )";
+                    }
+                    else
+                    {
+                        parameters.Add(string.IsNullOrEmpty(sessionId) ? "@StartIdTag" : "@Id", string.IsNullOrEmpty(sessionId) ? idTag : sessionId, DbType.String, ParameterDirection.Input);
+
+                        strSql = "Select Id, ConnectorId, StartTime,Fee, StartIdTag from TransactionRecord" +
+                          "where StopTime = '1991-01-01 00:00:00.000' and ChargeBoxId = @ChargeBoxId and StartTime in (select  max(StartTime) from [TransactionRecord] where  " + (string.IsNullOrEmpty(sessionId) ? "StartIdTag=@StartIdTag" : "Id=@TransactionId") + " and StopTime = '1991-01-01 00:00:00.000' and ChargeBoxId = @ChargeBoxId group by ConnectorId )";
+
+                    }
+
+                    transactionDatas = conn.Query<TransasctionData>(strSql, parameters, null, true, EVCBConfiguration.DB_DefaultConnectionTimeout).ToList();
+
+
+                }
+
+            }
+            catch (Exception ex)
+            {
+                ;
+            }
+
+
+            for (int i = 0; i < requiredMeasurands.Count; i++)
+            {
+                for (int j = 0; j < transactionDatas.Count; j++)
+                {
+                    var parameters = new DynamicParameters();
+                    parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input);
+                    parameters.Add("@TransactionId", transactionDatas[j].Id, DbType.String, ParameterDirection.Input);
+                    parameters.Add("@MeasurandId", requiredMeasurands[i], DbType.String, ParameterDirection.Input);
+
+                    try
+                    {
+                        using (SqlConnection conn = new SqlConnection(meterConnectionString))
+                        {
+                            string date = transactionDatas[j].StartTime.ToString("yyMMdd");
+                            string strSql = "Select Top(1) * from [dbo].[ConnectorMeterValueRecord" + date + "] where ChargeBoxId=@ChargeBoxId and TransactionId=@TransactionId and MeasurandId=@MeasurandId order by CreatedOn desc;";
+                            meterModel = conn.Query<ConnectorMeterValueModel>(strSql, parameters, null, true, EVCBConfiguration.DB_DefaultConnectionTimeout).FirstOrDefault();
+
+                        }
+
+                        if (meterModel != null)
+                        {
+                            if (transactionDatas[j].MeterValues == null)
+                            {
+                                transactionDatas[j].MeterValues = new List<ConnectorMeterValue>();
+                            }
+
+                            transactionDatas[j].MeterValues.Add(new ConnectorMeterValue()
+                            {
+                                ChargeBoxId = meterModel.ChargeBoxId,
+                                ConnectorId = meterModel.ConnectorId,
+                                CreatedOn = meterModel.CreatedOn,
+                                Context = meterModel.ContextId < 1 ? (ReadingContext?)null : (ReadingContext?)meterModel.ContextId,
+                                Format = meterModel.FormatId < 1 ? (ValueFormat?)null : (ValueFormat?)meterModel.FormatId,
+                                Location = meterModel.LocationId < 1 ? (Location?)null : (Location?)meterModel.LocationId,
+                                Measurand = meterModel.MeasurandId < 1 ? (Measurand?)null : (Measurand?)meterModel.MeasurandId,
+                                Phase = meterModel.PhaseId < 1 ? (Phase?)null : (Phase?)meterModel.PhaseId,
+                                Unit = meterModel.UnitId < 1 ? (UnitOfMeasure?)UnitOfMeasure.Wh : (UnitOfMeasure?)meterModel.UnitId,
+                                Value = meterModel.Value,
+                                TransactionId = meterModel.TransactionId
+
+                            });
+
+
+
+                        }
+                    }
+                    catch (Exception ex)
+                    {
+                        break;
+                    }
+                }
+
+
+            }
+
+            return transactionDatas;
+        }
+
+
+        public List<SessionDetail> GetSessionDetail(string chargeBoxId, string sessionId, string idTag, DateTime startTime, DateTime stopTime)
+        {
+            List<SessionDetail> detail = new List<SessionDetail>();
+            List<TransactionRecordModel> transactionModel = null;
+            if (string.IsNullOrEmpty(chargeBoxId)) return detail;
+
+
+            var parameters = new DynamicParameters();
+
+            try
+            {
+
+                bool restrictedRange = false;
+                if (startTime != new DateTime(1991, 1, 1))
+                {
+                    restrictedRange = true;
+                    parameters.Add("@startTime", startTime, DbType.DateTime, ParameterDirection.Input);
+                    parameters.Add("@stopTime", stopTime, DbType.DateTime, ParameterDirection.Input);
+                }
+
+                using (SqlConnection conn = new SqlConnection(mainConnectionString))
+                {
+                    string strSql = string.Empty;
+                    if (!string.IsNullOrEmpty(sessionId) && string.IsNullOrEmpty(idTag))
+                    {
+                        parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input);
+                        parameters.Add("@TransactionId", sessionId, DbType.String, ParameterDirection.Input);
+                        strSql = "Select Top(1) * from [dbo].[TransactionRecord] where ChargeBoxId=@ChargeBoxId and Id=@TransactionId and StopTime!='1991-01-01 00:00:00.000' " + (restrictedRange ? " and StartTime >=@startTime and  StartTime <=@stopTime" : "") + " Order by Id desc ;";
+                    }
+                    else if (!string.IsNullOrEmpty(idTag) && string.IsNullOrEmpty(sessionId))
+                    {
+                        if (!string.IsNullOrEmpty(chargeBoxId))
+                        {
+                            parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input);
+                        }
+
+                        parameters.Add("@StartIdTag", idTag, DbType.String, ParameterDirection.Input);
+                        strSql = "Select  * from [dbo].[TransactionRecord] where " + (!string.IsNullOrEmpty(chargeBoxId) ? " ChargeBoxId=@ChargeBoxId and  " : "") + "  StartIdTag=@StartIdTag   and StopTime!='1991-01-01 00:00:00.000' " + (restrictedRange ? " and StartTime >=@startTime and  StartTime <=@stopTime" : "") + " Order by Id desc  ;";
+
+                    }
+                    else
+                    {
+
+                        parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input);
+
+                        strSql = "Select  * from [dbo].[TransactionRecord] where ChargeBoxId=@ChargeBoxId  and StopTime!='1991-01-01 00:00:00.000' " + (restrictedRange ? " and StartTime >=@startTime and  StartTime <=@stopTime" : "") + " Order by Id desc  ;";
+
+                    }
+
+                    transactionModel = conn.Query<TransactionRecordModel>(strSql, parameters, null, true, EVCBConfiguration.DB_DefaultConnectionTimeout).ToList();
+
+
+                }
+
+                foreach (var item in transactionModel)
+                {
+                    detail.Add(new SessionDetail()
+                    {
+                        ChargeBoxId = item.ChargeBoxId,
+                        ConnectorId = (int)item.ConnectorId,
+                        IdTag = item.StartIdTag,
+                        MeterStart = item.MeterStart,
+                        MeterStop = item.MeterStop,
+                        StartTime = item.StartTime.ToString(EVCBConfiguration.UTC_DATETIMEFORMAT),
+                        StopTime = item.StopTime.ToString(EVCBConfiguration.UTC_DATETIMEFORMAT),
+                        SessionId = item.Id.ToString(),
+                        StopReason = item.StopReason,
+                        Currency = item.Fee.Length > 3 ? item.Fee.Substring(item.Fee.Length - 3, 3) : "",
+                        TotalCost = item.Cost
+                    });
+
+                }
+
+            }
+            catch (Exception ex)
+            {
+
+            }
+
+
+            return detail;
+        }
+
+
+        private Status ConvertConnectorStatus(int value)
+        {
+            Status result = Status.Unknown;
+
+            switch (value)
+            {
+                case 1://Available
+                    {
+                        result = Status.Available;
+                    }
+                    break;
+                case 2://Preparing
+                    {
+                        result = Status.Preparing;
+                    }
+                    break;
+                case 3://Charging
+                    {
+                        result = Status.Charging;
+                    }
+                    break;
+                case 4://SuspendedEVSE
+                    {
+                        result = Status.SuspendedEVSE;
+                    }
+                    break;
+                case 5://SuspendedEV
+                    {
+                        result = Status.SuspendedEV;
+                    }
+                    break;
+                case 6://Finishing
+                    {
+                        result = Status.Finishing;
+                    }
+                    break;
+                case 7://Reserved
+                    {
+                        result = Status.Reserved;
+                    }
+                    break;
+                case 8://Unavailable
+                    {
+                        result = Status.Unavailable;
+                    }
+                    break;
+                case 9://Faulted
+                    {
+                        result = Status.Faulted;
+                    }
+                    break;
+                default:
+                    break;
+
+
+
+            }
+            return result;
+
+        }
+
+
+
+        private ConnectorType ConvertConnectorType(int value)
+        {
+            ConnectorType result = (ConnectorType)value;
+
+            return result;
+        }
+
+    }
+}

+ 551 - 0
EVCB_OCPP.WEBAPI/Services/Integration/ChargePoint201Service.cs

@@ -0,0 +1,551 @@
+using Dapper;
+using EVCB_OCPP.Packet.Messages.SubTypes;
+using EVCB_OCPP.WEBAPI.Models;
+using EVCB_OCPP.WEBAPI.Models.WebAPI;
+using EVCB_OCPP.WEBAPI.Models.WebAPI.Dto;
+using System;
+using System.Collections.Generic;
+using System.Configuration;
+using System.Data;
+using System.Data.SqlClient;
+using System.Linq;
+using System.Web;
+
+namespace EVCB_OCPP.WEBAPI.Services.Integration
+{
+    public class ConnectorStatusDto_ocpp201
+    {
+        public int Status { set; get; }
+
+        public string ChargingState { set; get; }
+    }
+    public class ChargePoint201Service : IChargePointService
+    {
+
+        string mainConnectionString = ConfigurationManager.ConnectionStrings["Main20DBContext"].ConnectionString;
+        string meterConnectionString = ConfigurationManager.ConnectionStrings["MeterValue20DBContext"].ConnectionString;
+        public bool ContainsChargePoint(string chargeBoxId, string customerId)
+        {
+            bool existed = false;
+
+            if (string.IsNullOrEmpty(chargeBoxId)) return existed;
+
+            var parameters = new DynamicParameters();
+            parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input);
+            parameters.Add("@CustomerId", customerId, DbType.String, ParameterDirection.Input);
+
+
+            using (SqlConnection conn = new SqlConnection(mainConnectionString))
+            {
+                string strSql = "Select Count(*) from [dbo].[Machine] where ChargeBoxId=@ChargeBoxId and CustomerId=@CustomerId  and IsDelete=0; ";
+                existed = conn.ExecuteScalar<bool>(strSql, parameters, null, EVCBConfiguration.DB_DefaultConnectionTimeout);
+            }
+
+            return existed;
+        }
+
+        public bool Exists(string chargeBoxId)
+        {
+            bool exists = false;
+
+            if (string.IsNullOrEmpty(chargeBoxId)) return exists;
+            var parameters = new DynamicParameters();
+            parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input);
+            using (SqlConnection conn = new SqlConnection(mainConnectionString))
+            {
+                string strSql = "Select count(*) from [dbo].[Machine] where ChargeBoxId=@ChargeBoxId  and IsDelete=0; ";
+                exists = conn.ExecuteScalar<bool>(strSql, parameters, null, EVCBConfiguration.DB_DefaultConnectionTimeout);
+            }
+            return exists;
+        }
+
+        public List<TransasctionData> GetActiveSessionInfo(string chargeBoxId, List<Measurand> requiredMeasurands, string sessionId = "", string idTag = "")
+        {
+            List<ConnectorMeterValue> meterValues = new List<ConnectorMeterValue>();
+            ConnectorMeterValueModel meterModel = null;
+            List<TransasctionData> transactionDatas = null;
+            if (string.IsNullOrEmpty(chargeBoxId)) return transactionDatas;
+
+
+            try
+            {
+                var parameters = new DynamicParameters();
+                parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input);
+
+
+                using (SqlConnection conn = new SqlConnection(mainConnectionString))
+                {
+                    string date = DateTime.UtcNow.ToString("yyMMdd");
+                    string strSql = string.Empty;
+                    if (string.IsNullOrEmpty(sessionId) && string.IsNullOrEmpty(idTag))
+                    {
+                        strSql = "Select Id, ConnectorId, StartTime,Fee, StartIdTag from TransactionRecord " +
+                            "where StopTime = '1991-01-01 00:00:00.000' and ChargeBoxId = @ChargeBoxId and StartTime in (select  max(StartTime) from[TransactionRecord] where StopTime = '1991-01-01 00:00:00.000' and ChargeBoxId = @ChargeBoxId group by ConnectorId )";
+                    }
+                    else
+                    {
+                        parameters.Add(string.IsNullOrEmpty(sessionId) ? "@StartIdTag" : "@Id", string.IsNullOrEmpty(sessionId) ? idTag : sessionId, DbType.String, ParameterDirection.Input);
+
+                        strSql = "Select Id, ConnectorId, StartTime,Fee, StartIdTag from TransactionRecord" +
+                          "where StopTime = '1991-01-01 00:00:00.000' and ChargeBoxId = @ChargeBoxId and StartTime in (select  max(StartTime) from [TransactionRecord] where  " + (string.IsNullOrEmpty(sessionId) ? "StartIdTag=@StartIdTag" : "Id=@TransactionId") + " and StopTime = '1991-01-01 00:00:00.000' and ChargeBoxId = @ChargeBoxId group by ConnectorId )";
+
+                    }
+
+                    transactionDatas = conn.Query<TransasctionData>(strSql, parameters, null, true, EVCBConfiguration.DB_DefaultConnectionTimeout).ToList();
+
+
+                }
+
+            }
+            catch (Exception ex)
+            {
+                ;
+            }
+
+
+            for (int i = 0; i < requiredMeasurands.Count; i++)
+            {
+                for (int j = 0; j < transactionDatas.Count; j++)
+                {
+                    var parameters = new DynamicParameters();
+                    parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input);
+                    parameters.Add("@TransactionId", transactionDatas[j].Id, DbType.String, ParameterDirection.Input);
+                    parameters.Add("@MeasurandId", requiredMeasurands[i], DbType.String, ParameterDirection.Input);
+
+                    try
+                    {
+                        using (SqlConnection conn = new SqlConnection(meterConnectionString))
+                        {
+                            string date = transactionDatas[j].StartTime.ToString("yyMMdd");
+                            string strSql = "Select Top(1) * from [dbo].[ConnectorMeterValueRecord" + date + "] where ChargeBoxId=@ChargeBoxId and TransactionId=@TransactionId and MeasurandId=@MeasurandId order by CreatedOn desc;";
+                            meterModel = conn.Query<ConnectorMeterValueModel>(strSql, parameters, null, true, EVCBConfiguration.DB_DefaultConnectionTimeout).FirstOrDefault();
+
+                        }
+
+                        if (meterModel != null)
+                        {
+                            if (transactionDatas[j].MeterValues == null)
+                            {
+                                transactionDatas[j].MeterValues = new List<ConnectorMeterValue>();
+                            }
+
+                            transactionDatas[j].MeterValues.Add(new ConnectorMeterValue()
+                            {
+                                ChargeBoxId = meterModel.ChargeBoxId,
+                                ConnectorId = meterModel.ConnectorId,
+                                CreatedOn = meterModel.CreatedOn,
+                                Context = meterModel.ContextId < 1 ? (ReadingContext?)null : (ReadingContext?)meterModel.ContextId,
+                                Format = meterModel.FormatId < 1 ? (ValueFormat?)null : (ValueFormat?)meterModel.FormatId,
+                                Location = meterModel.LocationId < 1 ? (Location?)null : (Location?)meterModel.LocationId,
+                                Measurand = meterModel.MeasurandId < 1 ? (Measurand?)null : (Measurand?)meterModel.MeasurandId,
+                                Phase = meterModel.PhaseId < 1 ? (Phase?)null : (Phase?)meterModel.PhaseId,
+                                Unit = meterModel.UnitId < 1 ? (UnitOfMeasure?)UnitOfMeasure.Wh : (UnitOfMeasure?)meterModel.UnitId,
+                                Value = meterModel.Value,
+                                TransactionId = meterModel.TransactionId
+
+                            });
+
+
+
+                        }
+                    }
+                    catch (Exception ex)
+                    {
+                        break;
+                    }
+                }
+
+
+            }
+
+            return transactionDatas;
+        }
+
+        public EVSE GetBasicInfobyId(string machineId)
+        {
+            EVSE cp = new EVSE();
+            Machine _machine = new Machine();
+            using (SqlConnection conn = new SqlConnection(mainConnectionString))
+            {
+                var parameters = new DynamicParameters();
+                parameters.Add("@Id", machineId, DbType.String, ParameterDirection.Input);
+                string strSql = "Select ChargeBoxId,ChargePointSerialNumber,ModelName,RatedPower,Online,OfflineOn ,GunAmt,Latitude,Longitude,ConnectorType from [dbo].[Machine] where Id=@Id and IsDelete=0; ";
+                _machine = conn.Query<Machine>(strSql, parameters).FirstOrDefault();
+            }
+            if (_machine != null)
+            {
+                cp.ChargeBoxSystemID = _machine.ModelName + _machine.ChargePointSerialNumber;
+                cp.ChargeBoxId = _machine.ChargeBoxId;
+                cp.NumberofConnectors = _machine.GunAmt;
+                cp.RatedPower = _machine.RatedPower;
+                cp.Status = _machine.Online ? Status.Available : Status.Offline;
+                cp.LastUpdated = _machine.CreatedOn > _machine.OfflineOn ? _machine.CreatedOn : _machine.OfflineOn;
+                cp.Coordinates = new GeoLocation() { Latitude = _machine.Latitude, Longitude = _machine.Longitude };
+                cp.Connectors = new List<Connector>();
+                var _Connectors = GetConnectorStatus(_machine.ChargeBoxId);
+                for (int i = 1; i <= _machine.GunAmt; i++)
+                {
+                    var _RefConnector = _Connectors.Where(x => x.ConnectorId == i).FirstOrDefault();
+                    cp.Connectors.Add(new Connector()
+                    {
+                        ConnectorId = _RefConnector == null ? i : _RefConnector.ConnectorId,
+                        Status = cp.Status == Status.Offline ? Status.Offline : _RefConnector == null ? Status.Unknown : (Status)(int)ConvertConnectorStatus(new ConnectorStatusDto_ocpp201() { Status = _RefConnector.Status, ChargingState = _RefConnector.ChargingState }),
+                        ConnectorType = ConvertConnectorType(int.Parse(_machine.ConnectorType.Split(',')[i - 1]))
+                    });
+                }
+            }
+            return _machine == null ? null : cp;
+        }
+
+        public ChargePointStatus? GetChargePointCurrentSatus(string chargeBoxId, int connectorId = 0)
+        {
+            ChargePointStatus? _status = null;
+
+            if (string.IsNullOrEmpty(chargeBoxId)) return _status;
+
+            var parameters = new DynamicParameters();
+            parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input);
+            parameters.Add("@ConnectorId", connectorId, DbType.Int32, ParameterDirection.Input);
+
+            using (SqlConnection conn = new SqlConnection(mainConnectionString))
+            {
+                string strSql = "Select online from [dbo].[Machine] where ChargeBoxId=@ChargeBoxId  and IsDelete=0; ";
+                bool online = conn.ExecuteScalar<bool>(strSql, parameters, null, EVCBConfiguration.DB_DefaultConnectionTimeout);
+
+                if (online)
+                {
+                    string connectorStrSql = "Select Status,ChargingState from [dbo].[ConnectorStatus] where ChargeBoxId=@ChargeBoxId and ConnectorId=@ConnectorId; ";
+
+                    var _statusfromdb = conn.Query<ConnectorStatusDto_ocpp201>(connectorStrSql, parameters).FirstOrDefault();
+
+                    _status = (connectorId == 0) ? ((ChargePointStatus?)null) : ConvertConnectorStatus(_statusfromdb);
+
+                }
+
+            }
+
+            return _status;
+        }
+
+        public List<ConnectorStatus> GetConnectorStatus(string chargeBoxId)
+        {
+            List<ConnectorStatus> _Connectors = new List<ConnectorStatus>();
+            using (SqlConnection conn = new SqlConnection(mainConnectionString))
+            {
+                var parameters = new DynamicParameters();
+                parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input);
+                string strSql = "Select ConnectorId,Status,ChargingState from [dbo].[ConnectorStatus] where ChargeBoxId=@ChargeBoxId order by  ConnectorId; ";
+                _Connectors = conn.Query<ConnectorStatus>(strSql, parameters).SkipWhile(x => x.ConnectorId == 0).ToList();
+            }
+
+
+
+            return _Connectors;
+        }
+
+        public int GetConnectorwithOngoingTransaction(string chargeBoxId, string transactionId)
+        {
+            int connectorId = -1;
+
+            if (string.IsNullOrEmpty(chargeBoxId)) return connectorId;
+
+            var parameters = new DynamicParameters();
+            parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input);
+            parameters.Add("@TransactionId", transactionId, DbType.Int32, ParameterDirection.Input);
+            using (SqlConnection conn = new SqlConnection(mainConnectionString))
+            {
+                string strSql = "Select ConnectorId from [dbo].[TransactionRecord] where ChargeBoxId=@ChargeBoxId and TransactionId= @TransactionId and StopTime='1991/01/01'; ";
+                connectorId = conn.Query<Int32>(strSql, parameters).FirstOrDefault();
+            }
+
+            return connectorId;
+        }
+
+        public EVSE GetEVSEsbyChargeBoxId(string chargeboxid, DateTime? dateFrom, DateTime? dateTo)
+        {
+            string machineId = GetMachineIdbyChargeBoxId(chargeboxid);
+
+            var _machineUpdateOn = GetLastUpdatedTimebyMachineId(machineId);
+            var _machine = GetBasicInfobyId(machineId);
+            _machine.LastUpdated = _machineUpdateOn;
+
+
+            return _machine;
+        }
+
+        public DateTime GetLastUpdatedTimebyMachineId(string machineId)
+        {
+            DateTime lastUpdatedOn = DateTime.UtcNow;
+            using (SqlConnection conn = new SqlConnection(mainConnectionString))
+            {
+                var parameters = new DynamicParameters();
+
+                parameters.Add("@MachineId", machineId, DbType.String, ParameterDirection.Input);
+                parameters.Add("@LastUpdatedTime", lastUpdatedOn, DbType.DateTime, ParameterDirection.Output);
+                conn.Execute("GetBasicInfoLastUpdatedTimeById", parameters, commandType: System.Data.CommandType.StoredProcedure);
+                DateTime? time = null;
+                try
+                {
+                    time = parameters.Get<DateTime>("@LastUpdatedTime");
+
+                }
+                catch (Exception ex)
+                {
+                    time = DateTime.UtcNow;
+                }
+                lastUpdatedOn = DateTime.SpecifyKind(time.Value, DateTimeKind.Utc);
+            }
+
+            return lastUpdatedOn;
+        }
+
+        public string GetMachineIdbyChargeBoxId(string chargeBoxId)
+        {
+            string machineId = string.Empty;
+            using (SqlConnection conn = new SqlConnection(mainConnectionString))
+            {
+                var parameters = new DynamicParameters();
+                parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input);
+                string strSql = "Select Id from [dbo].[Machine] where ChargeBoxId=@ChargeBoxId and IsDelete=0; ";
+                machineId = conn.Query<string>(strSql, parameters).FirstOrDefault();
+
+            }
+
+            return machineId;
+        }
+
+        public int GetNumberofConnectors(string chargeBoxId)
+        {
+            int count = 0;
+
+            if (string.IsNullOrEmpty(chargeBoxId)) return -1;
+            if (Exists(chargeBoxId))
+            {
+                var parameters = new DynamicParameters();
+                parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input);
+                using (SqlConnection conn = new SqlConnection(mainConnectionString))
+                {
+                    string strSql = "Select GunAmt from [dbo].[Machine] where ChargeBoxId=@ChargeBoxId  and IsDelete=0; ";
+                    count = conn.ExecuteScalarAsync<int>(strSql, parameters, null, EVCBConfiguration.DB_DefaultConnectionTimeout).Result;
+                }
+
+            }
+            return count;
+        }
+
+        public DateTime GetMachineUpdatedOn(string chargeBoxId)
+        {
+            DateTime dt = new DateTime();
+            string machineId = string.Empty;
+            using (SqlConnection conn = new SqlConnection(mainConnectionString))
+            {
+                var parameters = new DynamicParameters();
+                parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input);
+                string strSql = "Select HeartbeatUpdatedOn from [dbo].[Machine] where ChargeBoxId=@ChargeBoxId and IsDelete=0; ";
+                dt = conn.Query<DateTime>(strSql, parameters).FirstOrDefault();
+
+            }
+
+            return dt;
+
+        }
+        public List<SessionDetail> GetSessionDetail(string chargeBoxId, string sessionId, string idTag, DateTime startTime, DateTime stopTime)
+        {
+            List<SessionDetail> detail = new List<SessionDetail>();
+            List<TransactionRecordModel> transactionModel = null;
+            if (string.IsNullOrEmpty(chargeBoxId)) return detail;
+
+
+            var parameters = new DynamicParameters();
+
+            try
+            {
+
+                bool restrictedRange = false;
+                if (startTime != new DateTime(1991, 1, 1))
+                {
+                    restrictedRange = true;
+                    parameters.Add("@startTime", startTime, DbType.DateTime, ParameterDirection.Input);
+                    parameters.Add("@stopTime", stopTime, DbType.DateTime, ParameterDirection.Input);
+                }
+
+                using (SqlConnection conn = new SqlConnection(mainConnectionString))
+                {
+                    string strSql = string.Empty;
+                    if (!string.IsNullOrEmpty(sessionId) && string.IsNullOrEmpty(idTag))
+                    {
+                        parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input);
+                        parameters.Add("@TransactionId", sessionId, DbType.String, ParameterDirection.Input);
+                        strSql = "Select Top(1) * from [dbo].[TransactionRecord] where ChargeBoxId=@ChargeBoxId and TransactionId=@TransactionId and StopTime!='1991-01-01 00:00:00.000' " + (restrictedRange ? " and StartTime >=@startTime and  StartTime <=@stopTime" : "") + " Order by Id desc ;";
+                    }
+                    else if (!string.IsNullOrEmpty(idTag) && string.IsNullOrEmpty(sessionId))
+                    {
+                        if (!string.IsNullOrEmpty(chargeBoxId))
+                        {
+                            parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input);
+                        }
+
+                        parameters.Add("@StartIdTag", idTag, DbType.String, ParameterDirection.Input);
+                        strSql = "Select  * from [dbo].[TransactionRecord] where " + (!string.IsNullOrEmpty(chargeBoxId) ? " ChargeBoxId=@ChargeBoxId and  " : "") + "  StartIdTag=@StartIdTag   and StopTime!='1991-01-01 00:00:00.000' " + (restrictedRange ? " and StartTime >=@startTime and  StartTime <=@stopTime" : "") + " Order by Id desc  ;";
+
+                    }
+                    else
+                    {
+
+                        parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input);
+
+                        strSql = "Select  * from [dbo].[TransactionRecord] where ChargeBoxId=@ChargeBoxId  and StopTime!='1991-01-01 00:00:00.000' " + (restrictedRange ? " and StartTime >=@startTime and  StartTime <=@stopTime" : "") + " Order by Id desc  ;";
+
+                    }
+
+                    transactionModel = conn.Query<TransactionRecordModel>(strSql, parameters, null, true, EVCBConfiguration.DB_DefaultConnectionTimeout).ToList();
+
+
+                }
+
+                foreach (var item in transactionModel)
+                {                  
+
+                    detail.Add(new SessionDetail()
+                    {
+                        ChargeBoxId = item.ChargeBoxId,
+                        ConnectorId = (int)item.ConnectorId,
+                        IdTag = item.StartIdTag,
+                        MeterStart = item.MeterStart,
+                        MeterStop = item.MeterStop,
+                        StartTime = item.StartTime.ToString(EVCBConfiguration.UTC_DATETIMEFORMAT),
+                        StopTime = item.StopTime.ToString(EVCBConfiguration.UTC_DATETIMEFORMAT),
+                        StopReason = item.StopReason,
+                        SessionId = item.Id.ToString(),
+                        Currency = item.Fee.Length > 3 ? item.Fee.Substring(item.Fee.Length - 3, 3) : "",
+                        TotalCost = item.Cost
+
+                    }); ;
+
+                }
+
+            }
+            catch (Exception ex)
+            {
+
+            }
+
+
+            return detail;
+        }
+
+        public string GetVersionbyChargeBoxId(string chargeBoxId)
+        {
+            string version = string.Empty;
+            using (SqlConnection conn = new SqlConnection(mainConnectionString))
+            {
+                var parameters = new DynamicParameters();
+                parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input);
+                string strSql = "Select BoardVersions from [dbo].[Machine] where ChargeBoxId=@ChargeBoxId and IsDelete=0; ";
+                version = conn.Query<string>(strSql, parameters).FirstOrDefault();
+            }
+            return version;
+        }
+
+        public bool IsOnline(string chargeBoxId)
+        {
+            bool online = false;
+
+            if (string.IsNullOrEmpty(chargeBoxId)) return online;
+
+            var parameters = new DynamicParameters();
+            parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input);
+
+
+            using (SqlConnection conn = new SqlConnection(mainConnectionString))
+            {
+                string strSql = "Select online from [dbo].[Machine] where ChargeBoxId=@ChargeBoxId  and IsDelete=0; ";
+                online = conn.ExecuteScalar<bool>(strSql, parameters, null, EVCBConfiguration.DB_DefaultConnectionTimeout);
+            }
+
+            return online;
+        }
+
+        public bool IsTransactionRunning(string chargeBoxId, string transactionId)
+        {
+            bool exists = false;
+
+            if (string.IsNullOrEmpty(chargeBoxId)) return exists;
+
+            var parameters = new DynamicParameters();
+            parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input);
+            parameters.Add("@TransactionId", transactionId, DbType.Int32, ParameterDirection.Input);
+            using (SqlConnection conn = new SqlConnection(mainConnectionString))
+            {
+                string strSql = "Select Id from [dbo].[TransactionRecord] where ChargeBoxId=@ChargeBoxId and TransactionId= @TransactionId and StopTime='1991/01/01'; ";
+                int id = conn.Query<Int32>(strSql, parameters).FirstOrDefault();
+                exists = id > 0 ? true : false;
+            }
+            return exists;
+        }
+
+        private ChargePointStatus? ConvertConnectorStatus(ConnectorStatusDto_ocpp201 status)
+        {
+            ChargePointStatus? result = null;
+
+            switch (status.Status)
+            {
+                case 1://Available
+                    {
+                        result = ChargePointStatus.Available;
+                    }
+                    break;
+                case 2://Occupied
+                    {
+                        if (status.ChargingState == "Charging")
+                        {
+                            result = ChargePointStatus.Charging;
+                        }
+                        else if (status.ChargingState == "EVConnected" || string.IsNullOrEmpty(status.ChargingState))
+                        {
+                            result = ChargePointStatus.Preparing;
+                        }
+                        else if (status.ChargingState == "SuspendedEV")
+                        {
+                            result = ChargePointStatus.SuspendedEV;
+                        }
+                        else if (status.ChargingState == "SuspendedEVSE")
+                        {
+                            result = ChargePointStatus.SuspendedEVSE;
+                        }
+
+                    }
+                    break;
+                case 3://Unavailable
+                    {
+                        result = ChargePointStatus.Unavailable;
+                    }
+                    break;
+                case 4://Reserved
+                    {
+                        result = ChargePointStatus.Reserved;
+                    }
+                    break;
+                case 5://Faulted
+                    {
+                        result = ChargePointStatus.Faulted;
+                    }
+                    break;
+                default:
+                    break;
+
+
+
+            }
+            return result;
+
+        }
+
+        private ConnectorType ConvertConnectorType(int value)
+        {
+            ConnectorType result = (ConnectorType)value;
+
+            return result;
+        }
+    }
+}

+ 153 - 0
EVCB_OCPP.WEBAPI/Services/Integration/ChargingStationService.cs

@@ -0,0 +1,153 @@
+using Dapper;
+using EVCB_OCPP.WEBAPI.Models.WebAPI;
+using EVCB_OCPP.WEBAPI.Models.WebAPI.Dto;
+using System;
+using System.Collections.Generic;
+using System.Configuration;
+using System.Data;
+using System.Data.SqlClient;
+using System.Linq;
+using System.Web;
+
+namespace EVCB_OCPP.WEBAPI.Services.Integration
+{
+    
+    /// <summary>
+    /// 抓充電站資訊 從Web撈資料
+    /// 因此沒有分 ocpp16....  機器
+    /// </summary>
+    public class ChargingStationService
+    {       //MainDBContext
+        string webConnectionString = ConfigurationManager.ConnectionStrings["WebDBContext"].ConnectionString;
+        string main16ConnectionString = ConfigurationManager.ConnectionStrings["MainDBContext"].ConnectionString;
+
+        public List<Station> GetStationsbyCustomerId(string customerId)
+        {
+            List<Station> _stations = new List<Station>();
+
+            var parameters = new DynamicParameters();
+            parameters.Add("@CustomerId", customerId, DbType.String, ParameterDirection.Input);
+            using (SqlConnection conn = new SqlConnection(webConnectionString))
+            {
+                string strSql = "Select Id, Name ,Latitude,Longitude from [dbo].[Station] where CustomerId=@CustomerId; ";
+                _stations = conn.Query<Station>(strSql, parameters).ToList();
+
+            }
+
+            if (_stations != null)
+            {
+                foreach (var station in _stations)
+                {
+                    station.Coordinates = new GetLocation() { Latitude = station.Latitude, Longitude = station.Longitude };
+                    station.EVSEs = GetEVSEsbyStationId(station.Id, null, null, -1, 100000);
+
+                }
+            }
+            return _stations;
+        }
+
+        public bool ContainsStation(string customerId, int stationId)
+        {
+            bool isContains = false;
+
+            var parameters = new DynamicParameters();
+            parameters.Add("@CustomerId", customerId, DbType.String, ParameterDirection.Input);
+            parameters.Add("@Id", stationId, DbType.Int32, ParameterDirection.Input);
+            using (SqlConnection conn = new SqlConnection(webConnectionString))
+            {
+                string strSql = "Select count(*) from [dbo].[Station] where CustomerId=@CustomerId and Id=@Id; ";
+                isContains = conn.ExecuteScalar<Int32>(strSql, parameters) > 0 ? true : false;
+            }
+
+            return isContains;
+        }
+
+
+        public List<EVSE> GetEVSEsbyStationId(int stationId, DateTime? dateFrom, DateTime? dateTo, int offset = -1, int limit = 10)
+        {
+            List<EVSE> _chargePoints = new List<EVSE>();
+            var parameters = new DynamicParameters();
+            parameters.Add("@StationId", stationId, DbType.Int16, ParameterDirection.Input);
+            int counter = 0;
+            int startIndex = offset == -1 ? 0 : offset;
+            limit = limit + startIndex;
+            List<string> machineIds = new List<string>();
+            using (SqlConnection conn = new SqlConnection(webConnectionString))
+            {
+                string strSql = "Select MachineId from [dbo].[StationMachine] where StationId=@StationId; ";
+                machineIds = conn.Query<String>(strSql, parameters).ToList();
+            }
+          
+            while (startIndex < limit && startIndex < machineIds.Count)
+            {
+                var machine_by201 = new ChargePoint201Service().GetBasicInfobyId(machineIds[startIndex]);
+                var machine_by16 = new ChargePoint16Service().GetBasicInfobyId(machineIds[startIndex]);
+                var machine201UpdateOn = machine_by201==null? EVCBConfiguration.DefaultTime:machine_by201.LastUpdated;
+                var machine16UpdateOn = machine_by16 == null ? EVCBConfiguration.DefaultTime : machine_by16.LastUpdated;
+                int connectiontype = machine201UpdateOn > machine16UpdateOn ? 2 : 1;
+                var machineUpdateOn = connectiontype == 2 ? machine201UpdateOn : machine16UpdateOn;
+                var machine = connectiontype == 2 ? machine_by201 : machine_by16;
+                if ((dateFrom.HasValue && machineUpdateOn < dateFrom.Value.ToUniversalTime()) )
+                {
+                    limit++;
+                    startIndex++;
+                    continue;
+                }
+
+                if (dateFrom.HasValue && dateTo.HasValue && (machineUpdateOn < dateFrom.Value.ToUniversalTime() || machineUpdateOn > dateTo.Value.ToUniversalTime()))
+                    
+                {
+                    limit++;
+                    startIndex++;
+                    continue;
+                }
+
+           
+                if (machine != null)
+                {
+                    machine.LastUpdated = machineUpdateOn;
+                    machine.StationId = stationId;
+                    _chargePoints.Add(machine);
+
+                }
+                else
+                {
+                    limit++;
+                }
+
+                startIndex++;
+
+            }
+            return _chargePoints;
+        }
+
+
+        public Station GetInfobyChargeBoxId(string chargeBoxId)
+        {
+            Station result = null;
+            var parameters = new DynamicParameters();
+            parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input);
+           
+            string machineId = string.Empty;
+            using (SqlConnection conn = new SqlConnection(main16ConnectionString))
+            {
+                string strSql = "SELECT Machine.Id from [dbo].[Machine] " +
+                " where ChargeBoxId=@ChargeBoxId; ";
+                machineId = conn.Query<string>(strSql, parameters).FirstOrDefault();
+
+            }
+            parameters.Add("@MachineId", machineId, DbType.String, ParameterDirection.Input);
+            using (SqlConnection conn = new SqlConnection(webConnectionString))
+            {
+                string strSql = "SELECT * from [dbo].[Station] station where Id in( select StationId  FROM[dbo].[Machine],[dbo].[StationMachine] " +
+                " where StationMachine.MachineId= @MachineId); ";
+                result = conn.Query<Station>(strSql, parameters).FirstOrDefault();
+
+            }
+
+            return result;
+        }
+
+
+    }
+}

+ 369 - 0
EVCB_OCPP.WEBAPI/Services/Integration/ServerTriggerService.cs

@@ -0,0 +1,369 @@
+using Dapper;
+using EVCB_OCPP.Packet.Features;
+using EVCB_OCPP20.Packet.Messages;
+using EVCB_OCPP.Packet.Messages.SubTypes;
+using EVCB_OCPP.WEBAPI.Models.WebAPI;
+using Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.Configuration;
+using System.Data;
+using System.Data.SqlClient;
+using System.Linq;
+using System.Net;
+using System.Web;
+
+namespace EVCB_OCPP.WEBAPI.Services.Integration
+{
+
+    public interface IServerTriggerService
+    {
+        void AddMessage(string ChargeBoxId, string uuid, IRequest request);
+
+    }
+
+    public enum Internal_ExecutionCode
+    {
+
+        Accepted = 1,
+        Blocked,
+        Expired,
+        Invalid,
+        ConcurrentTx,
+        Scheduled,
+        Inoperative,
+        Operative,
+        NotSupported,
+        Unknown,
+        RebootRequired,
+        UnknownMessageId,
+        UnknownVendorId,
+        Idle,
+        Uploaded,
+        UploadFailed,
+        Uploading,
+        Downloaded,
+        DownloadFailed,
+        Downloading,
+        Installing,
+        InstallationFailed,
+        Installed,
+        Pending,
+        Faulted,
+        Occupied,
+        Unavailable,
+        Unlocked,
+        UnlockFailed,
+        VersionMismatch,
+        Rejected,
+        Failed,
+
+
+
+    }
+
+    public enum Internal_Actions
+    {
+        ChangeAvailability = 1,
+        ChangeConfiguration,
+        GetConfiguration,
+        CancelReservation,
+        ClearCache,
+        ClearChargingProfile,
+        GetCompositeSchedule,
+        GetDiagnostics,
+        GetLocalListVersion,
+        RemoteStartTransaction,
+        RemoteStopTransaction,
+        ReserveNow,
+        Reset,
+        SendLocalList,
+        SetChargingProfile,
+        TriggerMessage,
+        UnlockConnector,
+        DataTransfer
+
+    }
+
+
+
+
+    public class ServerTriggerService : IServerTriggerService
+    {
+
+        string mainConnectionString = ConfigurationManager.ConnectionStrings["MainDBContext"].ConnectionString;
+        public ServerTriggerService()
+        {
+            var dt = new DateTime(1991, 1, 1).AddHours(8).ToUniversalTime();
+            long ticks = dt.Ticks;
+        }
+
+        public void AddMessage(string ChargeBoxId, string uuid, IRequest request)
+        {
+            string sql_MachineOperateRecord = "INSERT INTO [dbo].[MachineOperateRecord](SerialNo, RequestType, Status, CreatedOn, FinishedOn,"
+         + " EVSE_Value, EVSE_Status, ChargeBoxId, Action, ReportedOn) VALUES (@SerialNo, @RequestType,  @Status, @CreatedOn, @FinishedOn, @EVSE_Value, "
+         + "@EVSE_Status, @ChargeBoxId, @Action,@ReportedOn);";
+
+            string sql_ServerMessage = "INSERT INTO [dbo].[ServerMessage] (SerialNo, OutAction, OutRequest, InMessage, CreatedOn, CreatedBy, ReceivedOn, ChargeBoxId" +
+                ", UpdatedOn)  VALUES (@SerialNo, @OutAction, @OutRequest, @InMessage, @CreatedOn, @CreatedBy, @ReceivedOn, @ChargeBoxId" +
+                ", @UpdatedOn);";
+
+            string key = string.Empty;
+            var parameters = new DynamicParameters();
+            parameters.Add("@ChargeBoxId", ChargeBoxId, DbType.String, ParameterDirection.Input);
+            parameters.Add("@RequestType", 1, DbType.Int32, ParameterDirection.Input);
+            parameters.Add("@RequestContent", JsonConvert.SerializeObject(request, EVCBConfiguration.JSONSERIALIZER_FORMAT), DbType.String, ParameterDirection.Input);
+            parameters.Add("@Status", 0, DbType.Int32, ParameterDirection.Input);
+            parameters.Add("@CreatedOn", DateTime.Now.ToUniversalTime(), DbType.DateTime, ParameterDirection.Input);
+            parameters.Add("@FinishedOn", EVCBConfiguration.DefaultTime, DbType.DateTime, ParameterDirection.Input);
+            parameters.Add("@EVSE_Value", string.Empty, DbType.String, ParameterDirection.Input);
+            parameters.Add("@EVSE_Status", 0, DbType.Int32, ParameterDirection.Input);
+            parameters.Add("@SerialNo", uuid, DbType.String, ParameterDirection.Input);
+            parameters.Add("@Action", request.Action, DbType.String, ParameterDirection.Input);
+
+            parameters.Add("@OutAction", request.Action, DbType.String, ParameterDirection.Input);
+            parameters.Add("@OutRequest", JsonConvert.SerializeObject(request, EVCBConfiguration.JSONSERIALIZER_FORMAT), DbType.String, ParameterDirection.Input);
+            parameters.Add("@InMessage", "", DbType.String, ParameterDirection.Input);
+            parameters.Add("@CreatedOn", DateTime.Now.ToUniversalTime(), DbType.DateTime, ParameterDirection.Input);
+            parameters.Add("@CreatedBy", "WebAPI", DbType.String, ParameterDirection.Input);
+            parameters.Add("@ReceivedOn", EVCBConfiguration.DefaultTime, DbType.DateTime, ParameterDirection.Input);
+            parameters.Add("@UpdatedOn", EVCBConfiguration.DefaultTime, DbType.DateTime, ParameterDirection.Input);
+            parameters.Add("@ReportedOn", EVCBConfiguration.DefaultTime, DbType.DateTime, ParameterDirection.Input);
+
+
+            using (SqlConnection conn = new SqlConnection(mainConnectionString))
+            {
+                conn.Open();
+                using (var transaction = conn.BeginTransaction())
+                {
+                    try
+                    {
+                        conn.Execute(sql_MachineOperateRecord, parameters, transaction);
+                        conn.Execute(sql_ServerMessage, parameters, transaction);
+                        transaction.Commit();
+                    }
+                    catch
+                    {
+                        transaction.Rollback();
+                        throw;
+                    }
+                }
+
+            }
+        }
+
+        public void AddMessage(string ChargeBoxId, string uuid, EVCB_OCPP.Packet.Messages.IRequest request)
+        {
+            string sql_MachineOperateRecord = "INSERT INTO [dbo].[MachineOperateRecord](SerialNo, RequestType, RequestContent,Status, CreatedOn, FinishedOn,"
+         + " EVSE_Value, EVSE_Status, ChargeBoxId, Action, ReportedOn) VALUES (@SerialNo, @RequestType, @RequestContent, @Status, @CreatedOn, @FinishedOn, @EVSE_Value, "
+         + "@EVSE_Status, @ChargeBoxId, @Action,@ReportedOn);";
+
+            string sql_ServerMessage = "INSERT INTO [dbo].[ServerMessage] (SerialNo, OutAction, OutRequest, InMessage, CreatedOn, CreatedBy, ReceivedOn, ChargeBoxId" +
+                ", UpdatedOn)  VALUES (@SerialNo, @OutAction, @OutRequest, @InMessage, @CreatedOn, @CreatedBy, @ReceivedOn, @ChargeBoxId" +
+                ", @UpdatedOn);";
+
+            string key = string.Empty;
+            var parameters = new DynamicParameters();
+            parameters.Add("@ChargeBoxId", ChargeBoxId, DbType.String, ParameterDirection.Input);
+            parameters.Add("@RequestType", 1, DbType.Int32, ParameterDirection.Input);
+            parameters.Add("@RequestContent", JsonConvert.SerializeObject(request, EVCBConfiguration.JSONSERIALIZER_FORMAT), DbType.String, ParameterDirection.Input);
+            parameters.Add("@Status", 0, DbType.Int32, ParameterDirection.Input);
+            parameters.Add("@CreatedOn", DateTime.Now.ToUniversalTime(), DbType.DateTime, ParameterDirection.Input);
+            parameters.Add("@FinishedOn", EVCBConfiguration.DefaultTime, DbType.DateTime, ParameterDirection.Input);
+            parameters.Add("@EVSE_Value", string.Empty, DbType.String, ParameterDirection.Input);
+            parameters.Add("@EVSE_Status", 0, DbType.Int32, ParameterDirection.Input);
+            parameters.Add("@SerialNo", uuid, DbType.String, ParameterDirection.Input);
+            parameters.Add("@Action", request.Action, DbType.String, ParameterDirection.Input);
+
+            parameters.Add("@OutAction", request.Action, DbType.String, ParameterDirection.Input);
+            parameters.Add("@OutRequest", JsonConvert.SerializeObject(request, EVCBConfiguration.JSONSERIALIZER_FORMAT), DbType.String, ParameterDirection.Input);
+            parameters.Add("@InMessage", "", DbType.String, ParameterDirection.Input);
+            parameters.Add("@CreatedOn", DateTime.Now.ToUniversalTime(), DbType.DateTime, ParameterDirection.Input);
+            parameters.Add("@CreatedBy", "WebAPI", DbType.String, ParameterDirection.Input);
+            parameters.Add("@ReceivedOn", EVCBConfiguration.DefaultTime, DbType.DateTime, ParameterDirection.Input);
+            parameters.Add("@UpdatedOn", EVCBConfiguration.DefaultTime, DbType.DateTime, ParameterDirection.Input);
+            parameters.Add("@ReportedOn", EVCBConfiguration.DefaultTime, DbType.DateTime, ParameterDirection.Input);
+
+
+            using (SqlConnection conn = new SqlConnection(mainConnectionString))
+            {
+                conn.Open();
+                using (var transaction = conn.BeginTransaction())
+                {
+                    try
+                    {
+                        conn.Execute(sql_MachineOperateRecord, parameters, transaction);
+                        conn.Execute(sql_ServerMessage, parameters, transaction);
+                        transaction.Commit();
+                    }
+                    catch
+                    {
+                        transaction.Rollback();
+                        throw;
+                    }
+                }
+
+            }
+        }
+
+
+        public ComandExecution GetExecution(string uuid, Internal_Actions action, string chargeBoxId)
+        {
+            if (string.IsNullOrEmpty(chargeBoxId) || string.IsNullOrEmpty(uuid)) return null;
+            ComandExecution excution = new ComandExecution();
+
+            try
+            {
+                var parameters = new DynamicParameters();
+                parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input);
+                parameters.Add("@SerialNo", uuid, DbType.String, ParameterDirection.Input);
+                parameters.Add("@Action", action.ToString(), DbType.String, ParameterDirection.Input);
+
+                MachineOperation operation = new MachineOperation();
+
+                using (SqlConnection conn = new SqlConnection(mainConnectionString))
+                {
+                    string strSql = "Select Top(1) Status,EVSE_Value,EVSE_Status,Action from [dbo].[MachineOperateRecord] where ChargeBoxId=@ChargeBoxId and SerialNo=@SerialNo and Action=@Action; ";
+                    operation = conn.Query<MachineOperation>(strSql, parameters, null, true, EVCBConfiguration.DB_DefaultConnectionTimeout).FirstOrDefault();
+                }
+
+                if (operation.EVSE_Status > 0)
+                {
+                    excution.IsRepliedbyEVSE = true;
+
+                    if (operation.Action == "GetLocalListVersion")
+                    {
+                        excution.Code = 1;
+                        excution.Detail = operation.EVSE_Value;
+                    }
+                    else
+                    {
+                        excution.Code = ConverttoCode(operation.EVSE_Value);
+                        excution.Code = excution.Code == -1 ? (operation.EVSE_Status == 1 ? 1 : (operation.EVSE_Status == 255 ? 254 : excution.Code)) : excution.Code;
+                        excution.Detail = operation.EVSE_Value;
+                    }
+
+                }
+                else
+                {
+                    excution.IsRepliedbyEVSE = false;
+                    if (operation.Status == 0)
+                    {
+                        excution.Code = 0;
+                        //excution.IsWaited = true;
+                        excution.Detail = "Waited";
+
+                    }
+                    if (operation.Status == -1)
+                    {
+                      //  excution.IsTimeout = true;
+                        excution.Code = 0;
+                        excution.Detail = "Timeout";
+                    }
+
+
+                }
+
+
+            }
+            catch
+            {
+                excution = null;
+            }
+
+
+
+            return excution;
+
+        }
+
+        public ComandExecution GetExecution_ocpp201(string uuid, Internal_Actions action, string chargeBoxId)
+        {
+            if (string.IsNullOrEmpty(chargeBoxId) || string.IsNullOrEmpty(uuid)) return null;
+            ComandExecution excution = new ComandExecution();
+
+            try
+            {
+                var parameters = new DynamicParameters();
+                parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input);
+                parameters.Add("@SerialNo", uuid, DbType.String, ParameterDirection.Input);
+                parameters.Add("@Action", action.ToString(), DbType.String, ParameterDirection.Input);
+
+                MachineOperation operation = new MachineOperation();
+
+                using (SqlConnection conn = new SqlConnection(mainConnectionString))
+                {
+                    string strSql = "Select Top(1) Status,EVSE_Value,EVSE_Status,Action from [dbo].[MachineOperateRecord] where ChargeBoxId=@ChargeBoxId and SerialNo=@SerialNo and Action=@Action; ";
+                    operation = conn.Query<MachineOperation>(strSql, parameters, null, true, EVCBConfiguration.DB_DefaultConnectionTimeout).FirstOrDefault();
+                }
+
+                if (operation.EVSE_Status > 0)
+                {
+                    excution.IsRepliedbyEVSE = true;
+
+                    if (operation.Action == "GetLocalListVersion")
+                    {
+                        excution.Code = 1;
+                        excution.Detail = operation.EVSE_Value;
+                    }
+                    else
+                    {
+                        excution.Code = ConverttoCode(operation.EVSE_Value);
+                        excution.Code = excution.Code == -1 ? (operation.EVSE_Status == 1 ? 1 : (operation.EVSE_Status == 255 ? 254 : excution.Code)) : excution.Code;
+                        excution.Detail = operation.EVSE_Value;
+                    }
+
+                }
+                else
+                {
+                    excution.IsRepliedbyEVSE = false;
+                    if (operation.Status == 0)
+                    {
+                        excution.Code = 0;
+                        //excution.IsWaited = true;
+                        excution.Detail = "Waited";
+
+                    }
+                    if (operation.Status == -1)
+                    {
+                        //  excution.IsTimeout = true;
+                        excution.Code = 0;
+                        excution.Detail = "Timeout";
+                    }
+
+
+                }
+
+
+            }
+            catch
+            {
+                excution = null;
+            }
+
+
+
+            return excution;
+
+        }
+
+
+
+
+        public int ConverttoCode(string statusName)
+        {
+            int code = -1;
+
+            if (string.IsNullOrEmpty(statusName)) return code;
+            var tt = AuthorizationStatus.Accepted.ToString();
+
+            Internal_ExecutionCode result = Internal_ExecutionCode.Accepted;
+            if (Enum.TryParse<Internal_ExecutionCode>(statusName, out result))
+            {
+                code = (int)result;
+            }
+
+            return code;
+        }
+    }
+}

+ 2 - 3
EVCB_OCPP.WEBAPI/Web.config

@@ -5,9 +5,8 @@
   -->
 <configuration>
   <connectionStrings>
-    <!--<add name="ConnectionLogDBContext" connectionString="data source=172.1.0.142\SQLEXPRESS;initial catalog=OCPP_ConnectionLogDBContext;persist security info=True;user id=sa;password=Ph0930118811;MultipleActiveResultSets=True;App=EntityFramework" providerName="System.Data.SqlClient" />
-    <add name="MainDBContext" connectionString="data source=172.1.0.142\SQLEXPRESS;initial catalog=OCPP_MainDBContext;;persist security info=True;user id=sa;password=Ph0930118811;MultipleActiveResultSets=True;App=EntityFramework" providerName="System.Data.SqlClient" />
-    <add name="MeterValueDBContext" connectionString="data source=172.1.0.142\SQLEXPRESS;initial catalog=OCPP_MeterValueDBContext;;persist security info=True;user id=sa;password=Ph0930118811;MultipleActiveResultSets=True;App=EntityFramework" providerName="System.Data.SqlClient" />-->
+    <add name="Main20DBContext" connectionString="data source=172.1.0.131;initial catalog=StandardOCPP20_Main;;persist security info=True;user id=sa;password=Ph0930118811;MultipleActiveResultSets=True;App=EntityFramework" providerName="System.Data.SqlClient" />
+    <add name="MeterValue20DBContext" connectionString="data source=172.1.0.131;initial catalog=StandardOCPP20_MeterValue;;persist security info=True;user id=sa;password=Ph0930118811;MultipleActiveResultSets=True;App=EntityFramework" providerName="System.Data.SqlClient" />
     <add name="ConnectionLogDBContext" connectionString="data source=172.1.2.187\SQLEXPRESS2017;initial catalog=StandardOCPP_ConnectionLog;persist security info=True;user id=sa;password=Ph0930118811;MultipleActiveResultSets=True;App=EntityFramework" providerName="System.Data.SqlClient" />
     <add name="MainDBContext" connectionString="data source=172.1.2.187\SQLEXPRESS2017;initial catalog=StandardOCPP_Main;;persist security info=True;user id=sa;password=Ph0930118811;MultipleActiveResultSets=True;App=EntityFramework" providerName="System.Data.SqlClient" />
     <add name="MeterValueDBContext" connectionString="data source=172.1.2.187\SQLEXPRESS2017;initial catalog=StandardOCPP_MeterValue;;persist security info=True;user id=sa;password=Ph0930118811;MultipleActiveResultSets=True;App=EntityFramework" providerName="System.Data.SqlClient" />