Kaynağa Gözat

2020/04/14 Jessica
Actions:
1. New Feature : Add Third Party API
2.Modify Internal API UrlFormat & How to work signature

Jessica.Tseng 5 yıl önce
ebeveyn
işleme
220bed993c
39 değiştirilmiş dosya ile 3034 ekleme ve 163 silme
  1. 1 1
      EVCB_OCPP.WEBAPI/App_Start/WebApiConfig.cs
  2. 61 0
      EVCB_OCPP.WEBAPI/Controllers/FileController.cs
  3. 1116 0
      EVCB_OCPP.WEBAPI/Controllers/Version1/CPOController.cs
  4. 140 90
      EVCB_OCPP.WEBAPI/Controllers/Version1/InternalController.cs
  5. 3 1
      EVCB_OCPP.WEBAPI/EVCBConfiguration.cs
  6. 79 2
      EVCB_OCPP.WEBAPI/EVCB_OCPP.WEBAPI.csproj
  7. 175 0
      EVCB_OCPP.WEBAPI/Handlers/CPOAuthentication.cs
  8. 13 13
      EVCB_OCPP.WEBAPI/Handlers/InernalAuthentication.cs
  9. 33 0
      EVCB_OCPP.WEBAPI/Models/ConnectorMeterValue.cs
  10. 34 0
      EVCB_OCPP.WEBAPI/Models/ConnectorMeterValueModel.cs
  11. 45 0
      EVCB_OCPP.WEBAPI/Models/SessionDetail.cs
  12. 75 0
      EVCB_OCPP.WEBAPI/Models/TransactionRecordModel.cs
  13. 32 0
      EVCB_OCPP.WEBAPI/Models/WebAPI/CPOOuterResponse.cs
  14. 49 0
      EVCB_OCPP.WEBAPI/Models/WebAPI/CPOResponseDescription.cs
  15. 0 16
      EVCB_OCPP.WEBAPI/Models/WebAPI/ComandExcution.cs
  16. 21 0
      EVCB_OCPP.WEBAPI/Models/WebAPI/ComandExecution.cs
  17. 16 0
      EVCB_OCPP.WEBAPI/Models/WebAPI/Dto/ChargingStation.cs
  18. 16 0
      EVCB_OCPP.WEBAPI/Models/WebAPI/Dto/CommandResponseType.cs
  19. 22 0
      EVCB_OCPP.WEBAPI/Models/WebAPI/Dto/CommandResultType.cs
  20. 20 0
      EVCB_OCPP.WEBAPI/Models/WebAPI/Dto/CommandType.cs
  21. 21 0
      EVCB_OCPP.WEBAPI/Models/WebAPI/Dto/Connector.cs
  22. 14 0
      EVCB_OCPP.WEBAPI/Models/WebAPI/Dto/ConnectorPowerType.cs
  23. 17 0
      EVCB_OCPP.WEBAPI/Models/WebAPI/Dto/ConnectorType.cs
  24. 25 0
      EVCB_OCPP.WEBAPI/Models/WebAPI/Dto/EVSE.cs
  25. 22 0
      EVCB_OCPP.WEBAPI/Models/WebAPI/Dto/GeoLocation.cs
  26. 20 0
      EVCB_OCPP.WEBAPI/Models/WebAPI/Dto/ReserveNowRequest.cs
  27. 16 0
      EVCB_OCPP.WEBAPI/Models/WebAPI/Dto/StartSessionRequest.cs
  28. 20 0
      EVCB_OCPP.WEBAPI/Models/WebAPI/Dto/Status.cs
  29. 1 1
      EVCB_OCPP.WEBAPI/Models/WebAPI/ErrorResponse.cs
  30. 2 0
      EVCB_OCPP.WEBAPI/Models/WebAPI/MachineOperation.cs
  31. 3 0
      EVCB_OCPP.WEBAPI/Models/WebAPI/SetChargingProfileRequest.cs
  32. 120 0
      EVCB_OCPP.WEBAPI/Services/ChargePointService.cs
  33. 28 0
      EVCB_OCPP.WEBAPI/Services/ChargingStationService.cs
  34. 39 0
      EVCB_OCPP.WEBAPI/Services/EVSEService.cs
  35. 315 0
      EVCB_OCPP.WEBAPI/Services/HttpClientService.cs
  36. 296 0
      EVCB_OCPP.WEBAPI/Services/InternalHttpClient.cs
  37. 44 8
      EVCB_OCPP.WEBAPI/Services/ServerTriggerService.cs
  38. 63 31
      EVCB_OCPP.WEBAPI/Web.config
  39. 17 0
      EVCB_OCPP.WEBAPI/packages.config

+ 1 - 1
EVCB_OCPP.WEBAPI/App_Start/WebApiConfig.cs

@@ -18,7 +18,7 @@ namespace EVCB_OCPP.WEBAPI
 
             config.Routes.MapHttpRoute(
                 name: "DefaultApi",
-                routeTemplate: "api/{controller}/{id}",
+                routeTemplate: "api/v1/{controller}/{id}",
                 defaults: new { id = RouteParameter.Optional }
             );
         }

+ 61 - 0
EVCB_OCPP.WEBAPI/Controllers/FileController.cs

@@ -0,0 +1,61 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Net;
+using System.Net.Http;
+using System.Threading.Tasks;
+using System.Web.Http;
+
+
+namespace EVCB_OCPP.WEBAPI.Controllers
+{
+    public class FileController : ApiController
+    {
+        [HttpPost]
+        public  async Task<HttpResponseMessage> Upload()
+        {
+
+            var ctx = System.Web.HttpContext.Current;
+            var root = ctx.Server.MapPath("~/UploadFiles/Diagnostics");
+            var provider = new MultipartFileStreamProvider(root);
+
+            try
+            {
+                if (!Request.Content.IsMimeMultipartContent())
+                {
+                    throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
+                }
+
+                await Request.Content.ReadAsMultipartAsync(provider);
+
+              
+                foreach (var file in provider.FileData)
+                {
+                    if (file.Headers.ContentType.MediaType== "application/zip")
+                    {
+                        var name = file.Headers.ContentDisposition.FileName;
+                        name = name.Trim('"');
+
+                        var localFileName = file.LocalFileName;
+                        var filePath = Path.Combine(root, name);
+                        File.Move(localFileName, filePath);
+                    }
+                    else
+                    {
+                        return Request.CreateResponse(HttpStatusCode.Forbidden);
+                    }
+
+                       
+                }
+                return Request.CreateResponse(HttpStatusCode.OK);
+            }
+            catch(Exception ex)
+            {
+                return Request.CreateResponse(HttpStatusCode.InternalServerError, ex.ToString());
+            }
+
+          
+        }
+    }
+}

+ 1116 - 0
EVCB_OCPP.WEBAPI/Controllers/Version1/CPOController.cs

@@ -0,0 +1,1116 @@
+using EVCB_OCPP.WEBAPI.Handlers;
+using EVCB_OCPP.WEBAPI.Models.WebAPI;
+using EVCB_OCPP.WEBAPI.Services;
+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;
+
+namespace EVCB_OCPP.WEBAPI.Controllers.Version1
+{
+    public class TT
+    {
+        public bool Result { get; set; }
+
+        public int Timeout { set; get; }
+
+        public string Msg { set; get; }
+    }
+
+    [RoutePrefix("api/v1/cpo")]
+    [CPOAuthentication]
+    public class 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();
+
+            ChargePointService _service = new ChargePointService();
+            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);
+
+                }
+                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(string StationId, DateTime? DateFrom = null, DateTime? DateTo = null, int? Offset = 0, int? Limit = 1)
+        {
+
+            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();
+                    EVSEService _service = new EVSEService();
+                    var _innerResponse = new { Stations = _service.GetEVSEsbyCustomerIdAndStationId(_customerId, StationId) };
+                    result.Data = JsonConvert.SerializeObject(_innerResponse);
+
+                }
+                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);
+                }
+
+                ChargePointService _CPService = new ChargePointService();
+
+                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 StartTransactionRequest()
+                    {
+                        ConnectorId = request.ConnectorId,
+                        IdTag = request.Token
+                    };
+
+                    string urlformat = "http://localhost:{0}/api/v1/ocpp16/transaction?ChargeBoxId={1}";
+
+                    var _innerResult = await _client.Post(string.Format(urlformat, 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.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;
+                    }
+
+
+                }
+                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 urlformat = "http://localhost:{0}/api/v1/ocpp16/transaction?ChargeBoxId={1}&TransactionId={2}";
+
+                var _innerResult = await _client.Put(string.Format(urlformat, Request.RequestUri.Port, 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
+                {
+
+                    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/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 urlformat = "http://localhost:{0}/api/v1/ocpp16/reservation?ChargeBoxId={1}";
+
+                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, Request.RequestUri.Port, 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
+                {
+
+                    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/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 urlformat = "http://localhost:{0}/api/v1/ocpp16/reservation?ChargeBoxId={1}&ReservationId={2}";
+
+                var _innerResult = await _client.Delete(string.Format(urlformat, Request.RequestUri.Port, 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/chargingporfiles")]
+        [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 urlformat = "http://localhost:{0}/api/v1/ocpp16/compositeschedule?ChargeBoxId={1}&ConnectorId={2}&Duration={3}";
+
+                var _innerResult = await _client.Get(string.Format(urlformat, Request.RequestUri.Port, 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/chargingporfiles")]
+        [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 urlformat = "http://localhost:{0}/api/v1/ocpp16/chargingprofile?ChargeBoxId={1}";
+
+
+
+                var _innerResult = await _client.Post(string.Format(urlformat, Request.RequestUri.Port, 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/chargingporfiles")]
+        [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 urlformat = "http://localhost:{0}/api/v1/ocpp16/chargeprofile?ChargeBoxId={1}{2}";
+
+                var _innerResult = await _client.Delete(string.Format(urlformat, Request.RequestUri.Port, 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 urlformat = "http://localhost:{0}/api/v1/ocpp16/locallist?ChargeBoxId={1}";
+
+
+
+                var _innerResult = await _client.Post(string.Format(urlformat, Request.RequestUri.Port, 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 urlformat = "http://localhost:{0}/api/v1/ocpp16/locallistversion?ChargeBoxId={1}";
+
+
+
+                var _innerResult = await _client.Get(string.Format(urlformat, Request.RequestUri.Port, 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:
+                        break;
+
+
+                }
+
+
+                string urlformat = "http://localhost:{0}/api/v1/ocpp16/command?ChargeBoxId={1}{2}&SerialNo={3}";
+
+
+                var _innerResult = await _client.Get(string.Format(urlformat, Request.RequestUri.Port, 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.IsTimeout.HasValue && _execution.IsTimeout.Value) _cmdResult = CommandResultType.Timeout;
+                                if (_execution.IsWaited.HasValue && _execution.IsWaited.Value) _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)
+        {
+            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
+                ChargePointService _service = new ChargePointService();
+                var _meterValues = _service.GetActiveSessionInfo(ChargeBoxId, SessionId, new List<Packet.Messages.SubTypes.Measurand>()
+                {   Packet.Messages.SubTypes.Measurand.Voltage,
+                    Packet.Messages.SubTypes.Measurand.Current_Export,
+                    Packet.Messages.SubTypes.Measurand.SoC,
+                    Packet.Messages.SubTypes.Measurand.Power_Active_Export,
+                    Packet.Messages.SubTypes.Measurand.Energy_Active_Export_Interval
+                });
+
+                if (_meterValues.Count == 0)
+                {
+                    result.StatusCode = (int)CPO_StatusCode.CANT_FOUND_DATA;
+                    result.StatusMessage = CPO_StatusMessage.ERROR_MSG_CANT_FIND_RESULT;
+                    statusCode = HttpStatusCode.NotFound;
+                }
+                else
+                {
+                    var _innerData = new
+                    {
+                        Power = _meterValues.Where(x => x.Measurand == Packet.Messages.SubTypes.Measurand.Power_Active_Export).Select(x => x.Value).FirstOrDefault(),
+                        Power_Format = _meterValues.Where(x => x.Measurand == Packet.Messages.SubTypes.Measurand.Power_Active_Export).Select(x => x.Unit.ToString()).FirstOrDefault(),
+                        Current = _meterValues.Where(x => x.Measurand == Packet.Messages.SubTypes.Measurand.Current_Export).Select(x => x.Value).FirstOrDefault(),
+                        Current_Format = _meterValues.Where(x => x.Measurand == Packet.Messages.SubTypes.Measurand.Current_Export).Select(x => x.Unit.ToString()).FirstOrDefault(),
+                        Energy = _meterValues.Where(x => x.Measurand == Packet.Messages.SubTypes.Measurand.Energy_Active_Export_Interval).Select(x => x.Value).FirstOrDefault(),
+                        Energy_Format = _meterValues.Where(x => x.Measurand == Packet.Messages.SubTypes.Measurand.Energy_Active_Export_Interval).Select(x => x.Unit.ToString()).FirstOrDefault(),
+                        Voltage = _meterValues.Where(x => x.Measurand == Packet.Messages.SubTypes.Measurand.Voltage).Select(x => x.Value).FirstOrDefault(),
+                        Voltage_Format = _meterValues.Where(x => x.Measurand == Packet.Messages.SubTypes.Measurand.Voltage).Select(x => x.Unit.ToString()).FirstOrDefault(),
+                        SOC = _meterValues.Where(x => x.Measurand == Packet.Messages.SubTypes.Measurand.SoC).Select(x => x.Value).FirstOrDefault(),
+                        SOC_Format = _meterValues.Where(x => x.Measurand == Packet.Messages.SubTypes.Measurand.SoC).Select(x => x.Unit.ToString()).FirstOrDefault(),
+                    };
+
+                    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)
+        {
+            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
+                ChargePointService _service = new ChargePointService();
+                var _innerData = _service.GetSessionDetail(ChargeBoxId, SessionId);
+
+                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);
+            }
+
+        }
+
+        private CPOOuterResponse GetErrorDescription(InternalHttpResult innerResponse)
+        {
+            CPOOuterResponse result = new CPOOuterResponse();
+
+            result.ErrorDetail = innerResponse.Exception == null ? string.Empty : 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:
+                        {
+                            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;
+
+
+        }
+
+
+
+
+    }
+}

+ 140 - 90
EVCB_OCPP.WEBAPI/Controllers/InternalV1Controller.cs → EVCB_OCPP.WEBAPI/Controllers/Version1/InternalController.cs

@@ -20,19 +20,20 @@ using System.Web.Http;
 using System.Web.Http.Description;
 using StartTransactionRequest = EVCB_OCPP.WEBAPI.Models.WebAPI.StartTransactionRequest;
 
-namespace EVCB_OCPP.WEBAPI.Controllers
+namespace EVCB_OCPP.WEBAPI.Controllers.Version1
 {
     [RoutePrefix("api/v1/ocpp16")]
     [InernalAuthentication]
     public class InternalV1Controller : ApiController
     {
 
-        [Route("command/{OrderNo}/SerialNo/{SerialNo}/chargebox/{ChargeBoxId}")]
+        [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
@@ -42,12 +43,12 @@ namespace EVCB_OCPP.WEBAPI.Controllers
 
                 if (!IsValidEnum<Internal_Actions>(OrderNo) || string.IsNullOrEmpty(ChargeBoxId))
                 {
-                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Message = EVCBConfiguration.ERROR_MSG_PARAMETER_OUTOFRANGE_INCORRECT });
+                    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() { Message = EVCBConfiguration.ERROR_MSG_CHARGEBOXID_ISNT_EXIST_OR_OFFLINE });
+                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Code = 2101, Message = EVCBConfiguration.ERROR_MSG_CHARGEBOXID_ISNT_EXIST_OR_OFFLINE });
                 }
 
                 ServerTriggerService triggerService = new ServerTriggerService();
@@ -55,7 +56,7 @@ namespace EVCB_OCPP.WEBAPI.Controllers
 
                 if (excution == null)
                 {
-                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Message = EVCBConfiguration.ERROR_MSG_DATA_NOTFOUND });
+                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Code = 2102, Message = EVCBConfiguration.ERROR_MSG_DATA_NOTFOUND });
                 }
 
                 result.Message = JsonConvert.SerializeObject(excution, EVCBConfiguration.JSONSERIALIZER_FORMAT);
@@ -67,6 +68,7 @@ namespace EVCB_OCPP.WEBAPI.Controllers
 
                 return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse()
                 {
+                    Code = 2999,
                     Message = string.Format(EVCBConfiguration.ERRORMESSAGE_FORMAT, EVCBConfiguration.ERROR_MSG_UNEXPECTEDERROR, "CommandofExecution", ex.ToString())
                 });
             }
@@ -74,7 +76,7 @@ namespace EVCB_OCPP.WEBAPI.Controllers
             return Request.CreateResponse(statusCode, result);
         }
 
-        [Route("availability/chargebox/{ChargeBoxId}")]
+        [Route("availability")]
         [ResponseType(typeof(ErrorResponse))]
         [ResponseType(typeof(InternalGenericResponse))]
         [HttpPut]
@@ -91,7 +93,7 @@ namespace EVCB_OCPP.WEBAPI.Controllers
                 if (!chargePointService.IsOnline(ChargeBoxId))
                 {
 
-                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Message = EVCBConfiguration.ERROR_MSG_CHARGEBOXID_ISNT_EXIST_OR_OFFLINE });
+                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Code = 2101, Message = EVCBConfiguration.ERROR_MSG_CHARGEBOXID_ISNT_EXIST_OR_OFFLINE });
                 }
 
                 //check parameter
@@ -100,7 +102,7 @@ namespace EVCB_OCPP.WEBAPI.Controllers
                     !(Availiability.AvailabilityType > 0 && Availiability.AvailabilityType < 3))
                 {
 
-                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Message = EVCBConfiguration.ERROR_MSG_PARAMETER_OUTOFRANGE_INCORRECT });
+                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Code = 2100, Message = EVCBConfiguration.ERROR_MSG_PARAMETER_OUTOFRANGE_INCORRECT });
                 }
 
                 //create reqest
