Explorar el Código

2019/12/24 Jessica 7972
Actions:
1. 6 個 Profile 功能開發完成
2. 加入Reservation、SmartCharging、LocalAuthorization 觸發功能

Modified Files:
1.~\EVCB_OCPP.WSServer
2.~\TestTool.RemoteTriggerAPP

Jessica.Tseng hace 5 años
padre
commit
2e2c3d2541
Se han modificado 27 ficheros con 1888 adiciones y 349 borrados
  1. 8 2
      EVCB_OCPP.WSServer/App.config
  2. BIN
      EVCB_OCPP.WSServer/DLL/EVCB_OCPP.Domain.dll
  3. BIN
      EVCB_OCPP.WSServer/DLL/EVCB_OCPP.Packet.dll
  4. 9 2
      EVCB_OCPP.WSServer/EVCB_OCPP.WSServer.csproj
  5. 96 1
      EVCB_OCPP.WSServer/GlobalConfig.cs
  6. 5 5
      EVCB_OCPP.WSServer/Message/BasicMessageHandler.cs
  7. 63 70
      EVCB_OCPP.WSServer/Message/CoreProfileHandler.cs
  8. 207 0
      EVCB_OCPP.WSServer/Message/FirmwareManagementProfileHandler.cs
  9. 111 0
      EVCB_OCPP.WSServer/Message/LocalAuthListManagementProfileHandler.cs
  10. 0 15
      EVCB_OCPP.WSServer/Message/ProfileErrorHandler.cs
  11. 88 0
      EVCB_OCPP.WSServer/Message/RemoteTriggerHandler.cs
  12. 126 0
      EVCB_OCPP.WSServer/Message/ReservationProfileHandler.cs
  13. 135 0
      EVCB_OCPP.WSServer/Message/SmartChargingProfileHandler.cs
  14. 6 2
      EVCB_OCPP.WSServer/NLog.config
  15. 2 0
      EVCB_OCPP.WSServer/Program.cs
  16. 426 148
      EVCB_OCPP.WSServer/ProtalServer.cs
  17. 9 2
      EVCB_OCPP.WSServer/SuperSocket.Protocol/ClientData.cs
  18. 4 2
      EVCB_OCPP.WSServer/SuperSocket.Protocol/OCPPSubProtocol.cs
  19. 11 2
      EVCB_OCPP.WSServer/SuperSocket.Protocol/OCPPWSServer.cs
  20. 18 4
      TestTool.RemoteTriggerAPP/App.config
  21. BIN
      TestTool.RemoteTriggerAPP/DLL/EVCB_OCPP.Domain.dll
  22. BIN
      TestTool.RemoteTriggerAPP/DLL/EVCB_OCPP.Packet.dll
  23. 47 16
      TestTool.RemoteTriggerAPP/MainWindow.xaml
  24. 484 55
      TestTool.RemoteTriggerAPP/MainWindow.xaml.cs
  25. 22 17
      TestTool.RemoteTriggerAPP/Properties/Settings.Designer.cs
  26. 7 5
      TestTool.RemoteTriggerAPP/Properties/Settings.settings
  27. 4 1
      TestTool.RemoteTriggerAPP/TestTool.RemoteTriggerAPP.csproj

+ 8 - 2
EVCB_OCPP.WSServer/App.config

@@ -11,14 +11,20 @@
     <add name="MainDBContext" connectionString="data source=172.1.0.142\SQLEXPRESS;initial catalog=OCPP_MainDBContext;;persist security info=True;user id=sa;password=Ph0930118811;MultipleActiveResultSets=True;App=EntityFramework" providerName="System.Data.SqlClient" />
     <add name="MeterValueDBContext" connectionString="data source=172.1.0.142\SQLEXPRESS;initial catalog=OCPP_MeterValueDBContext;;persist security info=True;user id=sa;password=Ph0930118811;MultipleActiveResultSets=True;App=EntityFramework" providerName="System.Data.SqlClient" />
   </connectionStrings>
+  <appSettings>
+    <add key="ServerIP" value=""/>
+    <add key="WSPort" value="2017"/>
+    <add key="WSSPort" value="2013"/>
+  
+  </appSettings>
   <startup>
     <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.1" />
   </startup>
   <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>-->
+          <certificate filePath="localhost.pfx" password="supersocket" storeName="My" thumbprint="‎f42585bceed2cb049ef4a3c6d0ad572a6699f6f3" storeLocation="LocalMachine" clientCertificateRequired="false" keyStorageFlags="Exportable"></certificate> 
+        <!--<certificate filePath="phihongtest-net.pfx" password="y42j/4cj84" storeName="My" thumbprint="‎b4be1b6f0f4a4904f48d85c04f5c2b0005c64d76" storeLocation="LocalMachine" clientCertificateRequired="false" keyStorageFlags="Exportable"></certificate>-->
         <listeners></listeners>
       </server>
     </servers>

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


BIN
EVCB_OCPP.WSServer/DLL/EVCB_OCPP.Packet.dll


+ 9 - 2
EVCB_OCPP.WSServer/EVCB_OCPP.WSServer.csproj

@@ -89,9 +89,13 @@
     <Compile Include="Helper\Convertor.cs" />
     <Compile Include="Message\BasicMessageHandler.cs" />
     <Compile Include="Message\CoreProfileHandler.cs" />
+    <Compile Include="Message\FirmwareManagementProfileHandler.cs" />
+    <Compile Include="Message\LocalAuthListManagementProfileHandler.cs" />
     <Compile Include="Message\MessageResult.cs" />
     <Compile Include="Message\NeedConfirmMessage.cs" />
-    <Compile Include="Message\ProfileErrorHandler.cs" />
+    <Compile Include="Message\RemoteTriggerHandler.cs" />
+    <Compile Include="Message\ReservationProfileHandler.cs" />
+    <Compile Include="Message\SmartChargingProfileHandler.cs" />
     <Compile Include="Program.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />
     <Compile Include="ProtalServer.cs" />
@@ -106,13 +110,16 @@
     <Compile Include="SuperSocket.Protocol\OCPPWSServer.cs" />
   </ItemGroup>
   <ItemGroup>
-    <None Include="App.config" />
+    <None Include="App.config">
+      <SubType>Designer</SubType>
+    </None>
     <Content Include="DLL\SuperSocket.Common.dll" />
     <Content Include="DLL\SuperSocket.SocketBase.dll" />
     <Content Include="DLL\SuperSocket.SocketEngine.dll" />
     <Content Include="DLL\SuperWebSocket.dll" />
     <Content Include="NLog.config">
       <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+      <SubType>Designer</SubType>
     </Content>
     <None Include="NLog.xsd">
       <SubType>Designer</SubType>

+ 96 - 1
EVCB_OCPP.WSServer/GlobalConfig.cs

@@ -1,5 +1,6 @@
 using System;
 using System.Collections.Generic;
+using System.Configuration;
 using System.Linq;
 using System.Text;
 using System.Threading.Tasks;
@@ -8,9 +9,103 @@ namespace EVCB_OCPP.WSServer
 {
     public static class GlobalConfig
     {
+        public static List<string> ConfigKeys = new List<string>()
+        {
+            "WSPort",
+            "WSSPort",
+            ""
+        };
+
+
         /// <summary>
         /// 預設心跳間隔時間 單位:秒
         /// </summary>
-        public static readonly int DEFAULT_HEARTBEAT_INTERVAL=15;
+        private static int DEFAULT_HEARTBEAT_INTERVAL = 15;
+
+        /// <summary>
+        ///Server IP
+        /// </summary>
+        private static string ServerIP = "127.0.0.1";
+
+        /// <summary>
+        ///WS Port
+        /// </summary>
+        private static int WS_Port = 2012;
+
+
+        /// <summary>
+        ///WSS Port
+        /// </summary>
+        private static int WSS_Port = 2013;
+
+        /// <summary>
+        /// Load setting from app.config 
+        /// </summary>
+        public static bool  LoadAPPConfig()
+        {
+            bool result = false;
+            string key = string.Empty;
+            try
+            {
+               
+                for (int i = 0; i < ConfigKeys.Count; i++)
+                {
+                    key = ConfigKeys[i];
+                    switch(key)
+                    {
+                        case "WSPort":// convert to int type                       
+                            {
+                                var value = ConfigurationManager.AppSettings[key];
+
+                                WS_Port = Convert.ToInt32(value);
+                            }
+                            break;
+                        case "WSSPort":
+                            {
+                                var value = ConfigurationManager.AppSettings[key];
+
+                                WSS_Port = Convert.ToInt32(value);
+                            }
+                            break;
+                        default://convert to string type                             
+                            break;
+
+                    }
+                }
+                result = true;
+
+            }
+            catch (Exception ex)
+            {
+                Console.WriteLine(key + " Load from APPConfig "+ ex.ToString()); 
+              
+            }
+            
+            return result;
+        }
+
+
+
+        public static int GetWS_Port()
+        {
+            return WS_Port;
+        }
+
+
+        public static int GetWSS_Port()
+        {
+            return WSS_Port;
+        }
+
+        public static int GetHEARTBEAT_INTERVAL()
+        {
+            return DEFAULT_HEARTBEAT_INTERVAL;
+        }
+
+
+
+
+
+
     }
 }

+ 5 - 5
EVCB_OCPP.WSServer/Message/BasicMessageHandler.cs

@@ -101,7 +101,7 @@ namespace EVCB_OCPP.WSServer.Message
                                 }
                                 else
                                 {
-                                    string replyMsg = GenerateCallError(msg.Id, OCPPErrorCodes.NotImplemented, OCPPErrorDescription.NotImplemented);
+                                    string replyMsg = GenerateCallError(msg.Id, OCPPErrorCodes.OccurenceConstraintViolation, OCPPErrorDescription.OccurenceConstraintViolation);
                                     result.Id = TYPENUMBER_CALL;
                                     result.Message = request;
                                     result.Success = false;
@@ -136,8 +136,8 @@ namespace EVCB_OCPP.WSServer.Message
                                 }
                                 else
                                 {
-                                    string replyMsg = GenerateCallError(msg.Id, OCPPErrorCodes.NotImplemented.ToString(),
-                                   OCPPErrorDescription.NotImplemented);
+                                    string replyMsg = GenerateCallError(msg.Id, OCPPErrorCodes.OccurenceConstraintViolation.ToString(),
+                                   OCPPErrorDescription.OccurenceConstraintViolation);
                                     result.Id = TYPENUMBER_CALLRESULT;
                                     result.Message = confirmation;
                                     result.Success = false;
@@ -316,7 +316,7 @@ namespace EVCB_OCPP.WSServer.Message
             if (confirmation != null && confirmation.Validate())
             {
 
-                msg = string.Format(CALLRESULT_FORMAT, uniqueId, JsonConvert.SerializeObject(confirmation, new JsonSerializerSettings() {  NullValueHandling= NullValueHandling.Ignore}));
+                msg = string.Format(CALLRESULT_FORMAT, uniqueId, JsonConvert.SerializeObject(confirmation, new JsonSerializerSettings() {  NullValueHandling= NullValueHandling.Ignore, Formatting = Formatting.None }));
             }
             else
             {
@@ -331,7 +331,7 @@ namespace EVCB_OCPP.WSServer.Message
             if (request != null && request.Validate())
             {
 
-                msg = string.Format(CALL_FORMAT, uniqueId, action, JsonConvert.SerializeObject(request, new JsonSerializerSettings() { NullValueHandling = NullValueHandling.Ignore }));
+                msg = string.Format(CALL_FORMAT, uniqueId, action, JsonConvert.SerializeObject(request, new JsonSerializerSettings() { NullValueHandling = NullValueHandling.Ignore, Formatting = Formatting.None }));
             }
             else
             {

+ 63 - 70
EVCB_OCPP.WSServer/Message/CoreProfileHandler.cs

@@ -21,8 +21,7 @@ namespace EVCB_OCPP.WSServer.Message
 
     internal partial class ProfileHandler
     {
-        
-
+        int counnter = 0;
         internal MessageResult ExecuteCoreRequest(Actions action, ClientData session, IRequest request)
         {
             MessageResult result = new MessageResult() { Success = false };
@@ -33,7 +32,7 @@ namespace EVCB_OCPP.WSServer.Message
                 case Actions.BootNotification:
                     {
                         BootNotificationRequest _request = request as BootNotificationRequest;
-                        int heartbeat_interval = GlobalConfig.DEFAULT_HEARTBEAT_INTERVAL;
+                        int heartbeat_interval = GlobalConfig.GetHEARTBEAT_INTERVAL();
                         using (var db = new MainDBContext())
                         {
                             var _machine = db.Machine.Where(x => x.ChargeBoxId == session.ChargeBoxId).FirstOrDefault();
@@ -66,70 +65,74 @@ namespace EVCB_OCPP.WSServer.Message
                     {
                         //只保留最新上報狀況
                         StatusNotificationRequest _request = request as StatusNotificationRequest;
-                        List<string> removeIds = new List<string>();
-                        ConnectorErrorStauts _oldStatus = null;
-                        using (var oldDB = new MainDBContext())
-                        {
-                            if (_request.status == Packet.Messages.SubTypes.ChargePointStatus.Faulted)
-                            {
-                                _oldStatus = oldDB.ConnectorStatus.Where(x => x.ChargeBoxId == session.ChargeBoxId
-                             && x.ConnectorId == _request.connectorId).Select(x => new ConnectorErrorStauts
-                             {
-                                 Status = x.Status,
-                                 ChargePointErrorCodeId = x.ChargePointErrorCodeId,
-                                 ErrorInfo = x.ErrorInfo,
-                                 VendorId = x.VendorId,
-                                 VendorErrorCode = x.VendorErrorCode
-                             }).FirstOrDefault();
-                            }
 
-                            removeIds = oldDB.ConnectorStatus.Where(x => x.ChargeBoxId == session.ChargeBoxId
-                             && x.ConnectorId == _request.connectorId).Select(x => x.Id).ToList();
-                        }
-
-                        using (var db = new MainDBContext())
                         {
-                            foreach (var id in removeIds)
+                            List<string> removeIds = new List<string>();
+                            ConnectorErrorStauts _oldStatus = null;
+                            using (var oldDB = new MainDBContext())
                             {
+                                if (_request.status == Packet.Messages.SubTypes.ChargePointStatus.Faulted)
+                                {
+                                    _oldStatus = oldDB.ConnectorStatus.Where(x => x.ChargeBoxId == session.ChargeBoxId
+                                 && x.ConnectorId == _request.connectorId).Select(x => new ConnectorErrorStauts
+                                 {
+                                     Status = x.Status,
+                                     ChargePointErrorCodeId = x.ChargePointErrorCodeId,
+                                     ErrorInfo = x.ErrorInfo,
+                                     VendorId = x.VendorId,
+                                     VendorErrorCode = x.VendorErrorCode
+                                 }).FirstOrDefault();
+                                }
 
-                                string query = "DELETE FROM [dbo].[ConnectorStatus] WHERE [Id]={0} ";
-                                db.Database.ExecuteSqlCommand(query, id);
+                                removeIds = oldDB.ConnectorStatus.Where(x => x.ChargeBoxId == session.ChargeBoxId
+                                 && x.ConnectorId == _request.connectorId).Select(x => x.Id).ToList();
                             }
 
-                            db.SaveChanges();
-                            var _currentStatus = new Domain.Models.Database.ConnectorStatus()
+                            using (var db = new MainDBContext())
                             {
-                                ChargeBoxId = session.ChargeBoxId,
-                                ConnectorId = (byte)_request.connectorId,
-                                CreatedOn = _request.timestamp.HasValue ? _request.timestamp.Value : DateTime.Now,
-                                Status = (int)_request.status,
-                                ChargePointErrorCodeId = (int)_request.errorCode,
-                                ErrorInfo = _request.info,
-                                VendorId = _request.vendorId,
-                                VendorErrorCode = _request.vendorErrorCode,
-                                Id = Guid.NewGuid().ToString()
-                            };
-                            db.ConnectorStatus.Add(_currentStatus);
-
-                            if (_request.status == Packet.Messages.SubTypes.ChargePointStatus.Faulted)
-                            {
-                                db.MachineError.Add(new MachineError()
+                                foreach (var id in removeIds)
                                 {
+
+                                    string query = "DELETE FROM [dbo].[ConnectorStatus] WHERE [Id]={0} ";
+                                    db.Database.ExecuteSqlCommand(query, id);
+                                }
+
+                                db.SaveChanges();
+                                var _currentStatus = new Domain.Models.Database.ConnectorStatus()
+                                {
+                                    ChargeBoxId = session.ChargeBoxId,
                                     ConnectorId = (byte)_request.connectorId,
                                     CreatedOn = _request.timestamp.HasValue ? _request.timestamp.Value : DateTime.Now,
                                     Status = (int)_request.status,
-                                    ChargeBoxId = session.ChargeBoxId,
-                                    ErrorCodeId = (int)_request.errorCode,
+                                    ChargePointErrorCodeId = (int)_request.errorCode,
                                     ErrorInfo = _request.info,
-                                    PreStatus = _oldStatus.Status,
+                                    VendorId = _request.vendorId,
                                     VendorErrorCode = _request.vendorErrorCode,
-                                    VendorId = _request.vendorId
-                                });
-                            }
+                                    Id = Guid.NewGuid().ToString()
+                                };
+                                db.ConnectorStatus.Add(_currentStatus);
 
+                                if (_request.status == Packet.Messages.SubTypes.ChargePointStatus.Faulted)
+                                {
+                                    db.MachineError.Add(new MachineError()
+                                    {
+                                        ConnectorId = (byte)_request.connectorId,
+                                        CreatedOn = _request.timestamp.HasValue ? _request.timestamp.Value : DateTime.Now,
+                                        Status = (int)_request.status,
+                                        ChargeBoxId = session.ChargeBoxId,
+                                        ErrorCodeId = (int)_request.errorCode,
+                                        ErrorInfo = _request.info,
+                                        PreStatus = _oldStatus.Status,
+                                        VendorErrorCode = _request.vendorErrorCode,
+                                        VendorId = _request.vendorId
+                                    });
+                                }
 
-                            db.SaveChanges();
+
+                                db.SaveChanges();
+                            }
                         }
+
                         var confirm = new StatusNotificationConfirmation() { };
                         result.Message = confirm;
                         result.Success = true;
@@ -192,8 +195,6 @@ namespace EVCB_OCPP.WSServer.Message
                                     }
                                 }
                             }
-
-
                         }
 
                         var confirm = new MeterValuesConfirmation() { };
@@ -225,8 +226,6 @@ namespace EVCB_OCPP.WSServer.Message
                                 ReservationId = _request.reservationId.HasValue ? _request.reservationId.Value : 0,
                                 TransactionId = _tranId
 
-
-
                             });
 
                             db.SaveChanges();
