瀏覽代碼

2020/09/30 Jessica
Actions:
1.新增 OCPP2.0.1 Message
2.支援 OCPP1.6 SecurityProfile 0.1.2

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

+ 8 - 2
EVCB_OCPP.Server.sln

@@ -1,7 +1,7 @@
 
 Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio 15
-VisualStudioVersion = 15.0.28307.705
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.30413.136
 MinimumVisualStudioVersion = 10.0.40219.1
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EVCB_OCPP.WSServer", "EVCB_OCPP.WSServer\EVCB_OCPP.WSServer.csproj", "{DE0C1E9A-1EEE-42CC-8A91-73BF9056A7E7}"
 EndProject
@@ -15,6 +15,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SuperSocket.SocketEngine.Ne
 EndProject
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SuperWebSocket.NET45", "SuperWebSocket\SuperWebSocket.NET45.csproj", "{2DC79E40-BB70-4F6A-B378-905F2FBC6E97}"
 EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CertificateTool", "CertificateTool\CertificateTool.csproj", "{5C51604B-04A7-40BF-BE39-4DC9B8D142B9}"
+EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 		Debug|Any CPU = Debug|Any CPU
@@ -45,6 +47,10 @@ Global
 		{2DC79E40-BB70-4F6A-B378-905F2FBC6E97}.Debug|Any CPU.Build.0 = Debug|Any CPU
 		{2DC79E40-BB70-4F6A-B378-905F2FBC6E97}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{2DC79E40-BB70-4F6A-B378-905F2FBC6E97}.Release|Any CPU.Build.0 = Release|Any CPU