@@ -117,7 +119,7 @@ namespace EVCB_OCPP.WEBAPI.Controllers
                     throw new Exception("Write Command Fail!!");
                 }
 
-                statusCode = HttpStatusCode.Accepted;
+                statusCode = HttpStatusCode.OK;
                 result.SerialNo = uuid;
 
             }
@@ -126,6 +128,7 @@ namespace EVCB_OCPP.WEBAPI.Controllers
 
                 return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse()
                 {
+                    Code = 2999,
                     Message = string.Format(EVCBConfiguration.ERRORMESSAGE_FORMAT, EVCBConfiguration.ERROR_MSG_UNEXPECTEDERROR, "Availability", ex.ToString())
                 });
             }
@@ -134,7 +137,7 @@ namespace EVCB_OCPP.WEBAPI.Controllers
         }
 
 
-        [Route("configuration/chargebox/{ChargeBoxId}")]
+        [Route("configuration")]
         [ResponseType(typeof(ErrorResponse))]
         [ResponseType(typeof(InternalGenericResponse))]
         [HttpPut]
@@ -152,7 +155,7 @@ namespace EVCB_OCPP.WEBAPI.Controllers
                 if (!chargePointService.IsOnline(ChargeBoxId))
                 {
 
-                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Message = EVCBConfiguration.ERROR_MSG_CHARGEBOXID_ISNT_EXIST_OR_OFFLINE });
+                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Code = 2101, Message = EVCBConfiguration.ERROR_MSG_CHARGEBOXID_ISNT_EXIST_OR_OFFLINE });
                 }
 
                 //check parameter
@@ -160,7 +163,7 @@ namespace EVCB_OCPP.WEBAPI.Controllers
                     (string.IsNullOrEmpty(SingleConfiguration.Key) || string.IsNullOrEmpty(SingleConfiguration.Value)))
                 {
 
-                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Message = EVCBConfiguration.ERROR_MSG_PARAMETER_OUTOFRANGE_INCORRECT });
+                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Code = 2100, Message = EVCBConfiguration.ERROR_MSG_PARAMETER_OUTOFRANGE_INCORRECT });
                 }
 
                 //create reqest
@@ -176,7 +179,7 @@ namespace EVCB_OCPP.WEBAPI.Controllers
                     throw new Exception("Write Command Fail!!");
                 }
 
-                statusCode = HttpStatusCode.Accepted;
+                statusCode = HttpStatusCode.OK;
                 result.SerialNo = uuid;
             }
             catch (Exception ex)
@@ -184,6 +187,7 @@ namespace EVCB_OCPP.WEBAPI.Controllers
 
                 return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse()
                 {
+                    Code = 2999,
                     Message = string.Format(EVCBConfiguration.ERRORMESSAGE_FORMAT, EVCBConfiguration.ERROR_MSG_UNEXPECTEDERROR, "ChangeConfiguration", ex.ToString())
                 });
             }
@@ -191,7 +195,7 @@ namespace EVCB_OCPP.WEBAPI.Controllers
             return Request.CreateResponse(statusCode, result);
         }
 
-        [Route("configuration/chargebox/{ChargeBoxId}")]
+        [Route("configuration")]
         [ResponseType(typeof(ErrorResponse))]
         [ResponseType(typeof(InternalGenericResponse))]
         [HttpGet]
@@ -208,14 +212,14 @@ namespace EVCB_OCPP.WEBAPI.Controllers
                 if (!chargePointService.IsOnline(ChargeBoxId))
                 {
 
-                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Message = EVCBConfiguration.ERROR_MSG_CHARGEBOXID_ISNT_EXIST_OR_OFFLINE });
+                    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() { Message = EVCBConfiguration.ERROR_MSG_PARAMETER_OUTOFRANGE_INCORRECT });
+                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Code = 2100, Message = EVCBConfiguration.ERROR_MSG_PARAMETER_OUTOFRANGE_INCORRECT });
                 }
 
                 //create reqest
@@ -238,6 +242,7 @@ namespace EVCB_OCPP.WEBAPI.Controllers
 
                 return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse()
                 {
+                    Code = 2999,
                     Message = string.Format(EVCBConfiguration.ERRORMESSAGE_FORMAT, EVCBConfiguration.ERROR_MSG_UNEXPECTEDERROR, "GetConfiguration", ex.ToString())
                 });
             }
@@ -245,7 +250,7 @@ namespace EVCB_OCPP.WEBAPI.Controllers
             return Request.CreateResponse(statusCode, result);
         }
 
-        [Route("diagonostics/chargebox/{ChargeBoxId}")]
+        [Route("diagonostics")]
         [ResponseType(typeof(ErrorResponse))]
         [ResponseType(typeof(InternalGenericResponse))]
         [HttpGet]
@@ -263,7 +268,7 @@ namespace EVCB_OCPP.WEBAPI.Controllers
                 if (!chargePointService.IsOnline(ChargeBoxId))
                 {
 
-                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Message = EVCBConfiguration.ERROR_MSG_CHARGEBOXID_ISNT_EXIST_OR_OFFLINE });
+                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Code = 2101, Message = EVCBConfiguration.ERROR_MSG_CHARGEBOXID_ISNT_EXIST_OR_OFFLINE });
                 }
 
                 //check parameter
@@ -273,7 +278,7 @@ namespace EVCB_OCPP.WEBAPI.Controllers
                     || (!string.IsNullOrEmpty(StopTime) && !DateTime.TryParse(StopTime, out vaildtime)))
                 {
 
-                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Message = EVCBConfiguration.ERROR_MSG_PARAMETER_OUTOFRANGE_INCORRECT });
+                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Code = 2100, Message = EVCBConfiguration.ERROR_MSG_PARAMETER_OUTOFRANGE_INCORRECT });
                 }
 
                 //create reqest
@@ -292,7 +297,7 @@ namespace EVCB_OCPP.WEBAPI.Controllers
                     throw new Exception("Write Command Fail!!");
                 }
 
-                statusCode = HttpStatusCode.Accepted;
+                statusCode = HttpStatusCode.OK;
                 result.SerialNo = uuid;
 
             }
@@ -301,6 +306,7 @@ namespace EVCB_OCPP.WEBAPI.Controllers
 
                 return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse()
                 {
+                    Code = 2999,
                     Message = string.Format(EVCBConfiguration.ERRORMESSAGE_FORMAT, EVCBConfiguration.ERROR_MSG_UNEXPECTEDERROR, "GetDiagonostics", ex.ToString())
                 });
             }
@@ -309,7 +315,7 @@ namespace EVCB_OCPP.WEBAPI.Controllers
         }
 
 
-        [Route("locallistversion/chargebox/{ChargeBoxId}")]
+        [Route("locallistversion")]
         [ResponseType(typeof(ErrorResponse))]
         [ResponseType(typeof(InternalGenericResponse))]
         [HttpGet]
@@ -326,7 +332,7 @@ namespace EVCB_OCPP.WEBAPI.Controllers
                 if (!chargePointService.IsOnline(ChargeBoxId))
                 {
 
-                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Message = EVCBConfiguration.ERROR_MSG_CHARGEBOXID_ISNT_EXIST_OR_OFFLINE });
+                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Code = 2101, Message = EVCBConfiguration.ERROR_MSG_CHARGEBOXID_ISNT_EXIST_OR_OFFLINE });
                 }
 
                 if (!AddCommandtoServer(ChargeBoxId, uuid, new GetLocalListVersionRequest()))
@@ -334,20 +340,20 @@ namespace EVCB_OCPP.WEBAPI.Controllers
                     throw new Exception("Write Command Fail!!");
                 }
 
-                statusCode = HttpStatusCode.Accepted;
+                statusCode = HttpStatusCode.OK;
                 result.SerialNo = uuid;
 
             }
             catch (Exception ex)
             {
 
-                return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Message = string.Format(EVCBConfiguration.ERRORMESSAGE_FORMAT, EVCBConfiguration.ERROR_MSG_UNEXPECTEDERROR, "GetLocallistversion", ex.ToString()) });
+                return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Code = 2999, Message = string.Format(EVCBConfiguration.ERRORMESSAGE_FORMAT, EVCBConfiguration.ERROR_MSG_UNEXPECTEDERROR, "GetLocallistversion", ex.ToString()) });
             }
 
             return Request.CreateResponse(statusCode, result);
         }
 
-        [Route("transaction/chargebox/{ChargeBoxId}")]
+        [Route("transaction")]
         [ResponseType(typeof(ErrorResponse))]
         [ResponseType(typeof(InternalGenericResponse))]
         [HttpPost]
@@ -363,25 +369,52 @@ namespace EVCB_OCPP.WEBAPI.Controllers
                 if (!chargePointService.IsOnline(ChargeBoxId))
                 {
 
-                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Message = EVCBConfiguration.ERROR_MSG_CHARGEBOXID_ISNT_EXIST_OR_OFFLINE });
+                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Code = 2101, Message = EVCBConfiguration.ERROR_MSG_CHARGEBOXID_ISNT_EXIST_OR_OFFLINE });
                 }
 
                 //check parameter
-                if (StartTransaction == null || string.IsNullOrEmpty(StartTransaction.IdTag) ||
-                    !(StartTransaction.ConnectorId.HasValue && StartTransaction.ConnectorId > 0) ||
-                    !(StartTransaction.ChargingProfile != null && IsValidEnum<ChargingProfileKindType>((int)StartTransaction.ChargingProfile.chargingProfileKind)) ||
-                    !(StartTransaction.ChargingProfile != null && StartTransaction.ChargingProfile.recurrencyKind.HasValue && IsValidEnum<RecurrencyKindType>((int)StartTransaction.ChargingProfile.recurrencyKind)) ||
-                    !(StartTransaction.ChargingProfile != null && StartTransaction.ChargingProfile.recurrencyKind.HasValue && IsValidEnum<RecurrencyKindType>((int)StartTransaction.ChargingProfile.recurrencyKind)) ||
-                     !(StartTransaction.ChargingProfile != null && StartTransaction.ChargingProfile.chargingSchedule != null && IsValidEnum<ChargingRateUnitType>((int)StartTransaction.ChargingProfile.chargingSchedule.chargingRateUnit)))
 
+
+                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() { Message = EVCBConfiguration.ERROR_MSG_PARAMETER_OUTOFRANGE_INCORRECT });
+                    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 });
+
+                    }
+
+                }
+
+
+
                 if (StartTransaction.ConnectorId.HasValue && chargePointService.GetChargePointCurrentSatus(ChargeBoxId, StartTransaction.ConnectorId.Value).HasValue &&
                     chargePointService.GetChargePointCurrentSatus(ChargeBoxId, StartTransaction.ConnectorId.Value).Value != ChargePointStatus.Available)
                 {
-                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Message = EVCBConfiguration.ERROR_MSG_CONNECTOR_ISNOT_AVAILIABLE_MODE });
+                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Code = 2103, Message = EVCBConfiguration.ERROR_MSG_CONNECTOR_ISNOT_AVAILIABLE_MODE });
                 }
                 else
                 {
@@ -418,7 +451,7 @@ namespace EVCB_OCPP.WEBAPI.Controllers
                     }
                 }
 
-                statusCode = HttpStatusCode.Accepted;
+                statusCode = HttpStatusCode.OK;
                 result.SerialNo = uuid;
 
             }
@@ -427,6 +460,7 @@ namespace EVCB_OCPP.WEBAPI.Controllers
 
                 return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse()
                 {
+                    Code = 2999,
                     Message = string.Format(EVCBConfiguration.ERRORMESSAGE_FORMAT, EVCBConfiguration.ERROR_MSG_UNEXPECTEDERROR, "StopTransaction", ex.ToString())
                 });
             }
@@ -434,7 +468,7 @@ namespace EVCB_OCPP.WEBAPI.Controllers
             return Request.CreateResponse(statusCode, result);
         }
 
-        [Route("transaction/{TransactionId}/chargebox/{ChargeBoxId}")]
+        [Route("transaction")]
         [ResponseType(typeof(ErrorResponse))]
         [ResponseType(typeof(InternalGenericResponse))]
         [HttpPut]
@@ -450,13 +484,15 @@ namespace EVCB_OCPP.WEBAPI.Controllers
                 if (!chargePointService.IsOnline(ChargeBoxId))
                 {
 
-                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Message = EVCBConfiguration.ERROR_MSG_CHARGEBOXID_ISNT_EXIST_OR_OFFLINE });
+                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Code = 2101, Message = EVCBConfiguration.ERROR_MSG_CHARGEBOXID_ISNT_EXIST_OR_OFFLINE });
                 }
 
-                if (!chargePointService.GetChargePointCurrentSatus(ChargeBoxId, TransactionId % 10).HasValue)
+                var _ConnectorStatus = chargePointService.GetChargePointCurrentSatus(ChargeBoxId, TransactionId % 10);
+
+                if (!(_ConnectorStatus.HasValue && _ConnectorStatus == ChargePointStatus.Charging))
                 {
-                    //offline
-                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Message = EVCBConfiguration.ERROR_MSG_CONNECTOR_ISNOT_AVAILIABLE_MODE });
+
+                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Code = 2105, Message = EVCBConfiguration.ERROR_MSG_CONNECTOR_ISNOT_CHARGING_MODE });
                 }
                 else
                 {
@@ -475,27 +511,29 @@ namespace EVCB_OCPP.WEBAPI.Controllers
                     }
                     else
                     {
-                        return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Message = EVCBConfiguration.ERROR_MSG_SESSION_WAS_FINISHED });
+                        return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Code = 2104, Message = EVCBConfiguration.ERROR_MSG_SESSION_WAS_FINISHED });
                     }
                 }
 
-                statusCode = HttpStatusCode.Accepted;
+                statusCode = HttpStatusCode.OK;
                 result.SerialNo = uuid;
+                return Request.CreateResponse(statusCode, result);
 
             }
             catch (Exception ex)
             {
 
-                return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse()
+                return Request.CreateResponse(HttpStatusCode.InternalServerError, new ErrorResponse()
                 {
+                    Code = 2999,
                     Message = string.Format(EVCBConfiguration.ERRORMESSAGE_FORMAT, EVCBConfiguration.ERROR_MSG_UNEXPECTEDERROR, "StopTransaction", ex.ToString())
                 });
             }
 
-            return Request.CreateResponse(statusCode, result);
+
         }
 
-        [Route("reservation/chargebox/{ChargeBoxId}")]
+        [Route("reservation")]
         [ResponseType(typeof(ErrorResponse))]
         [ResponseType(typeof(InternalGenericResponse))]
         [HttpPost]