@@ -237,7 +236,7 @@ namespace EVCB_OCPP.WSServer.Message
                         {
                             idTagInfo = new Packet.Messages.SubTypes.IdTagInfo()
                             {
-                                status = Packet.Messages.SubTypes.AuthorizationStatus.Accepted
+                                status = AuthorizationStatus.Accepted
                             },
                             transactionId = _tranId
 
@@ -315,22 +314,18 @@ namespace EVCB_OCPP.WSServer.Message
 
                             }
                         }
-
-
-
-
                     }
                     break;
                 case Actions.Authorize:
                     {
-                       
+
 
                         var confirm = new AuthorizeConfirmation()
                         {
 
                             idTagInfo = new Packet.Messages.SubTypes.IdTagInfo()
                             {
-                                status =  AuthorizationStatus.Accepted
+                                status = AuthorizationStatus.Accepted
                             }
                         };
                         result.Message = confirm;
@@ -366,6 +361,7 @@ namespace EVCB_OCPP.WSServer.Message
                                 operation.FinishedOn = DateTime.Now;
                                 operation.Status = 1;//電樁有回覆
                                 operation.EVSE_Status = (int)_confirm.status;
+                                operation.EVSE_Value = _confirm.status.ToString();
                                 db.SaveChanges();
                             }
 
@@ -387,6 +383,7 @@ namespace EVCB_OCPP.WSServer.Message
                                 operation.FinishedOn = DateTime.Now;
                                 operation.Status = 1;//電樁有回覆
                                 operation.EVSE_Status = (int)_confirm.status;
+                                operation.EVSE_Value = _confirm.status.ToString();
                                 db.SaveChanges();
                             }
 
@@ -407,6 +404,7 @@ namespace EVCB_OCPP.WSServer.Message
                                 operation.FinishedOn = DateTime.Now;
                                 operation.Status = 1;//電樁有回覆
                                 operation.EVSE_Status = (int)_confirm.status;
+                                operation.EVSE_Value = _confirm.status.ToString();
                                 db.SaveChanges();
                             }
 
@@ -427,6 +425,7 @@ namespace EVCB_OCPP.WSServer.Message
                                 operation.FinishedOn = DateTime.Now;
                                 operation.Status = 1;//電樁有回覆
                                 operation.EVSE_Status = (int)_confirm.status;
+                                operation.EVSE_Value = _confirm.status.ToString();
                                 db.SaveChanges();
                             }
 
@@ -447,6 +446,7 @@ namespace EVCB_OCPP.WSServer.Message
                                 operation.FinishedOn = DateTime.Now;
                                 operation.Status = 1;//電樁有回覆
                                 operation.EVSE_Status = (int)_confirm.status;
+                                operation.EVSE_Value = _confirm.status.ToString();
                                 db.SaveChanges();
                             }
 
@@ -458,8 +458,6 @@ namespace EVCB_OCPP.WSServer.Message
                         ChangeConfigurationConfirmation _confirm = confirm as ChangeConfigurationConfirmation;
                         ChangeConfigurationRequest _request = _confirm.GetRequest() as ChangeConfigurationRequest;
 
-
-
                         using (var db = new MainDBContext())
                         {
                             var operation = db.MachineOperateRecord.Where(x => x.SerialNo == requestId &&
@@ -495,12 +493,7 @@ namespace EVCB_OCPP.WSServer.Message
                                     });
                                 }
                             }
-
-
-
-
                             db.SaveChanges();
-
                         }
 
                     }
@@ -542,7 +535,7 @@ namespace EVCB_OCPP.WSServer.Message
                                 operation.FinishedOn = DateTime.Now;
                                 operation.Status = 1;//電樁有回覆
                                 operation.EVSE_Status = 1;
-                                operation.EVSE_Value = JsonConvert.SerializeObject(_confirm.configurationKey, Formatting.Indented);
+                                operation.EVSE_Value = JsonConvert.SerializeObject(_confirm.configurationKey, Formatting.None);
 
                             }
 

+ 207 - 0
EVCB_OCPP.WSServer/Message/FirmwareManagementProfileHandler.cs

@@ -0,0 +1,207 @@
+using EVCB_OCPP.Domain;
+using EVCB_OCPP.Domain.Models.Database;
+using EVCB_OCPP.Packet.Features;
+using EVCB_OCPP.Packet.Messages;
+using EVCB_OCPP.Packet.Messages.FirmwareManagement;
+using Newtonsoft.Json;
+using OCPPServer.Protocol;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Data.Entity;
+
+namespace EVCB_OCPP.WSServer.Message
+{
+    internal partial class ProfileHandler
+    {
+        internal MessageResult ExecuteFirmwareManagementRequest(Actions action, ClientData session, IRequest request)
+        {
+            MessageResult result = new MessageResult() { Success = false };
+
+            switch (action)
+            {
+
+                case Actions.FirmwareStatusNotification:
+                    {
+                        FirmwareStatusNotificationRequest _request = request as FirmwareStatusNotificationRequest;
+
+                        if (_request.status == Packet.Messages.SubTypes.FirmwareStatus.Idle)
+                        {
+                            string requestId = Guid.NewGuid().ToString();
+                            using (var db = new MainDBContext())
+                            {
+                                var machine = db.Machine.Where(x => x.FW_AssignedMachineVersionId.HasValue == true &&
+                                    x.FW_AssignedMachineVersionId != x.FW_VersionReport && x.ChargeBoxId == session.ChargeBoxId)
+                                    .Select(x => new { x.Id, x.FW_AssignedMachineVersionId }).FirstOrDefault();
+
+                                if (machine != null)
+                                {
+                                    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();
+
+                                    string downloadUrl = mv.PublishVersion.PublishVersionFiles.FirstOrDefault().UploadFile.FileUrl;
+
+                                    var _updateFWrequest = new UpdateFirmwareRequest()
+                                    {
+                                        location = new Uri(downloadUrl),
+                                        retries = 3,
+                                        retrieveDate = DateTime.Now,
+                                        retryInterval = 10
+                                    };
+                                    db.MachineOperateRecord.Add(new MachineOperateRecord()
+                                    {
+                                        CreatedOn = DateTime.Now,
+                                        ChargeBoxId = session.ChargeBoxId,
+                                        SerialNo = requestId,
+                                        RequestContent = JsonConvert.SerializeObject(_updateFWrequest, new JsonSerializerSettings() { NullValueHandling = NullValueHandling.Ignore, Formatting = Formatting.None }),
+                                        EVSE_Status = 0,
+                                        EVSE_Value = "Fw Version:" + machine.FW_AssignedMachineVersionId,
+                                        Status = 0,
+                                        RequestType = 0,
+
+                                    });
+
+                                    db.ServerMessage.Add(new ServerMessage()
+                                    {
+                                        ChargeBoxId = session.ChargeBoxId,
+                                        CreatedBy = "Server",
+                                        CreatedOn = DateTime.Now,
+                                        OutAction = _updateFWrequest.Action.ToString(),
+                                        OutRequest = JsonConvert.SerializeObject(_updateFWrequest, new JsonSerializerSettings() { NullValueHandling = NullValueHandling.Ignore, Formatting = Formatting.None }),
+                                        SerialNo = requestId,
+                                        InMessage = string.Empty
+
+                                    });
+
+                                    db.SaveChanges();
+
+                                }
+
+                            }
+                        }
+                        else
+                        {
+                            using (var db = new MainDBContext())
+                            {
+                                var item = db.MachineOperateRecord.Where(x => x.ChargeBoxId == session.ChargeBoxId && x.RequestType == 0)
+                                    .OrderByDescending(x => x.CreatedOn).FirstOrDefault();
+
+                                item.EVSE_Status = (int)_request.status;
+                                item.FinishedOn = DateTime.Now;
+
+                                if (!string.IsNullOrEmpty(item.EVSE_Value) && _request.status == Packet.Messages.SubTypes.FirmwareStatus.Installed)
+                                {
+                                    int version = 0;
+                                    int.TryParse(item.EVSE_Value.Split(':').Last(), out version);
+                                    var machine = db.Machine.Where(x => x.ChargeBoxId == session.ChargeBoxId).FirstOrDefault();
+                                    machine.FW_VersionReport = version;
+                                }
+
+                                db.SaveChanges();
+                            }
+                        }
+
+                        var confirm = new FirmwareStatusNotificationConfirmation() { };
+
+                        result.Message = confirm;
+                        result.Success = true;
+                    }
+                    break;
+                case Actions.DiagnosticsStatusNotification:
+                    {
+                        DiagnosticsStatusNotificationRequest _request = request as DiagnosticsStatusNotificationRequest;
+
+                        var confirm = new DiagnosticsStatusNotificationConfirmation() { };
+
+                        result.Message = confirm;
+                        result.Success = true;
+
+                    }
+                    break;
+
+                default:
+                    {
+                        Console.WriteLine(string.Format("Not Implement {0} Logic", request.GetType().ToString().Replace("OCPPPackage.Messages.FirmwareManagement.", "")));
+                    }
+                    break;
+            }
+            return result;
+        }
+
+        internal MessageResult ExecuteFirmwareManagementConfirm(Actions action, ClientData session, IConfirmation confirm, string requestId)
+        {
+            MessageResult result = new MessageResult() { Success = true };
+
+            switch (action)
+            {
+                case Actions.UpdateFirmware:
+                case Actions.GetDiagnostics:
+                    {
+                        using (var db = new MainDBContext())
+                        {
+                            var operation = db.MachineOperateRecord.Where(x => x.SerialNo == requestId &&
+                            x.ChargeBoxId == session.ChargeBoxId && x.Status == 0).FirstOrDefault();
+                            if (operation != null)
+                            {
+                                operation.FinishedOn = DateTime.Now;
+                                operation.Status = 1;//電樁有回覆
+                                operation.EVSE_Status = (int)1;//OK
+                                db.SaveChanges();
+                            }
+
+                        }
+                    }
+                    break;
+                default:
+                    {
+                        Console.WriteLine(string.Format("Not Implement {0} Logic", confirm.GetType().ToString().Replace("OCPPPackage.Messages.FirmwareManagement.", "")));
+                    }
+                    break;
+            }
+            return result;
+        }
+
+
+        internal MessageResult ReceivedFirmwareManagementError(Actions action, string errorMsg, ClientData session, string requestId)
+        {
+            MessageResult result = new MessageResult() { Success = true };
+
+            switch (action)
+            {
+                case Actions.FirmwareStatusNotification:
+                case Actions.UpdateFirmware:
+                case Actions.GetDiagnostics:
+                case Actions.DiagnosticsStatusNotification:
+                    {
+                        using (var db = new MainDBContext())
+                        {
+                            var operation = db.MachineOperateRecord.Where(x => x.SerialNo == requestId &&
+                            x.ChargeBoxId == session.ChargeBoxId && x.Status == 0).FirstOrDefault();
+                            if (operation != null)
+                            {
+                                operation.FinishedOn = DateTime.Now;
+                                operation.Status = 1;//電樁有回覆
+                                operation.EVSE_Status = (int)255;//錯誤
+                                operation.EVSE_Value = errorMsg;
+                                db.SaveChanges();
+                            }
+
+                        }
+                    }
+                    break;
+
+                default:
+                    {
+                        Console.WriteLine(string.Format("Not Implement {0} Logic", action));
+                    }
+                    break;
+            }
+            return result;
+
+        }
+    }
+}

+ 111 - 0
EVCB_OCPP.WSServer/Message/LocalAuthListManagementProfileHandler.cs

@@ -0,0 +1,111 @@
+using EVCB_OCPP.Domain;
+using EVCB_OCPP.Packet.Features;
+using EVCB_OCPP.Packet.Messages;
+using EVCB_OCPP.Packet.Messages.LocalAuthListManagement;
+using OCPPServer.Protocol;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace EVCB_OCPP.WSServer.Message
+{
+    internal partial class ProfileHandler
+    {
+
+
+
+
+        internal MessageResult ExecuteLocalAuthListManagementConfirm(Actions action, ClientData session, IConfirmation confirm, string requestId)
+        {
+            MessageResult result = new MessageResult() { Success = true };
+
+            switch (action)
+            {
+                case Actions.GetLocalListVersion:
+                    {
+                        GetLocalListVersionConfirmation _confirm = confirm as GetLocalListVersionConfirmation;
+                        GetLocalListVersionRequest _request = _confirm.GetRequest() as GetLocalListVersionRequest;
+                        using (var db = new MainDBContext())
+                        {
+                            var operation = db.MachineOperateRecord.Where(x => x.SerialNo == requestId &&
+                            x.ChargeBoxId == session.ChargeBoxId && x.Status == 0).FirstOrDefault();
+                            if (operation != null)
+                            {
+                                operation.FinishedOn = DateTime.Now;
+                                operation.Status = 1;//電樁有回覆
+                                operation.EVSE_Status = 1;//OK
+                                operation.EVSE_Value = _confirm.listVersion.ToString();
+                                db.SaveChanges();
+                            }
+
+                        }
+                    }
+                    break;
+                case Actions.SendLocalList:
+                    {
+                        SendLocalListConfirmation _confirm = confirm as SendLocalListConfirmation;
+                        SendLocalListRequest _request = _confirm.GetRequest() as SendLocalListRequest;
+                        using (var db = new MainDBContext())
+                        {
+                            var operation = db.MachineOperateRecord.Where(x => x.SerialNo == requestId &&
+                            x.ChargeBoxId == session.ChargeBoxId && x.Status == 0).FirstOrDefault();
+                            if (operation != null)
+                            {
+                                operation.FinishedOn = DateTime.Now;
+                                operation.Status = 1;//電樁有回覆
+                                operation.EVSE_Status = (int)_confirm.updateStatus;//OK                              
+                                db.SaveChanges();
+                            }
+
+                        }
+                    }
+                    break;
+                default:
+                    {
+                        Console.WriteLine(string.Format("Not Implement {0} Logic", confirm.GetType().ToString().Replace("OCPPPackage.Messages.RemoteTrigger.", "")));
+                    }
+                    break;
+            }
+            return result;
+        }
+
+
+        internal MessageResult ReceivedLocalAuthListManagementError(Actions action, string errorMsg, ClientData session, string requestId)
+        {
+            MessageResult result = new MessageResult() { Success = true };
+
+            switch (action)
+            {
+                case Actions.SendLocalList:
+                case Actions.GetLocalListVersion:
+                    {
+                        using (var db = new MainDBContext())
+                        {
+                            var operation = db.MachineOperateRecord.Where(x => x.SerialNo == requestId &&
+                            x.ChargeBoxId == session.ChargeBoxId && x.Status == 0).FirstOrDefault();
+                            if (operation != null)
+                            {
+                                operation.FinishedOn = DateTime.Now;
+                                operation.Status = 1;//電樁有回覆
+                                operation.EVSE_Status = (int)255;//錯誤
+                                operation.EVSE_Value = errorMsg;
+                                db.SaveChanges();
+                            }
+
+                        }
+                    }
+                    break;
+
+                default:
+                    {
+                        Console.WriteLine(string.Format("Not Implement {0} Logic", action));
+                    }
+                    break;
+            }
+            return result;
+
+        }
+    }
+}