+		{5C51604B-04A7-40BF-BE39-4DC9B8D142B9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{5C51604B-04A7-40BF-BE39-4DC9B8D142B9}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{5C51604B-04A7-40BF-BE39-4DC9B8D142B9}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{5C51604B-04A7-40BF-BE39-4DC9B8D142B9}.Release|Any CPU.Build.0 = Release|Any CPU
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE

二進制
EVCB_OCPP.WSServer/DLL/EVCB_OCPP.Packet.dll


二進制
EVCB_OCPP.WSServer/DLL/EVCB_OCPP.Packet20.dll


+ 6 - 0
EVCB_OCPP.WSServer/EVCB_OCPP.WSServer.csproj

@@ -50,6 +50,9 @@
       <SpecificVersion>False</SpecificVersion>
       <HintPath>DLL\EVCB_OCPP.Packet.dll</HintPath>
     </Reference>
+    <Reference Include="EVCB_OCPP.Packet20">
+      <HintPath>DLL\EVCB_OCPP.Packet20.dll</HintPath>
+    </Reference>
     <Reference Include="log4net, Version=1.2.13.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a, processorArchitecture=MSIL">
       <HintPath>..\packages\log4net.2.0.3\lib\net40-full\log4net.dll</HintPath>
     </Reference>
@@ -128,6 +131,9 @@
   </ItemGroup>
   <ItemGroup>
     <Compile Include="Dto\ErrorDetails.cs" />
+    <Compile Include="Message\OCPP16MessageHandler.cs" />
+    <Compile Include="Message\OCPP20MessageHandler.cs" />
+    <Compile Include="Message\SecurityProfileHandler.cs" />
     <Compile Include="Service\BusinessServiceFactory.cs" />
     <Compile Include="Service\HttpClientService.cs" />
     <Compile Include="Service\LoadingBalanceService.cs" />

+ 35 - 266
EVCB_OCPP.WSServer/Message/BasicMessageHandler.cs

@@ -10,6 +10,7 @@ using System.Collections.Generic;
 using System.Linq;
 using System.Text;
 using System.Threading.Tasks;
+using Packet20 = EVCB_OCPP.Packet20;
 
 namespace EVCB_OCPP.WSServer.Message
 {
@@ -43,17 +44,9 @@ namespace EVCB_OCPP.WSServer.Message
         private const string DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ss'Z'";
         private const string DATE_FORMAT_WITH_MS = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'";
         #endregion
-
-        private List<Profile> profiles = new List<Profile>()
-        {
-             new CoreProfile(),
-             new FirmwareManagementProfile(),
-             new ReservationProfile(),
-             new RemoteTriggerProfile(),
-             new SmartChargingProfile(),
-             new LocalAuthListManagementProfile()
-
-        };
+        
+        private OCPP16MessageHandler _ocpp16Handler = new OCPP16MessageHandler();
+        private OCPP20MessageHandler _ocpp20Handler = new OCPP20MessageHandler();
 
         /// <summary>
         /// 將收到的封包做基本的拆解分成 Call 、CallResult、CallError
@@ -63,297 +56,73 @@ namespace EVCB_OCPP.WSServer.Message
         /// <returns></returns>
         internal MessageResult AnalysisReceiveData(ClientData client, string data)
         {
-            MessageResult result = new MessageResult();
-            try
+            MessageResult result = null;
+            if (client.IsOCPP16)
             {
-
-                var msg = Parse(data);
-                if (msg != null)
-                {
-
-                    result.UUID = msg.Id;
-                    switch (msg.TypeId)
-                    {
-                        case TYPENUMBER_CALL:
-                            {
-                                //只有CallMessage 才有在RawData有Action
-                                BasicMessageResult baseResult = UnPackPayloadbyCall(msg.Action, msg.Payload.ToString());
-                                Actions action = Actions.None;
-                                Enum.TryParse<Actions>(msg.Action, out action);
-                                result.Action = msg.Action;
-                                if (baseResult.Request != null)
-                                {
-                                    if (baseResult.Request.Validate())
-                                    {
-                                        result.Id = TYPENUMBER_CALL;
-                                        result.Message = baseResult.Request;
-
-                                    }
-                                    else
-                                    {
-                                      
-                                        string replyMsg = GenerateCallError(msg.Id, OCPPErrorCodes.OccurenceConstraintViolation.ToString(),
-                                             OCPPErrorDescription.OccurenceConstraintViolation);
-                                        result.Id = TYPENUMBER_CALL;
-                                        result.Message = baseResult.Request;
-                                        result.Success = false;
-                                        result.CallErrorMsg = replyMsg;
-                                        result.Exception = new Exception("Validation Failed");
-
-                                    }
-                                }
-                                else
-                                {
-                                  
-                                    string replyMsg = GenerateCallError(msg.Id, OCPPErrorCodes.OccurenceConstraintViolation, OCPPErrorDescription.OccurenceConstraintViolation);
-                                    result.Id = TYPENUMBER_CALL;
-                                    result.Message = baseResult.Request;
-                                    result.Success = false;
-                                    result.CallErrorMsg = replyMsg;
-                                    result.Exception = baseResult.Exception;
-                                }
-
-                            }
-                            break;
-                        case TYPENUMBER_CALLRESULT:
-                            {
-                                BasicMessageResult baseResult = UnPackPayloadbyCallResult(client.queue, msg.Id, msg.Payload.ToString());
-
-                                if (baseResult.Confirmation != null)
-                                {
-
-                                    if (baseResult.Confirmation.Validate())
-                                    {
-                                        result.Id = TYPENUMBER_CALLRESULT;
-                                        result.Message = baseResult.Confirmation;
-                                        result.Action = baseResult.Confirmation.GetRequest().Action;
-                                        //return data
-                                    }
-                                    else
-                                    {
-                                        string replyMsg = GenerateCallError(msg.Id, OCPPErrorCodes.OccurenceConstraintViolation.ToString(),
-                                      OCPPErrorDescription.OccurenceConstraintViolation);
-                                        result.Id = TYPENUMBER_CALLRESULT;
-                                        result.Message = baseResult.Confirmation;
-                                        result.Success = false;
-                                        result.CallErrorMsg = replyMsg;
-                                        result.Exception = new Exception("Validate Failed");
-                                    }
-                                }
-                                else
-                                {
-                                    string replyMsg = GenerateCallError(msg.Id, OCPPErrorCodes.OccurenceConstraintViolation.ToString(),
-                                   OCPPErrorDescription.OccurenceConstraintViolation);
-                                    result.Id = TYPENUMBER_CALLRESULT;
-                                    result.Message = baseResult.Confirmation;
-                                    result.Success = false;
-                                    result.CallErrorMsg = replyMsg;
-                                    result.Exception = baseResult.Exception;
-                                }
-
-                            }
-                            break;
-                        case TYPENUMBER_CALLERROR:
-                            {
-                                result.Id = TYPENUMBER_CALLERROR;
-                                var sentRequest = UnPackPayloadbyCallError(client.queue, msg.Id);
-
-                                if (sentRequest != null)
-                                {
-                                    IRequest request = sentRequest as IRequest;
-                                    result.Action = request.Action;
-
-                                    result.Message = sentRequest;
-                                    result.ReceivedErrorCode = string.Format("ErrorMsg {0}:{1}", ((CallErrorMessage)msg).ErrorCode, ((CallErrorMessage)msg).ErrorDescription);
-                                }
-
-
-                            }
-                            break;
-                        default:
-                            break;
-
-                    }
-
-                    // if (msg != null) Console.WriteLine(string.Format("Receieved Message : {0}", msg.ToString()));
-
-                }
+                result = _ocpp16Handler.AnalysisReceiveData(client, data);
             }
-            catch (Exception ex)
+            else
             {
-                if (string.IsNullOrEmpty(result.UUID))
-                {
-                    result.UUID = data.Substring(4, 39);
-                    result.UUID = result.UUID.Split(new string[] { "\"," }, StringSplitOptions.None)[0];
-                }
-                result.Success = false;
-                result.Exception = ex;
+                result = _ocpp20Handler.AnalysisReceiveData(client, data);
             }
+
             return result;
         }
 
-        #region 解析收到的訊息
-        /// <summary>
-        /// Parse data to OCPP Basic Message
-        /// </summary>
-        /// <param name="message"></param>
-        /// <returns></returns>
-        private BaseMessage Parse(string message)
-        {
-            try
-            {
-                if (message.StartsWith("[4,\""))
-                {
-                    message = message.Replace('{', '"');
-                    message = message.Replace('}', '"');
-                }
-                var array = JsonConvert.DeserializeObject<JArray>(message);
-                BaseMessage msg = null;
-                switch ((int)array[INDEX_MESSAGEID])
-                {
-                    case TYPENUMBER_CALL:
-                        {
-                            CallMessage call = new CallMessage();
-                            call.Action = array[INDEX_CALL_ACTION].ToString();
-                            call.Payload = array[INDEX_CALL_PAYLOAD].ToString().Replace("\r\n", "");
-                            msg = call;
-                        }
-                        break;
-                    case TYPENUMBER_CALLRESULT:
-                        {
-                            CallResultMessage callResult = new CallResultMessage();
-                            callResult.Payload = array[INDEX_CALLRESULT_PAYLOAD].ToString().Replace("\r\n", "");
-                            msg = callResult;
-                        }
-                        break;
-                    case TYPENUMBER_CALLERROR:
-                        {
-                            CallErrorMessage callError = new CallErrorMessage();
-                            callError.ErrorCode = array[INDEX_CALLERROR_ERRORCODE].ToString();
-                            callError.ErrorDescription = array[INDEX_CALLERROR_DESCRIPTION].ToString();
-                            callError.ErrorDetails = array[INDEX_CALLERROR_PAYLOAD].ToString().Replace("\r\n", "");
-                            msg = callError;
-                        }
-                        break;
-                    default:
-                        throw new Exception("Message Type notSupported");
-
-
-                }
-                msg.Id = array[INDEX_UNIQUEID].ToString();
-                return msg;
-            }
-            catch (Exception ex)
-            {
-                throw new Exception(string.Format("Parse Error=> {0} Problem: {0}", message, ex.Message));
-
-            }
 
+        static internal string GenerateCallError(string uniqueId, string errorCode, string errorDescription)
+        {
 
+            string msg = string.Format(CALLERROR_FORMAT, uniqueId, errorCode, errorDescription, "{}");
+            return msg;
 
         }
-
-
-        private BasicMessageResult UnPackPayloadbyCall(string action, string payload)
+        
+        static internal string GenerateConfirmation(string uniqueId,IConfirmation confirmation)
         {
-            BasicMessageResult result = new BasicMessageResult();
-            try
+            string msg = string.Empty;
+            if (confirmation != null && confirmation.Validate())
             {
-                Feature feature = null;
-                foreach (var profile in profiles)
-                {
-                    feature = profile.GetFeaturebyAction(action);
-                    if (feature == null)
-                    {
-                        continue;
-                    }
-                    else
-                    {
-                        break;
-                    }
-                }
-
-                result.Request = JsonConvert.DeserializeObject(payload, feature.GetRequestType()) as IRequest;
 
+                msg = string.Format(CALLRESULT_FORMAT, uniqueId, JsonConvert.SerializeObject(confirmation, new JsonSerializerSettings() { NullValueHandling = NullValueHandling.Ignore, Formatting = Formatting.None }));
             }
-            catch (Exception ex)
+            else
             {
-                result.Exception = ex;
-                logger.Error(string.Format("[{0}]UnPackPayloadbyCall Ex: {1}", action, ex.Message), "UnPack");
-
+                logger.Error(string.Format("confirmation is null  or InVaild in GenerateConfirmation Method"), "Warning");
             }
-
-            return result;
+            return msg;
         }
-
-        private BasicMessageResult UnPackPayloadbyCallResult(Queue requestQueue, string uniqueId, string payload)
+        static internal string GenerateConfirmationofOCPP20(string uniqueId, Packet20.Messages.IConfirmation confirmation)
         {
-            BasicMessageResult result = new BasicMessageResult();
-            try
+            string msg = string.Empty;
+            if (confirmation != null && confirmation.Validate())
             {
-                IRequest request = requestQueue.RestoreRequest(uniqueId);
-                Feature feature = null;
-                foreach (var profile in profiles)
-                {
-                    feature = profile.GetFeaturebyType(request.GetType());
-                    if (feature == null)
-                    {
-                        continue;
-                    }
-                    else
-                    {
-                        break;
-                    }
-                }
-
-                IConfirmation confrim = JsonConvert.DeserializeObject(payload, feature.GetConfirmationType()) as IConfirmation;
-                confrim.SetRequest(request);
-                result.Confirmation = confrim;
 
+                msg = string.Format(CALLRESULT_FORMAT, uniqueId, JsonConvert.SerializeObject(confirmation, new JsonSerializerSettings() { NullValueHandling = NullValueHandling.Ignore, Formatting = Formatting.None }));
             }
-            catch (Exception ex)
+            else
             {
-                result.Exception = ex;
-                logger.Error(string.Format("UnPackPayloadbyCallResult Data:[{0},{1}] Ex: {2}", uniqueId, payload, ex.ToString()), "UnPack");
-
+                logger.Error(string.Format("confirmation is null  or InVaild in GenerateConfirmation Method"), "Warning");
             }
-            return result;
-
-        }
-
-        private IRequest UnPackPayloadbyCallError(Queue requestQueue, string uniqueId)
-        {
-            IRequest sentMsg = requestQueue.RestoreRequest(uniqueId);
-
-            return sentMsg;
-
-        }
-        #endregion
-
-        internal string GenerateCallError(string uniqueId, string errorCode, string errorDescription)
-        {
-
-            string msg = string.Format(CALLERROR_FORMAT, uniqueId, errorCode, errorDescription, "{}");
             return msg;
-
         }
 
-        internal string GenerateConfirmation(string uniqueId, IConfirmation confirmation)
+        static internal string GenerateRequest(string uniqueId, string action,IRequest request)
         {
             string msg = string.Empty;
-            if (confirmation != null && confirmation.Validate())
+            if (request != null && request.Validate())
             {
 
-                msg = string.Format(CALLRESULT_FORMAT, uniqueId, JsonConvert.SerializeObject(confirmation, new JsonSerializerSettings() { NullValueHandling = NullValueHandling.Ignore, Formatting = Formatting.None }));
+                msg = string.Format(CALL_FORMAT, uniqueId, action, JsonConvert.SerializeObject(request, new JsonSerializerSettings() { NullValueHandling = NullValueHandling.Ignore, Formatting = Formatting.None }));
             }
             else
             {
-                logger.Error(string.Format("confirmation is null  or InVaild in GenerateConfirmation Method"), "Warning");
+                logger.Error(string.Format("confirmation is null  or InVaild in GenerateRequest Method"), "Warning");
             }
             return msg;
         }
 
-        internal string GenerateRequest(string uniqueId, string action, IRequest request)
+        static internal string GenerateRequestofOCPP20(string uniqueId, string action, Packet20.Messages.IRequest request)
         {
             string msg = string.Empty;
             if (request != null && request.Validate())
@@ -368,9 +137,9 @@ namespace EVCB_OCPP.WSServer.Message
             return msg;
         }
 
-        internal string GenerateDestroyRequest(string uniqueId, string action, string request)
+        static internal string GenerateDestroyRequest(string uniqueId, string action, string request)
         {
-           
+
 
             return string.Format(CALL_FORMAT, uniqueId, action, request);
         }

+ 18 - 1
EVCB_OCPP.WSServer/Message/CoreProfileHandler.cs

@@ -446,7 +446,7 @@ namespace EVCB_OCPP.WSServer.Message
                 watch.Stop();
                 if (watch.ElapsedMilliseconds / 1000 > 3)
                 {
-                    logger.Error("Processing Hearbeat costs " + watch.ElapsedMilliseconds/1000+" seconds");
+                    logger.Error("Processing Hearbeat costs " + watch.ElapsedMilliseconds / 1000 + " seconds");
                 }
             }
             return result;
@@ -656,9 +656,16 @@ namespace EVCB_OCPP.WSServer.Message
                             {
                                 foreach (var item in _confirm.configurationKey)
                                 {
+                                    string oldValue = string.Empty;
                                     var foundConfig = configure.Find(x => x.ConfigureName == item.key);
+
                                     if (foundConfig != null)
                                     {
+                                        if (foundConfig.ConfigureName == "SecurityProfile")
+                                        {
+                                            oldValue = foundConfig.ConfigureSetting;
+                                        }
+
                                         foundConfig.ReadOnly = item.IsReadOnly;
                                         foundConfig.ConfigureSetting = item.value;
                                     }
@@ -673,6 +680,15 @@ namespace EVCB_OCPP.WSServer.Message
                                             Exists = true
                                         });
                                     }
+
+                                    if (foundConfig.ConfigureName == "SecurityProfile")
+                                    {
+                                        if (oldValue != item.value)
+                                        {
+                                            session.ResetSecurityProfile = true;
+                                        }
+
+                                    }
                                 }
                             }
                             if (_confirm.unknownKey != null)
@@ -715,6 +731,7 @@ namespace EVCB_OCPP.WSServer.Message
                             db.SaveChanges();
 
                         }
+                       
                     }
                     break;
                 case Actions.UnlockConnector:

+ 334 - 0
EVCB_OCPP.WSServer/Message/OCPP16MessageHandler.cs