@@ -510,7 +548,7 @@ namespace EVCB_OCPP.WEBAPI.Controllers
 
                 if (!chargePointService.IsOnline(ChargeBoxId))
                 {
-                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Message = EVCBConfiguration.ERROR_MSG_CHARGEBOXID_ISNT_EXIST_OR_OFFLINE });
+                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Code = 2101, Message = EVCBConfiguration.ERROR_MSG_CHARGEBOXID_ISNT_EXIST_OR_OFFLINE });
                 }
 
 
@@ -523,14 +561,14 @@ namespace EVCB_OCPP.WEBAPI.Controllers
                     !DateTime.TryParse(ReserveNow.ExpiryDate, out expiryDate))
                 {
 
-                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Message = EVCBConfiguration.ERROR_MSG_PARAMETER_OUTOFRANGE_INCORRECT });
+                    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() { Message = EVCBConfiguration.ERROR_MSG_PARAMETER_OUTOFRANGE_INCORRECT });
+                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Code = 2100, Message = EVCBConfiguration.ERROR_MSG_PARAMETER_OUTOFRANGE_INCORRECT });
                 }
 
                 var connectorStatus = chargePointService.GetChargePointCurrentSatus(ChargeBoxId, ReserveNow.ConnectorId);
@@ -555,12 +593,12 @@ namespace EVCB_OCPP.WEBAPI.Controllers
                         throw new Exception("Write Command Fail!!");
                     }
 
-                    statusCode = HttpStatusCode.Accepted;
+                    statusCode = HttpStatusCode.OK;
                     result.SerialNo = uuid;
                 }
                 else
                 {
-                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Message = EVCBConfiguration.ERROR_MSG_CONNECTOR_ISNOT_AVAILIABLE_MODE });
+                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Code = 2103, Message = EVCBConfiguration.ERROR_MSG_CONNECTOR_ISNOT_AVAILIABLE_MODE });
                 }
 
 
@@ -571,6 +609,7 @@ namespace EVCB_OCPP.WEBAPI.Controllers
 
                 return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse()
                 {
+                    Code = 2999,
                     Message = string.Format(EVCBConfiguration.ERRORMESSAGE_FORMAT, EVCBConfiguration.ERROR_MSG_UNEXPECTEDERROR, "ReserveNow", ex.ToString())
                 });
             }
@@ -578,7 +617,7 @@ namespace EVCB_OCPP.WEBAPI.Controllers
             return Request.CreateResponse(statusCode, result);
         }
 
-        [Route("reservation/{ReservationId}/chargebox/{ChargeBoxId}")]
+        [Route("reservation")]
         [ResponseType(typeof(ErrorResponse))]
         [ResponseType(typeof(InternalGenericResponse))]
         [HttpDelete]
@@ -594,7 +633,7 @@ namespace EVCB_OCPP.WEBAPI.Controllers
                 if (!chargePointService.IsOnline(ChargeBoxId))
                 {
 
-                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Message = EVCBConfiguration.ERROR_MSG_CHARGEBOXID_ISNT_EXIST_OR_OFFLINE });
+                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Code = 2101, Message = EVCBConfiguration.ERROR_MSG_CHARGEBOXID_ISNT_EXIST_OR_OFFLINE });
                 }
 
                 var connectorStatus = chargePointService.GetChargePointCurrentSatus(ChargeBoxId, 0);
@@ -614,12 +653,12 @@ namespace EVCB_OCPP.WEBAPI.Controllers
                         throw new Exception("Write Command Fail!!");
                     }
 
-                    statusCode = HttpStatusCode.Accepted;
+                    statusCode = HttpStatusCode.OK;
                     result.SerialNo = uuid;
                 }
                 else
                 {
-                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Message = EVCBConfiguration.ERROR_MSG_CONNECTOR_ISNOT_AVAILIABLE_MODE });
+                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Code = 2103, Message = EVCBConfiguration.ERROR_MSG_CONNECTOR_ISNOT_AVAILIABLE_MODE });
                 }
 
 
@@ -629,6 +668,7 @@ namespace EVCB_OCPP.WEBAPI.Controllers
 
                 return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse()
                 {
+                    Code = 2999,
                     Message = string.Format(EVCBConfiguration.ERRORMESSAGE_FORMAT, EVCBConfiguration.ERROR_MSG_UNEXPECTEDERROR, "CancelResrvation", ex.ToString())
                 });
             }
@@ -636,7 +676,7 @@ namespace EVCB_OCPP.WEBAPI.Controllers
             return Request.CreateResponse(statusCode, result);
         }
 
-        [Route("reset/{ResetType}/chargebox/{ChargeBoxId}")]
+        [Route("reset")]
         [ResponseType(typeof(ErrorResponse))]
         [ResponseType(typeof(InternalGenericResponse))]
         [HttpPost]
@@ -652,7 +692,7 @@ namespace EVCB_OCPP.WEBAPI.Controllers
                 if (!chargePointService.IsOnline(ChargeBoxId))
                 {
 
-                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Message = EVCBConfiguration.ERROR_MSG_CHARGEBOXID_ISNT_EXIST_OR_OFFLINE });
+                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Code = 2101, Message = EVCBConfiguration.ERROR_MSG_CHARGEBOXID_ISNT_EXIST_OR_OFFLINE });
                 }
 
                 var connectorStatus = chargePointService.GetChargePointCurrentSatus(ChargeBoxId, 0);
@@ -672,12 +712,12 @@ namespace EVCB_OCPP.WEBAPI.Controllers
                         throw new Exception("Write Command Fail!!");
                     }
 
-                    statusCode = HttpStatusCode.Accepted;
+                    statusCode = HttpStatusCode.OK;
                     result.SerialNo = uuid;
                 }
                 else
                 {
-                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Message = EVCBConfiguration.ERROR_MSG_CONNECTOR_ISNOT_AVAILIABLE_MODE });
+                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Code = 2103, Message = EVCBConfiguration.ERROR_MSG_CONNECTOR_ISNOT_AVAILIABLE_MODE });
                 }
 
 
@@ -687,6 +727,7 @@ namespace EVCB_OCPP.WEBAPI.Controllers
 
                 return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse()
                 {
+                    Code = 2999,
                     Message = string.Format(EVCBConfiguration.ERRORMESSAGE_FORMAT, EVCBConfiguration.ERROR_MSG_UNEXPECTEDERROR, "Reset", ex.ToString())
                 });
             }
@@ -694,7 +735,7 @@ namespace EVCB_OCPP.WEBAPI.Controllers
             return Request.CreateResponse(statusCode, result);
         }
 
-        [Route("locallist/chargebox/{ChargeBoxId}")]
+        [Route("locallist")]
         [ResponseType(typeof(ErrorResponse))]
         [ResponseType(typeof(InternalGenericResponse))]
         [HttpPost]
@@ -710,7 +751,7 @@ namespace EVCB_OCPP.WEBAPI.Controllers
                 if (!chargePointService.IsOnline(ChargeBoxId))
                 {
 
-                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Message = EVCBConfiguration.ERROR_MSG_CHARGEBOXID_ISNT_EXIST_OR_OFFLINE });
+                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Code = 2101, Message = EVCBConfiguration.ERROR_MSG_CHARGEBOXID_ISNT_EXIST_OR_OFFLINE });
                 }
 
                 //check parameter
@@ -719,7 +760,7 @@ namespace EVCB_OCPP.WEBAPI.Controllers
                     || (LocalList.LocalAuthorizationList != null && LocalList.LocalAuthorizationList.Count == 0))
                 {
 
-                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Message = EVCBConfiguration.ERROR_MSG_PARAMETER_OUTOFRANGE_INCORRECT });
+                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Code = 2100, Message = EVCBConfiguration.ERROR_MSG_PARAMETER_OUTOFRANGE_INCORRECT });
                 }
 
                 bool badRequest = false;
@@ -734,7 +775,7 @@ namespace EVCB_OCPP.WEBAPI.Controllers
 
                     if (badRequest)
                     {
-                        return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Message = EVCBConfiguration.ERROR_MSG_PARAMETER_OUTOFRANGE_INCORRECT });
+                        return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Code = 2100, Message = EVCBConfiguration.ERROR_MSG_PARAMETER_OUTOFRANGE_INCORRECT });
                     }
                     localAuthorizationList.Add(new AuthorizationData()
                     {
@@ -762,7 +803,7 @@ namespace EVCB_OCPP.WEBAPI.Controllers
                     throw new Exception("Write Command Fail!!");
                 }
 
-                statusCode = HttpStatusCode.Accepted;
+                statusCode = HttpStatusCode.OK;
                 result.SerialNo = uuid;
             }
             catch (Exception ex)
@@ -770,6 +811,7 @@ namespace EVCB_OCPP.WEBAPI.Controllers
 
                 return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse()
                 {
+                    Code = 2999,
                     Message = string.Format(EVCBConfiguration.ERRORMESSAGE_FORMAT, EVCBConfiguration.ERROR_MSG_UNEXPECTEDERROR, "ClearCache", ex.ToString())
                 });
             }
@@ -778,7 +820,7 @@ namespace EVCB_OCPP.WEBAPI.Controllers
         }
 
 
-        [Route("cache/chargebox/{ChargeBoxId}")]
+        [Route("cache")]
         [ResponseType(typeof(ErrorResponse))]
         [ResponseType(typeof(InternalGenericResponse))]
         [HttpDelete]
@@ -794,7 +836,7 @@ namespace EVCB_OCPP.WEBAPI.Controllers
                 if (!chargePointService.IsOnline(ChargeBoxId))
                 {
 
-                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Message = EVCBConfiguration.ERROR_MSG_CHARGEBOXID_ISNT_EXIST_OR_OFFLINE });
+                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Code = 2101, Message = EVCBConfiguration.ERROR_MSG_CHARGEBOXID_ISNT_EXIST_OR_OFFLINE });
                 }
 
                 var connectorStatus = chargePointService.GetChargePointCurrentSatus(ChargeBoxId, 0);
@@ -807,12 +849,12 @@ namespace EVCB_OCPP.WEBAPI.Controllers
                         throw new Exception("Write Command Fail!!");
                     }
 
-                    statusCode = HttpStatusCode.Accepted;
+                    statusCode = HttpStatusCode.OK;
                     result.SerialNo = uuid;
                 }
                 else
                 {
-                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Message = EVCBConfiguration.ERROR_MSG_CONNECTOR_ISNOT_AVAILIABLE_MODE });
+                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Code = 2103, Message = EVCBConfiguration.ERROR_MSG_CONNECTOR_ISNOT_AVAILIABLE_MODE });
                 }
 
 
@@ -822,6 +864,7 @@ namespace EVCB_OCPP.WEBAPI.Controllers
 
                 return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse()
                 {
+                    Code = 2999,
                     Message = string.Format(EVCBConfiguration.ERRORMESSAGE_FORMAT, EVCBConfiguration.ERROR_MSG_UNEXPECTEDERROR, "ClearCache", ex.ToString())
                 });
             }
@@ -829,7 +872,7 @@ namespace EVCB_OCPP.WEBAPI.Controllers
             return Request.CreateResponse(statusCode, result);
         }
 
-        [Route("chargingprofile/chargebox/{ChargeBoxId}")]
+        [Route("chargingprofile")]
         [ResponseType(typeof(ErrorResponse))]
         [ResponseType(typeof(InternalGenericResponse))]
         [HttpPost]
@@ -846,7 +889,7 @@ namespace EVCB_OCPP.WEBAPI.Controllers
                 if (!chargePointService.IsOnline(ChargeBoxId))
                 {
 
-                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Message = EVCBConfiguration.ERROR_MSG_CHARGEBOXID_ISNT_EXIST_OR_OFFLINE });
+                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Code = 2101, Message = EVCBConfiguration.ERROR_MSG_CHARGEBOXID_ISNT_EXIST_OR_OFFLINE });
                 }
 
                 //check parameter
@@ -858,7 +901,7 @@ namespace EVCB_OCPP.WEBAPI.Controllers
                   !(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() { Message = EVCBConfiguration.ERROR_MSG_PARAMETER_OUTOFRANGE_INCORRECT });
+                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Code = 2100, Message = EVCBConfiguration.ERROR_MSG_PARAMETER_OUTOFRANGE_INCORRECT });
                 }
 
                 var request = new SetChargingProfileRequest()
@@ -892,7 +935,7 @@ namespace EVCB_OCPP.WEBAPI.Controllers
                 }
 
 
-                statusCode = HttpStatusCode.Accepted;
+                statusCode = HttpStatusCode.OK;
                 result.SerialNo = uuid;
 
             }
@@ -901,6 +944,7 @@ namespace EVCB_OCPP.WEBAPI.Controllers
 
                 return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse()
                 {
+                    Code = 2999,
                     Message = string.Format(EVCBConfiguration.ERRORMESSAGE_FORMAT, EVCBConfiguration.ERROR_MSG_UNEXPECTEDERROR, "StopTransaction", ex.ToString())
                 });
             }
@@ -908,7 +952,7 @@ namespace EVCB_OCPP.WEBAPI.Controllers
             return Request.CreateResponse(statusCode, result);
         }
 
-        [Route("chargeprofile/chargebox/{ChargeBoxId}")]
+        [Route("chargeprofile")]
         [ResponseType(typeof(ErrorResponse))]
         [ResponseType(typeof(InternalGenericResponse))]
         [HttpDelete]
@@ -924,7 +968,7 @@ namespace EVCB_OCPP.WEBAPI.Controllers
                 if (!chargePointService.IsOnline(ChargeBoxId))
                 {
 
-                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Message = EVCBConfiguration.ERROR_MSG_CHARGEBOXID_ISNT_EXIST_OR_OFFLINE });
+                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Code = 2101, Message = EVCBConfiguration.ERROR_MSG_CHARGEBOXID_ISNT_EXIST_OR_OFFLINE });
                 }
 
                 var connectorStatus = chargePointService.GetChargePointCurrentSatus(ChargeBoxId, 0);
@@ -945,12 +989,12 @@ namespace EVCB_OCPP.WEBAPI.Controllers
                         throw new Exception("Write Command Fail!!");
                     }
 
-                    statusCode = HttpStatusCode.Accepted;
+                    statusCode = HttpStatusCode.OK;
                     result.SerialNo = uuid;
                 }
                 else
                 {
-                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Message = EVCBConfiguration.ERROR_MSG_CONNECTOR_ISNOT_AVAILIABLE_MODE });
+                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Code = 2103, Message = EVCBConfiguration.ERROR_MSG_CONNECTOR_ISNOT_AVAILIABLE_MODE });
                 }
 
 
@@ -960,6 +1004,7 @@ namespace EVCB_OCPP.WEBAPI.Controllers
 
                 return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse()
                 {
+                    Code = 2999,
                     Message = string.Format(EVCBConfiguration.ERRORMESSAGE_FORMAT, EVCBConfiguration.ERROR_MSG_UNEXPECTEDERROR, "ClearChargingProfile", ex.ToString())
                 });
             }
@@ -967,7 +1012,7 @@ namespace EVCB_OCPP.WEBAPI.Controllers
             return Request.CreateResponse(statusCode, result);
         }
 
-        [Route("trigger/chargebox/{ChargeBoxId}")]
+        [Route("trigger")]
         [ResponseType(typeof(ErrorResponse))]
         [ResponseType(typeof(InternalGenericResponse))]
         [HttpPost]
@@ -983,14 +1028,14 @@ namespace EVCB_OCPP.WEBAPI.Controllers
                 if (!chargePointService.IsOnline(ChargeBoxId))
                 {
 
-                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Message = EVCBConfiguration.ERROR_MSG_CHARGEBOXID_ISNT_EXIST_OR_OFFLINE });
+                    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() { Message = EVCBConfiguration.ERROR_MSG_PARAMETER_OUTOFRANGE_INCORRECT });
+                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Code = 2100, Message = EVCBConfiguration.ERROR_MSG_PARAMETER_OUTOFRANGE_INCORRECT });
                 }
 
                 //create reqest
@@ -1007,7 +1052,7 @@ namespace EVCB_OCPP.WEBAPI.Controllers
                     throw new Exception("Write Command Fail!!");
                 }
 
-                statusCode = HttpStatusCode.Accepted;
+                statusCode = HttpStatusCode.OK;
                 result.SerialNo = uuid;
 
             }
@@ -1016,6 +1061,7 @@ namespace EVCB_OCPP.WEBAPI.Controllers
 
                 return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse()
                 {
+                    Code = 2999,
                     Message = string.Format(EVCBConfiguration.ERRORMESSAGE_FORMAT, EVCBConfiguration.ERROR_MSG_UNEXPECTEDERROR, "TriggerMessage", ex.ToString())
                 });
             }