+ 0 - 15
EVCB_OCPP.WSServer/Message/ProfileErrorHandler.cs

@@ -1,15 +0,0 @@
-using EVCB_OCPP.Packet.Messages;
-using OCPPServer.Protocol;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace EVCB_OCPP.WSServer.Message
-{
-    internal partial class ProfileHandler
-    {
-       
-    }
-}

+ 88 - 0
EVCB_OCPP.WSServer/Message/RemoteTriggerHandler.cs

@@ -0,0 +1,88 @@
+using EVCB_OCPP.Domain;
+using EVCB_OCPP.Packet.Features;
+using EVCB_OCPP.Packet.Messages;
+using EVCB_OCPP.Packet.Messages.RemoteTrigger;
+using OCPPServer.Protocol;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace EVCB_OCPP.WSServer.Message
+{
+    internal partial class ProfileHandler
+    {
+      
+
+        internal MessageResult ExecuteRemoteTriggerConfirm(Actions action, ClientData session, IConfirmation confirm, string requestId)
+        {
+            MessageResult result = new MessageResult() { Success = true };
+
+            switch (action)
+            {
+                case Actions.TriggerMessage:               
+                    {
+                        TriggerMessageConfirmation _confirm = confirm as TriggerMessageConfirmation;
+                        TriggerMessageRequest _request = _confirm.GetRequest() as TriggerMessageRequest;
+                        using (var db = new MainDBContext())
+                        {
+                            var operation = db.MachineOperateRecord.Where(x => x.SerialNo == requestId &&
+                            x.ChargeBoxId == session.ChargeBoxId && x.Status == 0).FirstOrDefault();
+                            if (operation != null)
+                            {
+                                operation.FinishedOn = DateTime.Now;
+                                operation.Status = 1;//電樁有回覆
+                                operation.EVSE_Status = (int)_confirm.status;//OK
+                                db.SaveChanges();
+                            }
+
+                        }
+                    }
+                    break;
+                default:
+                    {
+                        Console.WriteLine(string.Format("Not Implement {0} Logic", confirm.GetType().ToString().Replace("OCPPPackage.Messages.RemoteTrigger.", "")));
+                    }
+                    break;
+            }
+            return result;
+        }
+
+
+        internal MessageResult ReceivedRemoteTriggerError(Actions action, string errorMsg, ClientData session, string requestId)
+        {
+            MessageResult result = new MessageResult() { Success = true };
+
+            switch (action)
+            {
+                case Actions.TriggerMessage:               
+                    {
+                        using (var db = new MainDBContext())
+                        {
+                            var operation = db.MachineOperateRecord.Where(x => x.SerialNo == requestId &&
+                            x.ChargeBoxId == session.ChargeBoxId && x.Status == 0).FirstOrDefault();
+                            if (operation != null)
+                            {
+                                operation.FinishedOn = DateTime.Now;
+                                operation.Status = 1;//電樁有回覆
+                                operation.EVSE_Status = (int)255;//錯誤
+                                operation.EVSE_Value = errorMsg;
+                                db.SaveChanges();
+                            }
+
+                        }
+                    }
+                    break;
+
+                default:
+                    {
+                        Console.WriteLine(string.Format("Not Implement {0} Logic", action));
+                    }
+                    break;
+            }
+            return result;
+
+        }
+    }
+}

+ 126 - 0
EVCB_OCPP.WSServer/Message/ReservationProfileHandler.cs

@@ -0,0 +1,126 @@
+using EVCB_OCPP.Domain;
+using EVCB_OCPP.Packet.Features;
+using EVCB_OCPP.Packet.Messages;
+using EVCB_OCPP.Packet.Messages.Reservation;
+using OCPPServer.Protocol;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace EVCB_OCPP.WSServer.Message
+{
+    internal partial class ProfileHandler
+    {
+        
+
+        internal MessageResult ExecuteReservationConfirm(Actions action, ClientData session, IConfirmation confirm, string requestId)
+        {
+            MessageResult result = new MessageResult() { Success = true };
+
+            switch (action)
+            {
+                case Actions.ReserveNow:
+                    {
+                        ReserveNowConfirmation _confirm = confirm as ReserveNowConfirmation;
+                        ReserveNowRequest _request = _confirm.GetRequest() as ReserveNowRequest;
+                        using (var db = new MainDBContext())
+                        {
+                            var operation = db.MachineOperateRecord.Where(x => x.SerialNo == requestId &&
+                            x.ChargeBoxId == session.ChargeBoxId && x.Status == 0).FirstOrDefault();
+                            if (operation != null)
+                            {
+                                operation.FinishedOn = DateTime.Now;
+                                operation.Status = 1;//電樁有回覆
+                                operation.EVSE_Status = (int)_confirm.status;//OK
+                                db.SaveChanges();
+                            }
+
+                        }
+                    }
+                    break;
+                case Actions.CancelReservation:
+                    {
+                        CancelReservationConfirmation _confirm = confirm as CancelReservationConfirmation;
+                        CancelReservationRequest _request = _confirm.GetRequest() as CancelReservationRequest;
+                        using (var db = new MainDBContext())
+                        {
+                            var operation = db.MachineOperateRecord.Where(x => x.SerialNo == requestId &&
+                            x.ChargeBoxId == session.ChargeBoxId && x.Status == 0).FirstOrDefault();
+                            if (operation != null)
+                            {
+                                operation.FinishedOn = DateTime.Now;
+                                operation.Status = 1;//電樁有回覆
+                                operation.EVSE_Status = (int)_confirm.status;//OK
+                                db.SaveChanges();
+                            }
+
+                        }
+                    }
+                    break;
+                default:
+                    {
+                        Console.WriteLine(string.Format("Not Implement {0} Logic", confirm.GetType().ToString().Replace("OCPPPackage.Messages.RemoteTrigger.", "")));
+                    }
+                    break;
+            }
+            return result;
+        }
+
+
+        internal MessageResult ExecuteReservationError(Actions action, string errorMsg, ClientData session, string requestId)
+        {
+            MessageResult result = new MessageResult() { Success = true };
+
+            switch (action)
+            {
+                case Actions.ReserveNow:
+                    {
+                        using (var db = new MainDBContext())
+                        {
+                            var operation = db.MachineOperateRecord.Where(x => x.SerialNo == requestId &&
+                            x.ChargeBoxId == session.ChargeBoxId && x.Status == 0).FirstOrDefault();
+                            if (operation != null)
+                            {
+                                operation.FinishedOn = DateTime.Now;
+                                operation.Status = 1;//電樁有回覆
+                                operation.EVSE_Status = (int)255;//錯誤
+                                operation.EVSE_Value = errorMsg;
+                                db.SaveChanges();
+                            }
+
+                        }
+                    }
+                    break;
+                case Actions.CancelReservation:
+                    {
+                        using (var db = new MainDBContext())
+                        {
+                            var operation = db.MachineOperateRecord.Where(x => x.SerialNo == requestId &&
+                            x.ChargeBoxId == session.ChargeBoxId && x.Status == 0).FirstOrDefault();
+                            if (operation != null)
+                            {
+                                operation.FinishedOn = DateTime.Now;
+                                operation.Status = 1;//電樁有回覆
+                                operation.EVSE_Status = (int)255;//錯誤
+                                operation.EVSE_Value = errorMsg;
+                                db.SaveChanges();
+                            }
+
+                        }
+                    }
+                    break;
+
+
+                default:
+                    {
+                        Console.WriteLine(string.Format("Not Implement {0} Logic", action));
+                    }
+                    break;
+            }
+            return result;
+
+        }
+    }
+}

+ 135 - 0
EVCB_OCPP.WSServer/Message/SmartChargingProfileHandler.cs

@@ -0,0 +1,135 @@
+using EVCB_OCPP.Domain;
+using EVCB_OCPP.Packet.Features;
+using EVCB_OCPP.Packet.Messages;
+using EVCB_OCPP.Packet.Messages.SmartCharging;
+using Newtonsoft.Json;
+using OCPPServer.Protocol;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace EVCB_OCPP.WSServer.Message
+{
+    internal partial class ProfileHandler
+    {
+
+
+
+
+
+
+        internal MessageResult ExecuteSmartChargingConfirm(Actions action, ClientData session, IConfirmation confirm, string requestId)
+        {
+            MessageResult result = new MessageResult() { Success = true };
+
+            switch (action)
+            {
+                case Actions.ClearChargingProfile:
+
+                    {
+                        ClearChargingProfileConfirmation _confirm = confirm as ClearChargingProfileConfirmation;
+                        ClearChargingProfileRequest _request = _confirm.GetRequest() as ClearChargingProfileRequest;
+                        using (var db = new MainDBContext())
+                        {
+                            var operation = db.MachineOperateRecord.Where(x => x.SerialNo == requestId &&
+                            x.ChargeBoxId == session.ChargeBoxId && x.Status == 0).FirstOrDefault();
+                            if (operation != null)
+                            {
+                                operation.FinishedOn = DateTime.Now;
+                                operation.Status = 1;//電樁有回覆
+                                operation.EVSE_Status = (int)_confirm.status;//OK
+                                db.SaveChanges();
+                            }
+
+                        }
+                    }
+                    break;
+                case Actions.SetChargingProfile:
+                    {
+                        SetChargingProfileConfirmation _confirm = confirm as SetChargingProfileConfirmation;
+                        SetChargingProfileRequest _request = _confirm.GetRequest() as SetChargingProfileRequest;
+                        using (var db = new MainDBContext())
+                        {
+                            var operation = db.MachineOperateRecord.Where(x => x.SerialNo == requestId &&
+                            x.ChargeBoxId == session.ChargeBoxId && x.Status == 0).FirstOrDefault();
+                            if (operation != null)
+                            {
+                                operation.FinishedOn = DateTime.Now;
+                                operation.Status = 1;//電樁有回覆
+                                operation.EVSE_Status = (int)_confirm.status;//OK
+                                db.SaveChanges();
+                            }
+
+                        }
+                    }
+                    break;
+                case Actions.GetCompositeSchedule:
+                    {
+                        GetCompositeScheduleConfirmation _confirm = confirm as GetCompositeScheduleConfirmation;
+                        GetCompositeScheduleRequest _request = _confirm.GetRequest() as GetCompositeScheduleRequest;
+                        using (var db = new MainDBContext())
+                        {
+                            var operation = db.MachineOperateRecord.Where(x => x.SerialNo == requestId &&
+                            x.ChargeBoxId == session.ChargeBoxId && x.Status == 0).FirstOrDefault();
+                            if (operation != null)
+                            {
+                                operation.FinishedOn = DateTime.Now;
+                                operation.Status = 1;//電樁有回覆
+                                operation.EVSE_Status = (int)_confirm.status;//OK
+                                operation.EVSE_Value= JsonConvert.SerializeObject(_confirm.chargingSchedule, Formatting.None);
+                                db.SaveChanges();
+                            }
+
+                        }
+                    }
+                    break;
+                default:
+                    {
+                        Console.WriteLine(string.Format("Not Implement {0} Logic", confirm.GetType().ToString().Replace("OCPPPackage.Messages.RemoteTrigger.", "")));
+                    }
+                    break;
+            }
+            return result;
+        }
+
+
+        internal MessageResult ReceivedSmartChargingError(Actions action, string errorMsg, ClientData session, string requestId)
+        {
+            MessageResult result = new MessageResult() { Success = true };
+
+            switch (action)
+            {
+                case Actions.ClearChargingProfile:
+                case Actions.SetChargingProfile:
+                case Actions.GetCompositeSchedule:
+                    {
+                        using (var db = new MainDBContext())
+                        {
+                            var operation = db.MachineOperateRecord.Where(x => x.SerialNo == requestId &&
+                            x.ChargeBoxId == session.ChargeBoxId && x.Status == 0).FirstOrDefault();
+                            if (operation != null)
+                            {
+                                operation.FinishedOn = DateTime.Now;
+                                operation.Status = 1;//電樁有回覆
+                                operation.EVSE_Status = (int)255;//錯誤
+                                operation.EVSE_Value = errorMsg;
+                                db.SaveChanges();
+                            }
+
+                        }
+                    }
+                    break;
+
+                default:
+                    {
+                        Console.WriteLine(string.Format("Not Implement {0} Logic", action));
+                    }
+                    break;
+            }
+            return result;
+
+        }
+    }
+}

+ 6 - 2
EVCB_OCPP.WSServer/NLog.config

@@ -15,7 +15,7 @@
   See https://github.com/nlog/nlog/wiki/Configuration-file
   for information on customizing logging rules and outputs.
    -->
-  <targets>
+  <targets> 
 
     <!--
     add your targets here
@@ -30,8 +30,11 @@
     -->
    <target xsi:type="File" name="f" fileName="${basedir}/logs/${shortdate}.log"
             layout="${longdate} ${uppercase:${level}} ${message}" />
+    <target xsi:type="Console" name="Console"
+            layout="${longdate} ${uppercase:${level}} ${message}" />
+ 
+ 
   </targets>
-
   <rules>
     <!-- add your logging rules here -->
 
@@ -40,5 +43,6 @@
     <logger name="*" minlevel="Debug" writeTo="f" />
     -->
     <logger name="*" minlevel="Debug" writeTo="f" />
+    <logger name="*" minlevel="Debug" writeTo="Console" />
   </rules>
 </nlog>

+ 2 - 0
EVCB_OCPP.WSServer/Program.cs

@@ -13,6 +13,8 @@ namespace EVCB_OCPP.WSServer
             ProtalServer s = new ProtalServer();
             Console.WriteLine("Starting Server...");
             s.Start();
+
+            Console.Read();
         }
     }
 }

+ 426 - 148
EVCB_OCPP.WSServer/ProtalServer.cs

@@ -24,29 +24,50 @@ using OCPPPackage.Profiles;
 using System.Threading.Tasks;
 using EVCB_OCPP.WSServer.Helper;
 using System.Data.SqlClient;