@@ -0,0 +1,334 @@
+using EVCB_OCPP.Packet.Features;
+using EVCB_OCPP.Packet.Messages;
+using EVCB_OCPP.Packet.Messages.Basic;
+using Newtonsoft.Json;
+using Newtonsoft.Json.Linq;
+using NLog;
+using OCPPServer.Protocol;
+using System;
+using System.Collections.Generic;
+
+namespace EVCB_OCPP.WSServer.Message
+{
+    /// <summary>
+    /// 實現 OCPP16 基本傳送規範,
+    /// 1.訊息 基本格式,將訊息包裝成 Call 、CallResult、CallError 三種格式
+    /// 2.OCPP 定義的傳送規則:交易相關的訊息必須依照時序性傳送,一個傳完才能接著送下一個(忽略規則 由Center System定義)
+    /// </summary>
+    internal class OCPP16MessageHandler
+    {
+        static protected ILogger logger = NLog.LogManager.GetCurrentClassLogger();
+
+        #region 傳送 or 解析訊息需要欄位
+        private const int INDEX_MESSAGEID = 0;
+        private const int INDEX_UNIQUEID = 1;
+        internal const int TYPENUMBER_CALL = 2;
+        private const int INDEX_CALL_ACTION = 2;
+        private const int INDEX_CALL_PAYLOAD = 3;
+
+        internal const int TYPENUMBER_CALLRESULT = 3;
+        private const int INDEX_CALLRESULT_PAYLOAD = 2;
+
+        internal const int TYPENUMBER_CALLERROR = 4;
+        private const int INDEX_CALLERROR_ERRORCODE = 2;
+        private const int INDEX_CALLERROR_DESCRIPTION = 3;
+        private const int INDEX_CALLERROR_PAYLOAD = 4;
+
+        private const string CALL_FORMAT = "[2,\"{0}\",\"{1}\",{2}]";
+        private const string CALLRESULT_FORMAT = "[3,\"{0}\",{1}]";
+        private const string CALLERROR_FORMAT = "[4,\"{0}\",\"{1}\",\"{2}\",{3}]";
+        private const string DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ss'Z'";
+        private const string DATE_FORMAT_WITH_MS = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'";
+        #endregion
+
+        private List<Profile> profiles = new List<Profile>()
+        {
+             new CoreProfile(),
+             new FirmwareManagementProfile(),
+             new ReservationProfile(),
+             new RemoteTriggerProfile(),
+             new SmartChargingProfile(),
+             new LocalAuthListManagementProfile(),
+             new SecurityProfile()
+        };
+
+
+        /// <summary>
+        /// 將收到的封包做基本的拆解分成 Call 、CallResult、CallError
+        /// </summary>
+        /// <param name="client"></param>
+        /// <param name="data"></param>
+        /// <returns></returns>
+        internal MessageResult AnalysisReceiveData(ClientData client, string data)
+        {
+            MessageResult result = new MessageResult();
+            try
+            {
+
+                var msg = Parse(data);
+                if (msg != null)
+                {
+
+                    result.UUID = msg.Id;
+                    switch (msg.TypeId)
+                    {
+                        case TYPENUMBER_CALL:
+                            {
+                                //只有CallMessage 才有在RawData有Action
+                                BasicMessageResult baseResult = UnPackPayloadbyCall(msg.Action, msg.Payload.ToString());
+                                Actions action = Actions.None;
+                                Enum.TryParse<Actions>(msg.Action, out action);
+                                result.Action = msg.Action;
+                                if (baseResult.Request != null)
+                                {
+                                    if (baseResult.Request.Validate())
+                                    {
+                                        result.Id = TYPENUMBER_CALL;
+                                        result.Message = baseResult.Request;
+
+                                    }
+                                    else
+                                    {
+
+                                        string replyMsg = BasicMessageHandler.GenerateCallError(msg.Id, OCPPErrorCodes.OccurenceConstraintViolation.ToString(),
+                                             OCPPErrorDescription.OccurenceConstraintViolation);
+                                        result.Id = TYPENUMBER_CALL;
+                                        result.Message = baseResult.Request;
+                                        result.Success = false;
+                                        result.CallErrorMsg = replyMsg;
+                                        result.Exception = new Exception("Validation Failed");
+
+                                    }
+                                }
+                                else
+                                {
+
+                                    string replyMsg = BasicMessageHandler.GenerateCallError(msg.Id, OCPPErrorCodes.OccurenceConstraintViolation, OCPPErrorDescription.OccurenceConstraintViolation);
+                                    result.Id = TYPENUMBER_CALL;
+                                    result.Message = baseResult.Request;
+                                    result.Success = false;
+                                    result.CallErrorMsg = replyMsg;
+                                    result.Exception = baseResult.Exception;
+                                }
+
+                            }
+                            break;
+                        case TYPENUMBER_CALLRESULT:
+                            {
+                                BasicMessageResult baseResult = UnPackPayloadbyCallResult(client.queue, msg.Id, msg.Payload.ToString());
+
+                                if (baseResult.Confirmation != null)
+                                {
+
+                                    if (baseResult.Confirmation.Validate())
+                                    {
+                                        result.Id = TYPENUMBER_CALLRESULT;
+                                        result.Message = baseResult.Confirmation;
+                                        result.Action = baseResult.Confirmation.GetRequest().Action;
+                                        //return data
+                                    }
+                                    else
+                                    {
+                                        string replyMsg = BasicMessageHandler.GenerateCallError(msg.Id, OCPPErrorCodes.OccurenceConstraintViolation.ToString(),
+                                      OCPPErrorDescription.OccurenceConstraintViolation);
+                                        result.Id = TYPENUMBER_CALLRESULT;
+                                        result.Message = baseResult.Confirmation;
+                                        result.Success = false;
+                                        result.CallErrorMsg = replyMsg;
+                                        result.Exception = new Exception("Validate Failed");
+                                    }
+                                }
+                                else
+                                {
+                                    string replyMsg = BasicMessageHandler.GenerateCallError(msg.Id, OCPPErrorCodes.OccurenceConstraintViolation.ToString(),
+                                   OCPPErrorDescription.OccurenceConstraintViolation);
+                                    result.Id = TYPENUMBER_CALLRESULT;
+                                    result.Message = baseResult.Confirmation;
+                                    result.Success = false;
+                                    result.CallErrorMsg = replyMsg;
+                                    result.Exception = baseResult.Exception;
+                                }
+
+                            }
+                            break;
+                        case TYPENUMBER_CALLERROR:
+                            {
+                                result.Id = TYPENUMBER_CALLERROR;
+                                var sentRequest = UnPackPayloadbyCallError(client.queue, msg.Id);
+
+                                if (sentRequest != null)
+                                {
+                                    IRequest request = sentRequest as IRequest;
+                                    result.Action = request.Action;
+
+                                    result.Message = sentRequest;
+                                    result.ReceivedErrorCode = string.Format("ErrorMsg {0}:{1}", ((CallErrorMessage)msg).ErrorCode, ((CallErrorMessage)msg).ErrorDescription);
+                                }
+
+
+                            }
+                            break;
+                        default:
+                            break;
+
+                    }
+
+                    // if (msg != null) Console.WriteLine(string.Format("Receieved Message : {0}", msg.ToString()));
+
+                }
+            }
+            catch (Exception ex)
+            {
+                if (string.IsNullOrEmpty(result.UUID))
+                {
+                    result.UUID = data.Substring(4, 39);
+                    result.UUID = result.UUID.Split(new string[] { "\"," }, StringSplitOptions.None)[0];
+                }
+                result.Success = false;
+                result.Exception = ex;
+            }
+            return result;
+        }
+
+        #region 解析收到的訊息
+        /// <summary>
+        /// Parse data to OCPP Basic Message
+        /// </summary>
+        /// <param name="message"></param>
+        /// <returns></returns>
+        private BaseMessage Parse(string message)
+        {
+            try
+            {
+                if (message.StartsWith("[4,\""))
+                {
+                    message = message.Replace('{', '"');
+                    message = message.Replace('}', '"');
+                }
+                var array = JsonConvert.DeserializeObject<JArray>(message);
+                BaseMessage msg = null;
+                switch ((int)array[INDEX_MESSAGEID])
+                {
+                    case TYPENUMBER_CALL:
+                        {
+                            CallMessage call = new CallMessage();
+                            call.Action = array[INDEX_CALL_ACTION].ToString();
+                            call.Payload = array[INDEX_CALL_PAYLOAD].ToString().Replace("\r\n", "");
+                            msg = call;
+                        }
+                        break;
+                    case TYPENUMBER_CALLRESULT:
+                        {
+                            CallResultMessage callResult = new CallResultMessage();
+                            callResult.Payload = array[INDEX_CALLRESULT_PAYLOAD].ToString().Replace("\r\n", "");
+                            msg = callResult;
+                        }
+                        break;
+                    case TYPENUMBER_CALLERROR:
+                        {
+                            CallErrorMessage callError = new CallErrorMessage();
+                            callError.ErrorCode = array[INDEX_CALLERROR_ERRORCODE].ToString();
+                            callError.ErrorDescription = array[INDEX_CALLERROR_DESCRIPTION].ToString();
+                            callError.ErrorDetails = array[INDEX_CALLERROR_PAYLOAD].ToString().Replace("\r\n", "");
+                            msg = callError;
+                        }
+                        break;
+                    default:
+                        throw new Exception("Message Type notSupported");
+
+
+                }
+                msg.Id = array[INDEX_UNIQUEID].ToString();
+                return msg;
+            }
+            catch (Exception ex)
+            {
+                throw new Exception(string.Format("Parse Error=> {0} Problem: {0}", message, ex.Message));
+
+            }
+
+
+
+        }
+
+
+        private BasicMessageResult UnPackPayloadbyCall(string action, string payload)
+        {
+            BasicMessageResult result = new BasicMessageResult();
+            try
+            {
+                Feature feature = null;
+                foreach (var profile in profiles)
+                {
+                    feature = profile.GetFeaturebyAction(action);
+                    if (feature == null)
+                    {
+                        continue;
+                    }
+                    else
+                    {
+                        break;
+                    }
+                }
+
+                result.Request = JsonConvert.DeserializeObject(payload, feature.GetRequestType()) as IRequest;
+
+            }
+            catch (Exception ex)
+            {
+                result.Exception = ex;
+                logger.Error(string.Format("[{0}]UnPackPayloadbyCall Ex: {1}", action, ex.Message), "UnPack");
+
+            }
+
+            return result;
+        }
+
+        private BasicMessageResult UnPackPayloadbyCallResult(Queue requestQueue, string uniqueId, string payload)
+        {
+            BasicMessageResult result = new BasicMessageResult();
+            try
+            {
+                IRequest request = requestQueue.RestoreRequest(uniqueId);
+                Feature feature = null;
+                foreach (var profile in profiles)
+                {
+                    feature = profile.GetFeaturebyType(request.GetType());
+                    if (feature == null)
+                    {
+                        continue;
+                    }
+                    else
+                    {
+                        break;
+                    }
+                }
+
+                IConfirmation confrim = JsonConvert.DeserializeObject(payload, feature.GetConfirmationType()) as IConfirmation;
+                confrim.SetRequest(request);
+                result.Confirmation = confrim;
+
+            }
+            catch (Exception ex)
+            {
+                result.Exception = ex;
+                logger.Error(string.Format("UnPackPayloadbyCallResult Data:[{0},{1}] Ex: {2}", uniqueId, payload, ex.ToString()), "UnPack");
+
+            }
+            return result;
+
+        }
+
+        private IRequest UnPackPayloadbyCallError(Queue requestQueue, string uniqueId)
+        {
+            IRequest sentMsg = requestQueue.RestoreRequest(uniqueId);
+
+            return sentMsg;
+
+        }
+        #endregion
+
+
+    }
+}
+