@@ -1023,7 +1069,7 @@ namespace EVCB_OCPP.WEBAPI.Controllers
             return Request.CreateResponse(statusCode, result);
         }
 
-        [Route("unlockconnector/chargebox/{ChargeBoxId}/ connectorId/{ConnectorId}")]
+        [Route("unlockconnector")]
         [ResponseType(typeof(ErrorResponse))]
         [ResponseType(typeof(InternalGenericResponse))]
         [HttpPost]
@@ -1039,14 +1085,14 @@ namespace EVCB_OCPP.WEBAPI.Controllers
                 if (!chargePointService.IsOnline(ChargeBoxId))
                 {
 
-                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Message = EVCBConfiguration.ERROR_MSG_CHARGEBOXID_ISNT_EXIST_OR_OFFLINE });
+                    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() { Message = EVCBConfiguration.ERROR_MSG_PARAMETER_OUTOFRANGE_INCORRECT });
+                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Code = 2100, Message = EVCBConfiguration.ERROR_MSG_PARAMETER_OUTOFRANGE_INCORRECT });
                 }
 
                 //create reqest
@@ -1062,7 +1108,7 @@ namespace EVCB_OCPP.WEBAPI.Controllers
                     throw new Exception("Write Command Fail!!");
                 }
 
-                statusCode = HttpStatusCode.Accepted;
+                statusCode = HttpStatusCode.OK;
                 result.SerialNo = uuid;
 
             }
@@ -1071,6 +1117,7 @@ namespace EVCB_OCPP.WEBAPI.Controllers
 
                 return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse()
                 {
+                    Code = 2999,
                     Message = string.Format(EVCBConfiguration.ERRORMESSAGE_FORMAT, EVCBConfiguration.ERROR_MSG_UNEXPECTEDERROR, "UnlockConnector", ex.ToString())
                 });
             }
@@ -1079,7 +1126,7 @@ namespace EVCB_OCPP.WEBAPI.Controllers
         }
 
 
-        [Route("compositeschedule/chargebox/{ChargeBoxId}")]
+        [Route("compositeschedule")]
         [ResponseType(typeof(ErrorResponse))]
         [ResponseType(typeof(InternalGenericResponse))]
         [HttpGet]
@@ -1096,17 +1143,20 @@ namespace EVCB_OCPP.WEBAPI.Controllers
                 if (!chargePointService.IsOnline(ChargeBoxId))
                 {
 
-                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Message = EVCBConfiguration.ERROR_MSG_CHARGEBOXID_ISNT_EXIST_OR_OFFLINE });
+                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Code = 2101, Message = EVCBConfiguration.ERROR_MSG_CHARGEBOXID_ISNT_EXIST_OR_OFFLINE });
                 }
 
                 //check parameter
-                if (!(ConnectorId >= 0) ||
-                    !(ChargingRateUnit != -1 && ChargingRateUnit > 0 && ChargingRateUnit < 3))
+                if (!(ConnectorId >= 0) || !(Duration > 0))
                 {
 
-                    return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Message = EVCBConfiguration.ERROR_MSG_PARAMETER_OUTOFRANGE_INCORRECT });
+                    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()
                 {
@@ -1120,14 +1170,14 @@ namespace EVCB_OCPP.WEBAPI.Controllers
                     throw new Exception("Write Command Fail!!");
                 }
 
-                statusCode = HttpStatusCode.Accepted;
+                statusCode = HttpStatusCode.OK;
                 result.SerialNo = uuid;
 
             }
             catch (Exception ex)
             {
 
-                return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Message = string.Format(EVCBConfiguration.ERRORMESSAGE_FORMAT, EVCBConfiguration.ERROR_MSG_UNEXPECTEDERROR, "GetLocallistversion", ex.ToString()) });
+                return Request.CreateResponse(HttpStatusCode.BadRequest, new ErrorResponse() { Code = 2999, Message = string.Format(EVCBConfiguration.ERRORMESSAGE_FORMAT, EVCBConfiguration.ERROR_MSG_UNEXPECTEDERROR, "GetLocallistversion", ex.ToString()) });
             }
 
             return Request.CreateResponse(statusCode, result);

+ 3 - 1
EVCB_OCPP.WEBAPI/EVCBConfiguration.cs

@@ -16,10 +16,11 @@ namespace EVCB_OCPP.WEBAPI
         public static readonly string Header_Timestamp = "Timestamp";
        // public static readonly string Header_SerialNo = "SerialNo";
         public static readonly string DATETIMEFORMAT = "yyyy/MM/dd HH:mm:ss";
+        public static readonly string UTC_DATETIMEFORMAT = "yyyy/MM/dd'T'HH':'mm':'ss'Z'";
 
 
         public static readonly string ERRORMESSAGE_FORMAT = "{0}/{1}/{2}";
-      
+
         public static readonly DateTime DefaultTime = new DateTime(627982848000000000, DateTimeKind.Utc);
 
 
@@ -32,6 +33,7 @@ namespace EVCB_OCPP.WEBAPI
         public static readonly string ERROR_MSG_CHARGEPOINT_OFFLINE = "ChargePoint is offline.";
         public static readonly string ERROR_MSG_SESSION_WAS_FINISHED = "Session was finished.";
         public static readonly string ERROR_MSG_CONNECTOR_ISNOT_AVAILIABLE_MODE = "Connector is not in available mode.";
+        public static readonly string ERROR_MSG_CONNECTOR_ISNOT_CHARGING_MODE = "Connector is not in charging mode.";
         public static readonly string ERROR_MSG_DATA_NOTFOUND = "Oops! We can't find the details with request.";
 
         public static JsonSerializerSettings JSONSERIALIZER_FORMAT = new JsonSerializerSettings() { NullValueHandling = NullValueHandling.Ignore, Formatting = Formatting.None };

+ 79 - 2
EVCB_OCPP.WEBAPI/EVCB_OCPP.WEBAPI.csproj

@@ -52,13 +52,65 @@
       <SpecificVersion>False</SpecificVersion>
       <HintPath>Dll\EVCB_OCPP.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>
     <Reference Include="Microsoft.CSharp" />
+    <Reference Include="Microsoft.Extensions.Configuration, Version=3.1.2.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
+      <HintPath>..\packages\Microsoft.Extensions.Configuration.3.1.2\lib\netstandard2.0\Microsoft.Extensions.Configuration.dll</HintPath>
+    </Reference>
+    <Reference Include="Microsoft.Extensions.Configuration.Abstractions, Version=3.1.2.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
+      <HintPath>..\packages\Microsoft.Extensions.Configuration.Abstractions.3.1.2\lib\netstandard2.0\Microsoft.Extensions.Configuration.Abstractions.dll</HintPath>
+    </Reference>
+    <Reference Include="Microsoft.Extensions.Configuration.Binder, Version=3.1.2.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
+      <HintPath>..\packages\Microsoft.Extensions.Configuration.Binder.3.1.2\lib\netstandard2.0\Microsoft.Extensions.Configuration.Binder.dll</HintPath>
+    </Reference>
+    <Reference Include="Microsoft.Extensions.DependencyInjection, Version=3.1.2.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
+      <HintPath>..\packages\Microsoft.Extensions.DependencyInjection.3.1.2\lib\net461\Microsoft.Extensions.DependencyInjection.dll</HintPath>
+    </Reference>
+    <Reference Include="Microsoft.Extensions.DependencyInjection.Abstractions, Version=3.1.2.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
+      <HintPath>..\packages\Microsoft.Extensions.DependencyInjection.Abstractions.3.1.2\lib\netstandard2.0\Microsoft.Extensions.DependencyInjection.Abstractions.dll</HintPath>
+    </Reference>
+    <Reference Include="Microsoft.Extensions.Http, Version=3.1.2.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
+      <HintPath>..\packages\Microsoft.Extensions.Http.3.1.2\lib\netstandard2.0\Microsoft.Extensions.Http.dll</HintPath>
+    </Reference>
+    <Reference Include="Microsoft.Extensions.Logging, Version=3.1.2.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
+      <HintPath>..\packages\Microsoft.Extensions.Logging.3.1.2\lib\netstandard2.0\Microsoft.Extensions.Logging.dll</HintPath>
+    </Reference>
+    <Reference Include="Microsoft.Extensions.Logging.Abstractions, Version=3.1.2.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
+      <HintPath>..\packages\Microsoft.Extensions.Logging.Abstractions.3.1.2\lib\netstandard2.0\Microsoft.Extensions.Logging.Abstractions.dll</HintPath>
+    </Reference>
+    <Reference Include="Microsoft.Extensions.Options, Version=3.1.2.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
+      <HintPath>..\packages\Microsoft.Extensions.Options.3.1.2\lib\netstandard2.0\Microsoft.Extensions.Options.dll</HintPath>
+    </Reference>
+    <Reference Include="Microsoft.Extensions.Primitives, Version=3.1.2.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
+      <HintPath>..\packages\Microsoft.Extensions.Primitives.3.1.2\lib\netstandard2.0\Microsoft.Extensions.Primitives.dll</HintPath>
+    </Reference>
     <Reference Include="Newtonsoft.Json, Version=12.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
       <HintPath>..\packages\Newtonsoft.Json.12.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
     </Reference>
     <Reference Include="System" />
+    <Reference Include="System.Buffers, Version=4.0.2.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
+      <HintPath>..\packages\System.Buffers.4.4.0\lib\netstandard2.0\System.Buffers.dll</HintPath>
+    </Reference>
+    <Reference Include="System.ComponentModel.Annotations, Version=4.2.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
+      <HintPath>..\packages\System.ComponentModel.Annotations.4.7.0\lib\net461\System.ComponentModel.Annotations.dll</HintPath>
+    </Reference>
     <Reference Include="System.Data" />
     <Reference Include="System.Drawing" />
+    <Reference Include="System.Memory, Version=4.0.1.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
+      <HintPath>..\packages\System.Memory.4.5.2\lib\netstandard2.0\System.Memory.dll</HintPath>
+    </Reference>
+    <Reference Include="System.Numerics" />
+    <Reference Include="System.Numerics.Vectors, Version=4.1.3.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
+      <HintPath>..\packages\System.Numerics.Vectors.4.4.0\lib\net46\System.Numerics.Vectors.dll</HintPath>
+    </Reference>
+    <Reference Include="System.Runtime.CompilerServices.Unsafe, Version=4.0.6.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
+      <HintPath>..\packages\System.Runtime.CompilerServices.Unsafe.4.7.0\lib\netstandard2.0\System.Runtime.CompilerServices.Unsafe.dll</HintPath>
+    </Reference>
+    <Reference Include="System.Threading.Tasks.Extensions, Version=4.2.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
+      <HintPath>..\packages\System.Threading.Tasks.Extensions.4.5.2\lib\netstandard2.0\System.Threading.Tasks.Extensions.dll</HintPath>
+    </Reference>
     <Reference Include="System.Web.Entity" />
     <Reference Include="System.Web.ApplicationServices" />
     <Reference Include="System.ComponentModel.DataAnnotations" />
@@ -162,17 +214,38 @@
     <Compile Include="Areas\HelpPage\SampleGeneration\SampleDirection.cs" />
     <Compile Include="Areas\HelpPage\SampleGeneration\TextSample.cs" />
     <Compile Include="Areas\HelpPage\XmlDocumentationProvider.cs" />
+    <Compile Include="Controllers\FileController.cs" />
     <Compile Include="Controllers\HomeController.cs" />
-    <Compile Include="Controllers\InternalV1Controller.cs" />
+    <Compile Include="Controllers\Version1\CPOController.cs" />
+    <Compile Include="Controllers\Version1\InternalController.cs" />
     <Compile Include="Global.asax.cs">
       <DependentUpon>Global.asax</DependentUpon>
     </Compile>
     <Compile Include="EVCBConfiguration.cs" />
     <Compile Include="Handlers\APILogHandler.cs" />
+    <Compile Include="Handlers\CPOAuthentication.cs" />
     <Compile Include="Handlers\GlobalExceptionHandler .cs" />
     <Compile Include="Handlers\InernalAuthentication.cs" />
+    <Compile Include="Models\ConnectorMeterValue.cs" />
+    <Compile Include="Models\ConnectorMeterValueModel.cs" />
+    <Compile Include="Models\SessionDetail.cs" />
+    <Compile Include="Models\TransactionRecordModel.cs" />
     <Compile Include="Models\WebAPI\AvailiabilityRequest.cs" />
-    <Compile Include="Models\WebAPI\ComandExcution.cs" />
+    <Compile Include="Models\WebAPI\ComandExecution.cs" />
+    <Compile Include="Models\WebAPI\CPOResponseDescription.cs" />
+    <Compile Include="Models\WebAPI\CPOOuterResponse.cs" />
+    <Compile Include="Models\WebAPI\Dto\ChargingStation.cs" />
+    <Compile Include="Models\WebAPI\Dto\CommandResponseType.cs" />
+    <Compile Include="Models\WebAPI\Dto\CommandResultType.cs" />
+    <Compile Include="Models\WebAPI\Dto\CommandType.cs" />
+    <Compile Include="Models\WebAPI\Dto\Connector.cs" />
+    <Compile Include="Models\WebAPI\Dto\ConnectorPowerType.cs" />
+    <Compile Include="Models\WebAPI\Dto\ConnectorType.cs" />
+    <Compile Include="Models\WebAPI\Dto\EVSE.cs" />
+    <Compile Include="Models\WebAPI\Dto\GeoLocation.cs" />
+    <Compile Include="Models\WebAPI\Dto\ReserveNowRequest.cs" />
+    <Compile Include="Models\WebAPI\Dto\StartSessionRequest.cs" />
+    <Compile Include="Models\WebAPI\Dto\Status.cs" />
     <Compile Include="Models\WebAPI\ErrorResponse.cs" />
     <Compile Include="Models\WebAPI\InternalGenericRequest.cs" />
     <Compile Include="Models\WebAPI\InternalGenericResponse.cs" />
@@ -186,7 +259,11 @@
     <Compile Include="Properties\AssemblyInfo.cs" />
     <Compile Include="Services\ChargePointService.cs" />
     <Compile Include="Services\CustomerService.cs" />
+    <Compile Include="Services\EVSEService.cs" />
+    <Compile Include="Services\HttpClientService.cs" />
+    <Compile Include="Services\InternalHttpClient.cs" />
     <Compile Include="Services\ServerTriggerService.cs" />
+    <Compile Include="Services\ChargingStationService.cs" />
   </ItemGroup>
   <ItemGroup>
     <Content Include="Areas\HelpPage\HelpPage.css" />

+ 175 - 0
EVCB_OCPP.WEBAPI/Handlers/CPOAuthentication.cs