+using EVCB_OCPP.Packet.Messages.FirmwareManagement;
+using EVCB_OCPP.Packet.Messages.RemoteTrigger;
+using System.Configuration;
+using System.Net;
+using System.Net.Security;
+using System.Security.Cryptography.X509Certificates;
 
 namespace EVCB_OCPP.WSServer
 {
     internal class ProtalServer
     {
-
-        internal Dictionary<string, ClientData> ClientDic = new Dictionary<string, ClientData>();
         static private ILogger logger = NLog.LogManager.GetCurrentClassLogger();
+
+        private Dictionary<string, ClientData> ClientDic = new Dictionary<string, ClientData>();
         private readonly Object _lockClientDic = new object();
         private readonly Object _lockConfirmPacketList = new object();
-        ProfileHandler _profileHandler = new ProfileHandler();
+        private ProfileHandler _profileHandler = new ProfileHandler();
         private List<NeedConfirmMessage> NeedConfirmPacketList = new List<NeedConfirmMessage>();
+        private DateTime checkUpdateDt = DateTime.Now;
         private List<string> _needConfirmActions = new List<string>()
         {
-            "GetConfiguration",
-            "ChangeConfiguration",
-            "RemoteStartTransaction",
-            "RemoteStopTransaction",
-            "ChangeAvailability",
-            "ClearCache",
-            "DataTransfer",
-            "Reset",
+             "GetConfiguration",
+             "ChangeConfiguration",
+             "RemoteStartTransaction",
+             "RemoteStopTransaction",
+             "ChangeAvailability",
+             "ClearCache",
+             "DataTransfer",
+             "Reset",
              "UnlockConnector",
+             "TriggerMessage",
+             "GetDiagnostics",
+             "UpdateFirmware",
+             "GetLocalListVersion",
+             "SendLocalList",
+             "SetChargingProfile",
+             "ClearChargingProfile",
+             "GetCompositeSchedule",
+             "ReserveNow",
+             "CancelReservation",
+
+
+
+
 
 
         };
@@ -62,20 +83,30 @@ namespace EVCB_OCPP.WSServer
         private CancellationTokenSource _cts = new CancellationTokenSource();
         private CancellationToken _ct;
 
+
         internal ProtalServer()
         {
             _ct = _cts.Token;
-
+            WarmUpLog();
         }
 
 
         internal void Start()
         {
+
+            if (!GlobalConfig.LoadAPPConfig())
+            {
+                Console.WriteLine("Please check App.Config setting .");
+                return;
+            }
+
             OpenNetwork();
 
+            Task serverCommandTask = new Task(ServerMessageTrigger, _ct);
+            serverCommandTask.Start();
 
-            Task taskServerCommand = new Task(ServerMessageTrigger, _ct);
-            taskServerCommand.Start();
+            Task serverUpdateTask = new Task(ServerUpdateTrigger, _ct);
+            serverUpdateTask.Start();
 
             while (true)
             {
@@ -84,7 +115,8 @@ namespace EVCB_OCPP.WSServer
                 switch (input.ToLower())
                 {
                     case "stop":
-
+                        logger.Info("Command stop");
+                        Stop();
                         break;
 
                     case "gc":
@@ -93,15 +125,43 @@ namespace EVCB_OCPP.WSServer
                         break;
 
                     case "lc":
-                        logger.Info("Command List Clients");
+                        {
+                            logger.Info("Command List Clients");
+                            Dictionary<string, ClientData> _copyClientDic = null;
+                            lock (_lockClientDic)
+                            {
+                                _copyClientDic = new Dictionary<string, ClientData>(ClientDic);
 
-                        break;
+                            }
+                            var list = _copyClientDic.Select(c => c.Value).ToList();
+                            int i = 1;
+                            foreach (var c in list)
+                            {
+                                logger.Info(i + ":" + c.ChargeBoxId);
+                                i++;
+                            }
 
+                        }
+                        break;
                     case "lcn":
-                        logger.Info("Command List Customer Name");
+                        {
+                            logger.Info("Command List Customer Name");
+                            Dictionary<string, ClientData> _copyClientDic = null;
+                            lock (_lockClientDic)
+                            {
+                                _copyClientDic = new Dictionary<string, ClientData>(ClientDic);
 
-                        break;
+                            }
+                            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");
@@ -110,9 +170,8 @@ namespace EVCB_OCPP.WSServer
                         logger.Info("cls : clear console");
                         logger.Info("silent : silent");
                         logger.Info("show : show log");
-                        logger.Info("rcl : show Real Connection Limit");
+                        // logger.Info("rcl : show Real Connection Limit");
                         break;
-
                     case "cls":
                         logger.Info("Command clear");
                         Console.Clear();
@@ -130,7 +189,6 @@ namespace EVCB_OCPP.WSServer
                         }
                         xe.Save("NLog.config");
                         break;
-
                     case "show":
                         logger.Info("Command show");
                         var xe1 = XElement.Load("NLog.config");
@@ -143,31 +201,51 @@ namespace EVCB_OCPP.WSServer
                         }
                         xe1.Save("NLog.config");
                         break;
-
                     case "rcl":
-
-
                         break;
-
                     default:
                         break;
                 }
             }
         }
 
-        private void InitEVSEConfigure(string sn)
+        internal void Stop()
         {
-            List<MachineConfigure> configures = new List<MachineConfigure>();
-            configures.Add(new MachineConfigure() { ConfigureName = StandardConfiguration.AuthorizeRemoteTxRequests, ConfigureSetting = "" });
+            if (_cts != null)
+            {
+                _cts.Cancel();
+            }
+        }
+
+        private void CheckEVSEConfigure(string chargeBoxId)
+        {
+
+
             using (var db = new MainDBContext())
             {
-                var _sn = db.MachineConfigure.Where(x => x.ChargeBoxId == sn).Select(x => x.ChargeBoxId).FirstOrDefault();
+
+                var _sn = db.MachineConfigure.Where(x => x.ChargeBoxId == chargeBoxId).Select(x => x.ChargeBoxId).FirstOrDefault();
                 if (string.IsNullOrEmpty(_sn))
                 {
-                    db.MachineConfigure.Add(new MachineConfigure()
+                    db.ServerMessage.Add(new ServerMessage()
                     {
+                        ChargeBoxId = chargeBoxId,
+                        CreatedBy = "Server",
+                        CreatedOn = DateTime.Now,
+                        OutAction = Actions.GetConfiguration.ToString(),
+                        OutRequest = JsonConvert.SerializeObject(
+                            new GetConfigurationRequest()
+                            {
+                                key = new List<string>()
+
+                            },
+                            new JsonSerializerSettings() { NullValueHandling = NullValueHandling.Ignore, Formatting = Formatting.None }),
+                        SerialNo = Guid.NewGuid().ToString(),
+                        InMessage = string.Empty
 
                     });
+
+                    db.SaveChanges();
                 }
             }
         }
@@ -175,14 +253,17 @@ namespace EVCB_OCPP.WSServer
 
         private void OpenNetwork()
         {
+
             //載入OCPP Protocol
-            var appServer = new OCPPWSServer(new OCPPSubProtocol());
+            var appServer = new OCPPWSServer(new List<OCPPSubProtocol>() { new OCPPSubProtocol(), new OCPPSubProtocol(" ocpp1.6") });
 
             List<IListenerConfig> llistener = new List<IListenerConfig>();
-
+            //System.Net.IPAddress.Any.ToString()
             // llistener.Add(new ListenerConfig { Ip = "", Port = Convert.ToInt32(wssserverPort), Backlog = 100, Security = serverSecurity });
-            llistener.Add(new ListenerConfig { Ip = "172.17.40.13", Port = Convert.ToInt32(2012), Backlog = 100, Security = "None" });
-
+            llistener.Add(new ListenerConfig { Ip = System.Net.IPAddress.Any.ToString(), Port = Convert.ToInt32(GlobalConfig.GetWS_Port()), Backlog = 100, Security = "None" });
+            llistener.Add(new ListenerConfig { Ip = System.Net.IPAddress.Any.ToString(), Port = Convert.ToInt32(GlobalConfig.GetWSS_Port()), Backlog = 100, Security = "tls" });
+            var config = ConfigurationManager.GetSection("superSocket") as IConfigurationSource;
+            ICertificateConfig Certificate = config.Servers.ElementAt(0).Certificate;
             IEnumerable<IListenerConfig> listeners = llistener;
 
             //設定server config
@@ -192,8 +273,9 @@ namespace EVCB_OCPP.WSServer
                 //Ip = "172.17.40.13",
                 MaxRequestLength = 4096,
                 //Security = serverSecurity,
-                // Certificate = Certificate,
-                Listeners = listeners
+                Certificate = Certificate,
+                Listeners = listeners,
+
 
             };
 
@@ -218,6 +300,7 @@ namespace EVCB_OCPP.WSServer
 
         private void AppServer_SessionClosed(ClientData session, CloseReason value)
         {
+            Console.WriteLine(session.RemoteEndPoint.Address);
             WriteMachineLog(session.ChargeBoxId, string.Format("CloseReason: {0}", value), "Connection", "");
             RemoveClient(session);
             // close Connection
@@ -225,6 +308,7 @@ namespace EVCB_OCPP.WSServer
 
         private void AppServer_NewSessionConnected(ClientData session)
         {
+            Console.WriteLine("------------New");
             session.m_ReceiveData += new ClientData.OCPPClientDataEventHandler<ClientData, String>(ReceivedMessage);
             try
             {
@@ -238,12 +322,14 @@ namespace EVCB_OCPP.WSServer
                         RemoveClient(_removeClient);
                     }
                     ClientDic.Add(session.ChargeBoxId, session);
+                 
+                    Console.WriteLine("------------New" + (session == null ? "Oops" : session.ChargeBoxId));
                     WriteMachineLog(session.ChargeBoxId, "", "Connection", "");
                 }
             }
             catch (Exception ex)
             {
-
+                logger.Error(string.Format("NewSessionConnected Ex: {0}", ex.ToString()));
             }
 
 
@@ -257,14 +343,14 @@ namespace EVCB_OCPP.WSServer
 
 
             WriteMachineLog(session.ChargeBoxId, rawdata,
-                string.Format("{0} {1}", analysisResult.Action, analysisResult.Id == 2 ? "Request" : (analysisResult.Id == 3 ? "Confirmation" : "Error")));
+                string.Format("{0} {1}", string.IsNullOrEmpty(analysisResult.Action) ? "unknown" : analysisResult.Action, analysisResult.Id == 2 ? "Request" : (analysisResult.Id == 3 ? "Confirmation" : "Error")));
 
             if (analysisResult.Success == false)
             {
                 //解析RawData就發生錯誤
                 if (!string.IsNullOrEmpty(analysisResult.CallErrorMsg))
                 {
-                    Send(session, rawdata, string.Format("{0} {1}", analysisResult.Action, "Error"));
+                    Send(session, analysisResult.CallErrorMsg, string.Format("{0} {1}", analysisResult.Action, "Error"));
                 }
                 else
                 {
@@ -334,87 +420,8 @@ namespace EVCB_OCPP.WSServer
                 {
                     case "Core":
                         {
-                            if (!session.IsCheckIn && action == Actions.BootNotification)
-                            {
-
-                                var requestId = Guid.NewGuid();
-                                //測試命令
-                                try
-                                {
-
-
-                                    //using (var db = new MainDBContext())
-                                    //{
-                                    //    //db.MachineOperateRecord.Add(new MachineOperateRecord()
-                                    //    //{
-                                    //    //    CreatedOn = DateTime.Now,
-                                    //    //    ChargePointSerialNumber = session.ChargePointSerialNumber,
-                                    //    //    SerialNo = requestId.ToString(),
-                                    //    //    RequestContent = JsonConvert.SerializeObject(new GetConfigurationRequest() { key = new List<string>() { StandardConfiguration.HeartbeatInterval } }),
-                                    //    //    EVSE_Status = 0,
-                                    //    //    Status = 0,
-                                    //    //    RequestType = 1,
-
-
-                                    //    //});
-                                    //    //core 26 項 設定
-                                    //    GetConfigurationRequest core_getConfigReq = new GetConfigurationRequest()
-                                    //    {
-
-                                    //        key = new List<string>()
-                                    //     {
-                                    //           StandardConfiguration.AuthorizeRemoteTxRequests,
-                                    //           StandardConfiguration.ClockAlignedDataInterval,
-                                    //           StandardConfiguration.ConnectionTimeOut,
-                                    //           //StandardConfiguration.HeartbeatInterval,
-                                    //           //StandardConfiguration.HeartbeatInterval,
-                                    //           //StandardConfiguration.LocalAuthorizeOffline,
-                                    //           //StandardConfiguration.LocalPreAuthorize,
-                                    //           //StandardConfiguration.MeterValuesAlignedData,
-                                    //           //StandardConfiguration.MeterValuesAlignedDataMaxLength,
-                                    //           //StandardConfiguration.MeterValuesSampledData,
-                                    //           //StandardConfiguration.MeterValuesSampledDataMaxLength,
-                                    //           //StandardConfiguration.MeterValueSampleInterval,
-                                    //           //StandardConfiguration.NumberOfConnectors,
-                                    //           //StandardConfiguration.ResetRetries,
-                                    //           //StandardConfiguration.ConnectorPhaseRotation,
-                                    //           //StandardConfiguration.ConnectorPhaseRotationMaxLength,
-                                    //           //StandardConfiguration.StopTransactionOnEVSideDisconnect,
-                                    //           //StandardConfiguration.StopTransactionOnInvalidId,
-                                    //           //StandardConfiguration.StopTxnAlignedData,
-                                    //           //StandardConfiguration.StopTxnAlignedDataMaxLength,
-                                    //           //StandardConfiguration.StopTxnSampledData,
-                                    //           //StandardConfiguration.StopTxnSampledDataMaxLength,
-                                    //           //StandardConfiguration.SupportedFeatureProfiles,
-                                    //           //StandardConfiguration.SupportedFeatureProfilesMaxLength,
-                                    //           //StandardConfiguration.TransactionMessageAttempts,
-                                    //           //StandardConfiguration.TransactionMessageRetryInterval,
-                                    //           //StandardConfiguration.UnlockConnectorOnEVSideDisconnect,
-                                    //           //StandardConfiguration.WebSocketPingInterval
-
-                                    //     }
-                                    //    };
-                                    //    db.ServerMessage.Add(new ServerMessage()
-                                    //    {
-                                    //        ChargeBoxId = session.ChargeBoxId,
-                                    //        CreatedBy = "Server",
-                                    //        CreatedOn = DateTime.Now,
-                                    //        OutAction = Actions.GetConfiguration.ToString(),
-                                    //        OutRequest = JsonConvert.SerializeObject(core_getConfigReq),
-                                    //        SerialNo = Guid.Empty.ToString(),
-                                    //        InMessage = string.Empty
-
-                                    //    });
-
-                                    //    db.SaveChanges();
-                                    //}
-                                }
-                                catch (Exception ex)
-                                {
-
-                                }
 
-                            }
+                            bool oldstatus = session.IsCheckIn;
                             var replyResult = _profileHandler.ExecuteCoreRequest(action, session, (IRequest)analysisResult.Message);
                             if (replyResult.Success)
                             {
@@ -425,8 +432,43 @@ namespace EVCB_OCPP.WSServer
                                     if (((BootNotificationConfirmation)replyResult.Message).status == Packet.Messages.SubTypes.RegistrationStatus.Accepted)
                                     {
                                         session.IsCheckIn = true;
+                                        if (!oldstatus)
+                                        {
+                                            using (var db = new MainDBContext())
+                                            {
+                                                var machine = db.Machine.Where(x => x.ChargeBoxId == session.ChargeBoxId).FirstOrDefault();
+                                                if (machine != null)
+                                                {
+                                                    machine.ConnectionType = session.Origin.Contains("https") ? 2 : 1;
+                                                    db.SaveChanges();
+                                                }
+                                            }
+
+
+                                            CheckEVSEConfigure(session.ChargeBoxId);
+                                        }
                                     }
                                 }
+
+                            }
+                            else
+                            {
+                                string response = msgAnalyser.GenerateCallError(analysisResult.UUID, OCPPErrorCodes.InternalError, OCPPErrorDescription.InternalError);
+                                string errorMsg = replyResult.Exception != null ? replyResult.Exception.ToString() : string.Empty;
+
+                                Send(session, response, string.Format("{0} {1}", analysisResult.Action, "Error"), errorMsg);
+                            }
+
+                        }
+                        break;
+                    case "FirmwareManagement":
+                        {
+                            var replyResult = _profileHandler.ExecuteFirmwareManagementRequest(action, session, (IRequest)analysisResult.Message);
+                            if (replyResult.Success)
+                            {
+                                string response = msgAnalyser.GenerateConfirmation(analysisResult.UUID, (IConfirmation)replyResult.Message);
+                                Send(session, response, string.Format("{0} {1}", analysisResult.Action, "Confirmation"));
+
                             }
                             else
                             {
@@ -453,7 +495,7 @@ namespace EVCB_OCPP.WSServer
         private void ProcessConfirmationMessage(MessageResult analysisResult, ClientData session, Actions action)
         {
             BasicMessageHandler msgAnalyser = new BasicMessageHandler();
-            if (ConfirmMessage(analysisResult))
+            if (ReConfirmMessage(analysisResult))
             {
                 var profileName = profiles.Where(x => x.IsExisted(analysisResult.Action)).Select(x => x.Name).FirstOrDefault();
                 MessageResult confirmResult = null;
@@ -464,6 +506,31 @@ namespace EVCB_OCPP.WSServer
                             confirmResult = _profileHandler.ExecuteCoreConfirm(action, session, (IConfirmation)analysisResult.Message, analysisResult.RequestId);
                         }
                         break;
+                    case "FirmwareManagement":
+                        {
+                            confirmResult = _profileHandler.ExecuteFirmwareManagementConfirm(action, session, (IConfirmation)analysisResult.Message, analysisResult.RequestId);
+                        }
+                        break;
+                    case "RemoteTrigger":
+                        {
+                            confirmResult = _profileHandler.ExecuteRemoteTriggerConfirm(action, session, (IConfirmation)analysisResult.Message, analysisResult.RequestId);
+                        }
+                        break;
+                    case "Reservation":
+                        {
+                            confirmResult = _profileHandler.ExecuteReservationConfirm(action, session, (IConfirmation)analysisResult.Message, analysisResult.RequestId);
+                        }
+                        break;
+                    case "LocalAuthListManagement":
+                        {
+                            confirmResult = _profileHandler.ExecuteLocalAuthListManagementConfirm(action, session, (IConfirmation)analysisResult.Message, analysisResult.RequestId);
+                        }
+                        break;
+                    case "SmartCharging":
+                        {
+                            confirmResult = _profileHandler.ExecuteSmartChargingConfirm(action, session, (IConfirmation)analysisResult.Message, analysisResult.RequestId);
+                        }
+                        break;
                     default:
                         {
                             string replyMsg = msgAnalyser.GenerateCallError(analysisResult.UUID, OCPPErrorCodes.InternalError, OCPPErrorDescription.InternalError);
@@ -491,7 +558,7 @@ namespace EVCB_OCPP.WSServer
         private void ProcessErrorMessage(MessageResult analysisResult, ClientData session, Actions action)
         {
             BasicMessageHandler msgAnalyser = new BasicMessageHandler();
-            if (ConfirmMessage(analysisResult))
+            if (ReConfirmMessage(analysisResult))
             {
                 var profileName = profiles.Where(x => x.IsExisted(analysisResult.Action)).Select(x => x.Name).FirstOrDefault();
                 switch (profileName)
@@ -501,6 +568,31 @@ namespace EVCB_OCPP.WSServer
                             _profileHandler.ReceivedCoreError(action, analysisResult.ReceivedErrorCode, session, analysisResult.RequestId);
                         }
                         break;
+                    case "FirmwareManagement":
+                        {
+                            _profileHandler.ReceivedFirmwareManagementError(action, analysisResult.ReceivedErrorCode, session, analysisResult.RequestId);
+                        }
+                        break;
+                    case "RemoteTrigger":
+                        {
+                            _profileHandler.ReceivedRemoteTriggerError(action, analysisResult.ReceivedErrorCode, session, analysisResult.RequestId);
+                        }
+                        break;
+                    case "Reservation":
+                        {
+                            _profileHandler.ExecuteReservationError(action, analysisResult.ReceivedErrorCode, session, analysisResult.RequestId);
+                        }
+                        break;
+                    case "LocalAuthListManagement":
+                        {
+                            _profileHandler.ReceivedLocalAuthListManagementError(action, analysisResult.ReceivedErrorCode, session, analysisResult.RequestId);
+                        }
+                        break;
+                    case "SmartCharging":
+                        {
+                            _profileHandler.ReceivedSmartChargingError(action, analysisResult.ReceivedErrorCode, session, analysisResult.RequestId);
+                        }
+                        break;
                     default:
                         {
                             string replyMsg = msgAnalyser.GenerateCallError(analysisResult.UUID, OCPPErrorCodes.InternalError, OCPPErrorDescription.InternalError);
@@ -529,7 +621,7 @@ namespace EVCB_OCPP.WSServer
 
                 if (session != null)
                 {
-                    WriteMachineLog(session.ChargeBoxId, msg, messageType, errorMsg);
+                    WriteMachineLog(session.ChargeBoxId, msg, messageType, errorMsg, true);
                     session.Send(msg);
                 }
 
@@ -542,7 +634,136 @@ namespace EVCB_OCPP.WSServer
 
         }
 
-        private void ServerMessageTrigger()
+        async private void ServerUpdateTrigger()
+        {
+            for (; ; )
+            {
+                if (_ct.IsCancellationRequested)
+                {
+                    break;
+                }
+
+                var min_Interval = (DateTime.Now - checkUpdateDt).TotalMinutes;
+                if (min_Interval > 3)
+                {
+                    BasicMessageHandler msgAnalyser = new BasicMessageHandler();
+                    Dictionary<string, ClientData> _copyClientDic = null;
+                    lock (_lockClientDic)
+                    {
+                        _copyClientDic = new Dictionary<string, ClientData>(ClientDic);
+
+                    }
+                    checkUpdateDt = DateTime.Now;
+                    using (var db = new MainDBContext())
+                    {
+                        //var needUpdateChargers = db.Machine.Where(x => x.FW_AssignedMachineVersionId.HasValue == true &&
+                        //    x.FW_AssignedMachineVersionId != x.FW_VersionReport && x.Online == true)
+                        //    .Select(x => new { x.Id, x.ChargeBoxId, x.FW_AssignedMachineVersionId }).ToList();
+
+                        var needUpdateChargers = db.Machine.Where(x => x.FW_AssignedMachineVersionId.HasValue == true &&
+                          x.FW_AssignedMachineVersionId != x.FW_VersionReport && x.Online == true)
+                          .Select(x => x.ChargeBoxId).ToList();
+
+                        foreach (var chargeBoxId in needUpdateChargers)
+                        {
+                            try
+                            {
+                               
+
+                                ClientData session;
+                                if (_copyClientDic.TryGetValue(chargeBoxId, out session))
+                                {
+                                  
+                                    string requestId = Guid.NewGuid().ToString();
+                                   // using (var db = new MainDBContext())
+                                   
+                                    if (session.IsCheckIn)
+                                    {
+
+                                        var _request = new TriggerMessageRequest()
+                                        {
+                                            requestedMessage = Packet.Messages.SubTypes.MessageTrigger.FirmwareStatusNotification
+                                        };
+
+                                        var uuid = session.queue.store(_request);
+                                        string rawRequest = msgAnalyser.GenerateRequest(uuid, _request.Action, _request);
+                                        Send(session, rawRequest, string.Format("{0} {1}", _request.Action, "Request"), "");
+
+                                        #region OCTT   ,測試韌體更新方式
+                                        //--------------------> OCTT   ,測試韌體更新方式
+                                        //{
+                                        //    var machine = db.Machine.Where(x => x.FW_AssignedMachineVersionId.HasValue == true &&
+                                        //        x.FW_AssignedMachineVersionId != x.FW_VersionReport && x.ChargeBoxId == session.ChargeBoxId)
+                                        //        .Select(x => new { x.Id, x.FW_AssignedMachineVersionId }).FirstOrDefault();
+
+                                        //    if (machine != null)
+                                        //    {
+                                        //        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();
+
+                                        //        string downloadUrl = mv.PublishVersion.PublishVersionFiles.FirstOrDefault().UploadFile.FileUrl;
+
+                                        //        var _updateFWrequest = new UpdateFirmwareRequest()
+                                        //        {
+                                        //            location = new Uri(downloadUrl),
+                                        //            retries = 3,
+                                        //            retrieveDate = DateTime.Now,
+                                        //            retryInterval = 10
+                                        //        };
+                                        //        db.MachineOperateRecord.Add(new MachineOperateRecord()
+                                        //        {
+                                        //            CreatedOn = DateTime.Now,
+                                        //            ChargeBoxId = session.ChargeBoxId,
+                                        //            SerialNo = requestId,
+                                        //            RequestContent = JsonConvert.SerializeObject(_updateFWrequest, new JsonSerializerSettings() { NullValueHandling = NullValueHandling.Ignore, Formatting = Formatting.None }),
+                                        //            EVSE_Status = 0,
+                                        //            EVSE_Value = "Fw Version:" + machine.FW_AssignedMachineVersionId,
+                                        //            Status = 0,
+                                        //            RequestType = 0,
+
+                                        //        });
+
+                                        //        db.ServerMessage.Add(new ServerMessage()
+                                        //        {
+                                        //            ChargeBoxId = session.ChargeBoxId,
+                                        //            CreatedBy = "Server",
+                                        //            CreatedOn = DateTime.Now,
+                                        //            OutAction = _updateFWrequest.Action.ToString(),
+                                        //            OutRequest = JsonConvert.SerializeObject(_updateFWrequest, new JsonSerializerSettings() { NullValueHandling = NullValueHandling.Ignore, Formatting = Formatting.None }),
+                                        //            SerialNo = requestId,
+                                        //            InMessage = string.Empty
+
+                                        //        });
+
+                                        //        db.SaveChanges();
+
+                                        //    }
+
+                                        //}
+                                        #endregion
+                                    }
+
+
+
+                                }
+
+
+                            }
+                            catch (Exception ex)
+                            {
+                                logger.Error(string.Format("serverUpdateTrigger ChargeBoxId:{0}  Ex:{1}", chargeBoxId, ex.ToString()));
+                            }
+                        }
+                    }
+                    await Task.Delay(1000);
+                    //  Thread.CurrentThread.Join(1000);
+                }
+            }
+        }
+
+        async private void ServerMessageTrigger()
         {
             for (; ; )
             {
@@ -560,13 +781,17 @@ namespace EVCB_OCPP.WSServer
                     {
                         DateTime startDt = DateTime.Now.AddSeconds(-30);
                         DateTime dt = new DateTime(1991, 1, 1);
-                        Console.WriteLine(string.Format("{0} IN", DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss")));
-                        var commandList = db.ServerMessage.Where(c => c.ReceivedOn == dt && c.CreatedOn >= startDt && c.CreatedOn <= DateTime.Now).AsNoTracking().ToList();
+                        //Console.WriteLine(string.Format("{0} IN", DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss")));
+                        var commandList = db.ServerMessage.Where(c => c.ReceivedOn == dt && c.UpdatedOn == dt && c.CreatedOn >= startDt && c.CreatedOn <= DateTime.Now).AsNoTracking().ToList();
                         //處理主機傳送的有指令
                         var cmdMachineList = commandList.Select(c => c.ChargeBoxId).Distinct().ToList();
+                        if (commandList.Count > 0)
+                        {
+                            Console.WriteLine(string.Format("Now:{0} commandList Count:{1} ", DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss"), commandList.Count));
+                        }
+
                         foreach (var charger_SN in cmdMachineList)
                         {
-                           
                             ClientData session;
                             string uuid = string.Empty;
                             if (ClientDic.TryGetValue(charger_SN, out session))
@@ -602,23 +827,36 @@ namespace EVCB_OCPP.WSServer
                                             Send(session, rawRequest, string.Format("{0} {1}", action, "Request"), "");
                                         }
 
-
                                         AddConfirmMessage(charger_SN, item.Id, item.SerialNo, item.OutAction, uuid);
 
+                                        #region 更新資料表單一欄位
+                                        var _UpdatedItem = new ServerMessage() { Id = item.Id, UpdatedOn = DateTime.Now };
+                                        db.Configuration.AutoDetectChangesEnabled = false;//自動呼叫DetectChanges()比對所有的entry集合的每一個屬性Properties的新舊值
+                                        db.Configuration.ValidateOnSaveEnabled = false;// 因為Entity有些欄位必填,若不避開會有Validate錯誤
+                                                                                       // var _UpdatedItem = db.ServerMessage.Where(x => x.Id == item.Id).FirstOrDefault();
+                                        db.ServerMessage.Attach(_UpdatedItem);
+                                        _UpdatedItem.UpdatedOn = DateTime.Now;
+                                        db.Entry(_UpdatedItem).Property(x => x.UpdatedOn).IsModified = true;// 可以直接使用這方式強制某欄位要更新,只是查詢集合耗效能而己
+
+                                        db.SaveChanges();
+
+                                        #endregion
 
 
                                     }
+
                                 }
                             }
                         }
+                        db.ChangeTracker.DetectChanges();
                     }
 
-                    Task.Delay(2000);
+                    await Task.Delay(1000);
+                    //  Thread.CurrentThread.Join(1000);
                 }
                 catch (Exception ex)
                 {
-                    logger.Error("ServerMessageTrigger stop");
-                    logger.Error(ex);
+                    logger.Error(string.Format("ServerMessageTrigger  Ex:{0}", ex.ToString()));
                 }
             }
         }
@@ -641,6 +879,10 @@ namespace EVCB_OCPP.WSServer
                 lock (_lockConfirmPacketList)
                 {
                     NeedConfirmPacketList.Add(_needConfirmMsg);
+                    if (action == "GetConfiguration")
+                    {
+                        Console.WriteLine("AddConfirmMessage: " + msg_id);
+                    }
                 }
             }
         }
@@ -659,18 +901,22 @@ namespace EVCB_OCPP.WSServer
             }
         }
 
-        private bool ConfirmMessage(MessageResult analysisResult)
+        private bool ReConfirmMessage(MessageResult analysisResult)
         {
             bool confirmed = false;
             if (_needConfirmActions.Contains(analysisResult.Action))
             {
+                if (analysisResult.Action == "GetConfiguration")
+                {
+                    Console.WriteLine("ReConfirmMessage: " + analysisResult.UUID);
+                }
                 NeedConfirmMessage foundRequest = null;
                 lock (_lockConfirmPacketList)
                 {
                     foundRequest = NeedConfirmPacketList.Where(x => x.SentUniqueId == analysisResult.UUID).FirstOrDefault();
                 }
 
-                if (foundRequest.Id > 0)
+                if (foundRequest != null && foundRequest.Id > 0)
                 {
                     foundRequest.SentTimes = 0;
                     foundRequest.SentInterval = 0;
@@ -679,15 +925,20 @@ namespace EVCB_OCPP.WSServer
                     using (var db = new MainDBContext())
                     {
                         var sc = db.ServerMessage.Where(x => x.Id == foundRequest.Id).FirstOrDefault();
-                        sc.InMessage = JsonConvert.SerializeObject(analysisResult.Message, Formatting.Indented);
+                        sc.InMessage = JsonConvert.SerializeObject(analysisResult.Message, Formatting.None);
                         sc.ReceivedOn = DateTime.Now;
                         db.SaveChanges();
+                        Console.WriteLine(string.Format("Now:{0} ServerMessage Id:{1} ", DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss"), foundRequest.Id));
 
                     }
                     confirmed = true;
 
 
 
+                }
+                else if (analysisResult.Action == Actions.TriggerMessage.ToString())
+                {
+                    confirmed = true;
                 }
                 else
                 {
@@ -703,10 +954,13 @@ namespace EVCB_OCPP.WSServer
 
         private void RemoveClient(ClientData session)
         {
-            logger.Trace("RemoveClient" + session.ChargeBoxId);
-            RemoveClientDic(session);
+            Console.WriteLine("*********");
+
             if (session != null)
             {
+
+                logger.Trace("RemoveClient[" + session.ChargeBoxId + "]");
+                RemoveClientDic(session);
                 try
                 {
                     session.m_ReceiveData -= new ClientData.OCPPClientDataEventHandler<ClientData, String>(ReceivedMessage);
@@ -728,35 +982,59 @@ namespace EVCB_OCPP.WSServer
 
         private void RemoveClientDic(ClientData session)
         {
-            lock (_lockClientDic)
+            if (!string.IsNullOrEmpty(session.ChargeBoxId))
             {
-                if (ClientDic.ContainsKey(session.ChargeBoxId))
+                lock (_lockClientDic)
                 {
-                    ClientDic.Remove(session.ChargeBoxId);
-                    logger.Trace("RemoveClient ContainsKey " + session.ChargeBoxId);
+
+                    if (ClientDic.ContainsKey(session.ChargeBoxId))
+                    {
+                        ClientDic.Remove(session.ChargeBoxId);
+                        logger.Trace("RemoveClient ContainsKey " + session.ChargeBoxId);
+                    }
                 }
             }
+
         }
 
-        private void WriteMachineLog(string sn, string data, string messageType, string errorMsg = "")
+        private void WarmUpLog()
         {
 
-            using (var db = new ConnectionLogDBContext())
+            using (var log = new ConnectionLogDBContext())
             {
-                string sp = "[dbo].[uspInsertMachineConnectionLog] @CreatedOn," +
-                      "@ChargeBoxId,@MessageType,@Data,@Msg";
-                var dd = DateTime.Now.AddDays(-1);
-                SqlParameter[] parameter =
+                log.MachineConnectionLog.ToList();
+            }
+        }
+
+        private void WriteMachineLog(string sn, string data, string messageType, string errorMsg = "", bool isSent = false)
+        {
+            try
+            {
+                if (string.IsNullOrEmpty(sn) || string.IsNullOrEmpty(data)) return;
+                using (var db = new ConnectionLogDBContext())
                 {
+                    string sp = "[dbo].[uspInsertMachineConnectionLog] @CreatedOn," +
+                          "@ChargeBoxId,@MessageType,@Data,@Msg,@IsSent";
+                    var dd = DateTime.Now;
+                    SqlParameter[] parameter =
+                    {
                       new SqlParameter("CreatedOn",dd),
                       new SqlParameter("ChargeBoxId",sn.Replace("'","''")),
                       new SqlParameter("MessageType",messageType.Replace("'","''")),
                       new SqlParameter("Data",data.Replace("'","''")),
-                      new SqlParameter("Msg",errorMsg.Replace("'","''"))
+                      new SqlParameter("Msg",errorMsg.Replace("'","''")),
+                      new  SqlParameter("IsSent",isSent)
                };
 
-                db.Database.ExecuteSqlCommand(sp, parameter);
+                    db.Database.ExecuteSqlCommand(sp, parameter);
+                }
             }
+            catch (Exception ex)
+            {
+                Console.WriteLine(ex.ToString());
+            }
+
+
         }
     }
 }

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

@@ -16,17 +16,23 @@ namespace OCPPServer.Protocol
         public bool IsCheckIn { set; get; }
 
         public string ChargeBoxId { set; get; }
-        
+
+        public Guid CustomerId { get; set; }
+
+        public string CustomerName { get; set; }
+
         public delegate void OCPPClientDataEventHandler<ClientData, String>(ClientData clientdata, String msg);
 
         public event OCPPClientDataEventHandler<ClientData, String> m_ReceiveData;
 
-       public ClientData()
+        public ClientData()
         {
             IsCheckIn = false;
 
         }
 
+
+
         /// <summary>
         /// Sends the raw binary data to client.
         /// </summary>
@@ -52,5 +58,6 @@ namespace OCPPServer.Protocol
         protected override void OnSessionClosed(CloseReason reason)
         {
         }
+       
     }
 }

+ 4 - 2
EVCB_OCPP.WSServer/SuperSocket.Protocol/OCPPSubProtocol.cs

@@ -195,10 +195,12 @@ namespace OCPPServer.SubProtocol
             : base(name)
         {
             //The items in commandAssemblies may be null, so filter here
-            m_CommandAssemblies.AddRange(commandAssemblies.Where(a => a != null));
+            m_CommandAssemblies.AddRange(commandAssemblies.Where(a => a != null));         
             SubRequestParser = requestInfoParser;
         }
 
+
+
         #region ISubProtocol Members
 
         private void DiscoverCommands()
@@ -272,7 +274,7 @@ namespace OCPPServer.SubProtocol
             return m_CommandDict.TryGetValue(name, out command);
         }
 
-       
+
 
         public override bool Initialize(IAppServer appServer, SubProtocolConfig protocolConfig, ILog logger)
         {

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

@@ -6,6 +6,8 @@ using SuperWebSocket.SubProtocol;
 using System;
 using System.Collections.Generic;
 using System.Linq;
+using System.Net.Security;
+using System.Security.Cryptography.X509Certificates;
 using System.Text;
 
 namespace OCPPServer.Protocol
@@ -49,6 +51,13 @@ namespace OCPPServer.Protocol
 
         }
 
+        protected override bool ValidateClientCertificate(ClientData session, object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
+        {
+            Console.WriteLine(string.Format("{0} :{1}", session.ChargeBoxId+" ValidateClientCertificate", sslPolicyErrors));
+            return true;
+           // return base.ValidateClientCertificate(session, sender, certificate, chain, sslPolicyErrors);
+        }
+
         protected override bool ValidateHandshake(ClientData session, string origin)
         {
             string[] words = session.Path.Split('/');
@@ -79,7 +88,7 @@ namespace OCPPServer.Protocol
             else
             {
                 //確認電樁連線所送的SubProtocol是否被Server支援
-                if (session.SecWebSocketProtocol.ToLower() != "ocpp1.6")
+                if (!session.SecWebSocketProtocol.ToLower().Contains("ocpp1.6"))
                 {
                     const string m_Magic = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
                     const string SecWebSocketKey = "Sec-WebSocket-Key";
@@ -119,7 +128,7 @@ namespace OCPPServer.Protocol
                 }
             }
 
-            
+          
 
             return true;
         }

+ 18 - 4
TestTool.RemoteTriggerAPP/App.config

@@ -3,12 +3,19 @@
   <configSections>
     <!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
     <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
+    <sectionGroup name="applicationSettings" type="System.Configuration.ApplicationSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
+      <section name="TestTool.RemoteTriggerAPP.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
+    </sectionGroup>
   </configSections>
    <connectionStrings>
-    <add name="ConnectionLogDBContext" connectionString="data source=172.1.0.142\SQLEXPRESS;initial catalog=OCPP_ConnectionLogDBContext;persist security info=True;user id=sa;password=Ph0930118811;MultipleActiveResultSets=True;App=EntityFramework" providerName="System.Data.SqlClient" />
-    <add name="MainDBContext" connectionString="data source=172.1.0.142\SQLEXPRESS;initial catalog=OCPP_MainDBContext;;persist security info=True;user id=sa;password=Ph0930118811;MultipleActiveResultSets=True;App=EntityFramework" providerName="System.Data.SqlClient" />
-    <add name="MeterValueDBContext" connectionString="data source=172.1.0.142\SQLEXPRESS;initial catalog=OCPP_MeterValueDBContext;;persist security info=True;user id=sa;password=Ph0930118811;MultipleActiveResultSets=True;App=EntityFramework" providerName="System.Data.SqlClient" />
-  </connectionStrings>
+     <!--<add name="ConnectionLogDBContext" connectionString="data source=172.1.0.142\SQLEXPRESS;initial catalog=OCPP_ConnectionLogDBContext;persist security info=True;user id=sa;password=Ph0930118811;MultipleActiveResultSets=True;App=EntityFramework" providerName="System.Data.SqlClient" />
+     <add name="MainDBContext" connectionString="data source=172.1.0.142\SQLEXPRESS;initial catalog=OCPP_MainDBContext;;persist security info=True;user id=sa;password=Ph0930118811;MultipleActiveResultSets=True;App=EntityFramework" providerName="System.Data.SqlClient" />
+     <add name="MeterValueDBContext" connectionString="data source=172.1.0.142\SQLEXPRESS;initial catalog=OCPP_MeterValueDBContext;;persist security info=True;user id=sa;password=Ph0930118811;MultipleActiveResultSets=True;App=EntityFramework" providerName="System.Data.SqlClient" />-->
+
+     <add name="ConnectionLogDBContext" connectionString="data source=172.1.2.187\SQLEXPRESS2017;initial catalog=StandardOCPP_ConnectionLog;persist security info=True;user id=sa;password=Ph0930118811;MultipleActiveResultSets=True;App=EntityFramework" providerName="System.Data.SqlClient" />
+     <add name="MainDBContext" connectionString="data source=172.1.2.187\SQLEXPRESS2017;initial catalog=StandardOCPP_Main;;persist security info=True;user id=sa;password=Ph0930118811;MultipleActiveResultSets=True;App=EntityFramework" providerName="System.Data.SqlClient" />
+     <add name="MeterValueDBContext" connectionString="data source=172.1.2.187\SQLEXPRESS2017;initial catalog=StandardOCPP_MeterValue;;persist security info=True;user id=sa;password=Ph0930118811;MultipleActiveResultSets=True;App=EntityFramework" providerName="System.Data.SqlClient" />
+   </connectionStrings>  
   <startup>
     <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.1" />
   </startup>
@@ -22,4 +29,11 @@
       <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
     </providers>
   </entityFramework>
+  <applicationSettings>
+    <TestTool.RemoteTriggerAPP.Properties.Settings>
+      <setting name="FilePreUrl" serializeAs="String">
+        <value>http://test.evsocket.phihong.com.cn/</value>
+      </setting>
+    </TestTool.RemoteTriggerAPP.Properties.Settings>
+  </applicationSettings>
 </configuration>

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


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


+ 47 - 16
TestTool.RemoteTriggerAPP/MainWindow.xaml

@@ -5,35 +5,66 @@
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
         xmlns:local="clr-namespace:TestTool.RemoteTriggerAPP"
         mc:Ignorable="d"
-        Title="MainWindow" Height="450" Width="800">
-    <Grid>
+        Title="MainWindow" Height="450" Width="670">
+    <Grid Margin="0,2,0,-2">
         <Label Content="Charge Box Id:" HorizontalAlignment="Left" Height="27" Margin="69,23,0,0" VerticalAlignment="Top" Width="91"/>
         <Label Content="Connector Id:" HorizontalAlignment="Left" Height="27" Margin="336,23,0,0" VerticalAlignment="Top" Width="92"/>
         <TextBox Name="uxChargeBoxIdTb" Text="OCTT_1" HorizontalAlignment="Left" Height="27" Margin="179,23,0,0" VerticalAlignment="Top" Width="148"/>
         <TextBox Name="uxConnectorIdTb" Text="1" HorizontalAlignment="Left" Height="27" Margin="428,23,0,0" VerticalAlignment="Top" Width="35"/>
-        <ComboBox Name="uxCmdCb" HorizontalAlignment="Left" Margin="224,106,0,0" VerticalAlignment="Top" Width="253" Height="34" SelectionChanged="UxCmdCb_SelectionChanged">
+        <ComboBox Name="uxCmdCb" HorizontalAlignment="Left" Margin="212,163,0,0" VerticalAlignment="Top" Width="253" Height="34" SelectionChanged="UxCmdCb_SelectionChanged">
             <ComboBoxItem>ChangeAvailability_Inoperative</ComboBoxItem>
             <ComboBoxItem>ChangeAvailability_Operative</ComboBoxItem>
-            <ComboBoxItem>ChangeConfiguration_MeterValueSampleInterval</ComboBoxItem>
+            <ComboBoxItem>ChangeConfiguration</ComboBoxItem>
             <ComboBoxItem>ClearCache</ComboBoxItem>
-            <ComboBoxItem>GetConfiguration_SupportedFeatureProfiles</ComboBoxItem>
-            <ComboBoxItem>GetConfiguration_GetConfigurationMaxKeys</ComboBoxItem>
-            <ComboBoxItem>GetConfiguration_MeterValueSampleInterval</ComboBoxItem>
-            <ComboBoxItem>GetConfiguration_ALL</ComboBoxItem>
+            <ComboBoxItem>GetConfiguration</ComboBoxItem>
             <ComboBoxItem>RemoteStartTransaction</ComboBoxItem>
             <ComboBoxItem>RemoteStopTransaction</ComboBoxItem>
             <ComboBoxItem>SoftReset</ComboBoxItem>
             <ComboBoxItem>HardReset</ComboBoxItem>
             <ComboBoxItem>UnlockConnector</ComboBoxItem>
+            <ComboBoxItem>GetLocalListVersion</ComboBoxItem>
+            <ComboBoxItem>SendLocalAuthorizationList_Full</ComboBoxItem>
+            <ComboBoxItem>SendLocalAuthorizationList_Diff</ComboBoxItem>
+            <ComboBoxItem>GetDiagnostics</ComboBoxItem>
+            <ComboBoxItem>ReserveNow</ComboBoxItem>
+            <ComboBoxItem>CancelReservation</ComboBoxItem>
+            <ComboBoxItem>SetChargingProfile_TxDefault</ComboBoxItem>
+            <ComboBoxItem>SetChargingProfile_Tx</ComboBoxItem>
+            <ComboBoxItem>RemoteStartTransaction_ChargingProfile</ComboBoxItem>
+            <ComboBoxItem>ClearChargingProfile</ComboBoxItem>
+            <ComboBoxItem>GetCompositeSchedule</ComboBoxItem>
+            <ComboBoxItem>TriggerMessage_BootNotification</ComboBoxItem>
+            <ComboBoxItem>TriggerMessage_DiagnosticsStatusNotification</ComboBoxItem>
+            <ComboBoxItem>TriggerMessage_FirmwareStatusNotification</ComboBoxItem>
+            <ComboBoxItem>TriggerMessage_Heartbeat</ComboBoxItem>
+            <ComboBoxItem>TriggerMessage_MeterValues</ComboBoxItem>
+            <ComboBoxItem>TriggerMessage_StatusNotification</ComboBoxItem>
         </ComboBox>
-        <Label  Content="Remote Trigger Cmd:" HorizontalAlignment="Left" Height="27" Margin="69,110,0,0" VerticalAlignment="Top" Width="137"/>
-        <Button Name="uxSubmitBtn" Content="Submit" HorizontalAlignment="Left" Margin="515,108,0,0" VerticalAlignment="Top" Width="108" Height="34" Click="UxSubmitBtn_Click"/>
-        <TextBox Name="uxMsgTb" HorizontalAlignment="Left" Height="165" Margin="69,182,0,0" VerticalAlignment="Top" Width="471"/>
-        <Label Content="Msg:" HorizontalAlignment="Left" Height="27" Margin="69,148,0,0" VerticalAlignment="Top" Width="43"/>
-        <Label Content="Id Tag:" HorizontalAlignment="Left" Height="27" Margin="76,74,0,0" VerticalAlignment="Top" Width="47"/>
-        <TextBox x:Name="uxIdTagTb" Text="TestTool" HorizontalAlignment="Left" Height="27" Margin="128,74,0,0" VerticalAlignment="Top" Width="137" RenderTransformOrigin="3.714,1"/>
-        <Label Content="TransactionId:" HorizontalAlignment="Left" Height="27" Margin="284,74,0,0" VerticalAlignment="Top" Width="100"/>
-        <TextBox x:Name="uxTransactionIdTb" Text="0" HorizontalAlignment="Left" Height="27" Margin="403,74,0,0" VerticalAlignment="Top" Width="137" RenderTransformOrigin="3.714,1"/>
+        <Label  Content="Remote Trigger Cmd:" HorizontalAlignment="Left" Height="27" Margin="69,165,0,0" VerticalAlignment="Top" Width="137"/>
+        <Button Name="uxSubmitBtn" Content="Submit" HorizontalAlignment="Left" Margin="478,165,0,0" VerticalAlignment="Top" Width="51" Height="34" Click="UxSubmitBtn_Click"/>
+        <TextBox Name="uxMsgTb" HorizontalAlignment="Left" Height="80" Margin="58,329,0,0" VerticalAlignment="Top" Width="471"/>
+        <Label Content="Msg:" HorizontalAlignment="Left" Height="27" Margin="58,298,0,0" VerticalAlignment="Top" Width="43" RenderTransformOrigin="0.744,3.407"/>
+        <Label Content="Id Tag:" HorizontalAlignment="Left" Height="27" Margin="71,74,0,0" VerticalAlignment="Top" Width="47"/>
+        <TextBox x:Name="uxIdTagTb" Text="TestTool" HorizontalAlignment="Left" Height="27" Margin="128,74,0,0" VerticalAlignment="Top" Width="63" RenderTransformOrigin="3.714,1"/>
+        <Label Content="TransactionId:" HorizontalAlignment="Left" Height="27" Margin="380,74,0,0" VerticalAlignment="Top" Width="100"/>
+        <TextBox x:Name="uxTransactionIdTb" Text="0" HorizontalAlignment="Left" Height="27" Margin="485,74,0,0" VerticalAlignment="Top" Width="44" RenderTransformOrigin="3.714,1"/>
+        <Label Content="ParentId Tag:" HorizontalAlignment="Left" Height="27" Margin="212,74,0,0" VerticalAlignment="Top" Width="87"/>
+        <TextBox x:Name="uxParentIdTagTb" Text="TestTool" HorizontalAlignment="Left" Height="27" Margin="299,74,0,0" VerticalAlignment="Top" Width="73" RenderTransformOrigin="3.714,1"/>
+        <Label Content="Configuration Key:" HorizontalAlignment="Left" Height="27" Margin="71,119,0,0" VerticalAlignment="Top" Width="120"/>
+        <TextBox x:Name="uxConfigKeyTb" Text="ConnectionTimeOut" HorizontalAlignment="Left" Height="27" Margin="212,119,0,0" VerticalAlignment="Top" Width="138" RenderTransformOrigin="3.714,1"/>
+        <Label Content=" Value:" HorizontalAlignment="Left" Height="27" Margin="374,119,0,0" VerticalAlignment="Top" Width="54"/>
+        <TextBox x:Name="uxConfigValueTb" Text="30" HorizontalAlignment="Left" Height="27" Margin="433,119,0,0" VerticalAlignment="Top" Width="52" RenderTransformOrigin="3.714,1"/>
+        <Label  Content="Upload Firmware:" HorizontalAlignment="Left" Height="27" Margin="69,217,0,0" VerticalAlignment="Top" Width="113"/>
+
+        <TextBox x:Name="uxUploadFileTb" Text="" HorizontalAlignment="Left" Height="27" Margin="182,217,0,0" VerticalAlignment="Top" Width="210" RenderTransformOrigin="3.714,1"/>
+        <Button x:Name="uxFileSubmitBtn" Content="..." HorizontalAlignment="Left" Margin="405,215,0,0" VerticalAlignment="Top" Width="46" Height="29" Click="uxFileSubmitBtn_Click"/>
+        <Button x:Name="uxUploadBtn" Content="Upload" HorizontalAlignment="Left" Margin="477,212,0,0" VerticalAlignment="Top" Width="52" Height="34" Click="uxUploadBtn_Click"/>
+        <Label  Content="Publish Version:" HorizontalAlignment="Left" Height="27" Margin="69,266,0,0" VerticalAlignment="Top" Width="113"/>
+        <ComboBox x:Name="uxPublishCb" HorizontalAlignment="Left" Margin="179,266,0,0" VerticalAlignment="Top" Width="213" Height="34" SelectionChanged="uxPublishCb_SelectionChanged"/>
+        <Button x:Name="uxRefreshBtn" Content="Refresh" HorizontalAlignment="Left" Margin="410,266,0,0" VerticalAlignment="Top" Width="53" Height="34" Click="uxRefreshBtn_Click"/>
+        <Button x:Name="uxPublishBtn" Content="Publish" HorizontalAlignment="Left" Margin="476,266,0,0" VerticalAlignment="Top" Width="53" Height="34" Click="uxPublishBtn_Click"/>
+        <Label Content="ReservationId:" HorizontalAlignment="Left" Height="27" Margin="480,23,0,0" VerticalAlignment="Top" Width="100"/>
+        <TextBox x:Name="uxReservationTb" Text="0" HorizontalAlignment="Left" Height="27" Margin="585,23,0,0" VerticalAlignment="Top" Width="44" RenderTransformOrigin="3.714,1"/>
 
     </Grid>
 </Window>

+ 484 - 55
TestTool.RemoteTriggerAPP/MainWindow.xaml.cs

@@ -3,11 +3,16 @@ using EVCB_OCPP.Domain.Models.Database;
 using EVCB_OCPP.Packet.Features;
 using EVCB_OCPP.Packet.Messages;
 using EVCB_OCPP.Packet.Messages.Core;
+using Microsoft.Win32;
 using Newtonsoft.Json;
 using OCPPPackage.Profiles;
 using System;
 using System.Collections.Generic;
+using System.Configuration;
+using System.IO;
 using System.Linq;
+using System.Net;
+using System.Security.Cryptography;
 using System.Text;
 using System.Threading.Tasks;
 using System.Windows;
@@ -19,6 +24,13 @@ using System.Windows.Media;
 using System.Windows.Media.Imaging;
 using System.Windows.Navigation;
 using System.Windows.Shapes;
+using System.Data.Entity;
+using EVCB_OCPP.Packet.Messages.RemoteTrigger;
+using EVCB_OCPP.Packet.Messages.SubTypes;
+using EVCB_OCPP.Packet.Messages.LocalAuthListManagement;
+using EVCB_OCPP.Packet.Messages.FirmwareManagement;
+using EVCB_OCPP.Packet.Messages.Reservation;
+using EVCB_OCPP.Packet.Messages.SmartCharging;
 
 namespace TestTool.RemoteTriggerAPP
 {
@@ -28,8 +40,11 @@ namespace TestTool.RemoteTriggerAPP
     public partial class MainWindow : Window
     {
         string action = "";
+        List<PublishVersion> publishes = new List<PublishVersion>();
+        int selectedPublish = -1;
         public MainWindow()
         {
+           
             InitializeComponent();
         }
 
@@ -38,6 +53,7 @@ namespace TestTool.RemoteTriggerAPP
 
             switch (action)
             {
+                #region Core Profile
                 case "ChangeAvailability_Inoperative":
                     {
                         SetChangeAvailability_Inoperative();
@@ -48,22 +64,41 @@ namespace TestTool.RemoteTriggerAPP
                         SetChangeAvailability_Operative();
                     }
                     break;
-                
-                case "ChangeConfiguration_MeterValueSampleInterval":
+
+                case "GetConfiguration":
+                    {
+                        if (uxConfigKeyTb.Text == "")
+                        {
+                            SetGetConfiguration_ALL();
+                        }
+                        else
+                        {
+                            SetGetConfiguration();
+                        }
+
+                    }
+                    break;
+                case "ChangeConfiguration":
                     {
-                        SetChangeConfiguration_MeterValueSampleInterval();
+                        SetChangeConfiguration();
+
                     }
                     break;
                 case "ClearCache":
                     {
                         SetClearCache();
                     }
-                    break;              
+                    break;
                 case "RemoteStartTransaction":
                     {
                         SetRemoteStartTransaction();
                     }
                     break;
+                case "RemoteStartTransaction_ChargingProfile":
+                    {
+                        SetRemoteStartTransaction(true);
+                    }
+                    break;
                 case "RemoteStopTransaction":
                     {
                         SetRemoteStopTransaction();
@@ -85,53 +120,151 @@ namespace TestTool.RemoteTriggerAPP
                     }
 
                     break;
-                case "GetConfiguration_ALL":
+                #endregion
+                #region Local Authorization
+                case "GetLocalListVersion":
                     {
-                        SetGetConfiguration_ALL();
+                        GetLocalListVersion();
                     }
                     break;
-                case "GetConfiguration_SupportedFeatureProfiles":
+                case "SendLocalAuthorizationList_Full":
                     {
-                        SetGetConfiguration_SupportedFeatureProfiles();
+                        SendLocalAuthorizationList(true);
                     }
                     break;
-                case "GetConfiguration_GetConfigurationMaxKeys":
+                case "SendLocalAuthorizationList_Diff":
                     {
-                        SetGetConfiguration_GetConfigurationMaxKeys();
+                        SendLocalAuthorizationList(false);
                     }
                     break;
-                case "GetConfiguration_MeterValueSampleInterval":
+                #endregion
+                case "GetDiagnostics":
                     {
-                        SetGetConfiguration_MeterValueSampleInterval();
+                        GetDiagnostics();
                     }
                     break;
-                default:
+                case "ReserveNow":
                     {
-
+                        ReserveNow();
+                    }
+                    break;
+                case "CancelReservation":
+                    {
+                        CancelReservation();
+                    }
+                    break;
+                case "ClearChargingProfile":
+                    {
+                        ClearChargingProfile();
+                    }
+                    break;
+                case "GetCompositeSchedule":
+                    {
+                        GetCompositeSchedule();
+                    }
+                    break;
+                case "SetChargingProfile_TxDefault":
+                    {
+                        SetChargingProfile(true);
                     }
                     break;
+                case "SetChargingProfile_Tx":
+                    {
+                        SetChargingProfile(false);
+                    }
+                    break;
+                #region Trigger Profile
+                case "TriggerMessage_BootNotification":
+                case "TriggerMessage_DiagnosticsStatusNotification":
+                case "TriggerMessage_FirmwareStatusNotification":
+                case "TriggerMessage_Heartbeat":
+                case "TriggerMessage_MeterValues":
+                case "TriggerMessage_StatusNotification":
+                    {
+                        SetRemoteTrigger(action);
+                    }
+                    break;
+                #endregion
+                default:
+                    break;
 
             }
         }
 
-        private void UxCmdCb_SelectionChanged(object sender, SelectionChangedEventArgs e)
+        private void SetChargingProfile(bool isDefault)
         {
+            try
+            {
 
-            var item = uxCmdCb.SelectedValue as ComboBoxItem;
-            action = item.Content as string;
+                var uuid = Guid.NewGuid().ToString();
+                var request = new SetChargingProfileRequest()
+                {
+                    connectorId = Convert.ToInt32(uxConnectorIdTb.Text),
+                    csChargingProfiles = new csChargingProfiles()
+                    {
+                        chargingProfileId = Convert.ToInt32(DateTime.Now.ToString("yyMMddHHmm")),
+                        chargingProfileKind = ChargingProfileKindType.Absolute,
+                        chargingProfilePurpose = isDefault ? ChargingProfilePurposeType.TxDefaultProfile : ChargingProfilePurposeType.TxProfile,
+                        recurrencyKind = RecurrencyKindType.Daily,
+                        stackLevel = 1,
+                        chargingSchedule = new ChargingSchedule()
+                        {
+                            chargingRateUnit = ChargingRateUnitType.A,
+                            duration = 300,
+                            minChargingRate = 0,
+                            startSchedule = DateTime.Now.Date,
+                            chargingSchedulePeriod = new List<ChargingSchedulePeriod>()
+                                        {
+                                             new ChargingSchedulePeriod()
+                                             { limit=10, startPeriod=0, numberPhases=3 },
+                                              new ChargingSchedulePeriod()
+                                             { limit=2, startPeriod=60, numberPhases=3 },
+                                               new ChargingSchedulePeriod()
+                                             { limit=8, startPeriod=120, numberPhases=3 }
+                                        }
+                        }
+                    }
+                };
 
+                WritetoDB(uuid, request);
+                uxMsgTb.Text = string.Format("UUID:{0}", uuid);
+            }
+            catch (Exception ex)
+            {
+                MessageBox.Show(ex.ToString());
+            }
         }
 
+        private void GetCompositeSchedule()
+        {
+            try
+            {
+
+                var uuid = Guid.NewGuid().ToString();
+                var request = new GetCompositeScheduleRequest()
+                {
+                    connectorId = Convert.ToInt32(uxConnectorIdTb.Text),
+                    duration = 300
+                };
+
+                WritetoDB(uuid, request);
+                uxMsgTb.Text = string.Format("UUID:{0}", uuid);
+            }
+            catch (Exception ex)
+            {
+                MessageBox.Show(ex.ToString());
+            }
+        }
 
-        private void SetRemoteStartTransaction()
+        private void ClearChargingProfile()
         {
             try
             {
+
                 var uuid = Guid.NewGuid().ToString();
-                var request = new RemoteStartTransactionRequest()
+                var request = new ClearChargingProfileRequest()
                 {
-                    connectorId = byte.Parse(uxConnectorIdTb.Text),
-                    idTag = uxIdTagTb.Text
+                    connectorId = Convert.ToInt32(uxConnectorIdTb.Text),
 
                 };
 
@@ -144,14 +277,41 @@ namespace TestTool.RemoteTriggerAPP
             }
         }
 
-        private void SetUnlockConnector()
+        private void CancelReservation()
         {
+
             try
             {
+
                 var uuid = Guid.NewGuid().ToString();
-                var request = new UnlockConnectorRequest()
+                var request = new CancelReservationRequest()
                 {
-                    connectorId = byte.Parse(uxConnectorIdTb.Text),
+                    reservationId = Convert.ToInt32(uxReservationTb.Text),
+                };
+
+                WritetoDB(uuid, request);
+                uxMsgTb.Text = string.Format("UUID:{0}", uuid);
+            }
+            catch (Exception ex)
+            {
+                MessageBox.Show(ex.ToString());
+            }
+        }
+
+        private void ReserveNow()
+        {
+
+            try
+            {
+
+                var uuid = Guid.NewGuid().ToString();
+                var request = new ReserveNowRequest()
+                {
+                    connectorId = Convert.ToInt32(uxConnectorIdTb.Text),
+                    expiryDate = DateTime.Now.AddMinutes(1),
+                    idTag = uxIdTagTb.Text,
+                    parentIdTag = "PTAG",
+                    reservationId = Convert.ToInt32(DateTime.Now.ToString("yyMMddHHmm")),
 
                 };
 
@@ -164,15 +324,22 @@ namespace TestTool.RemoteTriggerAPP
             }
         }
 
-        private void SetChangeAvailability_Inoperative()
+        private void GetDiagnostics()
         {
             try
             {
+
                 var uuid = Guid.NewGuid().ToString();
-                var request = new ChangeAvailabilityRequest()
+                var request = new GetDiagnosticsRequest()
                 {
-                    connectorId = byte.Parse(uxConnectorIdTb.Text),
-                    type = EVCB_OCPP.Packet.Messages.SubTypes.AvailabilityType.Inoperative
+            
+                    location = new Uri("ftp://phihong:y42j%2f4cj84@test.evsocket.phihong.com.cn/"),
+                    retries = 1,
+                    retryInterval = 30,
+                    startTime = DateTime.Now.AddHours(-1),
+                    stopTime = DateTime.Now
+
+
                 };
 
                 WritetoDB(uuid, request);
@@ -184,15 +351,17 @@ namespace TestTool.RemoteTriggerAPP
             }
         }
 
-        private void SetChangeAvailability_Operative()
+        #region Local Authorization
+
+        private void GetLocalListVersion()
         {
             try
             {
+
                 var uuid = Guid.NewGuid().ToString();
-                var request = new ChangeAvailabilityRequest()
+                var request = new GetLocalListVersionRequest()
                 {
-                    connectorId = byte.Parse(uxConnectorIdTb.Text),
-                    type = EVCB_OCPP.Packet.Messages.SubTypes.AvailabilityType.Operative
+
                 };
 
                 WritetoDB(uuid, request);
@@ -204,15 +373,29 @@ namespace TestTool.RemoteTriggerAPP
             }
         }
 
-        private void SetChangeConfiguration_UnSupport()
+        private void SendLocalAuthorizationList(bool isFull)
         {
             try
             {
+
                 var uuid = Guid.NewGuid().ToString();
-                var request = new ChangeConfigurationRequest()
+                var request = new SendLocalListRequest()
                 {
-                    key = StandardConfiguration.MeterValueSampleInterval,
-                    value = "true",
+                    listVersion = Convert.ToInt32(DateTime.Now.ToString("yyMMddHHmm")),
+                    updateType = isFull ? UpdateType.Full : UpdateType.Differential,
+                    localAuthorizationList = new List<AuthorizationData>()
+                    {
+                         new AuthorizationData()
+                         {
+
+                              idTagInfo=new IdTagInfo(){  expiryDate=DateTime.Now.AddDays(3), status=  AuthorizationStatus.Accepted},
+                               idTag="123"
+                         }, new AuthorizationData()
+                         {
+                              idTagInfo=new IdTagInfo(){  expiryDate=DateTime.Now.AddDays(3), status=  AuthorizationStatus.Expired},
+                               idTag="456"
+                         }
+                    }
 
                 };
 
@@ -224,18 +407,37 @@ namespace TestTool.RemoteTriggerAPP
                 MessageBox.Show(ex.ToString());
             }
         }
+        #endregion
 
 
-        private void SetChangeConfiguration_MeterValueSampleInterval()
+        private void SetRemoteTrigger(string action)
         {
             try
             {
+                string type = action.Split('_').Last();
                 var uuid = Guid.NewGuid().ToString();
-                var request = new ChangeConfigurationRequest()
+                var request = new TriggerMessageRequest()
                 {
-                    key = StandardConfiguration.MeterValueSampleInterval,
-                    value = "true",
+                    requestedMessage = (MessageTrigger)Enum.Parse(typeof(MessageTrigger), type, false)
+                };
 
+                WritetoDB(uuid, request);
+                uxMsgTb.Text = string.Format("UUID:{0}", uuid);
+            }
+            catch (Exception ex)
+            {
+                MessageBox.Show(ex.ToString());
+            }
+        }
+
+        private void SetGetConfiguration()
+        {
+            try
+            {
+                var uuid = Guid.NewGuid().ToString();
+                var request = new GetConfigurationRequest()
+                {
+                    key = new List<string>() { uxConfigKeyTb.Text }
                 };
 
                 WritetoDB(uuid, request);
@@ -247,15 +449,53 @@ namespace TestTool.RemoteTriggerAPP
             }
         }
 
-        private void SetClearCache()
+        private void UxCmdCb_SelectionChanged(object sender, SelectionChangedEventArgs e)
+        {
+
+            var item = uxCmdCb.SelectedValue as ComboBoxItem;
+            action = item.Content as string;
+
+        }
+
+
+        private void SetRemoteStartTransaction(bool hasProfile = false)
         {
             try
             {
                 var uuid = Guid.NewGuid().ToString();
-                var request = new ClearCacheRequest()
+                var request = new RemoteStartTransactionRequest()
                 {
+                    connectorId = byte.Parse(uxConnectorIdTb.Text),
+                    idTag = uxIdTagTb.Text
 
                 };
+                if (hasProfile)
+                {
+                    request.chargingProfile = new csChargingProfiles()
+                    {
+                        chargingProfileId = Convert.ToInt32(DateTime.Now.ToString("yyMMddHHmm")),
+                        chargingProfileKind = ChargingProfileKindType.Absolute,
+                        chargingProfilePurpose = ChargingProfilePurposeType.TxProfile,
+                        recurrencyKind = RecurrencyKindType.Daily,
+                        stackLevel = 1,
+                        chargingSchedule = new ChargingSchedule()
+                        {
+                            chargingRateUnit = ChargingRateUnitType.A,
+                            duration = 300,
+                            minChargingRate = 0,
+                            startSchedule = DateTime.Now.Date,
+                            chargingSchedulePeriod = new List<ChargingSchedulePeriod>()
+                                        {
+                                             new ChargingSchedulePeriod()
+                                             { limit=10, startPeriod=0, numberPhases=3 },
+                                              new ChargingSchedulePeriod()
+                                             { limit=2, startPeriod=60, numberPhases=3 },
+                                               new ChargingSchedulePeriod()
+                                             { limit=8, startPeriod=120, numberPhases=3 }
+                                        }
+                        }
+                    };
+                }
 
                 WritetoDB(uuid, request);
                 uxMsgTb.Text = string.Format("UUID:{0}", uuid);
@@ -266,16 +506,35 @@ namespace TestTool.RemoteTriggerAPP
             }
         }
 
+        private void SetUnlockConnector()
+        {
+            try
+            {
+                var uuid = Guid.NewGuid().ToString();
+                var request = new UnlockConnectorRequest()
+                {
+                    connectorId = byte.Parse(uxConnectorIdTb.Text),
 
+                };
 
-        private void SetGetConfiguration_ALL()
+                WritetoDB(uuid, request);
+                uxMsgTb.Text = string.Format("UUID:{0}", uuid);
+            }
+            catch (Exception ex)
+            {
+                MessageBox.Show(ex.ToString());
+            }
+        }
+
+        private void SetChangeAvailability_Inoperative()
         {
             try
             {
                 var uuid = Guid.NewGuid().ToString();
-                var request = new GetConfigurationRequest()
+                var request = new ChangeAvailabilityRequest()
                 {
-                    key = new List<string>() {  }
+                    connectorId = byte.Parse(uxConnectorIdTb.Text),
+                    type = EVCB_OCPP.Packet.Messages.SubTypes.AvailabilityType.Inoperative
                 };
 
                 WritetoDB(uuid, request);
@@ -287,14 +546,15 @@ namespace TestTool.RemoteTriggerAPP
             }
         }
 
-        private void SetGetConfiguration_MeterValueSampleInterval()
+        private void SetChangeAvailability_Operative()
         {
             try
             {
                 var uuid = Guid.NewGuid().ToString();
-                var request = new GetConfigurationRequest()
+                var request = new ChangeAvailabilityRequest()
                 {
-                    key = new List<string>() { StandardConfiguration.MeterValueSampleInterval }
+                    connectorId = byte.Parse(uxConnectorIdTb.Text),
+                    type = EVCB_OCPP.Packet.Messages.SubTypes.AvailabilityType.Operative
                 };
 
                 WritetoDB(uuid, request);
@@ -307,14 +567,37 @@ namespace TestTool.RemoteTriggerAPP
         }
 
 
-        private void SetGetConfiguration_SupportedFeatureProfiles()
+
+
+        private void SetChangeConfiguration()
         {
             try
             {
                 var uuid = Guid.NewGuid().ToString();
-                var request = new GetConfigurationRequest()
+                var request = new ChangeConfigurationRequest()
+                {
+                    key = uxConfigKeyTb.Text,
+                    value = uxConfigValueTb.Text,
+
+                };
+
+                WritetoDB(uuid, request);
+                uxMsgTb.Text = string.Format("UUID:{0}", uuid);
+            }
+            catch (Exception ex)
+            {
+                MessageBox.Show(ex.ToString());
+            }
+        }
+
+        private void SetClearCache()
+        {
+            try
+            {
+                var uuid = Guid.NewGuid().ToString();
+                var request = new ClearCacheRequest()
                 {
-                    key = new List<string>() { StandardConfiguration.SupportedFeatureProfiles }
+
                 };
 
                 WritetoDB(uuid, request);
@@ -326,14 +609,16 @@ namespace TestTool.RemoteTriggerAPP
             }
         }
 
-        private void SetGetConfiguration_GetConfigurationMaxKeys()
+
+
+        private void SetGetConfiguration_ALL()
         {
             try
             {
                 var uuid = Guid.NewGuid().ToString();
                 var request = new GetConfigurationRequest()
                 {
-                    key = new List<string>() { StandardConfiguration.GetConfigurationMaxKeys }
+                    key = new List<string>() { }
                 };
 
                 WritetoDB(uuid, request);
@@ -345,6 +630,8 @@ namespace TestTool.RemoteTriggerAPP
             }
         }
 
+
+
         private void SetHardReset()
         {
             try
@@ -414,7 +701,7 @@ namespace TestTool.RemoteTriggerAPP
                     CreatedOn = DateTime.Now,
                     ChargeBoxId = uxChargeBoxIdTb.Text,
                     SerialNo = uuid,
-                    RequestContent = JsonConvert.SerializeObject(request, new JsonSerializerSettings() { NullValueHandling = NullValueHandling.Ignore }),
+                    RequestContent = JsonConvert.SerializeObject(request, new JsonSerializerSettings() { NullValueHandling = NullValueHandling.Ignore, Formatting = Formatting.None }),
                     EVSE_Status = 0,
                     Status = 0,
                     RequestType = 1,
@@ -427,7 +714,7 @@ namespace TestTool.RemoteTriggerAPP
                     CreatedBy = "TestTool",
                     CreatedOn = DateTime.Now,
                     OutAction = request.Action.ToString(),
-                    OutRequest = JsonConvert.SerializeObject(request, new JsonSerializerSettings() { NullValueHandling = NullValueHandling.Ignore }),
+                    OutRequest = JsonConvert.SerializeObject(request, new JsonSerializerSettings() { NullValueHandling = NullValueHandling.Ignore, Formatting = Formatting.None }),
                     SerialNo = uuid,
                     InMessage = string.Empty
 
@@ -436,5 +723,147 @@ namespace TestTool.RemoteTriggerAPP
                 db.SaveChanges();
             }
         }
+
+        private void uxFileSubmitBtn_Click(object sender, RoutedEventArgs e)
+        {
+            OpenFileDialog openFileDialog = new OpenFileDialog();
+            openFileDialog.Title = "Select file";
+            var result = openFileDialog.ShowDialog();
+            if (result == true)
+            {
+                uxUploadFileTb.Text = openFileDialog.FileName;
+            }
+        }
+
+        private void uxUploadBtn_Click(object sender, RoutedEventArgs e)
+        {
+            if (string.IsNullOrEmpty(uxUploadFileTb.Text))
+            {
+                uxMsgTb.Text = "Please select upload file!";
+                return;
+            }
+
+            FileInfo f = new FileInfo(uxUploadFileTb.Text);
+            int size = (int)f.Length;
+            string md5 = "";
+            string filePreUrl = ConfigurationManager.AppSettings["FilePreUrl"];
+            using (WebClient client = new WebClient())
+            {
+                client.UseDefaultCredentials = false;
+                client.Headers.Add("Content-Type", "application/octet-stream");
+                using (Stream fileStream = File.OpenRead(uxUploadFileTb.Text))
+                {
+                    var _md5 = MD5.Create();
+                    var hash = _md5.ComputeHash(fileStream);
+                    md5 = BitConverter.ToString(hash).Replace("-", String.Empty).ToLowerInvariant();
+                    //using (Stream requestStream = client.OpenWrite(new Uri(@filePreUrl + "UploadFiles/Fw/" + ufObj.FileName), "POST"))
+                    //{
+
+                    //    fileStream.CopyTo(requestStream);
+                    //}
+                }
+            }
+
+            UploadFile ufObj = new UploadFile();
+            ufObj.CreatedOn = DateTime.Now;
+            ufObj.FileExtensionName = System.IO.Path.GetExtension(uxUploadFileTb.Text);
+            ufObj.Id = Guid.NewGuid();
+            ufObj.FileName = md5 + ufObj.FileExtensionName;
+            ufObj.FilePath = "~/UploadFiles/Fw/" + ufObj.FileName;
+            ufObj.FileSize = size;
+            ufObj.FileMD5 = md5;
+            ufObj.CustomerId = new Guid("8456AED9-6DD9-4BF3-A94C-9F5DCB9506F7");
+            ufObj.OriginName = System.IO.Path.GetFileName(uxUploadFileTb.Text);
+            ufObj.FileUrl = new Uri(Properties.Settings.Default.FilePreUrl + ufObj.FilePath.Replace("~/","")).ToString();
+            ufObj.IsOnline = true;
+
+            using (var db = new MainDBContext())
+            {
+                db.UploadFile.Add(ufObj);
+                db.SaveChanges();
+                var pvQry = db.PublishVersion.Where(x => x.CustomerMachineComponentId == 1).OrderByDescending(c => c.Version).FirstOrDefault();
+                PublishVersion pv = new PublishVersion { CustomerMachineComponentId = 1, CreatedOn = DateTime.Now, Version = 1 };
+                if (pvQry != null)
+                {
+                    pv.Version = pvQry.Version + 1;
+                }
+                pv.PublishVersionFiles.Add(new PublishVersionFile() { UploadFileId = ufObj.Id });
+                db.PublishVersion.Add(pv);
+                db.SaveChanges();
+            }
+
+
+            uxMsgTb.Text = "write to DB ,but you must manaul upload file to server and filename replace with " + ufObj.FileName;
+
+        }
+
+        private void uxRefreshBtn_Click(object sender, RoutedEventArgs e)
+        {
+            using (var db = new MainDBContext())
+            {
+                publishes = db.PublishVersion
+                   .Include(c => c.PublishVersionFiles)
+                   .Include(c => c.PublishVersionFiles.Select(z => z.UploadFile))
+                   .Include(c => c.CustomerMachineComponent)
+                   .Include(c => c.CustomerMachineComponent.MachineComponent)
+                   .Include(c => c.CustomerMachineComponent.MachineComponent.MachineModel)
+                   .Include(c => c.CustomerMachineComponent.MachineComponent.MachinePart)
+                   .Where(c => c.CustomerMachineComponent.CustomerId == new Guid("8456AED9-6DD9-4BF3-A94C-9F5DCB9506F7") && c.CustomerMachineComponent.Id == 1 && c.CustomerMachineComponent.Id == 1).OrderByDescending(c => c.Id).Take(20).ToList();
+
+                StringBuilder sb = new StringBuilder();
+                uxPublishCb.Items.Clear();
+                foreach (var i in publishes)
+                {
+                    sb.Clear();
+                    sb.Append("_版本號:");
+                    sb.Append(i.Version);
+                    sb.Append("_上傳日期:");
+                    sb.Append(i.PublishVersionFiles.First().UploadFile.CreatedOn.ToString());
+                    sb.Append("_檔名:");
+                    foreach (var f in i.PublishVersionFiles)
+                    {
+                        sb.Append(f.UploadFile.OriginName);
+                        sb.Append("、");
+                    }
+                    uxPublishCb.Items.Add(sb.ToString());
+                    uxPublishCb.SelectedIndex = 0;
+                }
+            }
+
+        }
+
+        private void uxPublishBtn_Click(object sender, RoutedEventArgs e)
+        {
+            if (selectedPublish < 0)
+            {
+                uxMsgTb.Text = "Please choose publish version!";
+                return;
+            }
+            using (var db = new MainDBContext())
+            {
+
+                var machine = db.Machine.Where(x => x.ChargeBoxId == uxChargeBoxIdTb.Text).FirstOrDefault();
+                MachineVersion obj = new MachineVersion() { MachineId = machine.Id, PublishVersionId = publishes[selectedPublish].Id, CreatedOn = DateTime.Now };
+
+                obj.MachineVersionFiles.Add(new MachineVersionFile() { UploadFileId = publishes[selectedPublish].PublishVersionFiles.First().UploadFileId, CreatedOn = DateTime.Now });
+                db.MachineVersion.Add(obj);
+
+                //將machine的軟體更新更新到這個值
+
+                machine.FW_AssignedVersion = publishes[selectedPublish].Version;
+                machine.FW_MachineVersion = obj;
+
+                db.SaveChanges();
+            }
+            uxMsgTb.Text = "Publish Complete";
+
+
+        }
+
+        private void uxPublishCb_SelectionChanged(object sender, SelectionChangedEventArgs e)
+        {
+            selectedPublish = uxPublishCb.SelectedIndex;
+
+        }
     }
 }

+ 22 - 17
TestTool.RemoteTriggerAPP/Properties/Settings.Designer.cs

@@ -1,30 +1,35 @@
 //------------------------------------------------------------------------------
 // <auto-generated>
-//     This code was generated by a tool.
-//     Runtime Version:4.0.30319.42000
+//     這段程式碼是由工具產生的。
+//     執行階段版本:4.0.30319.42000
 //
-//     Changes to this file may cause incorrect behavior and will be lost if
-//     the code is regenerated.
+//     對這個檔案所做的變更可能會造成錯誤的行為,而且如果重新產生程式碼,
+//     變更將會遺失。
 // </auto-generated>
 //------------------------------------------------------------------------------
 
-namespace TestTool.RemoteTriggerAPP.Properties
-{
-
-
+namespace TestTool.RemoteTriggerAPP.Properties {
+    
+    
     [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
-    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")]
-    internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase
-    {
-
+    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.9.0.0")]
+    internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
+        
         private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
-
-        public static Settings Default
-        {
-            get
-            {
+        
+        public static Settings Default {
+            get {
                 return defaultInstance;
             }
         }
+        
+        [global::System.Configuration.ApplicationScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("http://test.evsocket.phihong.com.cn/")]
+        public string FilePreUrl {
+            get {
+                return ((string)(this["FilePreUrl"]));
+            }
+        }
     }
 }

+ 7 - 5
TestTool.RemoteTriggerAPP/Properties/Settings.settings

@@ -1,7 +1,9 @@
 <?xml version='1.0' encoding='utf-8'?>
-<SettingsFile xmlns="uri:settings" CurrentProfile="(Default)">
-  <Profiles>
-    <Profile Name="(Default)" />
-  </Profiles>
-  <Settings />
+<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)" GeneratedClassNamespace="TestTool.RemoteTriggerAPP.Properties" GeneratedClassName="Settings">
+  <Profiles />
+  <Settings>
+    <Setting Name="FilePreUrl" Type="System.String" Scope="Application">
+      <Value Profile="(Default)">http://test.evsocket.phihong.com.cn/</Value>
+    </Setting>
+  </Settings>
 </SettingsFile>

+ 4 - 1
TestTool.RemoteTriggerAPP/TestTool.RemoteTriggerAPP.csproj

@@ -52,6 +52,7 @@
     </Reference>
     <Reference Include="System" />
     <Reference Include="System.ComponentModel.DataAnnotations" />
+    <Reference Include="System.Configuration" />
     <Reference Include="System.Data" />
     <Reference Include="System.Xml" />
     <Reference Include="Microsoft.CSharp" />
@@ -109,7 +110,9 @@
     </None>
   </ItemGroup>
   <ItemGroup>
-    <None Include="App.config" />
+    <None Include="App.config">
+      <SubType>Designer</SubType>
+    </None>
   </ItemGroup>
   <ItemGroup>
     <Folder Include="DLL\" />