+ 332 - 0
EVCB_OCPP.WSServer/Message/OCPP20MessageHandler.cs

@@ -0,0 +1,332 @@
+using EVCB_OCPP.Packet.Messages;
+using EVCB_OCPP.Packet.Messages.Basic;
+using EVCB_OCPP.Packet20.Features;
+using Newtonsoft.Json;
+using Newtonsoft.Json.Linq;
+using NLog;
+using OCPPServer.Protocol;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+
+namespace EVCB_OCPP.WSServer.Message
+{
+    /// <summary>
+    /// 實現 OCPP20 基本傳送規範,
+    /// 1.訊息 基本格式,將訊息包裝成 Call 、CallResult、CallError 三種格式
+    /// 2.OCPP 定義的傳送規則:交易相關的訊息必須依照時序性傳送,一個傳完才能接著送下一個(忽略規則 由Center System定義)
+    /// </summary>
+    internal class OCPP20MessageHandler
+    {
+        static protected ILogger logger = NLog.LogManager.GetCurrentClassLogger();
+
+        #region 傳送 or 解析訊息需要欄位
+        private const int INDEX_MESSAGEID = 0;
+        private const int INDEX_UNIQUEID = 1;
+        internal const int TYPENUMBER_CALL = 2;
+        private const int INDEX_CALL_ACTION = 2;
+        private const int INDEX_CALL_PAYLOAD = 3;
+
+        internal const int TYPENUMBER_CALLRESULT = 3;
+        private const int INDEX_CALLRESULT_PAYLOAD = 2;
+
+        internal const int TYPENUMBER_CALLERROR = 4;
+        private const int INDEX_CALLERROR_ERRORCODE = 2;
+        private const int INDEX_CALLERROR_DESCRIPTION = 3;
+        private const int INDEX_CALLERROR_PAYLOAD = 4;
+
+        private const string CALL_FORMAT = "[2,\"{0}\",\"{1}\",{2}]";
+        private const string CALLRESULT_FORMAT = "[3,\"{0}\",{1}]";
+        private const string CALLERROR_FORMAT = "[4,\"{0}\",\"{1}\",\"{2}\",{3}]";
+        private const string DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ss'Z'";
+        private const string DATE_FORMAT_WITH_MS = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'";
+        #endregion
+
+        private List<Profile> profiles = new List<Profile>()
+        {
+             new CoreProfile(),            
+
+        };
+
+
+        /// <summary>
+        /// 將收到的封包做基本的拆解分成 Call 、CallResult、CallError
+        /// </summary>
+        /// <param name="client"></param>
+        /// <param name="data"></param>
+        /// <returns></returns>
+        internal MessageResult AnalysisReceiveData(ClientData client, string data)
+        {
+            MessageResult result = new MessageResult();
+            try
+            {
+
+                var msg = Parse(data);
+                if (msg != null)
+                {
+
+                    result.UUID = msg.Id;
+                    switch (msg.TypeId)
+                    {
+                        case TYPENUMBER_CALL:
+                            {
+                                //只有CallMessage 才有在RawData有Action
+                                BasicMessageResult baseResult = UnPackPayloadbyCall(msg.Action, msg.Payload.ToString());
+                                Actions action = Actions.None;
+                                Enum.TryParse<Actions>(msg.Action, out action);
+                                result.Action = msg.Action;
+                                if (baseResult.Request != null)
+                                {
+                                    if (baseResult.Request.Validate())
+                                    {
+                                        result.Id = TYPENUMBER_CALL;
+                                        result.Message = baseResult.Request;
+
+                                    }
+                                    else
+                                    {
+
+                                        string replyMsg = BasicMessageHandler.GenerateCallError(msg.Id, OCPPErrorCodes.OccurenceConstraintViolation.ToString(),
+                                             OCPPErrorDescription.OccurenceConstraintViolation);
+                                        result.Id = TYPENUMBER_CALL;
+                                        result.Message = baseResult.Request;
+                                        result.Success = false;
+                                        result.CallErrorMsg = replyMsg;
+                                        result.Exception = new Exception("Validation Failed");
+
+                                    }
+                                }
+                                else
+                                {
+
+                                    string replyMsg = BasicMessageHandler.GenerateCallError(msg.Id, OCPPErrorCodes.OccurenceConstraintViolation, OCPPErrorDescription.OccurenceConstraintViolation);
+                                    result.Id = TYPENUMBER_CALL;
+                                    result.Message = baseResult.Request;
+                                    result.Success = false;
+                                    result.CallErrorMsg = replyMsg;
+                                    result.Exception = baseResult.Exception;
+                                }
+
+                            }
+                            break;
+                        case TYPENUMBER_CALLRESULT:
+                            {
+                                BasicMessageResult baseResult = UnPackPayloadbyCallResult(client.queue, msg.Id, msg.Payload.ToString());
+
+                                if (baseResult.Confirmation != null)
+                                {
+
+                                    if (baseResult.Confirmation.Validate())
+                                    {
+                                        result.Id = TYPENUMBER_CALLRESULT;
+                                        result.Message = baseResult.Confirmation;
+                                        result.Action = baseResult.Confirmation.GetRequest().Action;
+                                        //return data
+                                    }
+                                    else
+                                    {
+                                        string replyMsg = BasicMessageHandler.GenerateCallError(msg.Id, OCPPErrorCodes.OccurenceConstraintViolation.ToString(),
+                                      OCPPErrorDescription.OccurenceConstraintViolation);
+                                        result.Id = TYPENUMBER_CALLRESULT;
+                                        result.Message = baseResult.Confirmation;
+                                        result.Success = false;
+                                        result.CallErrorMsg = replyMsg;
+                                        result.Exception = new Exception("Validate Failed");
+                                    }
+                                }
+                                else
+                                {
+                                    string replyMsg = BasicMessageHandler.GenerateCallError(msg.Id, OCPPErrorCodes.OccurenceConstraintViolation.ToString(),
+                                   OCPPErrorDescription.OccurenceConstraintViolation);
+                                    result.Id = TYPENUMBER_CALLRESULT;
+                                    result.Message = baseResult.Confirmation;
+                                    result.Success = false;
+                                    result.CallErrorMsg = replyMsg;
+                                    result.Exception = baseResult.Exception;
+                                }
+
+                            }
+                            break;
+                        case TYPENUMBER_CALLERROR:
+                            {
+                                result.Id = TYPENUMBER_CALLERROR;
+                                var sentRequest = UnPackPayloadbyCallError(client.queue, msg.Id);
+
+                                if (sentRequest != null)
+                                {
+                                    IRequest request = sentRequest as IRequest;
+                                    result.Action = request.Action;
+
+                                    result.Message = sentRequest;
+                                    result.ReceivedErrorCode = string.Format("ErrorMsg {0}:{1}", ((CallErrorMessage)msg).ErrorCode, ((CallErrorMessage)msg).ErrorDescription);
+                                }
+
+
+                            }
+                            break;
+                        default:
+                            break;
+
+                    }
+
+                    // if (msg != null) Console.WriteLine(string.Format("Receieved Message : {0}", msg.ToString()));
+
+                }
+            }
+            catch (Exception ex)
+            {
+                if (string.IsNullOrEmpty(result.UUID))
+                {
+                    result.UUID = data.Substring(4, 39);
+                    result.UUID = result.UUID.Split(new string[] { "\"," }, StringSplitOptions.None)[0];
+                }
+                result.Success = false;
+                result.Exception = ex;
+            }
+            return result;
+        }
+
+        #region 解析收到的訊息
+        /// <summary>
+        /// Parse data to OCPP Basic Message
+        /// </summary>
+        /// <param name="message"></param>
+        /// <returns></returns>
+        private BaseMessage Parse(string message)
+        {
+            try
+            {
+                if (message.StartsWith("[4,\""))
+                {
+                    message = message.Replace('{', '"');
+                    message = message.Replace('}', '"');
+                }
+                var array = JsonConvert.DeserializeObject<JArray>(message);
+                BaseMessage msg = null;
+                switch ((int)array[INDEX_MESSAGEID])
+                {
+                    case TYPENUMBER_CALL:
+                        {
+                            CallMessage call = new CallMessage();
+                            call.Action = array[INDEX_CALL_ACTION].ToString();
+                            call.Payload = array[INDEX_CALL_PAYLOAD].ToString().Replace("\r\n", "");
+                            msg = call;
+                        }
+                        break;
+                    case TYPENUMBER_CALLRESULT:
+                        {
+                            CallResultMessage callResult = new CallResultMessage();
+                            callResult.Payload = array[INDEX_CALLRESULT_PAYLOAD].ToString().Replace("\r\n", "");
+                            msg = callResult;
+                        }
+                        break;
+                    case TYPENUMBER_CALLERROR:
+                        {
+                            CallErrorMessage callError = new CallErrorMessage();
+                            callError.ErrorCode = array[INDEX_CALLERROR_ERRORCODE].ToString();
+                            callError.ErrorDescription = array[INDEX_CALLERROR_DESCRIPTION].ToString();
+                            callError.ErrorDetails = array[INDEX_CALLERROR_PAYLOAD].ToString().Replace("\r\n", "");
+                            msg = callError;
+                        }
+                        break;
+                    default:
+                        throw new Exception("Message Type notSupported");
+
+
+                }
+                msg.Id = array[INDEX_UNIQUEID].ToString();
+                return msg;
+            }
+            catch (Exception ex)
+            {
+                throw new Exception(string.Format("Parse Error=> {0} Problem: {0}", message, ex.Message));
+
+            }
+
+
+
+        }
+
+
+        private BasicMessageResult UnPackPayloadbyCall(string action, string payload)
+        {
+            BasicMessageResult result = new BasicMessageResult();
+            try
+            {
+                Feature feature = null;
+                foreach (var profile in profiles)
+                {
+                    feature = profile.GetFeaturebyAction(action);
+                    if (feature == null)
+                    {
+                        continue;
+                    }
+                    else
+                    {
+                        break;
+                    }
+                }
+
+                result.Request = JsonConvert.DeserializeObject(payload, feature.GetRequestType()) as IRequest;
+
+            }
+            catch (Exception ex)
+            {
+                result.Exception = ex;
+                logger.Error(string.Format("[{0}]UnPackPayloadbyCall Ex: {1}", action, ex.Message), "UnPack");
+
+            }
+
+            return result;
+        }
+
+        private BasicMessageResult UnPackPayloadbyCallResult(Queue requestQueue, string uniqueId, string payload)
+        {
+            BasicMessageResult result = new BasicMessageResult();
+            try
+            {
+                IRequest request = requestQueue.RestoreRequest(uniqueId);
+                Feature feature = null;
+                foreach (var profile in profiles)
+                {
+                    feature = profile.GetFeaturebyType(request.GetType());
+                    if (feature == null)
+                    {
+                        continue;
+                    }
+                    else
+                    {
+                        break;
+                    }
+                }
+
+                IConfirmation confrim = JsonConvert.DeserializeObject(payload, feature.GetConfirmationType()) as IConfirmation;
+                confrim.SetRequest(request);
+                result.Confirmation = confrim;
+
+            }
+            catch (Exception ex)
+            {
+                result.Exception = ex;
+                logger.Error(string.Format("UnPackPayloadbyCallResult Data:[{0},{1}] Ex: {2}", uniqueId, payload, ex.ToString()), "UnPack");
+
+            }
+            return result;
+
+        }
+
+        private IRequest UnPackPayloadbyCallError(Queue requestQueue, string uniqueId)
+        {
+            IRequest sentMsg = requestQueue.RestoreRequest(uniqueId);
+
+            return sentMsg;
+
+        }
+        #endregion
+
+
+    }
+}