@@ -0,0 +1,175 @@
+using EVCB_OCPP.WEBAPI.Models.WebAPI;
+using EVCB_OCPP.WEBAPI.Services;
+using Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Net;
+using System.Net.Http;
+using System.Security.Cryptography;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+using System.Web;
+using System.Web.Http.Controllers;
+using System.Web.Http.Filters;
+
+namespace EVCB_OCPP.WEBAPI.Handlers
+{
+    public class CPOAuthentication : FilterAttribute, IAuthorizationFilter
+    {
+        public Task<HttpResponseMessage> ExecuteAuthorizationFilterAsync(HttpActionContext actionContext, CancellationToken cancellationToken, Func<Task<HttpResponseMessage>> continuation)
+        {
+            HttpStatusCode _status = HttpStatusCode.Unauthorized;
+            CPOOuterResponse _errorResponse = new CPOOuterResponse() { StatusMessage = CPO_StatusMessage.ERROR_MSG_INVALIDHEADER };
+
+            try
+            {
+                string formatMsg = "";
+                if (CheckHeaders(actionContext, out formatMsg))
+                {
+                    string timestamp = actionContext.Request.Headers.GetValues(EVCBConfiguration.Header_Timestamp).FirstOrDefault();
+
+                    if (IsExpiryTime(timestamp))
+                    {
+                        _errorResponse.StatusMessage = CPO_StatusMessage.ERROR_MSG_INVALIDTIMESTAMP;
+                    }
+                    else
+                    {
+                        string partnerId = actionContext.Request.Headers.GetValues(EVCBConfiguration.Header_PartnerId).FirstOrDefault();
+                        string key = new CustomerService().GetAPIKey(new Guid(partnerId));
+
+                        if (IsPass(actionContext, key))
+                        {
+                            return continuation().ContinueWith<HttpResponseMessage>((tsk) =>
+                            {
+                                HttpResponseMessage response = tsk.Result;
+
+                                return response;
+
+                            }, cancellationToken);
+                        }
+                        else
+                        {
+                            _errorResponse.StatusMessage = CPO_StatusMessage.ERROR_MSG_INVALIDSIGNATURE;
+                        }
+                    }
+
+                }
+                else
+                {
+                    _errorResponse.StatusMessage = formatMsg;
+                }
+
+            }
+            catch (Exception ex)
+            {
+                _errorResponse.StatusMessage = CPO_StatusMessage.ERROR_MSG_UNEXPECTEDERROR;
+            }
+
+
+            return FromResult(new HttpResponseMessage(_status) { Content = new StringContent(JsonConvert.SerializeObject(_errorResponse), System.Text.Encoding.UTF8, "application/json") });
+        }
+
+        private Task<HttpResponseMessage> FromResult(HttpResponseMessage result)
+        {
+            var source = new TaskCompletionSource<HttpResponseMessage>();
+            source.SetResult(result);
+
+
+            return source.Task;
+        }
+
+        private bool IsPass(HttpActionContext actionContext, string key)
+        {
+            bool authenticated = false;
+            string timestamp = actionContext.Request.Headers.GetValues(EVCBConfiguration.Header_Timestamp).FirstOrDefault();
+            string partnerId = actionContext.Request.Headers.GetValues(EVCBConfiguration.Header_PartnerId).FirstOrDefault();
+            string signature = actionContext.Request.Headers.GetValues(EVCBConfiguration.Header_Signature).FirstOrDefault();
+
+            Task<string> content = actionContext.Request.Content.ReadAsStringAsync();
+            string body = content.Result;
+            string tempText = actionContext.Request.RequestUri.ToString().Substring(actionContext.Request.RequestUri.ToString().IndexOf('?') + 1).ToLower();
+            tempText = tempText.StartsWith("http") ? string.Empty : tempText;
+            body = tempText + body;
+
+
+            string unencodeText = string.Format("{0}{1}{2}{3}", body, timestamp, partnerId, key).ToLower();
+            string signVerification = GenerateSignature(unencodeText);
+            if (signVerification == signature)
+            {
+                authenticated = true;
+            }
+
+            return authenticated;
+        }
+
+        private bool CheckHeaders(HttpActionContext actionContext, out string formatMessage)
+        {
+            formatMessage = string.Empty;
+
+            if (actionContext.Request.Headers.Contains(EVCBConfiguration.Header_PartnerId)
+               && actionContext.Request.Headers.Contains(EVCBConfiguration.Header_Signature)
+               && actionContext.Request.Headers.Contains(EVCBConfiguration.Header_Timestamp))
+            {
+                string timestamp = actionContext.Request.Headers.GetValues(EVCBConfiguration.Header_Timestamp).FirstOrDefault();
+                string PartnerId = actionContext.Request.Headers.GetValues(EVCBConfiguration.Header_PartnerId).FirstOrDefault();
+
+                long _timestamp = 0;
+                if (!long.TryParse(timestamp, out _timestamp))
+                {
+                    formatMessage = string.Format("{0} ", "Timestamp's Format is incorrect.");
+                    return false;
+                }
+                Guid _PartnerId = Guid.Empty;
+                if (!Guid.TryParse(PartnerId, out _PartnerId))
+                {
+                    formatMessage = string.Format("{0} ", "PartnerId's Format is incorrect.it must be Guid type");
+                    return false;
+                }
+
+                return true;
+            }
+            else
+            {
+                return false;
+            }
+        }
+
+        private static bool IsExpiryTime(string timestamp)
+        {
+            bool result = true;
+            long minTime = DateTimeOffset.UtcNow.AddSeconds(-300).ToUnixTimeSeconds();
+            long maxTime = DateTimeOffset.UtcNow.AddSeconds(300).ToUnixTimeSeconds();
+            long requestTime = 0;
+
+            if (long.TryParse(timestamp, out requestTime))
+            {
+                if (minTime < requestTime && maxTime > requestTime)
+                {
+                    result = false;
+                }
+            }
+
+            return result;
+        }
+
+
+        private static string GenerateSignature(string unencodeText)
+        {
+            if ((unencodeText == null) || (unencodeText.Length == 0))
+            {
+                return String.Empty;
+            }
+            unencodeText = unencodeText.ToLower();
+
+            MD5 md5 = new MD5CryptoServiceProvider();
+            byte[] textToHash = Encoding.UTF8.GetBytes(unencodeText);
+            byte[] result = md5.ComputeHash(textToHash);
+            return BitConverter.ToString(result).Replace("-", "").ToLower();
+
+        }
+
+
+    }
+}

+ 13 - 13
EVCB_OCPP.WEBAPI/Handlers/InernalAuthentication.cs

@@ -22,17 +22,18 @@ namespace EVCB_OCPP.WEBAPI.Handlers
         public Task<HttpResponseMessage> ExecuteAuthorizationFilterAsync(HttpActionContext actionContext, CancellationToken cancellationToken, Func<Task<HttpResponseMessage>> continuation)
         {
             HttpStatusCode _status = HttpStatusCode.Unauthorized;
-            ErrorResponse _errorResponse = new ErrorResponse() { Message = EVCBConfiguration.ERROR_MSG_INVALIDHEADER };
+            ErrorResponse _errorResponse = new ErrorResponse() { Code = 2001, Message = EVCBConfiguration.ERROR_MSG_INVALIDHEADER };
 
             try
             {
                 string formatMsg = "";
-                if (CheckHeaders(actionContext,out formatMsg))
+                if (CheckHeaders(actionContext, out formatMsg))
                 {
                     string timestamp = actionContext.Request.Headers.GetValues(EVCBConfiguration.Header_Timestamp).FirstOrDefault();
 
                     if (IsExpiryTime(timestamp))
                     {
+                        _errorResponse.Code = 2002;
                         _errorResponse.Message = EVCBConfiguration.ERROR_MSG_INVALIDTIMESTAMP;
                     }
                     else
@@ -52,6 +53,7 @@ namespace EVCB_OCPP.WEBAPI.Handlers
                         }
                         else
                         {
+                            _errorResponse.Code = 2003;
                             _errorResponse.Message = EVCBConfiguration.ERROR_MSG_INVALIDSIGNATURE;
                         }
                     }
@@ -65,6 +67,7 @@ namespace EVCB_OCPP.WEBAPI.Handlers
             }
             catch (Exception ex)
             {
+                _errorResponse.Code = 2000;
                 _errorResponse.Message = string.Format(EVCBConfiguration.ERRORMESSAGE_FORMAT, EVCBConfiguration.ERROR_MSG_UNEXPECTEDERROR, "InernalAuthentication", ex.ToString());
             }
 
@@ -91,17 +94,14 @@ namespace EVCB_OCPP.WEBAPI.Handlers
 
             Task<string> content = actionContext.Request.Content.ReadAsStringAsync();
             string body = content.Result;
+            string tempText = actionContext.Request.RequestUri.ToString().Substring(actionContext.Request.RequestUri.ToString().IndexOf('?') + 1).ToLower();
+            tempText = tempText.StartsWith("http") ? string.Empty : tempText;
+            body = tempText + body;
 
-            if (actionContext.Request.Method == HttpMethod.Get || actionContext.Request.Method == HttpMethod.Delete)
-            {
-                string tempText = actionContext.Request.RequestUri.ToString();
-                body = actionContext.Request.RequestUri.ToString().Substring(tempText.IndexOf('?') + 1).ToLower();
-                body = body.StartsWith("http") ? string.Empty : body;
-            }
 
             string unencodeText = string.Format("{0}{1}{2}{3}", body, timestamp, partnerId, key).ToLower();
-            string tt = GenerateSignature(unencodeText);
-            if (tt == signature)
+            string signVerification = GenerateSignature(unencodeText);
+            if (signVerification == signature)
             {
                 authenticated = true;
             }
