Sfoglia il codice sorgente

2020/10/26
Actions:
1.資料庫異動 : 56c8ec4
2.加入支援OCPP20的選項
3.測試工具更新 原因:相依資料庫Domain

Jessica Tseng 4 anni fa
parent
commit
84ee19b2e4
37 ha cambiato i file con 9 aggiunte e 11648 eliminazioni
  1. 0 6
      EVCB_OCPP.Server.sln
  2. BIN
      EVCB_OCPP.WSServer/DLL/EVCB_OCPP.Domain.dll
  3. 3 10
      EVCB_OCPP.WSServer/ProtalServer.cs
  4. 0 86
      OCPPServer/App.config
  5. 0 114
      OCPPServer/ClientData.cs
  6. 0 23
      OCPPServer/Command/ProcessCallCmd.cs
  7. 0 23
      OCPPServer/Command/ProcessCallErrorCmd.cs
  8. 0 23
      OCPPServer/Command/ProcessCallResultCmd.cs
  9. 0 78
      OCPPServer/Common/ListenerConfig.cs
  10. 0 22
      OCPPServer/Common/LocalAuthorization.cs
  11. 0 61
      OCPPServer/Common/OCPPResult.cs
  12. 0 69
      OCPPServer/Config/log4net.config
  13. 0 69
      OCPPServer/Config/log4net.unix.config
  14. 0 109
      OCPPServer/Handler/FeatureHandler.cs
  15. 0 256
      OCPPServer/Handler/MakeConfirmationHandler.cs
  16. 0 612
      OCPPServer/Handler/MakeRequestHandler.cs
  17. 0 2556
      OCPPServer/Handler/OCPPMessageHandler.cs
  18. 0 60
      OCPPServer/NLog.config
  19. 0 3027
      OCPPServer/NLog.xsd
  20. 0 40
      OCPPServer/NeedConfirmPacket.cs
  21. 0 222
      OCPPServer/OCPPServer.csproj
  22. 0 127
      OCPPServer/OCPPWebSocketHeaderReceiveFilter.cs
  23. 0 35
      OCPPServer/OCPPWebSocketProtocol.cs
  24. 0 38
      OCPPServer/Properties/AssemblyInfo.cs
  25. 0 240
      OCPPServer/Protocol/ClientData.cs
  26. 0 149
      OCPPServer/Protocol/OCPPWSServer.cs
  27. 0 28
      OCPPServer/Server.cs
  28. 0 770
      OCPPServer/Service/WebSocketCommandService.cs
  29. 0 445
      OCPPServer/SubProtocol/OCPPLog.cs
  30. 0 108
      OCPPServer/SubProtocol/OCPPLogFactory.cs
  31. 0 35
      OCPPServer/SubProtocol/OCPPSubCommandParser.cs
  32. 0 319
      OCPPServer/SubProtocol/OCPPSubProtocol.cs
  33. 0 1862
      OCPPServer/WSServer.cs
  34. 0 20
      OCPPServer/packages.config
  35. BIN
      TestTool.RemoteTriggerAPP/DLL/EVCB_OCPP.Domain.dll
  36. 1 1
      TestTool.RemoteTriggerAPP/MainWindow.xaml
  37. 5 5
      TestTool.RemoteTriggerAPP/MainWindow.xaml.cs

+ 0 - 6
EVCB_OCPP.Server.sln

@@ -15,8 +15,6 @@ 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
@@ -47,10 +45,6 @@ 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

BIN
EVCB_OCPP.WSServer/DLL/EVCB_OCPP.Domain.dll


+ 3 - 10
EVCB_OCPP.WSServer/ProtalServer.cs

@@ -308,7 +308,7 @@ namespace EVCB_OCPP.WSServer
         {
 
             //載入OCPP Protocol
-            var appServer = new OCPPWSServer(new List<OCPPSubProtocol>() { new OCPPSubProtocol(), new OCPPSubProtocol(" ocpp1.6") });
+            var appServer = new OCPPWSServer(new List<OCPPSubProtocol>() { new OCPPSubProtocol(), new OCPPSubProtocol(" ocpp1.6"), new OCPPSubProtocol("ocpp2.0"), new OCPPSubProtocol(" ocpp2.0") });
 
             List<IListenerConfig> llistener = new List<IListenerConfig>();
             //System.Net.IPAddress.Any.ToString()
@@ -641,15 +641,8 @@ namespace EVCB_OCPP.WSServer
                                             }
                                         }
 
-                                        if (session.ResetSecurityProfile)
-                                        {
-                                            //
-                                        }
-                                        else
-                                        {
-                                            CheckVersion(session.ChargeBoxId);
-                                            CheckEVSEConfigure(session.ChargeBoxId);
-                                        }
+                                        CheckVersion(session.ChargeBoxId);
+                                        CheckEVSEConfigure(session.ChargeBoxId);
 
                                     }
                                 }

+ 0 - 86
OCPPServer/App.config

@@ -1,86 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<configuration>
-  <configSections>
-
-    <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
-    <section name="superSocket" type="SuperSocket.SocketEngine.Configuration.SocketServiceConfig, SuperSocket.SocketEngine" />
-    <!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
-  </configSections>
-  <connectionStrings>
-    <add name="DefaultConnection" connectionString="data source=172.1.0.142\SQLEXPRESS;initial catalog=Evcb_formal;persist security info=True;user id=sa;password=Ph0930118811;MultipleActiveResultSets=True;App=EntityFramework" providerName="System.Data.SqlClient" />
-    <!--<add name="DefaultConnection" connectionString="data source=localhost\SQL2016;initial catalog=Evcb;persist security info=True;user id=sa;password=Ph0930118811;MultipleActiveResultSets=True;App=EntityFramework" providerName="System.Data.SqlClient" />-->
-    <!-- <add name="DefaultConnection" connectionString="data source=localhost\SQL2016;initial catalog=Evcb;persist security info=True;user id=sa;password=Ph0930118811;MultipleActiveResultSets=True;App=EntityFramework" providerName="System.Data.SqlClient" /> -->
-    <!-- <add name="DefaultConnection" connectionString="Data Source=localhost;Integrated Security=SSPI;Initial Catalog=Evcb" providerName="System.Data.SqlClient" /> -->
-  </connectionStrings>
-  <startup>
-    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" />
-  </startup>
-  <entityFramework>
-    <defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
-      <parameters>
-        <parameter value="mssqllocaldb" />
-      </parameters>
-    </defaultConnectionFactory>
-    <providers>
-      <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
-    </providers>
-  </entityFramework>
-  <superSocket>
-    <servers>
-      <server name="SuperWebSocket" serverTypeName="SuperWebSocket">
-        <!--  <certificate filePath="localhost.pfx" password="supersocket" storeName="My" thumbprint="‎f42585bceed2cb049ef4a3c6d0ad572a6699f6f3" storeLocation="LocalMachine" clientCertificateRequired="false" keyStorageFlags="Exportable"></certificate> -->
-        <certificate filePath="certificate.pfx" password="y42j/4cj84" storeName="My" thumbprint="‎f115742946884724c07cd507564daa12dac89615" storeLocation="LocalMachine" clientCertificateRequired="false" keyStorageFlags="Exportable"></certificate>
-        <listeners>
-        </listeners>
-      </server>
-    </servers>
-    <serverTypes>
-      <add name="SuperWebSocket" type="SuperWebSocket.WebSocketServer, SuperWebSocket" />
-    </serverTypes>
-  </superSocket>
-  <appSettings>
-    <add key="ServerIp" value="172.17.40.13" />
-    <add key="ServerPort" value="8080" />
-    <add key="WSSServerPort" value="2013" />
-    <add key="ServerSecurity" value="tls" />
-    <add key="MaxRequestLength" value="3500" />
-    <!--<add key="ServerIp" value="127.0.0.1" />-->
-    <!--<add key="ServerPort" value="9999" />-->
-    <!--<add key="Customer" value="Phihong" />-->
-    <!-- 是否轉換socket 0:不要、1:要 -->
-    <add key="Redirect" value="0" />
-    <add key="ApiUrl" value="http://172.18.61.97:58612/api/ChargerService/" />
-    <!--<add key="ApiUrl" value="http://172.1.2.186/FoxconnWeb/api/ChargerService/" />-->
-    <add key="ClientSettingsProvider.ServiceUri" value="" />
-    <!-- 設定電樁連線數量資訊 (mac,limit,Signature 三組資料會作組合比對,切勿隨意修改)-->
-    <!-- Server Mac-->
-    <add key="mac" value="94-E9-79-91-A5-9A" />
-    <!-- 可連線數量  ∞ :無限制數量 -->
-    <add key="limit" value="∞" />
-    <!-- 為從 mac.limit 組合,計算出來的加密簽章 -->
-    <add key="Signature" value="2CVsI2YqXEG5zFxq1LbWH/8NuNCe3ItVyaOa4wUirdY=" />
-    <!-- 以上設定電樁連線數量資訊-->
-    <!-- 是否要記錄MachineConnectionLog 0:不要、1:要 -->
-    <add key="EnableMachineConnectionLog" value="1" />
-    <!-- 是否要將Machinelog、chargingRecordStatus轉移到mongodb ,若使用mssql 不能使用chargingRecordStatus trigger-->
-    <!--<add key="mongoDb" value="null" />-->
-    <!--mongodb connection example: mongodb://172.1.2.194:27017-->
-    <add key="mongoCon" value="" />
-  </appSettings>
-  <runtime>
-    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
-      <dependentAssembly>
-        <assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
-        <bindingRedirect oldVersion="0.0.0.0-10.0.0.0" newVersion="10.0.0.0" />
-      </dependentAssembly>
-      <dependentAssembly>
-        <assemblyIdentity name="System.Net.Http" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
-        <bindingRedirect oldVersion="0.0.0.0-4.1.1.2" newVersion="4.1.1.2" />
-      </dependentAssembly>
-      <dependentAssembly>
-        <assemblyIdentity name="Microsoft.Owin" publicKeyToken="31bf3856ad364e35" culture="neutral" />
-        <bindingRedirect oldVersion="0.0.0.0-3.1.0.0" newVersion="3.1.0.0" />
-      </dependentAssembly>
-    </assemblyBinding>
-  </runtime>
-</configuration>

+ 0 - 114
OCPPServer/ClientData.cs

@@ -1,114 +0,0 @@
-using OCPPServer.Protocol;
-using Packet.Cmd;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace OCPPServer
-{
-    public class ClientData
-    {
-        public byte[] _buffer = new byte[1024];
-        public List<byte> bufferList = new List<byte>();
-        public OCPPSession ClientSocket;
-
-        public CmdHelper CmdHelper;
-
-        public bool IsCheckIn { get; set; }
-
-        public DateTime LastAccessDatetime { get; set; }
-
-        /// <summary>
-        /// 每個client有他自己的指令序號 2 byte
-        /// </summary>
-        private ushort _cmdSerNum = 0;
-
-        /// <summary>
-        /// 傳送的封包序號 1 byte
-        /// </summary>
-        private byte _serNum = 0;
-
-        public string MachineId { get; set; }
-
-        public Guid CustomerId { get; set; }
-        public string CustomerName { get; set; }
-
-        /// <summary>
-        /// 客戶自訂的樁id
-        /// </summary>
-        public string MachineCustomId
-        {
-            get; set;
-        }
-
-        /// <summary>
-        ///  Accepted:0, Pending:1, Rejected:2
-        /// </summary>
-        public bool RegistrationStatus  { get; set; }
-
-        /// <summary>
-        /// 0: 会员、1: 卡号、2:不识别
-        /// </summary>
-        public byte StartWith { get; set; }
-
-        /// <summary>
-        /// 充電/預約卡號、 36 bytes assic碼、不夠長度補'\0'
-        /// </summary>
-        public string ReservationCardNum { get; set; }
-
-        /// <summary>
-        /// Remote充電 
-        /// </summary>
-        public bool RemoteCharging { get; set; }
-
-        public ClientData()
-        {
-            MachineCustomId = Guid.NewGuid().ToString();
-            IsCheckIn = false;
-            RegistrationStatus = false;
-            StartWith = 2; /// 0: 会员、1: 卡号、2:不识别
-            ReservationCardNum = "";
-            RemoteCharging = false;  /// Remote充電  
-            LastAccessDatetime = DateTime.Now;
-        }
-
-        public ClientData(OCPPSession clientSocket)
-        {
-            this.ClientSocket = clientSocket;
-            MachineCustomId = Guid.NewGuid().ToString();
-            RemoteCharging = false;  /// Remote充電 
-            LastAccessDatetime = DateTime.Now;
-        }
-
-        /// <summary>
-        /// 取得指令序號 0-65535
-        /// </summary>
-        /// <returns></returns>
-        public ushort GetCmdSerNum()
-        {
-            if (_cmdSerNum == ushort.MaxValue)
-                _cmdSerNum = 0;
-            return ++_cmdSerNum;
-        }
-
-        /// <summary>
-        /// 取得封包序號 1-255
-        /// </summary>
-        /// <returns></returns>
-        public byte GetSerNum()
-        {
-            if (_serNum == byte.MaxValue)
-            {
-                _serNum = 0;
-            }
-            return ++_serNum;
-        }
-
-        public bool CheckClient()
-        {
-            return false;
-        }
-    }
-}

+ 0 - 23
OCPPServer/Command/ProcessCallCmd.cs

@@ -1,23 +0,0 @@
-using OCPPServer;
-using OCPPServer.Protocol;
-using SuperWebSocket.SubProtocol;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-
-namespace OCPPServer.Command
-{
-    public class ProcessCallCmd : SubCommandBase<ClientData>
-    {
-        public override void ExecuteCommand(ClientData session, SubRequestInfo requestInfo)
-        {
-            session.ReceiveData(session, requestInfo.Body);
-        }
-
-        public override string Name
-        {
-            get { return "2"; }
-        }
-    }
-}

+ 0 - 23
OCPPServer/Command/ProcessCallErrorCmd.cs

@@ -1,23 +0,0 @@
-using OCPPServer.Protocol;
-using SuperWebSocket.SubProtocol;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace OCPPServer.Command
-{
-    public class ProcessCallErrorCmd : SubCommandBase<ClientData>
-    {
-        public override void ExecuteCommand(ClientData session, SubRequestInfo requestInfo)
-        {
-            session.ReceiveData(session, requestInfo.Body);
-        }
-
-        public override string Name
-        {
-            get { return "4"; }
-        }
-    }
-}

+ 0 - 23
OCPPServer/Command/ProcessCallResultCmd.cs

@@ -1,23 +0,0 @@
-using OCPPServer.Protocol;
-using SuperWebSocket.SubProtocol;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace OCPPServer.Command
-{
-    public class ProcessCallResultCmd : SubCommandBase<ClientData>
-    {
-        public override void ExecuteCommand(ClientData session, SubRequestInfo requestInfo)
-        {
-            session.ReceiveData(session, requestInfo.Body);
-        }
-
-        public override string Name
-        {
-            get { return "3"; }
-        }
-    }
-}

+ 0 - 78
OCPPServer/Common/ListenerConfig.cs

@@ -1,78 +0,0 @@
-using SuperSocket.SocketBase.Config;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace OCPPServer.Common
-{
-    public class ListenerConfig : IListenerConfig
-    {
-        /// <summary>
-        /// Gets the ip of listener
-        /// </summary>
-        private string ip;
-
-        /// <summary>
-        /// Gets the port of listener
-        /// </summary>
-        private int port;
-
-        /// <summary>
-        /// Gets the backlog.
-        /// </summary>
-        private int backlog;
-
-        /// <summary>
-        /// Gets the security option, None/Default/Tls/Ssl/...
-        /// </summary>
-        private string security;
-
-        public ListenerConfig(string a, int b, int c, string d)
-        {
-            ip = a;
-            port = b;
-            backlog = c;
-            security = d;
-        }
-
-        // Property implementation:
-        public string Ip
-        {
-            get
-            {
-                return ip;
-            }
-
-           
-        }
-
-        public int Port
-        {
-            get
-            {
-                return port;
-            }
-           
-        }
-
-        public int Backlog
-        {
-            get
-            {
-                return port;
-            }
-
-        }
-
-        public string Security
-        {
-            get
-            {
-                return security;
-            }
-
-        }
-    }
-}

+ 0 - 22
OCPPServer/Common/LocalAuthorization.cs

@@ -1,22 +0,0 @@
-using System.Collections.Generic;
-
-namespace OCPPServer.Common
-{
-    public class LocalAuthorization
-    {
-        /// <summary>
-        /// 卡片號碼
-        /// </summary>
-        public string CardNumber { set; get; }
-
-        /// <summary>
-        /// 卡片狀態 0:允許充電 1:鎖定卡片(不允許充電) 2:逾期卡片(不允許充電) 3:無效卡片(不允許充電)
-        /// </summary>
-        public int Status { set; get; }
-
-        /// <summary>
-        /// 逾期時間 格式:yyyy-MM-dd HH:mm:ss, 秒一律帶0, 例如:2018-06-08 23:00:00, 可不填寫
-        /// </summary>
-        public string ExpiryDate { set; get; }
-    }
-}

+ 0 - 61
OCPPServer/Common/OCPPResult.cs

@@ -1,61 +0,0 @@
-using Evcb.Service.Service.Common;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace OCPPServer.Common
-{
-    public class OCPPResult : IResult
-    {
-        public Guid ID
-        {
-            get;
-            private set;
-        }
-
-        public bool Success
-        {
-            get;
-            set;
-        }
-
-        public string Message
-        {
-            get;
-            set;
-        }
-
-        public Exception Exception
-        {
-            get;
-            set;
-        }
-
-        public List<IResult> InnerResults
-        {
-            get;
-            protected set;
-        }
-
-        public object Payload
-        {
-            get;
-            set;
-        }
-
-        public OCPPResult()
-            : this(false)
-        {
-        }
-
-        public OCPPResult(bool success)
-        {
-            ID = Guid.NewGuid();
-            Success = success;
-            InnerResults = new List<IResult>();
-        }
-
-    }
-}

+ 0 - 69
OCPPServer/Config/log4net.config

@@ -1,69 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<log4net>
-    <appender name="errorAppender" type="log4net.Appender.RollingFileAppender">
-        <filter type="log4net.Filter.LevelMatchFilter">
-            <levelToMatch value="ERROR" />
-        </filter>
-        <filter type="log4net.Filter.DenyAllFilter" />
-        <File value="Logs\err.log" />
-        <PreserveLogFileNameExtension value="true" />
-        <appendToFile value="true" />
-        <rollingStyle value="Date" />
-        <datePattern value="yyyyMMdd" />
-        <layout type="log4net.Layout.PatternLayout">
-            <conversionPattern value="%date [%thread] %-5level %logger - %message%newline" />
-        </layout>
-    </appender>
-    <appender name="infoAppender" type="log4net.Appender.RollingFileAppender">
-        <filter type="log4net.Filter.LevelMatchFilter">
-            <levelToMatch value="INFO" />
-        </filter>
-        <filter type="log4net.Filter.DenyAllFilter" />
-        <File value="Logs\info.log" />
-        <PreserveLogFileNameExtension value="true" />
-        <appendToFile value="true" />
-        <rollingStyle value="Date" />
-        <datePattern value="yyyyMMdd" />
-        <layout type="log4net.Layout.PatternLayout">
-            <conversionPattern value="%date [%thread] %-5level %logger - %message%newline" />
-        </layout>
-    </appender>
-    <appender name="debugAppender" type="log4net.Appender.RollingFileAppender">
-        <filter type="log4net.Filter.LevelMatchFilter">
-            <levelToMatch value="DEBUG" />
-        </filter>
-        <filter type="log4net.Filter.DenyAllFilter" />
-        <File value="Logs\debug.log" />
-        <PreserveLogFileNameExtension value="true" />
-        <appendToFile value="true" />
-        <rollingStyle value="Date" />
-        <datePattern value="yyyyMMdd" />
-        <layout type="log4net.Layout.PatternLayout">
-            <conversionPattern value="%date [%thread] %-5level %logger - %message%newline" />
-        </layout>
-    </appender>
-    <appender name="perfAppender" type="log4net.Appender.RollingFileAppender">
-        <filter type="log4net.Filter.LevelMatchFilter">
-            <levelToMatch value="INFO" />
-        </filter>
-        <filter type="log4net.Filter.DenyAllFilter" />
-        <File value="Logs\perf.log" />
-        <PreserveLogFileNameExtension value="true" />
-        <appendToFile value="true" />
-        <rollingStyle value="Date" />
-        <datePattern value="yyyyMMdd" />
-        <layout type="log4net.Layout.PatternLayout">
-            <conversionPattern value="%date %logger - %message%newline" />
-        </layout>
-    </appender>
-    <root>
-        <level value="ALL" />
-        <appender-ref ref="errorAppender" />
-        <appender-ref ref="infoAppender" />
-        <appender-ref ref="debugAppender" />
-    </root>
-    <logger name="Performance" additivity="false">
-      <level value="ALL" />
-      <appender-ref ref="perfAppender" />
-    </logger>
-</log4net>

+ 0 - 69
OCPPServer/Config/log4net.unix.config

@@ -1,69 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<log4net>
-    <appender name="errorAppender" type="log4net.Appender.RollingFileAppender">
-        <filter type="log4net.Filter.LevelMatchFilter">
-            <levelToMatch value="ERROR" />
-        </filter>
-        <filter type="log4net.Filter.DenyAllFilter" />
-        <File value="Logs/err.log" />
-        <PreserveLogFileNameExtension value="true" />
-        <appendToFile value="true" />
-        <rollingStyle value="Date" />
-        <datePattern value="yyyyMMdd" />
-        <layout type="log4net.Layout.PatternLayout">
-            <conversionPattern value="%date [%thread] %-5level %logger - %message%newline" />
-        </layout>
-    </appender>
-    <appender name="infoAppender" type="log4net.Appender.RollingFileAppender">
-        <filter type="log4net.Filter.LevelMatchFilter">
-            <levelToMatch value="INFO" />
-        </filter>
-        <filter type="log4net.Filter.DenyAllFilter" />
-        <File value="Logs/info.log" />
-        <PreserveLogFileNameExtension value="true" />
-        <appendToFile value="true" />
-        <rollingStyle value="Date" />
-        <datePattern value="yyyyMMdd" />
-        <layout type="log4net.Layout.PatternLayout">
-            <conversionPattern value="%date [%thread] %-5level %logger - %message%newline" />
-        </layout>
-    </appender>
-    <appender name="debugAppender" type="log4net.Appender.RollingFileAppender">
-        <filter type="log4net.Filter.LevelMatchFilter">
-            <levelToMatch value="DEBUG" />
-        </filter>
-        <filter type="log4net.Filter.DenyAllFilter" />
-        <File value="Logs/debug.log" />
-        <PreserveLogFileNameExtension value="true" />
-        <appendToFile value="true" />
-        <rollingStyle value="Date" />
-        <datePattern value="yyyyMMdd" />
-        <layout type="log4net.Layout.PatternLayout">
-            <conversionPattern value="%date [%thread] %-5level %logger - %message%newline" />
-        </layout>
-    </appender>
-    <appender name="perfAppender" type="log4net.Appender.RollingFileAppender">
-        <filter type="log4net.Filter.LevelMatchFilter">
-            <levelToMatch value="TRACE" />
-        </filter>
-        <filter type="log4net.Filter.DenyAllFilter" />
-        <File value="Logs/perf.log" />
-        <PreserveLogFileNameExtension value="true" />
-        <appendToFile value="true" />
-        <rollingStyle value="Date" />
-        <datePattern value="yyyyMMdd" />
-        <layout type="log4net.Layout.PatternLayout">
-            <conversionPattern value="%date %logger - %message%newline" />
-        </layout>
-    </appender>
-    <root>
-        <level value="ALL" />
-        <appender-ref ref="errorAppender" />
-        <appender-ref ref="infoAppender" />
-        <appender-ref ref="debugAppender" />
-    </root>
-    <logger name="Performance" additivity="false">
-        <level value="ALL" />
-        <appender-ref ref="perfAppender" />
-    </logger>
-</log4net>

+ 0 - 109
OCPPServer/Handler/FeatureHandler.cs

@@ -1,109 +0,0 @@
-using NLog;
-using OCPPPacket.Packet.Feature;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace OCPPServer.Handler
-{
-    public class FeatureHandler
-    {
-        private ILogger logger = NLog.LogManager.GetCurrentClassLogger();
-        List<Feature> featureList;
-        public FeatureHandler()
-        {
-            this.featureList = new List<Feature>();
-        }
-
-        public void AddFeatureProfile(Feature feature)
-        {
-            featureList.Add(feature);
-        }
-
-        public  Feature FindFeatureByConfirm(Type confirm)
-        {
-            return FindFeature(confirm, featureList);
-        }
-
-        public  Feature FindFeatureByRequest(Type request)
-        {
-            return FindFeature(request, featureList);
-        }
-
-        public bool FeatureContains(Feature feature, Type seektype)
-        {
-            bool contains = false;
-            if(feature.GetRequestType() == seektype)
-            {
-                contains |= true;
-            }
-
-            if(feature.GetConfirmationType() == seektype)
-            {
-                contains |= true;
-            }
-            //old coding type
-            ////contains |= feature.getAction().Equals(object1);
-            //contains |= feature.GetRequestType() == object1;
-            //contains |= feature.GetConfirmationType() == object1;
-            return contains;
-        }
-
-        public  Feature FindFeature(Type needle, List<Feature> featureList)
-        {
-            Feature output = null;
-
-            foreach (Feature feature in featureList)
-            {
-                if (FeatureContains(feature, needle))
-                {
-                    output = feature;
-                    break;
-                }
-            }
-
-            return output;
-        }
-
-        public  Feature FindFeatureByAction(string v)
-        {
-            try
-            {
-                Feature output = null;
-
-                foreach (Feature feature in featureList)
-                {
-                    if (TestfeatureContains(feature, v))
-                    {
-                        output = feature;
-                        break;
-                    }
-                }
-
-                return output;
-            }
-            catch (Exception ex)
-            {
-                logger.Error(ex);
-                throw new ApplicationException(ex.ToString());
-            }
-        }
-
-        public  bool TestfeatureContains(Feature feature, string v)
-        {
-            try
-            {
-                bool contains = false;
-                contains |= feature.GetAction().Equals(v);
-                return contains;
-            }
-            catch (Exception ex)
-            {
-                logger.Error(ex);
-                throw new ApplicationException(ex.ToString());
-            }
-        }
-    }
-}

+ 0 - 256
OCPPServer/Handler/MakeConfirmationHandler.cs

@@ -1,256 +0,0 @@
-using Newtonsoft.Json;
-using OCPPPacket.Packet.DataTransfer;
-using OCPPPacket.Packet.Messages;
-using OCPPPacket.Packet.Messages.Core;
-using OCPPPacket.Packet.Messages.FirmwareManagement;
-using OCPPPacket.Packet.Status;
-using System;
-
-namespace OCPPServer.Handler
-{
-    public class MakeConfirmationHandler
-    {
-        #region Core
-
-        /// <summary>
-        /// 建立 Authorize comfirm message
-        /// </summary>
-        /// <param name="request">AuthorizeRequest</param>
-        /// <param name="authstatus">AuthorizationStatus</param>
-        /// <returns></returns>
-        public IConfirmation MakeAuthorizeConfirmation(AuthorizeRequest request, AuthorizationStatus authstatus)
-        {
-            AuthorizeConfirmation conf = new AuthorizeConfirmation();
-            conf.idTagInfo = new IdTagInfo();
-            conf.idTagInfo.expiryDate = new DateTime(2020, 06, 19, 09, 10, 00, 000);//date;
-            conf.idTagInfo.parentIdTag = request.idTag;
-            conf.idTagInfo.status = authstatus;
-
-            return conf;
-        }
-
-        /// <summary>
-        /// 建立 BootNotification comfirm message
-        /// </summary>
-        /// <param name="request">BootNotificationRequest</param>
-        /// <returns></returns>
-        public IConfirmation MakeBootNotificationConfirmation(BootNotificationRequest request)
-        {
-            BootNotificationConfirmation conf = new BootNotificationConfirmation();
-            conf.currentTime = DateTime.Now;
-            conf.interval = 10;
-            conf.status = RegistrationStatus.Accepted;
-
-            return conf;
-        }
-
-        /// <summary>
-        /// 建立 StatusNotification comfirm message
-        /// </summary>
-        /// <param name="request">StatusNotificationRequest</param>
-        /// <returns></returns>
-        public IConfirmation MakeStatusNotificationConfirmation(StatusNotificationRequest request)
-        {
-            StatusNotificationConfirmation conf = new StatusNotificationConfirmation();
-
-            return conf;
-        }
-
-        /// <summary>
-        /// 建立 Heartbeat comfirm message
-        /// </summary>
-        /// <param name="request">HeartbeatRequest</param>
-        /// <returns></returns>
-        public IConfirmation MakeHeartbeatConfirmation(HeartbeatRequest request)
-        {
-            HeartbeatConfirmation conf = new HeartbeatConfirmation();
-            conf.currentTime = DateTime.Now;
-            return conf;
-        }
-
-        /// <summary>
-        /// 建立 ClearCache comfirm message
-        /// </summary>
-        /// <param name="request">ClearCacheRequest</param>
-        /// <returns></returns>
-        public IConfirmation MakeClearCacheConfirmation(ClearCacheRequest request)
-        {
-            ClearCacheConfirmation conf = new ClearCacheConfirmation();
-            conf.status = ClearCacheStatus.Accepted;
-            return conf;
-        }
-
-        /// <summary>
-        /// 建立 MeterValues comfirm message
-        /// </summary>
-        /// <param name="request">MeterValuesRequest</param>
-        /// <returns></returns>
-        public IConfirmation MakeMeterValuesConfirmation(MeterValuesRequest request)
-        {
-            MeterValuesConfirmation conf = new MeterValuesConfirmation();
-            return conf;
-        }
-
-        /// <summary>
-        /// 建立 StartTransaction comfirm message
-        /// </summary>
-        /// <param name="request">StartTransactionRequest</param>
-        /// <param name="transactionId"></param>
-        /// <returns></returns>
-        public IConfirmation MakeStartTransactionConfirmation(StartTransactionRequest request, out int transactionId)
-        {
-            StartTransactionConfirmation conf = new StartTransactionConfirmation();
-            conf.idTagInfo = new IdTagInfo();
-            conf.idTagInfo.expiryDate = new DateTime(2020, 06, 19, 09, 10, 00, 000);
-            conf.idTagInfo.parentIdTag = request.idTag;
-            conf.transactionId = new Random().Next(1, int.MaxValue);
-            conf.idTagInfo.status = AuthorizationStatus.Accepted; // 一律回 "Accepted"
-            transactionId = conf.transactionId;
-            return conf;
-        }
-
-        /// <summary>
-        /// 建立 Repeat StartTransaction comfirm message
-        /// </summary>
-        /// <param name="request">StartTransactionRequest</param>
-        /// <param name="transactionId"></param>
-        /// <returns></returns>
-        public IConfirmation MakeRePeatStartTransactionConfirmation(StartTransactionRequest request, int transactionId)
-        {
-            StartTransactionConfirmation conf = new StartTransactionConfirmation();
-            conf.idTagInfo = new IdTagInfo();
-            conf.idTagInfo.expiryDate = new DateTime(2020, 06, 19, 09, 10, 00, 000);
-            conf.idTagInfo.parentIdTag = request.idTag;
-            conf.transactionId = transactionId;
-            conf.idTagInfo.status = AuthorizationStatus.Accepted; // 一律回 "Accepted"
-            return conf;
-        }
-
-        /// <summary>
-        /// 建立 StopTransaction comfirm message
-        /// </summary>
-        /// <param name="request">StopTransactionRequest</param>
-        /// <param name="authstatus">AuthorizationStatus</param>
-        /// <returns></returns>
-        public IConfirmation MakeStopTransactionConfirmation(StopTransactionRequest request, AuthorizationStatus authstatus)
-        {
-            StopTransactionConfirmation conf = new StopTransactionConfirmation();
-            conf.idTagInfo = new IdTagInfo();
-            conf.idTagInfo.expiryDate = new DateTime(2020, 06, 19, 09, 10, 00, 000);
-            conf.idTagInfo.parentIdTag = request.idTag;
-            conf.idTagInfo.status = authstatus;
-            return conf;
-        }
-
-        /// <summary>
-        /// 建立 GunStatus comfirm message
-        /// </summary>
-        /// <returns></returns>
-        public IConfirmation MakeGunStatusConfirmation()
-        {
-            DataTransferConfirmation conf = new DataTransferConfirmation();
-            conf.status = DataTransferStatus.Accepted;
-            return conf;
-        }
-
-        /// <summary>
-        /// 建立 ChargeComplete comfirm message
-        /// </summary>
-        /// <returns></returns>
-        public IConfirmation MakeChargeCompleteConfirmation()
-        {
-            DataTransferConfirmation conf = new DataTransferConfirmation();
-            conf.status = DataTransferStatus.Accepted;
-            return conf;
-        }
-
-        /// <summary>
-        /// 建立 Location comfirm message
-        /// </summary>
-        /// <returns></returns>
-        public IConfirmation MakeLocationConfirmation()
-        {
-            DataTransferConfirmation conf = new DataTransferConfirmation();
-            conf.status = DataTransferStatus.Accepted;
-            return conf;
-        }
-
-        /// <summary>
-        /// 建立 ChargingGunBMS comfirm message
-        /// </summary>
-        /// <returns></returns>
-        public IConfirmation MakeChargingGunBMSConfirmation()
-        {
-            DataTransferConfirmation conf = new DataTransferConfirmation();
-            conf.status = DataTransferStatus.Accepted;
-            return conf;
-        }
-
-        /// <summary>
-        /// 建立 UpgradeVersionConf comfirm message
-        /// </summary>
-        /// <param name="result"></param>
-        /// <param name="param"></param>
-        /// <returns></returns>
-        public IConfirmation MakeUpgradeVersionConfConfirmation(bool result, ProgramParam param)
-        {
-            DataTransferConfirmation conf = new DataTransferConfirmation();
-            conf.status = DataTransferStatus.Accepted;
-            UpgradeVersionConf upgradeverConf = new UpgradeVersionConf();
-            upgradeverConf.param = param;
-            if (!result)
-            {
-                upgradeverConf.SameAsServer = true;
-            }
-            else
-            {
-                upgradeverConf.SameAsServer = false;
-            }
-
-            conf.data = JsonConvert.SerializeObject(upgradeverConf);
-            return conf;
-        }
-
-        #endregion Core
-
-        #region FirmwareManagement
-
-        /// <summary>
-        /// 建立 DiagnosticsStatusNotification comfirm message
-        /// </summary>
-        /// <returns></returns>
-        public IConfirmation MakeDiagnosticsStatusNotificationConfirmation()
-        {
-            DiagnosticsStatusNotificationConfirmation conf = new DiagnosticsStatusNotificationConfirmation();
-            return conf;
-        }
-
-        /// <summary>
-        /// 建立 FirmwareStatusNotification comfirm message
-        /// </summary>
-        /// <returns></returns>
-        public IConfirmation MakeFirmwareStatusNotificationConfirmation()
-        {
-            FirmwareStatusNotificationConfirmation conf = new FirmwareStatusNotificationConfirmation();
-            return conf;
-        }
-
-        #endregion FirmwareManagement
-
-        #region DataTransfer
-        public IConfirmation MakeAuthorizeDataConfConfirmation(AuthorizeData request, AuthorizeStatus authstatus)
-        {
-            DataTransferConfirmation conf = new DataTransferConfirmation();
-            conf.status = DataTransferStatus.Accepted;
-            AuthorizeResult authorizeResult = new AuthorizeResult();
-            authorizeResult.expiryDate = new DateTime(2020, 06, 19, 09, 10, 00, 000);//date;
-            authorizeResult.parentIdTag = request.idTag;
-            authorizeResult.status = authstatus;
-
-            conf.data = JsonConvert.SerializeObject(authorizeResult);
-            return conf;
-        }
-
-        #endregion
-    }
-}

+ 0 - 612
OCPPServer/Handler/MakeRequestHandler.cs

@@ -1,612 +0,0 @@
-using Evcb.Domain.Model;
-using Newtonsoft.Json;
-using OCPP_Packet.Packet.DataTransfer;
-using OCPPPacket.Packet.DataTransfer;
-using OCPPPacket.Packet.Messages;
-using OCPPPacket.Packet.Messages.Core;
-using OCPPPacket.Packet.Messages.FirmwareManagement;
-using OCPPPacket.Packet.Messages.LocalAuthListManagement;
-using OCPPPacket.Packet.Messages.RemoteTrigger;
-using OCPPPacket.Packet.Messages.Reservation;
-using OCPPPacket.Packet.Messages.SmartCharging;
-using OCPPPacket.Packet.Status;
-using OCPPServer.Common;
-using Packet.Cmd;
-using System;
-using System.Collections.Generic;
-
-namespace OCPPServer.Handler
-{
-    public class MakeRequestHandler
-    {
-        #region Core
-
-        /// <summary>
-        /// 取得電樁 configuration settings
-        /// </summary>
-        static public IRequest MakeGetConfigurationRequest()
-        {
-            GetConfigurationRequest req = new GetConfigurationRequest();
-            req.key = new List<string>();
-            //req.key.Add("AllowOfflineTxForUnknownIdAvailable");
-            //req.key.Add("AllowOfflineTxForUnknownIdEnabled");
-            //req.key.Add("AuthorizationCacheAvailable");
-            //req.key.Add("AuthorizationCacheEnabled");
-            //req.key.Add("BlinkRepeat");
-            //req.key.Add("ClockAlignedDataInterval");
-            //req.key.Add("ConnectionTimeOut");
-            //req.key.Add("HeartBeatInterval");
-            //req.key.Add("LightIntensity");
-            //req.key.Add("LocalAuthorizeOffline");
-            //req.key.Add("LocalPreAuthorize");
-            //req.key.Add("MeterValuesAlignedData");
-            //req.key.Add("MeterValuesSampledData");
-            //req.key.Add("MeterValueSampleInterval");
-            //req.key.Add("MinimumStatusDuration");
-            //req.key.Add("ResetRetries");
-            //req.key.Add("ConnectorPhaseRotation");
-            //req.key.Add("StopTransactionOnEVSideDisconnect");
-            //req.key.Add("LocalAuthorizationListEnabled");
-            //req.key.Add("StopTransactionOnInvalidId");
-            //req.key.Add("StopTxnAlignedData");
-            //req.key.Add("StopTxnSampledData");
-            //req.key.Add("SupportedCompliancyProfiles");
-            //req.key.Add("TransactionMessageAttempts");
-            //req.key.Add("TransactionMessageRetryInterval");
-            //req.key.Add("UnlockConnectorOnEVSideDisconnect");
-            //req.key.Add("ChargeProfileMaxStackLevel");
-            //req.key.Add("ChargingScheduleAllowedSchedulingUnit");
-            //req.key.Add("ChargingScheduleMaxPeriods");
-            //req.key.Add("MaxChargingProfilesInstalled");
-            //req.key.Add("ProximityLockRetries");
-            //req.key.Add("ProximityContactRetries");
-            //req.key.Add("ChargePointId");
-            //req.key.Add("GetConfigurationMaxKeys");
-            //req.key.Add("LocalAuthListSize");
-            //req.key.Add("LocalAuthMaxElementsOnce");
-            //req.key.Add("MaxEnergyOnInvalidId");
-            //req.key.Add("MeterValuesTriggeredData");
-            //req.key.Add("ReserveConnectorZeroSupported");
-            //req.key.Add("WebSocketPingInterval");
-            //req.key.Add("Testing");
-            return req;
-        }
-
-        /// <summary>
-        /// 要求電樁改變configuration parameters
-        /// </summary>
-        static public IRequest MakeChangeConfigurationRequest(string key, string keyvalue)
-        {
-            ChangeConfigurationRequest req = new ChangeConfigurationRequest();
-
-            if (key == "HeartbeatInterval")
-            {
-                req.key = "HeartbeatInterval";
-                req.value = keyvalue;
-            }
-            return req;
-        }
-
-        /// <summary>
-        /// APP啟動充電
-        /// </summary>
-        public IRequest MakeRemoteStartTransactionRequest(int gunSerNo, string memberId)
-        {
-            RemoteStartTransactionRequest req = new RemoteStartTransactionRequest();
-            req.connectorId = gunSerNo;//0;
-            req.idTag = memberId;//"990f57dd-b660-4734-8e96-4cd346d0qwez";
-
-            req.chargingProfile = null;
-            return req;
-        }
-
-        /// <summary>
-        /// APP結束充電
-        /// </summary>
-        public IRequest MakeRemoteStopTransactionRequest(int transactionId)
-        {
-            RemoteStopTransactionRequest req = new RemoteStopTransactionRequest();
-            req.transactionId = transactionId;
-            return req;
-        }
-
-        /// <summary>
-        /// 要求電樁清除 Authorization Cache
-        /// </summary>
-        public IRequest MakeClearCacheRequest()
-        {
-            ClearCacheRequest req = new ClearCacheRequest();
-            return req;
-        }
-
-        /// <summary>
-        /// 要求電樁 Hard Reset
-        /// </summary>
-        public IRequest MakeHardResetRequest()
-        {
-            ResetRequest req = new ResetRequest();
-            req.type = ResetType.Hard;
-            return req;
-        }
-
-        /// <summary>
-        /// 要求電樁 Soft Reset
-        /// </summary>
-        public IRequest MakeSoftResetRequest()
-        {
-            ResetRequest req = new ResetRequest();
-            req.type = ResetType.Soft;
-            return req;
-        }
-
-        /// <summary>
-        /// unlock 電樁 connector
-        /// </summary>
-        public IRequest MakeUnlockConnectorRequest(int connectorId)
-        {
-            UnlockConnectorRequest req = new UnlockConnectorRequest();
-            req.connectorId = connectorId;
-            return req;
-        }
-
-        /// <summary>
-        /// 取得 電樁 configuration
-        /// </summary>
-        public IRequest MakeGetConfigurationRequest(string key)
-        {
-            GetConfigurationRequest req = new GetConfigurationRequest();
-            //req.key = new List<string> {"LocalAuthListEnabled","SendLocalListMaxLength"};
-            //req.key = new List<string> { "AllowOfflineTxForUnknownId", "AuthorizationCacheEnabled", "AuthorizeRemoteTxRequests", "BlinkRepeat", "ClockAlignedDataInterval", "ConnectionTimeOut", "GetConfigurationMaxKeys", "HeartbeatInterval", "LightIntensity", "LocalAuthorizeOffline", "LocalPreAuthorize", "MaxEnergyOnInvalidId" , "MeterValuesAlignedData", "MeterValuesAlignedDataMaxLength", "MeterValuesSampledData", "MeterValuesSampledDataMaxLength", "MeterValueSampleInterval", "MinimumStatusDuration", "NumberOfConnectors", "ResetRetries", "ConnectorPhaseRotation", "ConnectorPhaseRotationMaxLength", "StopTransactionOnEVSideDisconnect", "StopTransactionOnInvalidId", "StopTxnAlignedData", "StopTxnAlignedDataMaxLength", "StopTxnSampledData", "StopTxnSampledDataMaxLength", "SupportedFeatureProfiles", "SupportedFeatureProfilesMaxLength", "TransactionMessageAttempts", "TransactionMessageRetryInterval", "UnlockConnectorOnEVSideDisconnect", "WebSocketPingInterval", "LocalAuthListEnabled", "LocalAuthListMaxLength", "SendLocalListMaxLength", "ReserveConnectorZeroSupported", "ChargeProfileMaxStackLevel", "ChargingScheduleAllowedChargingRateUnit", "ChargingScheduleMaxPeriods", "ConnectorSwitch3to1PhaseSupported", "MaxChargingProfilesInstalled" };
-            //req.key = new List<string> ();
-            req.key = new List<string> { "AllowOfflineTxForUnknownId", "AuthorizationCacheEnabled", "LocalAuthListEnabled", "SendLocalListMaxLength", "ConnectionTimeOut", "HeartbeatInterval", "test1", "test2" };
-
-            return req;
-        }
-
-        /// <summary>
-        /// 設定 電樁槍號 availability 改變
-        /// </summary>
-        public IRequest MakeChangeAvailabilityRequest(int connectorId)
-        {
-            ChangeAvailabilityRequest req = new ChangeAvailabilityRequest();
-            req.connectorId = connectorId;
-            req.type = AvailabilityType.Operative;
-            return req;
-        }
-
-        #endregion Core
-
-        #region RemoteTrigger
-
-        /// <summary>
-        /// Trigger 電樁 送相關的message
-        /// </summary>
-        public IRequest MakeTriggerMessageRequest(MessageTrigger messageType, int connectorId)
-        {
-            TriggerMessageRequest req = new TriggerMessageRequest();
-            req.requestedMessage = messageType;
-            req.connectorId = connectorId;
-            return req;
-        }
-
-        #endregion RemoteTrigger
-
-        #region FirmwareManagement
-
-        /// <summary>
-        /// 請電樁送diagnostic information
-        /// </summary>
-        static public IRequest MakeGetDiagnosticsRequest(bool ac)
-        {
-            GetDiagnosticsRequest req = new GetDiagnosticsRequest();
-
-            if (ac == true)
-                req.location = new Uri("ftp://ipc_ui:pht2016@ftp.phihong.com.tw/AC/log/");
-            else
-                req.location = new Uri("ftp://ipc_ui:pht2016@ftp.phihong.com.tw/DC/log/");
-
-            return req;
-        }
-
-        /// <summary>
-        /// 請電樁 update firmware
-        /// </summary>
-        static public IRequest MakeOCPPUpdateFirmwareRequest(string fileurl)
-        {
-            UpdateFirmwareRequest req = new UpdateFirmwareRequest();
-            req.location = new Uri(fileurl);
-            req.retrieveDate = DateTime.Now;
-            return req;
-        }
-
-        #endregion FirmwareManagement
-
-        #region LocalAuthListManagement
-
-        /// <summary>
-        /// 請電樁送 the Local Authorization Lis 版本號
-        /// </summary>
-        static public IRequest MakeGetLocalListVersionRequest()
-        {
-            GetLocalListVersionRequest req = new GetLocalListVersionRequest();
-
-            return req;
-        }
-
-        /// <summary>
-        /// 送給電樁 Local Authorization Lis 版本號 跟 idTags
-        /// </summary>
-        static public IRequest MakeSendLocalListRequest(List<OCPPServer.Common.LocalAuthorization> localauth, uint version, byte type)
-        {
-            SendLocalListRequest req = new SendLocalListRequest();
-            req.localAuthorizationList = new List<AuthorizationData>();
-            foreach (var localAuthorization in localauth)
-            {
-                AuthorizationData athData = new AuthorizationData();
-                athData.IdToken = localAuthorization.CardNumber;
-                IdTagInfo idTagInfo = new IdTagInfo();
-                idTagInfo.expiryDate = DateTime.Parse(localAuthorization.ExpiryDate);
-                idTagInfo.parentIdTag = localAuthorization.CardNumber;
-                idTagInfo.status = (AuthorizationStatus)localAuthorization.Status;
-                athData.idTagInfo = idTagInfo;
-                req.localAuthorizationList.Add(athData);
-            }
-            req.listVersion = Convert.ToInt32(version);
-
-            //0:全部更新 ,1:差异更新
-            if (type == 0)
-            {
-                req.updateType = UpdateType.Full;
-            }
-            else
-            {
-                req.updateType = UpdateType.Differential;
-            }
-
-            return req;
-        }
-
-        #endregion LocalAuthListManagement
-
-        #region Reservation
-
-        /// <summary>
-        /// 預約電樁槍號
-        /// </summary>
-        public IRequest MakeReserveNowRequest(int connectorId, string memberId, bool reserveConnectorZeroSupported, int reservationId)
-        {
-            int RetainMinute = 5;
-            ReserveNowRequest req = new ReserveNowRequest();
-
-            if (reserveConnectorZeroSupported == true)
-                req.connectorId = 0;
-            else
-                req.connectorId = connectorId;
-
-            req.expiryDate = DateTime.Now.AddMinutes(RetainMinute);
-            req.parentIdTag = memberId;
-            req.idTag = memberId;
-            req.reservationId = reservationId;
-
-            return req;
-        }
-
-        /// <summary>
-        /// 取消預約電樁槍號
-        /// </summary>
-        public IRequest MakeCancelReservationRequest(int reservationId)
-        {
-            CancelReservationRequest req = new CancelReservationRequest();
-            req.reservationId = reservationId;
-            return req;
-        }
-
-        #endregion Reservation
-
-        #region SmartCharging
-
-        /// <summary>
-        /// 設定 Charging Profile
-        /// </summary>
-        static public IRequest MakeSetChargingProfileRequest(int connectorId, int transactionId, int chargingProfileId, string purpose)
-        {
-            SetChargingProfileRequest req = new SetChargingProfileRequest();
-            req.connectorId = connectorId;
-            req.csChargingProfiles = new csChargingProfiles();
-            req.csChargingProfiles.chargingProfileId = chargingProfileId;
-            req.csChargingProfiles.transactionId = transactionId;
-
-            if (purpose.Contains("ChargePointMaxProfile"))
-            {
-                req.csChargingProfiles.stackLevel = 2;
-                req.csChargingProfiles.chargingProfilePurpose = ChargingProfilePurposeType.ChargePointMaxProfile;
-                req.csChargingProfiles.chargingProfileKind = ChargingProfileKindType.Recurring;
-                req.csChargingProfiles.recurrencyKind = RecurrencyKindType.Daily;
-            }
-            else if (purpose.Contains("TxDefaultProfile"))
-            {
-                req.csChargingProfiles.stackLevel = 1;
-                req.csChargingProfiles.chargingProfilePurpose = ChargingProfilePurposeType.TxDefaultProfile;
-                req.csChargingProfiles.chargingProfileKind = ChargingProfileKindType.Absolute;
-                req.csChargingProfiles.recurrencyKind = RecurrencyKindType.Weekly;
-            }
-            else if (purpose.Contains("TxProfile"))
-            {
-                req.csChargingProfiles.stackLevel = 0;
-                req.csChargingProfiles.chargingProfilePurpose = ChargingProfilePurposeType.TxProfile;
-                req.csChargingProfiles.chargingProfileKind = ChargingProfileKindType.Relative;
-                req.csChargingProfiles.recurrencyKind = RecurrencyKindType.Daily;
-            }
-
-            req.csChargingProfiles.validFrom = DateTime.Now;
-            req.csChargingProfiles.validTo = DateTime.Now.AddHours(2);
-            req.csChargingProfiles.chargingSchedule = new ChargingSchedule();
-            req.csChargingProfiles.chargingSchedule.chargingRateUnit = ChargingRateUnitType.A;
-            req.csChargingProfiles.chargingSchedule.chargingSchedulePeriod = new List<ChargingSchedulePeriod>();
-            req.csChargingProfiles.chargingSchedule.duration = 120;
-            req.csChargingProfiles.chargingSchedule.minChargingRate = 0.0m;
-            req.csChargingProfiles.chargingSchedule.startSchedule = DateTime.Now;
-            req.csChargingProfiles.chargingSchedule.chargingSchedulePeriod = new List<ChargingSchedulePeriod>();
-            req.csChargingProfiles.chargingSchedule.chargingSchedulePeriod.Add(new ChargingSchedulePeriod() { startPeriod = 0, limit = 11000.0m, numberPhases = 3 });
-            req.csChargingProfiles.chargingSchedule.chargingSchedulePeriod.Add(new ChargingSchedulePeriod() { startPeriod = 28800, limit = 6000.0m, numberPhases = 3 });
-            req.csChargingProfiles.chargingSchedule.chargingSchedulePeriod.Add(new ChargingSchedulePeriod() { startPeriod = 72000, limit = 6000.0m, numberPhases = 3 });
-
-            // Add parts to the list.
-            //req.csChargingProfiles.chargingSchedule.chargingSchedulePeriod.Add(new ChargingSchedulePeriod() { startPeriod = 5, limit = 8.1m, numberPhases = 3 });
-
-            return req;
-        }
-
-        /// <summary>
-        /// 設定 Charging Profile
-        /// </summary>
-        static public IRequest MakeSetChargingProfileRequest(BaseCmd cmd, int transactionId)
-        {
-            SetChargingProfileRequest req = new SetChargingProfileRequest();
-            var c = cmd as Cmd1013;
-
-            if(c.GunSerNo == 255)
-                req.connectorId = 0;
-            else
-                req.connectorId = c.GunSerNo + 1;
-
-            req.csChargingProfiles = new csChargingProfiles();
-            req.csChargingProfiles.chargingProfileId = c.ChargingProfileId;
-            req.csChargingProfiles.transactionId = transactionId;
-
-
-            req.csChargingProfiles.stackLevel = c.stackLevel;
-            req.csChargingProfiles.chargingProfilePurpose = (c.ChargingProfilePurpose == 0) ? ChargingProfilePurposeType.ChargePointMaxProfile : ((c.ChargingProfilePurpose == 1) ? ChargingProfilePurposeType.TxDefaultProfile : ChargingProfilePurposeType.TxProfile);
-            req.csChargingProfiles.chargingProfileKind = (c.ChargingProfileKind == 0) ? ChargingProfileKindType.Absolute : ((c.ChargingProfileKind == 1) ? ChargingProfileKindType.Recurring : ChargingProfileKindType.Relative);
-            req.csChargingProfiles.recurrencyKind = (c.RecurrencyKind == 0) ? RecurrencyKindType.Daily : RecurrencyKindType.Weekly;
-
-            req.csChargingProfiles.validFrom = c.ValidFrom.Value;
-            req.csChargingProfiles.validTo = c.ValidTo.Value;
-            req.csChargingProfiles.chargingSchedule = new ChargingSchedule();
-            req.csChargingProfiles.chargingSchedule.chargingRateUnit = (c.ChargingRateUnit == 0) ?  ChargingRateUnitType.W: ChargingRateUnitType.A;
-            req.csChargingProfiles.chargingSchedule.duration = Convert.ToInt32(c.Duration);
-            req.csChargingProfiles.chargingSchedule.minChargingRate = c.MinChargingRate.RealValue;
-            req.csChargingProfiles.chargingSchedule.startSchedule = c.StartSchedule.Value;
-            
-           
-
-            req.csChargingProfiles.chargingSchedule.chargingSchedulePeriod = new List<ChargingSchedulePeriod>();
-
-            var chargingPeriod = c.ChargingSchedulePeriod as List<ChargingSchedulePeriodParameter>;
-
-            foreach (var csp in chargingPeriod)
-            {
-                req.csChargingProfiles.chargingSchedule.chargingSchedulePeriod.Add(new ChargingSchedulePeriod() { startPeriod = Convert.ToInt32(csp.StartPeriod), limit =  csp.Limit.RealValue, numberPhases = 3 });
-            }
-       
-            return req;
-        }
-
-        /// <summary>
-        /// 設定Clear Charging Profile
-        /// </summary>
-        public IRequest MakeClearChargingProfileRequest(int connectorId)
-        {
-            ClearChargingProfileRequest req = new ClearChargingProfileRequest();
-            req.connectorId = 0;
-            req.id = 1;
-            req.stackLevel = 1;
-            req.chargingProfilePurpose = ChargingProfilePurposeType.TxDefaultProfile;
-            return req;
-        }
-
-        /// <summary>
-        /// 設定Clear Charging Profile
-        /// </summary>
-        public IRequest MakeClearChargingProfileRequest(BaseCmd cmd)
-        {
-            ClearChargingProfileRequest req = new ClearChargingProfileRequest();
-            var c = cmd as Cmd1015;
-            if (c.GunSerNo == 255)
-                req.connectorId = 0;
-            else
-                req.connectorId = c.GunSerNo + 1;
-
-            req.id = c.ChargingProfileId;
-            req.stackLevel = c.stackLevel;
-            req.chargingProfilePurpose = (c.ChargingProfilePurpose == 0) ? ChargingProfilePurposeType.ChargePointMaxProfile : ((c.ChargingProfilePurpose == 1) ? ChargingProfilePurposeType.TxDefaultProfile : ChargingProfilePurposeType.TxProfile);
-            return req;
-        }
-
-        /// <summary>
-        /// 取得電樁 Composite Charging Schedule
-        /// </summary>
-        public IRequest MakeGetCompositeScheduleRequest(int connectorId)
-        {
-            GetCompositeScheduleRequest req = new GetCompositeScheduleRequest();
-            req.connectorId = connectorId;
-            req.duration = 120;
-            req.chargingRateUnit = ChargingRateUnitType.A;
-            return req;
-        }
-
-
-
-        #endregion SmartCharging
-
-        #region DataTransfer
-
-        /// <summary>
-        /// 向充電樁下發升級指令
-        /// </summary>
-        public IRequest MakeUpdateFirmware(int type, ProgramParam param, UploadFile uploadFile)
-        {
-            UpdateFirmware updatefirm = new UpdateFirmware();
-            updatefirm.type = (ProgramType)type;
-            updatefirm.param = param;
-            updatefirm.url = @"http://" + uploadFile.FileUrl;
-            updatefirm.md5 = uploadFile.FileMD5.ToUpper();
-
-            DataTransferRequest req = new DataTransferRequest();
-            req.vendorId = "Phihong";
-            req.messageId = "UpdateFirmware";
-            req.data = JsonConvert.SerializeObject(updatefirm);
-
-            return req;
-        }
-
-        /// <summary>
-        /// 設定簡易版充電電量
-        /// </summary>
-        static public IRequest MakeSendChargingConfigRequest(BaseCmd cmd)
-        {
-            var c = cmd as Cmd1017;
-            DataTransferRequest req = new DataTransferRequest();
-            req.vendorId = c.vendorId;
-            req.messageId = "SetChargingConfig";
-            req.data = JsonConvert.SerializeObject( new ChargingRate() {  chargingRateUnit="A", limit=c.limit});
-            return req;
-        }
-
-        /// <summary>
-        /// 取得簡易版充電電量
-        /// </summary>
-        static public IRequest MakeSendGetChargingConfigRequest(BaseCmd cmd)
-        {
-            var c = cmd as Cmd1019;
-            DataTransferRequest req = new DataTransferRequest();
-            req.vendorId = c.vendorId;
-            req.messageId = "GetChargingConfig";
-         
-            return req;
-        }
-
-        /// <summary>
-        /// 設定樁的夥伴代碼
-        /// </summary>
-        public IRequest MakeSendPartnerPoleIdRequest(string partnerPoleId)
-        {
-            DataTransferRequest req = new DataTransferRequest();
-            req.vendorId = "Phihong";
-            req.messageId = "SendPartnerPoleId";
-            req.data = partnerPoleId;
-            return req;
-        }
-
-        /// <summary>
-        ///  將電樁轉伺服器
-        /// </summary>
-        public IRequest MakeServerDomainNameRequest(string ServerDomainName)
-        {
-            DataTransferRequest req = new DataTransferRequest();
-            req.vendorId = "Phihong";
-            req.messageId = "ServerDomainName";
-            req.data = ServerDomainName;
-            return req;
-        }
-
-        /// <summary>
-        ///  下發全天電費
-        /// </summary>
-        public IRequest MakeAllDayUniformElectricBillRequest(decimal pricePerKWH)
-        {
-            DataTransferRequest req = new DataTransferRequest();
-            req.vendorId = "Phihong";
-            req.messageId = "AllDayUniformElectricBill";
-            req.data = System.Convert.ToString((double)pricePerKWH);
-            return req;
-        }
-
-        /// <summary>
-        ///  下發全天 48 時段電費
-        /// </summary>
-        public IRequest MakeAllDaySectionElectricBillRequest(List<double> sectionElectricBill)
-        {
-            DataTransferRequest req = new DataTransferRequest();
-            req.vendorId = "Phihong";
-            req.messageId = "AllDaySectionElectricBill";
-            req.data = JsonConvert.SerializeObject(sectionElectricBill);
-
-            return req;
-        }
-
-        /// <summary>
-        ///   下發充電服務費
-        /// </summary>
-        public IRequest MakeFeePerKWHRequest(decimal pricePerKWH)
-        {
-            DataTransferRequest req = new DataTransferRequest();
-            req.vendorId = "Phihong";
-            req.messageId = "FeePerKWH";
-            req.data = System.Convert.ToString((double)pricePerKWH);
-            return req;
-        }
-
-        /// <summary>
-        ///   下發帳戶餘額
-        /// </summary>
-        public IRequest MakeAccountBalanceRequest(string uniqueId, decimal balance, int VehicleType)
-        {
-            DataTransferRequest req = new DataTransferRequest();
-            req.vendorId = "Phihong";
-            req.messageId = "AccountBalance";
-
-            AccountBalance account = new AccountBalance();
-            account.uniqueId = uniqueId;
-            account.balance = (double)balance;
-            account.VehicleType = VehicleType;
-            req.data = JsonConvert.SerializeObject(account);
-            return req;
-        }
-
-        /// <summary>
-        ///   下發定時充電資訊
-        /// </summary>
-        public IRequest MakeAutoChargeReservationRequest(AutoChargeReservation autoChargeReservationParam)
-        {
-            DataTransferRequest req = new DataTransferRequest();
-            req.vendorId = "Phihong";
-            req.messageId = "AutoChargeReservation";
-
-            req.data = JsonConvert.SerializeObject(autoChargeReservationParam);
-            return req;
-        }
-
-        /// <summary>
-        /// 
-        /// </summary>
-        /// <param name="gunNo"></param>
-        /// <param name="Type"></param>
-        /// <returns></returns>
-        public IRequest MakeCustomCommandRequest(int gunNo, int Type)
-        {
-            DataTransferRequest req = new DataTransferRequest();
-            req.vendorId = "Phihong";
-            req.messageId = "SetCustomCMD";
-
-            CustomCommand customCommandParam = new CustomCommand();
-            customCommandParam.connectorId = gunNo;
-            customCommandParam.CommandType = (Type == 18) ? OCPP_Packet.Packet.Status.CustomCommandType.QRCodeFlash : ((Type == 19) ? OCPP_Packet.Packet.Status.CustomCommandType.DisableCharger : OCPP_Packet.Packet.Status.CustomCommandType.EnableCharger);
-
-            req.data = JsonConvert.SerializeObject(customCommandParam);
-            return req;
-        }
-
-        #endregion DataTransfer
-    }
-}

+ 0 - 2556
OCPPServer/Handler/OCPPMessageHandler.cs

@@ -1,2556 +0,0 @@
-using Evcb.Domain.Model;
-using Evcb.Domain.mongo;
-using Evcb.Repository;
-using Evcb.Service;
-using Evcb.Utility;
-using Newtonsoft.Json;
-using Newtonsoft.Json.Linq;
-using NLog;
-using OCPP_Packet.Packet.DataTransfer;
-using OCPPPacket.Packet.DataTransfer;
-using OCPPPacket.Packet.Feature;
-using OCPPPacket.Packet.Feature.Core;
-using OCPPPacket.Packet.Feature.FirmwareManagement;
-using OCPPPacket.Packet.Feature.LocalAuthListManagement;
-using OCPPPacket.Packet.Feature.RemoteTrigger;
-using OCPPPacket.Packet.Feature.Reservation;
-using OCPPPacket.Packet.Feature.SmartCharging;
-using OCPPPacket.Packet.Messages;
-using OCPPPacket.Packet.Messages.Basic;
-using OCPPPacket.Packet.Messages.Core;
-using OCPPPacket.Packet.Messages.FirmwareManagement;
-using OCPPPacket.Packet.Messages.LocalAuthListManagement;
-using OCPPPacket.Packet.Messages.RemoteTrigger;
-using OCPPPacket.Packet.Messages.Reservation;
-using OCPPPacket.Packet.Messages.SmartCharging;
-using OCPPPacket.Packet.Status;
-using OCPPServer.Common;
-using OCPPServer.Protocol;
-using Packet.Cmd;
-using System;
-using System.Collections.Generic;
-using System.Configuration;
-using System.Data.Entity;
-using System.IO;
-using System.Linq;
-using System.Net;
-using System.Net.Http;
-using System.Threading.Tasks;
-
-namespace OCPPServer.Handler
-{
-    public class OCPPMessageHandler
-    {
-        private ILogger logger = NLog.LogManager.GetCurrentClassLogger();
-        private FeatureHandler featureHandler;
-
-        //private CmdHelper CmdHelper;
-        private List<string> _cmd202lst = new List<string>();
-
-        private static readonly Object _clientQueue = new object();
-
-        static private MakeConfirmationHandler makeConfirmation = new MakeConfirmationHandler();
-        static private MakeRequestHandler makeRequest = new MakeRequestHandler();
-
-        private string ApiUrl { get; set; }
-
-        //設定OCPP Message Constant
-        private const int INDEX_MESSAGEID = 0;
-
-        private const int TYPENUMBER_CALL = 2;
-        private const int TYPENUMBER_CALLRESULT = 3;
-        private const int TYPENUMBER_CALLERROR = 4;
-
-        private const int INDEX_CALL_ACTION = 2;
-        private const int INDEX_CALL_PAYLOAD = 3;
-        private const int INDEX_CALLRESULT_PAYLOAD = 2;
-        private const int INDEX_CALLERROR_ERRORCODE = 2;
-        private const int INDEX_CALLERROR_DESCRIPTION = 3;
-        private const int INDEX_CALLERROR_PAYLOAD = 4;
-        private const int INDEX_UNIQUEID = 1;
-
-        /// <summary>
-        /// 初始化 OCPPMessageHandler Class
-        /// </summary>
-        public OCPPMessageHandler()
-        {
-            this.featureHandler = new FeatureHandler();
-            ApiUrl = ConfigurationManager.AppSettings.Get("ApiUrl");
-
-            #region Core
-
-            //加入core feature
-            featureHandler.AddFeatureProfile(new AuthorizeFeature());
-            featureHandler.AddFeatureProfile(new BootNotificationFeature());
-            featureHandler.AddFeatureProfile(new ChangeAvailabilityFeature());
-            featureHandler.AddFeatureProfile(new ChangeConfigurationFeature());
-            featureHandler.AddFeatureProfile(new ClearCacheFeature());
-            featureHandler.AddFeatureProfile(new DataTransferFeature());
-            featureHandler.AddFeatureProfile(new GetConfigurationFeature());
-            featureHandler.AddFeatureProfile(new HeartbeatFeature());
-            featureHandler.AddFeatureProfile(new StartTransactionFeature());
-            featureHandler.AddFeatureProfile(new StatusNotificationFeature());
-            featureHandler.AddFeatureProfile(new MeterValuesFeature());
-            featureHandler.AddFeatureProfile(new RemoteStartTransactionFeature());
-            featureHandler.AddFeatureProfile(new RemoteStopTransactionFeature());
-            featureHandler.AddFeatureProfile(new ResetFeature());
-            featureHandler.AddFeatureProfile(new StopTransactionFeature());
-            featureHandler.AddFeatureProfile(new UnlockConnectorFeature());
-
-            #endregion Core
-
-            #region FirmwareManagement
-
-            //加入FirmwareManagement feature
-            featureHandler.AddFeatureProfile(new GetDiagnosticsFeature());
-            featureHandler.AddFeatureProfile(new DiagnosticsStatusNotificationFeature());
-            featureHandler.AddFeatureProfile(new FirmwareStatusNotificationFeature());
-            featureHandler.AddFeatureProfile(new UpdateFirmwareFeature());
-
-            #endregion FirmwareManagement
-
-            #region LocalAuthListManagement
-
-            //加入LocalAuthListManagement feature
-            featureHandler.AddFeatureProfile(new GetLocalListVersionFeature());
-            featureHandler.AddFeatureProfile(new SendLocalListFeature());
-
-            #endregion LocalAuthListManagement
-
-            #region RemoteTrigger
-
-            //加入RemoteTrigger feature
-            featureHandler.AddFeatureProfile(new TriggerMessageFeature());
-
-            #endregion RemoteTrigger
-
-            #region Reservation
-
-            //加入Reservation feature
-            featureHandler.AddFeatureProfile(new CancelReservationFeature());
-            featureHandler.AddFeatureProfile(new ReserveNowFeature());
-
-            #endregion Reservation
-
-            #region SmartCharging
-
-            //加入SmartCharging feature
-            featureHandler.AddFeatureProfile(new ClearChargingProfileFeature());
-            featureHandler.AddFeatureProfile(new GetCompositeScheduleFeature());
-            featureHandler.AddFeatureProfile(new SetChargingProfileFeature());
-
-            #endregion SmartCharging
-        }
-
-        /// <summary>
-        /// 解析message type,歸類為Call Message 或 CALLRESULT Message或 CALLERROR Message
-        /// </summary>
-        /// <param name="message">OCPP Message</param>
-        /// <returns></returns>
-        public BaseMessage Parse(string message)
-        {
-            const int INDEX_MESSAGEID = 0;
-            const int TYPENUMBER_CALL = 2;
-            const int TYPENUMBER_CALLRESULT = 3;
-            const int TYPENUMBER_CALLERROR = 4;
-
-            const int INDEX_CALL_ACTION = 2;
-            const int INDEX_CALL_PAYLOAD = 3;
-            const int INDEX_CALLRESULT_PAYLOAD = 2;
-            const int INDEX_CALLERROR_ERRORCODE = 2;
-            const int INDEX_CALLERROR_DESCRIPTION = 3;
-            const int INDEX_CALLERROR_PAYLOAD = 4;
-            const int INDEX_UNIQUEID = 1;
-
-            try
-            {
-                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();
-                            //假如沒有error details ,判斷CallError Message的payload 是 an empty object \{}.
-                            if (array.Count > INDEX_CALLERROR_PAYLOAD)
-                            {
-                                callError.payload = 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("Error=>Communicator.Parse: {0}", ex.ToString()));
-            }
-        }
-
-        /// <summary>
-        /// 解壓縮Payload為OCPP Message
-        /// </summary>
-        /// <param name="payload">OCPP Message Payload</param>
-        /// <param name="type">OCPP Message Type</param>
-        /// <returns></returns>
-        private object UnpackPayload(object payload, Type type)
-        {
-            var ocppMessage = JsonConvert.DeserializeObject(payload.ToString(), type);
-            return ocppMessage;
-        }
-
-        /// <summary>
-        /// 壓縮OCPP Message為Payload
-        /// </summary>
-        /// <param name="ocppMessage"></param>
-        /// <returns></returns>
-        private object PackPayload(object ocppMessage)
-        {
-            return JsonConvert.SerializeObject(ocppMessage);
-        }
-
-        /// <summary>
-        /// 透過OCPP Message 的UniqueId,從client queue 取出之前後台送出的request, 透過取出的request找出相對應的confirmation type
-        /// </summary>
-        /// <param name="queue">Messgae queue</param>
-        /// <param name="uniqueId">OCPP Message UniqueId</param>
-        /// <param name="requestObj">OCPP Request Message</param>
-        /// <returns></returns>
-        private Type GetConfirmationType(ref Queue queue, string uniqueId, out IRequest requestObj)
-        {
-            IRequest request = queue.RestoreRequest(uniqueId);
-            if (request == null)
-            {
-                requestObj = null;
-                return null;
-            }
-            Feature feature = this.featureHandler.FindFeatureByRequest(request.GetType());
-            requestObj = request;
-            return feature.GetConfirmationType();
-        }
-
-        //處理OCPP errorCode, 相對應到資料庫ChargingRecordStatus的Warning欄位
-        //DC:
-        //ConnectorLockFailure: 90000,EVCommunicationError: 90001,GroundFailure: 90002,HighTemperature: 90003,
-        //InternalError: 90004,LocalListConflict: 90005,NoError: 90006,OtherError: 90007,OverCurrentFailure: 90008,
-        //OverVoltage: 90009, PowerMeterFailure: 90010,PowerSwitchFailure: 90011,ReaderFailure: 90012,ResetFailure: 90013,
-        //UnderVoltage: 90014, WeakSignal: 90015
-        //AC:
-        //ConnectorLockFailure: 110000,EVCommunicationError: 110001,GroundFailure: 110002,HighTemperature: 110003,
-        //InternalError: 110004,LocalListConflict: 110005,NoError: 110006,OtherError: 110007,OverCurrentFailure: 110008,
-        //OverVoltage: 110009, PowerMeterFailure: 110010,PowerSwitchFailure: 110011,ReaderFailure: 110012,ResetFailure: 110013,
-        //UnderVoltage: 110014, WeakSignal: 110015
-        /// <summary>
-        /// 處理 Error Code
-        /// </summary>
-        /// <param name="typeAC"></param>
-        /// <param name="errorCode"></param>
-        /// <returns></returns>
-        private int ProcessErrorCode(bool typeAC, ChargePointErrorCode errorCode)
-        {
-            int warning = 0;
-            switch (errorCode)
-            {
-                case ChargePointErrorCode.ConnectorLockFailure:
-                    if (typeAC == true)
-                        warning = 110000; // AC
-                    else
-                        warning = 90000;  // DC
-                    break;
-
-                case ChargePointErrorCode.EVCommunicationError:
-                    if (typeAC == true)
-                        warning = 110001; // AC
-                    else
-                        warning = 90001;  // DC
-                    break;
-
-                case ChargePointErrorCode.GroundFailure:
-                    if (typeAC == true)
-                        warning = 110002; // AC
-                    else
-                        warning = 90002;  // DC
-                    break;
-
-                case ChargePointErrorCode.HighTemperature:
-                    if (typeAC == true)
-                        warning = 110003; // AC
-                    else
-                        warning = 90003;  // DC
-                    break;
-
-                case ChargePointErrorCode.InternalError:
-                    if (typeAC == true)
-                        warning = 110004; // AC
-                    else
-                        warning = 90004;  // DC
-                    break;
-
-                case ChargePointErrorCode.LocalListConflict:
-                    if (typeAC == true)
-                        warning = 110005; // AC
-                    else
-                        warning = 90005;  // DC
-                    break;
-
-                case ChargePointErrorCode.NoError:
-                    if (typeAC == true)
-                        warning = 110006; // AC
-                    else
-                        warning = 90006;  // DC
-                    break;
-
-                case ChargePointErrorCode.OtherError:
-                    if (typeAC == true)
-                        warning = 110007; // AC
-                    else
-                        warning = 90007;  // DC
-                    break;
-
-                case ChargePointErrorCode.OverCurrentFailure:
-                    if (typeAC == true)
-                        warning = 110008; // AC
-                    else
-                        warning = 90008;  // DC
-                    break;
-
-                case ChargePointErrorCode.OverVoltage:
-                    if (typeAC == true)
-                        warning = 110009; // AC
-                    else
-                        warning = 90009;  // DC
-                    break;
-
-                case ChargePointErrorCode.PowerMeterFailure:
-                    if (typeAC == true)
-                        warning = 110010; // AC
-                    else
-                        warning = 90010;  // DC
-                    break;
-
-                case ChargePointErrorCode.PowerSwitchFailure:
-                    if (typeAC == true)
-                        warning = 110011; // AC
-                    else
-                        warning = 90011;  // DC
-                    break;
-
-                case ChargePointErrorCode.ReaderFailure:
-                    if (typeAC == true)
-                        warning = 110012; // AC
-                    else
-                        warning = 90012;  // DC
-                    break;
-
-                case ChargePointErrorCode.ResetFailure:
-                    if (typeAC == true)
-                        warning = 110013; // AC
-                    else
-                        warning = 90013;  // DC
-                    break;
-
-                case ChargePointErrorCode.UnderVoltage:
-                    if (typeAC == true)
-                        warning = 110014; // AC
-                    else
-                        warning = 90014;  // DC
-                    break;
-
-                case ChargePointErrorCode.WeakSignal:
-                    if (typeAC == true)
-                        warning = 110015; // AC
-                    else
-                        warning = 90015;  // DC
-                    break;
-
-                default:
-                    break;
-            }
-            return warning;
-        }
-
-        /// <summary>
-        /// 產生 random 20 character alphanumeric strings
-        /// </summary>
-        /// <returns></returns>
-        private string GenerateRandomString()
-        {
-            var chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
-            var random = new Random();
-            var list = Enumerable.Repeat(0, 20).Select(x => chars[random.Next(chars.Length)]);
-            string finalString = string.Join("", list);
-            return finalString;
-        }
-
-        /// <summary>
-        /// 處理 Server Command
-        /// </summary>
-        /// <param name="cmd">server command</param>
-        /// <param name="machineCustomId">電樁樁號</param>
-        /// <param name="queue">Messgae queue</param>
-        /// <param name="configurationKey">Configuration Key</param>
-        /// <param name="reservationId">預約卡號</param>
-        /// <param name="chargingProfileId">充電檔案</param>
-        /// <param name="messageType">Message Type</param>
-        /// <param name="db">Data Base Entity</param>
-        /// <returns></returns>
-        public string HandleServerCommand(BaseCmd cmd, string machineCustomId, ref Queue queue, ref List<KeyValueType> configurationKey, int reservationId, int chargingProfileId, out string messageType, PhihongDbContext db)
-        {
-            string result = string.Empty;
-            messageType = string.Empty;
-            //設定心跳時間和心跳的timeout次數
-            if (cmd is Cmd1001)
-            {
-                var c = cmd as Cmd1001;
-                if (c.ParamIndex == 21)
-                {
-                    var machine = db.Machine.Where(x => x.CustomId == machineCustomId).AsNoTracking().FirstOrDefault();
-                    if (machine != null)
-                    {
-                        IRequest req = MakeRequestHandler.MakeChangeConfigurationRequest("HeartbeatInterval", machine.HeartbeatInterval.ToString());
-                        string uuid = String.Empty;
-                        lock (_clientQueue)
-                        {
-                            uuid = queue.store(req);
-                        }
-                        messageType = "ChangeConfiguration Request(HeartbeatInterval)";
-                        result = GenerateCall(uuid, Actions.ChangeConfiguration.ToString(), req);
-                    }
-                }
-            }
-
-            //校時
-            if (cmd is Cmd1003)
-            {
-                var c = cmd as Cmd1003;
-                var machine = db.Machine.Where(x => x.CustomId == machineCustomId).AsNoTracking().FirstOrDefault();
-
-                if (machine != null)
-                {
-                    //確認發送是校時參數,就修改校時時間為封包送出時間
-                    if (c.ParamIndex == 2)
-                    {
-                        IRequest req = MakeRequestHandler.MakeChangeConfigurationRequest("HeartbeatInterval", "1");
-                        string uuid = String.Empty;
-                        lock (_clientQueue)
-                        {
-                            uuid = queue.store(req);
-                        }
-
-                        messageType = "ChangeConfiguration Request(HeartbeatInterval)";
-                        result = GenerateCall(uuid, Actions.ChangeConfiguration.ToString(), req);
-                    }
-
-                    //確認發送設定Server Domain Name
-                    if (c.ParamIndex == 11)
-                    {
-                        //OCPP 不支援Server Domain Name
-                        messageType = "Server Domain Name Request";
-                        result = String.Empty;
-                    }
-
-                    //確認發送設定樁的夥伴代碼
-                    if (c.ParamIndex == 12)
-                    {
-                        IRequest req = makeRequest.MakeSendPartnerPoleIdRequest(machine.PartnerPoleId);
-                        string uuid = String.Empty;
-                        lock (_clientQueue)
-                        {
-                            uuid = queue.store(req);
-                        }
-
-                        messageType = "DataTransfer Request(SendPartnerPoleId)";
-                        result = GenerateCall(uuid, Actions.DataTransfer.ToString(), req);
-                    }
-                }
-            }
-
-            //Remote結束充電
-            if (cmd is Cmd1005)
-            {
-                var c = cmd as Cmd1005;
-                //int transactionId = 0;
-                var machine = db.Machine.Where(x => x.CustomId == machineCustomId).AsNoTracking().FirstOrDefault();
-
-                //確認發送停止充電
-                if (c.ParamIndex == 2)
-                {
-                    if (machine != null)
-                    {
-                        var gunStatusNow = db.MachineGun.Where(x => x.GunSerNo == c.GunSerNo
-                         && x.MachineId == machine.Id).AsNoTracking().FirstOrDefault();
-
-                        //如果是 DC且狀態等於 2(充電中)  或是 AC或 HMI 且在充電中
-                        if ((machine.MachineModelId == 2 && gunStatusNow.Status == 2) || (machine.MachineModelId != 2 && (gunStatusNow.Status == 2 || gunStatusNow.Status == 3)))
-                        {
-                            var record = db.ChargingRecord.Where(x => x.GunSerNo == c.GunSerNo
-                            && x.MachineId == machine.Id
-                            && x.ClientStartChargingDateTime == null
-                            && x.ClientEndChargingDateTime == null
-                            && x.EndChargingDateTime == null
-                            && x.StartChargingDateTime != null
-                            && x.ChargingSerNo == gunStatusNow.ChargingSerNo).AsNoTracking().FirstOrDefault();
-                            var chargingTransaction = db.ChargingTransaction.Where(x => x.ChargingRecordId == record.Id).AsNoTracking().FirstOrDefault();
-
-                            IRequest req = makeRequest.MakeRemoteStopTransactionRequest(chargingTransaction.TransactionId);
-                            //client.RemoteCharging = true; /// Remote充電
-                            string uuid = String.Empty;
-                            lock (_clientQueue)
-                            {
-                                uuid = queue.store(req);
-                            }
-
-                            messageType = "RemoteStopTransaction Request";
-                            result = GenerateCall(uuid, Actions.RemoteStopTransaction.ToString(), req);
-                        }
-                    }
-                }
-
-                //確認發送停止預約
-                if (c.ParamIndex == 10)
-                {
-                    if (machine != null)
-                    {
-                        IRequest req = makeRequest.MakeCancelReservationRequest(reservationId);
-                        //client.RemoteCharging = true; /// Remote充電
-                        string uuid = String.Empty;
-                        lock (_clientQueue)
-                        {
-                            uuid = queue.store(req);
-                        }
-
-                        messageType = "CancelReservation Request";
-                        result = GenerateCall(uuid, Actions.CancelReservation.ToString(), req);
-                    }
-                }
-
-                //確認發送Psu Log To Ftp (發送 GetDiagnostics 訊息)
-                if (c.ParamIndex == 17)
-                {
-                    if (machine != null)
-                    {
-                        IRequest req = MakeRequestHandler.MakeGetDiagnosticsRequest(machine.AC);
-                        string uuid = String.Empty;
-                        lock (_clientQueue)
-                        {
-                            uuid = queue.store(req);
-                        }
-
-                        messageType = "GetDiagnostics Request";
-                        result = GenerateCall(uuid, Actions.GetDiagnostics.ToString(), req);
-                    }
-                }
-
-                /// 18: QRCode Flash 效果 , 19: 禁用充电桩, 20: 启用充电桩
-                if (c.ParamIndex == 18 || c.ParamIndex == 19 || c.ParamIndex == 20)
-                {
-                    if (machine != null)
-                    {
-                        var type = Convert.ToInt32(c.ParamIndex);
-                        int gunNo = 0;
-                        switch (type)
-                        {
-                            //QRCode Flash 效果
-                            case 18:
-
-                                gunNo = c.GunSerNo + 1;
-                                break;
-
-                            // 19: 禁用充电桩
-                            case 19:
-                                gunNo = 0;
-                                break;
-
-                            //20: 启用充电桩
-                            case 20:
-                                gunNo = 0;
-                                break;
-                        }
-
-                        IRequest req = makeRequest.MakeCustomCommandRequest(gunNo, type);
-                        string uuid = String.Empty;
-                        lock (_clientQueue)
-                        {
-                            uuid = queue.store(req);
-                        }
-
-                        messageType = "DataTransfer Request(CustomCommand)";
-                        result = GenerateCall(uuid, Actions.DataTransfer.ToString(), req);
-                    }
-                }
-            }
-
-            //Remote啟動充電 / 預約充電
-            if (cmd is Cmd1007)
-            {
-                var c = cmd as Cmd1007;
-                if (c.StartChargingType == 0) // 0:实时充电
-                {
-                    var machine = db.Machine.Where(x => x.CustomId == machineCustomId).AsNoTracking().FirstOrDefault();
-                    var memberQuery = db.MemberCharging.Where(x => x.MemberId == c.ReservationCardNum).AsNoTracking().FirstOrDefault();
-                    string randomString = string.Empty;
-                    if (memberQuery == null) // member id不存在,才產生新的SelfDefinedId
-                    {
-                        randomString = GenerateRandomString();
-                        var selfDefinedIdQuery = db.MemberCharging.Where(x => x.SelfDefinedId == randomString).AsNoTracking().FirstOrDefault();
-                        while (selfDefinedIdQuery != null)
-                        {
-                            randomString = GenerateRandomString();
-                            selfDefinedIdQuery = db.MemberCharging.Where(x => x.SelfDefinedId == randomString).AsNoTracking().FirstOrDefault();
-                        }
-
-                        //將 random 20 character alphanumeric strings 與 MemberId 儲存到 Member 表格,之後處理Remote充電會透過Member表格取得 MemberId
-                        MemberMapping remotemember = new MemberMapping();
-                        remotemember.MemberId = c.ReservationCardNum;
-                        remotemember.SelfDefinedId = randomString;
-                        remotemember.CustomerId = machine.CustomerId;
-                        remotemember.CreatedOn = DateTime.Now;
-                        db.MemberCharging.Add(remotemember);
-                        db.SaveChanges();
-                    }
-                    else
-                    {
-                        randomString = memberQuery.SelfDefinedId;
-                    }
-
-                    //處理Remote充電命令,並且發送給電樁
-                    IRequest req = makeRequest.MakeRemoteStartTransactionRequest((int)c.GunSerNo + 1, randomString);
-                    string uuid = String.Empty;
-                    lock (_clientQueue)
-                    {
-                        uuid = queue.store(req);
-                    }
-
-                    messageType = "RemoteStartTransaction Request";
-                    result = GenerateCall(uuid, Actions.RemoteStartTransaction.ToString(), req);
-                }
-
-                if (c.StartChargingType == 1) // 1: 定時啟動充電
-                {
-                    var machine = db.Machine.Where(x => x.CustomId == machineCustomId).AsNoTracking().FirstOrDefault();
-                    var memberQuery = db.MemberCharging.Where(x => x.MemberId == c.ReservationCardNum).AsNoTracking().FirstOrDefault();
-                    string randomString = string.Empty;
-                    if (memberQuery == null) // member id不存在,才產生新的SelfDefinedId
-                    {
-                        randomString = GenerateRandomString();
-                        var selfDefinedIdQuery = db.MemberCharging.Where(x => x.SelfDefinedId == randomString).AsNoTracking().FirstOrDefault();
-                        while (selfDefinedIdQuery != null)
-                        {
-                            randomString = GenerateRandomString();
-                            selfDefinedIdQuery = db.MemberCharging.Where(x => x.SelfDefinedId == randomString).AsNoTracking().FirstOrDefault();
-                        }
-
-                        //將 random 20 character alphanumeric strings 與 MemberId 儲存到 Member 表格,之後處理Remote充電會透過Member表格取得 MemberId
-                        MemberMapping remotemember = new MemberMapping();
-                        remotemember.MemberId = c.ReservationCardNum;
-                        remotemember.SelfDefinedId = randomString;
-                        remotemember.CustomerId = machine.CustomerId;
-                        remotemember.CreatedOn = DateTime.Now;
-                        db.MemberCharging.Add(remotemember);
-                        db.SaveChanges();
-                    }
-                    else
-                    {
-                        randomString = memberQuery.SelfDefinedId;
-                    }
-
-                    AutoChargeReservation autoChargeReservation = new AutoChargeReservation();
-                    autoChargeReservation.connectorId = (int)c.GunSerNo + 1;
-                    autoChargeReservation.chargingStrategy = (ChargingStrategy)c.ChargingStrategy;
-                    autoChargeReservation.chargingStrategyParam = (double)c.ChargingStrategyParam;
-                    autoChargeReservation.startChargingDateTime = (DateTime)c.StartChargingDateTime;
-                    autoChargeReservation.idTag = randomString;
-                    autoChargeReservation.accountBalance = (double)c.AccountBalance.RealValue;
-                    autoChargeReservation.memberName = c.MemberName;
-                    autoChargeReservation.vehicleType = (int)c.VehicleType;
-                    autoChargeReservation.reservationId = reservationId;
-
-                    //處理定時啟動充電,並且發送給電樁
-                    IRequest req = makeRequest.MakeAutoChargeReservationRequest(autoChargeReservation);
-                    string uuid = String.Empty;
-                    lock (_clientQueue)
-                    {
-                        uuid = queue.store(req);
-                    }
-
-                    messageType = "DataTransfer Request(AutoChargeReservation)";
-                    result = GenerateCall(uuid, Actions.DataTransfer.ToString(), req);
-                }
-
-                if (c.StartChargingType == 2) // 2:预约充电
-                {
-                    var machine = db.Machine.Where(x => x.CustomId == machineCustomId).AsNoTracking().FirstOrDefault();
-                    var memberQuery = db.MemberCharging.Where(x => x.MemberId == c.ReservationCardNum).AsNoTracking().FirstOrDefault();
-                    string randomString = string.Empty;
-                    if (memberQuery == null) // member id不存在,才產生新的SelfDefinedId
-                    {
-                        randomString = GenerateRandomString();
-                        var selfDefinedIdQuery = db.MemberCharging.Where(x => x.SelfDefinedId == randomString).AsNoTracking().FirstOrDefault();
-                        while (selfDefinedIdQuery != null)
-                        {
-                            randomString = GenerateRandomString();
-                            selfDefinedIdQuery = db.MemberCharging.Where(x => x.SelfDefinedId == randomString).AsNoTracking().FirstOrDefault();
-                        }
-
-                        //將 random 20 character alphanumeric strings 與 MemberId 儲存到 Member 表格,之後處理Remote充電會透過Member表格取得 MemberId
-                        MemberMapping remotemember = new MemberMapping();
-                        remotemember.MemberId = c.ReservationCardNum;
-                        remotemember.SelfDefinedId = randomString;
-                        remotemember.CustomerId = machine.CustomerId;
-                        remotemember.CreatedOn = DateTime.Now;
-                        db.MemberCharging.Add(remotemember);
-                        db.SaveChanges();
-                    }
-                    else
-                    {
-                        randomString = memberQuery.SelfDefinedId;
-                    }
-
-                    var item = configurationKey.Where(a => a.key == "ReserveConnectorZeroSupported").FirstOrDefault();
-                    IRequest req = makeRequest.MakeReserveNowRequest((int)c.GunSerNo + 1, randomString, Convert.ToBoolean(item.value), reservationId);
-                    string uuid = String.Empty;
-                    lock (_clientQueue)
-                    {
-                        uuid = queue.store(req);
-                    }
-
-                    messageType = "ReserveNow Request";
-                    result = GenerateCall(uuid, Actions.ReserveNow.ToString(), req);
-                }
-            }
-
-            //后台服务器下发充电桩本地验证卡号名单命令
-            if (cmd is Cmd1009)
-            {
-                var c = cmd as Cmd1009;
-                string sLine = "";
-                if (!Directory.Exists(System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "UploadFiles")))
-                {
-                    Directory.CreateDirectory(System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "UploadFiles"));
-                }
-
-                string fileName = System.IO.Path.GetFileName(c.Url);
-                string destFilePath = System.IO.Path.Combine(System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "UploadFiles/"), fileName);
-                if (!Directory.Exists(destFilePath))
-                {
-                    List<Task> tList = new List<Task>();
-                    //downloading
-                    using (WebClient webClient = new WebClient())
-                    {
-                        webClient.Credentials = CredentialCache.DefaultNetworkCredentials;
-                        if (c.Url.Contains("http") == false)
-                        {
-                            c.Url = "http://" + c.Url;
-                        }
-                        tList.Add(Task.Run(() => webClient.DownloadFileTaskAsync(new Uri(c.Url), destFilePath)));
-                    }
-                    Task.WaitAll(tList.ToArray());
-                }
-
-                if (File.Exists(destFilePath))
-                {
-                    using (FileStream file = new FileStream(destFilePath, FileMode.Open, FileAccess.Read))
-                    {
-                        using (StreamReader srReader = new StreamReader(file))
-                        {
-                            sLine = srReader.ReadToEnd();
-                        }
-                    }
-                }
-
-                List<OCPPServer.Common.LocalAuthorization> localAuthorizationList = JsonConvert.DeserializeObject<List<OCPPServer.Common.LocalAuthorization>>(sLine);
-
-                IRequest req = MakeRequestHandler.MakeSendLocalListRequest(localAuthorizationList, c.VersionNo, c.Type);
-                string uuid = String.Empty;
-                lock (_clientQueue)
-                {
-                    uuid = queue.store(req);
-                }
-
-                messageType = "SendLocalListRequest Request";
-                result = GenerateCall(uuid, Actions.SendLocalList.ToString(), req);
-            }
-
-            if (cmd is Cmd1011)
-            {
-                IRequest req = MakeRequestHandler.MakeGetLocalListVersionRequest();
-                string uuid = String.Empty;
-                lock (_clientQueue)
-                {
-                    uuid = queue.store(req);
-                }
-
-                messageType = "GetLocalListVersion Request";
-                result = GenerateCall(uuid, Actions.GetLocalListVersion.ToString(), req);
-            }
-
-            if (cmd is Cmd1013)
-            {
-                var c = cmd as Cmd1013;
-                int TransactionId = 0;
-
-                var machine = db.Machine.Where(x => x.CustomId == machineCustomId).AsNoTracking().FirstOrDefault();
-
-                var gunStatusNow = db.MachineGun.Where(y => y.GunSerNo == c.GunSerNo
-                                     && y.MachineId == machine.Id).AsNoTracking().FirstOrDefault();
-
-                //充電目的檔為 TxProfile
-                if (gunStatusNow != null && c.ChargingProfilePurpose == 2)
-                {
-                    //確認電樁在充電中
-                    if (gunStatusNow.Status == 2 || gunStatusNow.Status == 3)
-                    {
-                        var chargingRecord = db.ChargingRecord.Where(x => x.ChargingSerNo == gunStatusNow.ChargingSerNo).AsNoTracking().FirstOrDefault();
-
-                        if (chargingRecord != null)
-                        {
-                            var chargingTransaction = db.ChargingTransaction.Where(x => x.MachineId == machine.Id
-                                                        && x.GunSerNo == c.GunSerNo
-                                                        && x.ChargingRecordId == chargingRecord.Id).AsNoTracking().FirstOrDefault();
-
-                            if (chargingTransaction != null)
-                            {
-                                TransactionId = chargingTransaction.TransactionId;
-                            }
-                        }
-
-                    }
-                }
-
-                IRequest req = MakeRequestHandler.MakeSetChargingProfileRequest(cmd, TransactionId);
-
-                lock (_clientQueue)
-                {
-                    queue.store(req, c.UUID);
-                }
-
-                messageType = "SetChargingProfile Request";
-                result = GenerateCall(c.UUID, Actions.SetChargingProfile.ToString(), req);
-            }
-
-            if (cmd is Cmd1015)
-            {
-                var c = cmd as Cmd1015;
-                IRequest req = makeRequest.MakeClearChargingProfileRequest(cmd);
-
-                lock (_clientQueue)
-                {
-                    queue.store(req, c.UUID);
-                }
-
-                messageType = "ClearChargingProfile Request";
-                result = GenerateCall(c.UUID, Actions.ClearChargingProfile.ToString(), req);
-            }
-
-            if (cmd is Cmd1017)
-            {
-                var c = cmd as Cmd1017;
-
-                IRequest req = MakeRequestHandler.MakeSendChargingConfigRequest(cmd);
-
-                lock (_clientQueue)
-                {
-                    queue.store(req, c.UUID);
-                }
-
-                messageType = "SetChargingConfig Request";
-                result = GenerateCall(c.UUID, Actions.DataTransfer.ToString(), req);
-            }
-
-            if (cmd is Cmd1019)
-            {
-                var c = cmd as Cmd1019;
-
-                IRequest req = MakeRequestHandler.MakeSendGetChargingConfigRequest(cmd);
-
-                lock (_clientQueue)
-                {
-                    queue.store(req, c.UUID);
-                }
-
-                messageType = "GetChargingConfig Request";
-                result = GenerateCall(c.UUID, Actions.DataTransfer.ToString(), req);
-            }
-
-            //設定每度費用
-            if (cmd is Cmd2301)
-            {
-                var c = cmd as Cmd2301;
-                IRequest req = makeRequest.MakeAllDayUniformElectricBillRequest(c.PricePerKWH.RealValue);
-                string uuid = String.Empty;
-                lock (_clientQueue)
-                {
-                    uuid = queue.store(req);
-                }
-
-                messageType = "DataTransfer Request(AllDayUniformElectricBill)";
-                result = GenerateCall(uuid, Actions.DataTransfer.ToString(), req);
-            }
-
-            //設定區段費用
-            if (cmd is Cmd2303)
-            {
-                var c = cmd as Cmd2303;
-                List<double> sectionElectricBill = new List<double>();
-                sectionElectricBill.Add((double)c.Section0000_0030.RealValue);
-                sectionElectricBill.Add((double)c.Section0030_0100.RealValue);
-                sectionElectricBill.Add((double)c.Section0100_0130.RealValue);
-                sectionElectricBill.Add((double)c.Section0130_0200.RealValue);
-                sectionElectricBill.Add((double)c.Section0200_0230.RealValue);
-                sectionElectricBill.Add((double)c.Section0230_0300.RealValue);
-                sectionElectricBill.Add((double)c.Section0300_0330.RealValue);
-                sectionElectricBill.Add((double)c.Section0330_0400.RealValue);
-                sectionElectricBill.Add((double)c.Section0400_0430.RealValue);
-                sectionElectricBill.Add((double)c.Section0430_0500.RealValue);
-                sectionElectricBill.Add((double)c.Section0500_0530.RealValue);
-                sectionElectricBill.Add((double)c.Section0530_0600.RealValue);
-                sectionElectricBill.Add((double)c.Section0600_0630.RealValue);
-                sectionElectricBill.Add((double)c.Section0630_0700.RealValue);
-                sectionElectricBill.Add((double)c.Section0700_0730.RealValue);
-                sectionElectricBill.Add((double)c.Section0730_0800.RealValue);
-                sectionElectricBill.Add((double)c.Section0800_0830.RealValue);
-                sectionElectricBill.Add((double)c.Section0830_0900.RealValue);
-                sectionElectricBill.Add((double)c.Section0900_0930.RealValue);
-                sectionElectricBill.Add((double)c.Section0930_1000.RealValue);
-                sectionElectricBill.Add((double)c.Section1000_1030.RealValue);
-                sectionElectricBill.Add((double)c.Section1030_1100.RealValue);
-                sectionElectricBill.Add((double)c.Section1100_1130.RealValue);
-                sectionElectricBill.Add((double)c.Section1130_1200.RealValue);
-                sectionElectricBill.Add((double)c.Section1200_1230.RealValue);
-                sectionElectricBill.Add((double)c.Section1230_1300.RealValue);
-                sectionElectricBill.Add((double)c.Section1300_1330.RealValue);
-                sectionElectricBill.Add((double)c.Section1330_1400.RealValue);
-                sectionElectricBill.Add((double)c.Section1400_1430.RealValue);
-                sectionElectricBill.Add((double)c.Section1430_1500.RealValue);
-                sectionElectricBill.Add((double)c.Section1500_1530.RealValue);
-                sectionElectricBill.Add((double)c.Section1530_1600.RealValue);
-                sectionElectricBill.Add((double)c.Section1600_1630.RealValue);
-                sectionElectricBill.Add((double)c.Section1630_1700.RealValue);
-                sectionElectricBill.Add((double)c.Section1700_1730.RealValue);
-                sectionElectricBill.Add((double)c.Section1730_1800.RealValue);
-                sectionElectricBill.Add((double)c.Section1800_1830.RealValue);
-                sectionElectricBill.Add((double)c.Section1830_1900.RealValue);
-                sectionElectricBill.Add((double)c.Section1900_1930.RealValue);
-                sectionElectricBill.Add((double)c.Section1930_2000.RealValue);
-                sectionElectricBill.Add((double)c.Section2000_2030.RealValue);
-                sectionElectricBill.Add((double)c.Section2030_2100.RealValue);
-                sectionElectricBill.Add((double)c.Section2100_2130.RealValue);
-                sectionElectricBill.Add((double)c.Section2130_2200.RealValue);
-                sectionElectricBill.Add((double)c.Section2200_2230.RealValue);
-                sectionElectricBill.Add((double)c.Section2230_2300.RealValue);
-                sectionElectricBill.Add((double)c.Section2300_2330.RealValue);
-                sectionElectricBill.Add((double)c.Section2330_2400.RealValue);
-                IRequest req = makeRequest.MakeAllDaySectionElectricBillRequest(sectionElectricBill);
-                string uuid = String.Empty;
-                lock (_clientQueue)
-                {
-                    uuid = queue.store(req);
-                }
-
-                messageType = "DataTransfer Request(AllDaySectionElectricBill)";
-                result = GenerateCall(uuid, Actions.DataTransfer.ToString(), req);
-            }
-
-            //設定每度服務費
-            if (cmd is Cmd2305)
-            {
-                var c = cmd as Cmd2305;
-                IRequest req = makeRequest.MakeFeePerKWHRequest(c.FeePerKWH.RealValue);
-                string uuid = String.Empty;
-                lock (_clientQueue)
-                {
-                    uuid = queue.store(req);
-                }
-
-                messageType = "DataTransfer Request(FeePerKWH)";
-                result = GenerateCall(uuid, Actions.DataTransfer.ToString(), req);
-            }
-
-            //ocpp cmd: MessageTrigger BootNotification
-            if (cmd is Cmd9001)
-            {
-                IRequest req = makeRequest.MakeTriggerMessageRequest(MessageTrigger.BootNotification, 1);
-                string uuid = String.Empty;
-                lock (_clientQueue)
-                {
-                    uuid = queue.store(req);
-                }
-                messageType = "TriggerMessage Request(BootNotification)";
-                result = GenerateCall(uuid, Actions.TriggerMessage.ToString(), req);
-            }
-
-            //ocpp cmd: MessageTrigger DiagnosticsStatusNotification
-            if (cmd is Cmd9003)
-            {
-                IRequest req = makeRequest.MakeTriggerMessageRequest(MessageTrigger.DiagnosticsStatusNotification, 1);
-                string uuid = String.Empty;
-                lock (_clientQueue)
-                {
-                    uuid = queue.store(req);
-                }
-                messageType = "TriggerMessage Request(DiagnosticsStatusNotification)";
-                result = GenerateCall(uuid, Actions.TriggerMessage.ToString(), req);
-            }
-
-            //ocpp cmd: MessageTrigger FirmwareStatusNotification
-            if (cmd is Cmd9005)
-            {
-                IRequest req = makeRequest.MakeTriggerMessageRequest(MessageTrigger.FirmwareStatusNotification, 1);
-                string uuid = String.Empty;
-                lock (_clientQueue)
-                {
-                    uuid = queue.store(req);
-                }
-                messageType = "TriggerMessage Request(FirmwareStatusNotification)";
-                result = GenerateCall(uuid, Actions.TriggerMessage.ToString(), req);
-            }
-
-            //ocpp cmd: MessageTrigger Heartbeat
-            if (cmd is Cmd9007)
-            {
-                IRequest req = makeRequest.MakeTriggerMessageRequest(MessageTrigger.Heartbeat, 1);
-                string uuid = String.Empty;
-                lock (_clientQueue)
-                {
-                    uuid = queue.store(req);
-                }
-                messageType = "TriggerMessage Request(Heartbeat)";
-                result = GenerateCall(uuid, Actions.TriggerMessage.ToString(), req);
-            }
-
-            //ocpp cmd: MessageTrigger MeterValues
-            if (cmd is Cmd9009)
-            {
-                IRequest req = makeRequest.MakeTriggerMessageRequest(MessageTrigger.MeterValues, 1);
-                string uuid = String.Empty;
-                lock (_clientQueue)
-                {
-                    uuid = queue.store(req);
-                }
-                messageType = "TriggerMessage Request(MeterValues)";
-                result = GenerateCall(uuid, Actions.TriggerMessage.ToString(), req);
-            }
-
-            //ocpp cmd: MessageTrigger StatusNotification
-            if (cmd is Cmd9011)
-            {
-                IRequest req = makeRequest.MakeTriggerMessageRequest(MessageTrigger.StatusNotification, 1);
-                string uuid = String.Empty;
-                lock (_clientQueue)
-                {
-                    uuid = queue.store(req);
-                }
-                messageType = "TriggerMessage Request(StatusNotification)";
-                result = GenerateCall(uuid, Actions.TriggerMessage.ToString(), req);
-            }
-
-            //ocpp cmd : SendLocalListRequest , GetLocalListVersion , OCPPUpdateFirmware
-            if (cmd is Cmd9013)
-            {
-                var c = cmd as Cmd9013;
-
-                //OCPP UpdateFirmware
-                if (c.ParamIndex == 4)
-                {
-                    var machine = db.Machine.Where(x => x.CustomId == machineCustomId).AsNoTracking().FirstOrDefault();
-
-                    IRequest req = MakeRequestHandler.MakeOCPPUpdateFirmwareRequest(@"http://");
-                    string uuid = String.Empty;
-                    lock (_clientQueue)
-                    {
-                        uuid = queue.store(req);
-                    }
-
-                    messageType = "OCPPUpdateFirmware Request";
-                    result = GenerateCall(uuid, Actions.UpdateFirmware.ToString(), req);
-                }
-            }
-
-            //ocpp cmd : SetChargingProfile
-            if (cmd is Cmd9015)
-            {
-                var c = cmd as Cmd9015;
-                string purpose = System.Text.Encoding.ASCII.GetString(c.ParamByteList.ToArray()).Trim('\0');
-                var machine = db.Machine.Where(x => x.CustomId == machineCustomId).AsNoTracking().FirstOrDefault();
-
-                IRequest req = MakeRequestHandler.MakeSetChargingProfileRequest(0, 0, chargingProfileId, purpose);
-                string uuid = String.Empty;
-                lock (_clientQueue)
-                {
-                    uuid = queue.store(req);
-                }
-
-                messageType = "SetChargingProfile Request";
-                result = GenerateCall(uuid, Actions.SetChargingProfile.ToString(), req);
-                if (result.Contains("TxProfile") == false)
-                {
-                    int location = result.IndexOf("transactionId");
-                    int len = "\"transactionId\":0,".Length;
-                    result = result.Remove(location - 1, len);
-                }
-            }
-
-            //ocpp cmd : ClearChargingProfile
-            if (cmd is Cmd9017)
-            {
-                IRequest req = makeRequest.MakeClearChargingProfileRequest(0);
-                string uuid = String.Empty;
-                lock (_clientQueue)
-                {
-                    uuid = queue.store(req);
-                }
-
-                messageType = "ClearChargingProfile Request";
-                result = GenerateCall(uuid, Actions.ClearChargingProfile.ToString(), req);
-            }
-
-            //ocpp cmd : GetCompositeSchedule
-            if (cmd is Cmd9019)
-            {
-                IRequest req = makeRequest.MakeGetCompositeScheduleRequest(0);
-                string uuid = String.Empty;
-                lock (_clientQueue)
-                {
-                    uuid = queue.store(req);
-                }
-
-                messageType = "GetCompositeSchedule Request";
-                result = GenerateCall(uuid, Actions.GetCompositeSchedule.ToString(), req);
-            }
-
-            //ocpp cmd : HardReset
-            if (cmd is Cmd9021)
-            {
-                IRequest req = makeRequest.MakeHardResetRequest();
-                string uuid = String.Empty;
-                lock (_clientQueue)
-                {
-                    uuid = queue.store(req);
-                }
-
-                messageType = "Reset Request(Hard)";
-                result = GenerateCall(uuid, Actions.Reset.ToString(), req);
-            }
-
-            //ocpp cmd : SoftReset
-            if (cmd is Cmd9023)
-            {
-                IRequest req = makeRequest.MakeSoftResetRequest();
-                string uuid = String.Empty;
-                lock (_clientQueue)
-                {
-                    uuid = queue.store(req);
-                }
-
-                messageType = "Reset Request(Soft)";
-                result = GenerateCall(uuid, Actions.Reset.ToString(), req);
-            }
-
-            //ocpp cmd : ClearCache
-            if (cmd is Cmd9025)
-            {
-                IRequest req = makeRequest.MakeClearCacheRequest();
-                string uuid = String.Empty;
-                lock (_clientQueue)
-                {
-                    uuid = queue.store(req);
-                }
-
-                messageType = "ClearCache Request";
-                result = GenerateCall(uuid, Actions.ClearCache.ToString(), req);
-            }
-
-            //ocpp cmd : ChangeAvailability
-            if (cmd is Cmd9027)
-            {
-                IRequest req = makeRequest.MakeChangeAvailabilityRequest(1);
-                string uuid = String.Empty;
-                lock (_clientQueue)
-                {
-                    uuid = queue.store(req);
-                }
-
-                messageType = "ChangeAvailability Request";
-                result = GenerateCall(uuid, Actions.ChangeAvailability.ToString(), req);
-            }
-
-            //ocpp cmd : GetConfiguration
-            if (cmd is Cmd9029)
-            {
-                IRequest req = makeRequest.MakeGetConfigurationRequest("");
-                string uuid = String.Empty;
-                lock (_clientQueue)
-                {
-                    uuid = queue.store(req);
-                }
-
-                messageType = "GetConfiguration Request";
-                result = GenerateCall(uuid, Actions.GetConfiguration.ToString(), req);
-            }
-
-            //ocpp cmd : UnlockConnector
-            if (cmd is Cmd9031)
-            {
-                IRequest req = makeRequest.MakeUnlockConnectorRequest(1);
-                string uuid = String.Empty;
-                lock (_clientQueue)
-                {
-                    uuid = queue.store(req);
-                }
-
-                messageType = "UnlockConnector Request";
-                result = GenerateCall(uuid, Actions.UnlockConnector.ToString(), req);
-            }
-
-            return result;
-        }
-
-        /// <summary>
-        /// 處理OCPP Request Message
-        /// </summary>
-        /// <param name="request">OCPP Request Message</param>
-        /// <param name="callid">OCPP Request Message Call Id</param>
-        /// <param name="db">Data Base Entity</param>
-        /// <param name="client">Connected Client Data</param>
-        /// <returns></returns>
-        public OCPPResult HandleRequest(IRequest request, string callid, PhihongDbContext db, ref ClientData client)
-        {
-            OCPPResult result = new OCPPResult();
-            IUnitOfWork uowtemp = new UnitOfWork(db);
-            IMachineService machineSrvTemp = new MachineService(uowtemp);
-            ISocketCommandService socketCommandSrvTemp = new SocketCommandService(uowtemp);
-            ICustomerService _customerServiceTemp = new CustomerService();
-
-            try
-            {
-                //簽到
-                if (request is BootNotificationRequest)
-                {
-                    var cmd = request as BootNotificationRequest;
-                    result.Success = true;
-                    result.Payload = makeConfirmation.MakeBootNotificationConfirmation(cmd);
-                }
-
-                //刷卡認證
-                if (request is AuthorizeRequest)
-                {
-                    #region AuthorizeRequest
-
-                    var cmd = request as AuthorizeRequest;
-                    var c = new HttpClient();
-                    string receivedCard = string.Empty;
-                    string cardpwd = string.Empty;
-                    //判斷此Authorize Reauest是Remote啟動充電 或 刷卡/後台啟動
-                    MemberMapping memberObj = db.MemberCharging.Where(x => x.SelfDefinedId == cmd.idTag).AsNoTracking().FirstOrDefault();
-                    if (memberObj != null)//為Remote啟動充電
-                    {
-                        receivedCard = memberObj.MemberId;
-                    }
-                    else //為刷卡或後台啟動
-                    {
-                        receivedCard = cmd.idTag;
-                        cardpwd = "nocheck";
-                    }
-
-                    var param = new { CustomerName = client.CustomerName, CardNum = receivedCard, PoleId = client.MachineCustomId, CardPwd = cardpwd };
-
-                    //將卡片資訊送到營運平台驗證
-                    var response = c.PostAsJsonAsync(ApiUrl + @"AuthenticateCard", param).Result;
-                    string responseBody = response.Content.ReadAsStringAsync().Result;
-                    if (response.IsSuccessStatusCode)
-                    {
-                        //伺服器回應正常
-                        var machine = machineSrvTemp.GetByCustomId(client.MachineCustomId);
-                        var authresult = JsonConvert.DeserializeObject<Cmd1203>(responseBody);
-                        if (authresult.UserMessageCode == 1) //卡片餘額充足
-                        {
-                            //卡片認證成功
-                            result.Payload = makeConfirmation.MakeAuthorizeConfirmation(cmd, AuthorizationStatus.Accepted);
-
-                            #region 下發卡片餘額
-
-                            IRequest req = makeRequest.MakeAccountBalanceRequest(callid, authresult.AccountBalance.RealValue, client.CarType);
-                            string uuid = String.Empty;
-                            lock (_clientQueue)
-                            {
-                                uuid = client.queue.store(req);
-                            }
-                            result.Message = GenerateCall(uuid, Actions.DataTransfer.ToString(), req);
-
-                            #endregion 下發卡片餘額
-                        }
-                        else
-                        {
-                            if (authresult.UserMessageCode == 6) //卡片被凍結
-                            {
-                                //卡片認證失敗,檢查卡片是否在充電中
-                                //取得充電樁目前的Status
-                                string rqueryCard = string.Empty;
-                                if (memberObj != null) //為Remote啟動充電
-                                {
-                                    rqueryCard = memberObj.MemberId;
-                                }
-                                else
-                                {
-                                    rqueryCard = cmd.idTag;
-                                }
-
-                                //若電樁狀態不是"充電中"/"充電結束" ,MachineGun的ReservationCardNum欄位為空白,此時取出的 gunStatusNow 為null
-                                var gunStatusNow = db.MachineGun.Where(x => x.ReservationCardNum == rqueryCard
-                                 && x.MachineId == machine.Id).AsNoTracking().FirstOrDefault();
-
-                                if (gunStatusNow != null && (gunStatusNow.Status == 2 || gunStatusNow.Status == 3))
-                                {
-                                    //取得充電樁在充電中或充電結束的狀態,回應有效
-                                    result.Payload = makeConfirmation.MakeAuthorizeConfirmation(cmd, AuthorizationStatus.Accepted);
-                                }
-                                else
-                                {
-                                    //取得充電樁不在充電中或充電結束的狀態,回應無效
-                                    result.Payload = makeConfirmation.MakeAuthorizeConfirmation(cmd, AuthorizationStatus.Blocked);
-
-                                    #region 下發卡片餘額
-
-                                    {
-                                        IRequest req = makeRequest.MakeAccountBalanceRequest(callid, authresult.AccountBalance.RealValue, client.CarType);
-                                        string uuid = String.Empty;
-                                        lock (_clientQueue)
-                                        {
-                                            uuid = client.queue.store(req);
-                                        }
-                                        result.Message = GenerateCall(uuid, Actions.DataTransfer.ToString(), req);
-                                    }
-
-                                    #endregion 下發卡片餘額
-                                }
-                            }
-                            else
-                            {
-                                //卡片為非餘額充足.非凍結的其他狀態
-                                result.Payload = makeConfirmation.MakeAuthorizeConfirmation(cmd, AuthorizationStatus.Invalid);
-
-                                #region 下發卡片餘額
-
-                                {
-                                    IRequest req = makeRequest.MakeAccountBalanceRequest(callid, authresult.AccountBalance.RealValue, client.CarType);
-                                    string uuid = String.Empty;
-                                    lock (_clientQueue)
-                                    {
-                                        uuid = client.queue.store(req);
-                                    }
-                                    result.Message = GenerateCall(uuid, Actions.DataTransfer.ToString(), req);
-                                }
-
-                                #endregion 下發卡片餘額
-                            }
-                        }
-                    }
-                    else
-                    {
-                        //伺服器異常
-                        result.Payload = makeConfirmation.MakeAuthorizeConfirmation((AuthorizeRequest)request, AuthorizationStatus.Invalid);
-                    }
-                    result.Success = true;
-
-                    #endregion AuthorizeRequest
-                }
-
-                //狀態包
-                if (request is StatusNotificationRequest)
-                {
-                    #region StatusNotificationRequest
-
-                    //目前以DataTransfer的GunStatus封包取代
-                    var cmd = request as StatusNotificationRequest;
-                    logger.Trace("Receive Command Status{0}", client.MachineCustomId);
-                    result.Success = true;
-                    result.Payload = makeConfirmation.MakeStatusNotificationConfirmation(cmd);
-
-                    #endregion StatusNotificationRequest
-                }
-
-                //心跳包
-                if (request is HeartbeatRequest)
-                {
-                    result.Success = true;
-                    result.Payload = makeConfirmation.MakeHeartbeatConfirmation((HeartbeatRequest)request);
-                    client.heartbeatDate = DateTime.Now;
-                }
-
-                //充電狀態包
-                if (request is MeterValuesRequest)
-                {
-                    #region MeterValuesRequest
-
-                    var cmd = request as MeterValuesRequest;
-                    logger.Trace("Receive Command Status{0}", client.MachineCustomId);
-                    WebSocketCommandService wsCommandSrv = new WebSocketCommandService(uowtemp);
-
-                    //處理104狀態包
-                    //不存在機器,要紀錄起來
-                    var machine = machineSrvTemp.GetByCustomId(client.MachineCustomId);
-
-                    if (machine != null)
-                    {
-                        //取得充電樁目前Status的充電序號
-                        var gunStatusNow = db.MachineGun.Where(c => c.GunSerNo == (cmd.connectorId - 1)
-                            && c.MachineId == machine.Id).AsNoTracking().FirstOrDefault();
-
-                        if (gunStatusNow.Status != (byte)ChargePointStatus.Charging)
-                        {
-                            result.Success = true;
-                            result.Payload = makeConfirmation.MakeMeterValuesConfirmation(cmd);
-                            return result;
-                        }
-
-                        result.Success = true;
-                        result.Payload = makeConfirmation.MakeMeterValuesConfirmation(cmd);
-                    }
-
-                    #endregion MeterValuesRequest
-                }
-
-                //啟動充電狀態包
-                if (request is StartTransactionRequest)
-                {
-                    #region StartTransactionRequest
-
-                    var cmd = request as StartTransactionRequest;
-                    logger.Trace("Receive Command Status{0}", client.MachineCustomId);
-                    WebSocketCommandService wsCommandSrv = new WebSocketCommandService(uowtemp);
-
-                    //處理104狀態包
-                    //不存在機器,要紀錄起來
-                    var machine = machineSrvTemp.GetByCustomId(client.MachineCustomId);
-
-                    if (machine != null)
-                    {
-                        //取得充電樁目前Status的充電序號
-                        var gunStatusNow = db.MachineGun.Where(c => c.GunSerNo == (cmd.connectorId - 1)
-                            && c.MachineId == machine.Id).AsNoTracking().FirstOrDefault();
-
-                        int transactionId = 0;
-                        result.Success = true;
-
-                        #region 確認是否有重覆的StartTransaction
-
-                        var repeatStartTransaction = db.ChargingTransaction.Where(c => c.GunSerNo == (cmd.connectorId - 1)
-                           && c.MachineId == machine.Id
-                           && c.StartChargingDateTime == cmd.timestamp
-                           ).AsNoTracking().FirstOrDefault();
-
-                        if (repeatStartTransaction != null) //重複的StartTransaction
-                            result.Payload = makeConfirmation.MakeRePeatStartTransactionConfirmation(cmd, repeatStartTransaction.TransactionId);
-                        else
-                            result.Payload = makeConfirmation.MakeStartTransactionConfirmation(cmd, out transactionId);
-
-                        #endregion 確認是否有重覆的StartTransaction
-
-                        //取得OCPP transactionId之後,寫入mapping table(OCPP transactionId, 充電紀錄ID),取得充電樁目前Status的充電序號
-                        if (gunStatusNow.Status != (byte)ChargePointStatus.Charging)
-                        {
-                            gunStatusNow = db.MachineGun.Where(c => c.GunSerNo == (cmd.connectorId - 1)
-                            && c.MachineId == machine.Id).AsNoTracking().FirstOrDefault();
-                        }
-
-                        var record = db.ChargingRecord.Where(c => c.GunSerNo == (cmd.connectorId - 1)
-                        && c.MachineId == machine.Id
-                        && c.ClientStartChargingDateTime == null
-                        && c.ClientEndChargingDateTime == null
-                        && c.EndChargingDateTime == null
-                        && c.StartChargingDateTime != null
-                        && c.ChargingSerNo == gunStatusNow.ChargingSerNo).AsNoTracking().FirstOrDefault();
-
-                        //處理沒有重複送的StartTransaction封包
-                        if (record != null)
-                        {
-                            //避免在物件 'dbo.ChargingTransaction' 中插入重複的索引鍵資料列
-                            var chargingTransactiontemp = db.ChargingTransaction.Where(c => c.GunSerNo == (cmd.connectorId - 1)
-                            && c.MachineId == machine.Id
-                            && c.StartChargingDateTime == record.StartChargingDateTime
-                            ).AsNoTracking().FirstOrDefault();
-
-                            if (chargingTransactiontemp == null)
-                            {
-                                ChargingTransaction chargingTransaction = new ChargingTransaction();
-                                chargingTransaction.MachineId = machine.Id;
-                                chargingTransaction.TransactionId = transactionId;
-                                chargingTransaction.GunSerNo = (byte)(cmd.connectorId - 1);
-                                chargingTransaction.StartChargingDateTime = record.StartChargingDateTime;
-                                chargingTransaction.ChargingRecordId = record.Id;
-                                chargingTransaction.CreatedOn = DateTime.Now;
-                                db.ChargingTransaction.Add(chargingTransaction);
-                                db.SaveChanges();
-                            }
-                        }
-                    }
-
-                    #endregion StartTransactionRequest
-                }
-
-                //停止充電,接收充电桩上報最新一次充电信息
-                if (request is StopTransactionRequest)
-                {
-                    #region StopTransactionRequest
-
-                    //目前採用DataTransfer的ChargeComplete封包來取代 StopTransactionRequest
-                    var cmd = request as StopTransactionRequest;
-                    result.Success = true;
-                    result.Payload = makeConfirmation.MakeStopTransactionConfirmation(cmd, AuthorizationStatus.Accepted);
-                    logger.Trace("reply StopTransactionRequest");
-
-                    #endregion StopTransactionRequest
-                }
-
-                //接收電樁DiagnosticsStatus狀態
-                if (request is DiagnosticsStatusNotificationRequest)
-                {
-                    var cmd = request as DiagnosticsStatusNotificationRequest;
-                    logger.Trace("Receive 電樁 {0} Staus {1}", client.MachineCustomId, cmd.status.ToString());
-                    result.Success = true;
-                    result.Payload = makeConfirmation.MakeDiagnosticsStatusNotificationConfirmation();
-                }
-
-                //接收電樁update firmware 進度狀態
-                if (request is FirmwareStatusNotificationRequest)
-                {
-                    var cmd = request as FirmwareStatusNotificationRequest;
-                    if ((cmd.status == FirmwareStatus.DownloadFailed) || (cmd.status == FirmwareStatus.InstallationFailed))
-                    {
-                        //更新主程序 或 FW 部分
-                    }
-                    logger.Trace("Receive 電樁 {0} Staus {1}", client.MachineCustomId, cmd.status.ToString());
-                    result.Success = true;
-                    result.Payload = makeConfirmation.MakeFirmwareStatusNotificationConfirmation();
-                }
-
-                //處理自訂的訊息
-                if (request is DataTransferRequest)
-                {
-                    var cmd = request as DataTransferRequest;
-
-                    //刷卡認證
-                    if (cmd.messageId == "AuthorizeData")
-                    {
-                        #region AuthorizeData
-                        logger.Trace("Receive Command Status{0}", client.MachineCustomId);
-                        var cmd1204 = JsonConvert.DeserializeObject<AuthorizeData>(cmd.data);
-
-                        var c = new HttpClient();
-                        string receivedCard = string.Empty;
-
-                        //判斷此Authorize Reauest是Remote啟動充電 或 刷卡/後台啟動
-                        MemberMapping memberObj = db.MemberCharging.Where(x => x.SelfDefinedId == cmd1204.idTag).AsNoTracking().FirstOrDefault();
-                        if (memberObj != null)//為Remote啟動充電
-                        {
-                            receivedCard = memberObj.MemberId;
-                        }
-                        else //為刷卡或後台啟動
-                        {
-                            receivedCard = cmd1204.idTag;
-                        }
-
-                        var param = new { CustomerName = client.CustomerName, CardNum = receivedCard, PoleId = client.MachineCustomId, CardPwd = cmd1204.password };
-
-                        //將卡片資訊送到營運平台驗證
-                        var response = c.PostAsJsonAsync(ApiUrl + @"AuthenticateCard", param).Result;
-                        string responseBody = response.Content.ReadAsStringAsync().Result;
-                        if (response.IsSuccessStatusCode)
-                        {
-                            //伺服器回應正常
-                            var machine = machineSrvTemp.GetByCustomId(client.MachineCustomId);
-                            var authresult = JsonConvert.DeserializeObject<Cmd1203>(responseBody);
-                            if (authresult.UserMessageCode == 1) //卡片餘額充足
-                            {
-                                //卡片認證成功
-                                result.Payload = makeConfirmation.MakeAuthorizeDataConfConfirmation(cmd1204, AuthorizeStatus.Accepted);
-
-                                #region 下發卡片餘額
-
-                                IRequest req = makeRequest.MakeAccountBalanceRequest(callid, authresult.AccountBalance.RealValue, client.CarType);
-                                string uuid = String.Empty;
-                                lock (_clientQueue)
-                                {
-                                    uuid = client.queue.store(req);
-                                }
-                                result.Message = GenerateCall(uuid, Actions.DataTransfer.ToString(), req);
-
-                                #endregion 下發卡片餘額
-                            }
-                            else
-                            {
-                                if (authresult.UserMessageCode == 6) //卡片被凍結
-                                {
-                                    //卡片認證失敗,檢查卡片是否在充電中
-                                    //取得充電樁目前的Status
-                                    string rqueryCard = string.Empty;
-                                    if (memberObj != null) //為Remote啟動充電
-                                    {
-                                        rqueryCard = memberObj.MemberId;
-                                    }
-                                    else
-                                    {
-                                        rqueryCard = cmd1204.idTag;
-                                    }
-
-                                    //若電樁狀態不是"充電中"/"充電結束" ,MachineGun的ReservationCardNum欄位為空白,此時取出的 gunStatusNow 為null
-                                    var gunStatusNow = db.MachineGun.Where(x => x.ReservationCardNum == rqueryCard
-                                     && x.MachineId == machine.Id).AsNoTracking().FirstOrDefault();
-
-                                    if (gunStatusNow != null && (gunStatusNow.Status == 2 || gunStatusNow.Status == 3))
-                                    {
-                                        //取得充電樁在充電中或充電結束的狀態,回應有效
-                                        result.Payload = makeConfirmation.MakeAuthorizeDataConfConfirmation(cmd1204, AuthorizeStatus.Accepted);
-                                    }
-                                    else
-                                    {
-                                        //取得充電樁不在充電中或充電結束的狀態,回應無效
-                                        result.Payload = makeConfirmation.MakeAuthorizeDataConfConfirmation(cmd1204, AuthorizeStatus.Blocked);
-
-                                        #region 下發卡片餘額
-
-                                        {
-                                            IRequest req = makeRequest.MakeAccountBalanceRequest(callid, authresult.AccountBalance.RealValue, client.CarType);
-                                            string uuid = String.Empty;
-                                            lock (_clientQueue)
-                                            {
-                                                uuid = client.queue.store(req);
-                                            }
-                                            result.Message = GenerateCall(uuid, Actions.DataTransfer.ToString(), req);
-                                        }
-
-                                        #endregion 下發卡片餘額
-                                    }
-                                }
-                                else if (authresult.UserMessageCode == 13) //密碼錯誤
-                                {
-                                    result.Payload = makeConfirmation.MakeAuthorizeDataConfConfirmation(cmd1204, AuthorizeStatus.PasswordError);
-                                }
-                                else
-                                {
-                                    //卡片為非餘額充足.非凍結的其他狀態
-                                    result.Payload = makeConfirmation.MakeAuthorizeDataConfConfirmation(cmd1204, AuthorizeStatus.Invalid);
-
-                                    #region 下發卡片餘額
-
-                                    {
-                                        IRequest req = makeRequest.MakeAccountBalanceRequest(callid, authresult.AccountBalance.RealValue, client.CarType);
-                                        string uuid = String.Empty;
-                                        lock (_clientQueue)
-                                        {
-                                            uuid = client.queue.store(req);
-                                        }
-                                        result.Message = GenerateCall(uuid, Actions.DataTransfer.ToString(), req);
-                                    }
-
-                                    #endregion 下發卡片餘額
-                                }
-                            }
-                        }
-                        else
-                        {
-                            //伺服器異常
-                            result.Payload = makeConfirmation.MakeAuthorizeConfirmation((AuthorizeRequest)request, AuthorizationStatus.Invalid);
-                        }
-                        result.Success = true;
-
-
-                        #endregion
-                    }
-
-                    if (cmd.messageId == "GunStatus")
-                    {
-                        #region GunStatus
-
-                        logger.Trace("Receive Command Status{0}", client.MachineCustomId);
-                        var cmd104 = JsonConvert.DeserializeObject<GunStatus>(cmd.data);
-                        WebSocketCommandService wsCommandSrv = new WebSocketCommandService(uowtemp);
-
-                        //處理104狀態包
-                        //不存在機器,要紀錄起來
-                        var machine = machineSrvTemp.GetByCustomId(client.MachineCustomId);
-
-                        #region mapper
-
-                        ChargingRecordStatus dObj = new ChargingRecordStatus();
-                        dObj.MachineId = machine.Id;
-                        dObj.MachineCustomId = machine.CustomId;
-                        dObj.Warning = ProcessErrorCode(machine.AC, cmd104.errorCode);
-                        dObj.DcV = (decimal)cmd104.dcVoltage;
-                        dObj.DcA = (decimal)cmd104.dcCurrent;
-                        dObj.BmsV = (decimal)cmd104.bmsVoltage;
-                        dObj.BmsA = (decimal)cmd104.bmsCurrent;
-                        dObj.AcV_A = (decimal)cmd104.acVoltage_A;
-                        dObj.AcV_B = (decimal)cmd104.acVoltage_B;
-                        dObj.AcV_C = (decimal)cmd104.acVoltage_C;
-                        dObj.AcA_A = (decimal)cmd104.acCurrent_A;
-                        dObj.AcA_B = (decimal)cmd104.acCurrent_B;
-                        dObj.AcA_C = (decimal)cmd104.acCurrent_C;
-                        dObj.BmsWorkingMode = (byte)cmd104.bmsWorkingMode;
-                        dObj.CumulativeKwh = (decimal)(cmd104.currentKwh - cmd104.beforeChargingKwh);//(decimal)cmd104.cumulativeKwh;
-                        dObj.CumulativeTime = cmd104.cumulativeTime;
-                        dObj.CurrentKwh = (decimal)cmd104.currentKwh;
-                        dObj.CardBalanceBeforeCharging = (decimal)cmd104.cardBalanceBeforeCharging;
-                        dObj.ChargingStrategy = (byte)cmd104.chargingStrategy;
-                        dObj.ChargingStrategyParam = (decimal)cmd104.chargingStrategyParameter;
-                        dObj.CurrentSoc = (byte)cmd104.currentSOC;
-                        dObj.CarConnection = (byte)cmd104.carConnectionStatus;
-                        dObj.KwhBeforeCharging = (decimal)cmd104.beforeChargingKwh;
-                        dObj.CumulativeChargeFee = (decimal)cmd104.cumulativeChargeFee;
-                        dObj.GunAmt = (byte)machine.GunAmt;
-                        dObj.GunSerNo = (byte)(cmd104.connectorId - 1);
-                        dObj.GunType = (byte)(machine.AC ? 2 : 1);
-                        dObj.RemainingTime = cmd104.remainingTime;
-                        dObj.Reservation = (byte)(cmd104.isReserved ? 1 : 0);
-                        dObj.ReservationOverTime = 0;
-                        dObj.StartWith = (byte)cmd104.startWith;
-                        dObj.CumulativeOutputKwh = Convert.ToDecimal(cmd104.CumulativeOutputKwh);
-                        dObj.GunTemperature = cmd104.GunTemperature;
-                        if (cmd104.status == ChargePointStatus.Charging || cmd104.status == ChargePointStatus.Finishing)
-                        {
-                            dObj.StartChargingDateTime = cmd104.startChargingDateTime;
-                        }
-                        else
-                        {
-                            dObj.StartChargingDateTime = null;
-                        }
-
-                        dObj.StartChargingType = (byte)cmd104.startChargingType;
-                        dObj.Status = (byte)cmd104.status;
-
-                        if (cmd104.startWith == StartWith.Member)
-                        {
-                            var membertb = db.MemberCharging.Where(c => c.SelfDefinedId == cmd104.idTag).AsNoTracking().FirstOrDefault();
-                            if (membertb != null)
-                            {
-                                //會員
-                                dObj.MemberId = membertb.MemberId.ToString();//client.ReservationCardNum;
-                                dObj.ReservationCardNum = membertb.MemberId.ToString();/*client.ReservationCardNum;*/
-                            }
-                        }
-                        else if ((cmd104.startWith == StartWith.CardNumber) || (cmd104.startWith == StartWith.Unknown))
-                        {
-                            dObj.ReservationCardNum = cmd104.idTag;
-                        }
-
-
-                        MChargingRecordStatus mdObj = new MChargingRecordStatus();
-                        mdObj.MachineId = machine.Id;
-                        mdObj.MachineCustomId = machine.CustomId;
-                        mdObj.Warning = ProcessErrorCode(machine.AC, cmd104.errorCode);
-                        mdObj.DcV = (decimal)cmd104.dcVoltage;
-                        mdObj.DcA = (decimal)cmd104.dcCurrent;
-                        mdObj.BmsV = (decimal)cmd104.bmsVoltage;
-                        mdObj.BmsA = (decimal)cmd104.bmsCurrent;
-                        mdObj.AcV_A = (decimal)cmd104.acVoltage_A;
-                        mdObj.AcV_B = (decimal)cmd104.acVoltage_B;
-                        mdObj.AcV_C = (decimal)cmd104.acVoltage_C;
-                        mdObj.AcA_A = (decimal)cmd104.acCurrent_A;
-                        mdObj.AcA_B = (decimal)cmd104.acCurrent_B;
-                        mdObj.AcA_C = (decimal)cmd104.acCurrent_C;
-                        mdObj.BmsWorkingMode = (byte)cmd104.bmsWorkingMode;
-                        mdObj.CumulativeKwh = (decimal)(cmd104.currentKwh - cmd104.beforeChargingKwh);//(decimal)cmd104.cumulativeKwh;
-                        mdObj.CumulativeTime = cmd104.cumulativeTime;
-                        mdObj.CurrentKwh = (decimal)cmd104.currentKwh;
-                        mdObj.CardBalanceBeforeCharging = (decimal)cmd104.cardBalanceBeforeCharging;
-                        mdObj.ChargingStrategy = (byte)cmd104.chargingStrategy;
-                        mdObj.ChargingStrategyParam = (decimal)cmd104.chargingStrategyParameter;
-                        mdObj.CurrentSoc = (byte)cmd104.currentSOC;
-                        mdObj.CarConnection = (byte)cmd104.carConnectionStatus;
-                        mdObj.KwhBeforeCharging = (decimal)cmd104.beforeChargingKwh;
-                        mdObj.CumulativeChargeFee = (decimal)cmd104.cumulativeChargeFee;
-                        mdObj.GunAmt = (byte)machine.GunAmt;
-                        mdObj.GunSerNo = (byte)(cmd104.connectorId - 1);
-                        mdObj.GunType = (byte)(machine.AC ? 2 : 1);
-                        mdObj.RemainingTime = cmd104.remainingTime;
-                        mdObj.Reservation = (byte)(cmd104.isReserved ? 1 : 0);
-                        mdObj.ReservationOverTime = 0;
-                        mdObj.StartWith = (byte)cmd104.startWith;
-                        mdObj.CumulativeOutputKwh = Convert.ToDecimal(cmd104.CumulativeOutputKwh);
-                        mdObj.GunTemperature = cmd104.GunTemperature;
-                        if (cmd104.status == ChargePointStatus.Charging || cmd104.status == ChargePointStatus.Finishing)
-                        {
-                            mdObj.StartChargingDateTime = cmd104.startChargingDateTime;
-                        }
-                        else
-                        {
-                            mdObj.StartChargingDateTime = null;
-                        }
-
-                        mdObj.StartChargingType = (byte)cmd104.startChargingType;
-                        mdObj.Status = (byte)cmd104.status;
-
-                        if (cmd104.startWith == StartWith.Member)
-                        {
-                            var membertb = db.MemberCharging.Where(c => c.SelfDefinedId == cmd104.idTag).AsNoTracking().FirstOrDefault();
-                            if (membertb != null)
-                            {
-                                //會員
-                                mdObj.MemberId = membertb.MemberId.ToString();//client.ReservationCardNum;
-                                mdObj.ReservationCardNum = membertb.MemberId.ToString();/*client.ReservationCardNum;*/
-                            }
-                        }
-                        else if ((cmd104.startWith == StartWith.CardNumber) || (cmd104.startWith == StartWith.Unknown))
-                        {
-                            mdObj.ReservationCardNum = cmd104.idTag;
-                        }
-                        #endregion mapper
-                        GunMessage socketCommand1104 = new GunMessage();
-                        socketCommand1104.chargingRecordStatus = dObj;
-                        socketCommand1104.mchargingRecordStatus = mdObj;
-                        var process1104Result = wsCommandSrv.Process1104(socketCommand1104);
-
-                        result.Success = true;
-                        result.Payload = makeConfirmation.MakeGunStatusConfirmation();
-
-                        #endregion GunStatus
-                    }
-
-                    if (cmd.messageId == "ChargeComplete")
-                    {
-                        #region ChargeComplete
-
-                        var chargeComplete = JsonConvert.DeserializeObject<ChargeComplete>(cmd.data);
-                        WebSocketCommandService wsCommandSrv = new WebSocketCommandService(uowtemp);
-                        //避免同時處理同一個樁號的ChargeComplete
-                        lock (_cmd202lst)
-                        {
-                            if (_cmd202lst.Contains(client.MachineCustomId))
-                            {
-                                result.Success = false;
-                                return result;
-                            }
-                            if (!_cmd202lst.Contains(client.MachineCustomId))
-                            {
-                                _cmd202lst.Add(client.MachineCustomId);
-                            }
-                        }
-                        logger.Trace("receive ChargeComplete{0}", client.MachineCustomId);
-
-                        var processChargeCompleteResult = wsCommandSrv.ProcessChargeComplete(chargeComplete, client.MachineCustomId);
-                        if (processChargeCompleteResult.Success)
-                        {
-                            result.Success = true;
-                            result.Payload = makeConfirmation.MakeChargeCompleteConfirmation();
-                            logger.Trace("reply ChargeComplete");
-                        }
-                        else
-                        {
-                            result.Success = false;
-                            result.Exception = processChargeCompleteResult.Exception;
-                            result.Message = processChargeCompleteResult.Message;
-                            logger.Error(processChargeCompleteResult.Exception, "ChargeComplete error");
-                        }
-                        lock (_cmd202lst)
-                        {
-                            _cmd202lst.Remove(client.MachineCustomId);
-                        }
-
-                        #endregion ChargeComplete
-                    }
-
-                    if (cmd.messageId == "Location")
-                    {
-                        #region Location
-
-                        var data = JsonConvert.DeserializeObject<OCPPPacket.Packet.DataTransfer.Location>(cmd.data);
-                        WebSocketCommandService wsCommandSrv = new WebSocketCommandService(uowtemp);
-                        logger.Trace("receive 1120 {0}", client.MachineCustomId);
-                        logger.Trace("receive 1120 {0} {1} {2}", client.MachineCustomId, data.longitude, data.latitude);
-                        var processLocationResult = wsCommandSrv.ProcessLocation(client.MachineCustomId, data);
-                        if (processLocationResult.Success)
-                        {
-                            result.Success = true;
-                            result.Payload = makeConfirmation.MakeLocationConfirmation();
-                            logger.Trace("reply Location");
-                        }
-                        else
-                        {
-                            result.Success = false;
-                            result.Exception = processLocationResult.Exception;
-                            logger.Error(processLocationResult.Exception, "Location.conf error");
-                        }
-
-                        #endregion Location
-                    }
-
-                    if (cmd.messageId == "ChargingGunBMS")
-                    {
-                        #region ChargingGunBMS
-
-                        var data = JsonConvert.DeserializeObject<ChargingGunBMS>(cmd.data);
-                        WebSocketCommandService wsCommandSrv = new WebSocketCommandService(uowtemp);
-                        var processChargingGunBMSResult = wsCommandSrv.ProcessChargingGunBMS(client.MachineId, data);
-                        if (processChargingGunBMSResult.Success)
-                        {
-                            result.Success = true;
-                            result.Payload = makeConfirmation.MakeChargingGunBMSConfirmation();
-                            logger.Trace("reply ChargingGunBMS");
-                        }
-
-                        #endregion ChargingGunBMS
-                    }
-
-                    //電樁上報升級文件的版
-                    if (cmd.messageId == "UpgradeVersion")
-                    {
-                        #region UpgradeVersion
-
-                        UploadFile uploadFile = null;
-                        WebSocketCommandService wsCommandSrv = new WebSocketCommandService(uowtemp);
-                        var data = JsonConvert.DeserializeObject<UpgradeVersion>(cmd.data);
-                        var processUpgradeVersionResult = wsCommandSrv.CheckCmd2104(client.MachineId, data, out uploadFile);
-
-                        result.Success = true;
-                        result.Payload = makeConfirmation.MakeUpgradeVersionConfConfirmation(processUpgradeVersionResult, data.param);
-                        logger.Trace("reply DataTransfer.conf");
-
-                        //DC 桩
-                        if (uploadFile != null)
-                        {
-                            //製作 UpdateFirmware Request
-                            if (((int)data.param == 1 || CmdHelper.GetCmd2101Type((byte)data.param) == 2) && processUpgradeVersionResult == false)
-                            {
-                                int type = CmdHelper.GetCmd2101Type((byte)data.param);
-                                IRequest req = makeRequest.MakeUpdateFirmware(type, data.param, uploadFile);
-                                string uuid = String.Empty;
-                                lock (_clientQueue)
-                                {
-                                    uuid = client.queue.store(req);
-                                }
-                                result.Message = GenerateCall(uuid, Actions.DataTransfer.ToString(), req);
-                            }
-                        }
-
-                        #endregion UpgradeVersion
-                    }
-
-                }
-            }
-            catch (Exception ex)
-            {
-                logger.Error(ex);
-                result.Exception = ex;
-                result.Success = false;
-            }
-            return result;
-        }
-
-        /// <summary>
-        /// 判斷是否由會員帳號充電
-        /// </summary>
-        /// <param name="request">OCPP Request</param>
-        /// <param name="db">Data Base Entity</param>
-        /// <returns></returns>
-        public bool IsMemberCharging(IRequest request, PhihongDbContext db)
-        {
-            bool result = new Boolean();
-            IUnitOfWork uowtemp = new UnitOfWork(db);
-            IMachineService machineSrvTemp = new MachineService(uowtemp);
-            ISocketCommandService socketCommandSrvTemp = new SocketCommandService(uowtemp);
-            ICustomerService _customerServiceTemp = new CustomerService();
-
-            try
-            {
-                //刷卡認證
-                if (request is AuthorizeRequest)
-                {
-                    var cmd = request as AuthorizeRequest;
-                    //判斷此Authorize Reauest是Remote啟動充電 或 刷卡/後台啟動
-                    MemberMapping memberObj = db.MemberCharging.Where(x => x.SelfDefinedId == cmd.idTag).AsNoTracking().FirstOrDefault();
-                    if (memberObj != null)//為Remote啟動充電
-                    {
-                        result = true;
-                    }
-                    else //為刷卡或後台啟動
-                    {
-                        result = false;
-                    }
-                }
-            }
-            catch (Exception ex)
-            {
-                logger.Error(ex);
-                result = false;
-            }
-            return result;
-        }
-
-        /// <summary>
-        /// 處理電樁所送的comfirm message
-        /// </summary>
-        /// <param name="uniqueId">OCPP Message uniqueId</param>
-        /// <param name="confirmation">OCPP Confirm Message</param>
-        /// <param name="db">Data Base Entity</param>
-        /// <param name="client">Connected Client Data</param>
-        /// <returns></returns>
-        public OCPPResult HandleConfirmation(string uniqueId, IConfirmation confirmation, string callResultAction, PhihongDbContext db, ref ClientData client)
-        {
-            OCPPResult result = new OCPPResult();
-            IUnitOfWork uowconf = new UnitOfWork(db);
-            IRepository<MachineVersionFile> _mvfRepo = uowconf.Repository<MachineVersionFile>();
-            try
-            {
-                #region Core
-
-                //接收電樁對Remote啟動充電回應
-                if (confirmation is RemoteStartTransactionConfirmation)
-                {
-                    IConfirmation cmd = confirmation as RemoteStartTransactionConfirmation;
-                }
-
-                //接收電樁對Remote停止充電回應
-                if (confirmation is RemoteStopTransactionConfirmation)
-                {
-                    IConfirmation cmd = confirmation as RemoteStopTransactionConfirmation;
-                }
-
-                //接收電樁對Unlock Connector回應
-                if (confirmation is UnlockConnectorConfirmation)
-                {
-                    IConfirmation cmd = confirmation as UnlockConnectorConfirmation;
-                }
-
-                //接收電樁對configuration 回應
-                if (confirmation is GetConfigurationConfirmation)
-                {
-                    GetConfigurationConfirmation cmd = confirmation as GetConfigurationConfirmation;
-
-                    foreach (var config in cmd.configurationKey)
-                    {
-                        var item = client.configurationKey.Where(c => c.key == config.key).FirstOrDefault();
-                        item.value = config.value;
-                    }
-                }
-
-                //接收電樁對電樁槍號 availability 改變 回應
-                if (confirmation is ChangeAvailabilityConfirmation)
-                {
-                    ChangeAvailabilityConfirmation cmd = confirmation as ChangeAvailabilityConfirmation;
-                }
-
-                #endregion Core
-
-                #region FirmwareManagement
-
-                //接收電樁對取得 GetDiagnostics資訊回應
-                if (confirmation is GetDiagnosticsConfirmation)
-                {
-                    GetDiagnosticsConfirmation cmd = confirmation as GetDiagnosticsConfirmation;
-                    logger.Trace("Receive 電樁 {0} 上傳檔案 {1}", client.MachineCustomId, cmd.fileName);
-                }
-
-                //接收電樁對UpdateFirmware回應
-                if (confirmation is UpdateFirmwareConfirmation)
-                {
-                    UpdateFirmwareConfirmation cmd = confirmation as UpdateFirmwareConfirmation;
-                }
-
-                #endregion FirmwareManagement
-
-                #region LocalAuthListManagement
-
-                //接收電樁對  Get Local List Version 回應
-                if (confirmation is GetLocalListVersionConfirmation)
-                {
-                    GetLocalListVersionConfirmation cmd = confirmation as GetLocalListVersionConfirmation;
-                    string customId = client.MachineCustomId;
-                    var localauthTable = db.LocalAuthorization.Where(c => c.CustomId == customId).FirstOrDefault();
-                    if (localauthTable != null)
-                    {
-                        localauthTable.CurrentVersion = cmd.listVersion;
-                        localauthTable.UpdatedOn = DateTime.Now;
-                        db.SaveChanges();
-                    }
-                }
-
-                //接收電樁對  Send Local List 回應
-                if (confirmation is SendLocalListConfirmation)
-                {
-                    SendLocalListConfirmation cmd = confirmation as SendLocalListConfirmation;
-
-                    if (cmd.updateStatus == UpdateStatus.Accepted)
-                    {
-                        //下發GetLocalListVersion.req
-                        Cmd1011 cmd1011 = client.CmdHelper.Create(1011) as Cmd1011;
-                        cmd1011.CmdSerNum = client.GetCmdSerNum();
-                        cmd1011.SerNum = client.GetSerNum();
-                        cmd1011.Pack();
-                        ServerCommand sc = new ServerCommand();
-                        sc.OutCmdNum = cmd1011.Cmd;
-                        sc.CreatedOn = DateTime.Now;
-                        sc.MachineId = client.MachineId;
-                        sc.MachineCustomId = client.MachineCustomId;
-                        sc.OutTransData = cmd1011.byteList.ToArray();
-                        db.ServerCommand.Add(sc);
-                        db.SaveChanges();
-                    }
-                }
-
-                #endregion LocalAuthListManagement
-
-                #region Reservation
-
-                //接收電樁對 預約 回應
-                if (confirmation is ReserveNowConfirmation)
-                {
-                    ReserveNowConfirmation cmd = confirmation as ReserveNowConfirmation;
-                }
-
-                //接收電樁對 取消預約 回應
-                if (confirmation is CancelReservationConfirmation)
-                {
-                    CancelReservationConfirmation cmd = confirmation as CancelReservationConfirmation;
-                }
-
-                #endregion Reservation
-
-                #region SmartCharging
-
-                //接收電樁對 Charging Profile回應
-                if (confirmation is SetChargingProfileConfirmation)
-                {
-                    SetChargingProfileConfirmation cmd = confirmation as SetChargingProfileConfirmation;
-                    var uuid = Guid.Parse(uniqueId);
-                    var chargingProfile = db.ChargingProfile.Where(x => x.Id == uuid).FirstOrDefault();
-                    if (chargingProfile != null)
-                    {
-                        chargingProfile.UpdatedOn = DateTime.Now;
-                        chargingProfile.ResponseStatus = (int)cmd.status;
-                        db.SaveChanges();
-                    }
-                    logger.Trace("Receive 電樁 {0} Charging Profile回應 Status:{1} \n", client.MachineCustomId, cmd.status);
-                }
-
-                //接收電樁對清除Charging Profile回應
-                if (confirmation is ClearChargingProfileConfirmation)
-                {
-                    ClearChargingProfileConfirmation cmd = confirmation as ClearChargingProfileConfirmation;
-                    var uuid = Guid.Parse(uniqueId);
-                    var chargingProfile = db.ChargingProfile.Where(x => x.Id == uuid).FirstOrDefault();
-                    if (chargingProfile != null)
-                    {
-                        chargingProfile.UpdatedOn = DateTime.Now;
-                        chargingProfile.ResponseStatus = (int)cmd.status;
-                        db.SaveChanges();
-                    }
-                    logger.Trace("Receive 電樁 {0} 清除Charging Profile Status:{1} \n", client.MachineCustomId, cmd.status);
-                }
-
-                //接收電樁對Composite Charging Schedule 回應
-                if (confirmation is GetCompositeScheduleConfirmation)
-                {
-                    GetCompositeScheduleConfirmation cmd = confirmation as GetCompositeScheduleConfirmation;
-                    if (cmd.chargingSchedule != null)
-                    {
-                        logger.Trace("Receive 電樁 {0} Composite Charging Schedule  connectorId:{1} Status:{2} ScheduleStart:{3} duration:{4}  chargingRateUnit:{5} minChargingRate:{6}\n", client.MachineCustomId, cmd.connectorId, cmd.status, cmd.scheduleStart.ToLocalTime(), cmd.chargingSchedule.duration, cmd.chargingSchedule.chargingRateUnit, cmd.chargingSchedule.minChargingRate);
-                        foreach (var period in cmd.chargingSchedule.chargingSchedulePeriod)
-                        {
-                            logger.Trace("startPeriod:{0} limit:{1} numberPhases:{2}\n", period.startPeriod, period.limit, period.numberPhases);
-                        }
-                    }
-                    else
-                        logger.Trace("Receive 電樁 {0} Composite Charging Schedule  connectorId:{1} Status:{2} ScheduleStart:{3} \n", client.MachineCustomId, cmd.connectorId, cmd.status, cmd.scheduleStart.ToLocalTime());
-                }
-
-                #endregion SmartCharging
-
-                #region DataTransfer
-
-                //處理自訂的訊息
-                if (confirmation is DataTransferConfirmation)
-                {
-
-
-                    DataTransferConfirmation cmd = confirmation as DataTransferConfirmation;
-                  
-
-                    if (cmd.data != null)
-                    {
-                        
-
-                        if (callResultAction.Contains("SetChargingConfig"))
-                        {
-                           
-                            var uuid = Guid.Parse(uniqueId);
-                            var chargingProfile = db.ChargingProfile.Where(x => x.Id == uuid).FirstOrDefault();
-                            if (chargingProfile != null)
-                            {
-                                chargingProfile.UpdatedOn = DateTime.Now;
-                                chargingProfile.ResponseStatus = (int)cmd.status;
-                                db.SaveChanges();
-                            }
-                           
-                        }
-                        else if (callResultAction.Contains("GetChargingConfig"))
-                        {
-                          
-                            var uuid = Guid.Parse(uniqueId);
-                            var chargingProfile = db.ChargingProfile.Where(x => x.Id == uuid).FirstOrDefault();
-                            if (chargingProfile != null)
-                            {
-                                var charingRate = JsonConvert.DeserializeObject<ChargingRate>(cmd.data);
-                                chargingProfile.UpdatedOn = DateTime.Now;
-                                chargingProfile.ResponseStatus = (int)cmd.status;
-                                chargingProfile.EasyConfig = String.Format("{0}:{1}", charingRate.chargingRateUnit, charingRate.limit);
-                                db.SaveChanges();
-                            }
-                           
-                        }
-                        else if (cmd.data[0] == '{')
-                        {
-                          
-                            JObject restoredObject = JObject.Parse(cmd.data);
-                            FirmwareMD5 fwmd5 = new FirmwareMD5();
-
-                          
-                            if (cmd.data.Contains("md5") == true)
-                            {
-                                // Copy to a static fwmd5 instance
-                                fwmd5 = restoredObject.ToObject<FirmwareMD5>();
-
-                                //充電樁對服務器下發升級指令的應答
-                                //處理 UpdateFirmware conf
-                                fwmd5.md5 = fwmd5.md5.ToUpper();
-                                string machineId = client.MachineId;
-                                var mvFile = _mvfRepo.Query(c => c.MachineVersion.MachineId.Equals(machineId) && c.UploadFile.FileMD5.ToUpper().Equals(fwmd5.md5)).Select(c => c).OrderByDescending(c => c.CreatedOn).FirstOrDefault();
-
-                                if (mvFile != null)
-                                {
-                                    mvFile.DownloadedOn = DateTime.Now;
-                                    uowconf.SaveChanges();
-                                    result.Success = true;
-                                }
-                                else
-                                {
-                                    throw new ApplicationException("找不到相關檔案");
-                                }
-                            }
-                        }
-                        else
-                        {
-                            if (cmd.data == "true") //成功
-                            {
-                                logger.Trace("Receive 電樁 {0} 處理電費/服務費 結果 {1}", client.MachineCustomId, cmd.data);
-                            }
-                            else if (cmd.data == "false") //失敗
-                            {
-                                logger.Trace("Receive 電樁 {0} 處理電費/服務費 結果 {1}", client.MachineCustomId, cmd.data);
-                            }
-                        }
-                    }
-                }
-
-                #endregion DataTransfer
-
-                result.Success = true;
-            }
-            catch (Exception ex)
-            {
-                logger.Error(ex);
-                result.Exception = ex;
-                result.Success = false;
-            }
-            return result;
-        }
-
-        //處理電樁所送的Error Message
-        public OCPPResult HandleError(string uniqueId, string errorCode, string errorDescription, object payload)
-        {
-            OCPPResult result = new OCPPResult();
-            return result;
-        }
-
-        /// <summary>
-        /// 處理WSServer 產生DataTransfer的ServerDomainName命令
-        /// </summary>
-        /// <param name="queue">Message Queue</param>
-        /// <param name="ServerDomainName">ServerDomainName</param>
-        /// <returns></returns>
-        public string HandleServerDomainName(ref Queue queue, string ServerDomainName)
-        {
-            IRequest req = makeRequest.MakeServerDomainNameRequest(ServerDomainName);
-            string uuid = String.Empty;
-            lock (_clientQueue)
-            {
-                uuid = queue.store(req);
-            }
-            return GenerateCall(uuid, Actions.DataTransfer.ToString(), req);
-        }
-
-        /// <summary>
-        /// 處理WSServer 產生DataTransfer的UpdateFirmware命令
-        /// </summary>
-        /// <param name="queue">Message Queue</param>
-        /// <param name="type">Messgae Type</param>
-        /// <param name="param">ProgramParam Type</param>
-        /// <param name="uploadFile">UploadFile</param>
-        /// <returns></returns>
-        public string HandleUpdateFirmware(ref Queue queue, int type, ProgramParam param, UploadFile uploadFile)
-        {
-            IRequest req = makeRequest.MakeUpdateFirmware(type, param, uploadFile);
-            string uuid = String.Empty;
-            lock (_clientQueue)
-            {
-                uuid = queue.store(req);
-            }
-            return GenerateCall(uuid, Actions.DataTransfer.ToString(), req);
-        }
-
-        /// <summary>
-        /// 處理WSServer 產生OCPP協議的UpdateFirmware命令
-        /// </summary>
-        /// <param name="queue">Message Queue</param>
-        /// <param name="fileurl">FileURL</param>
-        /// <returns></returns>
-        public string HandleOCPPUpdateFirmware(ref Queue queue, string fileurl)
-        {
-            IRequest req = MakeRequestHandler.MakeOCPPUpdateFirmwareRequest(fileurl);
-            string uuid = String.Empty;
-            lock (_clientQueue)
-            {
-                uuid = queue.store(req);
-            }
-            return GenerateCall(uuid, Actions.UpdateFirmware.ToString(), req);
-        }
-
-        /// <summary>
-        /// 將後台要傳給電樁的request轉換成Call Message
-        /// </summary>
-        /// <param name="uniqueId">OCPP Call Message uniqueId</param>
-        /// <param name="action">OCPP Call Message action</param>
-        /// <param name="request">Request Message</param>
-        /// <returns></returns>
-        public string GenerateCall(string uniqueId, string action, object request)
-        {
-            try
-            {
-                return MakeCall(uniqueId, action, PackPayload(request));
-            }
-            catch (Exception ex)
-            {
-                logger.Error(ex);
-                throw new ApplicationException(ex.ToString());
-            }
-        }
-
-        /// <summary>
-        /// 將後台要傳給電樁的comfirm轉換成CallResult Message
-        /// </summary>
-        /// <param name="uniqueId">OCPP Call Message uniqueId</param>
-        /// <param name="confirmation">Confirmation Message</param>
-        /// <returns></returns>
-        public string GenerateCallResult(string uniqueId, object confirmation)
-        {
-            try
-            {
-                return MakeCallResult(uniqueId, PackPayload(confirmation));
-            }
-            catch (Exception ex)
-            {
-                logger.Error(ex);
-                throw new ApplicationException(ex.ToString());
-            }
-        }
-
-        /// <summary>
-        /// 將後台要傳給電樁的錯誤訊息轉換成CallError Message
-        /// </summary>
-        /// <param name="uniqueId">OCPP CallError Message uniqueId</param>
-        /// <param name="errorCode">OCPP CallError Message errorCode</param>
-        /// <param name="errorDescription">OCPP CallError Message errorDescription</param>
-        /// <returns></returns>
-        public string GenerateCallError(string uniqueId, string errorCode, string errorDescription)
-        {
-            try
-            {
-                return MakeCallError(uniqueId, errorCode, errorDescription);
-            }
-            catch (Exception ex)
-            {
-                logger.Error(ex);
-                throw new ApplicationException(ex.ToString());
-            }
-        }
-
-        /// <summary>
-        /// 產生CallResult Message
-        /// </summary>
-        /// <param name="uniqueId">OCPP CallResult Message uniqueId</param>
-        /// <param name="payload">OCPP CallResult Message payload</param>
-        /// <returns></returns>
-        private string MakeCallResult(string uniqueId, object payload)
-        {
-            const string CALLRESULT_FORMAT = "[3,\"{0}\",{1}]";
-            return string.Format(CALLRESULT_FORMAT, uniqueId, payload.ToString());
-        }
-
-        /// <summary>
-        /// 產生Call Message
-        /// </summary>
-        /// <param name="uniqueId">OCPP CallResult Message uniqueId</param>
-        /// <param name="action">OCPP CallResult Message action</param>
-        /// <param name="payload">OCPP CallResult Message payload</param>
-        /// <returns></returns>
-        private string MakeCall(string uniqueId, string action, object payload)
-        {
-            const string CALL_FORMAT = "[2,\"{0}\",\"{1}\",{2}]";
-            return string.Format(CALL_FORMAT, uniqueId, action, payload.ToString());
-        }
-
-        /// <summary>
-        /// 產生CallError Message
-        /// </summary>
-        /// <param name="uniqueId">OCPP CallError Message uniqueId</param>
-        /// <param name="errorCode">OCPP CallError Message errorCode</param>
-        /// <param name="errorDescription">OCPP CallError Message errorDescription</param>
-        /// <returns></returns>
-        private string MakeCallError(string uniqueId, string errorCode, string errorDescription)
-        {
-            const string CALLERROR_FORMAT = "[4,\"{0}\",\"{1}\",\"{2}\",{3}]";
-            return string.Format(CALLERROR_FORMAT, uniqueId, errorCode, errorDescription, "{}");
-        }
-
-        /// <summary>
-        /// 處理OCPP CallResult Message
-        /// </summary>
-        /// <param name="id">OCPP CallResult Message uniqueId</param>
-        /// <param name="payload">OCPP CallResult Message payload</param>
-        /// <param name="queue">OCPP CallResult Message queue</param>
-        /// <param name="messageType">OCPP CallResult Message messageType</param>
-        /// <returns></returns>
-        public OCPPResult OnCallResult(string id, object payload, ref Queue queue, out string messageType)
-        {
-            OCPPResult result = new OCPPResult();
-
-            try
-            {
-                IRequest request;
-                Type actionType = GetConfirmationType(ref queue, id, out request);
-
-                if (request == null)
-                {
-                    messageType = "There are two conditions. Maybe it was sent repeatedly or there is no related Request. ";
-                    result.Message = "none";
-                    result.Success = false;
-                }
-                else
-                {
-                    IConfirmation confirmation = (IConfirmation)UnpackPayload(payload, actionType);
-                    if (actionType.Name.Contains("DataTransferConfirmation"))
-                    {
-                        messageType = "DataTransfer Confirmation(" + ((DataTransferRequest)request).messageId + ")";
-                    }
-                    else if (actionType.Name.Contains("TriggerMessageConfirmation"))
-                    {
-                        messageType = "TriggerMessage Confirmation(" + ((TriggerMessageRequest)request).requestedMessage.ToString() + ")";
-                    }
-                    else
-                    {
-                        messageType = actionType.Name.Remove(actionType.Name.IndexOf("Confirmation")) + " Confirmation";
-                    }
-
-                    if (confirmation.Validate())
-                    {
-                        result.Payload = confirmation;
-                        result.Success = true;
-                    }
-                    else
-                    {
-                        result.Message = GenerateCallError(id, "OccurenceConstraintViolation", "Payload for Action is syntactically correct but at least one of the fields violates occurence constraints");
-                        result.Success = false;
-                    }
-                }
-            }
-            catch (Exception ex)
-            {
-                logger.Error(ex);
-                result.Exception = ex;
-                messageType = string.Empty;
-                result.Success = false;
-            }
-            return result;
-        }
-
-        /// <summary>
-        /// 處理OCPP CALL Message
-        /// </summary>
-        /// <param name="id">OCPP CALL Message uniqueId</param>
-        /// <param name="action">OCPP CALL Message action</param>
-        /// <param name="payload">OCPP CALL Message payload</param>
-        /// <returns></returns>
-        public OCPPResult OnCall(string id, string action, object payload)
-        {
-            OCPPResult result = new OCPPResult();
-            Feature feature = featureHandler.FindFeatureByAction(action);
-            if (feature == null)
-            {
-                result.Message = GenerateCallError(id, "NotImplemented", "Requested Action is not known by receiver");
-                result.Success = false;
-            }
-            else
-            {
-                try
-                {
-                    IRequest request = (IRequest)UnpackPayload(payload, feature.GetRequestType());
-                    if (request.Validate())
-                    {
-                        result.Payload = request;
-                        result.Success = true;
-                    }
-                    else
-                    {
-                        result.Message = GenerateCallError(id, "OccurenceConstraintViolation", "Payload for Action is syntactically correct but at least one of the fields violates occurence constraints");
-                        result.Success = false;
-                    }
-                }
-                catch (Exception ex)
-                {
-                    logger.Error(ex);
-                    result.Exception = ex;
-                    result.Success = false;
-                }
-            }
-            return result;
-        }
-
-        /// <summary>
-        /// 處理OCPP Error Message
-        /// </summary>
-        /// <param name="id">OCPP Error Message uniqueId</param>
-        /// <param name="errorCode">OCPP Error Message errorCode</param>
-        /// <param name="errorDescription">OCPP Error Message errorDescription</param>
-        /// <param name="payload">OCPP Error Message payload</param>
-        /// <returns></returns>
-        public OCPPResult OnError(string id, string errorCode, string errorDescription, object payload)
-        {
-            OCPPResult result = new OCPPResult();
-            result.Success = true;
-            return result;
-        }
-    }
-}

+ 0 - 60
OCPPServer/NLog.config

@@ -1,60 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
-      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-      xsi:schemaLocation="http://www.nlog-project.org/schemas/NLog.xsd NLog.xsd"
-      autoReload="true"
-      throwExceptions="false"
-      internalLogLevel="Off" internalLogFile="c:\temp\nlog-internal.log">
-
-  <!-- optional, add some variabeles
-  https://github.com/nlog/NLog/wiki/Configuration-file#variables
-  -->
-  <variable name="myvar" value="myvalue" />
-
-  <!--
-  See https://github.com/nlog/nlog/wiki/Configuration-file
-  for information on customizing logging rules and outputs.
-   -->
-  <targets>
-    <target name="console" xsi:type="Console" layout="${date:format=HH\:MM\:ss} ${logger} ${message}" />
-    <target xsi:type="File" name="f" fileName="${basedir}/logs/${shortdate}.log"
-            layout="${longdate} ${uppercase:${level}} ${message}" />
-
-    <target xsi:type="Database" name="databaseLog"
-    commandText="insert into NlogTable (CreatedOn, LogLevel, Logger, Msg,Host,Type,Source,Stacktrace,Detail) Values (@CreatedOn, @LogLevel, @Logger, @Msg,@Host,@Type,@Source,@Stacktrace,@Detail)">
-      <connectionStringName>DefaultConnection</connectionStringName>
-      <parameter name="@CreatedOn" layout="${date}" />
-      <parameter name="@LogLevel" layout="${level}" />
-      <parameter name="@Logger" layout="${logger}" />
-      <parameter name="@Msg" layout="${message}" />
-      <parameter name="@Host" layout="${machinename}" />
-      <parameter name="@Type" layout="${exception:format=type}" />
-      <parameter name="@Source" layout="${callsite:className=true}" />
-      <parameter name="@Stacktrace" layout="${exception:stacktrace}" />
-      <parameter name="@Detail" layout="${exception:format=tostring}" />
-    </target>
-    <!--
-    add your targets here
-    See https://github.com/nlog/NLog/wiki/Targets for possible targets.
-    See https://github.com/nlog/NLog/wiki/Layout-Renderers for the possible layout renderers.
-    -->
-
-    <!--
-    Writing events to the a file with the date in the filename.
-    <target xsi:type="File" name="f" fileName="${basedir}/logs/${shortdate}.log"
-            layout="${longdate} ${uppercase:${level}} ${message}" />
-    -->
-  </targets>
-
-  <rules>
-    <logger name="*" minlevel="Trace" writeTo="f" />
-    <logger name="*" minlevel="Info" writeTo="console" />
-    <logger name="*" minlevel="Error" writeTo="databaseLog" />
-    <!-- add your logging rules here -->
-
-    <!--
-    Write all events with minimal level of Debug (So Debug, Info, Warn, Error and Fatal, but not Trace)  to "f"
-    <logger name="*" minlevel="Debug" writeTo="f" />
-    -->
-  </rules>
-</nlog>

+ 0 - 3027
OCPPServer/NLog.xsd

@@ -1,3027 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<xs:schema id="NLog" targetNamespace="http://www.nlog-project.org/schemas/NLog.xsd" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns="http://www.nlog-project.org/schemas/NLog.xsd">
-  <xs:element name="nlog" type="NLogConfiguration" />
-  <xs:complexType name="NLogConfiguration">
-    <xs:choice minOccurs="0" maxOccurs="unbounded">
-      <xs:element name="extensions" type="NLogExtensions" />
-      <xs:element name="include" type="NLogInclude" />
-      <xs:element name="variable" type="NLogVariable" />
-      <xs:element name="targets" type="NLogTargets" />
-      <xs:element name="rules" type="NLogRules" />
-      <xs:element name="time" type="TimeSource" />
-    </xs:choice>
-    <xs:attribute name="autoReload" type="xs:boolean">
-      <xs:annotation>
-        <xs:documentation>Watch config file for changes and reload automatically.</xs:documentation>
-      </xs:annotation>
-    </xs:attribute>
-    <xs:attribute name="internalLogToConsole" type="xs:boolean">
-      <xs:annotation>
-        <xs:documentation>Print internal NLog messages to the console. Default value is: false</xs:documentation>
-      </xs:annotation>
-    </xs:attribute>
-    <xs:attribute name="internalLogToConsoleError" type="xs:boolean">
-      <xs:annotation>
-        <xs:documentation>Print internal NLog messages to the console error output. Default value is: false</xs:documentation>
-      </xs:annotation>
-    </xs:attribute>
-    <xs:attribute name="internalLogFile" type="xs:string">
-      <xs:annotation>
-        <xs:documentation>Write internal NLog messages to the specified file.</xs:documentation>
-      </xs:annotation>
-    </xs:attribute>
-    <xs:attribute name="internalLogLevel" type="NLogLevel">
-      <xs:annotation>
-        <xs:documentation>Log level threshold for internal log messages. Default value is: Info.</xs:documentation>
-      </xs:annotation>
-    </xs:attribute>
-    <xs:attribute name="globalThreshold" type="NLogLevel">
-      <xs:annotation>
-        <xs:documentation>Global log level threshold for application log messages. Messages below this level won't be logged..</xs:documentation>
-      </xs:annotation>
-    </xs:attribute>
-    <xs:attribute name="throwExceptions" type="xs:boolean">
-      <xs:annotation>
-        <xs:documentation>Throw an exception when there is an internal error. Default value is: false.</xs:documentation>
-      </xs:annotation>
-    </xs:attribute>
-    <xs:attribute name="throwConfigExceptions" type="xs:boolean">
-      <xs:annotation>
-        <xs:documentation>Throw an exception when there is a configuration error. If not set, determined by throwExceptions.</xs:documentation>
-      </xs:annotation>
-    </xs:attribute>
-    <xs:attribute name="keepVariablesOnReload" type="xs:boolean">
-      <xs:annotation>
-        <xs:documentation>Gets or sets a value indicating whether Variables should be kept on configuration reload. Default value is: false.</xs:documentation>
-      </xs:annotation>
-    </xs:attribute>
-    <xs:attribute name="internalLogToTrace" type="xs:boolean">
-      <xs:annotation>
-        <xs:documentation>Write internal NLog messages to the System.Diagnostics.Trace. Default value is: false.</xs:documentation>
-      </xs:annotation>
-    </xs:attribute>
-    <xs:attribute name="internalLogIncludeTimestamp" type="xs:boolean">
-      <xs:annotation>
-        <xs:documentation>Write timestamps for internal NLog messages. Default value is: true.</xs:documentation>
-      </xs:annotation>
-    </xs:attribute>
-    <xs:attribute name="useInvariantCulture" type="xs:boolean">
-      <xs:annotation>
-        <xs:documentation>Use InvariantCulture as default culture instead of CurrentCulture.  Default value is: false.</xs:documentation>
-      </xs:annotation>
-    </xs:attribute>
-  </xs:complexType>
-  <xs:complexType name="NLogTargets">
-    <xs:choice minOccurs="0" maxOccurs="unbounded">
-      <xs:element name="default-wrapper" type="WrapperTargetBase" />
-      <xs:element name="default-target-parameters" type="Target" />
-      <xs:element name="target" type="Target" />
-      <xs:element name="wrapper-target" type="WrapperTargetBase" />
-      <xs:element name="compound-target" type="CompoundTargetBase" />
-    </xs:choice>
-    <xs:attribute name="async" type="xs:boolean">
-      <xs:annotation>
-        <xs:documentation>Make all targets within this section asynchronous (creates additional threads but the calling thread isn't blocked by any target writes).</xs:documentation>
-      </xs:annotation>
-    </xs:attribute>
-  </xs:complexType>
-  <xs:complexType name="NLogRules">
-    <xs:sequence minOccurs="0" maxOccurs="unbounded">
-      <xs:element name="logger" type="NLogLoggerRule" />
-    </xs:sequence>
-  </xs:complexType>
-  <xs:complexType name="NLogExtensions">
-    <xs:choice minOccurs="0" maxOccurs="unbounded">
-      <xs:element name="add" type="NLogExtensionsAdd" />
-    </xs:choice>
-  </xs:complexType>
-  <xs:complexType name="NLogExtensionsAdd">
-    <xs:attribute name="prefix" type="xs:string">
-      <xs:annotation>
-        <xs:documentation>Prefix for targets/layout renderers/filters/conditions loaded from this assembly.</xs:documentation>
-      </xs:annotation>
-    </xs:attribute>
-    <xs:attribute name="assemblyFile" type="xs:string">
-      <xs:annotation>
-        <xs:documentation>Load NLog extensions from the specified file (*.dll)</xs:documentation>
-      </xs:annotation>
-    </xs:attribute>
-    <xs:attribute name="assembly" type="xs:string">
-      <xs:annotation>
-        <xs:documentation>Load NLog extensions from the specified assembly. Assembly name should be fully qualified.</xs:documentation>
-      </xs:annotation>
-    </xs:attribute>
-  </xs:complexType>
-  <xs:complexType name="NLogLoggerRule">
-    <xs:choice minOccurs="0" maxOccurs="unbounded">
-      <xs:element name="filters" type="NLogFilters" />
-    </xs:choice>
-    <xs:attribute name="name" use="optional">
-      <xs:annotation>
-        <xs:documentation>Name of the logger. May include '*' character which acts like a wildcard. Allowed forms are: *, Name, *Name, Name* and *Name*</xs:documentation>
-      </xs:annotation>
-    </xs:attribute>
-    <xs:attribute name="levels" type="NLogLevelList">
-      <xs:annotation>
-        <xs:documentation>Comma separated list of levels that this rule matches.</xs:documentation>
-      </xs:annotation>
-    </xs:attribute>
-    <xs:attribute name="minlevel" type="NLogLevel">
-      <xs:annotation>
-        <xs:documentation>Minimum level that this rule matches.</xs:documentation>
-      </xs:annotation>
-    </xs:attribute>
-    <xs:attribute name="maxlevel" type="NLogLevel">
-      <xs:annotation>
-        <xs:documentation>Maximum level that this rule matches.</xs:documentation>
-      </xs:annotation>
-    </xs:attribute>
-    <xs:attribute name="level" type="NLogLevel">
-      <xs:annotation>
-        <xs:documentation>Level that this rule matches.</xs:documentation>
-      </xs:annotation>
-    </xs:attribute>
-    <xs:attribute name="writeTo" type="NLogTargetIDList">
-      <xs:annotation>
-        <xs:documentation>Comma separated list of target names.</xs:documentation>
-      </xs:annotation>
-    </xs:attribute>
-    <xs:attribute name="final" type="xs:boolean" default="false">
-      <xs:annotation>
-        <xs:documentation>Ignore further rules if this one matches.</xs:documentation>
-      </xs:annotation>
-    </xs:attribute>
-    <xs:attribute name="enabled" type="xs:boolean" default="true">
-      <xs:annotation>
-        <xs:documentation>Enable or disable logging rule. Disabled rules are ignored.</xs:documentation>
-      </xs:annotation>
-    </xs:attribute>
-  </xs:complexType>
-  <xs:complexType name="NLogFilters">
-    <xs:choice minOccurs="0" maxOccurs="unbounded">
-      <xs:element name="when" type="when" />
-      <xs:element name="whenContains" type="whenContains" />
-      <xs:element name="whenEqual" type="whenEqual" />
-      <xs:element name="whenNotContains" type="whenNotContains" />
-      <xs:element name="whenNotEqual" type="whenNotEqual" />
-    </xs:choice>
-  </xs:complexType>
-  <xs:simpleType name="NLogLevel">
-    <xs:restriction base="xs:string">
-      <xs:enumeration value="Off" />
-      <xs:enumeration value="Trace" />
-      <xs:enumeration value="Debug" />
-      <xs:enumeration value="Info" />
-      <xs:enumeration value="Warn" />
-      <xs:enumeration value="Error" />
-      <xs:enumeration value="Fatal" />
-    </xs:restriction>
-  </xs:simpleType>
-  <xs:simpleType name="LineEndingMode">
-    <xs:restriction base="xs:string">
-      <xs:enumeration value="Default" />
-      <xs:enumeration value="CRLF" />
-      <xs:enumeration value="CR" />
-      <xs:enumeration value="LF" />
-      <xs:enumeration value="None" />
-    </xs:restriction>
-  </xs:simpleType>
-  <xs:simpleType name="NLogLevelList">
-    <xs:restriction base="xs:string">
-      <xs:pattern value="(|Trace|Debug|Info|Warn|Error|Fatal)(,(Trace|Debug|Info|Warn|Error|Fatal))*" />
-    </xs:restriction>
-  </xs:simpleType>
-  <xs:complexType name="NLogInclude">
-    <xs:attribute name="file" type="SimpleLayoutAttribute" use="required">
-      <xs:annotation>
-        <xs:documentation>Name of the file to be included. You could use * wildcard. The name is relative to the name of the current config file.</xs:documentation>
-      </xs:annotation>
-    </xs:attribute>
-    <xs:attribute name="ignoreErrors" type="xs:boolean" use="optional" default="false">
-      <xs:annotation>
-        <xs:documentation>Ignore any errors in the include file.</xs:documentation>
-      </xs:annotation>
-    </xs:attribute>
-  </xs:complexType>
-  <xs:complexType name="NLogVariable">
-    <xs:attribute name="name" type="xs:string" use="required">
-      <xs:annotation>
-        <xs:documentation>Variable name.</xs:documentation>
-      </xs:annotation>
-    </xs:attribute>
-    <xs:attribute name="value" type="SimpleLayoutAttribute" use="required">
-      <xs:annotation>
-        <xs:documentation>Variable value.</xs:documentation>
-      </xs:annotation>
-    </xs:attribute>
-  </xs:complexType>
-  <xs:simpleType name="NLogTargetIDList">
-    <xs:restriction base="xs:string">
-      <xs:pattern value="(|([a-zA-Z][a-zA-Z0-9_\-]*))(,([a-zA-Z][a-zA-Z0-9_\-]*))*" />
-    </xs:restriction>
-  </xs:simpleType>
-  <xs:complexType name="Target" abstract="true"></xs:complexType>
-  <xs:complexType name="TargetRef">
-    <xs:attribute name="name" type="xs:string" use="required" />
-  </xs:complexType>
-  <xs:complexType name="WrapperTargetBase" abstract="true">
-    <xs:complexContent>
-      <xs:extension base="Target">
-        <xs:choice minOccurs="0" maxOccurs="unbounded">
-          <xs:element name="target" type="Target" minOccurs="1" maxOccurs="1" />
-          <xs:element name="wrapper-target" type="WrapperTargetBase" minOccurs="1" maxOccurs="1" />
-          <xs:element name="compound-target" type="CompoundTargetBase" minOccurs="1" maxOccurs="1" />
-          <xs:element name="target-ref" type="TargetRef" minOccurs="1" maxOccurs="1" />
-          <xs:element name="wrapper-target-ref" type="TargetRef" minOccurs="1" maxOccurs="1" />
-          <xs:element name="compound-target-ref" type="TargetRef" minOccurs="1" maxOccurs="1" />
-        </xs:choice>
-      </xs:extension>
-    </xs:complexContent>
-  </xs:complexType>
-  <xs:complexType name="CompoundTargetBase" abstract="true">
-    <xs:complexContent>
-      <xs:extension base="Target">
-        <xs:choice minOccurs="0" maxOccurs="unbounded">
-          <xs:element name="target" type="Target" minOccurs="1" maxOccurs="unbounded" />
-          <xs:element name="wrapper-target" type="WrapperTargetBase" minOccurs="1" maxOccurs="1" />
-          <xs:element name="compound-target" type="CompoundTargetBase" minOccurs="1" maxOccurs="1" />
-          <xs:element name="target-ref" type="TargetRef" minOccurs="1" maxOccurs="1" />
-          <xs:element name="wrapper-target-ref" type="TargetRef" minOccurs="1" maxOccurs="1" />
-          <xs:element name="compound-target-ref" type="TargetRef" minOccurs="1" maxOccurs="1" />
-        </xs:choice>
-      </xs:extension>
-    </xs:complexContent>
-  </xs:complexType>
-  <xs:complexType name="Filter" abstract="true"></xs:complexType>
-  <xs:complexType name="TimeSource" abstract="true"></xs:complexType>
-  <xs:simpleType name="SimpleLayoutAttribute">
-    <xs:restriction base="xs:string">
-      <xs:pattern value=".*" />
-    </xs:restriction>
-  </xs:simpleType>
-  <xs:simpleType name="Condition">
-    <xs:restriction base="xs:string">
-      <xs:minLength value="1" />
-    </xs:restriction>
-  </xs:simpleType>
-  <xs:complexType name="AsyncWrapper">
-    <xs:complexContent>
-      <xs:extension base="WrapperTargetBase">
-        <xs:choice minOccurs="0" maxOccurs="unbounded">
-          <xs:element name="name" minOccurs="0" maxOccurs="1" type="xs:string" />
-          <xs:element name="batchSize" minOccurs="0" maxOccurs="1" type="xs:integer" />
-          <xs:element name="fullBatchSizeWriteLimit" minOccurs="0" maxOccurs="1" type="xs:integer" />
-          <xs:element name="overflowAction" minOccurs="0" maxOccurs="1" type="NLog.Targets.Wrappers.AsyncTargetWrapperOverflowAction" />
-          <xs:element name="queueLimit" minOccurs="0" maxOccurs="1" type="xs:integer" />
-          <xs:element name="timeToSleepBetweenBatches" minOccurs="0" maxOccurs="1" type="xs:integer" />
-          <xs:element name="optimizeBufferReuse" minOccurs="0" maxOccurs="1" type="xs:boolean" />
-        </xs:choice>
-        <xs:attribute name="name" type="xs:string">
-          <xs:annotation>
-            <xs:documentation>Name of the target.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="batchSize" type="xs:integer">
-          <xs:annotation>
-            <xs:documentation>Number of log events that should be processed in a batch by the lazy writer thread.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="fullBatchSizeWriteLimit" type="xs:integer">
-          <xs:annotation>
-            <xs:documentation>Limit of full s to write before yielding into  Performance is better when writing many small batches, than writing a single large batch</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="overflowAction" type="NLog.Targets.Wrappers.AsyncTargetWrapperOverflowAction">
-          <xs:annotation>
-            <xs:documentation>Action to be taken when the lazy writer thread request queue count exceeds the set limit.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="queueLimit" type="xs:integer">
-          <xs:annotation>
-            <xs:documentation>Limit on the number of requests in the lazy writer thread request queue.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="timeToSleepBetweenBatches" type="xs:integer">
-          <xs:annotation>
-            <xs:documentation>Time in milliseconds to sleep between batches.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="optimizeBufferReuse" type="xs:boolean">
-          <xs:annotation>
-            <xs:documentation>Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-      </xs:extension>
-    </xs:complexContent>
-  </xs:complexType>
-  <xs:simpleType name="NLog.Targets.Wrappers.AsyncTargetWrapperOverflowAction">
-    <xs:restriction base="xs:string">
-      <xs:enumeration value="Grow" />
-      <xs:enumeration value="Discard" />
-      <xs:enumeration value="Block" />
-    </xs:restriction>
-  </xs:simpleType>
-  <xs:complexType name="AutoFlushWrapper">
-    <xs:complexContent>
-      <xs:extension base="WrapperTargetBase">
-        <xs:choice minOccurs="0" maxOccurs="unbounded">
-          <xs:element name="name" minOccurs="0" maxOccurs="1" type="xs:string" />
-          <xs:element name="asyncFlush" minOccurs="0" maxOccurs="1" type="xs:boolean" />
-          <xs:element name="condition" minOccurs="0" maxOccurs="1" type="Condition" />
-          <xs:element name="optimizeBufferReuse" minOccurs="0" maxOccurs="1" type="xs:boolean" />
-        </xs:choice>
-        <xs:attribute name="name" type="xs:string">
-          <xs:annotation>
-            <xs:documentation>Name of the target.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="asyncFlush" type="xs:boolean">
-          <xs:annotation>
-            <xs:documentation>Delay the flush until the LogEvent has been confirmed as written</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="condition" type="Condition">
-          <xs:annotation>
-            <xs:documentation>Condition expression. Log events who meet this condition will cause a flush on the wrapped target.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="optimizeBufferReuse" type="xs:boolean">
-          <xs:annotation>
-            <xs:documentation>Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-      </xs:extension>
-    </xs:complexContent>
-  </xs:complexType>
-  <xs:complexType name="BufferingWrapper">
-    <xs:complexContent>
-      <xs:extension base="WrapperTargetBase">
-        <xs:choice minOccurs="0" maxOccurs="unbounded">
-          <xs:element name="name" minOccurs="0" maxOccurs="1" type="xs:string" />
-          <xs:element name="bufferSize" minOccurs="0" maxOccurs="1" type="xs:integer" />
-          <xs:element name="flushTimeout" minOccurs="0" maxOccurs="1" type="xs:integer" />
-          <xs:element name="slidingTimeout" minOccurs="0" maxOccurs="1" type="xs:boolean" />
-          <xs:element name="optimizeBufferReuse" minOccurs="0" maxOccurs="1" type="xs:boolean" />
-        </xs:choice>
-        <xs:attribute name="name" type="xs:string">
-          <xs:annotation>
-            <xs:documentation>Name of the target.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="bufferSize" type="xs:integer">
-          <xs:annotation>
-            <xs:documentation>Number of log events to be buffered.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="flushTimeout" type="xs:integer">
-          <xs:annotation>
-            <xs:documentation>Timeout (in milliseconds) after which the contents of buffer will be flushed if there's no write in the specified period of time. Use -1 to disable timed flushes.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="slidingTimeout" type="xs:boolean">
-          <xs:annotation>
-            <xs:documentation>Indicates whether to use sliding timeout.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="optimizeBufferReuse" type="xs:boolean">
-          <xs:annotation>
-            <xs:documentation>Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-      </xs:extension>
-    </xs:complexContent>
-  </xs:complexType>
-  <xs:complexType name="Chainsaw">
-    <xs:complexContent>
-      <xs:extension base="Target">
-        <xs:choice minOccurs="0" maxOccurs="unbounded">
-          <xs:element name="name" minOccurs="0" maxOccurs="1" type="xs:string" />
-          <xs:element name="encoding" minOccurs="0" maxOccurs="1" type="xs:string" />
-          <xs:element name="layout" minOccurs="0" maxOccurs="1" type="Layout" />
-          <xs:element name="lineEnding" minOccurs="0" maxOccurs="1" type="LineEndingMode" />
-          <xs:element name="maxMessageSize" minOccurs="0" maxOccurs="1" type="xs:integer" />
-          <xs:element name="newLine" minOccurs="0" maxOccurs="1" type="xs:boolean" />
-          <xs:element name="onConnectionOverflow" minOccurs="0" maxOccurs="1" type="NLog.Targets.NetworkTargetConnectionsOverflowAction" />
-          <xs:element name="onOverflow" minOccurs="0" maxOccurs="1" type="NLog.Targets.NetworkTargetOverflowAction" />
-          <xs:element name="maxConnections" minOccurs="0" maxOccurs="1" type="xs:integer" />
-          <xs:element name="keepConnection" minOccurs="0" maxOccurs="1" type="xs:boolean" />
-          <xs:element name="connectionCacheSize" minOccurs="0" maxOccurs="1" type="xs:integer" />
-          <xs:element name="address" minOccurs="0" maxOccurs="1" type="Layout" />
-          <xs:element name="maxQueueSize" minOccurs="0" maxOccurs="1" type="xs:integer" />
-          <xs:element name="parameter" minOccurs="0" maxOccurs="unbounded" type="NLog.Targets.NLogViewerParameterInfo" />
-          <xs:element name="includeNdc" minOccurs="0" maxOccurs="1" type="xs:boolean" />
-          <xs:element name="includeSourceInfo" minOccurs="0" maxOccurs="1" type="xs:boolean" />
-          <xs:element name="includeNLogData" minOccurs="0" maxOccurs="1" type="xs:boolean" />
-          <xs:element name="includeMdc" minOccurs="0" maxOccurs="1" type="xs:boolean" />
-          <xs:element name="includeCallSite" minOccurs="0" maxOccurs="1" type="xs:boolean" />
-          <xs:element name="appInfo" minOccurs="0" maxOccurs="1" type="xs:string" />
-          <xs:element name="ndcItemSeparator" minOccurs="0" maxOccurs="1" type="xs:string" />
-          <xs:element name="includeMdlc" minOccurs="0" maxOccurs="1" type="xs:boolean" />
-          <xs:element name="optimizeBufferReuse" minOccurs="0" maxOccurs="1" type="xs:boolean" />
-        </xs:choice>
-        <xs:attribute name="name" type="xs:string">
-          <xs:annotation>
-            <xs:documentation>Name of the target.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="encoding" type="xs:string">
-          <xs:annotation>
-            <xs:documentation>Encoding to be used.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="layout" type="SimpleLayoutAttribute">
-          <xs:annotation>
-            <xs:documentation>Instance of  that is used to format log messages.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="lineEnding" type="LineEndingMode">
-          <xs:annotation>
-            <xs:documentation>End of line value if a newline is appended at the end of log message .</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="maxMessageSize" type="xs:integer">
-          <xs:annotation>
-            <xs:documentation>Maximum message size in bytes.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="newLine" type="xs:boolean">
-          <xs:annotation>
-            <xs:documentation>Indicates whether to append newline at the end of log message.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="onConnectionOverflow" type="NLog.Targets.NetworkTargetConnectionsOverflowAction">
-          <xs:annotation>
-            <xs:documentation>Action that should be taken if the will be more connections than .</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="onOverflow" type="NLog.Targets.NetworkTargetOverflowAction">
-          <xs:annotation>
-            <xs:documentation>Action that should be taken if the message is larger than maxMessageSize.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="maxConnections" type="xs:integer">
-          <xs:annotation>
-            <xs:documentation>Maximum current connections. 0 = no maximum.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="keepConnection" type="xs:boolean">
-          <xs:annotation>
-            <xs:documentation>Indicates whether to keep connection open whenever possible.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="connectionCacheSize" type="xs:integer">
-          <xs:annotation>
-            <xs:documentation>Size of the connection cache (number of connections which are kept alive).</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="address" type="SimpleLayoutAttribute">
-          <xs:annotation>
-            <xs:documentation>Network address.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="maxQueueSize" type="xs:integer">
-          <xs:annotation>
-            <xs:documentation>Maximum queue size.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="includeNdc" type="xs:boolean">
-          <xs:annotation>
-            <xs:documentation>Indicates whether to include  stack contents.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="includeSourceInfo" type="xs:boolean">
-          <xs:annotation>
-            <xs:documentation>Indicates whether to include source info (file name and line number) in the information sent over the network.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="includeNLogData" type="xs:boolean">
-          <xs:annotation>
-            <xs:documentation>Indicates whether to include NLog-specific extensions to log4j schema.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="includeMdc" type="xs:boolean">
-          <xs:annotation>
-            <xs:documentation>Indicates whether to include  dictionary contents.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="includeCallSite" type="xs:boolean">
-          <xs:annotation>
-            <xs:documentation>Indicates whether to include call site (class and method name) in the information sent over the network.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="appInfo" type="xs:string">
-          <xs:annotation>
-            <xs:documentation>AppInfo field. By default it's the friendly name of the current AppDomain.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="ndcItemSeparator" type="xs:string">
-          <xs:annotation>
-            <xs:documentation>NDC item separator.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="includeMdlc" type="xs:boolean">
-          <xs:annotation>
-            <xs:documentation>Indicates whether to include  dictionary contents.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="optimizeBufferReuse" type="xs:boolean">
-          <xs:annotation>
-            <xs:documentation>Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-      </xs:extension>
-    </xs:complexContent>
-  </xs:complexType>
-  <xs:simpleType name="NLog.Targets.NetworkTargetConnectionsOverflowAction">
-    <xs:restriction base="xs:string">
-      <xs:enumeration value="AllowNewConnnection" />
-      <xs:enumeration value="DiscardMessage" />
-      <xs:enumeration value="Block" />
-    </xs:restriction>
-  </xs:simpleType>
-  <xs:simpleType name="NLog.Targets.NetworkTargetOverflowAction">
-    <xs:restriction base="xs:string">
-      <xs:enumeration value="Error" />
-      <xs:enumeration value="Split" />
-      <xs:enumeration value="Discard" />
-    </xs:restriction>
-  </xs:simpleType>
-  <xs:complexType name="NLog.Targets.NLogViewerParameterInfo">
-    <xs:choice minOccurs="0" maxOccurs="unbounded">
-      <xs:element name="layout" minOccurs="0" maxOccurs="1" type="Layout" />
-      <xs:element name="name" minOccurs="0" maxOccurs="1" type="xs:string" />
-    </xs:choice>
-    <xs:attribute name="layout" type="SimpleLayoutAttribute">
-      <xs:annotation>
-        <xs:documentation>Layout that should be use to calcuate the value for the parameter.</xs:documentation>
-      </xs:annotation>
-    </xs:attribute>
-    <xs:attribute name="name" type="xs:string">
-      <xs:annotation>
-        <xs:documentation>Viewer parameter name.</xs:documentation>
-      </xs:annotation>
-    </xs:attribute>
-  </xs:complexType>
-  <xs:complexType name="ColoredConsole">
-    <xs:complexContent>
-      <xs:extension base="Target">
-        <xs:choice minOccurs="0" maxOccurs="unbounded">
-          <xs:element name="name" minOccurs="0" maxOccurs="1" type="xs:string" />
-          <xs:element name="layout" minOccurs="0" maxOccurs="1" type="Layout" />
-          <xs:element name="header" minOccurs="0" maxOccurs="1" type="Layout" />
-          <xs:element name="footer" minOccurs="0" maxOccurs="1" type="Layout" />
-          <xs:element name="useDefaultRowHighlightingRules" minOccurs="0" maxOccurs="1" type="xs:boolean" />
-          <xs:element name="highlight-row" minOccurs="0" maxOccurs="unbounded" type="NLog.Targets.ConsoleRowHighlightingRule" />
-          <xs:element name="highlight-word" minOccurs="0" maxOccurs="unbounded" type="NLog.Targets.ConsoleWordHighlightingRule" />
-          <xs:element name="detectConsoleAvailable" minOccurs="0" maxOccurs="1" type="xs:boolean" />
-          <xs:element name="encoding" minOccurs="0" maxOccurs="1" type="xs:string" />
-          <xs:element name="errorStream" minOccurs="0" maxOccurs="1" type="xs:boolean" />
-          <xs:element name="optimizeBufferReuse" minOccurs="0" maxOccurs="1" type="xs:boolean" />
-        </xs:choice>
-        <xs:attribute name="name" type="xs:string">
-          <xs:annotation>
-            <xs:documentation>Name of the target.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="layout" type="SimpleLayoutAttribute">
-          <xs:annotation>
-            <xs:documentation>Text to be rendered.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="header" type="SimpleLayoutAttribute">
-          <xs:annotation>
-            <xs:documentation>Header.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="footer" type="SimpleLayoutAttribute">
-          <xs:annotation>
-            <xs:documentation>Footer.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="useDefaultRowHighlightingRules" type="xs:boolean">
-          <xs:annotation>
-            <xs:documentation>Indicates whether to use default row highlighting rules.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="detectConsoleAvailable" type="xs:boolean">
-          <xs:annotation>
-            <xs:documentation>Indicates whether to auto-check if the console is available. - Disables console writing if Environment.UserInteractive = False (Windows Service) - Disables console writing if Console Standard Input is not available (Non-Console-App)</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="encoding" type="xs:string">
-          <xs:annotation>
-            <xs:documentation>The encoding for writing messages to the .</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="errorStream" type="xs:boolean">
-          <xs:annotation>
-            <xs:documentation>Indicates whether the error stream (stderr) should be used instead of the output stream (stdout).</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="optimizeBufferReuse" type="xs:boolean">
-          <xs:annotation>
-            <xs:documentation>Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-      </xs:extension>
-    </xs:complexContent>
-  </xs:complexType>
-  <xs:simpleType name="NLog.Targets.ConsoleOutputColor">
-    <xs:restriction base="xs:string">
-      <xs:enumeration value="Black" />
-      <xs:enumeration value="DarkBlue" />
-      <xs:enumeration value="DarkGreen" />
-      <xs:enumeration value="DarkCyan" />
-      <xs:enumeration value="DarkRed" />
-      <xs:enumeration value="DarkMagenta" />
-      <xs:enumeration value="DarkYellow" />
-      <xs:enumeration value="Gray" />
-      <xs:enumeration value="DarkGray" />
-      <xs:enumeration value="Blue" />
-      <xs:enumeration value="Green" />
-      <xs:enumeration value="Cyan" />
-      <xs:enumeration value="Red" />
-      <xs:enumeration value="Magenta" />
-      <xs:enumeration value="Yellow" />
-      <xs:enumeration value="White" />
-      <xs:enumeration value="NoChange" />
-    </xs:restriction>
-  </xs:simpleType>
-  <xs:complexType name="NLog.Targets.ConsoleRowHighlightingRule">
-    <xs:choice minOccurs="0" maxOccurs="unbounded">
-      <xs:element name="condition" minOccurs="0" maxOccurs="1" type="Condition" />
-      <xs:element name="backgroundColor" minOccurs="0" maxOccurs="1" type="NLog.Targets.ConsoleOutputColor" />
-      <xs:element name="foregroundColor" minOccurs="0" maxOccurs="1" type="NLog.Targets.ConsoleOutputColor" />
-    </xs:choice>
-    <xs:attribute name="condition" type="Condition">
-      <xs:annotation>
-        <xs:documentation>Condition that must be met in order to set the specified foreground and background color.</xs:documentation>
-      </xs:annotation>
-    </xs:attribute>
-    <xs:attribute name="backgroundColor" type="NLog.Targets.ConsoleOutputColor">
-      <xs:annotation>
-        <xs:documentation>Background color.</xs:documentation>
-      </xs:annotation>
-    </xs:attribute>
-    <xs:attribute name="foregroundColor" type="NLog.Targets.ConsoleOutputColor">
-      <xs:annotation>
-        <xs:documentation>Foreground color.</xs:documentation>
-      </xs:annotation>
-    </xs:attribute>
-  </xs:complexType>
-  <xs:complexType name="NLog.Targets.ConsoleWordHighlightingRule">
-    <xs:choice minOccurs="0" maxOccurs="unbounded">
-      <xs:element name="ignoreCase" minOccurs="0" maxOccurs="1" type="xs:boolean" />
-      <xs:element name="regex" minOccurs="0" maxOccurs="1" type="xs:string" />
-      <xs:element name="text" minOccurs="0" maxOccurs="1" type="xs:string" />
-      <xs:element name="wholeWords" minOccurs="0" maxOccurs="1" type="xs:boolean" />
-      <xs:element name="compileRegex" minOccurs="0" maxOccurs="1" type="xs:boolean" />
-      <xs:element name="backgroundColor" minOccurs="0" maxOccurs="1" type="NLog.Targets.ConsoleOutputColor" />
-      <xs:element name="foregroundColor" minOccurs="0" maxOccurs="1" type="NLog.Targets.ConsoleOutputColor" />
-    </xs:choice>
-    <xs:attribute name="ignoreCase" type="xs:boolean">
-      <xs:annotation>
-        <xs:documentation>Indicates whether to ignore case when comparing texts.</xs:documentation>
-      </xs:annotation>
-    </xs:attribute>
-    <xs:attribute name="regex" type="xs:string">
-      <xs:annotation>
-        <xs:documentation>Regular expression to be matched. You must specify either text or regex.</xs:documentation>
-      </xs:annotation>
-    </xs:attribute>
-    <xs:attribute name="text" type="xs:string">
-      <xs:annotation>
-        <xs:documentation>Text to be matched. You must specify either text or regex.</xs:documentation>
-      </xs:annotation>
-    </xs:attribute>
-    <xs:attribute name="wholeWords" type="xs:boolean">
-      <xs:annotation>
-        <xs:documentation>Indicates whether to match whole words only.</xs:documentation>
-      </xs:annotation>
-    </xs:attribute>
-    <xs:attribute name="compileRegex" type="xs:boolean">
-      <xs:annotation>
-        <xs:documentation>Compile the ? This can improve the performance, but at the costs of more memory usage. If false, the Regex Cache is used.</xs:documentation>
-      </xs:annotation>
-    </xs:attribute>
-    <xs:attribute name="backgroundColor" type="NLog.Targets.ConsoleOutputColor">
-      <xs:annotation>
-        <xs:documentation>Background color.</xs:documentation>
-      </xs:annotation>
-    </xs:attribute>
-    <xs:attribute name="foregroundColor" type="NLog.Targets.ConsoleOutputColor">
-      <xs:annotation>
-        <xs:documentation>Foreground color.</xs:documentation>
-      </xs:annotation>
-    </xs:attribute>
-  </xs:complexType>
-  <xs:complexType name="Console">
-    <xs:complexContent>
-      <xs:extension base="Target">
-        <xs:choice minOccurs="0" maxOccurs="unbounded">
-          <xs:element name="name" minOccurs="0" maxOccurs="1" type="xs:string" />
-          <xs:element name="layout" minOccurs="0" maxOccurs="1" type="Layout" />
-          <xs:element name="header" minOccurs="0" maxOccurs="1" type="Layout" />
-          <xs:element name="footer" minOccurs="0" maxOccurs="1" type="Layout" />
-          <xs:element name="error" minOccurs="0" maxOccurs="1" type="xs:boolean" />
-          <xs:element name="detectConsoleAvailable" minOccurs="0" maxOccurs="1" type="xs:boolean" />
-          <xs:element name="encoding" minOccurs="0" maxOccurs="1" type="xs:string" />
-          <xs:element name="optimizeBufferReuse" minOccurs="0" maxOccurs="1" type="xs:boolean" />
-        </xs:choice>
-        <xs:attribute name="name" type="xs:string">
-          <xs:annotation>
-            <xs:documentation>Name of the target.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="layout" type="SimpleLayoutAttribute">
-          <xs:annotation>
-            <xs:documentation>Text to be rendered.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="header" type="SimpleLayoutAttribute">
-          <xs:annotation>
-            <xs:documentation>Header.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="footer" type="SimpleLayoutAttribute">
-          <xs:annotation>
-            <xs:documentation>Footer.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="error" type="xs:boolean">
-          <xs:annotation>
-            <xs:documentation>Indicates whether to send the log messages to the standard error instead of the standard output.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="detectConsoleAvailable" type="xs:boolean">
-          <xs:annotation>
-            <xs:documentation>Indicates whether to auto-check if the console is available - Disables console writing if Environment.UserInteractive = False (Windows Service) - Disables console writing if Console Standard Input is not available (Non-Console-App)</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="encoding" type="xs:string">
-          <xs:annotation>
-            <xs:documentation>The encoding for writing messages to the .</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="optimizeBufferReuse" type="xs:boolean">
-          <xs:annotation>
-            <xs:documentation>Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-      </xs:extension>
-    </xs:complexContent>
-  </xs:complexType>
-  <xs:complexType name="Database">
-    <xs:complexContent>
-      <xs:extension base="Target">
-        <xs:choice minOccurs="0" maxOccurs="unbounded">
-          <xs:element name="name" minOccurs="0" maxOccurs="1" type="xs:string" />
-          <xs:element name="useTransactions" minOccurs="0" maxOccurs="1" type="xs:boolean" />
-          <xs:element name="dbUserName" minOccurs="0" maxOccurs="1" type="Layout" />
-          <xs:element name="dbProvider" minOccurs="0" maxOccurs="1" type="xs:string" />
-          <xs:element name="dbPassword" minOccurs="0" maxOccurs="1" type="Layout" />
-          <xs:element name="keepConnection" minOccurs="0" maxOccurs="1" type="xs:boolean" />
-          <xs:element name="dbDatabase" minOccurs="0" maxOccurs="1" type="Layout" />
-          <xs:element name="connectionStringName" minOccurs="0" maxOccurs="1" type="xs:string" />
-          <xs:element name="connectionString" minOccurs="0" maxOccurs="1" type="Layout" />
-          <xs:element name="dbHost" minOccurs="0" maxOccurs="1" type="Layout" />
-          <xs:element name="installConnectionString" minOccurs="0" maxOccurs="1" type="Layout" />
-          <xs:element name="install-command" minOccurs="0" maxOccurs="unbounded" type="NLog.Targets.DatabaseCommandInfo" />
-          <xs:element name="uninstall-command" minOccurs="0" maxOccurs="unbounded" type="NLog.Targets.DatabaseCommandInfo" />
-          <xs:element name="optimizeBufferReuse" minOccurs="0" maxOccurs="1" type="xs:boolean" />
-          <xs:element name="parameter" minOccurs="0" maxOccurs="unbounded" type="NLog.Targets.DatabaseParameterInfo" />
-          <xs:element name="commandText" minOccurs="0" maxOccurs="1" type="Layout" />
-          <xs:element name="commandType" minOccurs="0" maxOccurs="1" type="System.Data.CommandType" />
-        </xs:choice>
-        <xs:attribute name="name" type="xs:string">
-          <xs:annotation>
-            <xs:documentation>Name of the target.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="useTransactions" type="xs:boolean">
-          <xs:annotation>
-            <xs:documentation>Obsolete - value will be ignored! The logging code always runs outside of transaction. Gets or sets a value indicating whether to use database transactions. Some data providers require this.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="dbUserName" type="SimpleLayoutAttribute">
-          <xs:annotation>
-            <xs:documentation>Database user name. If the ConnectionString is not provided this value will be used to construct the "User ID=" part of the connection string.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="dbProvider" type="xs:string">
-          <xs:annotation>
-            <xs:documentation>Name of the database provider.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="dbPassword" type="SimpleLayoutAttribute">
-          <xs:annotation>
-            <xs:documentation>Database password. If the ConnectionString is not provided this value will be used to construct the "Password=" part of the connection string.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="keepConnection" type="xs:boolean">
-          <xs:annotation>
-            <xs:documentation>Indicates whether to keep the database connection open between the log events.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="dbDatabase" type="SimpleLayoutAttribute">
-          <xs:annotation>
-            <xs:documentation>Database name. If the ConnectionString is not provided this value will be used to construct the "Database=" part of the connection string.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="connectionStringName" type="xs:string">
-          <xs:annotation>
-            <xs:documentation>Name of the connection string (as specified in &lt;connectionStrings&gt; configuration section.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="connectionString" type="SimpleLayoutAttribute">
-          <xs:annotation>
-            <xs:documentation>Connection string. When provided, it overrides the values specified in DBHost, DBUserName, DBPassword, DBDatabase.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="dbHost" type="SimpleLayoutAttribute">
-          <xs:annotation>
-            <xs:documentation>Database host name. If the ConnectionString is not provided this value will be used to construct the "Server=" part of the connection string.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="installConnectionString" type="SimpleLayoutAttribute">
-          <xs:annotation>
-            <xs:documentation>Connection string using for installation and uninstallation. If not provided, regular ConnectionString is being used.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="optimizeBufferReuse" type="xs:boolean">
-          <xs:annotation>
-            <xs:documentation>Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="commandText" type="SimpleLayoutAttribute">
-          <xs:annotation>
-            <xs:documentation>Text of the SQL command to be run on each log level.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="commandType" type="System.Data.CommandType">
-          <xs:annotation>
-            <xs:documentation>Type of the SQL command to be run on each log level.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-      </xs:extension>
-    </xs:complexContent>
-  </xs:complexType>
-  <xs:simpleType name="System.Data.CommandType">
-    <xs:restriction base="xs:string">
-      <xs:enumeration value="Text" />
-      <xs:enumeration value="StoredProcedure" />
-      <xs:enumeration value="TableDirect" />
-    </xs:restriction>
-  </xs:simpleType>
-  <xs:complexType name="NLog.Targets.DatabaseCommandInfo">
-    <xs:choice minOccurs="0" maxOccurs="unbounded">
-      <xs:element name="commandType" minOccurs="0" maxOccurs="1" type="System.Data.CommandType" />
-      <xs:element name="connectionString" minOccurs="0" maxOccurs="1" type="Layout" />
-      <xs:element name="ignoreFailures" minOccurs="0" maxOccurs="1" type="xs:boolean" />
-      <xs:element name="parameter" minOccurs="0" maxOccurs="unbounded" type="NLog.Targets.DatabaseParameterInfo" />
-      <xs:element name="text" minOccurs="0" maxOccurs="1" type="Layout" />
-    </xs:choice>
-    <xs:attribute name="commandType" type="System.Data.CommandType">
-      <xs:annotation>
-        <xs:documentation>Type of the command.</xs:documentation>
-      </xs:annotation>
-    </xs:attribute>
-    <xs:attribute name="connectionString" type="SimpleLayoutAttribute">
-      <xs:annotation>
-        <xs:documentation>Connection string to run the command against. If not provided, connection string from the target is used.</xs:documentation>
-      </xs:annotation>
-    </xs:attribute>
-    <xs:attribute name="ignoreFailures" type="xs:boolean">
-      <xs:annotation>
-        <xs:documentation>Indicates whether to ignore failures.</xs:documentation>
-      </xs:annotation>
-    </xs:attribute>
-    <xs:attribute name="text" type="SimpleLayoutAttribute">
-      <xs:annotation>
-        <xs:documentation>Command text.</xs:documentation>
-      </xs:annotation>
-    </xs:attribute>
-  </xs:complexType>
-  <xs:complexType name="NLog.Targets.DatabaseParameterInfo">
-    <xs:choice minOccurs="0" maxOccurs="unbounded">
-      <xs:element name="layout" minOccurs="0" maxOccurs="1" type="Layout" />
-      <xs:element name="name" minOccurs="0" maxOccurs="1" type="xs:string" />
-      <xs:element name="precision" minOccurs="0" maxOccurs="1" type="xs:byte" />
-      <xs:element name="scale" minOccurs="0" maxOccurs="1" type="xs:byte" />
-      <xs:element name="size" minOccurs="0" maxOccurs="1" type="xs:integer" />
-    </xs:choice>
-    <xs:attribute name="layout" type="SimpleLayoutAttribute">
-      <xs:annotation>
-        <xs:documentation>Layout that should be use to calcuate the value for the parameter.</xs:documentation>
-      </xs:annotation>
-    </xs:attribute>
-    <xs:attribute name="name" type="xs:string">
-      <xs:annotation>
-        <xs:documentation>Database parameter name.</xs:documentation>
-      </xs:annotation>
-    </xs:attribute>
-    <xs:attribute name="precision" type="xs:byte">
-      <xs:annotation>
-        <xs:documentation>Database parameter precision.</xs:documentation>
-      </xs:annotation>
-    </xs:attribute>
-    <xs:attribute name="scale" type="xs:byte">
-      <xs:annotation>
-        <xs:documentation>Database parameter scale.</xs:documentation>
-      </xs:annotation>
-    </xs:attribute>
-    <xs:attribute name="size" type="xs:integer">
-      <xs:annotation>
-        <xs:documentation>Database parameter size.</xs:documentation>
-      </xs:annotation>
-    </xs:attribute>
-  </xs:complexType>
-  <xs:complexType name="Debugger">
-    <xs:complexContent>
-      <xs:extension base="Target">
-        <xs:choice minOccurs="0" maxOccurs="unbounded">
-          <xs:element name="name" minOccurs="0" maxOccurs="1" type="xs:string" />
-          <xs:element name="layout" minOccurs="0" maxOccurs="1" type="Layout" />
-          <xs:element name="header" minOccurs="0" maxOccurs="1" type="Layout" />
-          <xs:element name="footer" minOccurs="0" maxOccurs="1" type="Layout" />
-          <xs:element name="optimizeBufferReuse" minOccurs="0" maxOccurs="1" type="xs:boolean" />
-        </xs:choice>
-        <xs:attribute name="name" type="xs:string">
-          <xs:annotation>
-            <xs:documentation>Name of the target.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="layout" type="SimpleLayoutAttribute">
-          <xs:annotation>
-            <xs:documentation>Text to be rendered.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="header" type="SimpleLayoutAttribute">
-          <xs:annotation>
-            <xs:documentation>Header.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="footer" type="SimpleLayoutAttribute">
-          <xs:annotation>
-            <xs:documentation>Footer.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="optimizeBufferReuse" type="xs:boolean">
-          <xs:annotation>
-            <xs:documentation>Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-      </xs:extension>
-    </xs:complexContent>
-  </xs:complexType>
-  <xs:complexType name="Debug">
-    <xs:complexContent>
-      <xs:extension base="Target">
-        <xs:choice minOccurs="0" maxOccurs="unbounded">
-          <xs:element name="name" minOccurs="0" maxOccurs="1" type="xs:string" />
-          <xs:element name="layout" minOccurs="0" maxOccurs="1" type="Layout" />
-          <xs:element name="optimizeBufferReuse" minOccurs="0" maxOccurs="1" type="xs:boolean" />
-        </xs:choice>
-        <xs:attribute name="name" type="xs:string">
-          <xs:annotation>
-            <xs:documentation>Name of the target.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="layout" type="SimpleLayoutAttribute">
-          <xs:annotation>
-            <xs:documentation>Layout used to format log messages.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="optimizeBufferReuse" type="xs:boolean">
-          <xs:annotation>
-            <xs:documentation>Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-      </xs:extension>
-    </xs:complexContent>
-  </xs:complexType>
-  <xs:complexType name="EventLog">
-    <xs:complexContent>
-      <xs:extension base="Target">
-        <xs:choice minOccurs="0" maxOccurs="unbounded">
-          <xs:element name="name" minOccurs="0" maxOccurs="1" type="xs:string" />
-          <xs:element name="layout" minOccurs="0" maxOccurs="1" type="Layout" />
-          <xs:element name="category" minOccurs="0" maxOccurs="1" type="Layout" />
-          <xs:element name="eventId" minOccurs="0" maxOccurs="1" type="Layout" />
-          <xs:element name="log" minOccurs="0" maxOccurs="1" type="xs:string" />
-          <xs:element name="machineName" minOccurs="0" maxOccurs="1" type="xs:string" />
-          <xs:element name="source" minOccurs="0" maxOccurs="1" type="Layout" />
-          <xs:element name="onOverflow" minOccurs="0" maxOccurs="1" type="NLog.Targets.EventLogTargetOverflowAction" />
-          <xs:element name="entryType" minOccurs="0" maxOccurs="1" type="Layout" />
-          <xs:element name="maxKilobytes" minOccurs="0" maxOccurs="1" type="xs:long" />
-          <xs:element name="maxMessageLength" minOccurs="0" maxOccurs="1" type="xs:integer" />
-          <xs:element name="optimizeBufferReuse" minOccurs="0" maxOccurs="1" type="xs:boolean" />
-        </xs:choice>
-        <xs:attribute name="name" type="xs:string">
-          <xs:annotation>
-            <xs:documentation>Name of the target.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="layout" type="SimpleLayoutAttribute">
-          <xs:annotation>
-            <xs:documentation>Layout used to format log messages.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="category" type="SimpleLayoutAttribute">
-          <xs:annotation>
-            <xs:documentation>Layout that renders event Category.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="eventId" type="SimpleLayoutAttribute">
-          <xs:annotation>
-            <xs:documentation>Layout that renders event ID.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="log" type="xs:string">
-          <xs:annotation>
-            <xs:documentation>Name of the Event Log to write to. This can be System, Application or any user-defined name.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="machineName" type="xs:string">
-          <xs:annotation>
-            <xs:documentation>Name of the machine on which Event Log service is running.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="source" type="SimpleLayoutAttribute">
-          <xs:annotation>
-            <xs:documentation>Value to be used as the event Source.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="onOverflow" type="NLog.Targets.EventLogTargetOverflowAction">
-          <xs:annotation>
-            <xs:documentation>Action to take if the message is larger than the  option.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="entryType" type="SimpleLayoutAttribute">
-          <xs:annotation>
-            <xs:documentation>Optional entrytype. When not set, or when not convertable to  then determined by </xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="maxKilobytes" type="xs:long">
-          <xs:annotation>
-            <xs:documentation>Maximum Event log size in kilobytes. If null, the value won't be set. Default is 512 Kilobytes as specified by Eventlog API</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="maxMessageLength" type="xs:integer">
-          <xs:annotation>
-            <xs:documentation>Message length limit to write to the Event Log.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="optimizeBufferReuse" type="xs:boolean">
-          <xs:annotation>
-            <xs:documentation>Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-      </xs:extension>
-    </xs:complexContent>
-  </xs:complexType>
-  <xs:simpleType name="NLog.Targets.EventLogTargetOverflowAction">
-    <xs:restriction base="xs:string">
-      <xs:enumeration value="Truncate" />
-      <xs:enumeration value="Split" />
-      <xs:enumeration value="Discard" />
-    </xs:restriction>
-  </xs:simpleType>
-  <xs:complexType name="FallbackGroup">
-    <xs:complexContent>
-      <xs:extension base="CompoundTargetBase">
-        <xs:choice minOccurs="0" maxOccurs="unbounded">
-          <xs:element name="name" minOccurs="0" maxOccurs="1" type="xs:string" />
-          <xs:element name="returnToFirstOnSuccess" minOccurs="0" maxOccurs="1" type="xs:boolean" />
-          <xs:element name="optimizeBufferReuse" minOccurs="0" maxOccurs="1" type="xs:boolean" />
-        </xs:choice>
-        <xs:attribute name="name" type="xs:string">
-          <xs:annotation>
-            <xs:documentation>Name of the target.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="returnToFirstOnSuccess" type="xs:boolean">
-          <xs:annotation>
-            <xs:documentation>Indicates whether to return to the first target after any successful write.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="optimizeBufferReuse" type="xs:boolean">
-          <xs:annotation>
-            <xs:documentation>Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-      </xs:extension>
-    </xs:complexContent>
-  </xs:complexType>
-  <xs:complexType name="File">
-    <xs:complexContent>
-      <xs:extension base="Target">
-        <xs:choice minOccurs="0" maxOccurs="unbounded">
-          <xs:element name="name" minOccurs="0" maxOccurs="1" type="xs:string" />
-          <xs:element name="layout" minOccurs="0" maxOccurs="1" type="Layout" />
-          <xs:element name="header" minOccurs="0" maxOccurs="1" type="Layout" />
-          <xs:element name="footer" minOccurs="0" maxOccurs="1" type="Layout" />
-          <xs:element name="encoding" minOccurs="0" maxOccurs="1" type="xs:string" />
-          <xs:element name="lineEnding" minOccurs="0" maxOccurs="1" type="LineEndingMode" />
-          <xs:element name="archiveNumbering" minOccurs="0" maxOccurs="1" type="NLog.Targets.ArchiveNumberingMode" />
-          <xs:element name="archiveFileName" minOccurs="0" maxOccurs="1" type="Layout" />
-          <xs:element name="archiveEvery" minOccurs="0" maxOccurs="1" type="NLog.Targets.FileArchivePeriod" />
-          <xs:element name="archiveAboveSize" minOccurs="0" maxOccurs="1" type="xs:long" />
-          <xs:element name="enableArchiveFileCompression" minOccurs="0" maxOccurs="1" type="xs:boolean" />
-          <xs:element name="maxArchiveFiles" minOccurs="0" maxOccurs="1" type="xs:integer" />
-          <xs:element name="forceManaged" minOccurs="0" maxOccurs="1" type="xs:boolean" />
-          <xs:element name="archiveFileKind" minOccurs="0" maxOccurs="1" type="NLog.Targets.FilePathKind" />
-          <xs:element name="cleanupFileName" minOccurs="0" maxOccurs="1" type="xs:boolean" />
-          <xs:element name="discardAll" minOccurs="0" maxOccurs="1" type="xs:boolean" />
-          <xs:element name="fileNameKind" minOccurs="0" maxOccurs="1" type="NLog.Targets.FilePathKind" />
-          <xs:element name="forceMutexConcurrentWrites" minOccurs="0" maxOccurs="1" type="xs:boolean" />
-          <xs:element name="writeFooterOnArchivingOnly" minOccurs="0" maxOccurs="1" type="xs:boolean" />
-          <xs:element name="fileName" minOccurs="0" maxOccurs="1" type="Layout" />
-          <xs:element name="archiveDateFormat" minOccurs="0" maxOccurs="1" type="xs:string" />
-          <xs:element name="archiveOldFileOnStartup" minOccurs="0" maxOccurs="1" type="xs:boolean" />
-          <xs:element name="createDirs" minOccurs="0" maxOccurs="1" type="xs:boolean" />
-          <xs:element name="enableFileDelete" minOccurs="0" maxOccurs="1" type="xs:boolean" />
-          <xs:element name="fileAttributes" minOccurs="0" maxOccurs="1" type="NLog.Targets.Win32FileAttributes" />
-          <xs:element name="deleteOldFileOnStartup" minOccurs="0" maxOccurs="1" type="xs:boolean" />
-          <xs:element name="replaceFileContentsOnEachWrite" minOccurs="0" maxOccurs="1" type="xs:boolean" />
-          <xs:element name="concurrentWrites" minOccurs="0" maxOccurs="1" type="xs:boolean" />
-          <xs:element name="keepFileOpen" minOccurs="0" maxOccurs="1" type="xs:boolean" />
-          <xs:element name="maxLogFilenames" minOccurs="0" maxOccurs="1" type="xs:integer" />
-          <xs:element name="networkWrites" minOccurs="0" maxOccurs="1" type="xs:boolean" />
-          <xs:element name="openFileCacheSize" minOccurs="0" maxOccurs="1" type="xs:integer" />
-          <xs:element name="openFileCacheTimeout" minOccurs="0" maxOccurs="1" type="xs:integer" />
-          <xs:element name="optimizeBufferReuse" minOccurs="0" maxOccurs="1" type="xs:boolean" />
-          <xs:element name="bufferSize" minOccurs="0" maxOccurs="1" type="xs:integer" />
-          <xs:element name="autoFlush" minOccurs="0" maxOccurs="1" type="xs:boolean" />
-          <xs:element name="concurrentWriteAttemptDelay" minOccurs="0" maxOccurs="1" type="xs:integer" />
-          <xs:element name="concurrentWriteAttempts" minOccurs="0" maxOccurs="1" type="xs:integer" />
-        </xs:choice>
-        <xs:attribute name="name" type="xs:string">
-          <xs:annotation>
-            <xs:documentation>Name of the target.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="layout" type="SimpleLayoutAttribute">
-          <xs:annotation>
-            <xs:documentation>Text to be rendered.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="header" type="SimpleLayoutAttribute">
-          <xs:annotation>
-            <xs:documentation>Header.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="footer" type="SimpleLayoutAttribute">
-          <xs:annotation>
-            <xs:documentation>Footer.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="encoding" type="xs:string">
-          <xs:annotation>
-            <xs:documentation>File encoding.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="lineEnding" type="LineEndingMode">
-          <xs:annotation>
-            <xs:documentation>Line ending mode.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="archiveNumbering" type="NLog.Targets.ArchiveNumberingMode">
-          <xs:annotation>
-            <xs:documentation>Way file archives are numbered.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="archiveFileName" type="SimpleLayoutAttribute">
-          <xs:annotation>
-            <xs:documentation>Name of the file to be used for an archive.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="archiveEvery" type="NLog.Targets.FileArchivePeriod">
-          <xs:annotation>
-            <xs:documentation>Indicates whether to automatically archive log files every time the specified time passes.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="archiveAboveSize" type="xs:long">
-          <xs:annotation>
-            <xs:documentation>Size in bytes above which log files will be automatically archived. Warning: combining this with  isn't supported. We cannot create multiple archive files, if they should have the same name. Choose: </xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="enableArchiveFileCompression" type="xs:boolean">
-          <xs:annotation>
-            <xs:documentation>Indicates whether to compress archive files into the zip archive format.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="maxArchiveFiles" type="xs:integer">
-          <xs:annotation>
-            <xs:documentation>Maximum number of archive files that should be kept.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="forceManaged" type="xs:boolean">
-          <xs:annotation>
-            <xs:documentation>Gets or set a value indicating whether a managed file stream is forced, instead of using the native implementation.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="archiveFileKind" type="NLog.Targets.FilePathKind">
-          <xs:annotation>
-            <xs:documentation>Is the  an absolute or relative path?</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="cleanupFileName" type="xs:boolean">
-          <xs:annotation>
-            <xs:documentation>Cleanup invalid values in a filename, e.g. slashes in a filename. If set to true, this can impact the performance of massive writes. If set to false, nothing gets written when the filename is wrong.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="discardAll" type="xs:boolean">
-          <xs:annotation>
-            <xs:documentation>Whether or not this target should just discard all data that its asked to write. Mostly used for when testing NLog Stack except final write</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="fileNameKind" type="NLog.Targets.FilePathKind">
-          <xs:annotation>
-            <xs:documentation>Is the  an absolute or relative path?</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="forceMutexConcurrentWrites" type="xs:boolean">
-          <xs:annotation>
-            <xs:documentation>Value indicationg whether file creation calls should be synchronized by a system global mutex.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="writeFooterOnArchivingOnly" type="xs:boolean">
-          <xs:annotation>
-            <xs:documentation>Indicates whether the footer should be written only when the file is archived.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="fileName" type="SimpleLayoutAttribute">
-          <xs:annotation>
-            <xs:documentation>Name of the file to write to.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="archiveDateFormat" type="xs:string">
-          <xs:annotation>
-            <xs:documentation>Value specifying the date format to use when archiving files.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="archiveOldFileOnStartup" type="xs:boolean">
-          <xs:annotation>
-            <xs:documentation>Indicates whether to archive old log file on startup.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="createDirs" type="xs:boolean">
-          <xs:annotation>
-            <xs:documentation>Indicates whether to create directories if they do not exist.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="enableFileDelete" type="xs:boolean">
-          <xs:annotation>
-            <xs:documentation>Indicates whether to enable log file(s) to be deleted.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="fileAttributes" type="NLog.Targets.Win32FileAttributes">
-          <xs:annotation>
-            <xs:documentation>File attributes (Windows only).</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="deleteOldFileOnStartup" type="xs:boolean">
-          <xs:annotation>
-            <xs:documentation>Indicates whether to delete old log file on startup.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="replaceFileContentsOnEachWrite" type="xs:boolean">
-          <xs:annotation>
-            <xs:documentation>Indicates whether to replace file contents on each write instead of appending log message at the end.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="concurrentWrites" type="xs:boolean">
-          <xs:annotation>
-            <xs:documentation>Indicates whether concurrent writes to the log file by multiple processes on the same host.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="keepFileOpen" type="xs:boolean">
-          <xs:annotation>
-            <xs:documentation>Indicates whether to keep log file open instead of opening and closing it on each logging event.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="maxLogFilenames" type="xs:integer">
-          <xs:annotation>
-            <xs:documentation>Maximum number of log filenames that should be stored as existing.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="networkWrites" type="xs:boolean">
-          <xs:annotation>
-            <xs:documentation>Indicates whether concurrent writes to the log file by multiple processes on different network hosts.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="openFileCacheSize" type="xs:integer">
-          <xs:annotation>
-            <xs:documentation>Number of files to be kept open. Setting this to a higher value may improve performance in a situation where a single File target is writing to many files (such as splitting by level or by logger).</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="openFileCacheTimeout" type="xs:integer">
-          <xs:annotation>
-            <xs:documentation>Maximum number of seconds that files are kept open. If this number is negative the files are not automatically closed after a period of inactivity.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="optimizeBufferReuse" type="xs:boolean">
-          <xs:annotation>
-            <xs:documentation>Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="bufferSize" type="xs:integer">
-          <xs:annotation>
-            <xs:documentation>Log file buffer size in bytes.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="autoFlush" type="xs:boolean">
-          <xs:annotation>
-            <xs:documentation>Indicates whether to automatically flush the file buffers after each log message.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="concurrentWriteAttemptDelay" type="xs:integer">
-          <xs:annotation>
-            <xs:documentation>Delay in milliseconds to wait before attempting to write to the file again.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="concurrentWriteAttempts" type="xs:integer">
-          <xs:annotation>
-            <xs:documentation>Number of times the write is appended on the file before NLog discards the log message.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-      </xs:extension>
-    </xs:complexContent>
-  </xs:complexType>
-  <xs:simpleType name="NLog.Targets.ArchiveNumberingMode">
-    <xs:restriction base="xs:string">
-      <xs:enumeration value="Sequence" />
-      <xs:enumeration value="Rolling" />
-      <xs:enumeration value="Date" />
-      <xs:enumeration value="DateAndSequence" />
-    </xs:restriction>
-  </xs:simpleType>
-  <xs:simpleType name="NLog.Targets.FileArchivePeriod">
-    <xs:restriction base="xs:string">
-      <xs:enumeration value="None" />
-      <xs:enumeration value="Year" />
-      <xs:enumeration value="Month" />
-      <xs:enumeration value="Day" />
-      <xs:enumeration value="Hour" />
-      <xs:enumeration value="Minute" />
-      <xs:enumeration value="Sunday" />
-      <xs:enumeration value="Monday" />
-      <xs:enumeration value="Tuesday" />
-      <xs:enumeration value="Wednesday" />
-      <xs:enumeration value="Thursday" />
-      <xs:enumeration value="Friday" />
-      <xs:enumeration value="Saturday" />
-    </xs:restriction>
-  </xs:simpleType>
-  <xs:simpleType name="NLog.Targets.FilePathKind">
-    <xs:restriction base="xs:string">
-      <xs:enumeration value="Unknown" />
-      <xs:enumeration value="Relative" />
-      <xs:enumeration value="Absolute" />
-    </xs:restriction>
-  </xs:simpleType>
-  <xs:simpleType name="NLog.Targets.Win32FileAttributes">
-    <xs:restriction base="xs:string">
-      <xs:enumeration value="ReadOnly" />
-      <xs:enumeration value="Hidden" />
-      <xs:enumeration value="System" />
-      <xs:enumeration value="Archive" />
-      <xs:enumeration value="Device" />
-      <xs:enumeration value="Normal" />
-      <xs:enumeration value="Temporary" />
-      <xs:enumeration value="SparseFile" />
-      <xs:enumeration value="ReparsePoint" />
-      <xs:enumeration value="Compressed" />
-      <xs:enumeration value="NotContentIndexed" />
-      <xs:enumeration value="Encrypted" />
-      <xs:enumeration value="WriteThrough" />
-      <xs:enumeration value="NoBuffering" />
-      <xs:enumeration value="DeleteOnClose" />
-      <xs:enumeration value="PosixSemantics" />
-    </xs:restriction>
-  </xs:simpleType>
-  <xs:complexType name="FilteringWrapper">
-    <xs:complexContent>
-      <xs:extension base="WrapperTargetBase">
-        <xs:choice minOccurs="0" maxOccurs="unbounded">
-          <xs:element name="name" minOccurs="0" maxOccurs="1" type="xs:string" />
-          <xs:element name="condition" minOccurs="0" maxOccurs="1" type="Condition" />
-          <xs:element name="optimizeBufferReuse" minOccurs="0" maxOccurs="1" type="xs:boolean" />
-        </xs:choice>
-        <xs:attribute name="name" type="xs:string">
-          <xs:annotation>
-            <xs:documentation>Name of the target.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="condition" type="Condition">
-          <xs:annotation>
-            <xs:documentation>Condition expression. Log events who meet this condition will be forwarded to the wrapped target.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="optimizeBufferReuse" type="xs:boolean">
-          <xs:annotation>
-            <xs:documentation>Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-      </xs:extension>
-    </xs:complexContent>
-  </xs:complexType>
-  <xs:complexType name="ImpersonatingWrapper">
-    <xs:complexContent>
-      <xs:extension base="WrapperTargetBase">
-        <xs:choice minOccurs="0" maxOccurs="unbounded">
-          <xs:element name="name" minOccurs="0" maxOccurs="1" type="xs:string" />
-          <xs:element name="domain" minOccurs="0" maxOccurs="1" type="xs:string" />
-          <xs:element name="impersonationLevel" minOccurs="0" maxOccurs="1" type="NLog.Targets.Wrappers.SecurityImpersonationLevel" />
-          <xs:element name="logOnProvider" minOccurs="0" maxOccurs="1" type="NLog.Targets.Wrappers.LogOnProviderType" />
-          <xs:element name="logOnType" minOccurs="0" maxOccurs="1" type="NLog.Targets.Wrappers.SecurityLogOnType" />
-          <xs:element name="password" minOccurs="0" maxOccurs="1" type="xs:string" />
-          <xs:element name="revertToSelf" minOccurs="0" maxOccurs="1" type="xs:boolean" />
-          <xs:element name="userName" minOccurs="0" maxOccurs="1" type="xs:string" />
-          <xs:element name="optimizeBufferReuse" minOccurs="0" maxOccurs="1" type="xs:boolean" />
-        </xs:choice>
-        <xs:attribute name="name" type="xs:string">
-          <xs:annotation>
-            <xs:documentation>Name of the target.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="domain" type="xs:string">
-          <xs:annotation>
-            <xs:documentation>Windows domain name to change context to.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="impersonationLevel" type="NLog.Targets.Wrappers.SecurityImpersonationLevel">
-          <xs:annotation>
-            <xs:documentation>Required impersonation level.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="logOnProvider" type="NLog.Targets.Wrappers.LogOnProviderType">
-          <xs:annotation>
-            <xs:documentation>Type of the logon provider.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="logOnType" type="NLog.Targets.Wrappers.SecurityLogOnType">
-          <xs:annotation>
-            <xs:documentation>Logon Type.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="password" type="xs:string">
-          <xs:annotation>
-            <xs:documentation>User account password.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="revertToSelf" type="xs:boolean">
-          <xs:annotation>
-            <xs:documentation>Indicates whether to revert to the credentials of the process instead of impersonating another user.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="userName" type="xs:string">
-          <xs:annotation>
-            <xs:documentation>Username to change context to.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="optimizeBufferReuse" type="xs:boolean">
-          <xs:annotation>
-            <xs:documentation>Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-      </xs:extension>
-    </xs:complexContent>
-  </xs:complexType>
-  <xs:simpleType name="NLog.Targets.Wrappers.SecurityImpersonationLevel">
-    <xs:restriction base="xs:string">
-      <xs:enumeration value="Anonymous" />
-      <xs:enumeration value="Identification" />
-      <xs:enumeration value="Impersonation" />
-      <xs:enumeration value="Delegation" />
-    </xs:restriction>
-  </xs:simpleType>
-  <xs:simpleType name="NLog.Targets.Wrappers.LogOnProviderType">
-    <xs:restriction base="xs:string">
-      <xs:enumeration value="Default" />
-    </xs:restriction>
-  </xs:simpleType>
-  <xs:simpleType name="NLog.Targets.Wrappers.SecurityLogOnType">
-    <xs:restriction base="xs:string">
-      <xs:enumeration value="Interactive" />
-      <xs:enumeration value="Network" />
-      <xs:enumeration value="Batch" />
-      <xs:enumeration value="Service" />
-      <xs:enumeration value="NetworkClearText" />
-      <xs:enumeration value="NewCredentials" />
-    </xs:restriction>
-  </xs:simpleType>
-  <xs:complexType name="LimitingWrapper">
-    <xs:complexContent>
-      <xs:extension base="WrapperTargetBase">
-        <xs:choice minOccurs="0" maxOccurs="unbounded">
-          <xs:element name="name" minOccurs="0" maxOccurs="1" type="xs:string" />
-          <xs:element name="interval" minOccurs="0" maxOccurs="1" type="xs:string" />
-          <xs:element name="messageLimit" minOccurs="0" maxOccurs="1" type="xs:integer" />
-          <xs:element name="optimizeBufferReuse" minOccurs="0" maxOccurs="1" type="xs:boolean" />
-        </xs:choice>
-        <xs:attribute name="name" type="xs:string">
-          <xs:annotation>
-            <xs:documentation>Name of the target.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="interval" type="xs:string">
-          <xs:annotation>
-            <xs:documentation>Interval in which messages will be written up to the  number of messages.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="messageLimit" type="xs:integer">
-          <xs:annotation>
-            <xs:documentation>Maximum allowed number of messages written per .</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="optimizeBufferReuse" type="xs:boolean">
-          <xs:annotation>
-            <xs:documentation>Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-      </xs:extension>
-    </xs:complexContent>
-  </xs:complexType>
-  <xs:complexType name="LogReceiverService">
-    <xs:complexContent>
-      <xs:extension base="Target">
-        <xs:choice minOccurs="0" maxOccurs="unbounded">
-          <xs:element name="name" minOccurs="0" maxOccurs="1" type="xs:string" />
-          <xs:element name="endpointAddress" minOccurs="0" maxOccurs="1" type="xs:string" />
-          <xs:element name="endpointConfigurationName" minOccurs="0" maxOccurs="1" type="xs:string" />
-          <xs:element name="useOneWayContract" minOccurs="0" maxOccurs="1" type="xs:boolean" />
-          <xs:element name="clientId" minOccurs="0" maxOccurs="1" type="Layout" />
-          <xs:element name="includeEventProperties" minOccurs="0" maxOccurs="1" type="xs:boolean" />
-          <xs:element name="parameter" minOccurs="0" maxOccurs="unbounded" type="NLog.Targets.MethodCallParameter" />
-          <xs:element name="useBinaryEncoding" minOccurs="0" maxOccurs="1" type="xs:boolean" />
-          <xs:element name="optimizeBufferReuse" minOccurs="0" maxOccurs="1" type="xs:boolean" />
-        </xs:choice>
-        <xs:attribute name="name" type="xs:string">
-          <xs:annotation>
-            <xs:documentation>Name of the target.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="endpointAddress" type="xs:string">
-          <xs:annotation>
-            <xs:documentation>Endpoint address.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="endpointConfigurationName" type="xs:string">
-          <xs:annotation>
-            <xs:documentation>Name of the endpoint configuration in WCF configuration file.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="useOneWayContract" type="xs:boolean">
-          <xs:annotation>
-            <xs:documentation>Indicates whether to use a WCF service contract that is one way (fire and forget) or two way (request-reply)</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="clientId" type="SimpleLayoutAttribute">
-          <xs:annotation>
-            <xs:documentation>Client ID.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="includeEventProperties" type="xs:boolean">
-          <xs:annotation>
-            <xs:documentation>Indicates whether to include per-event properties in the payload sent to the server.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="useBinaryEncoding" type="xs:boolean">
-          <xs:annotation>
-            <xs:documentation>Indicates whether to use binary message encoding.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="optimizeBufferReuse" type="xs:boolean">
-          <xs:annotation>
-            <xs:documentation>Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-      </xs:extension>
-    </xs:complexContent>
-  </xs:complexType>
-  <xs:complexType name="NLog.Targets.MethodCallParameter">
-    <xs:choice minOccurs="0" maxOccurs="unbounded">
-      <xs:element name="layout" minOccurs="0" maxOccurs="1" type="Layout" />
-      <xs:element name="name" minOccurs="0" maxOccurs="1" type="xs:string" />
-      <xs:element name="parameterType" minOccurs="0" maxOccurs="1" type="xs:string" />
-      <xs:element name="type" minOccurs="0" maxOccurs="1" type="xs:string" />
-    </xs:choice>
-    <xs:attribute name="layout" type="SimpleLayoutAttribute">
-      <xs:annotation>
-        <xs:documentation>Layout that should be use to calculate the value for the parameter.</xs:documentation>
-      </xs:annotation>
-    </xs:attribute>
-    <xs:attribute name="name" type="xs:string">
-      <xs:annotation>
-        <xs:documentation>Name of the parameter.</xs:documentation>
-      </xs:annotation>
-    </xs:attribute>
-    <xs:attribute name="parameterType" type="xs:string">
-      <xs:annotation>
-        <xs:documentation>Type of the parameter.</xs:documentation>
-      </xs:annotation>
-    </xs:attribute>
-    <xs:attribute name="type" type="xs:string">
-      <xs:annotation>
-        <xs:documentation>Type of the parameter. Obsolete alias for </xs:documentation>
-      </xs:annotation>
-    </xs:attribute>
-  </xs:complexType>
-  <xs:complexType name="Mail">
-    <xs:complexContent>
-      <xs:extension base="Target">
-        <xs:choice minOccurs="0" maxOccurs="unbounded">
-          <xs:element name="name" minOccurs="0" maxOccurs="1" type="xs:string" />
-          <xs:element name="layout" minOccurs="0" maxOccurs="1" type="Layout" />
-          <xs:element name="header" minOccurs="0" maxOccurs="1" type="Layout" />
-          <xs:element name="footer" minOccurs="0" maxOccurs="1" type="Layout" />
-          <xs:element name="html" minOccurs="0" maxOccurs="1" type="xs:boolean" />
-          <xs:element name="encoding" minOccurs="0" maxOccurs="1" type="xs:string" />
-          <xs:element name="addNewLines" minOccurs="0" maxOccurs="1" type="xs:boolean" />
-          <xs:element name="cc" minOccurs="0" maxOccurs="1" type="Layout" />
-          <xs:element name="to" minOccurs="0" maxOccurs="1" type="Layout" />
-          <xs:element name="bcc" minOccurs="0" maxOccurs="1" type="Layout" />
-          <xs:element name="body" minOccurs="0" maxOccurs="1" type="Layout" />
-          <xs:element name="subject" minOccurs="0" maxOccurs="1" type="Layout" />
-          <xs:element name="from" minOccurs="0" maxOccurs="1" type="Layout" />
-          <xs:element name="timeout" minOccurs="0" maxOccurs="1" type="xs:integer" />
-          <xs:element name="priority" minOccurs="0" maxOccurs="1" type="Layout" />
-          <xs:element name="replaceNewlineWithBrTagInHtml" minOccurs="0" maxOccurs="1" type="xs:boolean" />
-          <xs:element name="optimizeBufferReuse" minOccurs="0" maxOccurs="1" type="xs:boolean" />
-          <xs:element name="smtpServer" minOccurs="0" maxOccurs="1" type="Layout" />
-          <xs:element name="smtpAuthentication" minOccurs="0" maxOccurs="1" type="NLog.Targets.SmtpAuthenticationMode" />
-          <xs:element name="smtpUserName" minOccurs="0" maxOccurs="1" type="Layout" />
-          <xs:element name="smtpPassword" minOccurs="0" maxOccurs="1" type="Layout" />
-          <xs:element name="enableSsl" minOccurs="0" maxOccurs="1" type="xs:boolean" />
-          <xs:element name="smtpPort" minOccurs="0" maxOccurs="1" type="xs:integer" />
-          <xs:element name="useSystemNetMailSettings" minOccurs="0" maxOccurs="1" type="xs:boolean" />
-          <xs:element name="pickupDirectoryLocation" minOccurs="0" maxOccurs="1" type="xs:string" />
-          <xs:element name="deliveryMethod" minOccurs="0" maxOccurs="1" type="System.Net.Mail.SmtpDeliveryMethod" />
-        </xs:choice>
-        <xs:attribute name="name" type="xs:string">
-          <xs:annotation>
-            <xs:documentation>Name of the target.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="layout" type="SimpleLayoutAttribute">
-          <xs:annotation>
-            <xs:documentation>Text to be rendered.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="header" type="SimpleLayoutAttribute">
-          <xs:annotation>
-            <xs:documentation>Header.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="footer" type="SimpleLayoutAttribute">
-          <xs:annotation>
-            <xs:documentation>Footer.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="html" type="xs:boolean">
-          <xs:annotation>
-            <xs:documentation>Indicates whether to send message as HTML instead of plain text.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="encoding" type="xs:string">
-          <xs:annotation>
-            <xs:documentation>Encoding to be used for sending e-mail.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="addNewLines" type="xs:boolean">
-          <xs:annotation>
-            <xs:documentation>Indicates whether to add new lines between log entries.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="cc" type="SimpleLayoutAttribute">
-          <xs:annotation>
-            <xs:documentation>CC email addresses separated by semicolons (e.g. john@domain.com;jane@domain.com).</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="to" type="SimpleLayoutAttribute">
-          <xs:annotation>
-            <xs:documentation>Recipients' email addresses separated by semicolons (e.g. john@domain.com;jane@domain.com).</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="bcc" type="SimpleLayoutAttribute">
-          <xs:annotation>
-            <xs:documentation>BCC email addresses separated by semicolons (e.g. john@domain.com;jane@domain.com).</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="body" type="SimpleLayoutAttribute">
-          <xs:annotation>
-            <xs:documentation>Mail message body (repeated for each log message send in one mail).</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="subject" type="SimpleLayoutAttribute">
-          <xs:annotation>
-            <xs:documentation>Mail subject.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="from" type="SimpleLayoutAttribute">
-          <xs:annotation>
-            <xs:documentation>Sender's email address (e.g. joe@domain.com).</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="timeout" type="xs:integer">
-          <xs:annotation>
-            <xs:documentation>Indicates the SMTP client timeout.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="priority" type="SimpleLayoutAttribute">
-          <xs:annotation>
-            <xs:documentation>Priority used for sending mails.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="replaceNewlineWithBrTagInHtml" type="xs:boolean">
-          <xs:annotation>
-            <xs:documentation>Indicates whether NewLine characters in the body should be replaced with  tags.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="optimizeBufferReuse" type="xs:boolean">
-          <xs:annotation>
-            <xs:documentation>Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="smtpServer" type="SimpleLayoutAttribute">
-          <xs:annotation>
-            <xs:documentation>SMTP Server to be used for sending.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="smtpAuthentication" type="NLog.Targets.SmtpAuthenticationMode">
-          <xs:annotation>
-            <xs:documentation>SMTP Authentication mode.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="smtpUserName" type="SimpleLayoutAttribute">
-          <xs:annotation>
-            <xs:documentation>Username used to connect to SMTP server (used when SmtpAuthentication is set to "basic").</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="smtpPassword" type="SimpleLayoutAttribute">
-          <xs:annotation>
-            <xs:documentation>Password used to authenticate against SMTP server (used when SmtpAuthentication is set to "basic").</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="enableSsl" type="xs:boolean">
-          <xs:annotation>
-            <xs:documentation>Indicates whether SSL (secure sockets layer) should be used when communicating with SMTP server.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="smtpPort" type="xs:integer">
-          <xs:annotation>
-            <xs:documentation>Port number that SMTP Server is listening on.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="useSystemNetMailSettings" type="xs:boolean">
-          <xs:annotation>
-            <xs:documentation>Indicates whether the default Settings from System.Net.MailSettings should be used.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="pickupDirectoryLocation" type="xs:string">
-          <xs:annotation>
-            <xs:documentation>Folder where applications save mail messages to be processed by the local SMTP server.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="deliveryMethod" type="System.Net.Mail.SmtpDeliveryMethod">
-          <xs:annotation>
-            <xs:documentation>Specifies how outgoing email messages will be handled.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-      </xs:extension>
-    </xs:complexContent>
-  </xs:complexType>
-  <xs:simpleType name="NLog.Targets.SmtpAuthenticationMode">
-    <xs:restriction base="xs:string">
-      <xs:enumeration value="None" />
-      <xs:enumeration value="Basic" />
-      <xs:enumeration value="Ntlm" />
-    </xs:restriction>
-  </xs:simpleType>
-  <xs:simpleType name="System.Net.Mail.SmtpDeliveryMethod">
-    <xs:restriction base="xs:string">
-      <xs:enumeration value="Network" />
-      <xs:enumeration value="SpecifiedPickupDirectory" />
-      <xs:enumeration value="PickupDirectoryFromIis" />
-    </xs:restriction>
-  </xs:simpleType>
-  <xs:complexType name="Memory">
-    <xs:complexContent>
-      <xs:extension base="Target">
-        <xs:choice minOccurs="0" maxOccurs="unbounded">
-          <xs:element name="name" minOccurs="0" maxOccurs="1" type="xs:string" />
-          <xs:element name="layout" minOccurs="0" maxOccurs="1" type="Layout" />
-          <xs:element name="optimizeBufferReuse" minOccurs="0" maxOccurs="1" type="xs:boolean" />
-        </xs:choice>
-        <xs:attribute name="name" type="xs:string">
-          <xs:annotation>
-            <xs:documentation>Name of the target.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="layout" type="SimpleLayoutAttribute">
-          <xs:annotation>
-            <xs:documentation>Layout used to format log messages.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="optimizeBufferReuse" type="xs:boolean">
-          <xs:annotation>
-            <xs:documentation>Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-      </xs:extension>
-    </xs:complexContent>
-  </xs:complexType>
-  <xs:complexType name="MSMQ">
-    <xs:complexContent>
-      <xs:extension base="Target">
-        <xs:choice minOccurs="0" maxOccurs="unbounded">
-          <xs:element name="name" minOccurs="0" maxOccurs="1" type="xs:string" />
-          <xs:element name="layout" minOccurs="0" maxOccurs="1" type="Layout" />
-          <xs:element name="encoding" minOccurs="0" maxOccurs="1" type="xs:string" />
-          <xs:element name="useXmlEncoding" minOccurs="0" maxOccurs="1" type="xs:boolean" />
-          <xs:element name="checkIfQueueExists" minOccurs="0" maxOccurs="1" type="xs:boolean" />
-          <xs:element name="optimizeBufferReuse" minOccurs="0" maxOccurs="1" type="xs:boolean" />
-          <xs:element name="createQueueIfNotExists" minOccurs="0" maxOccurs="1" type="xs:boolean" />
-          <xs:element name="label" minOccurs="0" maxOccurs="1" type="Layout" />
-          <xs:element name="queue" minOccurs="0" maxOccurs="1" type="Layout" />
-          <xs:element name="recoverable" minOccurs="0" maxOccurs="1" type="xs:boolean" />
-        </xs:choice>
-        <xs:attribute name="name" type="xs:string">
-          <xs:annotation>
-            <xs:documentation>Name of the target.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="layout" type="SimpleLayoutAttribute">
-          <xs:annotation>
-            <xs:documentation>Layout used to format log messages.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="encoding" type="xs:string">
-          <xs:annotation>
-            <xs:documentation>Encoding to be used when writing text to the queue.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="useXmlEncoding" type="xs:boolean">
-          <xs:annotation>
-            <xs:documentation>Indicates whether to use the XML format when serializing message. This will also disable creating queues.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="checkIfQueueExists" type="xs:boolean">
-          <xs:annotation>
-            <xs:documentation>Indicates whether to check if a queue exists before writing to it.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="optimizeBufferReuse" type="xs:boolean">
-          <xs:annotation>
-            <xs:documentation>Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="createQueueIfNotExists" type="xs:boolean">
-          <xs:annotation>
-            <xs:documentation>Indicates whether to create the queue if it doesn't exists.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="label" type="SimpleLayoutAttribute">
-          <xs:annotation>
-            <xs:documentation>Label to associate with each message.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="queue" type="SimpleLayoutAttribute">
-          <xs:annotation>
-            <xs:documentation>Name of the queue to write to.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="recoverable" type="xs:boolean">
-          <xs:annotation>
-            <xs:documentation>Indicates whether to use recoverable messages (with guaranteed delivery).</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-      </xs:extension>
-    </xs:complexContent>
-  </xs:complexType>
-  <xs:complexType name="MethodCall">
-    <xs:complexContent>
-      <xs:extension base="Target">
-        <xs:choice minOccurs="0" maxOccurs="unbounded">
-          <xs:element name="name" minOccurs="0" maxOccurs="1" type="xs:string" />
-          <xs:element name="className" minOccurs="0" maxOccurs="1" type="xs:string" />
-          <xs:element name="methodName" minOccurs="0" maxOccurs="1" type="xs:string" />
-          <xs:element name="parameter" minOccurs="0" maxOccurs="unbounded" type="NLog.Targets.MethodCallParameter" />
-          <xs:element name="optimizeBufferReuse" minOccurs="0" maxOccurs="1" type="xs:boolean" />
-        </xs:choice>
-        <xs:attribute name="name" type="xs:string">
-          <xs:annotation>
-            <xs:documentation>Name of the target.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="className" type="xs:string">
-          <xs:annotation>
-            <xs:documentation>Class name.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="methodName" type="xs:string">
-          <xs:annotation>
-            <xs:documentation>Method name. The method must be public and static. Use the AssemblyQualifiedName , https://msdn.microsoft.com/en-us/library/system.type.assemblyqualifiedname(v=vs.110).aspx e.g.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="optimizeBufferReuse" type="xs:boolean">
-          <xs:annotation>
-            <xs:documentation>Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-      </xs:extension>
-    </xs:complexContent>
-  </xs:complexType>
-  <xs:complexType name="Network">
-    <xs:complexContent>
-      <xs:extension base="Target">
-        <xs:choice minOccurs="0" maxOccurs="unbounded">
-          <xs:element name="name" minOccurs="0" maxOccurs="1" type="xs:string" />
-          <xs:element name="layout" minOccurs="0" maxOccurs="1" type="Layout" />
-          <xs:element name="encoding" minOccurs="0" maxOccurs="1" type="xs:string" />
-          <xs:element name="lineEnding" minOccurs="0" maxOccurs="1" type="LineEndingMode" />
-          <xs:element name="maxMessageSize" minOccurs="0" maxOccurs="1" type="xs:integer" />
-          <xs:element name="newLine" minOccurs="0" maxOccurs="1" type="xs:boolean" />
-          <xs:element name="onConnectionOverflow" minOccurs="0" maxOccurs="1" type="NLog.Targets.NetworkTargetConnectionsOverflowAction" />
-          <xs:element name="onOverflow" minOccurs="0" maxOccurs="1" type="NLog.Targets.NetworkTargetOverflowAction" />
-          <xs:element name="address" minOccurs="0" maxOccurs="1" type="Layout" />
-          <xs:element name="connectionCacheSize" minOccurs="0" maxOccurs="1" type="xs:integer" />
-          <xs:element name="keepConnection" minOccurs="0" maxOccurs="1" type="xs:boolean" />
-          <xs:element name="maxConnections" minOccurs="0" maxOccurs="1" type="xs:integer" />
-          <xs:element name="maxQueueSize" minOccurs="0" maxOccurs="1" type="xs:integer" />
-          <xs:element name="optimizeBufferReuse" minOccurs="0" maxOccurs="1" type="xs:boolean" />
-        </xs:choice>
-        <xs:attribute name="name" type="xs:string">
-          <xs:annotation>
-            <xs:documentation>Name of the target.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="layout" type="SimpleLayoutAttribute">
-          <xs:annotation>
-            <xs:documentation>Layout used to format log messages.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="encoding" type="xs:string">
-          <xs:annotation>
-            <xs:documentation>Encoding to be used.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="lineEnding" type="LineEndingMode">
-          <xs:annotation>
-            <xs:documentation>End of line value if a newline is appended at the end of log message .</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="maxMessageSize" type="xs:integer">
-          <xs:annotation>
-            <xs:documentation>Maximum message size in bytes.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="newLine" type="xs:boolean">
-          <xs:annotation>
-            <xs:documentation>Indicates whether to append newline at the end of log message.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="onConnectionOverflow" type="NLog.Targets.NetworkTargetConnectionsOverflowAction">
-          <xs:annotation>
-            <xs:documentation>Action that should be taken if the will be more connections than .</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="onOverflow" type="NLog.Targets.NetworkTargetOverflowAction">
-          <xs:annotation>
-            <xs:documentation>Action that should be taken if the message is larger than maxMessageSize.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="address" type="SimpleLayoutAttribute">
-          <xs:annotation>
-            <xs:documentation>Network address.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="connectionCacheSize" type="xs:integer">
-          <xs:annotation>
-            <xs:documentation>Size of the connection cache (number of connections which are kept alive).</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="keepConnection" type="xs:boolean">
-          <xs:annotation>
-            <xs:documentation>Indicates whether to keep connection open whenever possible.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="maxConnections" type="xs:integer">
-          <xs:annotation>
-            <xs:documentation>Maximum current connections. 0 = no maximum.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="maxQueueSize" type="xs:integer">
-          <xs:annotation>
-            <xs:documentation>Maximum queue size.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="optimizeBufferReuse" type="xs:boolean">
-          <xs:annotation>
-            <xs:documentation>Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-      </xs:extension>
-    </xs:complexContent>
-  </xs:complexType>
-  <xs:complexType name="NLogViewer">
-    <xs:complexContent>
-      <xs:extension base="Target">
-        <xs:choice minOccurs="0" maxOccurs="unbounded">
-          <xs:element name="name" minOccurs="0" maxOccurs="1" type="xs:string" />
-          <xs:element name="encoding" minOccurs="0" maxOccurs="1" type="xs:string" />
-          <xs:element name="layout" minOccurs="0" maxOccurs="1" type="Layout" />
-          <xs:element name="lineEnding" minOccurs="0" maxOccurs="1" type="LineEndingMode" />
-          <xs:element name="maxMessageSize" minOccurs="0" maxOccurs="1" type="xs:integer" />
-          <xs:element name="newLine" minOccurs="0" maxOccurs="1" type="xs:boolean" />
-          <xs:element name="onConnectionOverflow" minOccurs="0" maxOccurs="1" type="NLog.Targets.NetworkTargetConnectionsOverflowAction" />
-          <xs:element name="onOverflow" minOccurs="0" maxOccurs="1" type="NLog.Targets.NetworkTargetOverflowAction" />
-          <xs:element name="maxConnections" minOccurs="0" maxOccurs="1" type="xs:integer" />
-          <xs:element name="keepConnection" minOccurs="0" maxOccurs="1" type="xs:boolean" />
-          <xs:element name="connectionCacheSize" minOccurs="0" maxOccurs="1" type="xs:integer" />
-          <xs:element name="address" minOccurs="0" maxOccurs="1" type="Layout" />
-          <xs:element name="maxQueueSize" minOccurs="0" maxOccurs="1" type="xs:integer" />
-          <xs:element name="parameter" minOccurs="0" maxOccurs="unbounded" type="NLog.Targets.NLogViewerParameterInfo" />
-          <xs:element name="includeNdc" minOccurs="0" maxOccurs="1" type="xs:boolean" />
-          <xs:element name="includeSourceInfo" minOccurs="0" maxOccurs="1" type="xs:boolean" />
-          <xs:element name="includeNLogData" minOccurs="0" maxOccurs="1" type="xs:boolean" />
-          <xs:element name="includeMdc" minOccurs="0" maxOccurs="1" type="xs:boolean" />
-          <xs:element name="includeCallSite" minOccurs="0" maxOccurs="1" type="xs:boolean" />
-          <xs:element name="appInfo" minOccurs="0" maxOccurs="1" type="xs:string" />
-          <xs:element name="ndcItemSeparator" minOccurs="0" maxOccurs="1" type="xs:string" />
-          <xs:element name="includeMdlc" minOccurs="0" maxOccurs="1" type="xs:boolean" />
-          <xs:element name="optimizeBufferReuse" minOccurs="0" maxOccurs="1" type="xs:boolean" />
-        </xs:choice>
-        <xs:attribute name="name" type="xs:string">
-          <xs:annotation>
-            <xs:documentation>Name of the target.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="encoding" type="xs:string">
-          <xs:annotation>
-            <xs:documentation>Encoding to be used.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="layout" type="SimpleLayoutAttribute">
-          <xs:annotation>
-            <xs:documentation>Instance of  that is used to format log messages.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="lineEnding" type="LineEndingMode">
-          <xs:annotation>
-            <xs:documentation>End of line value if a newline is appended at the end of log message .</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="maxMessageSize" type="xs:integer">
-          <xs:annotation>
-            <xs:documentation>Maximum message size in bytes.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="newLine" type="xs:boolean">
-          <xs:annotation>
-            <xs:documentation>Indicates whether to append newline at the end of log message.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="onConnectionOverflow" type="NLog.Targets.NetworkTargetConnectionsOverflowAction">
-          <xs:annotation>
-            <xs:documentation>Action that should be taken if the will be more connections than .</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="onOverflow" type="NLog.Targets.NetworkTargetOverflowAction">
-          <xs:annotation>
-            <xs:documentation>Action that should be taken if the message is larger than maxMessageSize.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="maxConnections" type="xs:integer">
-          <xs:annotation>
-            <xs:documentation>Maximum current connections. 0 = no maximum.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="keepConnection" type="xs:boolean">
-          <xs:annotation>
-            <xs:documentation>Indicates whether to keep connection open whenever possible.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="connectionCacheSize" type="xs:integer">
-          <xs:annotation>
-            <xs:documentation>Size of the connection cache (number of connections which are kept alive).</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="address" type="SimpleLayoutAttribute">
-          <xs:annotation>
-            <xs:documentation>Network address.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="maxQueueSize" type="xs:integer">
-          <xs:annotation>
-            <xs:documentation>Maximum queue size.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="includeNdc" type="xs:boolean">
-          <xs:annotation>
-            <xs:documentation>Indicates whether to include  stack contents.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="includeSourceInfo" type="xs:boolean">
-          <xs:annotation>
-            <xs:documentation>Indicates whether to include source info (file name and line number) in the information sent over the network.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="includeNLogData" type="xs:boolean">
-          <xs:annotation>
-            <xs:documentation>Indicates whether to include NLog-specific extensions to log4j schema.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="includeMdc" type="xs:boolean">
-          <xs:annotation>
-            <xs:documentation>Indicates whether to include  dictionary contents.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="includeCallSite" type="xs:boolean">
-          <xs:annotation>
-            <xs:documentation>Indicates whether to include call site (class and method name) in the information sent over the network.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="appInfo" type="xs:string">
-          <xs:annotation>
-            <xs:documentation>AppInfo field. By default it's the friendly name of the current AppDomain.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="ndcItemSeparator" type="xs:string">
-          <xs:annotation>
-            <xs:documentation>NDC item separator.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="includeMdlc" type="xs:boolean">
-          <xs:annotation>
-            <xs:documentation>Indicates whether to include  dictionary contents.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="optimizeBufferReuse" type="xs:boolean">
-          <xs:annotation>
-            <xs:documentation>Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-      </xs:extension>
-    </xs:complexContent>
-  </xs:complexType>
-  <xs:complexType name="Null">
-    <xs:complexContent>
-      <xs:extension base="Target">
-        <xs:choice minOccurs="0" maxOccurs="unbounded">
-          <xs:element name="name" minOccurs="0" maxOccurs="1" type="xs:string" />
-          <xs:element name="layout" minOccurs="0" maxOccurs="1" type="Layout" />
-          <xs:element name="formatMessage" minOccurs="0" maxOccurs="1" type="xs:boolean" />
-          <xs:element name="optimizeBufferReuse" minOccurs="0" maxOccurs="1" type="xs:boolean" />
-        </xs:choice>
-        <xs:attribute name="name" type="xs:string">
-          <xs:annotation>
-            <xs:documentation>Name of the target.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="layout" type="SimpleLayoutAttribute">
-          <xs:annotation>
-            <xs:documentation>Layout used to format log messages.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="formatMessage" type="xs:boolean">
-          <xs:annotation>
-            <xs:documentation>Indicates whether to perform layout calculation.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="optimizeBufferReuse" type="xs:boolean">
-          <xs:annotation>
-            <xs:documentation>Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-      </xs:extension>
-    </xs:complexContent>
-  </xs:complexType>
-  <xs:complexType name="OutputDebugString">
-    <xs:complexContent>
-      <xs:extension base="Target">
-        <xs:choice minOccurs="0" maxOccurs="unbounded">
-          <xs:element name="name" minOccurs="0" maxOccurs="1" type="xs:string" />
-          <xs:element name="layout" minOccurs="0" maxOccurs="1" type="Layout" />
-          <xs:element name="optimizeBufferReuse" minOccurs="0" maxOccurs="1" type="xs:boolean" />
-        </xs:choice>
-        <xs:attribute name="name" type="xs:string">
-          <xs:annotation>
-            <xs:documentation>Name of the target.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="layout" type="SimpleLayoutAttribute">
-          <xs:annotation>
-            <xs:documentation>Layout used to format log messages.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="optimizeBufferReuse" type="xs:boolean">
-          <xs:annotation>
-            <xs:documentation>Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-      </xs:extension>
-    </xs:complexContent>
-  </xs:complexType>
-  <xs:complexType name="PerfCounter">
-    <xs:complexContent>
-      <xs:extension base="Target">
-        <xs:choice minOccurs="0" maxOccurs="unbounded">
-          <xs:element name="name" minOccurs="0" maxOccurs="1" type="xs:string" />
-          <xs:element name="autoCreate" minOccurs="0" maxOccurs="1" type="xs:boolean" />
-          <xs:element name="categoryName" minOccurs="0" maxOccurs="1" type="xs:string" />
-          <xs:element name="counterHelp" minOccurs="0" maxOccurs="1" type="xs:string" />
-          <xs:element name="counterName" minOccurs="0" maxOccurs="1" type="xs:string" />
-          <xs:element name="counterType" minOccurs="0" maxOccurs="1" type="System.Diagnostics.PerformanceCounterType" />
-          <xs:element name="incrementValue" minOccurs="0" maxOccurs="1" type="Layout" />
-          <xs:element name="instanceName" minOccurs="0" maxOccurs="1" type="xs:string" />
-          <xs:element name="optimizeBufferReuse" minOccurs="0" maxOccurs="1" type="xs:boolean" />
-        </xs:choice>
-        <xs:attribute name="name" type="xs:string">
-          <xs:annotation>
-            <xs:documentation>Name of the target.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="autoCreate" type="xs:boolean">
-          <xs:annotation>
-            <xs:documentation>Indicates whether performance counter should be automatically created.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="categoryName" type="xs:string">
-          <xs:annotation>
-            <xs:documentation>Name of the performance counter category.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="counterHelp" type="xs:string">
-          <xs:annotation>
-            <xs:documentation>Counter help text.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="counterName" type="xs:string">
-          <xs:annotation>
-            <xs:documentation>Name of the performance counter.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="counterType" type="System.Diagnostics.PerformanceCounterType">
-          <xs:annotation>
-            <xs:documentation>Performance counter type.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="incrementValue" type="SimpleLayoutAttribute">
-          <xs:annotation>
-            <xs:documentation>The value by which to increment the counter.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="instanceName" type="xs:string">
-          <xs:annotation>
-            <xs:documentation>Performance counter instance name.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="optimizeBufferReuse" type="xs:boolean">
-          <xs:annotation>
-            <xs:documentation>Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-      </xs:extension>
-    </xs:complexContent>
-  </xs:complexType>
-  <xs:simpleType name="System.Diagnostics.PerformanceCounterType">
-    <xs:restriction base="xs:string">
-      <xs:enumeration value="NumberOfItems32" />
-      <xs:enumeration value="NumberOfItems64" />
-      <xs:enumeration value="NumberOfItemsHEX32" />
-      <xs:enumeration value="NumberOfItemsHEX64" />
-      <xs:enumeration value="RateOfCountsPerSecond32" />
-      <xs:enumeration value="RateOfCountsPerSecond64" />
-      <xs:enumeration value="CountPerTimeInterval32" />
-      <xs:enumeration value="CountPerTimeInterval64" />
-      <xs:enumeration value="RawFraction" />
-      <xs:enumeration value="RawBase" />
-      <xs:enumeration value="AverageTimer32" />
-      <xs:enumeration value="AverageBase" />
-      <xs:enumeration value="AverageCount64" />
-      <xs:enumeration value="SampleFraction" />
-      <xs:enumeration value="SampleCounter" />
-      <xs:enumeration value="SampleBase" />
-      <xs:enumeration value="CounterTimer" />
-      <xs:enumeration value="CounterTimerInverse" />
-      <xs:enumeration value="Timer100Ns" />
-      <xs:enumeration value="Timer100NsInverse" />
-      <xs:enumeration value="ElapsedTime" />
-      <xs:enumeration value="CounterMultiTimer" />
-      <xs:enumeration value="CounterMultiTimerInverse" />
-      <xs:enumeration value="CounterMultiTimer100Ns" />
-      <xs:enumeration value="CounterMultiTimer100NsInverse" />
-      <xs:enumeration value="CounterMultiBase" />
-      <xs:enumeration value="CounterDelta32" />
-      <xs:enumeration value="CounterDelta64" />
-    </xs:restriction>
-  </xs:simpleType>
-  <xs:complexType name="PostFilteringWrapper">
-    <xs:complexContent>
-      <xs:extension base="WrapperTargetBase">
-        <xs:choice minOccurs="0" maxOccurs="unbounded">
-          <xs:element name="name" minOccurs="0" maxOccurs="1" type="xs:string" />
-          <xs:element name="defaultFilter" minOccurs="0" maxOccurs="1" type="Condition" />
-          <xs:element name="when" minOccurs="0" maxOccurs="unbounded" type="NLog.Targets.Wrappers.FilteringRule" />
-          <xs:element name="optimizeBufferReuse" minOccurs="0" maxOccurs="1" type="xs:boolean" />
-        </xs:choice>
-        <xs:attribute name="name" type="xs:string">
-          <xs:annotation>
-            <xs:documentation>Name of the target.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="defaultFilter" type="Condition">
-          <xs:annotation>
-            <xs:documentation>Default filter to be applied when no specific rule matches.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="optimizeBufferReuse" type="xs:boolean">
-          <xs:annotation>
-            <xs:documentation>Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-      </xs:extension>
-    </xs:complexContent>
-  </xs:complexType>
-  <xs:complexType name="NLog.Targets.Wrappers.FilteringRule">
-    <xs:choice minOccurs="0" maxOccurs="unbounded">
-      <xs:element name="exists" minOccurs="0" maxOccurs="1" type="Condition" />
-      <xs:element name="filter" minOccurs="0" maxOccurs="1" type="Condition" />
-    </xs:choice>
-    <xs:attribute name="exists" type="Condition">
-      <xs:annotation>
-        <xs:documentation>Condition to be tested.</xs:documentation>
-      </xs:annotation>
-    </xs:attribute>
-    <xs:attribute name="filter" type="Condition">
-      <xs:annotation>
-        <xs:documentation>Resulting filter to be applied when the condition matches.</xs:documentation>
-      </xs:annotation>
-    </xs:attribute>
-  </xs:complexType>
-  <xs:complexType name="RandomizeGroup">
-    <xs:complexContent>
-      <xs:extension base="CompoundTargetBase">
-        <xs:choice minOccurs="0" maxOccurs="unbounded">
-          <xs:element name="name" minOccurs="0" maxOccurs="1" type="xs:string" />
-          <xs:element name="optimizeBufferReuse" minOccurs="0" maxOccurs="1" type="xs:boolean" />
-        </xs:choice>
-        <xs:attribute name="name" type="xs:string">
-          <xs:annotation>
-            <xs:documentation>Name of the target.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="optimizeBufferReuse" type="xs:boolean">
-          <xs:annotation>
-            <xs:documentation>Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-      </xs:extension>
-    </xs:complexContent>
-  </xs:complexType>
-  <xs:complexType name="RepeatingWrapper">
-    <xs:complexContent>
-      <xs:extension base="WrapperTargetBase">
-        <xs:choice minOccurs="0" maxOccurs="unbounded">
-          <xs:element name="name" minOccurs="0" maxOccurs="1" type="xs:string" />
-          <xs:element name="optimizeBufferReuse" minOccurs="0" maxOccurs="1" type="xs:boolean" />
-          <xs:element name="repeatCount" minOccurs="0" maxOccurs="1" type="xs:integer" />
-        </xs:choice>
-        <xs:attribute name="name" type="xs:string">
-          <xs:annotation>
-            <xs:documentation>Name of the target.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="optimizeBufferReuse" type="xs:boolean">
-          <xs:annotation>
-            <xs:documentation>Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="repeatCount" type="xs:integer">
-          <xs:annotation>
-            <xs:documentation>Number of times to repeat each log message.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-      </xs:extension>
-    </xs:complexContent>
-  </xs:complexType>
-  <xs:complexType name="RetryingWrapper">
-    <xs:complexContent>
-      <xs:extension base="WrapperTargetBase">
-        <xs:choice minOccurs="0" maxOccurs="unbounded">
-          <xs:element name="name" minOccurs="0" maxOccurs="1" type="xs:string" />
-          <xs:element name="optimizeBufferReuse" minOccurs="0" maxOccurs="1" type="xs:boolean" />
-          <xs:element name="retryCount" minOccurs="0" maxOccurs="1" type="xs:integer" />
-          <xs:element name="retryDelayMilliseconds" minOccurs="0" maxOccurs="1" type="xs:integer" />
-        </xs:choice>
-        <xs:attribute name="name" type="xs:string">
-          <xs:annotation>
-            <xs:documentation>Name of the target.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="optimizeBufferReuse" type="xs:boolean">
-          <xs:annotation>
-            <xs:documentation>Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="retryCount" type="xs:integer">
-          <xs:annotation>
-            <xs:documentation>Number of retries that should be attempted on the wrapped target in case of a failure.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="retryDelayMilliseconds" type="xs:integer">
-          <xs:annotation>
-            <xs:documentation>Time to wait between retries in milliseconds.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-      </xs:extension>
-    </xs:complexContent>
-  </xs:complexType>
-  <xs:complexType name="RoundRobinGroup">
-    <xs:complexContent>
-      <xs:extension base="CompoundTargetBase">
-        <xs:choice minOccurs="0" maxOccurs="unbounded">
-          <xs:element name="name" minOccurs="0" maxOccurs="1" type="xs:string" />
-          <xs:element name="optimizeBufferReuse" minOccurs="0" maxOccurs="1" type="xs:boolean" />
-        </xs:choice>
-        <xs:attribute name="name" type="xs:string">
-          <xs:annotation>
-            <xs:documentation>Name of the target.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="optimizeBufferReuse" type="xs:boolean">
-          <xs:annotation>
-            <xs:documentation>Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-      </xs:extension>
-    </xs:complexContent>
-  </xs:complexType>
-  <xs:complexType name="SplitGroup">
-    <xs:complexContent>
-      <xs:extension base="CompoundTargetBase">
-        <xs:choice minOccurs="0" maxOccurs="unbounded">
-          <xs:element name="name" minOccurs="0" maxOccurs="1" type="xs:string" />
-          <xs:element name="optimizeBufferReuse" minOccurs="0" maxOccurs="1" type="xs:boolean" />
-        </xs:choice>
-        <xs:attribute name="name" type="xs:string">
-          <xs:annotation>
-            <xs:documentation>Name of the target.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="optimizeBufferReuse" type="xs:boolean">
-          <xs:annotation>
-            <xs:documentation>Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-      </xs:extension>
-    </xs:complexContent>
-  </xs:complexType>
-  <xs:complexType name="Trace">
-    <xs:complexContent>
-      <xs:extension base="Target">
-        <xs:choice minOccurs="0" maxOccurs="unbounded">
-          <xs:element name="name" minOccurs="0" maxOccurs="1" type="xs:string" />
-          <xs:element name="layout" minOccurs="0" maxOccurs="1" type="Layout" />
-          <xs:element name="optimizeBufferReuse" minOccurs="0" maxOccurs="1" type="xs:boolean" />
-        </xs:choice>
-        <xs:attribute name="name" type="xs:string">
-          <xs:annotation>
-            <xs:documentation>Name of the target.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="layout" type="SimpleLayoutAttribute">
-          <xs:annotation>
-            <xs:documentation>Layout used to format log messages.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="optimizeBufferReuse" type="xs:boolean">
-          <xs:annotation>
-            <xs:documentation>Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-      </xs:extension>
-    </xs:complexContent>
-  </xs:complexType>
-  <xs:complexType name="WebService">
-    <xs:complexContent>
-      <xs:extension base="Target">
-        <xs:choice minOccurs="0" maxOccurs="unbounded">
-          <xs:element name="name" minOccurs="0" maxOccurs="1" type="xs:string" />
-          <xs:element name="includeBOM" minOccurs="0" maxOccurs="1" type="xs:boolean" />
-          <xs:element name="parameter" minOccurs="0" maxOccurs="unbounded" type="NLog.Targets.MethodCallParameter" />
-          <xs:element name="optimizeBufferReuse" minOccurs="0" maxOccurs="1" type="xs:boolean" />
-          <xs:element name="encoding" minOccurs="0" maxOccurs="1" type="xs:string" />
-          <xs:element name="escapeDataNLogLegacy" minOccurs="0" maxOccurs="1" type="xs:boolean" />
-          <xs:element name="escapeDataRfc3986" minOccurs="0" maxOccurs="1" type="xs:boolean" />
-          <xs:element name="methodName" minOccurs="0" maxOccurs="1" type="xs:string" />
-          <xs:element name="namespace" minOccurs="0" maxOccurs="1" type="xs:string" />
-          <xs:element name="protocol" minOccurs="0" maxOccurs="1" type="NLog.Targets.WebServiceProtocol" />
-          <xs:element name="url" minOccurs="0" maxOccurs="1" type="xs:anyURI" />
-          <xs:element name="xmlRoot" minOccurs="0" maxOccurs="1" type="xs:string" />
-          <xs:element name="xmlRootNamespace" minOccurs="0" maxOccurs="1" type="xs:string" />
-        </xs:choice>
-        <xs:attribute name="name" type="xs:string">
-          <xs:annotation>
-            <xs:documentation>Name of the target.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="includeBOM" type="xs:boolean">
-          <xs:annotation>
-            <xs:documentation>Should we include the BOM (Byte-order-mark) for UTF? Influences the  property. This will only work for UTF-8.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="optimizeBufferReuse" type="xs:boolean">
-          <xs:annotation>
-            <xs:documentation>Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="encoding" type="xs:string">
-          <xs:annotation>
-            <xs:documentation>Encoding.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="escapeDataNLogLegacy" type="xs:boolean">
-          <xs:annotation>
-            <xs:documentation>Value whether escaping be done according to the old NLog style (Very non-standard)</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="escapeDataRfc3986" type="xs:boolean">
-          <xs:annotation>
-            <xs:documentation>Value whether escaping be done according to Rfc3986 (Supports Internationalized Resource Identifiers - IRIs)</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="methodName" type="xs:string">
-          <xs:annotation>
-            <xs:documentation>Web service method name. Only used with Soap.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="namespace" type="xs:string">
-          <xs:annotation>
-            <xs:documentation>Web service namespace. Only used with Soap.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="protocol" type="NLog.Targets.WebServiceProtocol">
-          <xs:annotation>
-            <xs:documentation>Protocol to be used when calling web service.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="url" type="xs:anyURI">
-          <xs:annotation>
-            <xs:documentation>Web service URL.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="xmlRoot" type="xs:string">
-          <xs:annotation>
-            <xs:documentation>Name of the root XML element, if POST of XML document chosen. If so, this property must not be null. (see  and ).</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="xmlRootNamespace" type="xs:string">
-          <xs:annotation>
-            <xs:documentation>(optional) root namespace of the XML document, if POST of XML document chosen. (see  and ).</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-      </xs:extension>
-    </xs:complexContent>
-  </xs:complexType>
-  <xs:simpleType name="NLog.Targets.WebServiceProtocol">
-    <xs:restriction base="xs:string">
-      <xs:enumeration value="Soap11" />
-      <xs:enumeration value="Soap12" />
-      <xs:enumeration value="HttpPost" />
-      <xs:enumeration value="HttpGet" />
-      <xs:enumeration value="JsonPost" />
-      <xs:enumeration value="XmlPost" />
-    </xs:restriction>
-  </xs:simpleType>
-  <xs:complexType name="CompoundLayout">
-    <xs:complexContent>
-      <xs:extension base="Layout">
-        <xs:choice minOccurs="0" maxOccurs="unbounded">
-          <xs:element name="layout" minOccurs="0" maxOccurs="unbounded" type="Layout" />
-        </xs:choice>
-      </xs:extension>
-    </xs:complexContent>
-  </xs:complexType>
-  <xs:complexType name="Layout">
-    <xs:choice minOccurs="0" maxOccurs="unbounded" />
-  </xs:complexType>
-  <xs:complexType name="CsvLayout">
-    <xs:complexContent>
-      <xs:extension base="Layout">
-        <xs:choice minOccurs="0" maxOccurs="unbounded">
-          <xs:element name="footer" minOccurs="0" maxOccurs="1" type="Layout" />
-          <xs:element name="header" minOccurs="0" maxOccurs="1" type="Layout" />
-          <xs:element name="layout" minOccurs="0" maxOccurs="1" type="Layout" />
-          <xs:element name="column" minOccurs="0" maxOccurs="unbounded" type="NLog.Layouts.CsvColumn" />
-          <xs:element name="customColumnDelimiter" minOccurs="0" maxOccurs="1" type="xs:string" />
-          <xs:element name="delimiter" minOccurs="0" maxOccurs="1" type="NLog.Layouts.CsvColumnDelimiterMode" />
-          <xs:element name="quoteChar" minOccurs="0" maxOccurs="1" type="xs:string" />
-          <xs:element name="quoting" minOccurs="0" maxOccurs="1" type="NLog.Layouts.CsvQuotingMode" />
-          <xs:element name="withHeader" minOccurs="0" maxOccurs="1" type="xs:boolean" />
-        </xs:choice>
-        <xs:attribute name="footer" type="SimpleLayoutAttribute">
-          <xs:annotation>
-            <xs:documentation>Footer layout.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="header" type="SimpleLayoutAttribute">
-          <xs:annotation>
-            <xs:documentation>Header layout.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="layout" type="SimpleLayoutAttribute">
-          <xs:annotation>
-            <xs:documentation>Body layout (can be repeated multiple times).</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="customColumnDelimiter" type="xs:string">
-          <xs:annotation>
-            <xs:documentation>Custom column delimiter value (valid when ColumnDelimiter is set to 'Custom').</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="delimiter" type="NLog.Layouts.CsvColumnDelimiterMode">
-          <xs:annotation>
-            <xs:documentation>Column delimiter.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="quoteChar" type="xs:string">
-          <xs:annotation>
-            <xs:documentation>Quote Character.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="quoting" type="NLog.Layouts.CsvQuotingMode">
-          <xs:annotation>
-            <xs:documentation>Quoting mode.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="withHeader" type="xs:boolean">
-          <xs:annotation>
-            <xs:documentation>Indicates whether CVS should include header.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-      </xs:extension>
-    </xs:complexContent>
-  </xs:complexType>
-  <xs:simpleType name="NLog.Layouts.CsvColumnDelimiterMode">
-    <xs:restriction base="xs:string">
-      <xs:enumeration value="Auto" />
-      <xs:enumeration value="Comma" />
-      <xs:enumeration value="Semicolon" />
-      <xs:enumeration value="Tab" />
-      <xs:enumeration value="Pipe" />
-      <xs:enumeration value="Space" />
-      <xs:enumeration value="Custom" />
-    </xs:restriction>
-  </xs:simpleType>
-  <xs:simpleType name="NLog.Layouts.CsvQuotingMode">
-    <xs:restriction base="xs:string">
-      <xs:enumeration value="All" />
-      <xs:enumeration value="Nothing" />
-      <xs:enumeration value="Auto" />
-    </xs:restriction>
-  </xs:simpleType>
-  <xs:complexType name="NLog.Layouts.CsvColumn">
-    <xs:choice minOccurs="0" maxOccurs="unbounded">
-      <xs:element name="layout" minOccurs="0" maxOccurs="1" type="Layout" />
-      <xs:element name="name" minOccurs="0" maxOccurs="1" type="xs:string" />
-    </xs:choice>
-    <xs:attribute name="layout" type="SimpleLayoutAttribute">
-      <xs:annotation>
-        <xs:documentation>Layout of the column.</xs:documentation>
-      </xs:annotation>
-    </xs:attribute>
-    <xs:attribute name="name" type="xs:string">
-      <xs:annotation>
-        <xs:documentation>Name of the column.</xs:documentation>
-      </xs:annotation>
-    </xs:attribute>
-  </xs:complexType>
-  <xs:complexType name="JsonLayout">
-    <xs:complexContent>
-      <xs:extension base="Layout">
-        <xs:choice minOccurs="0" maxOccurs="unbounded">
-          <xs:element name="attribute" minOccurs="0" maxOccurs="unbounded" type="NLog.Layouts.JsonAttribute" />
-          <xs:element name="excludeProperties" minOccurs="0" maxOccurs="1" type="xs:string" />
-          <xs:element name="includeAllProperties" minOccurs="0" maxOccurs="1" type="xs:boolean" />
-          <xs:element name="includeMdc" minOccurs="0" maxOccurs="1" type="xs:boolean" />
-          <xs:element name="renderEmptyObject" minOccurs="0" maxOccurs="1" type="xs:boolean" />
-          <xs:element name="suppressSpaces" minOccurs="0" maxOccurs="1" type="xs:boolean" />
-          <xs:element name="includeMdlc" minOccurs="0" maxOccurs="1" type="xs:boolean" />
-        </xs:choice>
-        <xs:attribute name="excludeProperties" type="xs:string">
-          <xs:annotation>
-            <xs:documentation>List of property names to exclude when  is true</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="includeAllProperties" type="xs:boolean">
-          <xs:annotation>
-            <xs:documentation>Option to include all properties from the log events</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="includeMdc" type="xs:boolean">
-          <xs:annotation>
-            <xs:documentation>Indicates whether to include contents of the  dictionary.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="renderEmptyObject" type="xs:boolean">
-          <xs:annotation>
-            <xs:documentation>Option to render the empty object value {}</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="suppressSpaces" type="xs:boolean">
-          <xs:annotation>
-            <xs:documentation>Option to suppress the extra spaces in the output json</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="includeMdlc" type="xs:boolean">
-          <xs:annotation>
-            <xs:documentation>Indicates whether to include contents of the  dictionary.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-      </xs:extension>
-    </xs:complexContent>
-  </xs:complexType>
-  <xs:complexType name="NLog.Layouts.JsonAttribute">
-    <xs:choice minOccurs="0" maxOccurs="unbounded">
-      <xs:element name="encode" minOccurs="0" maxOccurs="1" type="xs:boolean" />
-      <xs:element name="escapeUnicode" minOccurs="0" maxOccurs="1" type="xs:boolean" />
-      <xs:element name="layout" minOccurs="0" maxOccurs="1" type="Layout" />
-      <xs:element name="name" minOccurs="0" maxOccurs="1" type="xs:string" />
-    </xs:choice>
-    <xs:attribute name="encode" type="xs:boolean">
-      <xs:annotation>
-        <xs:documentation>Determines wether or not this attribute will be Json encoded.</xs:documentation>
-      </xs:annotation>
-    </xs:attribute>
-    <xs:attribute name="escapeUnicode" type="xs:boolean">
-      <xs:annotation>
-        <xs:documentation>Indicates whether to escape non-ascii characters</xs:documentation>
-      </xs:annotation>
-    </xs:attribute>
-    <xs:attribute name="layout" type="SimpleLayoutAttribute">
-      <xs:annotation>
-        <xs:documentation>Layout that will be rendered as the attribute's value.</xs:documentation>
-      </xs:annotation>
-    </xs:attribute>
-    <xs:attribute name="name" type="xs:string">
-      <xs:annotation>
-        <xs:documentation>Name of the attribute.</xs:documentation>
-      </xs:annotation>
-    </xs:attribute>
-  </xs:complexType>
-  <xs:complexType name="LayoutWithHeaderAndFooter">
-    <xs:complexContent>
-      <xs:extension base="Layout">
-        <xs:choice minOccurs="0" maxOccurs="unbounded">
-          <xs:element name="footer" minOccurs="0" maxOccurs="1" type="Layout" />
-          <xs:element name="header" minOccurs="0" maxOccurs="1" type="Layout" />
-          <xs:element name="layout" minOccurs="0" maxOccurs="1" type="Layout" />
-        </xs:choice>
-        <xs:attribute name="footer" type="SimpleLayoutAttribute">
-          <xs:annotation>
-            <xs:documentation>Footer layout.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="header" type="SimpleLayoutAttribute">
-          <xs:annotation>
-            <xs:documentation>Header layout.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="layout" type="SimpleLayoutAttribute">
-          <xs:annotation>
-            <xs:documentation>Body layout (can be repeated multiple times).</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-      </xs:extension>
-    </xs:complexContent>
-  </xs:complexType>
-  <xs:complexType name="Log4JXmlEventLayout">
-    <xs:complexContent>
-      <xs:extension base="Layout">
-        <xs:choice minOccurs="0" maxOccurs="unbounded">
-          <xs:element name="includeAllProperties" minOccurs="0" maxOccurs="1" type="xs:boolean" />
-          <xs:element name="includeMdc" minOccurs="0" maxOccurs="1" type="xs:boolean" />
-          <xs:element name="includeMdlc" minOccurs="0" maxOccurs="1" type="xs:boolean" />
-        </xs:choice>
-        <xs:attribute name="includeAllProperties" type="xs:boolean">
-          <xs:annotation>
-            <xs:documentation>Option to include all properties from the log events</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="includeMdc" type="xs:boolean">
-          <xs:annotation>
-            <xs:documentation>Indicates whether to include contents of the  dictionary.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="includeMdlc" type="xs:boolean">
-          <xs:annotation>
-            <xs:documentation>Indicates whether to include contents of the  dictionary.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-      </xs:extension>
-    </xs:complexContent>
-  </xs:complexType>
-  <xs:complexType name="SimpleLayout">
-    <xs:complexContent>
-      <xs:extension base="Layout">
-        <xs:choice minOccurs="0" maxOccurs="unbounded">
-          <xs:element name="text" minOccurs="0" maxOccurs="1" type="xs:string" />
-        </xs:choice>
-        <xs:attribute name="text" type="xs:string">
-          <xs:annotation>
-            <xs:documentation>Layout text.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-      </xs:extension>
-    </xs:complexContent>
-  </xs:complexType>
-  <xs:complexType name="when">
-    <xs:complexContent>
-      <xs:extension base="Filter">
-        <xs:choice minOccurs="0" maxOccurs="unbounded">
-          <xs:element name="action" minOccurs="0" maxOccurs="1" type="FilterResult" />
-          <xs:element name="condition" minOccurs="0" maxOccurs="1" type="Condition" />
-        </xs:choice>
-        <xs:attribute name="action" type="FilterResult">
-          <xs:annotation>
-            <xs:documentation>Action to be taken when filter matches.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="condition" type="Condition">
-          <xs:annotation>
-            <xs:documentation>Condition expression.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-      </xs:extension>
-    </xs:complexContent>
-  </xs:complexType>
-  <xs:simpleType name="FilterResult">
-    <xs:restriction base="xs:string">
-      <xs:enumeration value="Neutral" />
-      <xs:enumeration value="Log" />
-      <xs:enumeration value="Ignore" />
-      <xs:enumeration value="LogFinal" />
-      <xs:enumeration value="IgnoreFinal" />
-    </xs:restriction>
-  </xs:simpleType>
-  <xs:complexType name="whenContains">
-    <xs:complexContent>
-      <xs:extension base="Filter">
-        <xs:choice minOccurs="0" maxOccurs="unbounded">
-          <xs:element name="action" minOccurs="0" maxOccurs="1" type="FilterResult" />
-          <xs:element name="ignoreCase" minOccurs="0" maxOccurs="1" type="xs:boolean" />
-          <xs:element name="layout" minOccurs="0" maxOccurs="1" type="Layout" />
-          <xs:element name="substring" minOccurs="0" maxOccurs="1" type="xs:string" />
-        </xs:choice>
-        <xs:attribute name="action" type="FilterResult">
-          <xs:annotation>
-            <xs:documentation>Action to be taken when filter matches.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="ignoreCase" type="xs:boolean">
-          <xs:annotation>
-            <xs:documentation>Indicates whether to ignore case when comparing strings.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="layout" type="SimpleLayoutAttribute">
-          <xs:annotation>
-            <xs:documentation>Layout to be used to filter log messages.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="substring" type="xs:string">
-          <xs:annotation>
-            <xs:documentation>Substring to be matched.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-      </xs:extension>
-    </xs:complexContent>
-  </xs:complexType>
-  <xs:complexType name="whenEqual">
-    <xs:complexContent>
-      <xs:extension base="Filter">
-        <xs:choice minOccurs="0" maxOccurs="unbounded">
-          <xs:element name="action" minOccurs="0" maxOccurs="1" type="FilterResult" />
-          <xs:element name="compareTo" minOccurs="0" maxOccurs="1" type="xs:string" />
-          <xs:element name="ignoreCase" minOccurs="0" maxOccurs="1" type="xs:boolean" />
-          <xs:element name="layout" minOccurs="0" maxOccurs="1" type="Layout" />
-        </xs:choice>
-        <xs:attribute name="action" type="FilterResult">
-          <xs:annotation>
-            <xs:documentation>Action to be taken when filter matches.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="compareTo" type="xs:string">
-          <xs:annotation>
-            <xs:documentation>String to compare the layout to.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="ignoreCase" type="xs:boolean">
-          <xs:annotation>
-            <xs:documentation>Indicates whether to ignore case when comparing strings.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="layout" type="SimpleLayoutAttribute">
-          <xs:annotation>
-            <xs:documentation>Layout to be used to filter log messages.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-      </xs:extension>
-    </xs:complexContent>
-  </xs:complexType>
-  <xs:complexType name="whenNotContains">
-    <xs:complexContent>
-      <xs:extension base="Filter">
-        <xs:choice minOccurs="0" maxOccurs="unbounded">
-          <xs:element name="action" minOccurs="0" maxOccurs="1" type="FilterResult" />
-          <xs:element name="ignoreCase" minOccurs="0" maxOccurs="1" type="xs:boolean" />
-          <xs:element name="layout" minOccurs="0" maxOccurs="1" type="Layout" />
-          <xs:element name="substring" minOccurs="0" maxOccurs="1" type="xs:string" />
-        </xs:choice>
-        <xs:attribute name="action" type="FilterResult">
-          <xs:annotation>
-            <xs:documentation>Action to be taken when filter matches.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="ignoreCase" type="xs:boolean">
-          <xs:annotation>
-            <xs:documentation>Indicates whether to ignore case when comparing strings.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="layout" type="SimpleLayoutAttribute">
-          <xs:annotation>
-            <xs:documentation>Layout to be used to filter log messages.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="substring" type="xs:string">
-          <xs:annotation>
-            <xs:documentation>Substring to be matched.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-      </xs:extension>
-    </xs:complexContent>
-  </xs:complexType>
-  <xs:complexType name="whenNotEqual">
-    <xs:complexContent>
-      <xs:extension base="Filter">
-        <xs:choice minOccurs="0" maxOccurs="unbounded">
-          <xs:element name="action" minOccurs="0" maxOccurs="1" type="FilterResult" />
-          <xs:element name="compareTo" minOccurs="0" maxOccurs="1" type="xs:string" />
-          <xs:element name="ignoreCase" minOccurs="0" maxOccurs="1" type="xs:boolean" />
-          <xs:element name="layout" minOccurs="0" maxOccurs="1" type="Layout" />
-        </xs:choice>
-        <xs:attribute name="action" type="FilterResult">
-          <xs:annotation>
-            <xs:documentation>Action to be taken when filter matches.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="compareTo" type="xs:string">
-          <xs:annotation>
-            <xs:documentation>String to compare the layout to.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="ignoreCase" type="xs:boolean">
-          <xs:annotation>
-            <xs:documentation>Indicates whether to ignore case when comparing strings.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="layout" type="SimpleLayoutAttribute">
-          <xs:annotation>
-            <xs:documentation>Layout to be used to filter log messages.</xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-      </xs:extension>
-    </xs:complexContent>
-  </xs:complexType>
-  <xs:complexType name="AccurateLocal">
-    <xs:complexContent>
-      <xs:extension base="TimeSource">
-        <xs:choice minOccurs="0" maxOccurs="unbounded" />
-      </xs:extension>
-    </xs:complexContent>
-  </xs:complexType>
-  <xs:complexType name="AccurateUTC">
-    <xs:complexContent>
-      <xs:extension base="TimeSource">
-        <xs:choice minOccurs="0" maxOccurs="unbounded" />
-      </xs:extension>
-    </xs:complexContent>
-  </xs:complexType>
-  <xs:complexType name="FastLocal">
-    <xs:complexContent>
-      <xs:extension base="TimeSource">
-        <xs:choice minOccurs="0" maxOccurs="unbounded" />
-      </xs:extension>
-    </xs:complexContent>
-  </xs:complexType>
-  <xs:complexType name="FastUTC">
-    <xs:complexContent>
-      <xs:extension base="TimeSource">
-        <xs:choice minOccurs="0" maxOccurs="unbounded" />
-      </xs:extension>
-    </xs:complexContent>
-  </xs:complexType>
-</xs:schema>

+ 0 - 40
OCPPServer/NeedConfirmPacket.cs

@@ -1,40 +0,0 @@
-namespace OCPPServer
-{
-    /// <summary>
-    /// 需要被確認的數據包
-    /// </summary>
-    public class NeedConfirmPacket
-    {
-        /// <summary>
-        /// 資料庫的ID
-        /// </summary>
-        public int Id { get; set; }
-
-        public string MachineCustomId { get; set; }
-
-        /// <summary>
-        /// 傳送次數
-        /// </summary>
-        public int SentTimes { get; set; }
-
-        /// <summary>
-        /// 傳送間隔秒數
-        /// </summary>
-        public int SentInterval { get; set; }
-
-        /// <summary>
-        /// 送出訊息
-        /// </summary>
-        public string SentMessage { get; set; }
-
-        /// <summary>
-        /// 送出的UUID
-        /// </summary>
-        public string SentUniqueId { get; set; }
-
-        ///// <summary>
-        ///// 送出的action
-        ///// </summary>
-        public string SentAction { get; set; }
-    }
-}

+ 0 - 222
OCPPServer/OCPPServer.csproj

@@ -1,222 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
-  <PropertyGroup>
-    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
-    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
-    <ProjectGuid>{9EEC9681-46E9-4656-A4D4-102EB36CDEE2}</ProjectGuid>
-    <OutputType>Exe</OutputType>
-    <AppDesignerFolder>Properties</AppDesignerFolder>
-    <RootNamespace>OCPPServer</RootNamespace>
-    <AssemblyName>OCPPServer</AssemblyName>
-    <TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
-    <FileAlignment>512</FileAlignment>
-    <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
-    <PublishUrl>發行\</PublishUrl>
-    <Install>true</Install>
-    <InstallFrom>Disk</InstallFrom>
-    <UpdateEnabled>false</UpdateEnabled>
-    <UpdateMode>Foreground</UpdateMode>
-    <UpdateInterval>7</UpdateInterval>
-    <UpdateIntervalUnits>Days</UpdateIntervalUnits>
-    <UpdatePeriodically>false</UpdatePeriodically>
-    <UpdateRequired>false</UpdateRequired>
-    <MapFileExtensions>true</MapFileExtensions>
-    <ApplicationRevision>0</ApplicationRevision>
-    <ApplicationVersion>1.0.0.%2a</ApplicationVersion>
-    <IsWebBootstrapper>false</IsWebBootstrapper>
-    <UseApplicationTrust>false</UseApplicationTrust>
-    <BootstrapperEnabled>true</BootstrapperEnabled>
-    <TargetFrameworkProfile />
-  </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
-    <PlatformTarget>AnyCPU</PlatformTarget>
-    <DebugSymbols>true</DebugSymbols>
-    <DebugType>full</DebugType>
-    <Optimize>false</Optimize>
-    <OutputPath>bin\Debug\</OutputPath>
-    <DefineConstants>DEBUG;TRACE</DefineConstants>
-    <ErrorReport>prompt</ErrorReport>
-    <WarningLevel>4</WarningLevel>
-  </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
-    <PlatformTarget>AnyCPU</PlatformTarget>
-    <DebugType>pdbonly</DebugType>
-    <Optimize>true</Optimize>
-    <OutputPath>bin\Release\</OutputPath>
-    <DefineConstants>TRACE</DefineConstants>
-    <ErrorReport>prompt</ErrorReport>
-    <WarningLevel>4</WarningLevel>
-  </PropertyGroup>
-  <ItemGroup>
-    <Reference Include="DnsClient, Version=1.0.7.0, Culture=neutral, PublicKeyToken=4574bb5573c51424, processorArchitecture=MSIL">
-      <SpecificVersion>False</SpecificVersion>
-      <HintPath>..\packages\DnsClient.1.0.7\lib\net45\DnsClient.dll</HintPath>
-    </Reference>
-    <Reference Include="EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL">
-      <HintPath>..\packages\EntityFramework.6.2.0\lib\net45\EntityFramework.dll</HintPath>
-      <Private>True</Private>
-    </Reference>
-    <Reference Include="EntityFramework.SqlServer, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL">
-      <HintPath>..\packages\EntityFramework.6.2.0\lib\net45\EntityFramework.SqlServer.dll</HintPath>
-      <Private>True</Private>
-    </Reference>
-    <Reference Include="log4net">
-      <HintPath>..\SuperWebSocket\DLL\log4net.dll</HintPath>
-    </Reference>
-    <Reference Include="MongoDB.Bson, Version=2.7.2.0, Culture=neutral, processorArchitecture=MSIL">
-      <SpecificVersion>False</SpecificVersion>
-      <HintPath>..\packages\MongoDB.Bson.2.7.2\lib\net45\MongoDB.Bson.dll</HintPath>
-    </Reference>
-    <Reference Include="MongoDB.Driver, Version=2.7.2.0, Culture=neutral, processorArchitecture=MSIL">
-      <SpecificVersion>False</SpecificVersion>
-      <HintPath>..\packages\MongoDB.Driver.2.7.0\lib\net45\MongoDB.Driver.dll</HintPath>
-    </Reference>
-    <Reference Include="MongoDB.Driver.Core, Version=2.7.0.0, Culture=neutral, processorArchitecture=MSIL">
-      <SpecificVersion>False</SpecificVersion>
-      <HintPath>..\packages\MongoDB.Driver.Core.2.7.0\lib\net45\MongoDB.Driver.Core.dll</HintPath>
-    </Reference>
-    <Reference Include="Newtonsoft.Json, Version=10.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
-      <HintPath>..\packages\Newtonsoft.Json.10.0.2\lib\net45\Newtonsoft.Json.dll</HintPath>
-      <Private>True</Private>
-    </Reference>
-    <Reference Include="NLog, Version=4.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
-      <HintPath>..\packages\NLog.4.4.12\lib\net45\NLog.dll</HintPath>
-      <Private>True</Private>
-    </Reference>
-    <Reference Include="System" />
-    <Reference Include="System.ComponentModel.DataAnnotations" />
-    <Reference Include="System.Configuration" />
-    <Reference Include="System.Core" />
-    <Reference Include="System.Net.Http, Version=4.1.1.2, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
-      <HintPath>..\packages\System.Net.Http.4.3.3\lib\net46\System.Net.Http.dll</HintPath>
-      <Private>True</Private>
-    </Reference>
-    <Reference Include="System.Net.Http.Formatting, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
-      <HintPath>..\packages\Microsoft.AspNet.WebApi.Client.5.2.3\lib\net45\System.Net.Http.Formatting.dll</HintPath>
-      <Private>True</Private>
-    </Reference>
-    <Reference Include="System.Security.Cryptography.Algorithms, Version=4.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
-      <HintPath>..\packages\System.Security.Cryptography.Algorithms.4.3.0\lib\net461\System.Security.Cryptography.Algorithms.dll</HintPath>
-      <Private>True</Private>
-    </Reference>
-    <Reference Include="System.Security.Cryptography.Encoding, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
-      <HintPath>..\packages\System.Security.Cryptography.Encoding.4.3.0\lib\net46\System.Security.Cryptography.Encoding.dll</HintPath>
-      <Private>True</Private>
-    </Reference>
-    <Reference Include="System.Security.Cryptography.Primitives, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
-      <HintPath>..\packages\System.Security.Cryptography.Primitives.4.3.0\lib\net46\System.Security.Cryptography.Primitives.dll</HintPath>
-      <Private>True</Private>
-    </Reference>
-    <Reference Include="System.Security.Cryptography.X509Certificates, Version=4.1.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
-      <HintPath>..\packages\System.Security.Cryptography.X509Certificates.4.3.0\lib\net461\System.Security.Cryptography.X509Certificates.dll</HintPath>
-      <Private>True</Private>
-    </Reference>
-    <Reference Include="System.Xml.Linq" />
-    <Reference Include="System.Data.DataSetExtensions" />
-    <Reference Include="Microsoft.CSharp" />
-    <Reference Include="System.Data" />
-    <Reference Include="System.Xml" />
-  </ItemGroup>
-  <ItemGroup>
-    <Compile Include="Command\ProcessCallErrorCmd.cs" />
-    <Compile Include="Command\ProcessCallResultCmd.cs" />
-    <Compile Include="Common\ListenerConfig.cs" />
-    <Compile Include="Common\OCPPResult.cs" />
-    <Compile Include="Common\LocalAuthorization.cs" />
-    <Compile Include="Handler\FeatureHandler.cs" />
-    <Compile Include="Handler\MakeRequestHandler.cs" />
-    <Compile Include="Handler\OCPPMessageHandler.cs" />
-    <Compile Include="Command\ProcessCallCmd.cs" />
-    <Compile Include="NeedConfirmPacket.cs" />
-    <Compile Include="Protocol\OCPPWSServer.cs" />
-    <Compile Include="Protocol\ClientData.cs" />
-    <Compile Include="SubProtocol\OCPPLog.cs" />
-    <Compile Include="SubProtocol\OCPPLogFactory.cs" />
-    <Compile Include="SubProtocol\OCPPSubCommandParser.cs" />
-    <Compile Include="SubProtocol\OCPPSubProtocol.cs" />
-    <Compile Include="Server.cs" />
-    <Compile Include="Properties\AssemblyInfo.cs" />
-    <Compile Include="Handler\MakeConfirmationHandler.cs" />
-    <Compile Include="WSServer.cs" />
-  </ItemGroup>
-  <ItemGroup>
-    <None Include="App.config">
-      <SubType>Designer</SubType>
-    </None>
-    <Content Include="NLog.config">
-      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
-    </Content>
-    <None Include="certificate.pfx">
-      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
-    </None>
-    <None Include="Config\log4net.config" />
-    <None Include="Config\log4net.unix.config" />
-    <None Include="localhost.pfx">
-      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
-    </None>
-    <None Include="NLog.xsd">
-      <SubType>Designer</SubType>
-    </None>
-    <None Include="packages.config" />
-  </ItemGroup>
-  <ItemGroup>
-    <ProjectReference Include="..\SocketCommon\SuperSocket.Common.Net40.csproj">
-      <Project>{a24f4d38-ba9c-4fd6-95b7-4980de36131a}</Project>
-      <Name>SuperSocket.Common.Net40</Name>
-    </ProjectReference>
-    <ProjectReference Include="..\Evcb.Domain\Evcb.Domain.csproj">
-      <Project>{e67aaa23-f1aa-420e-9f6b-4ba9adfa9942}</Project>
-      <Name>Evcb.Domain</Name>
-    </ProjectReference>
-    <ProjectReference Include="..\Evcb.Service\Evcb.Service.csproj">
-      <Project>{dafb773d-bbc9-4e14-ab70-5cab24f39cdd}</Project>
-      <Name>Evcb.Service</Name>
-    </ProjectReference>
-    <ProjectReference Include="..\Evcb.Utility\Evcb.Utility.csproj">
-      <Project>{a40fff0e-ae48-48ee-bcf2-da7e9dd3f798}</Project>
-      <Name>Evcb.Utility</Name>
-    </ProjectReference>
-    <ProjectReference Include="..\OCPPPacket\OCPPPacket.csproj">
-      <Project>{EB2072E6-C383-48CE-8A33-B5760F32EDC9}</Project>
-      <Name>OCPPPacket</Name>
-    </ProjectReference>
-    <ProjectReference Include="..\Packet\Packet.csproj">
-      <Project>{d507c3f2-c539-4857-8bbf-c391a5f63e33}</Project>
-      <Name>Packet</Name>
-    </ProjectReference>
-    <ProjectReference Include="..\SocketBase\SuperSocket.SocketBase.Net40.csproj">
-      <Project>{40b77789-ea11-4c05-8f52-86711d7bcaaf}</Project>
-      <Name>SuperSocket.SocketBase.Net40</Name>
-    </ProjectReference>
-    <ProjectReference Include="..\SocketEngine\SuperSocket.SocketEngine.Net40.csproj">
-      <Project>{153fef72-191c-43d9-be71-2b351c7ac760}</Project>
-      <Name>SuperSocket.SocketEngine.Net40</Name>
-    </ProjectReference>
-    <ProjectReference Include="..\SuperWebSocket\SuperWebSocket.csproj">
-      <Project>{2dc79e40-bb70-4f6a-b378-905f2fbc6e97}</Project>
-      <Name>SuperWebSocket</Name>
-    </ProjectReference>
-  </ItemGroup>
-  <ItemGroup>
-    <BootstrapperPackage Include=".NETFramework,Version=v4.5.2">
-      <Visible>False</Visible>
-      <ProductName>Microsoft .NET Framework 4.5.2 %28x86 和 x64%29</ProductName>
-      <Install>true</Install>
-    </BootstrapperPackage>
-    <BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
-      <Visible>False</Visible>
-      <ProductName>.NET Framework 3.5 SP1</ProductName>
-      <Install>false</Install>
-    </BootstrapperPackage>
-  </ItemGroup>
-  <ItemGroup />
-  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
-  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
-       Other similar extension points exist, see Microsoft.Common.targets.
-  <Target Name="BeforeBuild">
-  </Target>
-  <Target Name="AfterBuild">
-  </Target>
-  -->
-</Project>

+ 0 - 127
OCPPServer/OCPPWebSocketHeaderReceiveFilter.cs

@@ -1,127 +0,0 @@
-using SuperSocket.Common;
-using SuperSocket.SocketBase;
-using SuperWebSocket;
-using SuperWebSocket.Protocol;
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace ConsoleApplication1
-{
-    class OCPPWebSocketHeaderReceiveFilter : WebSocketReceiveFilterBase
-    {
-        private static readonly byte[] m_HeaderTerminator = Encoding.UTF8.GetBytes("\r\n\r\n");
-
-        private readonly SearchMarkState<byte> m_SearchState;
-
-        public OCPPWebSocketHeaderReceiveFilter(IWebSocketSession session)
-            : base(session)
-        {
-            m_SearchState = new SearchMarkState<byte>(m_HeaderTerminator);
-        }
-
-        public override IWebSocketFragment Filter(byte[] readBuffer, int offset, int length, bool isReusableBuffer, out int rest)
-        {
-            rest = 0;
-
-            int prevMatched = m_SearchState.Matched;
-
-            var result = readBuffer.SearchMark(offset, length, m_SearchState);
-
-            if (result < 0)
-            {
-                this.AddArraySegment(readBuffer, offset, length, isReusableBuffer);
-                return null;
-            }
-
-            int findLen = result - offset;
-            string header = string.Empty;
-
-            if (this.BufferSegments.Count > 0)
-            {
-                if (findLen > 0)
-                {
-                    this.AddArraySegment(readBuffer, offset, findLen, false);
-                    header = this.BufferSegments.Decode(Encoding.UTF8);
-                }
-                else
-                {
-                    header = this.BufferSegments.Decode(Encoding.UTF8, 0, this.BufferSegments.Count - prevMatched);
-                }
-            }
-            else
-            {
-                header = Encoding.UTF8.GetString(readBuffer, offset, findLen);
-            }
-
-            var webSocketSession = Session;
-
-            try
-            {
-                WebSocketServer.ParseHandshake(webSocketSession, new StringReader(header));
-            }
-            catch (Exception e)
-            {
-                webSocketSession.Logger.Error("Failed to parse handshake!" + Environment.NewLine + header, e);
-                webSocketSession.Close(CloseReason.ProtocolError);
-                return null;
-            }
-
-            var secWebSocketKey1 = webSocketSession.Items.GetValue<string>(WebSocketConstant.SecWebSocketKey1, string.Empty);
-            var secWebSocketKey2 = webSocketSession.Items.GetValue<string>(WebSocketConstant.SecWebSocketKey2, string.Empty);
-            var secWebSocketVersion = webSocketSession.SecWebSocketVersion;
-
-            rest = length - findLen - (m_HeaderTerminator.Length - prevMatched);
-
-            this.ClearBufferSegments();
-
-            if (string.IsNullOrEmpty(secWebSocketKey1) && string.IsNullOrEmpty(secWebSocketKey2))
-            {
-                //draft-hixie-thewebsocketprotocol-75
-                if (Handshake(webSocketSession.AppServer.WebSocketProtocolProcessor, webSocketSession))
-                    return HandshakeRequestInfo;
-            }
-            else if ("6".Equals(secWebSocketVersion)) //draft-ietf-hybi-thewebsocketprotocol-06
-            {
-                if (Handshake(webSocketSession.AppServer.WebSocketProtocolProcessor, webSocketSession))
-                    return HandshakeRequestInfo;
-            }
-            else
-            {
-                //draft-hixie-thewebsocketprotocol-76/draft-ietf-hybi-thewebsocketprotocol-00
-                //Read SecWebSocketKey3(8 bytes)
-                if (rest == SecKey3Len)
-                {
-                    webSocketSession.Items[WebSocketConstant.SecWebSocketKey3] = readBuffer.CloneRange(offset + length - rest, rest);
-                    rest = 0;
-                    if (Handshake(webSocketSession.AppServer.WebSocketProtocolProcessor, webSocketSession))
-                        return HandshakeRequestInfo;
-                }
-                else if (rest > SecKey3Len)
-                {
-                    webSocketSession.Items[WebSocketConstant.SecWebSocketKey3] = readBuffer.CloneRange(offset + length - rest, 8);
-                    rest -= 8;
-                    if (Handshake(webSocketSession.AppServer.WebSocketProtocolProcessor, webSocketSession))
-                        return HandshakeRequestInfo;
-                }
-                else
-                {
-                    //rest < 8
-                    if (rest > 0)
-                    {
-                        AddArraySegment(readBuffer, offset + length - rest, rest, isReusableBuffer);
-                        rest = 0;
-                    }
-
-                    NextReceiveFilter = new WebSocketSecKey3ReceiveFilter(this);
-                    return null;
-                }
-            }
-
-            return null;
-        }
-    }
-}

+ 0 - 35
OCPPServer/OCPPWebSocketProtocol.cs

@@ -1,35 +0,0 @@
-using SuperSocket.SocketBase;
-using SuperSocket.SocketBase.Protocol;
-using SuperWebSocket;
-using SuperWebSocket.Protocol;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace ConsoleApplication1
-{
-    class OCPPWebSocketProtocol : WebSocketProtocol
-    {
-        /// <summary>
-        /// Initializes a new instance of the <see cref="WebSocketProtocol"/> class.
-        /// </summary>
-        public OCPPWebSocketProtocol()
-        {
-
-        }
-
-        /// <summary>
-        /// Creates the filter.
-        /// </summary>
-        /// <param name="appServer">The app server.</param>
-        /// <param name="appSession">The app session.</param>
-        /// <param name="remoteEndPoint">The remote end point.</param>
-        /// <returns></returns>
-        public IReceiveFilter<IWebSocketFragment> CreateFilter(IAppServer appServer, IAppSession appSession, System.Net.IPEndPoint remoteEndPoint)
-        {
-            return new OCPPWebSocketHeaderReceiveFilter((IWebSocketSession)appSession);
-        }
-    }
-}

+ 0 - 38
OCPPServer/Properties/AssemblyInfo.cs

@@ -1,38 +0,0 @@
-using System.Reflection;
-using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
-
-// 組件的一般資訊是由下列的屬性集控制。
-// 變更這些屬性的值即可修改組件的相關
-// 資訊。
-[assembly: AssemblyTitle("OCPPServer")]
-[assembly: AssemblyDescription("")]
-[assembly: AssemblyConfiguration("")]
-[assembly: AssemblyCompany("")]
-[assembly: AssemblyProduct("OCPPServer")]
-[assembly: AssemblyCopyright("Copyright ©  2017")]
-[assembly: AssemblyTrademark("")]
-[assembly: AssemblyCulture("")]
-
-// 將 ComVisible 設定為 false 會使得這個組件中的類型
-// 對 COM 元件而言為不可見。如果您需要從 COM 存取這個組件中
-// 的類型,請在該類型上將 ComVisible 屬性設定為 true。
-[assembly: ComVisible(false)]
-
-// 下列 GUID 為專案公開 (Expose) 至 COM 時所要使用的 typelib ID
-[assembly: Guid("9eec9681-46e9-4656-a4d4-102eb36cdee2")]
-
-// 組件的版本資訊由下列四個值所組成: 
-//
-//      主要版本
-//      次要版本 
-//      組建編號
-//      修訂編號
-//
-// 您可以指定所有的值,也可以依照以下的方式,使用 '*' 將組建和修訂編號
-// 指定為預設值: 
-// [assembly: AssemblyVersion("0.1.0.0")]
-[assembly: AssemblyVersion("0.1.0.0")]
-[assembly: AssemblyFileVersion("0.1.0.0")]
-
-[assembly: AssemblyInformationalVersion("9f82982")]

+ 0 - 240
OCPPServer/Protocol/ClientData.cs

@@ -1,240 +0,0 @@
-using OCPPPacket.Packet.Messages.Basic;
-using Packet.Cmd;
-using SuperSocket.SocketBase;
-using SuperWebSocket;
-using System;
-using System.Collections.Generic;
-
-namespace OCPPServer.Protocol
-{
-    public class ClientData : WebSocketSession<ClientData>
-    {
-        public string ocppmessage = String.Empty;
-
-        public delegate void OCPPClientDataEventHandler<ClientData, String>(ClientData clientdata, String msg);
-
-        public event OCPPClientDataEventHandler<ClientData, String> m_ReceiveData;
-
-        public CmdHelper CmdHelper;
-
-        public bool IsCheckIn { get; set; }
-        public string MachineId { get; set; }
-
-        public Guid CustomerId { get; set; }
-        public string CustomerName { get; set; }
-
-        /// <summary>
-        /// 每個client有他自己的指令序號 2 byte
-        /// </summary>
-        private ushort _cmdSerNum = 0;
-
-        /// <summary>
-        /// 傳送的封包序號 1 byte
-        /// </summary>
-        private byte _serNum = 0;
-
-        /// <summary>
-        /// 傳送的chargingProfileId 1 byte
-        /// </summary>
-        private byte _chargingProfileId = 0;
-
-        /// <summary>
-        /// 取得指令序號 0-65535
-        /// </summary>
-        /// <returns></returns>
-        public ushort GetCmdSerNum()
-        {
-            if (_cmdSerNum == ushort.MaxValue)
-                _cmdSerNum = 0;
-            return ++_cmdSerNum;
-        }
-
-        /// <summary>
-        /// 取得封包序號 1-255
-        /// </summary>
-        /// <returns></returns>
-        public byte GetSerNum()
-        {
-            if (_serNum == byte.MaxValue)
-            {
-                _serNum = 0;
-            }
-            return ++_serNum;
-        }
-
-        public byte GetCurrentSerNum()
-        {
-            return _serNum;
-        }
-
-        /// <summary>
-        /// 取得封包序號 1-255
-        /// </summary>
-        /// <returns></returns>
-        public byte GetChargingProfileId()
-        {
-            if (_chargingProfileId == byte.MaxValue)
-            {
-                _chargingProfileId = 0;
-            }
-            return ++_chargingProfileId;
-        }
-
-        public byte GetCurrentChargingProfileId()
-        {
-            return _chargingProfileId;
-        }
-
-        /// <summary>
-        /// 客戶自訂的樁id
-        /// </summary>
-        public string MachineCustomId
-        {
-            get; set;
-        }
-
-        /// <summary>
-        /// 客戶自訂的樁id
-        /// </summary>
-        public string MachineCustomIdTemp
-        {
-            get; set;
-        }
-
-        /// <summary>
-        /// 根據unique id來儲存.取出OCPP Request
-        /// </summary>
-        public Queue queue;
-
-        /// <summary>
-        /// 根據 GetConfiguration Key來儲存.
-        /// </summary>
-        public List<KeyValueType> configurationKey;
-
-        /// <summary>
-        /// 車輛類別
-        /// 0:默認樁體設定  , 1:小車(12V) , 2:大車(24V)
-        /// </summary>
-        public int CarType;
-
-        /// <summary>
-        /// 上一個Heartbeat日期封包
-        /// </summary>
-        public DateTime? heartbeatDate { get; set; }
-
-        /// <summary>
-        /// 當 Heartbeat 與 上一個 Heartbeat相差值小於2秒,判斷是否送出ChangeConfiguration.req(HeartbeatInterval: 15) 給電樁
-        /// </summary>
-        public bool IsSendHeartbeatChangeConfiguration { get; set; }
-
-        /// <summary>
-        /// Gets the app server.
-        /// </summary>
-        public new OCPPWSServer AppServer
-        {
-            get { return (OCPPWSServer)base.AppServer; }
-        }
-
-        /// <summary>
-        /// Sends the raw binary data to client.
-        /// </summary>
-        /// <param name="data">The data.</param>
-        /// <param name="offset">The offset.</param>
-        /// <param name="length">The length.</param>
-        public void SendRawData(byte[] data, int offset, int length)
-        {
-            base.Send(data, offset, length);
-        }
-
-        //receive data event trigger
-        public void ReceiveData(ClientData clientdata, string msg)
-        {
-            if (m_ReceiveData != null)
-                m_ReceiveData(clientdata, msg);
-        }
-
-        /// <summary>
-        /// Called when [session closed].
-        /// </summary>
-        /// <param name="reason">The reason.</param>
-        protected override void OnSessionClosed(CloseReason reason)
-        {
-        }
-
-        public void InitialPileData()
-        {
-            this.queue = new Queue();
-            this.MachineCustomId = Guid.NewGuid().ToString();
-            this.MachineCustomIdTemp = Guid.NewGuid().ToString();
-            this.IsCheckIn = false;
-            this.configurationKey = new List<KeyValueType>();
-            this.CarType = 0; // 默認樁體設定
-            heartbeatDate = null;
-            IsSendHeartbeatChangeConfiguration = false;
-
-            #region Core
-
-            configurationKey.Add(new KeyValueType { key = "AllowOfflineTxForUnknownId", keyreadonly = false, value = "false" });
-            configurationKey.Add(new KeyValueType { key = "AuthorizationCacheEnabled", keyreadonly = false, value = "false" });
-            configurationKey.Add(new KeyValueType { key = "AuthorizeRemoteTxRequests", keyreadonly = false, value = "false" });
-            configurationKey.Add(new KeyValueType { key = "BlinkRepeat", keyreadonly = false, value = "0" });
-            configurationKey.Add(new KeyValueType { key = "ClockAlignedDataInterval", keyreadonly = false, value = "0" });
-            configurationKey.Add(new KeyValueType { key = "ConnectionTimeOut", keyreadonly = false, value = "0" });
-            configurationKey.Add(new KeyValueType { key = "GetConfigurationMaxKeys", keyreadonly = true, value = "0" });
-            configurationKey.Add(new KeyValueType { key = "HeartbeatInterval", keyreadonly = false, value = "0" });
-            configurationKey.Add(new KeyValueType { key = "LightIntensity", keyreadonly = false, value = "0" });
-            configurationKey.Add(new KeyValueType { key = "LocalAuthorizeOffline", keyreadonly = false, value = "false" });
-            configurationKey.Add(new KeyValueType { key = "LocalPreAuthorize", keyreadonly = false, value = "false" });
-            configurationKey.Add(new KeyValueType { key = "MaxEnergyOnInvalidId", keyreadonly = false, value = "0" });
-            configurationKey.Add(new KeyValueType { key = "MeterValuesAlignedData", keyreadonly = false, value = "0" });
-            configurationKey.Add(new KeyValueType { key = "MeterValuesAlignedDataMaxLength", keyreadonly = true, value = "0" });
-            configurationKey.Add(new KeyValueType { key = "MeterValuesSampledData", keyreadonly = false, value = "0" });
-            configurationKey.Add(new KeyValueType { key = "MeterValuesSampledDataMaxLength", keyreadonly = true, value = "0" });
-            configurationKey.Add(new KeyValueType { key = "MeterValueSampleInterval", keyreadonly = false, value = "0" });
-            configurationKey.Add(new KeyValueType { key = "MinimumStatusDuration", keyreadonly = false, value = "0" });
-            configurationKey.Add(new KeyValueType { key = "NumberOfConnectors", keyreadonly = true, value = "0" });
-            configurationKey.Add(new KeyValueType { key = "ResetRetries", keyreadonly = false, value = "0" });
-            configurationKey.Add(new KeyValueType { key = "ConnectorPhaseRotation", keyreadonly = false, value = "0" });
-            configurationKey.Add(new KeyValueType { key = "ConnectorPhaseRotationMaxLength", keyreadonly = true, value = "0" });
-            configurationKey.Add(new KeyValueType { key = "StopTransactionOnEVSideDisconnect", keyreadonly = false, value = "false" });
-            configurationKey.Add(new KeyValueType { key = "StopTransactionOnInvalidId", keyreadonly = false, value = "false" });
-            configurationKey.Add(new KeyValueType { key = "StopTxnAlignedData", keyreadonly = false, value = "0" });
-            configurationKey.Add(new KeyValueType { key = "StopTxnAlignedDataMaxLength", keyreadonly = true, value = "0" });
-            configurationKey.Add(new KeyValueType { key = "StopTxnSampledData", keyreadonly = false, value = "0" });
-            configurationKey.Add(new KeyValueType { key = "StopTxnSampledDataMaxLength", keyreadonly = true, value = "0" });
-            configurationKey.Add(new KeyValueType { key = "SupportedFeatureProfiles", keyreadonly = true, value = "0" });
-            configurationKey.Add(new KeyValueType { key = "SupportedFeatureProfilesMaxLength", keyreadonly = true, value = "0" });
-            configurationKey.Add(new KeyValueType { key = "TransactionMessageAttempts", keyreadonly = false, value = "0" });
-            configurationKey.Add(new KeyValueType { key = "TransactionMessageRetryInterval", keyreadonly = false, value = "0" });
-            configurationKey.Add(new KeyValueType { key = "UnlockConnectorOnEVSideDisconnect", keyreadonly = false, value = "false" });
-            configurationKey.Add(new KeyValueType { key = "WebSocketPingInterval", keyreadonly = false, value = "0" });
-
-            #endregion Core
-
-            #region Local Auth List Management
-
-            configurationKey.Add(new KeyValueType { key = "LocalAuthListEnabled", keyreadonly = false, value = "false" });
-            configurationKey.Add(new KeyValueType { key = "LocalAuthListMaxLength", keyreadonly = true, value = "0" });
-            configurationKey.Add(new KeyValueType { key = "SendLocalListMaxLength", keyreadonly = true, value = "0" });
-            #endregion Local Auth List Management
-
-
-
-            #region Reservation Profile
-
-            configurationKey.Add(new KeyValueType { key = "ReserveConnectorZeroSupported", keyreadonly = true, value = "false" });
-
-            #endregion Reservation Profile
-
-            #region Smart Charging Profile
-
-            configurationKey.Add(new KeyValueType { key = "ChargeProfileMaxStackLevel", keyreadonly = true, value = "0" });
-            configurationKey.Add(new KeyValueType { key = "ChargingScheduleAllowedChargingRateUnit", keyreadonly = true, value = "0" });
-            configurationKey.Add(new KeyValueType { key = "ChargingScheduleMaxPeriods", keyreadonly = true, value = "0" });
-            configurationKey.Add(new KeyValueType { key = "ConnectorSwitch3to1PhaseSupported", keyreadonly = true, value = "false" });
-            configurationKey.Add(new KeyValueType { key = "MaxChargingProfilesInstalled", keyreadonly = true, value = "0" });
-
-            #endregion Smart Charging Profile
-        }
-    }
-}

+ 0 - 149
OCPPServer/Protocol/OCPPWSServer.cs

@@ -1,149 +0,0 @@
-using Evcb.Domain.Model;
-using Evcb.Repository;
-using Evcb.Service;
-using SuperSocket.Common;
-using SuperWebSocket;
-using SuperWebSocket.SubProtocol;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-
-namespace OCPPServer.Protocol
-{
-    public class OCPPWSServer : WebSocketServer<ClientData>
-    {
-        /// <summary>
-        /// 可允許連線Clinet數
-        /// </summary>
-        public int connectNum { get; set; }
-
-        /// <summary>
-        /// 是否限制連線Clinet數
-        /// </summary>
-        public bool beConnectLimit { get; set; }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="WebSocketServer"/> class.
-        /// </summary>
-        /// <param name="subProtocols">The sub protocols.</param>
-        public OCPPWSServer(IEnumerable<ISubProtocol<ClientData>> subProtocols)
-            : base(subProtocols)
-        {
-        }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="WebSocketServer"/> class.
-        /// </summary>
-        /// <param name="subProtocol">The sub protocol.</param>
-        public OCPPWSServer(ISubProtocol<ClientData> subProtocol)
-            : base(subProtocol)
-        {
-        }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="WebSocketServer"/> class.
-        /// </summary>
-        public OCPPWSServer()
-            : base(new List<ISubProtocol<ClientData>>())
-        {
-        }
-
-        protected override bool ValidateHandshake(ClientData session, string origin)
-        {
-            //初始化ClientData
-            session.InitialPileData();
-            //確認電樁所送的電樁識別碼是否包含在request path中
-            string[] words = session.Path.Split('/');
-            using (var db = new PhihongDbContext())
-            {
-                if (this.beConnectLimit == true)
-                {
-                    var connectPile = db.Machine.Where(c => c.Online == true).ToList();
-                    if (connectPile.Count >= this.connectNum)
-                    {
-                        byte[] m_SwitchResponse;
-                        var responseBuilder = new StringBuilder();
-                        responseBuilder.AppendWithCrCf("HTTP/1.1 403"); //403 Forbidden : 用戶端並無訪問權限,所以伺服器給予應有的回應。
-                        responseBuilder.AppendWithCrCf("Upgrade: WebSocket");
-                        responseBuilder.AppendWithCrCf("Connection: Upgrade");
-                        responseBuilder.AppendWithCrCf("Sec-WebSocket-Version: " + session.SecWebSocketVersion);
-                        responseBuilder.AppendWithCrCf();
-
-                        m_SwitchResponse = Encoding.UTF8.GetBytes(responseBuilder.ToString());
-
-                        session.SendRawData(m_SwitchResponse, 0, m_SwitchResponse.Length);
-                        return false;
-                    }
-                }
-
-                IUnitOfWork uow = new UnitOfWork(db);
-                IMachineService machineSrv = new MachineService(uow);
-                var machine = machineSrv.GetByCustomId(words.Last());
-                if (machine == null)
-                {
-                    byte[] m_SwitchResponse;
-                    var responseBuilder = new StringBuilder();
-                    responseBuilder.AppendWithCrCf("HTTP/1.1 404");
-                    responseBuilder.AppendWithCrCf("Upgrade: WebSocket");
-                    responseBuilder.AppendWithCrCf("Connection: Upgrade");
-                    responseBuilder.AppendWithCrCf("Sec-WebSocket-Version: " + session.SecWebSocketVersion);
-                    responseBuilder.AppendWithCrCf();
-
-                    m_SwitchResponse = Encoding.UTF8.GetBytes(responseBuilder.ToString());
-
-                    session.SendRawData(m_SwitchResponse, 0, m_SwitchResponse.Length);
-                    return false;
-
-                    //session.CloseWithHandshake(session.ProtocolProcessor.CloseStatusClode.NormalClosure, "This machine can't be  recognized.");
-                }
-                session.MachineCustomIdTemp = words.Last();
-                uow.Dispose();
-            }
-
-            //session.MachineCustomIdTemp = "RDTEST101";
-
-            //確認電樁連線所送的SubProtocol是否被Server支援
-            if (session.SecWebSocketProtocol.ToLower() != "ocpp1.6")
-            {
-                const string m_Magic = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
-                const string SecWebSocketKey = "Sec-WebSocket-Key";
-                const string ResponseHeadLine10 = "HTTP/1.1 101 Switching Protocols";
-                const string Upgrade = "Upgrade";
-                const string ResponseUpgradeLine = Upgrade + ": WebSocket";
-                const string Connection = "Connection";
-                const string ResponseConnectionLine = Connection + ": Upgrade";
-                const string ResponseAcceptLine = "Sec-WebSocket-Accept: {0}";
-
-                var responseBuilder = new StringBuilder();
-                var secWebSocketKey = session.Items.GetValue<string>(SecWebSocketKey, string.Empty);
-                if (string.IsNullOrEmpty(secWebSocketKey))
-                {
-                    return false;
-                }
-                string secKeyAccept = string.Empty;
-
-                try
-                {
-                    secKeyAccept = Convert.ToBase64String(System.Security.Cryptography.SHA1.Create().ComputeHash(Encoding.ASCII.GetBytes(secWebSocketKey + m_Magic)));
-                }
-                catch (Exception)
-                {
-                    return false;
-                }
-
-                responseBuilder.AppendWithCrCf(ResponseHeadLine10);
-                responseBuilder.AppendWithCrCf(ResponseUpgradeLine);
-                responseBuilder.AppendWithCrCf(ResponseConnectionLine);
-                responseBuilder.AppendFormatWithCrCf(ResponseAcceptLine, secKeyAccept);
-                responseBuilder.AppendWithCrCf();
-                byte[] data = Encoding.UTF8.GetBytes(responseBuilder.ToString());
-                session.SendRawData(data, 0, data.Length);
-                session.CloseWithHandshake(session.ProtocolProcessor.CloseStatusClode.NormalClosure, "This SubProtocol can't be  supported.");
-                return false;
-            }
-            //session.m_ReceiveData += new ClientData.OCPPClientDataEventHandler<ClientData, String>(WSServer.ReceivedMessage);
-            return true;
-        }
-    }
-}

+ 0 - 28
OCPPServer/Server.cs

@@ -1,28 +0,0 @@
-using Newtonsoft.Json;
-using Newtonsoft.Json.Linq;
-using NLog;
-using OCPPServer.Handler;
-using OCPPServer.Protocol;
-using OCPPServer.SubProtocol;
-using SuperSocket.SocketBase;
-using SuperWebSocket;
-using SuperWebSocket.SubProtocol;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Threading;
-using System.Threading.Tasks;
-using System.Xml.Linq;
-
-namespace OCPPServer
-{
-    internal class Server
-    {
-        private static void Main(string[] args)
-        {
-            WSServer s = new WSServer();
-            Console.WriteLine("Starting Server...");
-            s.Start();
-        }
-    }
-}

+ 0 - 770
OCPPServer/Service/WebSocketCommandService.cs

@@ -1,770 +0,0 @@
-using Evcb.Domain.Model;
-using Evcb.Repository;
-using Evcb.Service;
-using Evcb.Service.Helpers;
-using Evcb.Service.Service.Common;
-using Newtonsoft.Json;
-using NLog;
-using OCPP_Packet.Packet.DataTransfer;
-using OCPP_Packet.Packet.Status;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace OCPPServer.Service
-{
-    public class WebSocketCommandService : Service<Machine>
-    {
-        private ILogger logger = NLog.LogManager.GetCurrentClassLogger();
-
-        private readonly IRepository<ChargingRecordStatus> _chargingRecordStatusRepo;
-        private readonly IRepository<MachineGun> _machineGunRepo;
-        private readonly IRepository<ChargingRecord> _chargingRecordRepo;
-        private readonly IRepository<ChargingRecordReport> _chargingRecordReportRepo;
-        private readonly IRepository<MachineError> _meRepo;
-        private readonly IRepository<MemberCharging> _memberChargingRepo;
-        public WebSocketCommandService(IUnitOfWork uow) : base(uow)
-        {
-            _uow = uow;
-            _chargingRecordRepo = _uow.Repository<ChargingRecord>();
-            _machineGunRepo = _uow.Repository<MachineGun>();
-            _chargingRecordStatusRepo = _uow.Repository<ChargingRecordStatus>();
-            _chargingRecordReportRepo = _uow.Repository<ChargingRecordReport>();
-            _meRepo = _uow.Repository<MachineError>();
-            _memberChargingRepo = _uow.Repository<MemberCharging>();
-        }
-
-        public ProcessStatusPacketResult Process1104(ChargingRecordStatus value)
-        {
-            ProcessStatusPacketResult result = new ProcessStatusPacketResult() { StartChargingType = -1 };
-            var gun = _machineGunRepo.Query(c => c.GunSerNo == value.GunSerNo && c.Machine.Id == value.MachineId).Include(c => c.Machine).Include(c => c.Machine.Customer).Select().FirstOrDefault();
-            value.CreatedOn = DateTime.Now;
-            logger.Trace(value.MachineCustomId + "進入104處理");
-
-            if (gun != null)
-            {
-                //舊的充電序號
-                Guid oldGuid = Guid.Empty;
-
-                //狀態改變,更換序號
-                if ((gun.Status == 2 || gun.Status == 3) && (value.Status == 2 || value.Status == 3))
-                {
-                    //2跟3算同一個狀態 For AC,不更換序號
-                }
-                else if (gun.Status != value.Status)
-                {
-                    oldGuid = gun.ChargingSerNo;
-                    gun.ChargingSerNo = Guid.NewGuid();
-                }
-
-                //從正準備開始充電轉換到充電進行中,新增一筆充電紀錄
-                //if (((gun.Status == 1 || gun.Status == 0) && value.Status == 2) || ((gun.Status == 1 || gun.Status == 0) && value.Status == 3))
-                if (value.Status == 2)
-                {
-
-                    //DateTime sDate = value.StartChargingDateTime.Value.AddMilliseconds(-1);
-                    //DateTime eDate = value.StartChargingDateTime.Value.AddMilliseconds(3);
-                    ChargingRecord nObj = _chargingRecordRepo.Query(
-                    //    c => c.StartChargingDateTime >= sDate
-                    //&& c.StartChargingDateTime <= eDate
-                    c => c.StartChargingDateTime == value.StartChargingDateTime.Value
-                    && c.GunSerNo == value.GunSerNo
-                    && c.MachineId == gun.MachineId).Select().FirstOrDefault();
-
-                    //沒有該筆充電序才去產生帳單紀錄
-                    if (nObj == null && value.StartChargingDateTime.HasValue)
-                    {
-                        gun.ChargingSerNo = Guid.NewGuid();
-
-                        nObj = new ChargingRecord()
-                        {
-                            StartChargingDateTime = value.StartChargingDateTime.Value,
-                            StartWith = value.StartWith,
-                            GunSerNo = gun.GunSerNo,
-                            MachineId = gun.Machine.Id,
-                            MachineCustomId = gun.Machine.CustomId,
-                            ChargingSerNo = gun.ChargingSerNo,
-                            ChargingStrategy = value.ChargingStrategy,
-                            ChargingStrategyParam = (int)value.ChargingStrategyParam,
-                            CreatedOn = DateTime.Now
-                        };
-
-                        _chargingRecordRepo.Add(nObj);
-
-                        logger.Trace(gun.Machine.CustomId + "開始充電轉換到充電進行中");
-                        logger.Trace("nObj:" + JsonConvert.SerializeObject(nObj));
-                        logger.Trace("value:" + JsonConvert.SerializeObject(value));
-
-                        //如果每筆記錄都要回報
-                        if (gun.Machine.Customer.AutoCreateReportRecord)
-                        {
-                            //如果是卡片充電的話
-                            if (value.StartWith == 1)
-                            {
-                                logger.Trace("卡片充電:");
-                                ChargingRecordReport rr = new ChargingRecordReport()
-                                {
-                                    StartChargingDateTime = value.StartChargingDateTime.Value,
-                                    MachineId = nObj.MachineId,
-                                    MachineCustomId = nObj.MachineCustomId,
-                                    CardNum = value.ReservationCardNum,
-                                    StartWith = value.StartWith,
-                                    ChargingSerNo = nObj.ChargingSerNo,
-                                    CustomerId = gun.Machine.CustomerId,
-                                    GunSerNo = value.GunSerNo,
-                                    //ChargeStrategy = 2,
-                                    ChargeStrategy = value.ChargingStrategy,
-                                    ChargeStrategyParam = value.CardBalanceBeforeCharging,
-                                    CreatedOn = DateTime.Now,
-                                };
-                                logger.Trace("rr:" + JsonConvert.SerializeObject(rr));
-                                _chargingRecordReportRepo.Add(rr);
-                                result.StartChargingType = 0;
-                                result.ChargingSerNo = rr.ChargingSerNo;
-                                result.Result = 12;
-                            }
-                        }
-                    }
-                }
-
-                //發出一個新的告警,就紀錄到table中
-                if (value.Status == 6)
-                {
-                    var hasSameError = _uow.Repository<MachineError>().Query(c => c.MachineId == value.MachineId && c.GunSerNo == gun.GunSerNo).Select().OrderByDescending(c => c.CreatedOn).FirstOrDefault();
-
-                    MachineError me = new MachineError { CreatedOn = DateTime.Now, MachineId = gun.MachineId, PreStatus = gun.Status, Status = value.Status, ErrorCode = value.Warning, GunSerNo = gun.GunSerNo };
-
-                    if (gun.Status != 6)
-                    {
-                        // Gun previous status is other status
-                        if (hasSameError != null)
-                        {
-                            if (((value.Warning == hasSameError.ErrorCode) && ((value.CreatedOn - hasSameError.CreatedOn).Value.TotalMinutes > 3)) || (value.Warning != hasSameError.ErrorCode))
-                            {
-                                _meRepo.Add(me);
-                                NoticeError(me);
-                            }
-                        }
-                        else
-                        {
-                            _meRepo.Add(me);
-                            NoticeError(me);
-                        }
-                    }
-                    else
-                    {
-                        // Gun previous status is alarm status
-                        if (value.Warning != hasSameError.ErrorCode)
-                        {
-                            _meRepo.Add(me);
-                            NoticeError(me);
-                        }
-                        //logger.Trace("value.CreatedOn - hasSameError.CreatedOn=" + (value.CreatedOn - hasSameError.CreatedOn).Value.TotalMinutes.ToString());
-                    }
-                }
-                ////從充電中,切換狀態到充電結束
-                //if (gun.Status == 2 && value.Status == 3)
-                //{
-                //    var chargingRecordObj = _chargingRecordRepo.Query(c => c.ChargingSerNo == oldGuid).Select().FirstOrDefault();
-                //    chargingRecordObj.EndChargingDateTime = DateTime.Now;
-                //    _chargingRecordRepo.Update(chargingRecordObj);
-                //}
-
-                gun.Status = value.Status;
-                value.ChargingSerNo = gun.ChargingSerNo;
-                //value.CreatedOn = DateTime.Now;
-                _chargingRecordStatusRepo.Add(value);
-                _uow.SaveChanges();
-
-                return result;
-            }
-            else
-            {
-                throw new ApplicationException("wrong guns!");
-            }
-        }
-
-        private IResult NoticeError(MachineError error)
-        {
-            IResult result = new Result();
-            try
-            {
-                string description = "None";
-                var machineRepo = _uow.Repository<Machine>();
-                var machine = machineRepo.Query(c => c.Id == error.MachineId).Include(c => c.Customer).Select().FirstOrDefault();
-                var accountRepo = _uow.Repository<Account>();
-                var account = accountRepo.Query(c => c.CustomerId == machine.CustomerId).Select().FirstOrDefault();
-                var errorRepo = _uow.Repository<ErrorCode>();
-                var errorMsg = errorRepo.Query(c => c.Code == error.ErrorCode).Select().FirstOrDefault();
-                if (errorMsg != null)
-                {
-                    if (errorMsg.AC == machine.AC)
-                    {
-                        description = errorMsg.Description;
-                    }
-                }
-                if (!string.IsNullOrEmpty(account.Email))
-                {
-                    string[] emailgroup = account.Email.Split(',');
-                    string subject = string.Format("客户: {0} 飞宏电桩号: {1} 客户电桩号: {2} 错误代码:{3}", machine.Customer.CustomerDesc, machine.CustomId, machine.PartnerPoleId, error.ErrorCode);
-                    string detail = string.Format("[时间点: {0}] 飞宏电桩号: {1} 客户电桩号: {2},枪号 : {3},错误代码: {4} 说明: {5}", error.CreatedOn, machine.CustomId, machine.PartnerPoleId, Convert.ToChar(65 + error.GunSerNo), error.ErrorCode, description);
-                    string body = string.Format("详细讯息: {2} ", machine.PartnerPoleId, error.ErrorCode, detail);
-                    foreach (var email in emailgroup)
-                    {
-                        DispatchMessageHelper.SendMail(email, subject, body);
-                    }
-                }
-
-                result.Success = true;
-                return result;
-            }
-            catch (Exception ex)
-            {
-                logger.Error(ex);
-                result.Exception = ex;
-                result.Success = false;
-                return result;
-            }
-        }
-
-        /// <summary>
-        /// 處理經緯度
-        /// </summary>
-        /// <param name="machineId">電樁Id</param>
-        /// <param name="Location">Location command</param>
-        /// <returns></returns>
-        public IResult ProcessLocation(string customId, Location value)
-        {
-            IResult result = new Result();
-            double radius = 0.005d;
-            try
-            {
-                var machineRepo = _uow.Repository<Machine>();
-                var _chargerStationRepo = _uow.Repository<ChargerStation>();
-                var machine = machineRepo.Query(c => c.CustomId == customId).Select().FirstOrDefault();
-                var stations = _chargerStationRepo.Query(c => c.CustomerId == machine.CustomerId).Select().ToList();
-                //Mapping 充電樁的位置 以資料庫列表中充電樁站點為圓心,判斷上報的充電樁位置是否在附近
-                //以0.005d為半徑 超出者預設 0
-                //double KeyX = 0d, KeyY = 0d;
-                bool isNearAnyStation = false;
-                foreach (var station in stations)
-                {
-                    double YDist = Convert.ToDouble(station.Latitude - Convert.ToDecimal(value.latitude));
-                    double XDist = Convert.ToDouble(station.Longitude - Convert.ToDecimal(value.longitude));
-                    if (Math.Pow(XDist, 2d) + Math.Pow(YDist, 2d) <= Math.Pow(radius, 2d))
-                    {
-                        isNearAnyStation = true;
-                        if (machine.Location != station.Id)
-                        {
-                            machine.Location = station.Id;
-                        }
-                    }
-                }
-
-                if (!isNearAnyStation & machine.Location != 0)
-                {
-                    machine.Location = 0;
-                }
-                _uow.SaveChanges();
-                result.Success = true;
-                return result;
-            }
-            catch (Exception ex)
-            {
-                logger.Error(ex);
-                result.Exception = ex;
-                result.Success = false;
-                return result;
-            }
-        }
-
-        /// <summary>
-        /// 處理BMS訊息
-        /// </summary>
-        /// <param name="machineId">電樁Id</param>
-        /// <param name="ChargingGunBMS">ChargingGunBMS command</param>
-        /// <returns></returns>
-        public IResult ProcessChargingGunBMS(string machineId, ChargingGunBMS cmd)
-        {
-            IResult result = new Result();
-            var _machineGunRepo = _uow.Repository<MachineGun>();
-            var _chargingRecordBMSRepo = _uow.Repository<ChargingRecordBMS>();
-            try
-            {
-                var chargingSerNo = _machineGunRepo.Query(x => x.MachineId == machineId && x.GunSerNo == cmd.connectorId && x.Status != 0).Select(x => x.ChargingSerNo).FirstOrDefault();
-                if (chargingSerNo == null) chargingSerNo = Guid.Empty;
-
-                _chargingRecordBMSRepo.Add(new ChargingRecordBMS()
-                {
-                    MachineId = machineId,
-                    MachineCustomId = _repository.Query(x => x.Id == machineId).Select(x => x.PartnerPoleId).FirstOrDefault(),
-                    GunSerNo = Convert.ToByte(cmd.connectorId-1),
-                    ChargingSerNo = chargingSerNo == null ? Guid.Empty : chargingSerNo,
-                    Status = Convert.ToByte(cmd.status),
-                    CarConnection = Convert.ToByte(cmd.carConnectionStatus),
-                    BRMBMS_ProtocolVersion = cmd.brm_bmsVersion,
-                    BR_BatteryType = Convert.ToByte(cmd.br_BatteryType),
-                    BRM_CarBattery_SystemRatedCurrent = Convert.ToDecimal(cmd.brm_BatterySystemRatedcapacity),
-                    BRM_CarBattery_SystemRatedVoltage = Convert.ToDecimal(cmd.brm_BatterySystemRatedVoltage),
-                    BRM_BatteryManufacturer = cmd.brm_BatteryManufacturer,
-                    BRM_BatteryGroupSN = cmd.brm_BatteryNumber,
-                    BRM_BatteryGroupProductionDate = cmd.brm_ProductionDate,
-                    BRM_BatteryGroupChargingTimes = cmd.brm_BatteryChargeTimes,
-                    BRM_BatteryGroupPropertyRight = Convert.ToByte(cmd.brm_BatteryPropertySign),
-                    BRM_Reserve = Convert.ToByte(cmd.brm_Reserved),
-                    BRM_VIN = cmd.brm_Vin,
-                    BRMBMS_SoftwareVersion = cmd.brm_bmsSoftwareVersion,
-                    BCP_SingleBatteryAllowChargeMaxVoltage = Convert.ToDecimal(cmd.bcp_SingleBatteryHightestChargeVoltage),
-                    BCP_AllowChargeMaxCurrent = Convert.ToDecimal(cmd.bcp_HightestChargeCurrent),
-                    BCP_BatteryFlagTotalEnergy = Convert.ToDecimal(cmd.bcp_BatteryLabelingTotalEnergy),
-                    BCP_AllowChargeMaxTotalVoltage = Convert.ToDecimal(cmd.bcp_HightestChargeVoltage),
-                    BCP_AllowHighestTemperature = cmd.bcp_HightestTemperature,
-                    BCP_CarBatterySOC = Convert.ToDecimal(cmd.bcp_VehiclePowerBatteryChargeState),
-                    BCP_CarBatteryCurrentBatteryVoltage = Convert.ToDecimal(cmd.bcp_VehicleBatteryCurrentVoltage),
-                    BROBMS_IsReadyCharge = Convert.ToByte((cmd.bro_bms_ChargeReadyStatus == ChargeReadyStatus.NotReady) ? 0x00 : ((cmd.bro_bms_ChargeReadyStatus == ChargeReadyStatus.Ready) ? 0xAA : 0xFF)),
-                    BCL_Voltage = Convert.ToDecimal(cmd.bcl_DemandVoltage),
-                    BCL_Current = Convert.ToDecimal(cmd.bcl_DemandCurrent),
-                    BCL_ChargeMode = Convert.ToByte(cmd.bcl_ChargeMode),
-                    BCS_ChargeVotageMeasurement = Convert.ToDecimal(cmd.bcs_ChargeVoltageMeasurement),
-                    BCS_ChargeCurrentMeasurement = Convert.ToDecimal(cmd.bcs_ChargeCurrentMeasurement),
-                    BCS_SingleBatteryMaxVoltage = Convert.ToDecimal(cmd.bcs_HightestSingleBatteryVoltage),
-                    BCS_SingleBatteryGroupNumber = cmd.bcs_HightestSingleBatteryNumber,
-                    BCS_CurrentSOC = Convert.ToByte(cmd.bcs_CurrentSOC),
-                    RemainingChargeMins = cmd.remainingChargeTime,
-                    BSM_SingleBatteryMaxVoltageNumber = cmd.bsm_HightestSingleBatteryVoltageNumber,
-                    BSM_BatteryHighestTemperature = cmd.bsm_HightestBatteryTemperature,
-                    BSM_HighestTemperatureCheckPointNumber = cmd.bsm_HightestTemperatureDetectionPointNumber,
-                    BSM_BatteryLowestTemperature = cmd.bsm_LowestBatteryTemperature,
-                    BSM_LowestTemperatureCheckPointNumber = cmd.bsm_LowestTemperatureDetectionPointNumber,
-                    BSM_SingleBatteryVoltageStatus = Convert.ToByte((cmd.bsm_SingleBatteryVoltageStatus == BMSStatusAType.Normal) ? 0x00 : ((cmd.bsm_SingleBatteryVoltageStatus == BMSStatusAType.TooHigh) ? 0x01 : 0x10)),
-                    BSM_CarBatterySOCStatus = Convert.ToByte((cmd.bsm_VehicleBatterySOCStatus == BMSStatusAType.Normal) ? 0x00: ((cmd.bsm_VehicleBatterySOCStatus == BMSStatusAType.TooHigh) ? 0x01 : 0x10)),
-                    BSM_BatteryChargineCurrentStatus = Convert.ToByte((cmd.bsm_BatteryChargeCurrentStatus == BMSStatusBType.Normal) ? 0x00 : ((cmd.bsm_BatteryChargeCurrentStatus == BMSStatusBType.TooHigh) ? 0x01 : 0x10)),
-                    BSM_BatteryTemperatureTooHigh = Convert.ToByte((cmd.bsm_BatteryTemperatureStatus == BMSStatusBType.Normal) ? 0x00 : ((cmd.bsm_BatteryTemperatureStatus == BMSStatusBType.TooHigh) ? 0x01 : 0x10)),
-                    BSM_BatteryInsulationStatus = Convert.ToByte((cmd.bsm_BatteryInsulationStatus == BMSStatusBType.Normal) ? 0x00 : ((cmd.bsm_BatteryInsulationStatus == BMSStatusBType.TooHigh) ? 0x01 : 0x10)),
-                    BSM_BatteryOutputConnectionStatus = Convert.ToByte((cmd.bsm_BatteryOutputConnectorConnectionStatus == BMSStatusBType.Normal) ? 0x00 : ((cmd.bsm_BatteryOutputConnectorConnectionStatus == BMSStatusBType.TooHigh) ? 0x01 : 0x10)),
-                    BSM_AllowCharge = Convert.ToByte((cmd.bsm_IsAllowedCharge == false) ? 0x00 : 0x01),
-                    BSTBMS_SOCGoal = Convert.ToByte((cmd.bst_bms_IsAchievedSOCTargetStatus == BMSStatusCType.Below) ? 0x00 : ((cmd.bst_bms_IsAchievedSOCTargetStatus == BMSStatusCType.Standard) ? 0x01 : 0x10)),
-                    BSTBMS_TotalVotageSetting = Convert.ToByte((cmd.bst_bms_IsAchievedSettingTotalVoltageStatus == BMSStatusCType.Below) ? 0x00 : ((cmd.bst_bms_IsAchievedSettingTotalVoltageStatus == BMSStatusCType.Standard) ? 0x01 : 0x10)),
-                    BST_SingleVotageSetting = Convert.ToByte((cmd.bst_IsAchievedSettingSingleVoltageStatus == BMSStatusCType.Below) ? 0x00 : ((cmd.bst_IsAchievedSettingSingleVoltageStatus == BMSStatusCType.Standard) ? 0x01 : 0x10)),
-                    BST_ChargerActiveStop = Convert.ToByte((cmd.bst_chargerAutoTerminationStatus == ChargerAutoTerminationStatus.Normal) ? 0x00 : ((cmd.bst_chargerAutoTerminationStatus == ChargerAutoTerminationStatus.ChargerIsTerminated) ? 0x01 : 0x10)),
-                    BST_InsulationError = Convert.ToByte((cmd.bst_InsulationFaultStatus == BMSStatusDType.Normal) ? 0x00 : ((cmd.bst_InsulationFaultStatus == BMSStatusDType.Fault) ? 0x01 : 0x10)),
-                    BST_OutputConnectionOverTemperatureError = Convert.ToByte((cmd.bst_OutputConnectorTemperatureStatus == BMSStatusDType.Normal) ? 0x00 : ((cmd.bst_OutputConnectorTemperatureStatus == BMSStatusDType.Fault) ? 0x01 : 0x10)),
-                    BSTBMSComponent_OutputConnectionOverTemperatureError = Convert.ToByte((cmd.bst_bms_OutputConnectorTemperatureStatus == BMSStatusDType.Normal) ? 0x00 : ((cmd.bst_bms_OutputConnectorTemperatureStatus == BMSStatusDType.Fault) ? 0x01 : 0x10)),
-                    BST_ChargeConnectionError = Convert.ToByte((cmd.bst_chargerConnectorStatus == BMSStatusBType.Normal) ? 0x00 : ((cmd.bst_chargerConnectorStatus == BMSStatusBType.TooHigh) ? 0x01 : 0x10)),
-                    BST_BatteryGroupOverTemperatureError = Convert.ToByte((cmd.bst_BatteryTemperatureStatus == BMSStatusBType.Normal) ? 0x00 : ((cmd.bst_BatteryTemperatureStatus == BMSStatusBType.TooHigh) ? 0x01 : 0x10)),
-                    BST_HighVoltageRelayError = Convert.ToByte((cmd.bst_HighVoltageRelayStatus == BMSStatusBType.Normal) ? 0x00 : ((cmd.bst_HighVoltageRelayStatus == BMSStatusBType.TooHigh) ? 0x01 : 0x10)),
-                    BST_Checkponit2VoltageCheckError = Convert.ToByte((cmd.bst_DetectionPoint2Voltage == BMSStatusBType.Normal) ? 0x00 : ((cmd.bst_DetectionPoint2Voltage == BMSStatusBType.TooHigh) ? 0x01 : 0x10)),
-                    BST_OtherError = Convert.ToByte((cmd.bst_Other == BMSStatusBType.Normal) ? 0x00 : ((cmd.bst_Other == BMSStatusBType.TooHigh) ? 0x01 : 0x10)),
-                    BST_OverCurrent = Convert.ToByte((cmd.bst_Current == BMSStatusBType.Normal) ? 0x00 : ((cmd.bst_Current == BMSStatusBType.TooHigh) ? 0x01 : 0x10)),
-                    BST_VoltageError = Convert.ToByte((cmd.bst_Voltage == BMSStatusBType.Normal) ? 0x00 : ((cmd.bst_Voltage == BMSStatusBType.TooHigh) ? 0x01 : 0x10)),
-                    BSD_StopSOC = Convert.ToByte(cmd.bsd_EndSOC),
-                    BSD_SingleBatteryLowestVoltage = Convert.ToDecimal(cmd.bsd_SingleBatteryLowestVoltage),
-                    BSD_SingleBatteryHighestVoltage = Convert.ToDecimal(cmd.bsd_SingleBatteryHightestVoltage),
-                    BSD_BatteryLowestTemperature = cmd.bsd_BatteryLowestTemperature,
-                    BSD_BatteryHighestTemperature = cmd.bsd_BatteryHightestTemperature,
-                    BEM_ReceivedSPN2560_0x00 = Convert.ToByte((cmd.bem_ReceivedSPN2560_00_Status == BMSStatusEType.Normal) ? 0x00 : ((cmd.bem_ReceivedSPN2560_00_Status == BMSStatusEType.TimeOut) ? 0x01 : 0x10)),
-                    BEM_ReceivedSPN2560_0xAA = Convert.ToByte((cmd.bem_ReceivedSPN2560_aa_Status == BMSStatusEType.Normal) ? 0x00 : ((cmd.bem_ReceivedSPN2560_aa_Status == BMSStatusEType.TimeOut) ? 0x01 : 0x10)),
-                    BEM_ReceivedSyncAndMaxOutputPower_Timeout = Convert.ToByte((cmd.bem_ReceivedTimeSyncAndMaxOutputStatus == BMSStatusEType.Normal) ? 0x00 : ((cmd.bem_ReceivedTimeSyncAndMaxOutputStatus == BMSStatusEType.TimeOut) ? 0x01 : 0x10)),
-                    BEM_ReceivedReadyCharge_Timeout = Convert.ToByte((cmd.bem_ReceivedReadyMessageStatus == BMSStatusEType.Normal) ? 0x00 : ((cmd.bem_ReceivedReadyMessageStatus == BMSStatusEType.TimeOut) ? 0x01 : 0x10)),
-                    BEM_ReceivedChargerStatus_Timeout = Convert.ToByte((cmd.bem_ReceivedStatusMessageStatus == BMSStatusEType.Normal) ? 0x00 : ((cmd.bem_ReceivedStatusMessageStatus == BMSStatusEType.TimeOut) ? 0x01 : 0x10)),
-                    BEM_ReceivedChargerStopCharge_Timeout = Convert.ToByte((cmd.bem_ReceivedStopMessageStatus == BMSStatusEType.Normal) ? 0x00 : ((cmd.bem_ReceivedStopMessageStatus == BMSStatusEType.TimeOut) ? 0x01 : 0x10)),
-                    BEM_ReceivedChargerChargeStatistics_Timeout = Convert.ToByte((cmd.bem_ReceivedStatisticsMessageStatus == BMSStatusEType.Normal) ? 0x00 : ((cmd.bem_ReceivedStatisticsMessageStatus == BMSStatusEType.TimeOut) ? 0x01 : 0x10)),
-                    BEM_Other = Convert.ToByte(cmd.bem_Other),
-                    CreateOn = DateTime.Now
-                });
-                _uow.SaveChanges();
-                result.Success = true;
-            }
-            catch (Exception ex)
-            {
-                result.Exception = ex;
-                result.Message = ex.Message;
-            }
-
-            return result;
-        }
-
-        /// <summary>
-        /// 處理ChargeComplete
-        /// </summary>
-        /// <param name="value">ChargeComplete command</param>
-        /// <param name="MachineCustomId">電樁樁號</param>
-        /// <returns></returns>
-        public IResult ProcessChargeComplete(ChargeComplete value, string MachineCustomId)
-        {
-            IResult result = new Result();
-            var _chargingRecordRepo = _uow.Repository<ChargingRecord>();
-            var crrRepo = _uow.Repository<ChargingRecordReport>();
-            var machineRepo = _uow.Repository<Machine>();
-            try
-            {
-                var machine = machineRepo.Query(c => c.CustomId == MachineCustomId).Select().FirstOrDefault();
-                var chargingTransaction = _uow.Repository<ChargingTransaction>().Query(c => c.TransactionId == value.transactionId).Select().FirstOrDefault();
-                if(chargingTransaction == null)
-                {
-                    result.Success = false;
-                    result.Message = "No Transaction Id";
-                    return result;
-                }
-                var record = _chargingRecordRepo.Query(c => c.Id == chargingTransaction.ChargingRecordId).Select().FirstOrDefault();
-
-                //沒有資料就補上去
-                bool isNew = false;
-                if (record == null)
-                {
-                    record = new ChargingRecord();
-                    record.MachineId = machine.Id;
-                    record.MachineCustomId = machine.CustomId;
-                    record.GunSerNo = (byte)(value.connectorId-1);
-                    record.ChargingSerNo = Guid.NewGuid();
-                    record.StartChargingDateTime = value.startChargingDateTime;//value.startChargingDateTime.ToLocalTime();
-                    record.EndChargingDateTime = value.chargeCompleteDateTime;//value.chargeCompleteDateTime.ToLocalTime();
-                    record.CreatedOn = DateTime.Now;
-                    isNew = true;
-                }
-
-                #region Mapper
-                record.CumulativeKwh = (decimal)value.cumulativeKwh;
-                record.KwhBeforeCharging = (decimal)value.beforeChargingKwh;
-                record.KwhAfterCharging = (decimal)value.chargeCompleteKwh;
-                record.ElectricBill = Decimal.Multiply((decimal)value.cumulativeKwh, machine.PricePerKWH);//(decimal)value.electricBill;
-                record.FeeAmount = Decimal.Multiply((decimal)value.cumulativeKwh, machine.FeePerKWH);//(decimal)value.feeAmount;
-                record.SumOfMoney = record.ElectricBill + record.FeeAmount;
-                record.StopChargingReason = (int)value.reason;
-                record.StartWith = (byte)value.startWith;
-                record.StartSoc = (byte)value.startChargingSOC;
-                record.StartChargingType = (byte)value.startChargingType;
-                record.PayOffline = (byte)(value.isPayOffline ? 1 : 0);
-                record.EndSoc = (byte)value.chargeCompleteSOC;
-                record.ChargingStrategyParam = (int)value.chargingStrategyParameter;
-                record.ChargingStrategy = (byte)value.chargingStrategy;
-                record.CarNum = value.licensePlateNumber;
-                record.CardVIN = value.vinCode;
-                record.CardBalanceBeforeCharging = (decimal)value.cardBalanceBeforeCharging;
-                record.CardBalanceAfterCharging = (decimal)value.cardBalanceAfterCharging;
-                record.Time1 = (decimal)value.sectionKwh[0];
-                record.Time2 = (decimal)value.sectionKwh[1];
-                record.Time3 = (decimal)value.sectionKwh[2]; 
-                record.Time4 = (decimal)value.sectionKwh[3];
-                record.Time5 = (decimal)value.sectionKwh[4];
-                record.Time6 = (decimal)value.sectionKwh[5];
-                record.Time7 = (decimal)value.sectionKwh[6];
-                record.Time8 = (decimal)value.sectionKwh[7];
-                record.Time9 = (decimal)value.sectionKwh[8];
-                record.Time10 = (decimal)value.sectionKwh[9];
-                record.Time11 = (decimal)value.sectionKwh[10];
-                record.Time12 = (decimal)value.sectionKwh[11];
-                record.Time13 = (decimal)value.sectionKwh[12];
-                record.Time14 = (decimal)value.sectionKwh[13];
-                record.Time15 = (decimal)value.sectionKwh[14];
-                record.Time16 = (decimal)value.sectionKwh[15];
-                record.Time17 = (decimal)value.sectionKwh[16];
-                record.Time18 = (decimal)value.sectionKwh[17];
-                record.Time19 = (decimal)value.sectionKwh[18];
-                record.Time20 = (decimal)value.sectionKwh[19];
-                record.Time21 = (decimal)value.sectionKwh[20];
-                record.Time22 = (decimal)value.sectionKwh[21];
-                record.Time23 = (decimal)value.sectionKwh[22];
-                record.Time24 = (decimal)value.sectionKwh[23];
-                record.Time25 = (decimal)value.sectionKwh[24];
-                record.Time26 = (decimal)value.sectionKwh[25];
-                record.Time27 = (decimal)value.sectionKwh[26];
-                record.Time28 = (decimal)value.sectionKwh[27];
-                record.Time29 = (decimal)value.sectionKwh[28];
-                record.Time30 = (decimal)value.sectionKwh[29];
-                record.Time31 = (decimal)value.sectionKwh[30];
-                record.Time32 = (decimal)value.sectionKwh[31];
-                record.Time33 = (decimal)value.sectionKwh[32];
-                record.Time34 = (decimal)value.sectionKwh[33];
-                record.Time35 = (decimal)value.sectionKwh[34];
-                record.Time36 = (decimal)value.sectionKwh[35];
-                record.Time37 = (decimal)value.sectionKwh[36];
-                record.Time38 = (decimal)value.sectionKwh[37];
-                record.Time39 = (decimal)value.sectionKwh[38];
-                record.Time40 = (decimal)value.sectionKwh[39];
-                record.Time41 = (decimal)value.sectionKwh[40];
-                record.Time42 = (decimal)value.sectionKwh[41];
-                record.Time43 = (decimal)value.sectionKwh[42];
-                record.Time44 = (decimal)value.sectionKwh[43];
-                record.Time45 = (decimal)value.sectionKwh[44];
-                record.Time46 = (decimal)value.sectionKwh[45];
-                record.Time47 = (decimal)value.sectionKwh[46];
-                record.Time48 = (decimal)value.sectionKwh[47];
-
-                record.ClientStartChargingDateTime = value.startChargingDateTime;//value.startChargingDateTime.ToLocalTime();
-                record.ClientEndChargingDateTime = value.chargeCompleteDateTime;//value.chargeCompleteDateTime.ToLocalTime();
-
-                if (value.startWith == StartWith.Member)
-                {
-                    
-                    var membertb = _memberChargingRepo.Query(c => c.SelfDefinedId == value.idTag).Select().FirstOrDefault();
-                    if (membertb != null)
-                    {
-                        //會員
-                        record.MemberId = membertb.MemberChargingId.ToString();               
-                    }
-                }
-                else if ((value.startWith == StartWith.CardNumber) || (value.startWith == StartWith.Unknown))
-                {
-                    record.CardNum = value.idTag;
-                }
-                #endregion Mapper
-                if (isNew)
-                    _chargingRecordRepo.Add(record);
-                else
-                    _chargingRecordRepo.Update(record);
-
-                //處理傳送給客戶api的紀錄
-                var report = crrRepo.Query(c => c.ChargingSerNo == record.ChargingSerNo).Select().FirstOrDefault();
-
-                if (report == null)
-                {
-                    report = new ChargingRecordReport();
-                    report.CreatedOn = DateTime.Now;
-                    report.StartChargingDateTime = record.StartChargingDateTime;
-                    report.ChargingSerNo = record.ChargingSerNo;
-                    report.CustomerId = machine.CustomerId;
-                    report.GunSerNo = record.GunSerNo;
-                    report.MachineCustomId = machine.CustomId;
-                    report.MachineId = machine.Id;
-                    report.MemberId = record.MemberId;
-                    report.CardNum = record.CardNum;
-                    report.StartWith = record.StartWith;
-                    report.Time1 = record.Time1;
-                    report.Time2 = record.Time2;
-                    report.Time3 = record.Time3;
-                    report.Time4 = record.Time4;
-                    report.Time5 = record.Time5;
-                    report.Time6 = record.Time6;
-                    report.Time7 = record.Time7;
-                    report.Time8 = record.Time8;
-                    report.Time9 = record.Time9;
-                    report.Time10 = record.Time10;
-                    report.Time11 = record.Time11;
-                    report.Time12 = record.Time12;
-                    report.Time13 = record.Time13;
-                    report.Time14 = record.Time14;
-                    report.Time15 = record.Time15;
-                    report.Time16 = record.Time16;
-                    report.Time17 = record.Time17;
-                    report.Time18 = record.Time18;
-                    report.Time19 = record.Time19;
-                    report.Time20 = record.Time20;
-                    report.Time21 = record.Time21;
-                    report.Time22 = record.Time22;
-                    report.Time23 = record.Time23;
-                    report.Time24 = record.Time24;
-                    report.Time25 = record.Time25;
-                    report.Time26 = record.Time26;
-                    report.Time27 = record.Time27;
-                    report.Time28 = record.Time28;
-                    report.Time29 = record.Time29;
-                    report.Time30 = record.Time30;
-                    report.Time31 = record.Time31;
-                    report.Time32 = record.Time32;
-                    report.Time33 = record.Time33;
-                    report.Time34 = record.Time34;
-                    report.Time35 = record.Time35;
-                    report.Time36 = record.Time36;
-                    report.Time37 = record.Time37;
-                    report.Time38 = record.Time38;
-                    report.Time39 = record.Time39;
-                    report.Time40 = record.Time40;
-                    report.Time41 = record.Time41;
-                    report.Time42 = record.Time42;
-                    report.Time43 = record.Time43;
-                    report.Time44 = record.Time44;
-                    report.Time45 = record.Time45;
-                    report.Time46 = record.Time46;
-                    report.Time47 = record.Time47;
-                    report.Time48 = record.Time48;
-                    report.ChargeStrategy = record.ChargingStrategy;
-                    report.ChargeStrategyParam = record.ChargingStrategyParam;
-                    report.SumOfMoney = record.SumOfMoney;
-                    report.FeeAmount = record.FeeAmount;
-                    report.ElectricBill = record.ElectricBill;
-                    report.StartChargingDateTime = record.ClientStartChargingDateTime;
-                    report.EndChargingDateTime = record.ClientEndChargingDateTime;
-                    report.CumulativeKwh = record.CumulativeKwh;
-                    var ts = report.EndChargingDateTime - report.StartChargingDateTime;
-                    report.TotalUsedTime = Convert.ToInt32(ts.Value.TotalSeconds);
-                    report.CarNum = record.CarNum;
-                    report.StartSoc = record.StartSoc;
-                    report.EndSoc = record.EndSoc;
-                    report.KwhBeforeCharging = record.KwhBeforeCharging;
-                    report.KwhAfterCharging = record.KwhAfterCharging;
-                    report.CardBalanceBeforeCharging = record.CardBalanceBeforeCharging;
-                    report.CardBalanceAfterCharging = record.CardBalanceAfterCharging;
-                    report.PayOffline = record.PayOffline;
-                    report.CardVIN = record.CardVIN;
-                    report.StartChargingType = record.StartChargingType;
-                    report.StopChargingReason = record.StopChargingReason;
-                    report.UpdatedOn = DateTime.Now;
-                    crrRepo.Add(report);
-                }
-                else
-                {
-                    report.MemberId = record.MemberId;
-                    report.CardNum = record.CardNum;
-                    report.StartWith = record.StartWith;
-                    report.Time1 = record.Time1;
-                    report.Time2 = record.Time2;
-                    report.Time3 = record.Time3;
-                    report.Time4 = record.Time4;
-                    report.Time5 = record.Time5;
-                    report.Time6 = record.Time6;
-                    report.Time7 = record.Time7;
-                    report.Time8 = record.Time8;
-                    report.Time9 = record.Time9;
-                    report.Time10 = record.Time10;
-                    report.Time11 = record.Time11;
-                    report.Time12 = record.Time12;
-                    report.Time13 = record.Time13;
-                    report.Time14 = record.Time14;
-                    report.Time15 = record.Time15;
-                    report.Time16 = record.Time16;
-                    report.Time17 = record.Time17;
-                    report.Time18 = record.Time18;
-                    report.Time19 = record.Time19;
-                    report.Time20 = record.Time20;
-                    report.Time21 = record.Time21;
-                    report.Time22 = record.Time22;
-                    report.Time23 = record.Time23;
-                    report.Time24 = record.Time24;
-                    report.Time25 = record.Time25;
-                    report.Time26 = record.Time26;
-                    report.Time27 = record.Time27;
-                    report.Time28 = record.Time28;
-                    report.Time29 = record.Time29;
-                    report.Time30 = record.Time30;
-                    report.Time31 = record.Time31;
-                    report.Time32 = record.Time32;
-                    report.Time33 = record.Time33;
-                    report.Time34 = record.Time34;
-                    report.Time35 = record.Time35;
-                    report.Time36 = record.Time36;
-                    report.Time37 = record.Time37;
-                    report.Time38 = record.Time38;
-                    report.Time39 = record.Time39;
-                    report.Time40 = record.Time40;
-                    report.Time41 = record.Time41;
-                    report.Time42 = record.Time42;
-                    report.Time43 = record.Time43;
-                    report.Time44 = record.Time44;
-                    report.Time45 = record.Time45;
-                    report.Time46 = record.Time46;
-                    report.Time47 = record.Time47;
-                    report.Time48 = record.Time48;
-                    report.CumulativeKwh = record.CumulativeKwh;
-                    report.EndChargingDateTime = record.ClientEndChargingDateTime;
-                    report.StartChargingDateTime = record.ClientStartChargingDateTime;
-                    report.FeeAmount = record.FeeAmount;
-                    report.ElectricBill = record.ElectricBill;
-                    report.SumOfMoney = record.SumOfMoney;
-                    var ts = report.EndChargingDateTime - report.StartChargingDateTime;
-                    report.TotalUsedTime = Convert.ToInt32(ts.Value.TotalSeconds);
-                    report.CarNum = record.CarNum;
-                    report.StartSoc = record.StartSoc;
-                    report.EndSoc = record.EndSoc;
-                    report.KwhBeforeCharging = record.KwhBeforeCharging;
-                    report.KwhAfterCharging = record.KwhAfterCharging;
-                    report.CardBalanceBeforeCharging = record.CardBalanceBeforeCharging;
-                    report.CardBalanceAfterCharging = record.CardBalanceAfterCharging;
-                    report.PayOffline = record.PayOffline;
-                    report.CardVIN = record.CardVIN;
-                    report.StartChargingType = record.StartChargingType;
-                    report.StopChargingReason = record.StopChargingReason;
-                    report.UpdatedOn = DateTime.Now;
-                }
-
-                WarnChargeIsAbnormal(record);
-                _uow.SaveChanges();
-                result.Success = true;
-                return result;
-            }
-            catch (Exception ex)
-            {
-                logger.Error(ex);
-                result.Exception = ex;
-                result.Success = false;
-                return result;
-            }
-
-        }
-
-        /// <summary>
-        /// 通知Email
-        /// </summary>
-        /// <param name="machineId">電樁Id</param>
-        /// <param name="subject">主旨</param>
-        /// <param name="body">內文</param>
-        /// <returns></returns>
-        private IResult NoticeEmail(string machineId, string subject, string body)
-        {
-            IResult result = new Result();
-            try
-            {
-                var machineRepo = _uow.Repository<Machine>();
-                var machine = machineRepo.Query(c => c.Id == machineId).Include(c => c.Customer).Select().FirstOrDefault();
-                var accountRepo = _uow.Repository<Account>();
-                var account = accountRepo.Query(c => c.CustomerId == machine.CustomerId).Select().FirstOrDefault();
-
-                if (!string.IsNullOrEmpty(account.Email))
-                {
-                    string[] emailgroup = account.Email.Split(',');
-                    string _subject = string.Format("[{0}] 客户: {1} 飞宏电桩号: {2} 客户电桩号: {3} ", subject, machine.Customer.CustomerDesc, machine.CustomId, machine.PartnerPoleId);
-                    foreach (var email in emailgroup)
-                    {
-                        DispatchMessageHelper.SendMail(email, _subject, body);
-                    }
-                }
-                result.Success = true;
-                return result;
-            }
-            catch (Exception ex)
-            {
-                logger.Error(ex);
-                result.Exception = ex;
-                result.Success = false;
-                return result;
-            }
-        }
-
-        /// <summary>
-        /// 警告充電量異常
-        /// </summary>
-        /// <returns></returns>
-        private IResult WarnChargeIsAbnormal(ChargingRecord record)
-        {
-            IResult result = new Result();
-            try
-            {
-                //設定條件-充電時間超過 1800秒 -總充電量小於 0.5kw  - StartWith != 2
-                if (record.CumulativeKwh < Convert.ToDecimal(0.5) && record.ClientEndChargingDateTime.HasValue
-                    && record.ClientStartChargingDateTime.HasValue && record.StartWith != 2)
-                {
-                    var totalSeconds = record.ClientEndChargingDateTime.Value.Subtract(record.ClientStartChargingDateTime.Value).TotalSeconds;
-                    if (totalSeconds > 1800d)
-                    {
-                        string body = string.Format("详细讯息: 充电序:{0} 充电开始时间:{1} 充电结束时间: {2} 充电秒数:{3} 充电度数:{4}",
-                            record.ChargingSerNo, record.ClientStartChargingDateTime.HasValue ? record.ClientStartChargingDateTime.Value.ToString("yyyy-MM-dd HH:mm:ss") : "None",
-                            record.ClientEndChargingDateTime.HasValue ? record.ClientEndChargingDateTime.Value.ToString("yyyy-MM-dd HH:mm:ss") : "None", totalSeconds, record.CumulativeKwh);
-                        NoticeEmail(record.MachineId, "充电量异常通知", body);
-                    }
-                }
-                result.Success = true;
-                return result;
-            }
-            catch (Exception ex)
-            {
-                logger.Error(ex);
-                result.Success = false;
-                result.Exception = ex;
-                result.Message = ex.Message;
-                return result;
-            }
-        }
-    }
-}

+ 0 - 445
OCPPServer/SubProtocol/OCPPLog.cs

@@ -1,445 +0,0 @@
-using NLog;
-using NLog.Fluent;
-using SuperSocket.SocketBase.Logging;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace OCPPServer.SubProtocol
-{
-    public class OCPPLog : ILog
-    {
-        private NLog.ILogger m_Log;
-
-        public OCPPLog(string name)
-        {
-            m_Log = NLog.LogManager.GetCurrentClassLogger();
-        }
-
-        /// <summary>
-        /// Gets a value indicating whether this instance is debug enabled.
-        /// </summary>
-        /// <value>
-        /// 	<c>true</c> if this instance is debug enabled; otherwise, <c>false</c>.
-        /// </value>
-        public bool IsDebugEnabled
-        {
-            get { return m_Log.IsDebugEnabled; }
-        }
-
-        /// <summary>
-        /// Gets a value indicating whether this instance is error enabled.
-        /// </summary>
-        /// <value>
-        /// 	<c>true</c> if this instance is error enabled; otherwise, <c>false</c>.
-        /// </value>
-        public bool IsErrorEnabled
-        {
-            get { return m_Log.IsErrorEnabled; }
-        }
-
-        /// <summary>
-        /// Gets a value indicating whether this instance is fatal enabled.
-        /// </summary>
-        /// <value>
-        /// 	<c>true</c> if this instance is fatal enabled; otherwise, <c>false</c>.
-        /// </value>
-        public bool IsFatalEnabled
-        {
-            get { return m_Log.IsFatalEnabled; }
-        }
-
-        /// <summary>
-        /// Gets a value indicating whether this instance is info enabled.
-        /// </summary>
-        /// <value>
-        /// 	<c>true</c> if this instance is info enabled; otherwise, <c>false</c>.
-        /// </value>
-        public bool IsInfoEnabled
-        {
-            get { return m_Log.IsInfoEnabled; }
-        }
-
-        /// <summary>
-        /// Gets a value indicating whether this instance is warn enabled.
-        /// </summary>
-        /// <value>
-        /// 	<c>true</c> if this instance is warn enabled; otherwise, <c>false</c>.
-        /// </value>
-        public bool IsWarnEnabled
-        {
-            get { return m_Log.IsWarnEnabled; }
-        }
-
-        /// <summary>
-        /// Logs the debug message.
-        /// </summary>
-        /// <param name="message">The message.</param>
-        public void Debug(object message)
-        {
-            m_Log.Debug(message);
-        }
-
-        /// <summary>
-        /// Logs the debug message.
-        /// </summary>
-        /// <param name="message">The message.</param>
-        /// <param name="exception">The exception.</param>
-        public void Debug(object message, Exception exception)
-        {
-            //m_Log.Debug((System.IFormatProvider)message, exception);
-            m_Log.Debug(exception, message.ToString());
-        }
-
-        /// <summary>
-        /// Logs the debug message.
-        /// </summary>
-        /// <param name="format">The format.</param>
-        /// <param name="arg0">The arg0.</param>
-        public void DebugFormat(string format, object arg0)
-        {
-            
-        }
-
-        /// <summary>
-        /// Logs the debug message.
-        /// </summary>
-        /// <param name="format">The format.</param>
-        /// <param name="args">The args.</param>
-        public void DebugFormat(string format, params object[] args)
-        {
-            
-        }
-
-        /// <summary>
-        /// Logs the debug message.
-        /// </summary>
-        /// <param name="provider">The provider.</param>
-        /// <param name="format">The format.</param>
-        /// <param name="args">The args.</param>
-        public void DebugFormat(IFormatProvider provider, string format, params object[] args)
-        {
-           
-        }
-
-        /// <summary>
-        /// Logs the debug message.
-        /// </summary>
-        /// <param name="format">The format.</param>
-        /// <param name="arg0">The arg0.</param>
-        /// <param name="arg1">The arg1.</param>
-        public void DebugFormat(string format, object arg0, object arg1)
-        {
-           
-        }
-
-        /// <summary>
-        /// Logs the debug message.
-        /// </summary>
-        /// <param name="format">The format.</param>
-        /// <param name="arg0">The arg0.</param>
-        /// <param name="arg1">The arg1.</param>
-        /// <param name="arg2">The arg2.</param>
-        public void DebugFormat(string format, object arg0, object arg1, object arg2)
-        {
-           
-        }
-
-        /// <summary>
-        /// Logs the error message.
-        /// </summary>
-        /// <param name="message">The message.</param>
-        public void Error(object message)
-        {
-            m_Log.Error(message);
-        }
-
-        /// <summary>
-        /// Logs the error message.
-        /// </summary>
-        /// <param name="message">The message.</param>
-        /// <param name="exception">The exception.</param>
-        public void Error(object message, Exception exception)
-        {
-            //m_Log.Error((System.IFormatProvider)message, exception);
-            m_Log.Error(exception, message.ToString());
-        }
-
-        /// <summary>
-        /// Logs the error message.
-        /// </summary>
-        /// <param name="format">The format.</param>
-        /// <param name="arg0">The arg0.</param>
-        public void ErrorFormat(string format, object arg0)
-        {
-            
-        }
-
-        /// <summary>
-        /// Logs the error message.
-        /// </summary>
-        /// <param name="format">The format.</param>
-        /// <param name="args">The args.</param>
-        public void ErrorFormat(string format, params object[] args)
-        {
-           
-        }
-
-        /// <summary>
-        /// Logs the error message.
-        /// </summary>
-        /// <param name="provider">The provider.</param>
-        /// <param name="format">The format.</param>
-        /// <param name="args">The args.</param>
-        public void ErrorFormat(IFormatProvider provider, string format, params object[] args)
-        {
-            
-        }
-
-        /// <summary>
-        /// Logs the error message.
-        /// </summary>
-        /// <param name="format">The format.</param>
-        /// <param name="arg0">The arg0.</param>
-        /// <param name="arg1">The arg1.</param>
-        public void ErrorFormat(string format, object arg0, object arg1)
-        {
-            
-        }
-
-        /// <summary>
-        /// Logs the error message.
-        /// </summary>
-        /// <param name="format">The format.</param>
-        /// <param name="arg0">The arg0.</param>
-        /// <param name="arg1">The arg1.</param>
-        /// <param name="arg2">The arg2.</param>
-        public void ErrorFormat(string format, object arg0, object arg1, object arg2)
-        {
-           
-        }
-
-        /// <summary>
-        /// Logs the fatal error message.
-        /// </summary>
-        /// <param name="message">The message.</param>
-        public void Fatal(object message)
-        {
-            m_Log.Fatal(message);
-        }
-
-        /// <summary>
-        /// Logs the fatal error message.
-        /// </summary>
-        /// <param name="message">The message.</param>
-        /// <param name="exception">The exception.</param>
-        public void Fatal(object message, Exception exception)
-        {
-            m_Log.Fatal((System.IFormatProvider)message, exception);
-        }
-
-        /// <summary>
-        /// Logs the fatal error message.
-        /// </summary>
-        /// <param name="format">The format.</param>
-        /// <param name="arg0">The arg0.</param>
-        public void FatalFormat(string format, object arg0)
-        {
-            
-        }
-
-        /// <summary>
-        /// Logs the fatal error message.
-        /// </summary>
-        /// <param name="format">The format.</param>
-        /// <param name="args">The args.</param>
-        public void FatalFormat(string format, params object[] args)
-        {
-           
-        }
-
-        /// <summary>
-        /// Logs the fatal error message.
-        /// </summary>
-        /// <param name="provider">The provider.</param>
-        /// <param name="format">The format.</param>
-        /// <param name="args">The args.</param>
-        public void FatalFormat(IFormatProvider provider, string format, params object[] args)
-        {
-          
-        }
-
-        /// <summary>
-        /// Logs the fatal error message.
-        /// </summary>
-        /// <param name="format">The format.</param>
-        /// <param name="arg0">The arg0.</param>
-        /// <param name="arg1">The arg1.</param>
-        public void FatalFormat(string format, object arg0, object arg1)
-        {
-           
-        }
-
-        /// <summary>
-        /// Logs the fatal error message.
-        /// </summary>
-        /// <param name="format">The format.</param>
-        /// <param name="arg0">The arg0.</param>
-        /// <param name="arg1">The arg1.</param>
-        /// <param name="arg2">The arg2.</param>
-        public void FatalFormat(string format, object arg0, object arg1, object arg2)
-        {
-           
-        }
-
-        /// <summary>
-        /// Logs the info message.
-        /// </summary>
-        /// <param name="message">The message.</param>
-        public void Info(object message)
-        {
-            m_Log.Info(message);
-        }
-
-        /// <summary>
-        /// Logs the info message.
-        /// </summary>
-        /// <param name="message">The message.</param>
-        /// <param name="exception">The exception.</param>
-        public void Info(object message, Exception exception)
-        {
-            //m_Log.Info((System.IFormatProvider)message, exception);
-            m_Log.Info(exception, message.ToString());
-        }
-
-        /// <summary>
-        /// Logs the info message.
-        /// </summary>
-        /// <param name="format">The format.</param>
-        /// <param name="arg0">The arg0.</param>
-        public void InfoFormat(string format, object arg0)
-        {
-           
-        }
-
-        /// <summary>
-        /// Logs the info message.
-        /// </summary>
-        /// <param name="format">The format.</param>
-        /// <param name="args">The args.</param>
-        public void InfoFormat(string format, params object[] args)
-        {
-            
-        }
-
-        /// <summary>
-        /// Logs the info message.
-        /// </summary>
-        /// <param name="provider">The provider.</param>
-        /// <param name="format">The format.</param>
-        /// <param name="args">The args.</param>
-        public void InfoFormat(IFormatProvider provider, string format, params object[] args)
-        {
-            
-        }
-
-        /// <summary>
-        /// Logs the info message.
-        /// </summary>
-        /// <param name="format">The format.</param>
-        /// <param name="arg0">The arg0.</param>
-        /// <param name="arg1">The arg1.</param>
-        public void InfoFormat(string format, object arg0, object arg1)
-        {
-            
-        }
-
-        /// <summary>
-        /// Logs the info message.
-        /// </summary>
-        /// <param name="format">The format.</param>
-        /// <param name="arg0">The arg0.</param>
-        /// <param name="arg1">The arg1.</param>
-        /// <param name="arg2">The arg2.</param>
-        public void InfoFormat(string format, object arg0, object arg1, object arg2)
-        {
-            
-        }
-
-        /// <summary>
-        /// Logs the warning message.
-        /// </summary>
-        /// <param name="message">The message.</param>
-        public void Warn(object message)
-        {
-            m_Log.Warn(message);
-        }
-
-        /// <summary>
-        /// Logs the warning message.
-        /// </summary>
-        /// <param name="message">The message.</param>
-        /// <param name="exception">The exception.</param>
-        public void Warn(object message, Exception exception)
-        {
-            //m_Log.Warn((System.IFormatProvider)message, exception);
-            m_Log.Warn(exception, message.ToString());
-        }
-
-        /// <summary>
-        /// Logs the warning message.
-        /// </summary>
-        /// <param name="format">The format.</param>
-        /// <param name="arg0">The arg0.</param>
-        public void WarnFormat(string format, object arg0)
-        {
-           
-        }
-
-        /// <summary>
-        /// Logs the warning message.
-        /// </summary>
-        /// <param name="format">The format.</param>
-        /// <param name="args">The args.</param>
-        public void WarnFormat(string format, params object[] args)
-        {
-           
-        }
-
-        /// <summary>
-        /// Logs the warning message.
-        /// </summary>
-        /// <param name="provider">The provider.</param>
-        /// <param name="format">The format.</param>
-        /// <param name="args">The args.</param>
-        public void WarnFormat(IFormatProvider provider, string format, params object[] args)
-        {
-           
-        }
-
-        /// <summary>
-        /// Logs the warning message.
-        /// </summary>
-        /// <param name="format">The format.</param>
-        /// <param name="arg0">The arg0.</param>
-        /// <param name="arg1">The arg1.</param>
-        public void WarnFormat(string format, object arg0, object arg1)
-        {
-           
-        }
-
-        /// <summary>
-        /// Logs the warning message.
-        /// </summary>
-        /// <param name="format">The format.</param>
-        /// <param name="arg0">The arg0.</param>
-        /// <param name="arg1">The arg1.</param>
-        /// <param name="arg2">The arg2.</param>
-        public void WarnFormat(string format, object arg0, object arg1, object arg2)
-        {
-            
-        }
-    }
-}

+ 0 - 108
OCPPServer/SubProtocol/OCPPLogFactory.cs

@@ -1,108 +0,0 @@
-
-using SuperSocket.SocketBase;
-using SuperSocket.SocketBase.Logging;
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace OCPPServer.SubProtocol
-{
-    /// <summary>
-    /// OCPP log factory
-    /// </summary>
-    public class OCPPLogFactory : LogFactoryBase 
-    {
-        public OCPPLogFactory()
-            : this("NLog.config")
-        {
-
-        }
-
-        public OCPPLogFactory(string log4netConfig)
-            : base(log4netConfig)
-        {
-            List<string> configlist = new List<string>();
-            configlist.Add(ConfigFile);
-            NLog.Config.XmlLoggingConfiguration.SetCandidateConfigFilePaths(configlist);
-        }
-
-
-        /// <summary>
-        /// Gets the config file file path.
-        /// </summary>
-        //protected string ConfigFile { get; private set; }
-
-        //public OCPPLogFactory()
-        //{
-        //    string configFile = "NLog.config";
-        //    var currentAppDomain = AppDomain.CurrentDomain;
-        //    var isolation = IsolationMode.None;
-
-        //    var isolationValue = currentAppDomain.GetData(typeof(IsolationMode).Name);
-
-        //    if (isolationValue != null)
-        //        isolation = (IsolationMode)isolationValue;
-
-        //    if (isolation == IsolationMode.None)
-        //    {
-        //        var filePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, configFile);
-
-        //        if (File.Exists(filePath))
-        //        {
-        //            ConfigFile = filePath;
-        //            return;
-        //        }
-
-        //        filePath = Path.Combine(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Config"), configFile);
-
-        //        if (File.Exists(filePath))
-        //        {
-        //            ConfigFile = filePath;
-        //            return;
-        //        }
-
-        //        ConfigFile = configFile;
-
-        //        List<string> configlist = new List<string>();
-        //        configlist.Add(ConfigFile);
-        //        NLog.Config.XmlLoggingConfiguration.SetCandidateConfigFilePaths(configlist);
-        //        return;
-        //    }
-        //}
-
-        /// <summary>
-        /// Gets the log by name.
-        /// </summary>
-        /// <param name="name">The name.</param>
-        /// <returns></returns>
-        /// <summary>
-        /// Gets the log by name.
-        /// </summary>
-        /// <param name="name">The name.</param>
-        /// <returns></returns>
-        /// 
-
-
-        //public override ILog GetLog(string name)
-        //{
-        //    NLog.ILogger logger = NLog.LogManager.GetCurrentClassLogger();
-        //    //return new ConsoleLog(name);
-
-        //    ILog log = logger as Log4NetLog;
-
-
-
-
-
-        //    return new Log4NetLog(LogManager.GetLogger(name)); ;
-        //}
-        public override SuperSocket.SocketBase.Logging.ILog GetLog(string name)
-        {
-           
-            return new OCPPLog(name);
-        }
-    }
-}

+ 0 - 35
OCPPServer/SubProtocol/OCPPSubCommandParser.cs

@@ -1,35 +0,0 @@
-using SuperSocket.SocketBase.Protocol;
-using SuperWebSocket.SubProtocol;
-
-namespace OCPPServer.SubProtocol
-{
-    public class OCPPSubCommandParser : IRequestInfoParser<SubRequestInfo>
-    {
-        #region ISubProtocolCommandParser Members
-
-        /// <summary>
-        /// Parses the request info.
-        /// </summary>
-        /// <param name="source">The source.</param>
-        /// <returns></returns>
-        public SubRequestInfo ParseRequestInfo(string source)
-        {
-            var cmd = source.Trim();
-            int pos = cmd.IndexOf(',');
-            string name;
-
-            if (pos > 0)
-            {
-                name = cmd.Substring(pos - 1,1);
-            }
-            else
-            {
-                name = "4";
-            }
-
-            return new SubRequestInfo(name, "", source);
-        }
-
-        #endregion ISubProtocolCommandParser Members
-    }
-}

+ 0 - 319
OCPPServer/SubProtocol/OCPPSubProtocol.cs

@@ -1,319 +0,0 @@
-using OCPPServer.Protocol;
-using SuperSocket.Common;
-using SuperSocket.SocketBase;
-using SuperSocket.SocketBase.Logging;
-using SuperSocket.SocketBase.Protocol;
-using SuperWebSocket;
-using SuperWebSocket.Config;
-using SuperWebSocket.SubProtocol;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Reflection;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace OCPPServer.SubProtocol
-{
-    public class OCPPSubProtocol : OCPPSubProtocol<ClientData>
-    {
-        /// <summary>
-        /// Initializes a new instance of the <see cref="BasicSubProtocol"/> class.
-        /// </summary>
-        public OCPPSubProtocol()
-            : base(Assembly.GetCallingAssembly())
-        {
-
-        }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="BasicSubProtocol"/> class.
-        /// </summary>
-        /// <param name="name">The sub protocol name.</param>
-        public OCPPSubProtocol(string name)
-            : base(name, Assembly.GetCallingAssembly())
-        {
-
-        }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="BasicSubProtocol"/> class.
-        /// </summary>
-        /// <param name="commandAssembly">The command assembly.</param>
-        public OCPPSubProtocol(Assembly commandAssembly)
-            : base(commandAssembly)
-        {
-
-        }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="OCPPSubProtocol"/> class.
-        /// </summary>
-        /// <param name="commandAssemblies">The command assemblies.</param>
-        public OCPPSubProtocol(IEnumerable<Assembly> commandAssemblies)
-            : base(commandAssemblies)
-        {
-
-        }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="OCPPSubProtocol"/> class.
-        /// </summary>
-        /// <param name="name">The sub protocol name.</param>
-        /// <param name="commandAssembly">The command assembly.</param>
-        public OCPPSubProtocol(string name, Assembly commandAssembly)
-            : base(name, commandAssembly)
-        {
-
-        }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="OCPPSubProtocol"/> class.
-        /// </summary>
-        /// <param name="name">The sub protocol name.</param>
-        /// <param name="commandAssemblies">The command assemblies.</param>
-        public OCPPSubProtocol(string name, IEnumerable<Assembly> commandAssemblies)
-            : base(name, commandAssemblies)
-        {
-
-        }
-
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="OCPPSubProtocol"/> class.
-        /// </summary>
-        /// <param name="name">The name.</param>
-        /// <param name="commandAssemblies">The command assemblies.</param>
-        /// <param name="requestInfoParser">The request info parser.</param>
-        public OCPPSubProtocol(string name, IEnumerable<Assembly> commandAssemblies, IRequestInfoParser<SubRequestInfo> requestInfoParser)
-            : base(name, commandAssemblies, requestInfoParser)
-        {
-
-        }
-
-        public ILog Getmlog()
-        {
-            return getlog();
-        }
-
-    }
-
-    public class OCPPSubProtocol<TWebSocketSession> : SubProtocolBase<TWebSocketSession>
-       where TWebSocketSession : WebSocketSession<TWebSocketSession>, new()
-    {
-        /// <summary>
-        /// Default basic sub protocol name
-        /// </summary>
-        public const string DefaultName = "ocpp1.6";//"OCPP1.6";
-
-        private List<Assembly> m_CommandAssemblies = new List<Assembly>();
-
-        private Dictionary<string, ISubCommand<TWebSocketSession>> m_CommandDict;
-
-        private ILog m_Logger;
-
-        private SubCommandFilterAttribute[] m_GlobalFilters;
-
-        internal static BasicSubProtocol<TWebSocketSession> CreateDefaultSubProtocol()
-        {
-            var commandAssembly = typeof(TWebSocketSession).Assembly;
-
-            if (commandAssembly == Assembly.GetExecutingAssembly())
-                commandAssembly = Assembly.GetEntryAssembly();
-
-            return new BasicSubProtocol<TWebSocketSession>(DefaultName, commandAssembly);
-        }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="BasicSubProtocol&lt;TWebSocketSession&gt;"/> class with the calling aseembly as command assembly
-        /// </summary>
-        public OCPPSubProtocol()
-            : this(DefaultName, Assembly.GetCallingAssembly())
-        {
-
-        }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="BasicSubProtocol&lt;TWebSocketSession&gt;"/> class with the calling aseembly as command assembly
-        /// </summary>
-        /// <param name="name">The sub protocol name.</param>
-        public OCPPSubProtocol(string name)
-            : this(name, Assembly.GetCallingAssembly())
-        {
-
-        }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="BasicSubProtocol&lt;TWebSocketSession&gt;"/> class with command assemblies
-        /// </summary>
-        /// <param name="commandAssemblies">The command assemblies.</param>
-        public OCPPSubProtocol(IEnumerable<Assembly> commandAssemblies)
-            : this(DefaultName, commandAssemblies, new OCPPSubCommandParser())
-        {
-
-        }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="BasicSubProtocol&lt;TWebSocketSession&gt;"/> class with single command assembly.
-        /// </summary>
-        /// <param name="commandAssembly">The command assembly.</param>
-        public OCPPSubProtocol(Assembly commandAssembly)
-            : this(DefaultName, new List<Assembly> { commandAssembly }, new OCPPSubCommandParser())
-        {
-
-        }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="BasicSubProtocol&lt;TWebSocketSession&gt;"/> class with name and single command assembly.
-        /// </summary>
-        /// <param name="name">The sub protocol name.</param>
-        /// <param name="commandAssembly">The command assembly.</param>
-        public OCPPSubProtocol(string name, Assembly commandAssembly)
-            : this(name, new List<Assembly> { commandAssembly }, new OCPPSubCommandParser())
-        {
-
-        }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="BasicSubProtocol&lt;TWebSocketSession&gt;"/> class with name and command assemblies.
-        /// </summary>
-        /// <param name="name">The sub protocol name.</param>
-        /// <param name="commandAssemblies">The command assemblies.</param>
-        public OCPPSubProtocol(string name, IEnumerable<Assembly> commandAssemblies)
-            : this(name, commandAssemblies, new OCPPSubCommandParser())
-        {
-
-        }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="BasicSubProtocol&lt;TWebSocketSession&gt;"/> class.
-        /// </summary>
-        /// <param name="name">The name.</param>
-        /// <param name="commandAssemblies">The command assemblies.</param>
-        /// <param name="requestInfoParser">The request info parser.</param>
-        public OCPPSubProtocol(string name, IEnumerable<Assembly> commandAssemblies, IRequestInfoParser<SubRequestInfo> requestInfoParser)
-            : base(name)
-        {
-            //The items in commandAssemblies may be null, so filter here
-            m_CommandAssemblies.AddRange(commandAssemblies.Where(a => a != null));
-            SubRequestParser = requestInfoParser;
-        }
-
-        #region ISubProtocol Members
-
-        private void DiscoverCommands()
-        {
-            var subCommands = new List<ISubCommand<TWebSocketSession>>();
-
-            foreach (var assembly in m_CommandAssemblies)
-            {
-                subCommands.AddRange(assembly.GetImplementedObjectsByInterface<ISubCommand<TWebSocketSession>>());
-            }
-
-#if DEBUG
-            var cmdbuilder = new StringBuilder();
-            cmdbuilder.AppendLine(string.Format("SubProtocol {0} found the commands below:", this.Name));
-
-            foreach (var c in subCommands)
-            {
-                cmdbuilder.AppendLine(c.Name);
-            }
-
-
-            m_Logger.Debug(cmdbuilder.ToString());
-#endif
-
-            m_CommandDict = new Dictionary<string, ISubCommand<TWebSocketSession>>(subCommands.Count, StringComparer.OrdinalIgnoreCase);
-
-            subCommands.ForEach(c =>
-            {
-                var fc = c as ISubCommandFilterLoader;
-
-                if (fc != null)
-                    fc.LoadSubCommandFilters(m_GlobalFilters);
-
-                m_CommandDict.Add(c.Name, c);
-            }
-                );
-        }
-
-
-        private bool ResolveCommmandAssembly(string definition)
-        {
-            try
-            {
-                var assemblies = AssemblyUtil.GetAssembliesFromString(definition);
-
-                if (assemblies.Any())
-                    m_CommandAssemblies.AddRange(assemblies);
-
-                return true;
-            }
-            catch (Exception e)
-            {
-                m_Logger.Error(e);
-                return false;
-            }
-        }
-
-        public ILog getlog()
-        {
-            return m_Logger;
-        }
-
-        /// <summary>
-        /// Tries get command from the sub protocol's command inventory.
-        /// </summary>
-        /// <param name="name">The name.</param>
-        /// <param name="command">The command.</param>
-        /// <returns></returns>
-        public override bool TryGetCommand(string name, out ISubCommand<TWebSocketSession> command)
-        {
-            return m_CommandDict.TryGetValue(name, out command);
-        }
-
-        public override bool Initialize(IAppServer appServer, SubProtocolConfig protocolConfig, ILog logger)
-        {
-            m_Logger = logger;
-
-            var config = appServer.Config;
-
-            m_GlobalFilters = appServer.GetType()
-                    .GetCustomAttributes(true)
-                    .OfType<SubCommandFilterAttribute>()
-                    .Where(a => string.IsNullOrEmpty(a.SubProtocol) || Name.Equals(a.SubProtocol, StringComparison.OrdinalIgnoreCase)).ToArray();
-
-            if (Name.Equals(DefaultName, StringComparison.OrdinalIgnoreCase))
-            {
-                var commandAssembly = config.Options.GetValue("commandAssembly");
-
-                if (!string.IsNullOrEmpty(commandAssembly))
-                {
-                    if (!ResolveCommmandAssembly(commandAssembly))
-                        return false;
-                }
-            }
-
-            if (protocolConfig != null && protocolConfig.Commands != null)
-            {
-                foreach (var commandConfig in protocolConfig.Commands)
-                {
-                    var assembly = commandConfig.Options.GetValue("assembly");
-
-                    if (!string.IsNullOrEmpty(assembly))
-                    {
-                        if (!ResolveCommmandAssembly(assembly))
-                            return false;
-                    }
-                }
-            }
-
-            //Always discover commands
-            DiscoverCommands();
-
-            return true;
-        }
-
-        #endregion
-    }
-}

+ 0 - 1862
OCPPServer/WSServer.cs

@@ -1,1862 +0,0 @@
-using Evcb.Domain.Model;
-using Evcb.Domain.mongo;
-using Evcb.Repository;
-using Evcb.Service;
-using Evcb.Service.Helpers;
-using Evcb.Service.Service;
-using MongoDB.Driver;
-using Newtonsoft.Json;
-using Newtonsoft.Json.Linq;
-using NLog;
-using OCPPPacket.Packet.Feature;
-using OCPPPacket.Packet.Messages;
-using OCPPPacket.Packet.Messages.Basic;
-using OCPPPacket.Packet.Messages.Core;
-using OCPPPacket.Packet.Status;
-using OCPPServer.Handler;
-using OCPPServer.Protocol;
-using OCPPServer.SubProtocol;
-using Packet;
-using Packet.Cmd;
-using SuperSocket.SocketBase;
-using SuperSocket.SocketBase.Config;
-using System;
-using System.Collections.Generic;
-using System.Configuration;
-using System.Data.Entity;
-using System.Data.Entity.Validation;
-using System.Linq;
-using System.Net;
-using System.Net.Sockets;
-using System.Text;
-using System.Threading;
-using System.Threading.Tasks;
-using System.Xml.Linq;
-
-namespace OCPPServer
-{
-    public class WSServer
-    {
-        private readonly Object _lockClientDic = new object();
-        private readonly Object _lockConfirmPacketList = new object();
-        private CancellationTokenSource _cts = new CancellationTokenSource();
-        private CancellationToken _ct;
-        private IMongoService mongoService = new MongoService();
-        static private ILogger logger = NLog.LogManager.GetCurrentClassLogger();
-        private List<string> _cmd202lst = new List<string>();
-        private List<int> _needConfirmCmdList;
-        public Dictionary<string, ClientData> ClientDic { get; set; }
-        public string Listening { get; set; }
-
-        public string ApiUrl { get; set; }
-        public List<NeedConfirmPacket> NeedConfirmPacketList { get; set; }
-
-        /// <summary>
-        /// 上次校時時間
-        /// </summary>
-        private DateTime sendTiming { get; set; }
-
-        /// <summary>
-        /// 檢查軟韌體時間
-        /// </summary>
-        private DateTime checkUpdateDt { get; set; }
-
-        /// <summary>
-        /// 可允許連線Clinet數
-        /// </summary>
-        public int connectNum { get; set; }
-
-        /// <summary>
-        /// 是否限制連線Clinet數
-        /// </summary>
-        public bool beConnectLimit { get; set; }
-
-        /// <summary>
-        /// 是否紀錄與充電樁互傳命令 在 MachineConnectionLog
-        /// </summary>
-        private bool ENABLELOG_MACHINECMD = false;
-
-        public WSServer()
-        {
-            using (var db = new PhihongDbContext())
-            {
-                _ct = _cts.Token;
-                ClientDic = new Dictionary<string, ClientData>();
-                NeedConfirmPacketList = new List<NeedConfirmPacket>();
-
-                //需要確認回傳的指令
-                _needConfirmCmdList = db.NeedConfirmCmd.Select(c => c.Id).ToList();
-
-                //載入相關config
-                ENABLELOG_MACHINECMD = ConfigurationManager.AppSettings.Get("EnableMachineConnectionLog").Equals("0") ? false : true;
-                ApiUrl = ConfigurationManager.AppSettings.Get("ApiUrl");
-                string serverIp = ConfigurationManager.AppSettings.Get("ServerIp");
-                string serverPort = ConfigurationManager.AppSettings.Get("ServerPort");
-                
-                string wssserverPort = ConfigurationManager.AppSettings.Get("WSSServerPort");
-                string serverSecurity = ConfigurationManager.AppSettings.Get("ServerSecurity");
-                int maxRequestLength = int.Parse(ConfigurationManager.AppSettings.Get("MaxRequestLength"));
-                var config = ConfigurationManager.GetSection("superSocket") as IConfigurationSource;
-                ICertificateConfig Certificate = config.Servers.ElementAt(0).Certificate;
-
-                sendTiming = DateTime.Now;
-                checkUpdateDt = DateTime.Now;
-
-                //載入OCPP Protocol
-                var appServer = new OCPPWSServer(new OCPPSubProtocol());
-
-                List<IListenerConfig> llistener = new List<IListenerConfig>();
-
-                llistener.Add(new ListenerConfig { Ip = serverIp, Port = Convert.ToInt32(wssserverPort), Backlog = 100, Security = serverSecurity });
-                llistener.Add(new ListenerConfig { Ip = serverIp, Port = Convert.ToInt32(serverPort), Backlog = 100, Security = "None" });
-
-                IEnumerable<IListenerConfig> listeners = llistener;
-
-               //設定server config
-               var serverConfig = new ServerConfig
-                {
-                    //Port = Convert.ToInt32(serverPort),
-                    //Ip = serverIp,
-                    MaxRequestLength = maxRequestLength,
-                    //Security = serverSecurity,
-                    Certificate = Certificate,
-                   Listeners = listeners
-
-               };
-
-                //Setup with listening port
-                if (!appServer.Setup(serverConfig, logFactory: new OCPPLogFactory()))
-                {
-                    Console.WriteLine("Failed to setup!");
-                    Console.ReadKey();
-                    return;
-                }
-
-                appServer.NewSessionConnected += AppServer_NewSessionConnected;
-                appServer.SessionClosed += AppServer_SessionClosed;
-                Console.WriteLine();
-
-                string mac = ConfigurationManager.AppSettings.Get("mac");
-                string limit = ConfigurationManager.AppSettings.Get("limit");
-                string signature = ConfigurationManager.AppSettings.Get("Signature");
-                appServer.beConnectLimit = true;
-                Console.Write("<=============================================================== \n");
-                Console.Write("Server Mac: {0}\n", mac);
-                Console.Write("Connection Limit: {0}\n", limit);
-                Console.Write("Signature: {0}\n", signature);
-                var result = ConnectionLimitHepler.ConnectionLimitValidation(ConnectionLimitHepler.Key, signature, mac, limit);
-                if (result.IsValid == true)
-                {
-                    Console.Write("Verification Signature Result : correct\n");
-                    if (limit.Contains("∞") == false)
-                    {
-                        appServer.connectNum = Int32.Parse(limit);
-                        Console.Write("Real Connection Limit: {0}\n", appServer.connectNum);
-                    }
-                    else
-                    {
-                        appServer.connectNum = 0;
-                        appServer.beConnectLimit = false;
-                        Console.Write("Real Connection Limit: {0}\n", "∞");
-                    }
-                }
-                else
-                {
-                    Console.Write("Verification Signature Result : incorrect\n");
-                    appServer.connectNum = 10;
-                    Console.Write("Real Connection Limit: {0}\n", appServer.connectNum);
-                }
-                Console.Write("===============================================================> \n");
-
-                //Try to start the appServer
-                if (!appServer.Start())
-                {
-                    Console.WriteLine("Failed to start!");
-                    Console.ReadKey();
-                    return;
-                }
-            }
-        }
-
-        public void Start()
-        {
-            Task taskServerCommand = new Task(ServerCommandThread, _ct);
-            taskServerCommand.Start();
-
-            while (true)
-            {
-                var input = Console.ReadLine();
-
-                switch (input.ToLower())
-                {
-                    case "stop":
-                        //ListenerSocket.Shutdown(SocketShutdown.Both);
-                        //ListenerSocket.Close();
-                        Stop();
-                        logger.Info("server stop");
-                        Task.WaitAny(taskServerCommand);
-                        break;
-
-                    case "gc":
-                        logger.Info("Command GC");
-                        GC.Collect();
-                        break;
-
-                    case "lc":
-                        logger.Info("Command List Clients");
-                        var list = ClientDic.Select(c => c.Value).ToList();
-                        int i = 1;
-                        foreach (var c in list)
-                        {
-                            logger.Info(i + ":" + c.MachineCustomId);
-                            i++;
-                        }
-                        break;
-
-                    case "lcn":
-                        logger.Info("Command List Customer Name");
-                        var lcn = ClientDic.Select(c => c.Value.CustomerName).Distinct().ToList();
-                        int iLcn = 1;
-                        foreach (var c in lcn)
-                        {
-                            logger.Info(iLcn + ":" + c + ":" + ClientDic.Where(z => z.Value.CustomerName == c).Count().ToString());
-                            iLcn++;
-                        }
-                        break;
-
-                    case "help":
-                        logger.Info("Command help!!");
-                        logger.Info("lcn : List Customer Name");
-                        logger.Info("gc : GC Collect");
-                        logger.Info("lc : List Clients");
-                        logger.Info("cls : clear console");
-                        logger.Info("silent : silent");
-                        logger.Info("show : show log");
-                        logger.Info("rcl : show Real Connection Limit");
-                        break;
-
-                    case "cls":
-                        logger.Info("Command clear");
-                        Console.Clear();
-                        break;
-
-                    case "silent":
-                        logger.Info("Command silent");
-                        var xe = XElement.Load("NLog.config");
-                        var xns = xe.GetDefaultNamespace();
-                        var minlevelattr = xe.Descendants(xns + "rules").Elements(xns + "logger")
-                            .Where(c => c.Attribute("writeTo").Value.Equals("console")).Attributes("minlevel").FirstOrDefault();
-                        if (minlevelattr != null)
-                        {
-                            minlevelattr.Value = "info";
-                        }
-                        xe.Save("NLog.config");
-                        break;
-
-                    case "show":
-                        logger.Info("Command show");
-                        var xe1 = XElement.Load("NLog.config");
-                        var xns1 = xe1.GetDefaultNamespace();
-                        var minlevelattr1 = xe1.Descendants(xns1 + "rules").Elements(xns1 + "logger")
-                            .Where(c => c.Attribute("writeTo").Value.Equals("console")).Attributes("minlevel").FirstOrDefault();
-                        if (minlevelattr1 != null)
-                        {
-                            minlevelattr1.Value = "trace";
-                        }
-                        xe1.Save("NLog.config");
-                        break;
-
-                    case "rcl":
-                        logger.Info("Command rcln");
-                        if (beConnectLimit == true)
-                        {
-                            logger.Info("Real Connection Limit:" + connectNum);
-                        }
-                        else
-                        {
-                            logger.Info("Real Connection Limit:" + "∞");
-                        }
-
-                        break;
-
-                    default:
-                        break;
-                }
-            }
-        }
-
-        /// <summary>
-        /// 處理電樁送的OCPP 訊息
-        /// </summary>
-        public void ReceivedMessage(ClientData ctdata, String msg)
-        {
-            using (var db = new PhihongDbContext())
-            {
-                IUnitOfWork uow = new UnitOfWork(db);
-                IMachineService machineSrv = new MachineService(uow);
-                ISocketCommandService socketCommandSrv = new SocketCommandService(uow);
-                ICustomerService _customerService = new CustomerService();
-                OCPPMessageHandler ocppMsgHandler = new OCPPMessageHandler();
-                try
-                {
-                    //檢查是否有Connection 沒有加入ClientDic
-                    if (ctdata.IsCheckIn)
-                    {
-                        lock (_lockClientDic)
-                        {
-                            if (!ClientDic.ContainsKey(ctdata.MachineCustomId))
-                            {
-                                ClientDic.Add(ctdata.MachineCustomId, ctdata);
-                                logger.Trace("Rejoin MachineCustomId: {0}", ctdata.MachineCustomId);
-                            }
-                        }
-                    }
-
-                    BaseMessage message = ocppMsgHandler.Parse(msg);
-                    CheckConfirmPacket(ctdata, message);
-                    if (message is CallResultMessage)
-                    {
-                        #region 處理CallResultMessage
-
-                        //更新充電樁的心跳包接收時間
-                        socketCommandSrv.UpdateHeartbeat(ctdata.MachineCustomId);
-                        CallResultMessage call = (CallResultMessage)message;
-                        string callResultAction = string.Empty;
-                        var result = ocppMsgHandler.OnCallResult(call.id, call.payload, ref ctdata.queue, out callResultAction);
-
-                        if (result.Success == true)
-                        {
-                            if (ENABLELOG_MACHINECMD)
-                            {
-                                MachineConnectionLog log = new MachineConnectionLog();
-                                log.MachineCustomId = ctdata.MachineCustomId;
-                                log.MachineId = ctdata.MachineId;
-                                log.IpPort = ctdata.LocalEndPoint.ToString();
-                                log.IsIllegal = false;
-
-                                if (msg.Length >= 2000)
-                                    log.Data = msg.Substring(0, 1999);
-                                else
-                                    log.Data = msg;
-
-                                log.IsDataOut = false;
-                                log.CmdNum = 0;
-                                log.CreatedOn = DateTime.Now;
-                                log.Msg = callResultAction;
-                                var ep = ((IPEndPoint)ctdata.RemoteEndPoint);
-                                log.ClientIpPort = ep.Address.ToString() + ":" + ep.Port.ToString();
-
-                                SaveMachineConnectionLog(log);
-
-                                if (msg.Length >= 2000) //  GetConfiguration.conf封包
-                                {
-                                    MachineConnectionLog log1 = new MachineConnectionLog();
-                                    log1.MachineCustomId = ctdata.MachineCustomId;
-                                    log1.MachineId = ctdata.MachineId;
-                                    log1.IpPort = ctdata.LocalEndPoint.ToString();
-                                    log1.IsIllegal = false;
-                                    log1.IsDataOut = false;
-                                    log1.CmdNum = 0;
-                                    log1.Data = "config :" + msg.Substring(2000, msg.Length - 2000);
-                                    log1.CreatedOn = DateTime.Now;
-                                    log1.Msg = callResultAction;
-                                    var ep1 = ((IPEndPoint)ctdata.RemoteEndPoint);
-                                    log1.ClientIpPort = ep1.Address.ToString() + ":" + ep1.Port.ToString();
-
-                                    SaveMachineConnectionLog(log1);
-                                }
-
-                              
-                            }
-
-                            if (!ctdata.IsCheckIn && (result.Payload is GetConfigurationConfirmation))
-                            {
-                                IRequest req = MakeRequestHandler.MakeChangeConfigurationRequest("HeartBeatInterval", "60");
-                                string uuid = ctdata.queue.store(req);
-                                Send(ctdata, ocppMsgHandler.GenerateCall(uuid, Actions.ChangeConfiguration.ToString(), req), "ChangeConfiguration Request");
-                            }
-
-                            //將OCPP CallResult Message的Payload所夾帶參數資訊進行處理
-                            var handleConfirmationResult = ocppMsgHandler.HandleConfirmation(call.id, (IConfirmation)result.Payload, callResultAction, db, ref ctdata);
-                            if (handleConfirmationResult.Success == true)
-                            {
-                                //do nothing
-                            }
-                            else
-                            {
-                                if (ENABLELOG_MACHINECMD)
-                                {
-                                    //紀錄error type message
-                                    MachineConnectionLog log1 = new MachineConnectionLog();
-                                    log1.MachineCustomId = ctdata.MachineCustomId;
-                                    log1.MachineId = ctdata.MachineId;
-                                    log1.IpPort = ctdata.LocalEndPoint.ToString();
-                                    log1.IsIllegal = true;
-                                    log1.IsDataOut = false;
-                                    log1.CmdNum = 0;
-                                    log1.Data = msg;
-                                    log1.CreatedOn = DateTime.Now;
-                                    log1.Msg = handleConfirmationResult.Message;
-                                    var ep1 = ((IPEndPoint)ctdata.RemoteEndPoint);
-                                    log1.ClientIpPort = ep1.Address.ToString() + ":" + ep1.Port.ToString();
-
-                                    SaveMachineConnectionLog(log1);
-                                }
-                                //送出錯誤訊息給電樁
-                                //Send(ctdata, handleConfirmationResult.Message);
-                            }
-                        }
-                        else
-                        {
-                            #region error type message 處理
-
-                            if(result.Message.Equals("none") == true)
-                            {
-                                //重複送相同Message, 不處理
-                            }
-                            else
-                            {
-                                if (ENABLELOG_MACHINECMD)
-                                {
-                                    //紀錄error type message
-                                    MachineConnectionLog log = new MachineConnectionLog();
-                                    log.MachineCustomId = ctdata.MachineCustomId;
-                                    log.MachineId = ctdata.MachineId;
-                                    log.IpPort = ctdata.LocalEndPoint.ToString();
-                                    log.IsIllegal = true;
-                                    log.IsDataOut = false;
-                                    log.CmdNum = 0;
-                                    log.Data = msg;
-                                    log.CreatedOn = DateTime.Now;
-
-                                    //紀錄exception, 送出錯誤訊息給電樁
-                                    if (result.Exception != null)
-                                    {
-                                        logger.Error(result.Exception, "OnCallResult error");
-                                        log.Msg = result.Exception.ToString();
-                                    }
-                                    else
-                                    {
-                                        ////送出錯誤訊息給電樁
-                                        //Send(ctdata, result.Message, "Error Message");
-                                        log.Msg = result.Message;
-                                    }
-
-                                    var ep = ((IPEndPoint)ctdata.RemoteEndPoint);
-                                    log.ClientIpPort = ep.Address.ToString() + ":" + ep.Port.ToString();
-
-                                    SaveMachineConnectionLog(log);
-                                }
-                                Send(ctdata, result.Message, "Error Message");
-
-                            }
-
-                          
-                            #endregion error type message 處理
-                        }
-
-                        #endregion 處理CallResultMessage
-                    }
-                    else if (message is CallErrorMessage)
-                    {
-                        #region 處理CallErrorMessage
-
-                        //failedFlag = true;
-                        //更新充電樁的心跳包接收時間
-                        socketCommandSrv.UpdateHeartbeat(ctdata.MachineCustomId);
-                        CallErrorMessage call = (CallErrorMessage)message;
-                        var result = ocppMsgHandler.OnError(call.id, call.ErrorCode, call.ErrorDescription, call.payload);
-                        if (result.Success == true)
-                        {
-                            if (ENABLELOG_MACHINECMD)
-                            {
-                                MachineConnectionLog log = new MachineConnectionLog();
-                                log.MachineCustomId = ctdata.MachineCustomId;
-                                log.MachineId = ctdata.MachineId;
-                                log.IpPort = ctdata.LocalEndPoint.ToString();
-                                log.IsIllegal = false;
-                                log.Data = msg;//call.id.ToString() + "," + JsonConvert.SerializeObject(result.Payload); ;
-                                log.IsDataOut = false;
-                                log.CmdNum = 0;
-                                log.CreatedOn = DateTime.Now;
-                                log.Msg = call.ErrorCode;
-                                var ep = ((IPEndPoint)ctdata.RemoteEndPoint);
-                                log.ClientIpPort = ep.Address.ToString() + ":" + ep.Port.ToString();
-
-                                SaveMachineConnectionLog(log);
-                            }
-                            //重送上次未成功的訊息 或 移除Client
-                        }
-
-                        var handleErrorResult = ocppMsgHandler.HandleError(call.id, call.ErrorCode, call.ErrorDescription, call.payload);
-
-                        #endregion 處理CallErrorMessage
-                    }
-                    else if (message is CallMessage)
-                    {
-                        #region 處理CallMessage
-
-                        //處理OCPP Call Message
-                        CallMessage call = (CallMessage)message;
-                        var result = ocppMsgHandler.OnCall(call.id, call.action, call.payload);
-                        bool BootNotificationPending = false;
-
-                        if (result.Success == true)
-                        {
-                            //如果沒有 check in,設定為illegal的封包資料,紀錄之後,此筆放棄,處理下一個
-                            if (!ctdata.IsCheckIn)
-                            {
-                                if (ENABLELOG_MACHINECMD)
-                                {
-                                    MachineConnectionLog log = new MachineConnectionLog();
-                                    log.MachineCustomId = ctdata.MachineCustomId;
-                                    log.MachineId = ctdata.MachineId;
-                                    log.IpPort = ctdata.LocalEndPoint.ToString();
-                                    log.IsIllegal = true;
-                                    log.Data = msg;
-                                    log.IsDataOut = false;
-                                    log.CmdNum = 0;
-                                    log.CreatedOn = DateTime.Now;
-                                    log.Msg = call.action + " Request";
-                                    var ep = ((IPEndPoint)ctdata.RemoteEndPoint);
-                                    log.ClientIpPort = ep.Address.ToString() + ":" + ep.Port.ToString();
-
-                                    SaveMachineConnectionLog(log);
-                                }
-
-                                //如果不是 BootNotificationRequest 就不處理,處理下一個指令
-                                if (!(result.Payload is BootNotificationRequest))
-                                {
-                                    return;
-                                }
-                                else
-                                {
-                                    if (ENABLELOG_MACHINECMD)
-                                    {
-                                        //紀錄收到BootNotificationRequest(目前還沒有CheckIn)
-                                        MachineConnectionLog log2 = new MachineConnectionLog();
-                                        log2.MachineCustomId = ctdata.MachineCustomId;
-                                        log2.MachineId = ctdata.MachineId;
-                                        log2.IpPort = ctdata.LocalEndPoint.ToString();
-                                        log2.IsIllegal = false;
-                                        log2.Data = msg;//call.id.ToString() + "," + call.action.ToString() + "," + JsonConvert.SerializeObject(result.Payload);
-                                        log2.IsDataOut = false;
-                                        log2.CmdNum = 0;
-                                        log2.CreatedOn = DateTime.Now;
-                                        log2.Msg = "first signin";
-                                        var ep2 = ((IPEndPoint)ctdata.RemoteEndPoint);
-                                        log2.ClientIpPort = ep2.Address.ToString() + ":" + ep2.Port.ToString();
-
-                                        SaveMachineConnectionLog(log2);
-                                    }
-                                    //初始化client的CmdHelper instance
-                                    var machine = machineSrv.GetByCustomId(ctdata.MachineCustomIdTemp);
-                                    var customer = _customerService.GetByCustomerId(machine.CustomerId);
-                                    ctdata.CmdHelper = new CmdHelper(customer.MachineCode1, customer.MachineCode2);
-                                }
-                            }
-                            else
-                            {
-                                //更新充電樁的心跳包接收時間
-                                socketCommandSrv.UpdateHeartbeat(ctdata.MachineCustomId);
-
-                                //當 Heartbeat 與 上一個 Heartbeat相差值小於2秒,送出ChangeConfiguration.req(HeartbeatInterval: 15) 給電樁
-                                if ((IRequest)result.Payload is HeartbeatRequest)
-                                {
-
-                                    //var HeartbeatNow = db.MachineConnectionLog.Where(c => c.MachineCustomId == ctdata.MachineCustomId).OrderByDescending(c => c.Id).AsNoTracking().FirstOrDefault();
-                                    //if (HeartbeatNow.Data.Contains("currentTime") == true)
-                                    if (ctdata.heartbeatDate != null)
-                                    {
-                                        DateTime currenttime = DateTime.Now;
-                                        //DateTime basetime = HeartbeatNow.CreatedOn;
-                                        DateTime basetime = (DateTime)ctdata.heartbeatDate;
-                                        TimeSpan ts = currenttime.Subtract(basetime).Duration();
-                                        double seconddiff = ts.TotalSeconds;
-                                        if ((seconddiff <= 2) && (ctdata.IsSendHeartbeatChangeConfiguration == false)) // Heartbeat 與上一個 Heartbeat時間小於 2秒
-                                        {
-                                            //當 Heartbeat 與 上一個 Heartbeat相差值小於2秒,判斷是否送出ChangeConfiguration.req(HeartbeatInterval: 15) 給電樁
-                                            ctdata.IsSendHeartbeatChangeConfiguration = true;
-
-                                            var machine = machineSrv.GetByCustomId(ctdata.MachineCustomId);
-                                            //重發校時
-                                            //設定心跳時間和心跳的timeout次數
-                                            logger.Trace("set 心跳時間和心跳的timeout次數");
-                                            Cmd1001 cmd1001temp = ctdata.CmdHelper.Create(1001) as Cmd1001;
-                                            cmd1001temp.Type = 1;
-                                            cmd1001temp.ParamIndex = 21;
-                                            cmd1001temp.ParamAmt = 2;
-                                            cmd1001temp.ParamByteLength = (ushort)((ushort)cmd1001temp.ParamAmt * 4);
-
-                                            uint p21 = (uint)machine.HeartbeatInterval;
-                                            cmd1001temp.ParamByteList.AddRange(CmdUtil.ToByteArray(p21).ToList());
-                                            uint p22 = (uint)machine.HeartbeatTimeoutTimes;
-                                            cmd1001temp.ParamByteList.AddRange(CmdUtil.ToByteArray(p22).ToList());
-
-                                            cmd1001temp.Pack();
-                                            ServerCommand sc = new ServerCommand();
-                                            sc.OutCmdNum = cmd1001temp.Cmd;
-                                            sc.CreatedOn = DateTime.Now;
-                                            sc.MachineId = ctdata.MachineId;
-                                            sc.MachineCustomId = ctdata.MachineCustomId;
-                                            sc.OutTransData = cmd1001temp.byteList.ToArray();
-                                            db.ServerCommand.Add(sc);
-                                            db.SaveChanges();
-                                        }
-                                    }
-                                }
-                                if (ENABLELOG_MACHINECMD)
-                                {
-                                    //紀錄電樁的連線資訊
-                                    MachineConnectionLog log = new MachineConnectionLog();
-                                    log.MachineCustomId = ctdata.MachineCustomId;
-                                    log.MachineId = ctdata.MachineId;
-                                    log.IpPort = ctdata.LocalEndPoint.ToString();
-                                    log.IsIllegal = false;
-                                    log.IsDataOut = false;
-                                    log.CmdNum = 0;
-                                    if (msg.Length > 2000)
-                                        log.Data = msg.Substring(0, 1999);
-                                    else
-                                        log.Data = msg;//call.id.ToString() + "," +call.action.ToString() + "," + JsonConvert.SerializeObject(result.Payload);
-                                    log.CreatedOn = DateTime.Now;
-                                    if (call.action.Contains("DataTransfer"))
-                                    {
-                                        log.Msg = call.action + " Request(" + ((DataTransferRequest)(result.Payload)).messageId + ")";
-                                    }
-                                    else
-                                        log.Msg = call.action + " Request";
-
-                                    var ep = ((IPEndPoint)ctdata.RemoteEndPoint);
-                                    log.ClientIpPort = ep.Address.ToString() + ":" + ep.Port.ToString();
-
-                                    SaveMachineConnectionLog(log);
-
-                                    if (msg.Length >= 2000) // BMS封包
-                                    {
-                                        MachineConnectionLog log1 = new MachineConnectionLog();
-                                        log1.MachineCustomId = ctdata.MachineCustomId;
-                                        log1.MachineId = ctdata.MachineId;
-                                        log1.IpPort = ctdata.LocalEndPoint.ToString();
-                                        log1.IsIllegal = false;
-                                        log1.IsDataOut = false;
-                                        log1.CmdNum = 0;
-                                        log1.Data = "ChargingGunBMS :" + msg.Substring(2000, msg.Length - 2000);
-                                        log1.CreatedOn = DateTime.Now;
-                                        if (call.action.Contains("DataTransfer"))
-                                        {
-                                            log.Msg = call.action + " Request(" + ((DataTransferRequest)(result.Payload)).messageId + ")";
-                                        }
-                                        else
-                                            log.Msg = call.action + " Request";
-                                        var ep1 = ((IPEndPoint)ctdata.RemoteEndPoint);
-                                        log1.ClientIpPort = ep1.Address.ToString() + ":" + ep1.Port.ToString();
-
-                                        SaveMachineConnectionLog(log1);
-                                    }
-                              
-                                }
-
-                               
-                            }
-
-                            //將OCPP Call Message的Payload所夾帶參數資訊進行處理
-                            var handleRequestResult = ocppMsgHandler.HandleRequest((IRequest)result.Payload, call.id, db, ref ctdata);
-
-                            if (handleRequestResult.Success == true)
-                            {
-                                //針對即將回傳給電樁的Confirm Message進行處理
-                                IConfirmation conf = (IConfirmation)handleRequestResult.Payload;
-
-                                if (!ctdata.IsCheckIn && (conf is BootNotificationConfirmation))
-                                {
-                                    //後台接受電樁發送的BootNotification Request
-                                    if (((BootNotificationConfirmation)conf).status == RegistrationStatus.Accepted)
-                                    {
-                                        //不存在機器,要紀錄起來
-                                        var machine = machineSrv.GetByCustomId(ctdata.MachineCustomIdTemp);
-
-                                        ctdata.CustomerId = machine.CustomerId;
-                                        ctdata.CustomerName = machine.Customer.Name;
-                                        ctdata.MachineId = machine.Id;
-                                        string temp = String.Empty;
-                                        temp = ctdata.MachineCustomId;
-                                        ctdata.MachineCustomId = ctdata.MachineCustomIdTemp;
-                                        ctdata.MachineCustomIdTemp = temp;
-                                        OCPP_ClientDicAdded(ctdata);
-
-                                        //確認是否已經有新增槍數
-                                        machineSrv.CheckGunsByMachineCustomId(ctdata.MachineCustomId);
-                                        uow.SaveChanges();
-
-                                        //設定心跳時間和心跳的timeout次數
-                                        logger.Trace("set 心跳時間和心跳的timeout次數");
-                                        Cmd1001 cmd1001 = ctdata.CmdHelper.Create(1001) as Cmd1001;
-                                        cmd1001.Type = 1;
-                                        cmd1001.ParamIndex = 21;
-                                        cmd1001.ParamAmt = 2;
-                                        cmd1001.ParamByteLength = (ushort)((ushort)cmd1001.ParamAmt * 4);
-
-                                        uint p21 = (uint)machine.HeartbeatInterval;
-                                        cmd1001.ParamByteList.AddRange(CmdUtil.ToByteArray(p21).ToList());
-                                        uint p22 = (uint)machine.HeartbeatTimeoutTimes;
-                                        cmd1001.ParamByteList.AddRange(CmdUtil.ToByteArray(p22).ToList());
-
-                                        cmd1001.Pack();
-                                        ServerCommand sc = new ServerCommand();
-                                        sc.OutCmdNum = cmd1001.Cmd;
-                                        sc.CreatedOn = DateTime.Now;
-                                        sc.MachineId = ctdata.MachineId;
-                                        sc.MachineCustomId = ctdata.MachineCustomId;
-                                        sc.OutTransData = cmd1001.byteList.ToArray();
-                                        db.ServerCommand.Add(sc);
-                                        db.SaveChanges();
-
-                                        //設定樁的夥伴代碼
-                                        Cmd1003 cmd1003 = ctdata.CmdHelper.Create(1003) as Cmd1003;
-                                        cmd1003.ParamByteLength = 36;
-                                        cmd1003.Type = 1;
-                                        cmd1003.ParamIndex = 12;
-                                        cmd1003.ParamByteList.AddRange(CmdUtil.ToByteArray(machine.PartnerPoleId, 36));
-                                        cmd1003.Pack();
-
-                                        ServerCommand sc1003 = new ServerCommand();
-                                        sc1003.OutCmdNum = cmd1003.Cmd;
-                                        sc1003.CreatedOn = DateTime.Now;
-                                        sc1003.MachineId = ctdata.MachineId;
-                                        sc1003.MachineCustomId = ctdata.MachineCustomId;
-                                        sc1003.OutTransData = cmd1003.byteList.ToArray();
-                                        db.ServerCommand.Add(sc1003);
-                                        db.SaveChanges();
-
-                                        SendElectricityRates(machine, ctdata);
-
-                                        //設定GetConfiguration
-                                        Cmd9029 cmd9029 = ctdata.CmdHelper.Create(9029) as Cmd9029;
-                                        cmd9029.SerNum = 1;
-                                        cmd9029.CmdSerNum = 1;
-                                        cmd9029.ParamIndex = 1;
-                                        //cmd1005.ParamAmt = 2;
-                                        cmd9029.ParamByteLength = (ushort)4;
-                                        uint p2 = 0x55;
-                                        cmd9029.ParamByteList.AddRange(CmdUtil.ToByteArray(p2));
-                                        //string type = "GetConfiguration";
-                                        //cmd1005.ParamByteList.AddRange(CmdUtil.ToByteArray(type));
-                                        cmd9029.Pack();
-
-                                        ServerCommand sc9029 = new ServerCommand();
-                                        sc9029.OutCmdNum = cmd9029.Cmd;
-                                        sc9029.CreatedOn = DateTime.Now;
-                                        sc9029.MachineId = machine.Id;
-                                        sc9029.MachineCustomId = machine.CustomId;
-                                        sc9029.OutTransData = cmd9029.byteList.ToArray();
-                                        db.ServerCommand.Add(sc9029);
-                                        db.SaveChanges();
-
-
-                                        //后台服务器下发查询目前验证卡号名单版号
-                                        var localauthTable = db.LocalAuthorization.Where(l => l.CustomId == ctdata.MachineCustomId).FirstOrDefault();
-
-                                        if (localauthTable != null)    //查詢電樁是否已建立 Local Authorization Table
-                                        {
-                                            //下發GetLocalListVersion.req
-                                            logger.Trace("set CMD1011 to ServerCommand");
-                                            Cmd1011 cmd1011 = ctdata.CmdHelper.Create(1011) as Cmd1011;
-                                            cmd1011.CmdSerNum = ctdata.GetCmdSerNum();
-                                            cmd1011.SerNum = ctdata.GetSerNum();
-                                            cmd1011.Pack();
-                                            ServerCommand sc1011 = new ServerCommand();
-                                            sc1011.OutCmdNum = cmd1011.Cmd;
-                                            sc1011.CreatedOn = DateTime.Now;
-                                            sc1011.MachineId = ctdata.MachineId;
-                                            sc1011.MachineCustomId = ctdata.MachineCustomId;
-                                            sc1011.OutTransData = cmd1011.byteList.ToArray();
-                                            db.ServerCommand.Add(sc1011);
-                                            db.SaveChanges();
-                                        }
-                                    }
-                                    else if (((BootNotificationConfirmation)conf).status == RegistrationStatus.Pending)
-                                    {
-                                        BootNotificationPending = true;
-                                    }
-                                }
-
-                                //回傳Confirm Message給電樁
-                                string confirmType = string.Empty;
-                                if (call.action.Contains("DataTransfer"))
-                                {
-                                    confirmType = call.action + " Confirm(" + ((DataTransferRequest)(result.Payload)).messageId + ")";
-                                }
-                                else
-                                    confirmType = call.action + " Confirm";
-                                Send(ctdata, ocppMsgHandler.GenerateCallResult(call.id, conf), confirmType);
-
-                                //若BootNotification的status為Pending,後台送出 GetConfiguration Request 給電樁
-                                if (BootNotificationPending == true)
-                                {
-                                    IRequest req = MakeRequestHandler.MakeGetConfigurationRequest();
-                                    string uuid = ctdata.queue.store(req);
-                                    Send(ctdata, ocppMsgHandler.GenerateCall(uuid, Actions.GetConfiguration.ToString(), req), "GetConfiguration Request");
-                                    BootNotificationPending = false;
-                                }
-
-                                if (handleRequestResult.Message != null)
-                                {
-                                    //送 UpdateFirmware封包給電樁
-                                    if (handleRequestResult.Message.Contains("UpdateFirmware"))
-                                    {
-                                        //DataTransfer的下發升級指令
-                                        Send(ctdata, handleRequestResult.Message, "UpdateFirmware Request");
-                                    }
-
-                                    //在回覆StartTransaction.conf後,下發SetChargingProfile.req
-                                    if (handleRequestResult.Message.Contains("SetChargingProfile"))
-                                    {
-                                        //下發SetChargingProfile.req
-                                        Send(ctdata, handleRequestResult.Message, "SetChargingProfile Request");
-                                    }
-
-                                    //下發 APP 餘額/卡片餘額
-                                    if (handleRequestResult.Message.Contains("AccountBalance"))
-                                    {
-                                        //判斷是否為會員
-                                        if (ocppMsgHandler.IsMemberCharging((IRequest)result.Payload, db) == false)
-                                        {
-                                            var machine = machineSrv.GetByCustomId(ctdata.MachineCustomId);
-                                            SendElectricityRates(machine, ctdata);
-                                        }
-
-                                        //下發AccountBalance.req
-                                        Send(ctdata, handleRequestResult.Message, "AccountBalance Request");
-                                    }
-                                }
-                            }
-                            else
-                            {
-                                if (ENABLELOG_MACHINECMD)
-                                {
-                                    //紀錄error type message
-                                    MachineConnectionLog log = new MachineConnectionLog();
-                                    log.MachineCustomId = ctdata.MachineCustomId;
-                                    log.MachineId = ctdata.MachineId;
-                                    log.IpPort = ctdata.LocalEndPoint.ToString();
-                                    log.IsIllegal = true;
-                                    log.IsDataOut = false;
-                                    log.CmdNum = 0;
-                                    if (msg.Length >= 2000)
-                                        log.Data = msg.Substring(0, 1999);
-                                    else
-                                        log.Data = msg;
-                                    log.CreatedOn = DateTime.Now;
-                                    log.Msg = handleRequestResult.Message;
-                                    var ep = ((IPEndPoint)ctdata.RemoteEndPoint);
-                                    log.ClientIpPort = ep.Address.ToString() + ":" + ep.Port.ToString();
-
-                                    SaveMachineConnectionLog(log);
-
-                                    if (msg.Length >= 2000) // BMS錯誤封包
-                                    {
-                                        MachineConnectionLog log1 = new MachineConnectionLog();
-                                        log1.MachineCustomId = ctdata.MachineCustomId;
-                                        log1.MachineId = ctdata.MachineId;
-                                        log1.IpPort = ctdata.LocalEndPoint.ToString();
-                                        log1.IsIllegal = true;
-                                        log1.IsDataOut = false;
-                                        log1.CmdNum = 0;
-                                        log1.Data = "ChargingGunBMS :" + msg.Substring(2000, msg.Length - 2000);
-                                        log1.CreatedOn = DateTime.Now;
-                                        log1.Msg = handleRequestResult.Message;
-                                        var ep1 = ((IPEndPoint)ctdata.RemoteEndPoint);
-                                        log1.ClientIpPort = ep1.Address.ToString() + ":" + ep1.Port.ToString();
-
-                                        SaveMachineConnectionLog(log1);
-                                    }
-                                }
-                                //送出錯誤訊息給電樁
-
-                                Send(ctdata, ocppMsgHandler.GenerateCallError(call.id, "NotImplemented", handleRequestResult.Message), "NotImplemented");
-                            }
-                        }
-                        else
-                        {
-                            #region error type 處理
-
-                            if (ENABLELOG_MACHINECMD)
-                            {
-                                //紀錄error type message
-                                MachineConnectionLog log = new MachineConnectionLog();
-                                log.MachineCustomId = ctdata.MachineCustomId;
-                                log.MachineId = ctdata.MachineId;
-                                log.IpPort = ctdata.LocalEndPoint.ToString();
-                                log.IsIllegal = true;
-                                log.IsDataOut = false;
-                                log.CmdNum = 0;
-                                log.Data = msg;
-                                log.CreatedOn = DateTime.Now;
-
-                                //紀錄exception, 送出錯誤訊息給電樁
-                                if (result.Exception != null)
-                                {
-                                    logger.Error(result.Exception, "OnCall error");
-                                    log.Msg = result.Exception.ToString();
-                                }
-                                else
-                                {
-                                    Send(ctdata, result.Message, "Error Message");
-                                    log.Msg = result.Message;
-                                }
-
-                                var ep = ((IPEndPoint)ctdata.RemoteEndPoint);
-                                log.ClientIpPort = ep.Address.ToString() + ":" + ep.Port.ToString();
-
-                                SaveMachineConnectionLog(log);
-                            }
-
-                            #endregion error type 處理
-                        }
-
-                        #endregion 處理CallMessage
-                    }
-                }
-                catch (SocketException e)
-                {
-                    logger.Trace("disconnected:{0}", ctdata.MachineCustomId);
-                    RemoveClient(ctdata);
-                    return;
-                }
-                catch (ObjectDisposedException e)
-                {
-                    logger.Trace("ObjectDisposedException:{0}", ctdata.MachineCustomId);
-                    //RemoveClientDic(client);
-                    return;
-                }
-                catch (DbEntityValidationException e)
-                {
-                    StringBuilder sb = new StringBuilder();
-                    foreach (var eve in e.EntityValidationErrors)
-                    {
-                        sb.AppendLine(string.Format("Entity of type \"{0}\" in state \"{1}\" has the following validation errors:",
-                                                        eve.Entry.Entity.GetType().Name,
-                                                        eve.Entry.State));
-                        foreach (var ve in eve.ValidationErrors)
-                        {
-                            sb.AppendLine(string.Format("- Property: \"{0}\", Error: \"{1}\"",
-                                                        ve.PropertyName,
-                                                        ve.ErrorMessage));
-                        }
-                    }
-                    logger.Warn(e);
-                }
-                catch (Exception e)
-                {
-                    logger.Warn(e);
-                }
-                finally
-                {
-                    uow.Dispose();
-                }
-            }
-        }
-
-        /// <summary>
-        /// 增加電樁到ClientDic
-        /// </summary>
-        private void OCPP_ClientDicAdded(ClientData ctdata)
-        {
-            //刪除重複的機器
-            if (ClientDic.ContainsKey(ctdata.MachineCustomId))
-            {
-                //刪除重複機器
-                var dupClient = ClientDic[ctdata.MachineCustomId];
-                RemoveClient(dupClient);
-            }
-
-            //刪掉剛連線的紀錄
-            lock (_lockClientDic)
-            {
-                if (ClientDic.ContainsKey(ctdata.MachineCustomIdTemp))
-                {
-                    ClientDic.Remove(ctdata.MachineCustomIdTemp);
-                    logger.Trace("delete connect record {0}", ctdata.MachineCustomId);
-                }
-
-                var oldMachineCustomId = ctdata.MachineCustomId;
-                ctdata.MachineCustomIdTemp = ctdata.MachineCustomId;
-                ctdata.IsCheckIn = true;
-
-                logger.Trace("connect id {0} check in id {1}", oldMachineCustomId, ctdata.MachineCustomId);
-                ClientDic.Add(ctdata.MachineCustomId, ctdata);
-            }
-        }
-
-        /// <summary>
-        /// 從ClientDic取出電樁
-        /// </summary>
-        private void OCPP_ClientDataRemoved(ClientData ctdata)
-        {
-            RemoveClient(ctdata);
-        }
-
-        private void AppServer_SessionClosed(ClientData session, CloseReason reason)
-        {
-            logger.Trace("Enter AppServer_SessionClosed()");
-            lock (_lockClientDic)
-            {
-                ClientData client;
-
-                if (!String.IsNullOrEmpty(session.Path))
-                {
-                    string[] words = session.Path.Split('/');
-
-                    if (ClientDic.ContainsKey(words.Last()))
-                    {
-                        if (ClientDic.TryGetValue(words.Last(), out client))
-                        {
-                            ClientDic.Remove(words.Last());
-                            logger.Trace("RemoveClient ContainsKey" + words.Last());
-                            client = null;
-                        }
-                    }
-                    else
-                    {
-                        if((session.MachineCustomId != null) && (session.MachineCustomIdTemp != null))
-                        {
-                            if (ClientDic.TryGetValue(session.MachineCustomId, out client))
-                            {
-                                ClientDic.Remove(session.MachineCustomId);
-                                logger.Trace("RemoveClient ContainsKey" + words.Last());
-                                client = null;
-                            }
-                            else if (ClientDic.TryGetValue(session.MachineCustomIdTemp, out client))
-                            {
-                                ClientDic.Remove(session.MachineCustomIdTemp);
-                                logger.Trace("RemoveClient ContainsKey" + words.Last());
-                                client = null;
-                            }
-                        }
-
-                    }
-                }
-            }
-        }
-
-        private void AppServer_NewSessionConnected(ClientData client)
-        {
-            try
-            {
-                client.m_ReceiveData += new ClientData.OCPPClientDataEventHandler<ClientData, String>(ReceivedMessage);
-                lock (_lockClientDic)
-                {
-                    ClientDic.Add(client.MachineCustomId, client);
-                }
-
-                logger.Trace("client: " + client.MachineCustomId + " in");
-                using (var db = new PhihongDbContext())
-                {
-                    if (ENABLELOG_MACHINECMD)
-                    {
-                        // 紀錄電樁的新連線資訊
-                        MachineConnectionLog log = new MachineConnectionLog();
-                        log.MachineCustomId = client.MachineCustomId;
-                        log.MachineId = client.MachineId;
-                        log.IpPort = client.LocalEndPoint.ToString();
-                        log.IsIllegal = true;
-                        log.IsDataOut = false;
-                        log.CmdNum = 0;
-                        log.CreatedOn = DateTime.Now;
-                        var ep = ((IPEndPoint)client.RemoteEndPoint);
-                        log.ClientIpPort = ep.ToString();
-                        log.Msg = "connect";
-
-                        SaveMachineConnectionLog(log);
-                    }
-                }
-            }
-            catch (Exception ex)
-            {
-                logger.Warn(ex);
-                RemoveClient(client);
-            }
-        }
-
-        public void Stop()
-        {
-            _cts.Cancel();
-
-            var list = ClientDic.Select(c => c.Value).ToList();
-            foreach (var c in list)
-            {
-                RemoveClient(c);
-            }
-        }
-
-        public void RemoveClient(ClientData client)
-        {
-            logger.Trace("RemoveClient" + client.MachineCustomId);
-            if (client != null)
-            {
-                try
-                {
-                    client.Close(CloseReason.ServerClosing);
-                }
-                catch (Exception ex)
-                {
-                    //logger.Warn("Close client socket error!!");
-                    logger.Warn(string.Format("Close client socket error!! {0} Msg:{1}", client.MachineCustomId, ex.Message));
-                }
-                client.m_ReceiveData -= new ClientData.OCPPClientDataEventHandler<ClientData, String>(ReceivedMessage);
-                client.Close();
-                // logger.Trace("Close client socket!!");
-                logger.Trace("Close client socket!!" + client.MachineCustomId);
-                RemoveClientDic(client);
-
-                logger.Trace("RemoveClient null" + client.MachineCustomId);
-                if (client != null)
-                {
-                    client = null;
-                }
-            }
-        }
-
-        public void RemoveClientDic(ClientData client)
-        {
-            lock (_lockClientDic)
-            {
-                if (ClientDic.ContainsKey(client.MachineCustomId))
-                {
-                    ClientDic.Remove(client.MachineCustomId);
-                    logger.Trace("RemoveClient ContainsKey" + client.MachineCustomId);
-                }
-            }
-        }
-
-        public void ServerCommandThread()
-        {
-            for (; ; )
-            {
-                if (_ct.IsCancellationRequested)
-                {
-                    break;
-                }
-
-                logger.Trace("command loop");
-                logger.Trace("ClientDic:" + ClientDic.Count().ToString());
-                logger.Trace("NeedConfirmPacketList:" + NeedConfirmPacketList.Count().ToString());
-
-                try
-                {
-                    var redirect = ConfigurationManager.AppSettings.Get("Redirect");
-                    if (redirect.Equals("1"))
-                    {
-                        System.Threading.Thread.Sleep(1000);
-                        continue;
-                    }
-
-                    using (var db = new PhihongDbContext())
-                    {
-                        ProcessServerCommand(db);
-
-                        ProcessConfirmPacket();
-
-                        System.Threading.Thread.Sleep(1000);
-
-                        //每小時發送校時
-                        var ts = DateTime.Now - sendTiming;
-                        if (ts.TotalHours > 1)
-                        {
-                            Timing(db);
-                            sendTiming = DateTime.Now;
-                        }
-
-                        //每5分鐘檢查
-                        ts = DateTime.Now - checkUpdateDt;
-                        if (ts.TotalMinutes > 5)
-                        {
-                            logger.Trace("check sw update");
-                            CheckSW(db);
-                            logger.Trace("check fw update");
-                            CheckFW(db);
-                            checkUpdateDt = DateTime.Now;
-                        }
-                    }
-                }
-                catch (Exception ex)
-                {
-                    logger.Error("server stop");
-                    logger.Error(ex);
-                }
-            }
-        }
-
-        private void ProcessServerCommand(PhihongDbContext db)
-        {
-            OCPPMessageHandler ocppMsgHandler = new OCPPMessageHandler();
-            string respone = String.Empty;
-            string messageType = string.Empty;
-            var machineList = ClientDic.Select(c => c.Key).ToList();
-
-            DateTime startDt = DateTime.Now.AddSeconds(-30);
-
-            var commandList = db.ServerCommand.Where(c => !c.UpdatedOn.HasValue && c.CreatedOn >= startDt && c.CreatedOn <= DateTime.Now).ToList().Where(c => machineList.Contains(c.MachineCustomId)).ToList();
-            //處理主機傳送的有指令
-            var cmdMachineList = commandList.Select(c => c.MachineCustomId).Distinct().ToList();
-            foreach (var cmdMachine in cmdMachineList)
-            {
-                ClientData client;
-                if (ClientDic.TryGetValue(cmdMachine, out client))
-                {
-                    //有簽到或測試指令模式
-                    if (client.IsCheckIn)
-                    {
-                        var cmdList = commandList.Where(c => c.MachineCustomId == cmdMachine && c.OutTransData != null).ToList();
-
-                        foreach (var item in cmdList)
-                        {
-                            BaseCmd c = client.CmdHelper.UpPack(item.OutTransData.ToList());
-                            int reservationId = 0;
-                            int chargingProfileId = 0;
-                            if (c is CmdError)
-                            {
-                                continue;
-                            }
-
-                            if (c is Cmd1005) //Remote結束充電
-                            {
-                                var cmd = c as Cmd1005;
-                                //Cancel預約reservationId
-                                if (cmd.ParamIndex == 10)
-                                {
-                                    //槍號=> reservationID, OCPP 槍號從1 開始
-                                    reservationId = cmd.GunSerNo + 1;
-                                }
-                            }
-                            else if (c is Cmd1007) //Remote啟動充電, 如果是發送充電指令的,送一次費率過去
-                            {
-                                var cmd = c as Cmd1007;
-
-                                IMachineService machineSrv = new MachineService();
-                                var machine = machineSrv.GetByCustomId(item.MachineCustomId);
-                                SendElectricityRates(machine, client);
-                                //產生定時充電/預約 reservationId
-                                if (cmd.StartChargingType == 1 || cmd.StartChargingType == 2)
-                                {
-                                    //槍號=> reservationID, OCPP 槍號從1 開始
-                                    reservationId = cmd.GunSerNo + 1;
-                                }
-
-                                client.CarType = Convert.ToInt32(cmd.VehicleType);
-                            }
-                            else if (c is Cmd9015) //ocpp command : SetChargingProfile
-                            {
-                                var cmd9015 = c as Cmd9015;
-                                chargingProfileId = client.GetChargingProfileId();
-                            }
-                            respone = ocppMsgHandler.HandleServerCommand(c, client.MachineCustomId, ref client.queue, ref client.configurationKey, reservationId, chargingProfileId, out messageType, db);
-
-                            item.OutTransData = CmdUtil.ToByteArray(respone, respone.Length);//System.Text.UTF8Encoding.Default.GetBytes(respone);//c.byteList.ToArray();
-                            item.UpdatedOn = DateTime.Now;
-                            db.SaveChanges();
-                            Send(client, respone, messageType);
-                            AddConfirmPacket(client, c, respone, item.Id, messageType);
-                            respone = String.Empty;
-                            Thread.Sleep(1);
-                        }
-                    }
-                }
-            }
-        }
-
-        /// <summary>
-        /// 送出指令
-        /// </summary>
-        /// <param name="client"></param>
-        /// <param name="cmd"></param>
-        /// <returns></returns>
-        private bool Send(ClientData client, string ocppmessage, string messageType)
-        {
-            try
-            {
-                if (String.IsNullOrEmpty(ocppmessage) == true)
-                    return false;
-                using (var db = new PhihongDbContext())
-                {
-                    if (ENABLELOG_MACHINECMD)
-                    {
-                        MachineConnectionLog log = new MachineConnectionLog();
-                        log.MachineCustomId = client.MachineCustomId;
-                        log.MachineId = client.MachineId;
-                        log.IpPort = client.LocalEndPoint.ToString();
-
-                        if (ocppmessage.Length > 2000)
-                            log.Data = ocppmessage.Substring(0, 1999);
-                        else
-                            log.Data = ocppmessage;
-
-                        //log.Data = ocppmessage;
-                        log.IsDataOut = true;
-                        log.CmdNum = 0;
-                        log.CreatedOn = DateTime.Now;
-                        log.Msg = messageType;
-                        var ep = ((IPEndPoint)client.RemoteEndPoint);
-                        log.ClientIpPort = ep.Address.ToString() + ":" + ep.Port.ToString();
-
-                        SaveMachineConnectionLog(log);
-
-                        if (ocppmessage.Length >= 2000) // BMS封包
-                        {
-                            MachineConnectionLog log1 = new MachineConnectionLog();
-                            log1.MachineCustomId = client.MachineCustomId;
-                            log1.MachineId = client.MachineId;
-                            log1.IpPort = client.LocalEndPoint.ToString();
-                            log1.IsIllegal = false;
-                            log1.IsDataOut = false;
-                            log1.CmdNum = 0;
-                            log1.Data = "Key :" + ocppmessage.Substring(2000, ocppmessage.Length - 2000);
-                            log1.CreatedOn = DateTime.Now;
-                            log1.Msg = messageType;
-                            var ep1 = ((IPEndPoint)client.RemoteEndPoint);
-                            log1.ClientIpPort = ep1.Address.ToString() + ":" + ep1.Port.ToString();
-
-                            SaveMachineConnectionLog(log1);
-                        }
-
-                      
-                    }
-                }
-
-                client.Send(ocppmessage);
-            }
-            catch (Exception ex)
-            {
-                RemoveClient(client);
-                logger.Error(ex);
-                return false;
-            }
-            return true;
-        }
-
-        /// <summary>
-        /// 判斷數據包的指令,是否需要確認
-        /// </summary>
-        /// <param name="cmd"></param>
-        public void AddConfirmPacket(ClientData client, BaseCmd cmd, string sentmessage, int id, string messageType)
-        {
-            if (String.IsNullOrEmpty(sentmessage) == true)
-                return;
-            NeedConfirmPacket p = new NeedConfirmPacket();
-            var array = JsonConvert.DeserializeObject<JArray>(sentmessage);
-            p.Id = id;
-            //p.CmdSerNum = cmd.CmdSerNum;
-            p.SentInterval = 10;
-            p.SentTimes = 3;
-            p.MachineCustomId = client.MachineCustomId;
-            p.SentMessage = sentmessage;
-            p.SentAction = messageType;
-            if (_needConfirmCmdList.Contains(cmd.Cmd))
-            {
-                p.SentUniqueId = array[1].ToString();
-
-                lock (_lockConfirmPacketList)
-                {
-                    NeedConfirmPacketList.Add(p);
-                    logger.Trace("Add NeedConfirmPacketList ");
-                }
-            }
-        }
-
-        private void Timing(PhihongDbContext db)
-        {
-            var list = ClientDic.Values.Where(c => c.IsCheckIn).ToList();
-
-            foreach (var item in list)
-            {
-                logger.Trace(item.MachineCustomId + ":sent commant timing");
-
-                Cmd1003 cmd3 = item.CmdHelper.Create(1003) as Cmd1003;
-
-                cmd3.ParamByteLength = 8;
-                cmd3.Type = 1;
-                cmd3.ParamIndex = 2;
-                cmd3.ParamByteList.AddRange(CmdUtil.ToByteArray(DateTime.Now));
-                cmd3.Pack();
-
-                ServerCommand sc2 = new ServerCommand();
-                sc2.OutCmdNum = cmd3.Cmd;
-                sc2.CreatedOn = DateTime.Now;
-                sc2.MachineId = item.MachineId;
-                sc2.MachineCustomId = item.MachineCustomId;
-                sc2.OutTransData = cmd3.byteList.ToArray();
-                db.ServerCommand.Add(sc2);
-                db.SaveChanges();
-            }
-        }
-
-        /// <summary>
-        /// 確認機器版本
-        /// </summary>
-        /// <param name="db"></param>
-        private void CheckSW(PhihongDbContext db)
-        {
-            OCPPMessageHandler ocppMsgHandler = new OCPPMessageHandler();
-            string respone = String.Empty;
-            if (ClientDic.Count() == 0)
-                return;
-
-            foreach (var item in ClientDic)
-            {
-                logger.Trace("check sw loop");
-                logger.Trace("check sw" + item.Value.MachineCustomId);
-                var machine = db.Machine.Where(c => c.Id == item.Value.MachineId).AsNoTracking().FirstOrDefault();
-
-                if (machine == null)
-                {
-                    logger.Error("check sw,can't find machine " + item.Value.MachineCustomId);
-                    continue;
-                }
-
-                if (machine.SW_AssignedMachineVersionId.HasValue)
-                {
-                    logger.Trace(machine.CustomId + "asinged sw value");
-
-                    var mv = db.MachineVersion.Include(c => c.PublishVersion)
-                        .Include(c => c.PublishVersion.PublishVersionFiles)
-                        .Include(c => c.PublishVersion.PublishVersionFiles.Select(z => z.UploadFile))
-                        .Where(c => c.Id == machine.SW_AssignedMachineVersionId.Value).First();
-
-                    logger.Trace(mv.Id + "get sw value");
-
-                    if (!machine.SW_VersionReport.HasValue || machine.SW_VersionReport.Value != mv.PublishVersion.Version)
-                    {
-                        logger.Trace(machine.CustomId + "ready to sent commmand to update sw ");
-                        UploadFile uploadFile;
-
-                        //ipc 就更新清單,非ipc就更新檔案
-                        if (mv.PublishVersion.UpdateJsonUploadFileId == null)
-                            uploadFile = mv.PublishVersion.PublishVersionFiles.First().UploadFile;
-                        else
-                            uploadFile = db.UploadFile.Find(mv.PublishVersion.UpdateJsonUploadFileId.Value);
-
-                        byte param = 0;
-
-                        //DataTransfer的下發升級指令
-                        respone = ocppMsgHandler.HandleUpdateFirmware(ref item.Value.queue, 1, (ProgramParam)param, uploadFile);
-                        Send(item.Value, respone, "UpdateFirmware Request");
-
-                        ////OCPP 的下發升級指令
-                        //respone = String.Empty;
-                        //string fileurl = @"http://" + uploadFile.FileUrl;
-                        //respone = ocppMsgHandler.HandleOCPPUpdateFirmware(ref item.Value.queue, fileurl);
-                        //Send(item.Value, respone);
-
-                        logger.Trace(item.Key + ":sent command to update sw");
-                    }
-                }
-            }
-        }
-
-        /// <summary>
-        /// 確認機器版本
-        /// </summary>
-        /// <param name="db"></param>
-        private void CheckFW(PhihongDbContext db)
-        {
-            OCPPMessageHandler ocppMsgHandler = new OCPPMessageHandler();
-            string respone = String.Empty;
-            foreach (var item in ClientDic)
-            {
-                logger.Trace("check fw loop");
-                logger.Trace("check fw" + item.Value.MachineCustomId);
-                var machine = db.Machine.Where(c => c.Id == item.Value.MachineId).AsNoTracking().FirstOrDefault();
-
-                if (machine == null)
-                {
-                    logger.Error("check fw,can't find machine" + item.Value.MachineCustomId);
-                    continue;
-                }
-
-                if (machine.FW_AssignedMachineVersionId.HasValue)
-                {
-                    logger.Trace(machine.CustomId + "assigned fw update value");
-
-                    var mv = db.MachineVersion.Include(c => c.PublishVersion)
-                        .Include(c => c.PublishVersion.PublishVersionFiles)
-                        .Include(c => c.PublishVersion.PublishVersionFiles.Select(z => z.UploadFile))
-                        .Where(c => c.Id == machine.FW_AssignedMachineVersionId.Value).First();
-
-                    logger.Trace(mv.Id + "get fw update value");
-
-                    if (!machine.FW_VersionReport.HasValue || machine.FW_VersionReport.Value != mv.PublishVersion.Version)
-                    {
-                        logger.Trace(machine.CustomId + "ready to sent command to update fw");
-                        UploadFile uploadFile;
-
-                        List<UploadFile> ufList = new List<UploadFile>();
-
-                        //ipc 就更新清單,非ipc就更新檔案
-                        if (mv.PublishVersion.UpdateJsonUploadFileId == null)
-                        {
-                            ufList.AddRange(mv.PublishVersion.PublishVersionFiles.Select(c => c.UploadFile).ToList());
-                            //uploadFile = mv.PublishVersion.PublishVersionFiles.First().UploadFile;
-                        }
-                        else
-                        {
-                            uploadFile = db.UploadFile.Find(mv.PublishVersion.UpdateJsonUploadFileId.Value);
-                            ufList.Add(uploadFile);
-                        }
-
-                        foreach (var f in ufList)
-                        {
-                            byte param = 0;
-                            if (mv.PublishVersion.UpdateJsonUploadFileId == null)
-                            {
-                                param = (byte)f.FwTagId.Value;
-                            }
-
-                            if (param == 28) // HMI-B2
-                                continue;
-
-                            //DataTransfer的下發升級指令
-                            respone = ocppMsgHandler.HandleUpdateFirmware(ref item.Value.queue, 2, (ProgramParam)param, f);
-
-                            Send(item.Value, respone, "DataTransfer Request(UpdateFirmware)");
-
-                            ////OCPP 的下發升級指令
-                            //respone = String.Empty;
-                            //string fileurl = @"http://" + f.FileUrl;
-                            //respone = ocppMsgHandler.HandleOCPPUpdateFirmware(ref item.Value.queue, fileurl);
-                            //Send(item.Value, respone);
-
-                            logger.Trace(item.Key + ":send command to update fw");
-                        }
-                    }
-                }
-            }
-        }
-
-        /// <summary>
-        /// 處理需確認的數據包
-        /// </summary>
-        private void ProcessConfirmPacket()
-        {
-            List<NeedConfirmPacket> removeList = new List<NeedConfirmPacket>();
-            //處理需要重送的數據包
-            var count = NeedConfirmPacketList.Count;
-            for (int i = 0; i < count; i++)
-            {
-                var item = NeedConfirmPacketList[i];
-
-                //這個要移除,不處理
-                if (item.SentTimes <= 0 && item.SentInterval <= 0)
-                {
-                    removeList.Add(item);
-                    continue;
-                }
-
-                //要處理送出
-                if (--item.SentInterval <= 0)
-                {
-                    ClientData client;
-                    if (ClientDic.TryGetValue(item.MachineCustomId, out client))
-                    {
-                        //有簽到或測試指令模式
-                        if (client.IsCheckIn)
-                        {
-                            Send(client, item.SentMessage, item.SentAction);
-                        }
-                    }
-
-                    //如果已經到了次數限制,3,就不再送了
-                    if (--item.SentTimes <= 0)
-                    {
-                        item.SentTimes = 0;
-                        item.SentInterval = 0;
-                        removeList.Add(item);
-                    }
-                    else
-                    {
-                        //把間隔秒數set 3
-                        item.SentInterval = 10;
-                    }
-                }
-            }
-
-            //移除已經結束的數據包
-            lock (_lockConfirmPacketList)
-            {
-                foreach (var item in removeList)
-                {
-                    NeedConfirmPacketList.Remove(item);
-                    logger.Trace("delete needConfirmPacketList MachineCustomId:{0},UUID:{1}", item.MachineCustomId, item.SentUniqueId);
-                }
-            }
-        }
-
-        /// <summary>
-        /// 送出電費及服務費率
-        /// </summary>
-        /// <param name="machine"></param>
-        /// <param name="client"></param>
-        private void SendElectricityRates(Machine machine, ClientData client)
-        {
-            using (var db = new PhihongDbContext())
-            {
-                if (machine.Customer.SinglePricePerKWH)
-                {
-                    //設定每度費用
-                    Cmd2301 cmd2301 = client.CmdHelper.Create(2301) as Cmd2301;
-                    cmd2301.CmdSerNum = client.GetCmdSerNum();
-                    cmd2301.SerNum = client.GetSerNum();
-                    cmd2301.PricePerKWH.RealValue = machine.PricePerKWH;
-                    cmd2301.Pack();
-
-                    ServerCommand sc1 = new ServerCommand();
-                    sc1.OutCmdNum = cmd2301.Cmd;
-                    sc1.CreatedOn = DateTime.Now;
-                    sc1.MachineId = client.MachineId;
-                    sc1.MachineCustomId = client.MachineCustomId;
-                    sc1.OutTransData = cmd2301.byteList.ToArray();
-                    db.ServerCommand.Add(sc1);
-                    db.SaveChanges();
-                }
-                else
-                {
-                    Cmd2303 cmd2303 = client.CmdHelper.Create(2303) as Cmd2303;
-                    cmd2303.CmdSerNum = client.GetCmdSerNum();
-                    cmd2303.SerNum = client.GetSerNum();
-                    cmd2303.Section0000_0030.RealValue = machine.Section0000_0030;
-                    cmd2303.Section0030_0100.RealValue = machine.Section0030_0100;
-                    cmd2303.Section0100_0130.RealValue = machine.Section0100_0130;
-                    cmd2303.Section0130_0200.RealValue = machine.Section0130_0200;
-                    cmd2303.Section0200_0230.RealValue = machine.Section0200_0230;
-                    cmd2303.Section0230_0300.RealValue = machine.Section0230_0300;
-                    cmd2303.Section0300_0330.RealValue = machine.Section0300_0330;
-                    cmd2303.Section0330_0400.RealValue = machine.Section0330_0400;
-                    cmd2303.Section0400_0430.RealValue = machine.Section0400_0430;
-                    cmd2303.Section0430_0500.RealValue = machine.Section0430_0500;
-                    cmd2303.Section0500_0530.RealValue = machine.Section0500_0530;
-                    cmd2303.Section0530_0600.RealValue = machine.Section0530_0600;
-                    cmd2303.Section0600_0630.RealValue = machine.Section0600_0630;
-                    cmd2303.Section0630_0700.RealValue = machine.Section0630_0700;
-                    cmd2303.Section0700_0730.RealValue = machine.Section0700_0730;
-                    cmd2303.Section0730_0800.RealValue = machine.Section0730_0800;
-                    cmd2303.Section0800_0830.RealValue = machine.Section0800_0830;
-                    cmd2303.Section0830_0900.RealValue = machine.Section0830_0900;
-                    cmd2303.Section0900_0930.RealValue = machine.Section0900_0930;
-                    cmd2303.Section0930_1000.RealValue = machine.Section0930_1000;
-                    cmd2303.Section1000_1030.RealValue = machine.Section1000_1030;
-                    cmd2303.Section1030_1100.RealValue = machine.Section1030_1100;
-                    cmd2303.Section1100_1130.RealValue = machine.Section1100_1130;
-                    cmd2303.Section1130_1200.RealValue = machine.Section1130_1200;
-                    cmd2303.Section1200_1230.RealValue = machine.Section1200_1230;
-                    cmd2303.Section1230_1300.RealValue = machine.Section1230_1300;
-                    cmd2303.Section1300_1330.RealValue = machine.Section1300_1330;
-                    cmd2303.Section1330_1400.RealValue = machine.Section1330_1400;
-                    cmd2303.Section1400_1430.RealValue = machine.Section1400_1430;
-                    cmd2303.Section1430_1500.RealValue = machine.Section1430_1500;
-                    cmd2303.Section1500_1530.RealValue = machine.Section1500_1530;
-                    cmd2303.Section1530_1600.RealValue = machine.Section1530_1600;
-                    cmd2303.Section1600_1630.RealValue = machine.Section1600_1630;
-                    cmd2303.Section1630_1700.RealValue = machine.Section1630_1700;
-                    cmd2303.Section1700_1730.RealValue = machine.Section1700_1730;
-                    cmd2303.Section1730_1800.RealValue = machine.Section1730_1800;
-                    cmd2303.Section1800_1830.RealValue = machine.Section1800_1830;
-                    cmd2303.Section1830_1900.RealValue = machine.Section1830_1900;
-                    cmd2303.Section1900_1930.RealValue = machine.Section1900_1930;
-                    cmd2303.Section1930_2000.RealValue = machine.Section1930_2000;
-                    cmd2303.Section2000_2030.RealValue = machine.Section2000_2030;
-                    cmd2303.Section2030_2100.RealValue = machine.Section2030_2100;
-                    cmd2303.Section2100_2130.RealValue = machine.Section2100_2130;
-                    cmd2303.Section2130_2200.RealValue = machine.Section2130_2200;
-                    cmd2303.Section2200_2230.RealValue = machine.Section2200_2230;
-                    cmd2303.Section2230_2300.RealValue = machine.Section2230_2300;
-                    cmd2303.Section2300_2330.RealValue = machine.Section2300_2330;
-                    cmd2303.Section2330_2400.RealValue = machine.Section2330_2400;
-                    cmd2303.Pack();
-
-                    ServerCommand sc2 = new ServerCommand();
-                    sc2.OutCmdNum = cmd2303.Cmd;
-                    sc2.CreatedOn = DateTime.Now;
-                    sc2.MachineId = client.MachineId;
-                    sc2.MachineCustomId = client.MachineCustomId;
-                    sc2.OutTransData = cmd2303.byteList.ToArray();
-                    db.ServerCommand.Add(sc2);
-                    db.SaveChanges();
-                }
-                //設定每度服務費
-                Cmd2305 cmd2305 = client.CmdHelper.Create(2305) as Cmd2305;
-                cmd2305.CmdSerNum = client.GetCmdSerNum();
-                cmd2305.SerNum = client.GetSerNum();
-                cmd2305.FeePerKWH.RealValue = machine.FeePerKWH;
-                cmd2305.Pack();
-
-                ServerCommand sc3 = new ServerCommand();
-                sc3.OutCmdNum = cmd2305.Cmd;
-                sc3.CreatedOn = DateTime.Now;
-                sc3.MachineId = client.MachineId;
-                sc3.MachineCustomId = client.MachineCustomId;
-                sc3.OutTransData = cmd2305.byteList.ToArray();
-                db.ServerCommand.Add(sc3);
-                db.SaveChanges();
-            }
-        }
-
-        private void CheckConfirmPacket(ClientData client, BaseMessage message)
-        {
-            lock (_lockConfirmPacketList)
-            {
-                logger.Trace("CheckConfirmPacket NeedConfirmPacketList:" + NeedConfirmPacketList.Count().ToString());
-                //檢查 Call Message/ CallResult Message / CallError Message的 UniqueId屬性, 是否與  NeedConfirmPacket的 SentUniqueId屬性 一致
-                var item = NeedConfirmPacketList.Where(c => c.MachineCustomId == client.MachineCustomId && c.SentUniqueId == message.id).FirstOrDefault();
-
-                if (item != null)
-                {
-                    logger.Trace("check CheckConfirmPacket MachineCustomId:{0},SentUniqueId:{1}", item.MachineCustomId, item.SentUniqueId);
-                    using (var db = new PhihongDbContext())
-                    {
-                        var sc = db.ServerCommand.Where(c => c.Id == item.Id).FirstOrDefault();
-                        object payload = null;
-
-                        if (sc.OutCmdNum == 1001)
-                        {
-                            // 當 Heartbeat 與 上一個 Heartbeat相差值小於2秒,判斷是否送出ChangeConfiguration.req(HeartbeatInterval: 15) 給電樁
-                            client.IsSendHeartbeatChangeConfiguration = false;
-                        }
-                        else if (sc.OutCmdNum == 9001)
-                        {
-                            sc.InCmdNum = 9002; /*9002為Cmd9002, 目前Packet Cmd沒有建立此Command*/
-                        }
-                        else if (sc.OutCmdNum == 9003)
-                        {
-                            sc.InCmdNum = 9004; /*9004為Cmd9004, 目前Packet Cmd沒有建立此Command*/
-                        }
-                        else if (sc.OutCmdNum == 9005)
-                        {
-                            sc.InCmdNum = 9006; /*9006為Cmd9006, 目前Packet Cmd沒有建立此Command*/
-                        }
-                        else if (sc.OutCmdNum == 9007)
-                        {
-                            sc.InCmdNum = 9008; /*9008為Cmd9008, 目前Packet Cmd沒有建立此Command*/
-                        }
-                        else if (sc.OutCmdNum == 9009)
-                        {
-                            sc.InCmdNum = 9010; /*9010為Cmd9010, 目前Packet Cmd沒有建立此Command*/
-                        }
-                        else if (sc.OutCmdNum == 9011)
-                        {
-                            sc.InCmdNum = 9012; /*9012為Cmd9012, 目前Packet Cmd沒有建立此Command*/
-                        }
-                        else if (sc.OutCmdNum == 9013)
-                        {
-                            sc.InCmdNum = 9014; /*9014為Cmd9014, 目前Packet Cmd沒有建立此Command*/
-                        }
-                        else if (sc.OutCmdNum == 9015)
-                        {
-                            sc.InCmdNum = 9016; /*9016為Cmd9016, 目前Packet Cmd沒有建立此Command*/
-                        }
-                        else if (sc.OutCmdNum == 9017)
-                        {
-                            sc.InCmdNum = 9018; /*9018為Cmd9018, 目前Packet Cmd沒有建立此Command*/
-                        }
-                        else if (sc.OutCmdNum == 9019)
-                        {
-                            sc.InCmdNum = 9020; /*9020為Cmd9020, 目前Packet Cmd沒有建立此Command*/
-                        }
-                        else if (sc.OutCmdNum == 9021)
-                        {
-                            sc.InCmdNum = 9022; /*9022為Cmd9022, 目前Packet Cmd沒有建立此Command*/
-                        }
-                        else if (sc.OutCmdNum == 9023)
-                        {
-                            sc.InCmdNum = 9024; /*9024為Cmd9024, 目前Packet Cmd沒有建立此Command*/
-                        }
-                        else if (sc.OutCmdNum == 9025)
-                        {
-                            sc.InCmdNum = 9026; /*9026為Cmd9026, 目前Packet Cmd沒有建立此Command*/
-                        }
-                        else if (sc.OutCmdNum == 9027)
-                        {
-                            sc.InCmdNum = 9028; /*9028為Cmd9028, 目前Packet Cmd沒有建立此Command*/
-                        }
-                        else if (sc.OutCmdNum == 9029)
-                        {
-                            sc.InCmdNum = 9030; /*9030為Cmd9030, 目前Packet Cmd沒有建立此Command*/
-                        }
-                        else if (sc.OutCmdNum == 9031)
-                        {
-                            sc.InCmdNum = 9032; /*9032為Cmd9032, 目前Packet Cmd沒有建立此Command*/
-                        }
-                        else
-                        {
-                            sc.InCmdNum = 0;
-                        }
-
-                        if (message is CallResultMessage)
-                        {
-                            CallResultMessage call = (CallResultMessage)message;
-                            payload = call.payload;
-                        }
-                        else if (message is CallErrorMessage)
-                        {
-                            CallErrorMessage call = (CallErrorMessage)message;
-                            payload = call.payload;
-                        }
-                        else if (message is CallMessage)
-                        {
-                            CallMessage call = (CallMessage)message;
-                            payload = call.payload;
-                        }
-
-                        //sc.InTransData = CmdUtil.ToByteArray(message.ToString(), message.ToString().Length);//System.Text.UTF8Encoding.Default.GetBytes(message.ToString());
-                        sc.InTransData = CmdUtil.ToByteArray(payload.ToString(), payload.ToString().Length);//System.Text.UTF8Encoding.Default.GetBytes(message.ToString());
-                        sc.ReceivedOn = DateTime.Now;
-                        db.SaveChanges();
-
-                        item.SentInterval = 0;
-                        item.SentTimes = 0;
-
-                        logger.Trace("reply NeedConfirmPacket MachineCustomId:{0},SentUniqueId:{1}", item.MachineCustomId, item.SentUniqueId);
-                    }
-                }
-            }
-        }
-
-        private void SaveMachineConnectionLog(MachineConnectionLog log)
-        {
-            if (System.Configuration.ConfigurationManager.AppSettings["mongoDb"] != null)
-            {
-
-                try
-                {
-                    MMachineConnectionLog mlog = new MMachineConnectionLog();
-                    mlog.MachineCustomId = log.MachineCustomId;
-                    mlog.MachineId = log.MachineId;
-                    mlog.IpPort = log.IpPort;
-                    mlog.IsIllegal = log.IsIllegal;
-                    mlog.IsDataOut = log.IsDataOut;
-                    mlog.CmdNum = log.CmdNum;
-                    mlog.CreatedOn = log.CreatedOn;                 
-                    mlog.ClientIpPort = log.ClientIpPort;
-                    mlog.Msg = log.Msg;
-                    mlog.Data = log.Data;
-                    IMongoDatabase database = mongoService.getMongoDatabase();
-                    var mdb = database.GetCollection<MMachineConnectionLog>(Globals._col_MachineConnectionLog);
-                    mdb.InsertOne(mlog);
-                }
-                catch (Exception e)
-                {
-                    logger.Trace("mongo MachineConnectionLog error:" + e.Message);
-
-                }
-            }
-            else
-            {
-                using (var db = new PhihongDbContext())
-                {
-                    db.MachineConnectionLog.Add(log);
-                    db.SaveChanges();
-                }
-                  
-            }
-        }
-    }
-}

+ 0 - 20
OCPPServer/packages.config

@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<packages>
-  <package id="DnsClient" version="1.0.7" targetFramework="net461" />
-  <package id="EntityFramework" version="6.2.0" targetFramework="net461" />
-  <package id="Microsoft.AspNet.WebApi.Client" version="5.2.3" targetFramework="net461" />
-  <package id="MongoDB.Bson" version="2.7.0" targetFramework="net461" />
-  <package id="MongoDB.Driver" version="2.7.0" targetFramework="net461" />
-  <package id="MongoDB.Driver.Core" version="2.7.0" targetFramework="net461" />
-  <package id="Newtonsoft.Json" version="10.0.2" targetFramework="net452" />
-  <package id="NLog" version="4.4.12" targetFramework="net461" />
-  <package id="NLog.Config" version="4.4.10" targetFramework="net461" />
-  <package id="NLog.Schema" version="4.4.10" targetFramework="net461" />
-  <package id="System.Buffers" version="4.3.0" targetFramework="net461" />
-  <package id="System.Net.Http" version="4.3.3" targetFramework="net461" />
-  <package id="System.Runtime.InteropServices.RuntimeInformation" version="4.0.0" targetFramework="net461" />
-  <package id="System.Security.Cryptography.Algorithms" version="4.3.0" targetFramework="net461" />
-  <package id="System.Security.Cryptography.Encoding" version="4.3.0" targetFramework="net461" />
-  <package id="System.Security.Cryptography.Primitives" version="4.3.0" targetFramework="net461" />
-  <package id="System.Security.Cryptography.X509Certificates" version="4.3.0" targetFramework="net461" />
-</packages>

BIN
TestTool.RemoteTriggerAPP/DLL/EVCB_OCPP.Domain.dll


+ 1 - 1
TestTool.RemoteTriggerAPP/MainWindow.xaml

@@ -5,7 +5,7 @@
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
         xmlns:local="clr-namespace:TestTool.RemoteTriggerAPP"      
         mc:Ignorable="d"
-        Title="下發測試用工具(公司內網) V1.1.27 (20200831)" Height="481" Width="652">
+        Title="下發測試用工具(公司內網) V1.1.28 (20201026)" Height="481" Width="652">
     <Viewbox>
         <Grid Margin="0,2,2,0">
             <Grid.ColumnDefinitions>

+ 5 - 5
TestTool.RemoteTriggerAPP/MainWindow.xaml.cs

@@ -411,11 +411,11 @@ namespace TestTool.RemoteTriggerAPP
                 try
                 {
                     expiryTime = Convert.ToDateTime(uxExpiryTimeTb.Text);
-                    if (expiryTime < DateTime.Now.AddSeconds(60))
-                    {
-                        isError = true;
-                        uxMsgTb.Text = string.Format("ExpiryTime is too close or too early to the current time (60 seconds).");
-                    }
+                    //if (expiryTime < DateTime.Now.AddSeconds(60))
+                    //{
+                    //    isError = true;
+                    //    uxMsgTb.Text = string.Format("ExpiryTime is too close or too early to the current time (60 seconds).");
+                    //}
 
                 }
                 catch (Exception ex)