+ 81 - 0
EVCB_OCPP.WSServer/Message/SecurityProfileHandler.cs

@@ -0,0 +1,81 @@
+using EVCB_OCPP.Domain;
+using EVCB_OCPP.Packet.Features;
+using EVCB_OCPP.Packet.Messages;
+using EVCB_OCPP.Packet.Messages.Security;
+using OCPPServer.Protocol;
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace EVCB_OCPP.WSServer.Message
+{
+    internal partial class ProfileHandler
+    {
+        internal MessageResult ExecuteSecurityRequest(Actions action, ClientData session, IRequest request)
+        {            
+            MessageResult result = new MessageResult() { Success = false };
+
+            try
+            {
+                switch (action)
+                {
+                 
+                                  
+                    default:
+                        {
+                            Console.WriteLine(string.Format("Not Implement {0} Logic(ExecuteCoreRequest)", request.GetType().ToString().Replace("OCPPPackage.Messages.Core.", "")));
+                        }
+                        break;
+                }
+            }
+            catch (Exception ex)
+            {
+                logger.Fatal(string.Format("chargeBoxId:{0} {1}", session.ChargeBoxId, action));
+                logger.Fatal(string.Format("Data {0}", request.ToString()));
+                logger.Fatal(string.Format("Error {0}", ex.ToString()));
+                result.Exception = ex;
+            }
+
+
+           
+            return result;
+        }
+        internal MessageResult ExecuteSecurityConfirm(Actions action, ClientData session, IConfirmation confirm, string requestId)
+        {
+            MessageResult result = new MessageResult() { Success = false };
+
+            switch (action)
+            {               
+               
+                default:
+                    {
+                        Console.WriteLine(string.Format("Not Implement {0} Logic", confirm.GetType().ToString().Replace("OCPPPackage.Messages.RemoteTrigger.", "")));
+                    }
+                    break;
+            }
+            return result;
+        }
+
+
+        internal MessageResult ReceivedSecurityError(Actions action, string errorMsg, ClientData session, string requestId)
+        {
+            MessageResult result = new MessageResult() { Success = true };
+
+            switch (action)
+            {
+                
+                default:
+                    {
+                        Console.WriteLine(string.Format("Not Implement {0} Logic", action));
+                    }
+                    break;
+            }
+            return result;
+
+        }
+    }
+}

+ 0 - 14
EVCB_OCPP.WSServer/Program.cs

@@ -16,21 +16,7 @@ namespace EVCB_OCPP.WSServer
     {
         static void Main(string[] args)
         {
-            //[2,"2185519c-18ef-4455-a968-4a219126bbd0","DataTransfer",{"vendorId":"Phihong Technology","messageId":"ID_FirmwareVersion","data":"{ "CsuBootLoadFwRev": "01.01", "CsuKernelFwRev": "4.9.59-ga75d8e9305\n", "CsuRootFsFwRev": "B0.30.60.1770.B0", "CsuPrimFwRev": "D0.53.60.1770.B0" }"}]
-            var ff = new { CsuBootLoadFwRev = "01.01", CsuKernelFwRev = "4.9.59-ga75d8e9305\n", CsuRootFsFwRev = "B0.30.60.1770.B0", CsuPrimFwRev = "D0.53.60.1770.B0" };
-            BasicMessageHandler msgAnalyser = new BasicMessageHandler();
-            DataTransferRequest req = new DataTransferRequest
-            {
-                vendorId = "Phihong Technology",
-                messageId = "ID_FirmwareVersion",
-                data = JsonConvert.SerializeObject(ff)
-            
-            };
-           var ttttttttttt = JsonConvert.SerializeObject(req);
 
-           // var ttttttttttttt =JsonConvert.SerializeObject(req);
-            var tttttttt= msgAnalyser.GenerateRequest(Guid.NewGuid().ToString(),Actions.DataTransfer.ToString(), req);
-            var array = JsonConvert.DeserializeObject<JArray>(tttttttt);
 
             ProtalServer s = new ProtalServer();
             Console.WriteLine("Starting Server...");

+ 150 - 89
EVCB_OCPP.WSServer/ProtalServer.cs

@@ -35,6 +35,7 @@ using EVCB_OCPP.Packet.Messages.SmartCharging;
 using System.Security.Authentication;
 using NLog.Fluent;
 using System.Diagnostics;
+using Packet20 = EVCB_OCPP.Packet20;
 
 namespace EVCB_OCPP.WSServer
 {
@@ -85,6 +86,7 @@ namespace EVCB_OCPP.WSServer
              "GetCompositeSchedule",
              "ReserveNow",
              "CancelReservation",
+             "ExtendedTriggerMessage"
         };
         private List<Profile> profiles = new List<Profile>()
         {
@@ -93,7 +95,8 @@ namespace EVCB_OCPP.WSServer
              new ReservationProfile(),
              new RemoteTriggerProfile(),
              new SmartChargingProfile(),
-             new LocalAuthListManagementProfile()
+             new LocalAuthListManagementProfile(),
+             new SecurityProfile(),
         };
         private CancellationTokenSource _cts = new CancellationTokenSource();
         private CancellationToken _ct;
@@ -274,8 +277,6 @@ namespace EVCB_OCPP.WSServer
         private void CheckEVSEConfigure(string chargeBoxId)
         {
             if (string.IsNullOrEmpty(chargeBoxId)) return;
-            int skipCount = 0;
-            int takeCount = 8;
             using (var db = new MainDBContext())
             {
                 db.ServerMessage.Add(new ServerMessage()
@@ -298,60 +299,11 @@ namespace EVCB_OCPP.WSServer
 
                 db.SaveChanges();
 
-                //string maxKeys = StandardConfiguration.AllConfigs.Skip(skipCount).Take(1).FirstOrDefault();
-                //if (maxKeys == StandardConfiguration.GetConfigurationMaxKeys)
-                //{
-                //    var _Configure = db.MachineConfiguration.Where(x => x.ChargeBoxId == chargeBoxId && x.ConfigureName == maxKeys).Select(x => new { ConfigureSetting = x.ConfigureSetting, ConfigureName = x.ConfigureName }).FirstOrDefault();
-                //    if (_Configure != null)
-                //    {
-                //        int cp_ConfiureCount = 0;
-                //        int.TryParse(_Configure.ConfigureSetting, out cp_ConfiureCount);
-                //        takeCount = takeCount > cp_ConfiureCount ? cp_ConfiureCount : takeCount;
-                //        skipCount = 1;
-                //        if (string.IsNullOrEmpty(_Configure.ConfigureSetting)) return;
-                //    }
-
-                //}
-
-                //while (StandardConfiguration.AllConfigs.Count > skipCount)
-                //{
-                //    string _key = StandardConfiguration.AllConfigs.Skip(skipCount).Take(1).FirstOrDefault();
-                //    var _Configure = db.MachineConfiguration.Where(x => x.ChargeBoxId == chargeBoxId && x.ConfigureName == _key).Select(x => new { ConfigureSetting = x.ConfigureSetting, ConfigureName = x.ConfigureName }).FirstOrDefault();
-                //    takeCount = StandardConfiguration.AllConfigs.Count - skipCount > takeCount ? takeCount : StandardConfiguration.AllConfigs.Count - skipCount;
-
-                //    var _keys = StandardConfiguration.AllConfigs.Skip(skipCount).Take(takeCount).ToList();
-                //    //   Console.WriteLine("===============Skip:" + skipCount);
-                //    if (_Configure == null)
-                //    {
-                //        // Console.WriteLine("_Configure == null===============Skip:" + skipCount);
-                //        db.ServerMessage.Add(new ServerMessage()
-                //        {
-                //            ChargeBoxId = chargeBoxId,
-                //            CreatedBy = "Server",
-                //            CreatedOn = DateTime.Now,
-                //            OutAction = Actions.GetConfiguration.ToString(),
-                //            OutRequest = JsonConvert.SerializeObject(
-                //            new GetConfigurationRequest()
-                //            {
-                //                key = _keys
-
-                //            },
-                //            new JsonSerializerSettings() { NullValueHandling = NullValueHandling.Ignore, Formatting = Formatting.None }),
-                //            SerialNo = Guid.NewGuid().ToString(),
-                //            InMessage = string.Empty
-
-                //        });
-
-                //        db.SaveChanges();
-                //    }
-
-                //    skipCount = skipCount + takeCount;
-
-                //}
-
             }
         }
 
+        
+
         private void OpenNetwork()
         {
 
@@ -363,6 +315,7 @@ namespace EVCB_OCPP.WSServer
             // llistener.Add(new ListenerConfig { Ip = "", Port = Convert.ToInt32(wssserverPort), Backlog = 100, Security = serverSecurity });
             llistener.Add(new ListenerConfig { Ip = System.Net.IPAddress.Any.ToString(), Port = Convert.ToInt32(GlobalConfig.GetWS_Port()), Backlog = 100, Security = "None" });
             llistener.Add(new ListenerConfig { Ip = System.Net.IPAddress.Any.ToString(), Port = Convert.ToInt32(GlobalConfig.GetWSS_Port()), Backlog = 100, Security = SslProtocols.Tls12.ToString() });
+
             // llistener.Add(new ListenerConfig { Ip = System.Net.IPAddress.Any.ToString(), Port = Convert.ToInt32(GlobalConfig.GetWSS_Port()), Backlog = 100, Security = SslProtocols.Tls11.ToString() });
             var config = ConfigurationManager.GetSection("superSocket") as IConfigurationSource;
             ICertificateConfig Certificate = config.Servers.ElementAt(0).Certificate;
@@ -378,9 +331,9 @@ namespace EVCB_OCPP.WSServer
                 //Security = serverSecurity,
                 Certificate = Certificate,
                 Listeners = listeners,
-              //  LogAllSocketException = true,
+                //  LogAllSocketException = true,
                 KeepAliveTime = 10,
-               // LogBasicSessionActivity = true
+                // LogBasicSessionActivity = true
 
 
             };
@@ -455,8 +408,8 @@ namespace EVCB_OCPP.WSServer
                         }
                     }
 
-                  
-                   // CheckEVSEConfigure(session.ChargeBoxId);
+
+                    // CheckEVSEConfigure(session.ChargeBoxId);
                 }
             }
             catch (Exception ex)