@@ -113,11 +113,11 @@ namespace EVCB_OCPP.WEBAPI.Handlers
         {
             formatMessage = string.Empty;
 
-            if (actionContext.Request.Headers.Contains(EVCBConfiguration.Header_PartnerId)             
+            if (actionContext.Request.Headers.Contains(EVCBConfiguration.Header_PartnerId)
                && actionContext.Request.Headers.Contains(EVCBConfiguration.Header_Signature)
                && actionContext.Request.Headers.Contains(EVCBConfiguration.Header_Timestamp))
             {
-                string timestamp = actionContext.Request.Headers.GetValues(EVCBConfiguration.Header_Timestamp).FirstOrDefault();              
+                string timestamp = actionContext.Request.Headers.GetValues(EVCBConfiguration.Header_Timestamp).FirstOrDefault();
                 string PartnerId = actionContext.Request.Headers.GetValues(EVCBConfiguration.Header_PartnerId).FirstOrDefault();
 
                 long _timestamp = 0;
@@ -125,7 +125,7 @@ namespace EVCB_OCPP.WEBAPI.Handlers
                 {
                     formatMessage = string.Format("{0} ", "Timestamp's Format is incorrect.");
                     return false;
-                }               
+                }
                 Guid _PartnerId = Guid.Empty;
                 if (!Guid.TryParse(PartnerId, out _PartnerId))
                 {

+ 33 - 0
EVCB_OCPP.WEBAPI/Models/ConnectorMeterValue.cs

@@ -0,0 +1,33 @@
+using EVCB_OCPP.Packet.Messages.SubTypes;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Web;
+
+namespace EVCB_OCPP.WEBAPI.Models
+{
+    public class ConnectorMeterValue
+    {
+        public int ConnectorId { set; get; }
+
+        public int TransactionId { set; get; }
+
+        public string ChargeBoxId { set; get; }
+
+        public DateTime CreatedOn { set; get; }
+
+        public ReadingContext? Context { set; get; }
+       
+        public ValueFormat? Format { set; get; }
+      
+        public Measurand? Measurand { set; get; }
+      
+        public Phase? Phase { set; get; }
+       
+        public Location? Location { set; get; }
+     
+        public UnitOfMeasure? Unit { set; get; }
+
+        public string Value { set; get; }
+    }
+}

+ 34 - 0
EVCB_OCPP.WEBAPI/Models/ConnectorMeterValueModel.cs

@@ -0,0 +1,34 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Web;
+
+namespace EVCB_OCPP.WEBAPI.Models
+{
+    public class ConnectorMeterValueModel
+    {
+        public int ConnectorId { set; get; }
+
+        public int TransactionId { set; get; }
+
+        public string ChargeBoxId { set; get; }
+
+        public DateTime CreatedOn { set; get; }
+
+        public int ContextId { set; get; }
+
+        public int FormatId { set; get; }
+
+        public int MeasurandId { set; get; }
+
+        public int PhaseId { set; get; }
+
+        public int LocationId { set; get; }
+
+        public int UnitId { set; get; }
+
+        public string Value { set; get; }
+
+
+    }
+}

+ 45 - 0
EVCB_OCPP.WEBAPI/Models/SessionDetail.cs

@@ -0,0 +1,45 @@
+using EVCB_OCPP.Packet.Messages.SubTypes;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Web;
+
+namespace EVCB_OCPP.WEBAPI.Models
+{
+    public class SessionDetail
+    {
+        
+        /// <summary>
+        /// 槍號 
+        /// </summary>       
+        public int ConnectorId { get; set; }      
+
+        public string IdTag { get; set; }    
+
+        /// <summary>
+        /// 開始充電開始時間
+        /// </summary>
+        public string StartTime { get; set; }
+
+        /// <summary>
+        /// 充電結束時間
+        /// </summary>
+        public string StopTime { get; set; }      
+      
+
+        /// <summary>
+        /// 開始meter
+        /// </summary>      
+        public decimal MeterStart { get; set; }
+
+        /// <summary>
+        /// 結束meter
+        /// </summary>
+        public decimal MeterStop { get; set; }
+
+        /// <summary>
+        /// 停止原因
+        /// </summary>
+        public Reason StopReason { set; get; }
+    }
+}

+ 75 - 0
EVCB_OCPP.WEBAPI/Models/TransactionRecordModel.cs

@@ -0,0 +1,75 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Web;
+
+namespace EVCB_OCPP.WEBAPI.Models
+{
+    public class TransactionRecordModel
+    {
+        /// <summary>
+        /// chargePointSerialNumber
+        /// </summary>       
+        public string ChargeBoxId { get; set; }
+
+
+        /// <summary>
+        /// 槍號  1 byte string、本來是 string、改為byte
+        /// </summary>       
+        public byte ConnectorId { get; set; }
+
+
+        /// <summary>
+        /// TransactionId
+        /// </summary>     
+        public int TransactionId { get; set; }
+
+
+       
+
+        /// <summary>
+        /// StartIdTag
+        /// </summary>
+        public string StartIdTag { get; set; }
+
+
+        /// <summary>
+        /// StopIdTag
+        /// </summary>   
+        public string StopIdTag { get; set; }
+
+        /// <summary>
+        /// 開始充電開始時間
+        /// </summary>
+        public DateTime StartTime { get; set; }
+
+        /// <summary>
+        /// 充電結束時間
+        /// </summary>
+        public DateTime StopTime { get; set; }
+
+        /// <summary>
+        /// 預約Id
+        /// </summary>
+        public int ReservationId { set; get; }
+
+        /// <summary>
+        /// 停止原因No
+        /// </summary>
+        public int StopReasonId { set; get; }
+
+        /// <summary>
+        /// 開始meter
+        /// </summary>      
+        public decimal MeterStart { get; set; }
+
+        /// <summary>
+        /// 結束meter
+        /// </summary>
+        public decimal MeterStop { get; set; }
+       
+
+
+       
+    }
+}

+ 32 - 0
EVCB_OCPP.WEBAPI/Models/WebAPI/CPOOuterResponse.cs

@@ -0,0 +1,32 @@
+using Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Web;
+
+namespace EVCB_OCPP.WEBAPI.Models.WebAPI
+{
+    public class CPOOuterResponse
+    {
+        public CPOOuterResponse()
+        {
+            StatusCode = (int)CPO_StatusCode.NoAction;
+        }
+
+        public int StatusCode { set; get; }
+
+        public string StatusMessage { set; get;}
+
+        public string Data { set; get; }
+
+        [JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
+        public string SerialNo { set; get; }
+
+        [JsonIgnore]
+        public string ErrorDetail { set; get; }
+
+
+    }
+
+
+}

+ 49 - 0
EVCB_OCPP.WEBAPI/Models/WebAPI/CPOResponseDescription.cs

@@ -0,0 +1,49 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Web;
+
+namespace EVCB_OCPP.WEBAPI.Models.WebAPI
+{
+    public enum CPO_StatusCode
+    {
+        NoAction = -1,
+        Success = 1000,
+        Generic_Client_Error = 2000,
+        Unknown_AuthorizationHeader = 2001,
+        PARAMETER_OUTOFRANGE_INCORRECT = 2100,
+        CHARGEBOXID_ISNT_EXIST_OR_OFFLINE = 2101,
+        CANT_FOUND_DATA = 2102,
+        ChargePoint_OFFLINE_OR_UNAVAILABLE = 2103,
+        SESSION_FINISHED = 2104,
+        ChargePoint_UNCHARGING_MODE = 2105,
+
+
+
+
+        UnexpectedError = 2999,
+
+    }
+
+    public static class CPO_StatusMessage
+    {
+        public static readonly string SUCCESS = "Success";
+        public static readonly string ERROR_MSG_INVALIDHEADER = "Invaild Headers";
+        public static readonly string ERROR_MSG_INVALIDTIMESTAMP = "Invaild Timestamp";
+        public static readonly string ERROR_MSG_INVALIDSIGNATURE = "Invaild Signature";
+        public static readonly string ERROR_MSG_UNEXPECTEDERROR = "Unexpected Error";
+        public static readonly string ERROR_MSG_PARAMETER_OUTOFRANGE_INCORRECT = "Parameter is out of range or incorrect.";
+        public static readonly string ERROR_MSG_CHARGEBOXID_ISNT_EXIST_OR_OFFLINE = "ChargeBoxId isn't exist or offline.";
+        public static readonly string ERROR_MSG_CHARGEBOXID_DOESNT_EXIST = "ChargeBoxId doesn't exist.";
+        public static readonly string ERROR_MSG_CHARGEPOINT_OFFLINE = "ChargePoint is offline.";
+        public static readonly string ERROR_MSG_SESSION_WAS_FINISHED = "Session was finished.";
+        public static readonly string ERROR_MSG_CONNECTOR_ISNOT_AVAILIABLE_MODE = "Connector is not in available mode.";
+        public static readonly string ERROR_MSG_DATA_NOTFOUND = "Oops! We can't find the details with request.";
+        public static readonly string ERROR_MSG_InnerService_TERMINATED = "Oops! Inner service terminated.";
+        public static readonly string ERROR_MSG_CANT_FIND_ERRORCODE = "Can't find the descirption of error code.";
+        public static readonly string ERROR_MSG_CANT_FIND_RESULT = "Can't find the execution of result.";
+        public static readonly string ERROR_MSG_CANT_FIND_SESSIONDETAIL = "Can't find the session details.";
+        public static readonly string ERROR_MSG_CONNECTOR_ISNOT_CHARGING_MODE = "Connector is not in charging mode.";
+        public static readonly string ERROR_MSG_INNERSERVICE_ERROR = "An internal error has occurred.";
+    }
+}

+ 0 - 16
EVCB_OCPP.WEBAPI/Models/WebAPI/ComandExcution.cs

@@ -1,16 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Web;
-
-namespace EVCB_OCPP.WEBAPI.Models.WebAPI
-{
-    public class ComandExcution
-    {
-        public bool IeRepliedbyEVSE { set; get; }
-
-        public int Code { set; get; }
-
-        public string Detail { set; get; }
-    }
-}

+ 21 - 0
EVCB_OCPP.WEBAPI/Models/WebAPI/ComandExecution.cs

@@ -0,0 +1,21 @@
+using Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Web;
+
+namespace EVCB_OCPP.WEBAPI.Models.WebAPI
+{
+    public class ComandExecution
+    {
+        public bool? IsTimeout { set; get; }
+
+        public bool? IsWaited { set; get; }
+
+        public bool IsRepliedbyEVSE { set; get; }
+
+        public int Code { set; get; }
+
+        public string Detail { set; get; }
+    }
+}

+ 16 - 0
EVCB_OCPP.WEBAPI/Models/WebAPI/Dto/ChargingStation.cs

@@ -0,0 +1,16 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Web;
+
+namespace EVCB_OCPP.WEBAPI.Models.WebAPI.Dto
+{
+    public class ChargingStation
+    {
+        public string Id { set; get; }
+
+        public string Name { set; get; }
+
+        public GeoLocation Coordinates { set; get; }
+    }
+}

+ 16 - 0
EVCB_OCPP.WEBAPI/Models/WebAPI/Dto/CommandResponseType.cs

@@ -0,0 +1,16 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Web;
+
+namespace EVCB_OCPP.WEBAPI.Models.WebAPI.Dto
+{
+    public enum CommandResponseType
+    {
+        NotSupported,
+        Rejected,
+        Accepted,
+        UnknownSession
+
+    }
+}

+ 22 - 0
EVCB_OCPP.WEBAPI/Models/WebAPI/Dto/CommandResultType.cs

@@ -0,0 +1,22 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Web;
+
+namespace EVCB_OCPP.WEBAPI.Models.WebAPI.Dto
+{
+    public enum CommandResultType
+    {
+        Waited,//server
+        Timeout,//server
+        Accepted,
+        Rejected,
+        Failed,
+        Occupied,
+        Notsupported,
+        Unknown,
+        EVSE_ERROR//EVSE Replied error call
+
+
+    }
+}

+ 20 - 0
EVCB_OCPP.WEBAPI/Models/WebAPI/Dto/CommandType.cs

@@ -0,0 +1,20 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Web;
+
+namespace EVCB_OCPP.WEBAPI.Models.WebAPI.Dto
+{
+    public enum CommandType
+    {
+        Start_Session,
+        Stop_Session,
+        Reserve_Now,
+        CancelReservation,
+        GetAcitveChargingProfile,
+        SetChargingProfile,
+        ClearChargingProfile,
+        SetLocalList,
+        GetLocalListVersion
+    }
+}

+ 21 - 0
EVCB_OCPP.WEBAPI/Models/WebAPI/Dto/Connector.cs

@@ -0,0 +1,21 @@
+using Newtonsoft.Json;
+using Newtonsoft.Json.Converters;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Web;
+
+namespace EVCB_OCPP.WEBAPI.Models.WebAPI.Dto
+{
+    public class Connector
+    {
+        [JsonConverter(typeof(StringEnumConverter))]
+        public Status Status { set; get; }
+
+        [JsonConverter(typeof(StringEnumConverter))]
+        public ConnectorType ConnectorType { set; get; }
+
+        [JsonConverter(typeof(StringEnumConverter))]
+        public ConnectorPowerType PowerType { set; get; }
+    }
+}

+ 14 - 0
EVCB_OCPP.WEBAPI/Models/WebAPI/Dto/ConnectorPowerType.cs

@@ -0,0 +1,14 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Web;
+
+namespace EVCB_OCPP.WEBAPI.Models.WebAPI.Dto
+{
+    public enum ConnectorPowerType
+    {
+        AC_1_PHASE,
+        AC_3_PHASE,
+        DC
+    }
+}

+ 17 - 0
EVCB_OCPP.WEBAPI/Models/WebAPI/Dto/ConnectorType.cs

@@ -0,0 +1,17 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Web;
+
+namespace EVCB_OCPP.WEBAPI.Models.WebAPI.Dto
+{
+    public enum ConnectorType
+    {
+        CHADEMO,
+        AC,
+        CCS1,
+        CCS2,
+        GB,
+        Other
+    }
+}

+ 25 - 0
EVCB_OCPP.WEBAPI/Models/WebAPI/Dto/EVSE.cs

@@ -0,0 +1,25 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
+using System.Linq;
+using System.Web;
+
+namespace EVCB_OCPP.WEBAPI.Models.WebAPI.Dto
+{
+    public class EVSE
+    {
+        [MaxLength(25)]
+        public string ChargeBoxId { set; get; }
+
+        public int StationId { set; get; }
+
+        public int RatedPower { set; get; }
+
+        public List<Connector> Connectors { set; get; }
+
+        public Status Status { set; get; }
+
+        public GeoLocation Coordinates { set; get; }

+        public DateTime LastUpdated { set; get; }
+    }
+}

+ 22 - 0
EVCB_OCPP.WEBAPI/Models/WebAPI/Dto/GeoLocation.cs

@@ -0,0 +1,22 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Web;
+
+namespace EVCB_OCPP.WEBAPI.Models.WebAPI.Dto
+{
+    public class GeoLocation
+    {
+        /// <summary>
+        /// Latitude of the point in decimal degree. Example: 50.770774. Decimal
+        ///separator: "." Regex: -?[0-9]{1,2}\.[0-9]{5,7}
+        /// </summary>
+        public string Latitude { set; get; }
+
+        /// <summary>
+        /// Longitude of the point in decimal degree. Example: -126.104965. Decimal
+        ///separator: "." Regex: -?[0-9]{1,3}\.[0-9]{5,7}
+        /// </summary>
+        public string Longitude { set; get; }
+    }
+}

+ 20 - 0
EVCB_OCPP.WEBAPI/Models/WebAPI/Dto/ReserveNowRequest.cs

@@ -0,0 +1,20 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Web;
+
+namespace EVCB_OCPP.WEBAPI.Models.WebAPI.Dto
+{
+    public class ReserveNowRequest
+    {
+        public string ChargeBoxId { set; get; }
+
+        public int ConnectorId { set; get; }
+
+        public string Token { set; get; }
+
+        public int ReservationId { set; get; }
+
+        public DateTime ExpiryDate { set; get; }
+    }
+}

+ 16 - 0
EVCB_OCPP.WEBAPI/Models/WebAPI/Dto/StartSessionRequest.cs

@@ -0,0 +1,16 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Web;
+
+namespace EVCB_OCPP.WEBAPI.Models.WebAPI.Dto
+{
+    public class StartSessionRequest
+    {
+        public string ChargeBoxId { set; get; }
+
+        public int ConnectorId { set; get; }
+
+        public string Token { set; get; }
+    }
+}

+ 20 - 0
EVCB_OCPP.WEBAPI/Models/WebAPI/Dto/Status.cs

@@ -0,0 +1,20 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Web;
+
+namespace EVCB_OCPP.WEBAPI.Models.WebAPI.Dto
+{
+    public enum Status
+    {
+        Available,
+        Unavailable,
+        Charging,
+        UnderConstruction,
+        Faulted,
+        Remove,
+        Reserved,
+        Unknown
+
+    }
+}

+ 1 - 1
EVCB_OCPP.WEBAPI/Models/WebAPI/ErrorResponse.cs

@@ -8,7 +8,7 @@ namespace EVCB_OCPP.WEBAPI.Models.WebAPI
     public class ErrorResponse
     {
 
-        //public string Code { set; get; }
+        public int Code { set; get; }
 
         public string Message { set; get; }
     }

+ 2 - 0
EVCB_OCPP.WEBAPI/Models/WebAPI/MachineOperation.cs

@@ -7,6 +7,8 @@ namespace EVCB_OCPP.WEBAPI.Models.WebAPI
 {
     public class MachineOperation
     {
+        public string Action { set; get; }
+
         public int Status { set; get; }
 
         public int EVSE_Status { set; get; }

+ 3 - 0
EVCB_OCPP.WEBAPI/Models/WebAPI/SetChargingProfileRequest.cs

@@ -7,6 +7,9 @@ using System.Web;
 
 namespace EVCB_OCPP.WEBAPI.Models.WebAPI
 {
+   
+
+
     public class ChargingProfileRequest
     {
         [Required]

+ 120 - 0
EVCB_OCPP.WEBAPI/Services/ChargePointService.cs

@@ -1,5 +1,6 @@
 using Dapper;
 using EVCB_OCPP.Packet.Messages.SubTypes;
+using EVCB_OCPP.WEBAPI.Models;
 using System;
 using System.Collections.Generic;
 using System.Configuration;
@@ -133,6 +134,125 @@ namespace EVCB_OCPP.WEBAPI.Services
         }
 
 
+        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; ";
+                existed = conn.ExecuteScalar<bool>(strSql, parameters, null, EVCBConfiguration.DB_DefaultConnectionTimeout);
+            }
+
+            return existed;
+        }
+
+        public List<ConnectorMeterValue> GetActiveSessionInfo(string chargeBoxId, string sessionId, List<Measurand> requiredMeasurands)
+        {
+            List<ConnectorMeterValue> meterValues = new List<ConnectorMeterValue>();
+            ConnectorMeterValueModel meterModel = null;
+            if (string.IsNullOrEmpty(chargeBoxId)) return meterValues;
+
+            for (int i = 0; i < requiredMeasurands.Count; i++)
+            {
+                var parameters = new DynamicParameters();
+                parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input);
+                parameters.Add("@TransactionId", sessionId, DbType.String, ParameterDirection.Input);
+                parameters.Add("@MeasurandId", requiredMeasurands[i], DbType.String, ParameterDirection.Input);
+
+                try
+                {
+                    using (SqlConnection conn = new SqlConnection(mainConnectionString))
+                    {
+                        string date = DateTime.UtcNow.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)
+                    {
+                        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
+                {
+                    break;
+                }
+              
+            }
+
+            return meterValues;
+        }
+
+
+        public SessionDetail GetSessionDetail(string chargeBoxId, string sessionId)
+        {
+            SessionDetail detail = null;
+            TransactionRecordModel transactionModel = null;
+            if (string.IsNullOrEmpty(chargeBoxId)) return detail;
+
+            var parameters = new DynamicParameters();
+            parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input);
+            parameters.Add("@TransactionId", sessionId, DbType.String, ParameterDirection.Input);
+
+            try
+            {
+                using (SqlConnection conn = new SqlConnection(mainConnectionString))
+                {
+                    string date = DateTime.UtcNow.ToString("yyMMdd");
+                    string strSql = "Select Top(1) * from [dbo].[TransactionRecord] where ChargeBoxId=@ChargeBoxId and TransactionId=@TransactionId and StopTime!='1991-01-01 00:00:00.000' ;";
+                    transactionModel = conn.Query<TransactionRecordModel>(strSql, parameters, null, true, EVCBConfiguration.DB_DefaultConnectionTimeout).FirstOrDefault();
+
+                }
+
+                if (transactionModel != null)
+                {
+                    detail = new SessionDetail()
+                    {
+                        ConnectorId = (int)transactionModel.ConnectorId,
+                        IdTag = transactionModel.StartIdTag,
+                        MeterStart = transactionModel.MeterStart,
+                        MeterStop = transactionModel.MeterStop,
+                        StartTime = transactionModel.StartTime.ToString(EVCBConfiguration.UTC_DATETIMEFORMAT),
+                        StopTime = transactionModel.StopTime.ToString(EVCBConfiguration.UTC_DATETIMEFORMAT),
+                        StopReason = transactionModel.StopReasonId < 1 ? Reason.Local : (Reason)transactionModel.StopReasonId
+                    };
+
+                }
+
+            }
+            catch
+            {
+               
+            }
+
+            
+            return detail;
+        }
 
     }
 }

+ 28 - 0
EVCB_OCPP.WEBAPI/Services/ChargingStationService.cs

@@ -0,0 +1,28 @@
+using EVCB_OCPP.WEBAPI.Models.WebAPI.Dto;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Web;
+
+namespace EVCB_OCPP.WEBAPI.Services
+{
+
+    public interface IChargingStationService
+    {
+        List<ChargingStation> GetStationsbyCustomerId(string customerId);
+
+    }
+    public class ChargingStationService : IChargingStationService
+    {
+        public List<ChargingStation> GetStationsbyCustomerId(string customerId)
+        {
+            return new List<ChargingStation>();
+        }
+
+
+        public List<EVSE> GetEVSEsbyStationId(string customerId,int stationId)
+        {
+            return new List<EVSE>();
+        }
+    }
+}

+ 39 - 0
EVCB_OCPP.WEBAPI/Services/EVSEService.cs

@@ -0,0 +1,39 @@
+using EVCB_OCPP.WEBAPI.Models.WebAPI.Dto;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Web;
+
+namespace EVCB_OCPP.WEBAPI.Services
+{
+
+    public interface IEVSEService
+    {
+        List<EVSE> GetEVSEsbyCustomerIdAndStationId(string customerId, string stationId);
+
+        EVSE GetEVSEbyChargeBoxId(string chargeBoxId);
+
+
+     //   EVSE GetEVSEbyChargeBoxId(string chargeBoxId);
+
+
+
+    }
+    public class EVSEService : IEVSEService
+    {
+        public EVSE GetEVSEbyChargeBoxId(string chargeBoxId)
+        {
+            throw new NotImplementedException();
+        }
+
+        public List<EVSE> GetEVSEsbyCustomerId(string customerId)
+        {
+            throw new NotImplementedException();
+        }
+
+        public List<EVSE> GetEVSEsbyCustomerIdAndStationId(string customerId, string stationId)
+        {
+            throw new NotImplementedException();
+        }
+    }
+}

+ 315 - 0
EVCB_OCPP.WEBAPI/Services/HttpClientService.cs

@@ -0,0 +1,315 @@
+using Microsoft.Extensions.DependencyInjection;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Net;
+using System.Net.Http;
+using System.Net.Http.Headers;
+using System.Threading.Tasks;
+using System.Web;
+
+namespace EVCB_OCPP.WEBAPI.Services
+{
+    public class HttpClientService
+    {
+        /// <summary>
+        /// 要求逾時前等候的時間長度
+        /// #網域名稱系統(DNS)查詢最多可能需要15秒的時間才會傳回或超時
+        /// 預設60秒
+        /// </summary>
+        public int Timeout { get => _timeout; set => _timeout = value; }
+
+        /// <summary>
+        /// 取得或設定使用 HttpClient 物件提出要求時,所允許的同時連線 數目上限 (每個伺服器端點)。
+        /// 請注意,此限制是按照每個伺服器端點計算,例如值 256 允許 http://www.adatum.com/ 使用 256 個同時連線,
+        /// 而 http://www.adventure-works.com/ 另有 256 個同時連線。
+        /// 預設100個
+        /// </summary>
+        public int MaxConnectionsPerServer { get => _maxConnectionsPerServer; set => _maxConnectionsPerServer = value; }
+
+
+        /// <summary>
+        /// 設定HttpMessageHandler的生命週期,如果其存留期間尚未過期,HttpMessageHandler 執行個體可從集區重複使用(建立新的 HttpClient 執行個體時)
+        /// 因為處理常式通常會管理自己專屬的底層 HTTP 連線。 建立比所需數目更多的處理常式,可能會導致連線延遲。 有些處理常式也會保持連線無限期地開啟,這可能導致處理常式無法回應 DNS (網域名稱系統)變更。
+        /// 預設處理常式存留時間為120秒。
+        /// </summary>
+        public int HandlerLifetime { get => _handlerLifetime; set => _handlerLifetime = value; }
+
+
+        private IHttpClientFactory _clientFactory = null;
+        private IServiceCollection _services = new ServiceCollection();
+        private int _handlerLifetime = 2;
+        private int _maxConnectionsPerServer = 20;
+        private int _timeout = 60;
+
+
+        public HttpClientService(string baseAddress = "")
+        {
+
+            _services.AddHttpClient("Default", c =>
+            {
+                if (!string.IsNullOrEmpty(baseAddress))
+                {
+                    c.BaseAddress = new Uri(baseAddress);
+                }
+                c.Timeout = TimeSpan.FromSeconds(_timeout);
+                c.DefaultRequestHeaders.Add("Cache-Control", "no-cache");
+            })
+          .AddTypedClient<HttpClient>().SetHandlerLifetime(TimeSpan.FromSeconds(_handlerLifetime)).ConfigurePrimaryHttpMessageHandler((h =>
+          {
+              return new HttpClientHandler
+              {
+                  MaxConnectionsPerServer = _maxConnectionsPerServer
+
+              };
+          }));
+
+            Init();
+        }
+
+
+        //public HttpClientService(IServiceCollection services)
+        //{
+        //    _services = services;
+        //    Init();
+
+        //}
+
+        private void Init()
+        {
+            _clientFactory = _services.BuildServiceProvider()
+                     .GetRequiredService<IHttpClientFactory>();
+        }
+
+
+        public virtual async Task<HttpResponse> PostJsonAsync(string Url, string bodyData, Dictionary<string, string> headers, string clientName = "Default", bool bearerToken = false, string authorizationToken = null)
+        {
+            HttpResponse result = new HttpResponse() { IsError = false };
+
+            try
+            {
+                var client = _clientFactory.CreateClient(clientName);
+
+                if (!string.IsNullOrEmpty(authorizationToken))
+                {
+                    client.DefaultRequestHeaders.Authorization = bearerToken ? new AuthenticationHeaderValue("Bearer", authorizationToken) : new AuthenticationHeaderValue(authorizationToken);
+                }
+                if (headers != null)
+                {
+                    for (int idx = 0; idx < headers.Count; idx++)
+                    {
+                        client.DefaultRequestHeaders.Add(headers.ElementAt(idx).Key, headers.ElementAt(idx).Value);
+                    }
+                }
+
+                HttpContent content = new StringContent(bodyData);
+                content.Headers.ContentType = new MediaTypeWithQualityHeaderValue("application/json");
+                content.Headers.ContentType.CharSet = "UTF-8";
+
+                var response = await client.PostAsync(Url, content).ConfigureAwait(false);
+
+                result.IsSuccessStatusCode = response.IsSuccessStatusCode;
+                result.Headers = response.Headers;
+                result.RequestMessage = response.RequestMessage;
+                result.StatusCode = response.StatusCode;
+                result.Response = await response.Content.ReadAsStringAsync();
+
+
+
+            }
+            catch (Exception ex)
+            {
+                result.IsError = true;
+                result.Exception = ex;
+
+            }
+
+
+            return result;
+        }
+
+        public virtual async Task<HttpResponse> GetJsonAsync(string Url, Dictionary<string, string> headers, string clientName = "Default", bool bearerToken = false, string authorizationToken = null)
+        {
+            HttpResponse result = new HttpResponse() { IsError = false };
+
+            try
+            {
+                var client = _clientFactory.CreateClient(clientName);
+
+                if (!string.IsNullOrEmpty(authorizationToken))
+                {
+                    client.DefaultRequestHeaders.Authorization = bearerToken ? new AuthenticationHeaderValue("Bearer", authorizationToken) : new AuthenticationHeaderValue(authorizationToken);
+                }
+
+                if (headers != null)
+                {
+                    for (int idx = 0; idx < headers.Count; idx++)
+                    {
+                        client.DefaultRequestHeaders.Add(headers.ElementAt(idx).Key, headers.ElementAt(idx).Value);
+                    }
+                }
+
+               // client.DefaultRequestHeaders.Add("Content-Type", "application/json");
+
+
+                var response = await client.GetAsync(Url).ConfigureAwait(false);
+
+                result.IsSuccessStatusCode = response.IsSuccessStatusCode;
+                result.Headers = response.Headers;
+                result.RequestMessage = response.RequestMessage;
+                result.StatusCode = response.StatusCode;
+                result.Response = await response.Content.ReadAsStringAsync();
+
+
+
+            }
+            catch (Exception ex)
+            {
+                result.IsError = true;
+                result.Exception = ex;
+
+            }
+
+
+            return result;
+        }
+
+        public virtual async Task<HttpResponse> PutJsonAsync(string Url, string bodyData, Dictionary<string, string> headers, string clientName = "Default", bool bearerToken = false, string authorizationToken = null)
+        {
+            HttpResponse result = new HttpResponse() { IsError = false };
+
+            try
+            {
+                var client = _clientFactory.CreateClient(clientName);
+
+                if (!string.IsNullOrEmpty(authorizationToken))
+                {
+                    client.DefaultRequestHeaders.Authorization = bearerToken ? new AuthenticationHeaderValue("Bearer", authorizationToken) : new AuthenticationHeaderValue(authorizationToken);
+                }
+                if (headers != null)
+                {
+                    for (int idx = 0; idx < headers.Count; idx++)
+                    {
+                        client.DefaultRequestHeaders.Add(headers.ElementAt(idx).Key, headers.ElementAt(idx).Value);
+                    }
+                }
+
+                HttpContent content = new StringContent(bodyData);
+                content.Headers.ContentType = new MediaTypeWithQualityHeaderValue("application/json");
+                content.Headers.ContentType.CharSet = "UTF-8";
+
+                var response = await client.PutAsync(Url, content).ConfigureAwait(false);
+
+                result.IsSuccessStatusCode = response.IsSuccessStatusCode;
+                result.Headers = response.Headers;
+                result.RequestMessage = response.RequestMessage;
+                result.StatusCode = response.StatusCode;
+                result.Response = await response.Content.ReadAsStringAsync();
+
+
+
+            }
+            catch (Exception ex)
+            {
+                result.IsError = true;
+                result.Exception = ex;
+
+            }
+
+
+            return result;
+        }
+
+        public virtual async Task<HttpResponse> DeleteJsonAsync(string Url, Dictionary<string, string> headers, string clientName = "Default", bool bearerToken = false, string authorizationToken = null)
+        {
+            HttpResponse result = new HttpResponse() { IsError = false };
+
+            try
+            {
+                var client = _clientFactory.CreateClient(clientName);
+
+                if (!string.IsNullOrEmpty(authorizationToken))
+                {
+                    client.DefaultRequestHeaders.Authorization = bearerToken ? new AuthenticationHeaderValue("Bearer", authorizationToken) : new AuthenticationHeaderValue(authorizationToken);
+                }
+
+                if (headers != null)
+                {
+                    for (int idx = 0; idx < headers.Count; idx++)
+                    {
+                        client.DefaultRequestHeaders.Add(headers.ElementAt(idx).Key, headers.ElementAt(idx).Value);
+                    }
+                }
+
+             //   client.DefaultRequestHeaders.Add("Content-Type", "application/json");
+
+
+                var response = await client.DeleteAsync(Url).ConfigureAwait(false);
+
+                result.IsSuccessStatusCode = response.IsSuccessStatusCode;
+                result.Headers = response.Headers;
+                result.RequestMessage = response.RequestMessage;
+                result.StatusCode = response.StatusCode;
+                result.Response = await response.Content.ReadAsStringAsync();
+
+
+
+            }
+            catch (Exception ex)
+            {
+                result.IsError = true;
+                result.Exception = ex;
+
+            }
+
+
+            return result;
+        }
+
+    }
+
+
+    public class HttpResponse
+    {
+        public bool IsError { internal set; get; }
+
+        public Exception Exception { internal set; get; }
+
+        public string Response { internal set; get; }
+
+        /// <summary>
+        /// 摘要:
+        ///     取得或設定 HTTP 回應的狀態碼。
+        /// 傳回:
+        ///    HTTP 回應的狀態碼。
+        /// </summary>
+        public HttpStatusCode StatusCode { get; internal set; }
+
+
+        /// <summary>
+        /// 摘要:
+        ///      取得 HTTP 回應標頭的集合。
+        /// 傳回:
+        ///     HTTP 回應標頭的集合。
+        /// </summary>
+        public HttpResponseHeaders Headers { get; internal set; }
+
+
+        /// <summary>
+        /// 摘要:
+        ///     取得或設定導致此回應訊息的要求訊息。
+        /// 傳回:
+        ///       導致此回應訊息的要求訊息。
+        /// </summary>
+        public HttpRequestMessage RequestMessage { get; internal set; }
+
+        /// <summary>
+        /// 摘要:
+        ///   取得指示 HTTP 回應是否成功的值。
+        /// 傳回:
+        ///       指示 HTTP 回應是否成功的值。 如果 System.Net.Http.HttpResponseMessage.StatusCode 在 200-299
+        ///     的範圍內,則為 true;否則為 false。
+        /// </summary>
+        public bool IsSuccessStatusCode { get; internal set; }
+    }
+}

+ 296 - 0
EVCB_OCPP.WEBAPI/Services/InternalHttpClient.cs

@@ -0,0 +1,296 @@
+using EVCB_OCPP.WEBAPI.Models.WebAPI;
+using Newtonsoft.Json;
+using Newtonsoft.Json.Linq;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Net;
+using System.Security.Cryptography;
+using System.Text;
+using System.Threading.Tasks;
+using System.Web;
+
+namespace EVCB_OCPP.WEBAPI.Services
+{
+    public class InternalHttpClient
+    {
+        private HttpClientService httpClient = new HttpClientService();
+
+        async public Task<InternalHttpResult> Post(string url, Dictionary<string, string> headers, object requestBody, string saltkey)
+        {
+            InternalHttpResult result = new InternalHttpResult() { Success = false };
+
+            try
+            {
+                string body = PreAction(url, ref headers, requestBody, saltkey);
+                var _response = await httpClient.PostJsonAsync(url, body, headers);
+                if (_response.IsSuccessStatusCode)
+                {
+                    JObject jo = JObject.Parse(_response.Response);
+
+                    if (jo.ContainsKey("SerialNo"))
+                    {
+                        string _SerialNo = jo["SerialNo"].Value<string>();
+                        result.SerialNo = _SerialNo;
+                    }
+
+                    if (jo.ContainsKey("Message"))
+                    {
+                        string _Message = jo["Message"].Value<string>();
+                        result.Message = _Message;
+                    }
+
+                }
+                else
+                {
+                    JObject jo = JObject.Parse(_response.Response);                   
+
+                    if (jo.ContainsKey("Message"))
+                    {
+                        string _Message = jo["Message"].Value<string>();
+                        result.Message = _Message;
+                    }
+
+                    if (jo.ContainsKey("Code"))
+                    {
+                        int _ErrorCode = jo["Code"].Value<int>();
+                        result.ErrorCode = _ErrorCode;
+                    }
+                }               
+
+                result.Status = _response.StatusCode;
+                result.Success = _response.IsSuccessStatusCode;
+                result.Exception = _response.Exception;
+
+
+            }
+            catch (Exception ex)
+            {
+                result.Exception = ex;
+            }
+
+            return result;
+        }
+
+        async public Task<InternalHttpResult> Get(string url, Dictionary<string, string> headers, string saltkey)
+        {
+
+            InternalHttpResult result = new InternalHttpResult() { Success = false };
+
+            try
+            {
+                string body = PreAction(url, ref headers, null, saltkey);
+                var _response = await httpClient.GetJsonAsync(url, headers);
+                if (_response.IsSuccessStatusCode)
+                {
+                    JObject jo = JObject.Parse(_response.Response);
+
+                    if (jo.ContainsKey("SerialNo"))
+                    {
+                        string _SerialNo = jo["SerialNo"].Value<string>();
+                        result.SerialNo = _SerialNo;
+                    }
+
+                    if (jo.ContainsKey("Message"))
+                    {
+                        string _Message = jo["Message"].Value<string>();
+                        result.Message = _Message;
+                    }
+
+                }
+                else
+                {
+                    JObject jo = JObject.Parse(_response.Response);
+
+                    if (jo.ContainsKey("Message"))
+                    {
+                        string _Message = jo["Message"].Value<string>();
+                        result.Message = _Message;
+                    }
+
+                    if (jo.ContainsKey("Code"))
+                    {
+                        int _ErrorCode = jo["Code"].Value<int>();
+                        result.ErrorCode = _ErrorCode;
+                    }
+                }
+
+                result.Status = _response.StatusCode;
+                result.Success = _response.IsSuccessStatusCode;
+                result.Exception = _response.Exception;
+
+
+            }
+            catch (Exception ex)
+            {
+                result.Exception = ex;
+            }
+
+            return result;
+        }
+
+        async public Task<InternalHttpResult> Delete(string url, Dictionary<string, string> headers, string saltkey)
+        {
+            InternalHttpResult result = new InternalHttpResult() { Success = false };
+
+            try
+            {
+                string body = PreAction(url, ref headers, null, saltkey);
+                var _response = await httpClient.DeleteJsonAsync(url, headers);
+                if (_response.IsSuccessStatusCode)
+                {
+                    JObject jo = JObject.Parse(_response.Response);
+
+                    if (jo.ContainsKey("SerialNo"))
+                    {
+                        string _SerialNo = jo["SerialNo"].Value<string>();
+                        result.SerialNo = _SerialNo;
+                    }
+
+                    if (jo.ContainsKey("Message"))
+                    {
+                        string _Message = jo["Message"].Value<string>();
+                        result.Message = _Message;
+                    }
+
+                }
+                else
+                {
+                    JObject jo = JObject.Parse(_response.Response);
+
+                    if (jo.ContainsKey("Message"))
+                    {
+                        string _Message = jo["Message"].Value<string>();
+                        result.Message = _Message;
+                    }
+
+                    if (jo.ContainsKey("Code"))
+                    {
+                        int _ErrorCode = jo["Code"].Value<int>();
+                        result.ErrorCode = _ErrorCode;
+                    }
+                }
+
+                result.Status = _response.StatusCode;
+                result.Success = _response.IsSuccessStatusCode;
+                result.Exception = _response.Exception;
+
+
+            }
+            catch (Exception ex)
+            {
+                result.Exception = ex;
+            }
+
+            return result;
+        }
+
+        async public Task<InternalHttpResult> Put(string url, Dictionary<string, string> headers, object requestBody, string saltkey)
+        {
+            InternalHttpResult result = new InternalHttpResult() { Success = false };
+
+            try
+            {
+                string body = PreAction(url, ref headers, requestBody, saltkey);
+                var _response = await httpClient.PutJsonAsync(url, body, headers);
+                if (_response.IsSuccessStatusCode)
+                {
+                    JObject jo = JObject.Parse(_response.Response);
+
+                    if (jo.ContainsKey("SerialNo"))
+                    {
+                        string _SerialNo = jo["SerialNo"].Value<string>();
+                        result.SerialNo = _SerialNo;
+                    }
+
+                    if (jo.ContainsKey("Message"))
+                    {
+                        string _Message = jo["Message"].Value<string>();
+                        result.Message = _Message;
+                    }
+
+                }
+                else
+                {
+                    JObject jo = JObject.Parse(_response.Response);
+
+                    if (jo.ContainsKey("Message"))
+                    {
+                        string _Message = jo["Message"].Value<string>();
+                        result.Message = _Message;
+                    }
+
+                    if (jo.ContainsKey("Code"))
+                    {
+                        int _ErrorCode = jo["Code"].Value<int>();
+                        result.ErrorCode = _ErrorCode;
+                    }
+                }
+
+                result.Status = _response.StatusCode;
+                result.Success = _response.IsSuccessStatusCode;
+                result.Exception = _response.Exception;
+
+
+            }
+            catch (Exception ex)
+            {
+                result.Exception = ex;
+            }
+
+            return result;
+        }
+
+        private string PreAction(string url, ref Dictionary<string, string> headers, object requestBody, string saltkey)
+        {
+            var _body = requestBody == null ? "" : JsonConvert.SerializeObject(requestBody, EVCBConfiguration.JSONSERIALIZER_FORMAT);
+            headers.Add("Timestamp", DateTimeOffset.UtcNow.ToUnixTimeSeconds().ToString());
+            string signature = GetSignature(GetUnencodeText( url, _body, headers["Timestamp"], headers["PartnerId"], saltkey));
+            headers.Add("Signature", signature);
+
+            return _body;
+        }
+
+
+        private string GetUnencodeText( string url, string body, string timestamp, string partnerId, string saltkey)
+        {
+
+            string tempText = url.Substring(url.IndexOf('?') + 1).ToLower();
+            tempText = tempText.StartsWith("http") ? string.Empty : tempText;
+            body = tempText+ body;            
+            string unencodeText = string.Format("{0}{1}{2}{3}", body, timestamp, partnerId, saltkey).ToLower();
+
+            return unencodeText;
+        }
+
+        private string GetSignature(string unencodeText)
+        {
+            if ((unencodeText == null) || (unencodeText.Length == 0))
+            {
+                return String.Empty;
+            }
+            unencodeText = unencodeText.ToLower();
+
+            MD5 md5 = new MD5CryptoServiceProvider();
+            byte[] textToHash = Encoding.UTF8.GetBytes(unencodeText);
+            byte[] result = md5.ComputeHash(textToHash);
+            return BitConverter.ToString(result).Replace("-", "").ToLower();
+        }
+
+    }
+
+    public class InternalHttpResult : InternalGenericResponse
+    {
+        public int ErrorCode { set; get; }
+
+        public bool Success { set; get; }
+
+        public HttpStatusCode Status { set; get; }
+
+        public Exception Exception { set; get; }
+
+
+
+    }
+
+}

+ 44 - 8
EVCB_OCPP.WEBAPI/Services/ServerTriggerService.cs

@@ -24,6 +24,7 @@ namespace EVCB_OCPP.WEBAPI.Services
 
     public enum Internal_ExecutionCode
     {
+
         Accepted = 1,
         Blocked,
         Expired,
@@ -53,7 +54,10 @@ namespace EVCB_OCPP.WEBAPI.Services
         Unavailable,
         Unlocked,
         UnlockFailed,
-        VersionMismatch
+        VersionMismatch,
+        Rejected,
+        Failed,
+
 
 
     }
@@ -147,10 +151,10 @@ namespace EVCB_OCPP.WEBAPI.Services
         }
 
 
-        public ComandExcution GetExecution(string uuid, Internal_Actions action, string chargeBoxId)
+        public ComandExecution GetExecution(string uuid, Internal_Actions action, string chargeBoxId)
         {
             if (string.IsNullOrEmpty(chargeBoxId) || string.IsNullOrEmpty(uuid)) return null;
-            ComandExcution excution = new ComandExcution();
+            ComandExecution excution = new ComandExecution();
 
             try
             {
@@ -163,14 +167,46 @@ namespace EVCB_OCPP.WEBAPI.Services
 
                 using (SqlConnection conn = new SqlConnection(mainConnectionString))
                 {
-                    string strSql = "Select Top(1) Status,EVSE_Value,EVSE_Status from [dbo].[MachineOperateRecord] where ChargeBoxId=@ChargeBoxId and SerialNo=@SerialNo and Action=@Action; ";
+                    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();
                 }
 
-                int code = ConverttoCode(operation.EVSE_Value);
-                excution.IeRepliedbyEVSE = operation.Status == 1 ? true : false;
-                excution.Code = excution.IeRepliedbyEVSE == false ? 0 : (code == -1 ? 255 : code);
-                excution.Detail = code == -1 ? operation.EVSE_Value : string.Empty;
+                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 == 200)
+                    {
+                        excution.Code = 0;
+                        excution.IsWaited = true;
+
+                    }
+                    if (operation.Status == -1)
+                    {
+                        excution.IsTimeout = true;
+                        excution.Code = 0;
+                        excution.Detail = "Timeout";
+                    }
+
+
+                }
+
 
             }
             catch

+ 63 - 31
EVCB_OCPP.WEBAPI/Web.config

@@ -1,4 +1,4 @@
-<?xml version="1.0"?>
+<?xml version="1.0" encoding="utf-8"?>
 <!--
   如需如何設定 ASP.NET 應用程式的詳細資訊,請前往
   https://go.microsoft.com/fwlink/?LinkId=301879
@@ -8,68 +8,100 @@
     <!--<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="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"/>
+    <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" />
   </connectionStrings>
   <appSettings>
-    <add key="webpages:Version" value="3.0.0.0"/>
-    <add key="webpages:Enabled" value="false"/>
-    <add key="ClientValidationEnabled" value="true"/>
-    <add key="UnobtrusiveJavaScriptEnabled" value="true"/>
+    <add key="webpages:Version" value="3.0.0.0" />
+    <add key="webpages:Enabled" value="false" />
+    <add key="ClientValidationEnabled" value="true" />
+    <add key="UnobtrusiveJavaScriptEnabled" value="true" />
   </appSettings>
   <system.web>
-    <compilation debug="true" targetFramework="4.7.2"/>
-    <httpRuntime targetFramework="4.7.2"/>
-  <customErrors  mode="On"/>
+    <compilation debug="true" targetFramework="4.7.2" />
+    <httpRuntime targetFramework="4.7.2" />
+  <customErrors mode="On" />
   </system.web>
   <system.webServer>
     <!--<httpErrors errorMode="Custom" existingResponse="PassThrough">-->
  
 <!--</httpErrors>-->
     <handlers>
-      <remove name="ExtensionlessUrlHandler-Integrated-4.0"/>
-      <remove name="OPTIONSVerbHandler"/>
-      <remove name="TRACEVerbHandler"/>
-      <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0"/>
+      <remove name="ExtensionlessUrlHandler-Integrated-4.0" />
+      <remove name="OPTIONSVerbHandler" />
+      <remove name="TRACEVerbHandler" />
+      <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
     </handlers>
   </system.webServer>
   <runtime>
     <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
       <dependentAssembly>
-        <assemblyIdentity name="Antlr3.Runtime" publicKeyToken="eb42632606e9261f"/>
-        <bindingRedirect oldVersion="0.0.0.0-3.5.0.2" newVersion="3.5.0.2"/>
+        <assemblyIdentity name="Antlr3.Runtime" publicKeyToken="eb42632606e9261f" />
+        <bindingRedirect oldVersion="0.0.0.0-3.5.0.2" newVersion="3.5.0.2" />
       </dependentAssembly>
       <dependentAssembly>
-        <assemblyIdentity name="Newtonsoft.Json" culture="neutral" publicKeyToken="30ad4fe6b2a6aeed"/>
-        <bindingRedirect oldVersion="0.0.0.0-12.0.0.0" newVersion="12.0.0.0"/>
+        <assemblyIdentity name="Newtonsoft.Json" culture="neutral" publicKeyToken="30ad4fe6b2a6aeed" />
+        <bindingRedirect oldVersion="0.0.0.0-12.0.0.0" newVersion="12.0.0.0" />
       </dependentAssembly>
       <dependentAssembly>
-        <assemblyIdentity name="System.Web.Optimization" publicKeyToken="31bf3856ad364e35"/>
-        <bindingRedirect oldVersion="1.0.0.0-1.1.0.0" newVersion="1.1.0.0"/>
+        <assemblyIdentity name="System.Web.Optimization" publicKeyToken="31bf3856ad364e35" />
+        <bindingRedirect oldVersion="1.0.0.0-1.1.0.0" newVersion="1.1.0.0" />
       </dependentAssembly>
       <dependentAssembly>
-        <assemblyIdentity name="WebGrease" publicKeyToken="31bf3856ad364e35"/>
-        <bindingRedirect oldVersion="0.0.0.0-1.6.5135.21930" newVersion="1.6.5135.21930"/>
+        <assemblyIdentity name="WebGrease" publicKeyToken="31bf3856ad364e35" />
+        <bindingRedirect oldVersion="0.0.0.0-1.6.5135.21930" newVersion="1.6.5135.21930" />
       </dependentAssembly>
       <dependentAssembly>
-        <assemblyIdentity name="System.Web.Helpers" publicKeyToken="31bf3856ad364e35"/>
-        <bindingRedirect oldVersion="1.0.0.0-3.0.0.0" newVersion="3.0.0.0"/>
+        <assemblyIdentity name="System.Web.Helpers" publicKeyToken="31bf3856ad364e35" />
+        <bindingRedirect oldVersion="1.0.0.0-3.0.0.0" newVersion="3.0.0.0" />
       </dependentAssembly>
       <dependentAssembly>
-        <assemblyIdentity name="System.Web.WebPages" publicKeyToken="31bf3856ad364e35"/>
-        <bindingRedirect oldVersion="1.0.0.0-3.0.0.0" newVersion="3.0.0.0"/>
+        <assemblyIdentity name="System.Web.WebPages" publicKeyToken="31bf3856ad364e35" />
+        <bindingRedirect oldVersion="1.0.0.0-3.0.0.0" newVersion="3.0.0.0" />
       </dependentAssembly>
       <dependentAssembly>
-        <assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35"/>
-        <bindingRedirect oldVersion="1.0.0.0-5.2.4.0" newVersion="5.2.4.0"/>
+        <assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" />
+        <bindingRedirect oldVersion="1.0.0.0-5.2.4.0" newVersion="5.2.4.0" />
+      </dependentAssembly>
+      <dependentAssembly>
+        <assemblyIdentity name="System.Runtime.CompilerServices.Unsafe" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
+        <bindingRedirect oldVersion="0.0.0.0-4.0.6.0" newVersion="4.0.6.0" />
+      </dependentAssembly>
+      <dependentAssembly>
+        <assemblyIdentity name="Microsoft.Extensions.Primitives" publicKeyToken="adb9793829ddae60" culture="neutral" />
+        <bindingRedirect oldVersion="0.0.0.0-3.1.2.0" newVersion="3.1.2.0" />
+      </dependentAssembly>
+      <dependentAssembly>
+        <assemblyIdentity name="Microsoft.Extensions.Configuration.Abstractions" publicKeyToken="adb9793829ddae60" culture="neutral" />
+        <bindingRedirect oldVersion="0.0.0.0-3.1.2.0" newVersion="3.1.2.0" />
+      </dependentAssembly>
+      <dependentAssembly>
+        <assemblyIdentity name="Microsoft.Extensions.DependencyInjection.Abstractions" publicKeyToken="adb9793829ddae60" culture="neutral" />
+        <bindingRedirect oldVersion="0.0.0.0-3.1.2.0" newVersion="3.1.2.0" />
+      </dependentAssembly>
+      <dependentAssembly>
+        <assemblyIdentity name="Microsoft.Extensions.Options" publicKeyToken="adb9793829ddae60" culture="neutral" />
+        <bindingRedirect oldVersion="0.0.0.0-3.1.2.0" newVersion="3.1.2.0" />
+      </dependentAssembly>
+      <dependentAssembly>
+        <assemblyIdentity name="Microsoft.Extensions.Logging.Abstractions" publicKeyToken="adb9793829ddae60" culture="neutral" />
+        <bindingRedirect oldVersion="0.0.0.0-3.1.2.0" newVersion="3.1.2.0" />
+      </dependentAssembly>
+      <dependentAssembly>
+        <assemblyIdentity name="Microsoft.Extensions.DependencyInjection" publicKeyToken="adb9793829ddae60" culture="neutral" />
+        <bindingRedirect oldVersion="0.0.0.0-3.1.2.0" newVersion="3.1.2.0" />
+      </dependentAssembly>
+      <dependentAssembly>
+        <assemblyIdentity name="Microsoft.Extensions.Logging" publicKeyToken="adb9793829ddae60" culture="neutral" />
+        <bindingRedirect oldVersion="0.0.0.0-3.1.2.0" newVersion="3.1.2.0" />
       </dependentAssembly>
     </assemblyBinding>
   </runtime>
   <system.codedom>
     <compilers>
-      <compiler language="c#;cs;csharp" extension=".cs" type="Microsoft.CodeDom.Providers.DotNetCompilerPlatform.CSharpCodeProvider, Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" warningLevel="4" compilerOptions="/langversion:default /nowarn:1659;1699;1701"/>
-      <compiler language="vb;vbs;visualbasic;vbscript" extension=".vb" type="Microsoft.CodeDom.Providers.DotNetCompilerPlatform.VBCodeProvider, Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" warningLevel="4" compilerOptions="/langversion:default /nowarn:41008 /define:_MYTYPE=\&quot;Web\&quot; /optionInfer+"/>
+      <compiler language="c#;cs;csharp" extension=".cs" type="Microsoft.CodeDom.Providers.DotNetCompilerPlatform.CSharpCodeProvider, Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" warningLevel="4" compilerOptions="/langversion:default /nowarn:1659;1699;1701" />
+      <compiler language="vb;vbs;visualbasic;vbscript" extension=".vb" type="Microsoft.CodeDom.Providers.DotNetCompilerPlatform.VBCodeProvider, Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" warningLevel="4" compilerOptions="/langversion:default /nowarn:41008 /define:_MYTYPE=\&quot;Web\&quot; /optionInfer+" />
     </compilers>
   </system.codedom>
 </configuration>

+ 17 - 0
EVCB_OCPP.WEBAPI/packages.config

@@ -20,9 +20,26 @@
   <package id="Microsoft.AspNet.WebApi.WebHost.zh-Hant" version="5.2.4" targetFramework="net472" />
   <package id="Microsoft.AspNet.WebPages" version="3.2.4" targetFramework="net472" />
   <package id="Microsoft.AspNet.WebPages.zh-Hant" version="3.2.4" targetFramework="net472" />
+  <package id="Microsoft.Bcl.AsyncInterfaces" version="1.1.0" targetFramework="net472" />
   <package id="Microsoft.CodeDom.Providers.DotNetCompilerPlatform" version="2.0.0" targetFramework="net472" />
+  <package id="Microsoft.Extensions.Configuration" version="3.1.2" targetFramework="net472" />
+  <package id="Microsoft.Extensions.Configuration.Abstractions" version="3.1.2" targetFramework="net472" />
+  <package id="Microsoft.Extensions.Configuration.Binder" version="3.1.2" targetFramework="net472" />
+  <package id="Microsoft.Extensions.DependencyInjection" version="3.1.2" targetFramework="net472" />
+  <package id="Microsoft.Extensions.DependencyInjection.Abstractions" version="3.1.2" targetFramework="net472" />
+  <package id="Microsoft.Extensions.Http" version="3.1.2" targetFramework="net472" />
+  <package id="Microsoft.Extensions.Logging" version="3.1.2" targetFramework="net472" />
+  <package id="Microsoft.Extensions.Logging.Abstractions" version="3.1.2" targetFramework="net472" />
+  <package id="Microsoft.Extensions.Options" version="3.1.2" targetFramework="net472" />
+  <package id="Microsoft.Extensions.Primitives" version="3.1.2" targetFramework="net472" />
   <package id="Microsoft.Web.Infrastructure" version="1.0.0.0" targetFramework="net472" />
   <package id="Modernizr" version="2.8.3" targetFramework="net472" />
   <package id="Newtonsoft.Json" version="12.0.1" targetFramework="net472" />
+  <package id="System.Buffers" version="4.4.0" targetFramework="net472" />
+  <package id="System.ComponentModel.Annotations" version="4.7.0" targetFramework="net472" />
+  <package id="System.Memory" version="4.5.2" targetFramework="net472" />
+  <package id="System.Numerics.Vectors" version="4.4.0" targetFramework="net472" />
+  <package id="System.Runtime.CompilerServices.Unsafe" version="4.7.0" targetFramework="net472" />
+  <package id="System.Threading.Tasks.Extensions" version="4.5.2" targetFramework="net472" />
   <package id="WebGrease" version="1.6.0" targetFramework="net472" />
 </packages>