@@ -477,7 +430,12 @@ namespace EVCB_OCPP.WSServer
                 WriteMachineLog(session, rawdata,
                      string.Format("{0} {1}", string.IsNullOrEmpty(analysisResult.Action) ? "unknown" : analysisResult.Action, analysisResult.Id == 2 ? "Request" : (analysisResult.Id == 3 ? "Confirmation" : "Error")), analysisResult.Exception == null ? "" : analysisResult.Exception.Message);
 
-
+                if(session.ResetSecurityProfile)
+                {
+                    logger.Error(string.Format("[{0}] ChargeBoxId:{1} ResetSecurityProfile", DateTime.Now, session.ChargeBoxId));
+                    RemoveClient(session);                   
+                    return;
+                }
 
 
                 if (!analysisResult.Success)
@@ -491,7 +449,7 @@ namespace EVCB_OCPP.WSServer
                     {
                         if (analysisResult.Message == null)
                         {
-                            string replyMsg = msgAnalyser.GenerateCallError(analysisResult.UUID, OCPPErrorCodes.InternalError, OCPPErrorDescription.InternalError);
+                            string replyMsg = BasicMessageHandler.GenerateCallError(analysisResult.UUID, OCPPErrorCodes.InternalError, OCPPErrorDescription.InternalError);
                             string errorMsg = string.Empty;
                             if (analysisResult.Exception != null)
                             {
@@ -505,7 +463,7 @@ namespace EVCB_OCPP.WSServer
                             BaseMessage _baseMsg = analysisResult.Message as BaseMessage;
 
 
-                            string replyMsg = msgAnalyser.GenerateCallError(_baseMsg.Id, OCPPErrorCodes.InternalError, OCPPErrorDescription.InternalError);
+                            string replyMsg = BasicMessageHandler.GenerateCallError(_baseMsg.Id, OCPPErrorCodes.InternalError, OCPPErrorDescription.InternalError);
                             string errorMsg = string.Empty;
                             if (analysisResult.Exception != null)
                             {
@@ -521,11 +479,81 @@ namespace EVCB_OCPP.WSServer
                 {
 
                     Actions action = Convertor.GetAction(analysisResult.Action);
+
+                    if (!session.IsOCPP16 && !(action != Actions.BootNotification || action != Actions.Heartbeat))
+                    {
+                        Send(session, "Backend doesn't support this message.", string.Format("{0} {1}", analysisResult.Action, "Error"));
+                        return;
+                    }
                     switch (analysisResult.Id)
                     {
                         case BasicMessageHandler.TYPENUMBER_CALL:
                             {
-                                ProcessRequestMessage(analysisResult, session, action);
+                                if (session.IsOCPP16)
+                                {
+                                    ProcessRequestMessage(analysisResult, session, action);
+                                }
+                                else
+                                {
+                                    MessageResult result = new MessageResult() { Success = true };
+                                    //ocpp20 處理
+                                    switch (action)
+                                    {
+                                        case Actions.Heartbeat:
+                                            {
+                                                var confirm = new Packet20.Messages.HeartbeatResponse() { CurrentTime = DateTime.Now };
+                                                result.Message = confirm;
+                                                result.Success = true;
+
+                                                string response = BasicMessageHandler.GenerateConfirmationofOCPP20(analysisResult.UUID, (Packet20.Messages.IConfirmation)result.Message);
+                                                Send(session, response, string.Format("{0} {1}", analysisResult.Action, "Response"), result.Exception == null ? string.Empty : result.Exception.ToString());
+                                            }
+                                            break;
+                                        case Actions.BootNotification:
+                                            {
+                                                Packet20.Messages.BootNotificationRequest _request = (Packet20.Messages.IRequest)analysisResult.Message as Packet20.Messages.BootNotificationRequest;
+                                                int heartbeat_interval = GlobalConfig.GetHEARTBEAT_INTERVAL();
+                                                //using (var db = new MainDBContext())
+                                                //{
+                                                //    var _machine = db.Machine.Where(x => x.ChargeBoxId == session.ChargeBoxId).FirstOrDefault();
+                                                //    _machine.ChargeBoxSerialNumber = string.IsNullOrEmpty(_request.chargeBoxSerialNumber) ? string.Empty : _request.chargeBoxSerialNumber;
+                                                //    _machine.ChargePointModel = string.IsNullOrEmpty(_request.chargePointModel) ? string.Empty : _request.chargePointModel;
+                                                //    _machine.ChargePointVendor = string.IsNullOrEmpty(_request.chargePointVendor) ? string.Empty : _request.chargePointVendor;
+                                                //    _machine.FW_CurrentVersion = string.IsNullOrEmpty(_request.firmwareVersion) ? string.Empty : _request.firmwareVersion;
+                                                //    _machine.Iccid = string.IsNullOrEmpty(_request.iccid) ? string.Empty : _request.iccid;
+                                                //    _machine.Imsi = string.IsNullOrEmpty(_request.imsi) ? string.Empty : _request.imsi;
+                                                //    _machine.MeterSerialNumber = string.IsNullOrEmpty(_request.meterSerialNumber) ? string.Empty : _request.meterSerialNumber;
+                                                //    _machine.MeterType = string.IsNullOrEmpty(_request.meterType) ? string.Empty : _request.meterType;
+
+                                                //    db.SaveChanges();
+
+                                                //    var configVaule = db.MachineConfiguration.Where(x => x.ChargeBoxId == session.ChargeBoxId && x.ConfigureName == StandardConfiguration.HeartbeatInterval)
+                                                //        .Select(x => x.ConfigureSetting).FirstOrDefault();
+
+                                                //    if (configVaule != null)
+                                                //    {
+                                                //        int.TryParse(configVaule, out heartbeat_interval);
+                                                //    }
+                                                //}
+                                                var confirm = new Packet20.Messages.BootNotificationResponse() { CurrentTime = DateTime.Now, Interval = heartbeat_interval, Status = Packet20.DataTypes.EnumTypes.RegistrationStatusEnumType.Accepted };
+
+                                                result.Message = confirm;
+                                                result.Success = true;
+
+                                                string response = BasicMessageHandler.GenerateConfirmationofOCPP20(analysisResult.UUID, (Packet20.Messages.IConfirmation)result.Message);
+                                                Send(session, response, string.Format("{0} {1}", analysisResult.Action, "Response"), result.Exception == null ? string.Empty : result.Exception.ToString());
+
+                                            }
+                                            break;
+                                        default:
+                                            {
+                                                logger.Error(string.Format("We don't implement messagetype:{0} of raw data :{1} by {2}", analysisResult.Id, rawdata, session.ChargeBoxId));
+                                            }
+                                            break;
+                                    }
+
+                                }
+
 
                             }
                             break;
@@ -570,14 +598,14 @@ namespace EVCB_OCPP.WSServer
 
         }
 
-     
+
 
         async private void ProcessRequestMessage(MessageResult analysisResult, ClientData session, Actions action)
         {
             BasicMessageHandler msgAnalyser = new BasicMessageHandler();
             if (!session.IsCheckIn && action != Actions.BootNotification)
             {
-                string response = msgAnalyser.GenerateCallError(analysisResult.UUID, OCPPErrorCodes.GenericError, OCPPErrorDescription.NotChecked);
+                string response = BasicMessageHandler.GenerateCallError(analysisResult.UUID, OCPPErrorCodes.GenericError, OCPPErrorDescription.NotChecked);
                 Send(session, response, string.Format("{0} {1}", analysisResult.Action, "Error"));
             }
             else
@@ -589,11 +617,11 @@ namespace EVCB_OCPP.WSServer
                         {
 
 
-                            
+
                             var replyResult = await profileHandler.ExecuteCoreRequest(action, session, (IRequest)analysisResult.Message).ConfigureAwait(false);
                             if (replyResult.Success)
                             {
-                                string response = msgAnalyser.GenerateConfirmation(analysisResult.UUID, (IConfirmation)replyResult.Message);
+                                string response = BasicMessageHandler.GenerateConfirmation(analysisResult.UUID, (IConfirmation)replyResult.Message);
 
 
                                 Send(session, response, string.Format("{0} {1}", analysisResult.Action, "Confirmation"), replyResult.Exception == null ? string.Empty : replyResult.Exception.ToString());
@@ -613,15 +641,23 @@ namespace EVCB_OCPP.WSServer
                                             }
                                         }
 
-                                        CheckVersion(session.ChargeBoxId);
-                                        CheckEVSEConfigure(session.ChargeBoxId);
+                                        if (session.ResetSecurityProfile)
+                                        {
+                                            //
+                                        }
+                                        else
+                                        {
+                                            CheckVersion(session.ChargeBoxId);
+                                            CheckEVSEConfigure(session.ChargeBoxId);
+                                        }
+
                                     }
                                 }
 
                             }
                             else
                             {
-                                string response = msgAnalyser.GenerateCallError(analysisResult.UUID, OCPPErrorCodes.InternalError, OCPPErrorDescription.InternalError);
+                                string response = BasicMessageHandler.GenerateCallError(analysisResult.UUID, OCPPErrorCodes.InternalError, OCPPErrorDescription.InternalError);
                                 string errorMsg = replyResult.Exception != null ? replyResult.Exception.ToString() : string.Empty;
 
                                 Send(session, response, string.Format("{0} {1}", analysisResult.Action, "Error"), errorMsg);
@@ -704,13 +740,13 @@ namespace EVCB_OCPP.WSServer
                             var replyResult = profileHandler.ExecuteFirmwareManagementRequest(action, session, (IRequest)analysisResult.Message);
                             if (replyResult.Success)
                             {
-                                string response = msgAnalyser.GenerateConfirmation(analysisResult.UUID, (IConfirmation)replyResult.Message);
+                                string response = BasicMessageHandler.GenerateConfirmation(analysisResult.UUID, (IConfirmation)replyResult.Message);
                                 Send(session, response, string.Format("{0} {1}", analysisResult.Action, "Confirmation", replyResult.Exception == null ? string.Empty : replyResult.Exception.ToString()));
 
                             }
                             else
                             {
-                                string response = msgAnalyser.GenerateCallError(analysisResult.UUID, OCPPErrorCodes.InternalError, OCPPErrorDescription.InternalError);
+                                string response = BasicMessageHandler.GenerateCallError(analysisResult.UUID, OCPPErrorCodes.InternalError, OCPPErrorDescription.InternalError);
                                 string errorMsg = replyResult.Exception != null ? replyResult.Exception.ToString() : string.Empty;
 
                                 Send(session, response, string.Format("{0} {1}", analysisResult.Action, "Error"), errorMsg);
@@ -718,9 +754,27 @@ namespace EVCB_OCPP.WSServer
 
                         }
                         break;
+                    case "Security":
+                        {
+                            var replyResult = profileHandler.ExecuteSecurityRequest(action, session, (IRequest)analysisResult.Message);
+                            if (replyResult.Success)
+                            {
+                                string response = BasicMessageHandler.GenerateConfirmation(analysisResult.UUID, (IConfirmation)replyResult.Message);
+                                Send(session, response, string.Format("{0} {1}", analysisResult.Action, "Confirmation", replyResult.Exception == null ? string.Empty : replyResult.Exception.ToString()));
+
+                            }
+                            else
+                            {
+                                string response = BasicMessageHandler.GenerateCallError(analysisResult.UUID, OCPPErrorCodes.InternalError, OCPPErrorDescription.InternalError);
+                                string errorMsg = replyResult.Exception != null ? replyResult.Exception.ToString() : string.Empty;
+
+                                Send(session, response, string.Format("{0} {1}", analysisResult.Action, "Error"), errorMsg);
+                            }
+                        }
+                        break;
                     default:
                         {
-                            string replyMsg = msgAnalyser.GenerateCallError(analysisResult.UUID, OCPPErrorCodes.InternalError, OCPPErrorDescription.InternalError);
+                            string replyMsg = BasicMessageHandler.GenerateCallError(analysisResult.UUID, OCPPErrorCodes.InternalError, OCPPErrorDescription.InternalError);
                             string errorMsg = string.Format("Couldn't find action name: {0} of profile", action);
                             Send(session, replyMsg, string.Format("{0} {1}", analysisResult.Action, "Error"), errorMsg);
                         }
@@ -769,9 +823,14 @@ namespace EVCB_OCPP.WSServer
                             confirmResult = profileHandler.ExecuteSmartChargingConfirm(action, session, (IConfirmation)analysisResult.Message, analysisResult.RequestId);
                         }
                         break;
+                    case "Security":
+                        {
+                            confirmResult = profileHandler.ExecuteSecurityConfirm(action, session, (IConfirmation)analysisResult.Message, analysisResult.RequestId);
+                        }
+                        break;
                     default:
                         {
-                            string replyMsg = msgAnalyser.GenerateCallError(analysisResult.UUID, OCPPErrorCodes.InternalError, OCPPErrorDescription.InternalError);
+                            string replyMsg = BasicMessageHandler.GenerateCallError(analysisResult.UUID, OCPPErrorCodes.InternalError, OCPPErrorDescription.InternalError);
                             string errorMsg = string.Format("Couldn't find action name: {0} of profile", action);
                             Send(session, replyMsg, string.Format("{0} {1}", analysisResult.Action, "Error"), errorMsg);
                         }
@@ -787,7 +846,7 @@ namespace EVCB_OCPP.WSServer
             }
             else
             {
-                string replyMsg = msgAnalyser.GenerateCallError(analysisResult.UUID, OCPPErrorCodes.InternalError, OCPPErrorDescription.InternalError);
+                string replyMsg = BasicMessageHandler.GenerateCallError(analysisResult.UUID, OCPPErrorCodes.InternalError, OCPPErrorDescription.InternalError);
                 string errorMsg = string.Format("Action:{0} MessageId:{1}  didn't exist in confirm message", analysisResult.Action, analysisResult.UUID);
                 Send(session, replyMsg, string.Format("{0} {1}", analysisResult.Action, "Error"), errorMsg);
             }
@@ -833,7 +892,7 @@ namespace EVCB_OCPP.WSServer
                         break;
                     default:
                         {
-                            string replyMsg = msgAnalyser.GenerateCallError(analysisResult.UUID, OCPPErrorCodes.InternalError, OCPPErrorDescription.InternalError);
+                            string replyMsg = BasicMessageHandler.GenerateCallError(analysisResult.UUID, OCPPErrorCodes.InternalError, OCPPErrorDescription.InternalError);
                             string errorMsg = string.Format("Couldn't find action name: {0} of profile", action);
                             Send(session, replyMsg, string.Format("{0} {1}", analysisResult.Action, "Error"), errorMsg);
                         }
@@ -843,7 +902,7 @@ namespace EVCB_OCPP.WSServer
             }
             else
             {
-                string replyMsg = msgAnalyser.GenerateCallError(analysisResult.UUID, OCPPErrorCodes.InternalError, OCPPErrorDescription.InternalError);
+                string replyMsg = BasicMessageHandler.GenerateCallError(analysisResult.UUID, OCPPErrorCodes.InternalError, OCPPErrorDescription.InternalError);
                 string errorMsg = string.Format("Action:{0} MessageId:{1}  didn't exist in confirm message", analysisResult.Action, analysisResult.UUID);
                 Send(session, replyMsg, string.Format("{0} {1}", analysisResult.Action, "Error"), errorMsg);
 
@@ -915,7 +974,7 @@ namespace EVCB_OCPP.WSServer
                                     string requestId = Guid.NewGuid().ToString();
                                     // using (var db = new MainDBContext())
 
-                                    if (session.IsCheckIn)
+                                    if (session.IsCheckIn && session.IsOCPP16)
                                     {
 
                                         var _request = new TriggerMessageRequest()
@@ -924,7 +983,7 @@ namespace EVCB_OCPP.WSServer
                                         };
 
                                         var uuid = session.queue.store(_request);
-                                        string rawRequest = msgAnalyser.GenerateRequest(uuid, _request.Action, _request);
+                                        string rawRequest = BasicMessageHandler.GenerateRequest(uuid, _request.Action, _request);
                                         Send(session, rawRequest, string.Format("{0} {1}", _request.Action, "Request"), "");
 
                                         #region OCTT   ,測試韌體更新方式
@@ -1019,13 +1078,15 @@ namespace EVCB_OCPP.WSServer
                     {
                         DateTime startDt = DateTime.Now.AddSeconds(-30);
                         DateTime dt = new DateTime(1991, 1, 1);
-                        //Console.WriteLine(string.Format("{0} IN", DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss")));
-                        var commandList = db.ServerMessage.Where(c => c.ReceivedOn == dt && c.UpdatedOn == dt && c.CreatedOn >= startDt && c.CreatedOn <= DateTime.Now).AsNoTracking().ToList();
+                        DateTime currentTime = DateTime.Now;
+                        var commandList = db.ServerMessage.Where(c => c.ReceivedOn == dt && c.UpdatedOn == dt && c.CreatedOn >= startDt && c.CreatedOn <= currentTime).AsNoTracking().ToList();
+
+
                         //處理主機傳送的有指令
                         var cmdMachineList = commandList.Select(c => c.ChargeBoxId).Distinct().ToList();
                         if (commandList.Count > 0)
                         {
-                           // Console.WriteLine(string.Format("Now:{0} commandList Count:{1} ", DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss"), commandList.Count));
+                            // Console.WriteLine(string.Format("Now:{0} commandList Count:{1} ", DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss"), commandList.Count));
                         }
 
                         foreach (var charger_SN in cmdMachineList)
@@ -1036,7 +1097,7 @@ namespace EVCB_OCPP.WSServer
                             {
                                 Console.WriteLine(string.Format("charger_SN:{0} startDt:{1} CreatedOn:{2}", charger_SN, startDt.ToString("yyyy/MM/dd HH:mm:ss"), DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss")));
 
-                                if (session.IsCheckIn)
+                                if (session.IsCheckIn && session.IsOCPP16)
                                 {
                                     var cmdList = commandList.Where(c => c.ChargeBoxId == charger_SN).ToList();
 
@@ -1058,22 +1119,22 @@ namespace EVCB_OCPP.WSServer
                                             }
                                         }
 
-                                        if (_RequestType != null && item.CreatedBy!= "Destroyer")
+                                        if (_RequestType != null && item.CreatedBy != "Destroyer")
                                         {
                                             request = JsonConvert.DeserializeObject(item.OutRequest, _RequestType) as IRequest;
                                             uuid = session.queue.store(request);
-                                            string rawRequest = msgAnalyser.GenerateRequest(uuid, item.OutAction, request);
+                                            string rawRequest = BasicMessageHandler.GenerateRequest(uuid, item.OutAction, request);
                                             Send(session, rawRequest, string.Format("{0} {1}", action, "Request"), "");
                                         }
 
-                                      
+
                                         if (_RequestType != null && item.CreatedBy == "Destroyer")
                                         {
                                             Console.WriteLine("********************************");
                                             request = Activator.CreateInstance(_RequestType) as IRequest;
                                             Console.WriteLine("++++++++++++++++++++++++++++++++++++++++");
                                             uuid = session.queue.store(request);
-                                            string rawRequest = msgAnalyser.GenerateDestroyRequest(uuid, item.OutAction, item.OutRequest);
+                                            string rawRequest = BasicMessageHandler.GenerateDestroyRequest(uuid, item.OutAction, item.OutRequest);
                                             Send(session, rawRequest, string.Format("{0} {1}", action, "Request"), "");
                                         }
 
@@ -1098,7 +1159,7 @@ namespace EVCB_OCPP.WSServer
                                 }
                             }
                         }
-                       
+
                     }
 
                     await Task.Delay(1000);
@@ -1135,7 +1196,7 @@ namespace EVCB_OCPP.WSServer
 
                         var cdt = DateTime.Now;
                         var clients = _copyClientDic.Where(x => x.Value.LastActiveTime > cdt.AddSeconds(-30)).Select(x => x.Value).ToList();
-                      
+
                         watch.Start();
                         foreach (var session in clients)
                         {
@@ -1278,7 +1339,7 @@ namespace EVCB_OCPP.WSServer
                         sc.InMessage = JsonConvert.SerializeObject(analysisResult.Message, Formatting.None);
                         sc.ReceivedOn = DateTime.Now;
                         db.SaveChanges();
-                      //  Console.WriteLine(string.Format("Now:{0} ServerMessage Id:{1} ", DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss"), foundRequest.Id));
+                        //  Console.WriteLine(string.Format("Now:{0} ServerMessage Id:{1} ", DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss"), foundRequest.Id));
 
                     }
                     confirmed = true;

+ 6 - 2
EVCB_OCPP.WSServer/SuperSocket.Protocol/ClientData.cs

@@ -21,6 +21,10 @@ namespace OCPPServer.Protocol
 
         public string MachineId { set; get; }
 
+        public bool IsOCPP16 { set; get; }
+
+        public bool ResetSecurityProfile { set; get; }
+
         public string CustomerName { get; set; }
 
         public delegate void OCPPClientDataEventHandler<ClientData, String>(ClientData clientdata, String msg);
@@ -35,7 +39,7 @@ namespace OCPPServer.Protocol
 
         }
 
-         
+
 
         /// <summary>
         /// Sends the raw binary data to client.
@@ -62,6 +66,6 @@ namespace OCPPServer.Protocol
         protected override void OnSessionClosed(CloseReason reason)
         {
         }
-       
+
     }
 }

+ 85 - 2
EVCB_OCPP.WSServer/SuperSocket.Protocol/OCPPWSServer.cs

@@ -1,5 +1,6 @@
 
 using EVCB_OCPP.Domain;
+using OCPPPackage.Profiles;
 using SuperSocket.Common;
 using SuperWebSocket;
 using SuperWebSocket.SubProtocol;
@@ -61,7 +62,11 @@ namespace OCPPServer.Protocol
 
         protected override bool ValidateHandshake(ClientData session, string origin)
         {
-            if(string.IsNullOrEmpty(session.Path))
+            session.IsOCPP16 = session.SecWebSocketProtocol.ToLower().Contains("ocpp2.0") ? false : true;
+
+            int securityProfile = 0;
+            string authorizationKey = string.Empty;
+            if (string.IsNullOrEmpty(session.Path))
             {
                 Console.WriteLine("===========================================");
                 Console.WriteLine("session.Path EMPTY");
@@ -72,13 +77,90 @@ namespace OCPPServer.Protocol
             session.ChargeBoxId = words.Last();
             Console.WriteLine(string.Format("{0} :ValidateHandshake: {1}", DateTime.Now.ToString("yy/MM/dd HH:mm:ss.fff"), session.Path));
             bool isExistedSN = false;
+            bool authorizated = false;
             using (var db = new MainDBContext())
             {
-                var machine = db.Machine.Where(x => x.ChargeBoxId == session.ChargeBoxId && x.IsDelete == false).FirstOrDefault();
+                var machine = db.Machine.Where(x => x.ChargeBoxId == session.ChargeBoxId && x.IsDelete == false).Select(x => new { x.CustomerId, x.Id }).FirstOrDefault();
                 session.CustomerId = machine == null ? Guid.Empty : machine.CustomerId;
                 session.MachineId = machine == null ? String.Empty : machine.Id;
                 isExistedSN = machine == null ? false : true;
+
+                if (session.IsOCPP16)
+                {
+                    var configVaule = db.MachineConfiguration.Where(x => x.ChargeBoxId == session.ChargeBoxId && x.ConfigureName == StandardConfiguration.SecurityProfile)
+                                   .Select(x => x.ConfigureSetting).FirstOrDefault();
+                    int.TryParse(configVaule, out securityProfile);
+
+                    if (securityProfile == 1 || securityProfile == 2)
+                    {
+                        authorizationKey = db.MachineConfiguration.Where(x => x.ChargeBoxId == session.ChargeBoxId && x.ConfigureName == StandardConfiguration.AuthorizationKey)
+                                  .Select(x => x.ConfigureSetting).FirstOrDefault();
+
+                    }
+                }
+            }
+            if (securityProfile == 3 && session.UriScheme == "ws")
+            {
+                StringBuilder responseBuilder = new StringBuilder();
+
+                responseBuilder.AppendFormatWithCrCf(@"HTTP/{0} {1} {2}", "1.1",
+                (int)HttpStatusCode.Unauthorized, @"Unauthorized");
+
+                responseBuilder.AppendWithCrCf();
+                string sb = responseBuilder.ToString();
+                byte[] data = Encoding.UTF8.GetBytes(sb);
+
+                ((IWebSocketSession)session).SendRawData(data, 0, data.Length);
+
+                return false;
             }
+
+            if ((securityProfile == 1 || securityProfile == 2))
+            {
+                if (securityProfile == 2 && session.UriScheme == "ws")
+                {
+                    authorizated = false;
+                }
+
+                if (session.Items.ContainsKey("Authorization"))
+                {
+
+
+                    string base64Encoded = session.Items["Authorization"].ToString().Replace("Basic ", "");
+                    byte[] data = Convert.FromBase64String(base64Encoded);
+                    string[] base64Decoded = System.Text.ASCIIEncoding.ASCII.GetString(data).Split(':');
+                    if (base64Decoded.Count() == 2 && base64Decoded[0] == session.ChargeBoxId && base64Decoded[1] == authorizationKey)
+                    {
+                        authorizated = true;
+                    }
+
+                }
+                else
+                {
+                    authorizated = true;
+                  
+                }
+
+
+
+                if (!authorizated)
+                {
+                    StringBuilder responseBuilder = new StringBuilder();
+
+                    responseBuilder.AppendFormatWithCrCf(@"HTTP/{0} {1} {2}", "1.1",
+                    (int)HttpStatusCode.Unauthorized, @"Unauthorized");
+
+                    responseBuilder.AppendWithCrCf();
+                    string sb = responseBuilder.ToString();
+                    byte[] data = Encoding.UTF8.GetBytes(sb);
+
+                    ((IWebSocketSession)session).SendRawData(data, 0, data.Length);
+
+                    return false;
+                }
+            }
+
+
             if (!isExistedSN)
             {
                 StringBuilder responseBuilder = new StringBuilder();
@@ -96,6 +178,7 @@ namespace OCPPServer.Protocol
             }
 
 
+
             return true;
         }
     }

+ 1 - 0
SuperWebSocket/Protocol/WebSocketHeaderReceiveFilter.cs

@@ -24,6 +24,7 @@ namespace SuperWebSocket.Protocol
 
         public override IWebSocketFragment Filter(byte[] readBuffer, int offset, int length, bool isReusableBuffer, out int rest)
         {
+            Console.WriteLine("Inside.............");
             rest = 0;
 
             int prevMatched = m_SearchState.Matched;