Robert 4 жил өмнө
commit
e102772ece
44 өөрчлөгдсөн 4999 нэмэгдсэн , 0 устгасан
  1. 261 0
      .gitignore
  2. 29 0
      AwInitilizer.sln
  3. 6 0
      AwInitilizer/App.config
  4. 10 0
      AwInitilizer/App.xaml
  5. 31 0
      AwInitilizer/App.xaml.cs
  6. 45 0
      AwInitilizer/Assist/SemaphoreQueue.cs
  7. 309 0
      AwInitilizer/Assist/SerialPortocol.cs
  8. 210 0
      AwInitilizer/Assist/TcpSerializer.cs
  9. 19 0
      AwInitilizer/Assist/WebClientTimeout.cs
  10. 29 0
      AwInitilizer/Converter/BooleanAndConverter.cs
  11. 133 0
      AwInitilizer/Initilizer.csproj
  12. 13 0
      AwInitilizer/Interface/IIogger.cs
  13. 26 0
      AwInitilizer/Interface/ISerialPort.cs
  14. 89 0
      AwInitilizer/MainViewModel.cs
  15. 144 0
      AwInitilizer/MainWindow.xaml
  16. 554 0
      AwInitilizer/MainWindow.xaml.cs
  17. 15 0
      AwInitilizer/Model/ButtonStatus.cs
  18. 16 0
      AwInitilizer/Model/EvseSerialResponseModel.cs
  19. 20 0
      AwInitilizer/Model/FirmwareUpdateModel.cs
  20. 19 0
      AwInitilizer/Model/SettingConfig.cs
  21. 15 0
      AwInitilizer/Model/SimStatus.cs
  22. 484 0
      AwInitilizer/Model/SystemID.cs
  23. 127 0
      AwInitilizer/Model/UpdateData.cs
  24. 21 0
      AwInitilizer/Model/UploadFile.cs
  25. 148 0
      AwInitilizer/Procedure/BasicInfoUpdateProcedure.cs
  26. 222 0
      AwInitilizer/Procedure/ButtonStatusCheckPorcedure.cs
  27. 370 0
      AwInitilizer/Procedure/FirmwareUpdateProcedure.cs
  28. 111 0
      AwInitilizer/Procedure/FourGenModuleCheckProcedure.cs
  29. 91 0
      AwInitilizer/Procedure/ProcedureBase.cs
  30. 150 0
      AwInitilizer/Procedure/RestarttoIdelProcedure.cs
  31. 55 0
      AwInitilizer/Properties/AssemblyInfo.cs
  32. 63 0
      AwInitilizer/Properties/Resources.Designer.cs
  33. 117 0
      AwInitilizer/Properties/Resources.resx
  34. 26 0
      AwInitilizer/Properties/Settings.Designer.cs
  35. 7 0
      AwInitilizer/Properties/Settings.settings
  36. 76 0
      AwInitilizer/app.manifest
  37. 4 0
      AwInitilizer/packages.config
  38. 849 0
      AwInitlizerInstaller/AwInitlizerInstaller.vdproj
  39. 9 0
      Initilizer/App.xaml
  40. 17 0
      Initilizer/App.xaml.cs
  41. 10 0
      Initilizer/AssemblyInfo.cs
  42. 9 0
      Initilizer/Initilizer.csproj
  43. 12 0
      Initilizer/MainWindow.xaml
  44. 28 0
      Initilizer/MainWindow.xaml.cs

+ 261 - 0
.gitignore

@@ -0,0 +1,261 @@
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+
+# User-specific files
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+
+# Visual Studio 2015 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUNIT
+*.VisualState.xml
+TestResult.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# DNX
+project.lock.json
+project.fragment.lock.json
+artifacts/
+
+*_i.c
+*_p.c
+*_i.h
+*.ilk
+*.meta
+*.obj
+*.pch
+*.pdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*.log
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# JustCode is a .NET coding add-in
+.JustCode
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# TODO: Comment the next line if you want to checkin your web deploy settings
+# but database connection strings (with potential passwords) will be unencrypted
+#*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# The packages folder can be ignored because of Package Restore
+**/packages/*
+# except build/, which is used as an MSBuild target.
+!**/packages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/packages/repositories.config
+# NuGet v3's project.json files produces more ignoreable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+node_modules/
+orleans.codegen.cs
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+
+# SQL Server files
+*.mdf
+*.ldf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# JetBrains Rider
+.idea/
+*.sln.iml
+
+# CodeRush
+.cr/
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc

+ 29 - 0
AwInitilizer.sln

@@ -0,0 +1,29 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.30413.136
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Initilizer", "AwInitilizer\Initilizer.csproj", "{7A23D514-38E1-423E-9238-464B0E2AFCC0}"
+EndProject
+Project("{54435603-DBB4-11D2-8724-00A0C9A8B90C}") = "AwInitlizerInstaller", "AwInitlizerInstaller\AwInitlizerInstaller.vdproj", "{9A5A71D0-545F-43BB-9411-467C30365306}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Any CPU = Debug|Any CPU
+		Release|Any CPU = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{7A23D514-38E1-423E-9238-464B0E2AFCC0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{7A23D514-38E1-423E-9238-464B0E2AFCC0}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{7A23D514-38E1-423E-9238-464B0E2AFCC0}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{7A23D514-38E1-423E-9238-464B0E2AFCC0}.Release|Any CPU.Build.0 = Release|Any CPU
+		{9A5A71D0-545F-43BB-9411-467C30365306}.Debug|Any CPU.ActiveCfg = Debug
+		{9A5A71D0-545F-43BB-9411-467C30365306}.Release|Any CPU.ActiveCfg = Release
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+	GlobalSection(ExtensibilityGlobals) = postSolution
+		SolutionGuid = {F83AB2ED-7223-44BF-A441-9175A5E1B45F}
+	EndGlobalSection
+EndGlobal

+ 6 - 0
AwInitilizer/App.config

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<configuration>
+    <startup> 
+        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8"/>
+    </startup>
+</configuration>

+ 10 - 0
AwInitilizer/App.xaml

@@ -0,0 +1,10 @@
+<Application x:Class="AwInitilizer.App"
+             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+             xmlns:local="clr-namespace:AwInitilizer" 
+             xmlns:converterNamespace="clr-namespace:AwInitilizer.Converter"
+             StartupUri="MainWindow.xaml">
+    <Application.Resources>
+        <converterNamespace:BooleanAndConverter x:Key="booleanAndConverter" />
+    </Application.Resources>
+</Application>

+ 31 - 0
AwInitilizer/App.xaml.cs

@@ -0,0 +1,31 @@
+using System;
+using System.Collections.Generic;
+using System.Configuration;
+using System.Data;
+using System.IO;
+using System.Linq;
+using System.Threading.Tasks;
+using System.Windows;
+
+namespace AwInitilizer
+{
+    /// <summary>
+    /// Interaction logic for App.xaml
+    /// </summary>
+    public partial class App : Application
+    {
+        public App():base()
+        {
+            DispatcherUnhandledException += App_DispatcherUnhandledException;
+        }
+
+        private void App_DispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
+        {
+            var fileName = DateTime.Now.ToString("yyyyMMddHHmmss") + ".txt";
+            File.WriteAllText(fileName,e.Exception.Message);
+            File.WriteAllText(fileName, e.Exception.StackTrace);
+            MessageBox.Show($"App crashed,Please report error and send back {fileName}");
+            Application.Current.Shutdown();
+        }
+    }
+}

+ 45 - 0
AwInitilizer/Assist/SemaphoreQueue.cs

@@ -0,0 +1,45 @@
+using System;
+using System.Collections.Concurrent;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace AwInitilizer.Assist
+{
+    public class SemaphoreQueue
+    {
+        private SemaphoreSlim semaphore;
+        private ConcurrentQueue<TaskCompletionSource<bool>> queue =
+            new ConcurrentQueue<TaskCompletionSource<bool>>();
+        public SemaphoreQueue(int initialCount)
+        {
+            semaphore = new SemaphoreSlim(initialCount);
+        }
+        public SemaphoreQueue(int initialCount, int maxCount)
+        {
+            semaphore = new SemaphoreSlim(initialCount, maxCount);
+        }
+        public void Wait()
+        {
+            WaitAsync().Wait();
+        }
+        public Task WaitAsync()
+        {
+            var tcs = new TaskCompletionSource<bool>();
+            queue.Enqueue(tcs);
+            semaphore.WaitAsync().ContinueWith(t =>
+            {
+                TaskCompletionSource<bool> popped;
+                if (queue.TryDequeue(out popped))
+                    popped.SetResult(true);
+            });
+            return tcs.Task;
+        }
+        public void Release()
+        {
+            semaphore.Release();
+        }
+    }
+}

+ 309 - 0
AwInitilizer/Assist/SerialPortocol.cs

@@ -0,0 +1,309 @@
+using AwInitilizer.Model;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Linq;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace AwInitilizer.Assist
+{
+    public class SerialPortocol : INotifyPropertyChanged
+    {
+        private static int TimeoutDuration = 1 * 1000;
+
+        public event EventHandler<EvseSerialResponseModel> OnMsgReceived;
+        public event PropertyChangedEventHandler PropertyChanged;
+
+        private Interface.ISerialPort _serialPort;
+
+        private SemaphoreQueue receivedBufferLock = new SemaphoreQueue(1, 1);
+        private byte[] receivedBuffer = new byte[0];
+
+        private bool IsSerialPortAvaliable
+        {
+            get
+            {
+                if (_serialPort == null || _serialPort.ConnectStatus != Interface.ConnectStatus.Connected)
+                    return false;
+                return true;
+            }
+        }
+
+        public void Open() => _serialPort?.Open();
+        public void Close() => _serialPort?.Close();
+
+        public Interface.ConnectStatus ConnectStatus => _serialPort == null ? Interface.ConnectStatus.Cleared : _serialPort.ConnectStatus;
+
+        public SerialPortocol(Interface.ISerialPort serialPort)
+        {
+            _serialPort = serialPort;
+            _serialPort.OnDataReceived += _serialPort_OnDataReceived;
+            _serialPort.PropertyChanged += _serialPort_PropertyChanged;
+        }
+
+        public async Task<string> GetModelName()
+        {
+            return await SendAndWait(0x24, SimpleStringParser);
+        }
+
+        public async Task<bool> SetModelName(string modelName)
+        {
+            var param = Encoding.ASCII.GetBytes(modelName);
+            return await SendAndWait(0x83, SimpleResultParser, parameter: param);
+        }
+
+        public async Task<string> GetSerialNumber()
+        {
+            return await SendAndWait(0x23, SerialNumberParser);
+
+            string SerialNumberParser(byte[] parameter)
+            {
+                if (parameter == null || parameter.Length < 19)
+                    return null;
+
+                var snBytes = parameter.Skip(8).ToArray();
+                return SimpleStringParser(snBytes);
+            }
+        }
+
+        public async Task<bool> SetSerialNumber(string serialNumber)
+        {
+            DateTime nowTime = DateTime.Now.ToUniversalTime();
+
+            var DataString = nowTime.ToString("yyyyMMdd");
+            var dateTimeParam = Encoding.ASCII.GetBytes(DataString);
+
+            var snParam = Encoding.ASCII.GetBytes(serialNumber);
+
+            var param = new byte[dateTimeParam.Length + snParam.Length];
+            Array.Copy(dateTimeParam, 0, param, 0, dateTimeParam.Length);
+            Array.Copy(snParam, 0, param, dateTimeParam.Length, snParam.Length);
+            return await SendAndWait(0x82, SimpleResultParser, parameter: param);
+        }
+
+        public async Task<DateTime?> GetUTCTime()
+        {
+            return await SendAndWait(0x26, TimeParser);
+
+            DateTime? TimeParser(byte[] parameter)
+            {
+                if (parameter == null || parameter.Length < 14)
+                    return null;
+
+                string rawDateString = Encoding.ASCII.GetString(parameter);
+
+                var year = int.Parse(rawDateString.Substring(0,4));
+                var month = int.Parse(rawDateString.Substring(4, 2));
+                var day = int.Parse(rawDateString.Substring(6, 2));
+                var hour = int.Parse(rawDateString.Substring(8, 2));
+                var minut = int.Parse(rawDateString.Substring(10, 2));
+                var sec = int.Parse(rawDateString.Substring(12, 2));
+
+                try
+                {
+                    DateTime dateTime = new DateTime(year, month, day, hour, minut, sec);
+                    return dateTime;
+                }
+                catch
+                {
+                    return null;
+                }
+            }
+        }
+
+        public async Task<bool> SetUTCTime(DateTime dateTime)
+        {
+            var DataString = dateTime.ToString("yyyyMMddHHmmss");
+            var param = Encoding.ASCII.GetBytes(DataString);
+            return await SendAndWait(0x87, SimpleResultParser, parameter: param);
+        }
+
+        public async Task<string> GetFourGenModuleVersion()
+        {
+            return await SendAndWait(0x31, SimpleStringParser);
+        }
+
+        public async Task<SimStatus> GetSimStatus()
+        {
+            return await SendAndWait(0x34, SimStatusParser);
+
+            SimStatus SimStatusParser(byte[] param)
+            {
+                if(param==null || param.Length != 39)
+                {
+                    return null;
+                }
+
+                SimStatus toReturn = new SimStatus();
+                toReturn.IsInstalled = param[0] == 0x01;
+                toReturn.ICCID = param.Skip(1).Take(22).ToArray();
+                toReturn.IMSI = param.Skip(22).Take(16).ToArray();
+                return toReturn;
+            }
+        }
+
+        public async Task<bool> SettingChangeConfirm()
+        {
+            return await SendAndWait(0x91, SimpleResultParser, WaitSec: 10);
+        }
+
+        private void _serialPort_PropertyChanged(object sender, PropertyChangedEventArgs e)
+        {
+            if (e.PropertyName == nameof(Interface.ISerialPort.ConnectStatus))
+            {
+                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(SerialPortocol.ConnectStatus)));
+            }
+        }
+
+        private async Task<T> SendAndWait<T>(byte command, Func<byte[], T> ParserFunction, byte[] parameter = null, T defauit = default(T), int WaitSec = -1)
+        {
+            if (!IsSerialPortAvaliable)
+                return defauit;
+
+            T result = defauit;
+            SemaphoreSlim signal = new SemaphoreSlim(0, 1);
+
+            OnMsgReceived += EvseSerialProtocal_OnMsgReceived;
+            if (SendMessage(command, parameter))
+            {
+                if (WaitSec < 0)
+                    await signal.WaitAsync(TimeoutDuration);
+                else
+                    await signal.WaitAsync(WaitSec * 1000);
+            }
+            OnMsgReceived -= EvseSerialProtocal_OnMsgReceived;
+
+            return result;
+
+            void EvseSerialProtocal_OnMsgReceived(object sender, EvseSerialResponseModel e)
+            {
+                if (e.Command == command)
+                {
+                    result = ParserFunction(e.Parameter);
+                    signal.Release();
+                }
+            }
+        }
+
+        private bool SendMessage(byte command, byte[] parameter = null)
+        {
+            if (!IsSerialPortAvaliable)
+                return false;
+
+            int parameterLength = parameter == null ? 0 : parameter.Length;
+            int messagLength = parameterLength + 7;
+
+            byte[] message = new byte[parameterLength + 7];
+            message[0] = 0xAA;
+            message[1] = 0x10; //Master
+            message[2] = 0xFF; //broadcast
+            message[3] = command;
+            message[4] = (byte)(parameterLength % 256);
+            message[5] = (byte)(parameterLength / 256);
+            if (parameter != null && parameter.Length > 0)
+                Array.Copy(parameter, 0, message, 6, parameter.Length);
+
+            byte chksum = 0x00;
+            for (int idx = 0; idx < parameterLength; idx++)
+                chksum ^= message[6 + idx];
+            message[6 + parameterLength] = chksum;
+
+            _serialPort?.WriteData(message);
+            //_serialPort?.WriteData(message);
+
+            return true;
+        }
+
+        private void _serialPort_OnDataReceived(object sender, byte[] e)
+        {
+            receivedBufferLock.Wait();
+            {
+                var tmp = new byte[e.Length + receivedBuffer.Length];
+                Array.Copy(receivedBuffer, 0, tmp, 0, receivedBuffer.Length);
+                Array.Copy(e, 0, tmp, receivedBuffer.Length, e.Length);
+                //receivedBuffer = tmp;
+
+                receivedBuffer = ParseReceive(tmp, out List<EvseSerialResponseModel> reponseModels);
+
+                foreach (EvseSerialResponseModel responseModel in reponseModels)
+                {
+                    OnMsgReceived?.Invoke(this, responseModel);
+                }
+            }
+            receivedBufferLock.Release();
+        }
+
+        private bool SimpleResultParser(byte[] parameter)
+        {
+            if (parameter == null || parameter.Length != 1)
+                return false;
+            var resultByte = parameter[0];
+
+            return resultByte == 0x01;
+        }
+
+        private string SimpleStringParser(byte[] parameter)
+        {
+            if (parameter == null || parameter.Length <= 1)
+                return string.Empty;
+            if(parameter.ToList().Contains(0x00))
+            {
+                int endIndex = Array.FindIndex(parameter, (x) => { return x == 0x00; });
+                //int endIndex = parameter.FindIndex((x) => { return x == 0x00; });
+                if (endIndex != default)
+                {
+                    parameter = parameter.Take(endIndex).ToArray();
+                }
+            }
+            while (parameter.Length != 0 && parameter[parameter.Length - 1] < 32)
+            {
+                parameter = parameter.Take(parameter.Length - 1).ToArray();
+            }
+            var result = Encoding.ASCII.GetString(parameter);
+            return result;
+        }
+
+        private byte[] ParseReceive(byte[] parseData, out List<EvseSerialResponseModel> reponseModels)
+        {
+            reponseModels = new List<EvseSerialResponseModel>();
+
+            while (true)
+            {
+                int stIndex = -1;
+                //find first 0xff 0xff
+                for (int index = 0; index < parseData.Length - 1; index++)
+                {
+                    if (parseData[index] == 0xAA)
+                    {
+                        stIndex = index;
+                        break;
+                    }
+                }
+                //int index = Array.IndexOf(receivedBuffer, startChar);
+                if (stIndex < 0)
+                    break;
+                //discard data before 0xaa
+                parseData = parseData.Skip(stIndex).ToArray();
+                //response msg is at leat 6 bytes
+                if (parseData.Length < 6)
+                    break;
+                var msgLength = parseData[5] * 256 + parseData[4];
+                if (parseData.Length < msgLength + 6)
+                    break;
+                //Add handle data
+
+                reponseModels.Add(new EvseSerialResponseModel() { 
+                    Source = parseData[1],
+                    Destination = parseData[2],
+                    Command = parseData[3],
+                    Parameter = parseData.Skip(6).Take(msgLength).ToArray()
+                });
+                parseData = parseData.Skip(msgLength + 6).ToArray();
+            }
+
+            return parseData;
+        }
+    }
+}

+ 210 - 0
AwInitilizer/Assist/TcpSerializer.cs

@@ -0,0 +1,210 @@
+using AwInitilizer.Interface;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Linq;
+using System.Net;
+using System.Net.Sockets;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace AwInitilizer.Assist
+{
+    public class TcpSerializer : Interface.ISerialPort
+    {
+        public event EventHandler<byte[]> OnDataReceived;
+        public event PropertyChangedEventHandler PropertyChanged;
+
+        public string IP { get; private set; }
+
+        private ConnectStatus _ConnectStatus = ConnectStatus.Cleared;
+        public ConnectStatus ConnectStatus
+        {
+            get => _ConnectStatus;
+            set
+            {
+                if (_ConnectStatus != value)
+                {
+                    _ConnectStatus = value;
+                    PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("ConnectStatus"));
+                }
+            }
+        }
+
+        private IPAddress iPAddress;
+        private IPEndPoint iPEndPoint;
+        private Socket tcpSocket;
+
+        public TcpSerializer(string ip = "192.168.1.10",int port = 8234)
+        {
+            IP = ip;
+
+            iPAddress = IPAddress.Parse(ip);
+            iPEndPoint = new IPEndPoint(iPAddress, port);
+        }
+
+        public async Task OpenAsync()
+        {
+            await Conenct();
+        }
+
+        public void Open()
+        {
+            _ = Conenct();
+        }
+
+        public void Close()
+        {
+            ConnectStatus = ConnectStatus.DisConnected;
+            try
+            {
+                tcpSocket?.Close();
+                tcpSocket?.Dispose();
+            }
+            catch
+            {
+
+            }
+        }
+
+        public void WriteData(byte[] msg)
+        {
+            if (ConnectStatus != ConnectStatus.Connected)
+                return;
+            tcpSocket.Send(msg);
+        }
+
+        private async Task Conenct()
+        {
+            ConnectStatus = ConnectStatus.Connecting;
+
+            tcpSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
+            tcpSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
+            var connectTask = tcpSocket.ConnectAsync(iPEndPoint);
+            //var asyncResult = tcpSocket.BeginConnect(iPEndPoint, OnTcpConnectComplete, null);
+            //await Task.Delay(2 * 1000);
+            await Task.WhenAny(connectTask, Task.Delay(2 * 1000));
+            if (tcpSocket.Connected)
+            {
+                ConnectStatus = ConnectStatus.Connected;
+
+                var stateObject = new StateObject(bufferSize: 512, tcpSocket);
+                WaitForData(stateObject);
+            }
+            else
+            {
+                ConnectStatus = ConnectStatus.ConnectionFail;
+
+                //Try Clear - disconnect
+                Close();
+            }
+        }
+
+        private void OnTcpConnectComplete(IAsyncResult ar)
+        {
+            if (tcpSocket.Connected)
+            {
+                ConnectStatus = ConnectStatus.Connected;
+
+                var stateObject = new StateObject(bufferSize: 512, tcpSocket);
+                WaitForData(stateObject);
+            }
+            else
+            {
+                ConnectStatus = ConnectStatus.ConnectionFail;
+            }
+        }
+
+        private void WaitForData(StateObject stateObject)
+        {
+            try
+            {
+                var soc = stateObject.sSocket;
+
+                if (!soc.Connected) { return; }
+
+                IAsyncResult iar = soc.BeginReceive(
+                    stateObject.sBuffer,
+                    0,
+                    stateObject.sBuffer.Length,
+                    SocketFlags.None,
+                    new AsyncCallback(ReveiveCallBack),
+                    stateObject);
+            }
+            catch (Exception e)
+            {
+                if (e != null)
+                {
+                    if (e.Message != null)
+                        Console.WriteLine(e.Message);
+                    if (e.StackTrace != null)
+                        Console.WriteLine(e.StackTrace);
+                }
+            }
+        }
+
+        private void ReveiveCallBack(IAsyncResult ar)
+        {
+            StateObject stateObject = (StateObject)ar.AsyncState;
+
+            if (!stateObject.sSocket.Connected)
+            {
+                //server Diconnected
+                HandleDisconnected();
+                return;
+            }
+
+            int bytesReceived;
+            try
+            {
+                bytesReceived = stateObject.sSocket.EndReceive(ar);
+            }
+            catch (SocketException e)
+            {
+                if (e != null)
+                {
+                    if (e.Message != null)
+                        System.Diagnostics.Debug.WriteLine(e.Message);
+                    if (e.StackTrace != null)
+                        System.Diagnostics.Debug.WriteLine(e.StackTrace);
+                }
+
+                //server Diconnected
+                HandleDisconnected();
+                return;
+            }
+
+            if (bytesReceived == 0)
+            {
+                stateObject.sSocket.Disconnect(true);
+                HandleDisconnected();
+                return;
+            }
+
+            byte[] receivedBytes = new byte[bytesReceived];
+            Array.Copy(stateObject.sBuffer, 0, receivedBytes, 0, bytesReceived);
+
+            OnDataReceived?.Invoke(this, receivedBytes);
+
+            //continue receive
+            WaitForData(stateObject);
+        }
+
+        private void HandleDisconnected()
+        {
+            Close();
+        }
+    }
+
+    internal class StateObject
+    {
+        public byte[] sBuffer;
+        public Socket sSocket;
+
+        public StateObject(int bufferSize, Socket sock, int timeOutMilliSecond = -1)
+        {
+            sBuffer = new byte[bufferSize];
+            sSocket = sock;
+        }
+    }
+}

+ 19 - 0
AwInitilizer/Assist/WebClientTimeout.cs

@@ -0,0 +1,19 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Net;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace AwInitilizer.Assist
+{
+    public class WebClientTimeout : WebClient
+    {
+        protected override WebRequest GetWebRequest(Uri uri)
+        {
+            WebRequest w = base.GetWebRequest(uri);
+            w.Timeout = 2 * 1000;
+            return w;
+        }
+    }
+}

+ 29 - 0
AwInitilizer/Converter/BooleanAndConverter.cs

@@ -0,0 +1,29 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Data;
+
+namespace AwInitilizer.Converter
+{
+    public class BooleanAndConverter : IMultiValueConverter
+    {
+        public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
+        {
+            foreach (object value in values)
+            {
+                if ((value is bool) && (bool)value == false)
+                {
+                    return false;
+                }
+            }
+            return true;
+        }
+
+        public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
+        {
+            throw new NotSupportedException("BooleanAndConverter is a OneWay converter.");
+        }
+    }
+}

+ 133 - 0
AwInitilizer/Initilizer.csproj

@@ -0,0 +1,133 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProjectGuid>{7A23D514-38E1-423E-9238-464B0E2AFCC0}</ProjectGuid>
+    <OutputType>WinExe</OutputType>
+    <RootNamespace>AwInitilizer</RootNamespace>
+    <AssemblyName>AwInitilizer</AssemblyName>
+    <TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
+    <FileAlignment>512</FileAlignment>
+    <ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+    <WarningLevel>4</WarningLevel>
+    <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
+    <Deterministic>true</Deterministic>
+    <TargetFrameworkProfile />
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <PlatformTarget>AnyCPU</PlatformTarget>
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <PlatformTarget>AnyCPU</PlatformTarget>
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup>
+    <ApplicationManifest>app.manifest</ApplicationManifest>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="Newtonsoft.Json, Version=12.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
+      <HintPath>..\packages\Newtonsoft.Json.12.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
+    </Reference>
+    <Reference Include="System" />
+    <Reference Include="System.Data" />
+    <Reference Include="System.Web" />
+    <Reference Include="System.Xml" />
+    <Reference Include="Microsoft.CSharp" />
+    <Reference Include="System.Core" />
+    <Reference Include="System.Xml.Linq" />
+    <Reference Include="System.Data.DataSetExtensions" />
+    <Reference Include="System.Net.Http" />
+    <Reference Include="System.Xaml">
+      <RequiredTargetFramework>4.0</RequiredTargetFramework>
+    </Reference>
+    <Reference Include="WindowsBase" />
+    <Reference Include="PresentationCore" />
+    <Reference Include="PresentationFramework" />
+  </ItemGroup>
+  <ItemGroup>
+    <ApplicationDefinition Include="App.xaml">
+      <Generator>MSBuild:Compile</Generator>
+      <SubType>Designer</SubType>
+    </ApplicationDefinition>
+    <Page Include="MainWindow.xaml">
+      <Generator>MSBuild:Compile</Generator>
+      <SubType>Designer</SubType>
+    </Page>
+    <Compile Include="App.xaml.cs">
+      <DependentUpon>App.xaml</DependentUpon>
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="Assist\SemaphoreQueue.cs" />
+    <Compile Include="Assist\SerialPortocol.cs" />
+    <Compile Include="Assist\TcpSerializer.cs" />
+    <Compile Include="Assist\WebClientTimeout.cs">
+      <SubType>Component</SubType>
+    </Compile>
+    <Compile Include="Converter\BooleanAndConverter.cs" />
+    <Compile Include="Interface\IIogger.cs" />
+    <Compile Include="Interface\ISerialPort.cs" />
+    <Compile Include="MainViewModel.cs" />
+    <Compile Include="MainWindow.xaml.cs">
+      <DependentUpon>MainWindow.xaml</DependentUpon>
+      <SubType>Code</SubType>
+    </Compile>
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="Model\ButtonStatus.cs" />
+    <Compile Include="Model\FirmwareUpdateModel.cs" />
+    <Compile Include="Model\SettingConfig.cs" />
+    <Compile Include="Model\UploadFile.cs" />
+    <Compile Include="Procedure\ButtonStatusCheckPorcedure.cs" />
+    <Compile Include="Model\EvseSerialResponseModel.cs" />
+    <Compile Include="Model\SimStatus.cs" />
+    <Compile Include="Procedure\BasicInfoUpdateProcedure.cs" />
+    <Compile Include="Procedure\FirmwareUpdateProcedure.cs" />
+    <Compile Include="Procedure\FourGenModuleCheckProcedure.cs" />
+    <Compile Include="Procedure\ProcedureBase.cs" />
+    <Compile Include="Model\SystemID.cs" />
+    <Compile Include="Model\UpdateData.cs" />
+    <Compile Include="Procedure\RestarttoIdelProcedure.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="Properties\Resources.Designer.cs">
+      <AutoGen>True</AutoGen>
+      <DesignTime>True</DesignTime>
+      <DependentUpon>Resources.resx</DependentUpon>
+    </Compile>
+    <Compile Include="Properties\Settings.Designer.cs">
+      <AutoGen>True</AutoGen>
+      <DependentUpon>Settings.settings</DependentUpon>
+      <DesignTimeSharedInput>True</DesignTimeSharedInput>
+    </Compile>
+    <EmbeddedResource Include="Properties\Resources.resx">
+      <Generator>ResXFileCodeGenerator</Generator>
+      <LastGenOutput>Resources.Designer.cs</LastGenOutput>
+    </EmbeddedResource>
+    <None Include="app.manifest" />
+    <None Include="packages.config" />
+    <None Include="Properties\Settings.settings">
+      <Generator>SettingsSingleFileGenerator</Generator>
+      <LastGenOutput>Settings.Designer.cs</LastGenOutput>
+    </None>
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="App.config" />
+  </ItemGroup>
+  <ItemGroup />
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+</Project>

+ 13 - 0
AwInitilizer/Interface/IIogger.cs

@@ -0,0 +1,13 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace AwInitilizer.Interface
+{
+    public interface IIogger
+    {
+        void Print(string msg,bool isError = false);
+    }
+}

+ 26 - 0
AwInitilizer/Interface/ISerialPort.cs

@@ -0,0 +1,26 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace AwInitilizer.Interface
+{
+    public enum ConnectStatus
+    {
+        Cleared, Connecting, Connected, DisConnected, ConnectionFail
+    }
+
+    public interface ISerialPort : INotifyPropertyChanged
+    {
+        ConnectStatus ConnectStatus { get; }
+
+        void Open();
+        Task OpenAsync();
+        void Close();
+
+        void WriteData(byte[] msg);
+        event EventHandler<byte[]> OnDataReceived;
+    }
+}

+ 89 - 0
AwInitilizer/MainViewModel.cs

@@ -0,0 +1,89 @@
+using AwInitilizer.Procedure;
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.ComponentModel;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace AwInitilizer
+{
+    public class MainViewModel : Model.UpdateData,INotifyPropertyChanged
+    {
+        private bool _IsUdatIng = false;
+        public bool IsUdatIng
+        {
+            get => _IsUdatIng;
+            set
+            {
+                if(_IsUdatIng!=value)
+                {
+                    _IsUdatIng = value;
+                    RaisePropertyChanged("IsUdatIng");
+                    RaisePropertyChanged("IsInputLock");
+                }
+            }
+        }
+
+        public bool IsInputLock => !IsUdatIng;
+
+        private string _SettingFileName;
+        public string SettingFileName
+        {
+            get => _SettingFileName;
+            set
+            {
+                if (_SettingFileName != value)
+                {
+                    _SettingFileName = value;
+                    RaisePropertyChanged("SettingFileName");
+                }
+            }
+        }
+
+        private string _SettingModelName;
+        public string SettingModelName
+        {
+            get => _SettingModelName;
+            set
+            {
+                if (_SettingModelName != value)
+                {
+                    _SettingModelName = value;
+                    RaisePropertyChanged("SettingModelName");
+                }
+            }
+        }
+
+        private ObservableCollection<ProcedureBase> _updateProcedure;
+        public ObservableCollection<ProcedureBase> UpdateProcedure
+        {
+            get => _updateProcedure;
+            set
+            {
+                if (_updateProcedure != value)
+                {
+                    if(_updateProcedure!=null)
+                    {
+                        _updateProcedure.CollectionChanged -= _updateProcedure_CollectionChanged;
+                    }
+
+                    _updateProcedure = value;
+                    RaisePropertyChanged("UpdateProcedure");
+                }
+            }
+        }
+
+        public MainViewModel()
+        {
+            _updateProcedure = new ObservableCollection<ProcedureBase>();
+            _updateProcedure.CollectionChanged += _updateProcedure_CollectionChanged;
+        }
+
+        private void _updateProcedure_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
+        {
+            RaisePropertyChanged("UpdateProcedure");
+        }
+    }
+}

+ 144 - 0
AwInitilizer/MainWindow.xaml

@@ -0,0 +1,144 @@
+<Window x:Class="AwInitilizer.MainWindow"
+        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
+        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+        xmlns:local="clr-namespace:AwInitilizer"
+        mc:Ignorable="d"
+        Title="Initlizer" Height="1023" Width="789.5" Background="#FF363535" >
+    <Window.Resources>
+    </Window.Resources>
+    <Viewbox>
+        <StackPanel Orientation="Vertical" Margin="10">
+            <GroupBox>
+                <GroupBox.Header>
+                    <Label Content="Barcode Setting" Foreground="White" FontSize="16"/>
+                </GroupBox.Header>
+                <StackPanel Orientation="Vertical">
+                    <StackPanel Orientation="Horizontal">
+                        <StackPanel Orientation="Horizontal" Height="30">
+                            <Grid Width="200">
+                                <Label Content="Model Name" Foreground="White" FontSize="16" HorizontalAlignment="Center"/>
+                            </Grid>
+                            <TextBox x:Name="uxModelName" Text="{Binding ModelName}" IsEnabled="{Binding IsInputLock}" IsReadOnly="True" Width="170" FontSize="16" TextAlignment="Center" VerticalContentAlignment="Center"/>
+                        </StackPanel>
+                        <StackPanel Orientation="Horizontal" Height="30">
+                            <Grid Width="200">
+                                <Label Content="Serial Number" Foreground="White" FontSize="16" HorizontalAlignment="Center"/>
+                            </Grid>
+                            <TextBox x:Name="uxSerialNumber" Text="{Binding SerialNumber}" IsEnabled="{Binding IsInputLock}" IsReadOnly="True" Width="170" FontSize="16" TextAlignment="Center" VerticalContentAlignment="Center"/>
+                        </StackPanel>
+                    </StackPanel>
+                    <Frame Height="10"/>
+                </StackPanel>
+            </GroupBox>
+            <GroupBox>
+                <GroupBox.Header>
+                    <Label Content="Config Setting" Foreground="White" FontSize="16"/>
+                </GroupBox.Header>
+                <StackPanel Orientation="Vertical">
+                    <StackPanel Orientation="Horizontal" Height="30">
+                        <Grid Width="200">
+                            <Label Content="Setting File" Foreground="White" FontSize="16" HorizontalAlignment="Center"/>
+                        </Grid>
+                        <TextBox x:Name="uxSettingFile" Text="{Binding SettingFileName}" IsEnabled="{Binding IsInputLock}" IsReadOnly="True" Width="510" FontSize="16" TextAlignment="Center" VerticalContentAlignment="Center"/>
+                        <Button Width="30" Click="SettingFileSelect_Click" IsEnabled="{Binding IsInputLock}">
+                            <Label Content="..."/>
+                        </Button>
+                    </StackPanel>
+                    <Frame Height="10"/>
+                    <StackPanel Orientation="Horizontal" Height="30">
+                        <Grid Width="200">
+                            <Label Content="4G Module Reversiion" Foreground="White" FontSize="16" HorizontalAlignment="Center"/>
+                        </Grid>
+                        <TextBox x:Name="uxFourGModuleVer" Text="{Binding FourGenModuleVersion}" IsEnabled="{Binding IsInputLock}" IsReadOnly="True" Width="540" FontSize="16" TextAlignment="Center" VerticalContentAlignment="Center"/>
+                    </StackPanel>
+                    <Frame Height="10"/>
+                    <StackPanel Orientation="Horizontal" Height="30">
+                        <Grid Width="200">
+                            <Label Content="4G Sim Card Information" Foreground="White" FontSize="16" HorizontalAlignment="Center"/>
+                        </Grid>
+                        <CheckBox x:Name="uxIsSimCheckEnabled" IsChecked="{Binding IsSimInsert}" IsEnabled="{Binding IsInputLock}" IsHitTestVisible="False" VerticalAlignment="Center" />
+                        <Grid Width="10"/>
+                        <Grid Width="70">
+                            <Label Content="ICCID" Foreground="White" FontSize="16" HorizontalAlignment="Center"/>
+                        </Grid>
+                        <Grid Width="10"/>
+                        <TextBox x:Name="uxICCID" Text="{Binding ICCID}" IsReadOnly="True" Width="176" FontSize="16" TextAlignment="Center" VerticalContentAlignment="Center">
+                            <TextBox.IsEnabled>
+                                <MultiBinding Converter="{StaticResource booleanAndConverter}">
+                                    <Binding Path="IsSimInsert" />
+                                    <Binding Path="IsInputLock" />
+                                </MultiBinding>
+                            </TextBox.IsEnabled>
+                        </TextBox>
+                        <Grid Width="70">
+                            <Label Content="IMSI" Foreground="White" FontSize="16" HorizontalAlignment="Center"/>
+                        </Grid>
+                        <Grid Width="10"/>
+                        <TextBox x:Name="uxIMSI" Text="{Binding IMSI}" IsReadOnly="True" Width="176" FontSize="16" TextAlignment="Center" VerticalContentAlignment="Center">
+                            <TextBox.IsEnabled>
+                                <MultiBinding Converter="{StaticResource booleanAndConverter}">
+                                    <Binding Path="IsSimInsert" />
+                                    <Binding Path="IsInputLock" />
+                                </MultiBinding>
+                            </TextBox.IsEnabled>
+                        </TextBox>
+                        <Grid Width="10"/>
+                    </StackPanel>
+                    <Frame Height="10"/>
+                </StackPanel>
+            </GroupBox>
+
+            <GroupBox>
+                <GroupBox.Header>
+                    <Label Content="Firmware version" Foreground="White" FontSize="16"/>
+                </GroupBox.Header>
+
+                <DataGrid AutoGenerateColumns="False" Margin="10" Height="150" CanUserSortColumns="False" IsEnabled="{Binding IsInputLock}" ItemsSource="{Binding FirmwareUpdateModels}">
+                    <DataGrid.Columns>
+                        <DataGridTextColumn Header="Module" Width="150" MinWidth="50" Binding="{Binding Path=Module}" IsReadOnly="True"/>
+                        <DataGridTextColumn Header="Version" Width="150" MinWidth="70" Binding="{Binding Path=Version}" IsReadOnly="True"/>
+                        <DataGridTextColumn Header="File name" Binding="{Binding Path=FirmwareFileName}" IsReadOnly="False"/>
+                    </DataGrid.Columns>
+                </DataGrid>
+            </GroupBox>
+
+            <Grid Height="50">
+                <StackPanel Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Center">
+                    <ProgressBar Minimum="0" Maximum="100" x:Name="uxProgress" VerticalAlignment="Center" Height="10" Width="250"/>
+                    <Label x:Name="uxProgressRate" Content="0%" Foreground="White" FontSize="16"/>
+                    <Grid Width="10"/>
+                    <Button x:Name="uxStartBtn" Click="StartInit_Click" IsEnabled="{Binding IsInputLock}">
+                        <Label Content="Start DC Initialize"/>
+                    </Button>
+                </StackPanel>
+            </Grid>
+
+            <GroupBox Height="280" >
+                <GroupBox.Header>
+                    <Label Content="Init Procedure" Foreground="White" FontSize="16"/>
+                </GroupBox.Header>
+
+                <DataGrid AutoGenerateColumns="False" Margin="10" x:Name="uxProcedureDataGrid" CanUserSortColumns="False" IsEnabled="{Binding IsInputLock}" ItemsSource="{Binding UpdateProcedure}">
+                    <DataGrid.Columns>
+                        <DataGridTextColumn Header="Name" Width="150" MinWidth="50" Binding="{Binding Path=Name}" IsReadOnly="True"/>
+                        <DataGridTextColumn Header="Content" Width="500" MinWidth="70" Binding="{Binding Path=Content}" IsReadOnly="True"/>
+                        <DataGridCheckBoxColumn Header="Action" Binding="{Binding Path=IsActivated}" IsReadOnly="False"/>
+                    </DataGrid.Columns>
+                </DataGrid>
+            </GroupBox>
+
+            <GroupBox Height="200">
+                <GroupBox.Header>
+                    <Label Content="Terminal" Foreground="White" FontSize="16"/>
+                </GroupBox.Header>
+
+                <ScrollViewer x:Name="uxTerminalScroller">
+                    <TextBlock x:Name="uxTerminal" Background="Black" Margin="10" Foreground="Green">
+                    </TextBlock>
+                </ScrollViewer>
+            </GroupBox>
+        </StackPanel>
+    </Viewbox>
+</Window>

+ 554 - 0
AwInitilizer/MainWindow.xaml.cs

@@ -0,0 +1,554 @@
+using AwInitilizer.Model;
+using AwInitilizer.Procedure;
+using Microsoft.Win32;
+using Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Net;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Navigation;
+using System.Windows.Threading;
+
+namespace AwInitilizer
+{
+    /// <summary>
+    /// Interaction logic for MainWindow.xaml
+    /// </summary>
+    public partial class MainWindow : Window, Interface.IIogger
+    {
+        private string barCode = string.Empty;
+        private DispatcherTimer CleanInputTimer;
+
+        private bool IsInitilizing = false;
+
+        private SystemID inputSystemID;
+        private string csuFilePath;
+        private string mcuFilePath;
+
+        private MainViewModel ViewModel => DataContext as MainViewModel;
+
+        public MainWindow()
+        {
+            InitializeComponent();
+
+            ServicePointManager.ServerCertificateValidationCallback +=
+                (sender, cert, chain, sslPolicyErrors) => true;
+            System.Net.ServicePointManager.Expect100Continue = false;
+
+            CleanInputTimer = new DispatcherTimer();
+            CleanInputTimer.Interval = TimeSpan.FromSeconds(2);
+            CleanInputTimer.Tick += CleanInputTimer_Tick;
+
+            Loaded += MainWindow_Loaded;
+            PreviewKeyDown += MainWindow_PreviewKeyDown;
+
+            //this.DataContext = new MainViewModel();
+            this.DataContext = new MainViewModel() {
+                //ModelName = "DSYE601E0ED2PH",
+                //SerialNumber = "NeedSetupSN",
+                //FourGenModuleVersion = "EC25AFFAR07A08M4G",
+                //IsSimInsert = false,
+                //ICCID = "12345678901234567890",
+                //IMSI = "123456789012345",
+                //CSUVersion = "V1.01.01.0601.00",
+                //MCUVersion = "D0.52.40.1770.P0"
+            };
+            this.DataContextChanged += MainWindow_DataContextChanged;
+        }
+
+        private void MainWindow_DataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
+        {
+
+        }
+
+        private void CleanInputTimer_Tick(object sender, EventArgs e)
+        {
+            CleanInputTimer.Stop();
+            barCode = string.Empty;
+        }
+
+        private void MainWindow_PreviewKeyDown(object sender, KeyEventArgs e)
+        {
+            barCode += e.Key;
+
+            CleanInputTimer.Stop();
+            CleanInputTimer.Start();
+
+            if (SystemID.TryParse(barCode,out SystemID systemID))
+            {
+                inputSystemID = systemID;
+                uxModelName.Text = systemID.ModelName.ToString();
+                uxSerialNumber.Text = systemID.SerialNumber;
+
+                if(ViewModel!=null && !string.IsNullOrEmpty(ViewModel.ModelName))
+                {
+                    if (systemID.ModelName.ToString() != ViewModel.ModelName)
+                    {
+                        MessageBox.Show("Model Name Mismatch");
+                    }
+                }
+            }
+        }
+
+        private void MainWindow_Loaded(object sender, RoutedEventArgs e)
+        {
+            Loaded -= MainWindow_Loaded;
+
+            //init intilize procedure list
+            //procedures.Add(new BasicInfoUpdateProcedure());
+            //procedures.Add(new FourGenModuleCheckProcedure());
+            //procedures.Add(new CsuFirmwareUpdateProcedure());
+            //procedures.Add(new McuFirmwareUpdateProcedure());
+            //procedures.Add(new ButtonStatusCheckPorcedure());
+            //procedures.Add(new RestarttoIdelProcedure());
+
+            //uxProcedureDataGrid.ItemsSource = procedures;
+        }
+
+        private void StartInit_Click(object sender, RoutedEventArgs e)
+        {
+            if(CheckInputData())
+            {
+                ViewModel.IsUdatIng = true;
+                _ = UpdateTask();
+            }
+        }
+
+        //private void CSUFileSelect_Click(object sender, RoutedEventArgs e)
+        //{
+        //    OpenFileDialog openFileDialog = new OpenFileDialog();
+        //    if (openFileDialog.ShowDialog() == true){
+        //        ViewModel.CSUFileName = openFileDialog.SafeFileName;
+        //        ViewModel.CSUFilePath = openFileDialog.FileName;
+        //    }
+        //}
+
+        //private void MCUFileSelect_Click(object sender, RoutedEventArgs e)
+        //{
+        //    OpenFileDialog openFileDialog = new OpenFileDialog();
+        //    if (openFileDialog.ShowDialog() == true)
+        //    {
+        //        ViewModel.MCUFileName = openFileDialog.SafeFileName;
+        //        ViewModel.MCUFilePath = openFileDialog.FileName;
+        //    }
+        //}
+
+        #region
+        private bool CheckInputData()
+        {
+            bool isAvaliable = true;
+            string alertMsg = string.Empty;
+            UpdateData updateData;
+            if(DataContext is MainViewModel viewModel)
+            {
+                updateData = viewModel;
+            }
+            else
+            {
+                throw new Exception("DataContext type error");
+            }
+
+
+            if(string.IsNullOrEmpty(updateData.ModelName))
+            {
+                alertMsg += "Model Name is Required\n";
+                isAvaliable = false;
+            }
+            else if(ViewModel.SettingModelName!= updateData.ModelName)
+            {
+                alertMsg += "Model Name setting is Mismathed\n";
+                isAvaliable = false;
+            }
+
+            if (string.IsNullOrEmpty(updateData.SerialNumber))
+            {
+                alertMsg += "Serial Number is Required\n";
+                isAvaliable = false;
+            }
+
+            var systemIDString = updateData.ModelName + updateData.SerialNumber;
+            if(!string.IsNullOrEmpty(systemIDString))
+            {
+                if(SystemID.TryParse(systemIDString,out SystemID systemID))
+                {
+                    updateData.SystemID = systemID;
+                }
+                else
+                {
+                    alertMsg += "Model Name format Error\n";
+                    isAvaliable = false;
+                }
+            }
+
+            if (updateData.SystemID!=null &&
+                updateData.SystemID.ModelName.Network.ToString().Contains("4G"))
+            {
+                if (string.IsNullOrEmpty(updateData.FourGenModuleVersion))
+                {
+                    alertMsg += "4G Module Version is Required\n";
+                    isAvaliable = false;
+                }
+
+                if (updateData.IsSimInsert)
+                {
+                    if (string.IsNullOrEmpty(updateData.ICCID))
+                    {
+                        alertMsg += "ICCID is Required when sim installed\n";
+                        isAvaliable = false;
+                    }
+
+                    if (string.IsNullOrEmpty(updateData.IMSI))
+                    {
+                        alertMsg += "IMSI is Required when sim installed\n";
+                        isAvaliable = false;
+                    }
+                }
+            }
+
+            if (updateData.FirmwareUpdateModels == null)
+            {
+                alertMsg += "FirmwareUpdateModels should be decalred\n";
+                isAvaliable = false;
+            }
+            else
+            {
+                foreach (var model in updateData.FirmwareUpdateModels)
+                {
+                    if (string.IsNullOrEmpty(model.Module))
+                    {
+                        alertMsg += "Firmware module name is Required\n";
+                        isAvaliable = false;
+                    }
+
+                    if (string.IsNullOrEmpty(model.Version))
+                    {
+                        alertMsg += "Firmware module name is Required\n";
+                        isAvaliable = false;
+                    }
+
+                    if (string.IsNullOrEmpty(model.FirmwareFileName))
+                    {
+                        alertMsg += "Firmware file is Required\n";
+                        isAvaliable = false;
+                    }
+                }
+            }
+
+            if(!isAvaliable)
+            {
+                MessageBox.Show(alertMsg);
+            }
+            return isAvaliable;
+        }
+
+        private async Task UpdateTask()
+        {
+            ProcedureBase.UpdateData = ViewModel;
+            ProcedureBase.Logger = this;
+            uxTerminal.Inlines.Clear();
+
+            ViewModel.IsUdatIng = true;
+            var procedureList = ViewModel.UpdateProcedure.Where(x => x.IsActivated).ToList();
+            int procedureIndex;
+            for (procedureIndex = 0; procedureIndex < procedureList.Count; procedureIndex++)
+            {
+                procedureList[procedureIndex].Reset();
+            }
+
+            for (procedureIndex = 0; procedureIndex < procedureList.Count; procedureIndex++)
+            {
+                uxProgress.Value = (procedureIndex * 100 / procedureList.Count);
+                uxProgressRate.Content = ((int)(procedureIndex * 100 / procedureList.Count)) + "%";
+                var result = await procedureList[procedureIndex].DoWork();
+                if (!result)
+                    break;
+            }
+
+            if (procedureIndex == procedureList.Count)
+            {
+                uxProgress.Value = 100;
+                uxProgressRate.Content = "100%";
+            }
+            CreateLogFile();
+            ViewModel.IsUdatIng = false;
+        }
+
+        private void CreateLogFile()
+        {
+            var fileName = ViewModel.SystemID + ViewModel.SerialNumber + DateTime.Now.ToString("yyyyMMddHHmmssffff") + ".txt";
+            var folderName = "Log";
+            var filePath = Path.Combine(folderName, fileName);
+            string content = "";
+            
+            if(File.Exists(fileName))
+            {
+                File.Delete(fileName);
+            }
+
+            FileStream fileStream = new FileStream(filePath, FileMode.Create);
+            StreamWriter fileWriter = new StreamWriter(fileStream);
+
+            fileWriter.WriteLine("Barcode");
+            fileWriter.WriteLine($"Model name:{ ViewModel.ModelName } , Serial number: { ViewModel.SerialNumber }");
+
+            fileWriter.WriteLine("==========================");
+            fileWriter.WriteLine("Setting file");
+            fileWriter.WriteLine($"Model name:{ ViewModel.SettingModelName}");
+            fileWriter.WriteLine($"4G Module Version:{ ViewModel.FourGenModuleVersion}");
+            fileWriter.WriteLine($"Is sim insert:{ ViewModel.IsSimInsert}");
+            fileWriter.WriteLine($"sim ICCID:{ ViewModel.ICCID}");
+            fileWriter.WriteLine($"sim IMSI:{ ViewModel.IMSI}");
+
+            foreach(var model in ViewModel.FirmwareUpdateModels)
+            {
+                fileWriter.WriteLine($"{model.Module} version:{ model.Version}");
+            }
+
+            var procedureList = ViewModel.UpdateProcedure.ToList();
+            for (int procedureIndex = 0; procedureIndex < procedureList.Count; procedureIndex++)
+            {
+                var procedure = procedureList[procedureIndex];
+                fileWriter.WriteLine("==========================");
+                fileWriter.WriteLine(procedure.Name);
+                fileWriter.WriteLine("Is Activated:" + (procedure.IsActivated ? "Yes" : "No"));
+                fileWriter.WriteLine("Status:" + procedure.Status.ToString());
+                fileWriter.WriteLine(procedure.InfoLog);
+            }
+
+            fileWriter.WriteLine("==========================");
+            fileWriter.Close();
+            //fileStream.Close();
+        }
+
+        public void Print(string msg, bool isError = false)
+        {
+            Dispatcher.Invoke(()=> {
+                Span line = new Span();
+                line.Inlines.Add(msg+"\n");
+                Span.SetForeground(line, isError ? Brushes.Red : Brushes.Green);
+
+                uxTerminal.Inlines.Add(line);
+                uxTerminalScroller.ScrollToEnd();
+            });
+        }
+        #endregion
+
+        private void SettingFileSelect_Click(object sender, RoutedEventArgs e)
+        {
+            OpenFileDialog openFileDialog = new OpenFileDialog();
+            openFileDialog.Filter = "Setting file|*.ini";
+            openFileDialog.Multiselect = false;
+            if (openFileDialog.ShowDialog() == true)
+            {
+                //check format
+                var filePath = openFileDialog.FileName;
+                if (!string.IsNullOrEmpty(filePath) &&
+                    File.Exists(filePath))
+                {
+                    var settingString = File.ReadAllText(filePath);
+                    SettingConfig setting;
+                    try
+                    {
+                         setting = JsonConvert.DeserializeObject<SettingConfig>(settingString);
+                    }
+                    catch
+                    {
+                        MessageBox.Show("Setting file ERROR");
+                        return;
+                    }
+
+                    if(CheckSettingConfig(System.IO.Path.GetDirectoryName(filePath),ref setting))
+                    {
+                        ViewModel.SettingModelName = setting.ModelName;
+                        ViewModel.SettingFileName = Path.GetFileName(filePath);
+                        ViewModel.FourGenModuleVersion = setting.FourGenModuleVersion;
+                        ViewModel.IsSimInsert = setting.IsSimInsert;
+                        ViewModel.ICCID = setting.ICCID;
+                        ViewModel.IMSI = setting.IMSI;
+                        ViewModel.FirmwareUpdateModels = setting.FirmwareUpdateList
+                            .Where(x => !string.IsNullOrEmpty(x.Module) && !string.IsNullOrEmpty(x.Version) && !string.IsNullOrEmpty(x.FirmwareFileName)
+                            ).ToList() ;
+
+                        UpdateProcedure();
+                    }
+                }
+            }
+        }
+
+        private void UpdateProcedure()
+        {
+            List<ProcedureBase> procedures = new List<ProcedureBase>();
+
+            //init intilize procedure list
+            procedures.Add(new BasicInfoUpdateProcedure());
+            procedures.Add(new FourGenModuleCheckProcedure());
+            for (int firemwareIndex = 0; firemwareIndex < ViewModel.FirmwareUpdateModels.Count ; firemwareIndex++)
+            {
+                procedures.Add(new FirmwareUpdateProcedure(ViewModel.FirmwareUpdateModels[firemwareIndex]));
+            }
+
+            procedures.Add(new ButtonStatusCheckPorcedure());
+            procedures.Add(new RestarttoIdelProcedure());
+
+            ViewModel.UpdateProcedure.Clear();
+
+            foreach(var p in procedures)
+            {
+                ViewModel.UpdateProcedure.Add(p);
+            }
+
+            //uxProcedureDataGrid.ItemsSource = procedures;
+        }
+
+        private bool CheckSettingConfig(string folderPath, ref SettingConfig setting)
+        {
+            if (setting == null)
+                return false;
+            bool isCheckPassed = true;
+
+            if (string.IsNullOrEmpty(setting.ModelName))
+            {
+                MessageBox.Show("ModelName is requred");
+                isCheckPassed = false;
+            }
+            else if(!ModelName.TryParse(setting.ModelName,out _))
+            {
+                MessageBox.Show("ModelName format Error");
+                isCheckPassed = false;
+            }
+
+            if (setting.IsSimInsert)
+            {
+                if (string.IsNullOrEmpty(setting.ICCID))
+                {
+                    MessageBox.Show("ICCID should not empty while IsSimInsert is set");
+                    isCheckPassed = false;
+                }
+
+                if (string.IsNullOrEmpty(setting.IMSI))
+                {
+                    MessageBox.Show("IMSI should not empty while IsSimInsert is set");
+                    isCheckPassed = false;
+                }
+            }
+
+            if(setting.FirmwareUpdateList!=null)
+            {
+                for (int firmwareIndex = 0; firmwareIndex < setting.FirmwareUpdateList.Count; firmwareIndex++)
+                {
+                    var model = setting.FirmwareUpdateList[firmwareIndex];
+                    bool isVersionVaild = !string.IsNullOrEmpty(model.Version);
+                    bool isFileNameVaild = !string.IsNullOrEmpty(model.FirmwareFileName);
+                    bool isNoduleNameVaild = !string.IsNullOrEmpty(model.Module);
+
+                    if(!isNoduleNameVaild)
+                    {
+                        MessageBox.Show("Firmware module name should not empty");
+                        isCheckPassed = false;
+                    }
+                    if (isVersionVaild || isFileNameVaild)
+                    {
+                        if (!isVersionVaild)
+                        {
+                            MessageBox.Show($"Version should not empty while {model.Module} firmware is set");
+                            isCheckPassed = false;
+                        }
+
+                        if (!isFileNameVaild)
+                        {
+                            MessageBox.Show($"File name should not empty while {model.Module} version is set");
+                            isCheckPassed = false;
+                        }
+
+                        if (isVersionVaild && isFileNameVaild)
+                        {
+                            var filePath = System.IO.Path.Combine(folderPath, model.FirmwareFileName);
+                            //check file exist
+                            if (!File.Exists(filePath))
+                            {
+                                MessageBox.Show($"{model.Module} Firemware file is missing");
+                                isCheckPassed = false;
+                            }
+                            else
+                            {
+                                try
+                                {
+                                    using (var fs = File.OpenRead(filePath))
+                                    {
+                                        byte[] systemIDBytes = new byte[16];
+                                        if (fs.Read(systemIDBytes, 0, 16) == 16)
+                                        {
+                                            if (systemIDBytes.ToList().Contains(0x00))
+                                            {
+                                                int endIndex = Array.FindIndex(systemIDBytes, (x) => { return x == 0x00; });
+                                                //int endIndex = parameter.FindIndex((x) => { return x == 0x00; });
+                                                if (endIndex != default && endIndex != -1)
+                                                {
+                                                    systemIDBytes = systemIDBytes.Take(endIndex).ToArray();
+                                                }
+                                            }
+
+                                            if (ModelName.TryParse(systemIDBytes, out var modelName))
+                                            {
+                                                if (modelName.ToString() != setting.ModelName)
+                                                {
+                                                    MessageBox.Show($"{model.Module} Firemware and ModelName is Mismatched");
+                                                    isCheckPassed = false;
+                                                }
+                                            }
+                                            else
+                                            {
+                                                MessageBox.Show($"{model.Module} Firemware header ERROR");
+                                                isCheckPassed = false;
+                                            }
+                                        }
+                                        else
+                                        {
+                                            MessageBox.Show($"{model.Module} Firemware header ERROR");
+                                            isCheckPassed = false;
+                                        }
+
+                                        byte[] imgType = new byte[4];
+                                        if (fs.Read(imgType, 0, 4) == 4)
+                                        {
+                                            if (!imgType.SequenceEqual(new byte[] { 0x10, 0x00, 0x00, 0x04, }))
+                                            {
+                                                MessageBox.Show($"{model.Module} Firemware type ERROR");
+                                                isCheckPassed = false;
+                                            }
+                                        }
+                                        else
+                                        {
+                                            MessageBox.Show($"{model.Module} Firemware header ERROR");
+                                            isCheckPassed = false;
+                                        }
+                                    }
+                                }
+                                catch
+                                {
+                                    MessageBox.Show($"{model.Module} Firemware header ERROR");
+                                    isCheckPassed = false;
+                                }
+
+                                model.FirmwareFileName = filePath;
+                            }
+                        }
+                    }
+                }
+            }
+
+            return isCheckPassed;
+        }
+    }
+}

+ 15 - 0
AwInitilizer/Model/ButtonStatus.cs

@@ -0,0 +1,15 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace AwInitilizer.Model
+{
+    public class ButtonStatus
+    {
+        public int Button1 { get; set; }
+        public int Button2 { get; set; }
+        public int EmergencyButton { get; set; }
+    }
+}

+ 16 - 0
AwInitilizer/Model/EvseSerialResponseModel.cs

@@ -0,0 +1,16 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace AwInitilizer.Model
+{
+    public class EvseSerialResponseModel
+    {
+        public byte Source { get; set; }
+        public byte Destination { get; set; }
+        public byte Command { get; set; }
+        public byte[] Parameter { get; set; }
+    }
+}

+ 20 - 0
AwInitilizer/Model/FirmwareUpdateModel.cs

@@ -0,0 +1,20 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace AwInitilizer.Model
+{
+    public class FirmwareUpdateModel
+    {
+        public string Module { get; set; }
+        public string Version { get; set; }
+        public string FirmwareFileName { get; set; }
+
+        public FirmwareUpdateModel()
+        {
+
+        }
+    }
+}

+ 19 - 0
AwInitilizer/Model/SettingConfig.cs

@@ -0,0 +1,19 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Input;
+
+namespace AwInitilizer.Model
+{
+    public class SettingConfig
+    {
+        public string ModelName { get; set; }
+        public string FourGenModuleVersion { get; set; }
+        public bool IsSimInsert { get; set; }
+        public string ICCID { get; set; }
+        public string IMSI { get; set; }
+        public List<FirmwareUpdateModel> FirmwareUpdateList { get; set; }
+    }
+}

+ 15 - 0
AwInitilizer/Model/SimStatus.cs

@@ -0,0 +1,15 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace AwInitilizer.Model
+{
+    public class SimStatus
+    {
+        public bool IsInstalled { get; set; }
+        public byte[] ICCID { get; set; }
+        public byte[] IMSI { get; set; }
+    }
+}

+ 484 - 0
AwInitilizer/Model/SystemID.cs

@@ -0,0 +1,484 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace AwInitilizer.Model
+{
+    public enum ConnectorType
+    {
+        Unknown, None, CHadeMO, CCS1, CCS2, GBT, AC
+    }
+
+    public class SystemID
+    {
+        public ModelName ModelName { get; set; }
+        public string SerialNumber { get; set; }
+
+        public string sourceString { get; set; }
+
+        public static bool TryParse(byte[] byteData, out SystemID connectInfo)
+        {
+            connectInfo = null;
+            if (byteData == null || byteData.Length < 14)
+                return false;
+
+            string systemIDString = null;
+            try
+            {
+                systemIDString = Encoding.ASCII.GetString(byteData);
+            }
+            catch
+            {
+                return false;
+            }
+
+            if (!string.IsNullOrEmpty(systemIDString))
+            {
+                return TryParse(systemIDString, out connectInfo);
+            }
+            return false;
+        }
+
+        public static bool TryParse(string byteString, out SystemID connectInfo)
+        {
+            connectInfo = null;
+            SystemID tmp = new SystemID();
+
+            tmp.sourceString = byteString;
+
+            if (tmp.sourceString.Length < 14)
+                return false;
+
+            if (!ModelName.TryParse(tmp.sourceString.Substring(0, 14), out var model))
+                return false;
+            tmp.ModelName = model;
+            tmp.SerialNumber = tmp.sourceString.Substring(14);
+            connectInfo = tmp;
+
+            return true;
+        }
+
+        public string ToWifiPwd()
+        {
+            return SerialNumber + ModelName.ToString();
+        }
+
+        public override string ToString()
+        {
+            return sourceString;
+        }
+
+        public override bool Equals(object obj)
+        {
+            return obj.ToString() == this.ToString();
+        }
+
+        public override int GetHashCode()
+        {
+            return this.ToString().GetHashCode();
+        }
+
+        public static bool operator ==(SystemID a, SystemID b)
+        {
+            string stra = null, strb = null;
+
+            if (Object.Equals(a, null))
+                stra = null;
+            else
+                stra = a.ToString();
+
+            if (Object.Equals(b, null))
+                strb = null;
+            else
+                strb = b.ToString();
+            return string.Equals(a, b);
+        }
+
+        public static bool operator !=(SystemID a, SystemID b)
+        {
+            string stra = null, strb = null;
+
+            if (Object.Equals(a, null))
+                stra = null;
+            else
+                stra = a.ToString();
+
+            if (Object.Equals(b, null))
+                strb = null;
+            else
+                strb = b.ToString();
+            return !string.Equals(a, b);
+        }
+    }
+
+    public class ModelName
+    {
+        public enum EVSE_TYPE_CAT
+        {
+            Unknown,
+            AC,
+            DC,
+            Hybrid
+        }
+
+        public enum EVSE_TYPE
+        {
+            Unknown,
+            AC_Cordset,
+            AC_Wallmount,
+            AC_Pedestal,
+            DC_Wallmount,
+            DC_Standalong,
+            DC_Movable,
+            DC_Roadside,
+            DC_Disppenser,
+            DC_Outputpowercabinet
+        }
+
+        public enum EVSE_InputConfig
+        {
+            Y, D, L, S, W, T, E , N0, N1, N2, N3, N4, N5, N6, N7, N8, N9,
+        }
+
+        public enum EVSE_SafetyReg
+        {
+            Europoean,
+            NorthAmerica,
+            China,
+            Taiwan,
+            Japan,
+            Singapor,
+            Korea,
+            UK,
+            French,
+            M,
+            P,
+            I,
+            F,
+            L
+        }
+
+        public enum EVSE_network
+        {
+            None,
+            Ethernet,
+            Ble,
+            EthWiFi,
+            Eth4G,
+            EthBle,
+            EthWiFi4G,
+        }
+
+        public EVSE_TYPE Type { get; private set; }
+        public EVSE_InputConfig InputConfig { get; private set; }
+        public EVSE_SafetyReg SafetyReg { get; private set; }
+        public double RatedPower { get; private set; }
+        public ConnectorType[] ConnectorTypes { get; private set; }
+        public EVSE_network Network { get; private set; }
+        public int Generation { get; private set; }
+        public string CustomCode { get; private set; }
+
+        public EVSE_TYPE_CAT Type_Cat { get => GetTypeCat(); }
+
+        private string _modelNameString;
+        public string modelNameString
+        {
+            get => _modelNameString;
+            set
+            {
+                if (TryParse(value, out var result))
+                {
+                    this.Type = result.Type;
+                    this.InputConfig = result.InputConfig;
+                    this.SafetyReg = result.SafetyReg;
+                    this.RatedPower = result.RatedPower;
+                    this.ConnectorTypes = result.ConnectorTypes;
+                    this.Network = result.Network;
+                    this.Generation = result.Generation;
+                    this.CustomCode = result.CustomCode;
+
+                    _modelNameString = value;
+                }
+            }
+        }
+
+        public static bool TryParse(byte[] modeNameByte, out ModelName modelName)
+        {
+            modelName = null;
+            string modelNameString;
+            try
+            {
+                modelNameString = Encoding.ASCII.GetString(modeNameByte);
+            }
+            catch
+            {
+                return false;
+            }
+
+            if (modelNameString.Length != 14)
+                return false;
+            return TryParse(modelNameString, out modelName);
+        }
+
+        public static bool TryParse(string modeNameString, out ModelName modelName)
+        {
+            modelName = null;
+            ModelName model = new ModelName();
+
+            if (modeNameString == null || modeNameString.Length != 14)
+                return false;
+            bool isAc = modeNameString[0] == 'A';
+            var typeString = modeNameString.Substring(0, 2);
+            switch (typeString)
+            {
+                case "AC":
+                    model.Type = EVSE_TYPE.AC_Cordset;
+                    break;
+                case "AW":
+                    model.Type = EVSE_TYPE.AC_Wallmount;
+                    break;
+                case "AP":
+                    model.Type = EVSE_TYPE.AC_Pedestal;
+                    break;
+                case "DW":
+                    model.Type = EVSE_TYPE.DC_Wallmount;
+                    break;
+                case "DS":
+                    model.Type = EVSE_TYPE.DC_Standalong;
+                    break;
+                case "DM":
+                    model.Type = EVSE_TYPE.DC_Movable;
+                    break;
+                case "DR":
+                    model.Type = EVSE_TYPE.DC_Roadside;
+                    break;
+                case "DD":
+                    model.Type = EVSE_TYPE.DC_Disppenser;
+                    break;
+                case "DO":
+                    model.Type = EVSE_TYPE.DC_Outputpowercabinet;
+                    break;
+                default:
+                    return false;
+            }
+
+            var inputConfigStr = modeNameString.Substring(2, 1);
+            switch (inputConfigStr)
+            {
+                case "Y":
+                    model.InputConfig = EVSE_InputConfig.Y;
+                    break;
+                case "D":
+                    model.InputConfig = EVSE_InputConfig.D;
+                    break;
+                case "L":
+                    model.InputConfig = EVSE_InputConfig.L;
+                    break;
+                case "S":
+                    model.InputConfig = EVSE_InputConfig.S;
+                    break;
+                case "W":
+                    model.InputConfig = EVSE_InputConfig.W;
+                    break;
+                case "T":
+                    model.InputConfig = EVSE_InputConfig.T;
+                    break;
+                case "E":
+                    model.InputConfig = EVSE_InputConfig.E;
+                    break;
+                case "0":
+                    model.InputConfig = EVSE_InputConfig.N0;
+                    break;
+                case "1":
+                    model.InputConfig = EVSE_InputConfig.N1;
+                    break;
+                case "2":
+                    model.InputConfig = EVSE_InputConfig.N2;
+                    break;
+                case "3":
+                    model.InputConfig = EVSE_InputConfig.N3;
+                    break;
+                case "4":
+                    model.InputConfig = EVSE_InputConfig.N4;
+                    break;
+                case "5":
+                    model.InputConfig = EVSE_InputConfig.N5;
+                    break;
+                case "6":
+                    model.InputConfig = EVSE_InputConfig.N6;
+                    break;
+                case "7":
+                    model.InputConfig = EVSE_InputConfig.N7;
+                    break;
+                case "8":
+                    model.InputConfig = EVSE_InputConfig.N8;
+                    break;
+                case "9":
+                    model.InputConfig = EVSE_InputConfig.N9;
+                    break;
+                default:
+                    return false;
+            }
+
+            var safeRegStr = modeNameString.Substring(3, 1);
+            switch (safeRegStr)
+            {
+                case "E":
+                    model.SafetyReg = EVSE_SafetyReg.Europoean;
+                    break;
+                case "U":
+                    model.SafetyReg = EVSE_SafetyReg.NorthAmerica;
+                    break;
+                case "G":
+                    model.SafetyReg = EVSE_SafetyReg.China;
+                    break;
+                case "C":
+                    model.SafetyReg = EVSE_SafetyReg.Taiwan;
+                    break;
+                case "J":
+                    model.SafetyReg = EVSE_SafetyReg.Japan;
+                    break;
+                case "T":
+                    model.SafetyReg = EVSE_SafetyReg.Singapor;
+                    break;
+                case "K":
+                    model.SafetyReg = EVSE_SafetyReg.Korea;
+                    break;
+                case "B":
+                    model.SafetyReg = EVSE_SafetyReg.UK;
+                    break;
+                case "Z":
+                    model.SafetyReg = EVSE_SafetyReg.French;
+                    break;
+                case "M":
+                    model.SafetyReg = EVSE_SafetyReg.M;
+                    break;
+                case "P":
+                    model.SafetyReg = EVSE_SafetyReg.P;
+                    break;
+                case "I":
+                    model.SafetyReg = EVSE_SafetyReg.I;
+                    break;
+                case "F":
+                    model.SafetyReg = EVSE_SafetyReg.F;
+                    break;
+                case "L":
+                    model.SafetyReg = EVSE_SafetyReg.L;
+                    break;
+                default:
+                    return false;
+            }
+
+            var ratedPowerStr = modeNameString.Substring(4, 3);
+            if (!int.TryParse(ratedPowerStr, out int ratedPowerNum) &&
+                ratedPowerNum > 0)
+                return false;
+            double realnum = (double)ratedPowerNum / 10;
+            var exp = ratedPowerNum % 10;
+            model.RatedPower = (double)(realnum * (10 ^ exp));
+
+            model.ConnectorTypes = new ConnectorType[3];
+            var connectorListStr = modeNameString.Substring(7, 3);
+            /*
+            model.ConnectorTypes.Add(ConnectorType.CHadeMO);
+            model.ConnectorTypes.Add(ConnectorType.CCS);
+            model.ConnectorTypes.Add(ConnectorType.IEC);
+            */
+            for (int index = 0; index < 3; index++)
+            {
+                var connectorStr = connectorListStr.Substring(index, 1);
+
+                switch (connectorStr)
+                {
+                    case "0":
+                        //none connecter
+                        model.ConnectorTypes[index] = ConnectorType.None;
+                        break;
+                    case "1":
+                    case "2":
+                    case "3":
+                    case "4":
+                    case "5":
+                    case "6":
+                        model.ConnectorTypes[index] = ConnectorType.AC;
+                        break;
+                    case "J":
+                        model.ConnectorTypes[index] = ConnectorType.CHadeMO;
+                        break;
+                    case "U":
+                    case "V":
+                        model.ConnectorTypes[index] = ConnectorType.CCS1;
+                        break;
+                    case "E":
+                    case "F":
+                        model.ConnectorTypes[index] = ConnectorType.CCS2;
+                        break;
+                    case "G":
+                        model.ConnectorTypes[index] = ConnectorType.GBT;
+                        break;
+                    default:
+                        return false;
+                }
+            }
+
+            var networkOpStr = modeNameString.Substring(10, 1);
+            switch (networkOpStr)
+            {
+                case "0":
+                    model.Network = EVSE_network.None;
+                    break;
+                case "E":
+                    model.Network = EVSE_network.Ethernet;
+                    break;
+                case "B":
+                    model.Network = EVSE_network.Ble;
+                    break;
+                case "W":
+                    model.Network = EVSE_network.EthWiFi;
+                    break;
+                case "T":
+                    model.Network = EVSE_network.Eth4G;
+                    break;
+                case "U":
+                    model.Network = EVSE_network.EthBle;
+                    break;
+                case "D":
+                case "A":
+                    model.Network = EVSE_network.EthWiFi4G;
+                    break;
+                default:
+                    return false;
+            }
+
+            var genStr = modeNameString.Substring(11, 1);
+            if (!int.TryParse(genStr, out var genInt))
+                return false;
+            model.Generation = genInt;
+
+            model.CustomCode = modeNameString.Substring(12, 2);
+            model._modelNameString = modeNameString;
+
+            modelName = model;
+            return true;
+        }
+
+        public ModelName() { }
+
+        public override string ToString()
+        {
+            return modelNameString;
+        }
+
+        private EVSE_TYPE_CAT GetTypeCat()
+        {
+            string typeString = Type.ToString();
+            if (typeString.Contains("AC"))
+                return EVSE_TYPE_CAT.AC;
+            else if (typeString.Contains("DC"))
+                return EVSE_TYPE_CAT.DC;
+            return EVSE_TYPE_CAT.Hybrid;
+        }
+    }
+}

+ 127 - 0
AwInitilizer/Model/UpdateData.cs

@@ -0,0 +1,127 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace AwInitilizer.Model
+{
+    public class UpdateData : INotifyPropertyChanged
+    {
+        private SystemID _SystemID;
+        public SystemID SystemID {
+            get => _SystemID;
+            set
+            {
+                if(_SystemID!=value)
+                {
+                    _SystemID = value;
+                    RaisePropertyChanged("SystemID");
+                }
+            }
+        }
+
+        private string _ModelName;
+        public string ModelName {
+            get => _ModelName;
+            set
+            {
+                if(_ModelName!=value)
+                {
+                    _ModelName = value;
+                    RaisePropertyChanged("ModelName");
+                }
+            }
+        }
+
+        private string _SerialNumber;
+        public string SerialNumber
+        {
+            get => _SerialNumber;
+            set
+            {
+                if (_SerialNumber != value)
+                {
+                    _SerialNumber = value;
+                    RaisePropertyChanged("SerialNumber");
+                }
+            }
+        }
+
+        private string _FourGenModuleVersion;
+        public string FourGenModuleVersion
+        {
+            get => _FourGenModuleVersion;
+            set
+            {
+                if (_FourGenModuleVersion != value)
+                {
+                    _FourGenModuleVersion = value;
+                    RaisePropertyChanged("FourGenModuleVersion");
+                }
+            }
+        }
+
+        private bool _IsSimInsert;
+        public bool IsSimInsert
+        {
+            get => _IsSimInsert;
+            set
+            {
+                if(_IsSimInsert != value)
+                {
+                    _IsSimInsert = value;
+                    RaisePropertyChanged("IsSimInsert");
+                }
+            }
+        }
+
+        private string _ICCID;
+        public string ICCID {
+            get => _ICCID;
+            set
+            {
+                if (_ICCID != value)
+                {
+                    _ICCID = value;
+                    RaisePropertyChanged("ICCID");
+                }
+            }
+        }
+
+        private string _IMSI;
+        public string IMSI
+        {
+            get => _IMSI;
+            set
+            {
+                if (_IMSI != value)
+                {
+                    _IMSI = value;
+                    RaisePropertyChanged("IMSI");
+                }
+            }
+        }
+
+        private List<FirmwareUpdateModel> _FirmwareUpdateModels;
+        public List<FirmwareUpdateModel> FirmwareUpdateModels
+        {
+            get => _FirmwareUpdateModels;
+            set
+            {
+                if (_FirmwareUpdateModels != value)
+                {
+                    _FirmwareUpdateModels = value;
+                    RaisePropertyChanged("FirmwareUpdateModels");
+                }
+            }
+        }
+
+        public event PropertyChangedEventHandler PropertyChanged;
+        internal void RaisePropertyChanged(string name)
+        {
+            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
+        }
+    }
+}

+ 21 - 0
AwInitilizer/Model/UploadFile.cs

@@ -0,0 +1,21 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace AwInitilizer.Model
+{
+    public class UploadFile
+    {
+        public UploadFile()
+        {
+            //ContentType = "application/octet-stream";
+        }
+        public string Name { get; set; }
+        public string Filename { get; set; }
+        //public string ContentType { get; set; }
+        public Stream Stream { get; set; }
+    }
+}

+ 148 - 0
AwInitilizer/Procedure/BasicInfoUpdateProcedure.cs

@@ -0,0 +1,148 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Net.Sockets;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace AwInitilizer.Procedure
+{
+    public class BasicInfoUpdateProcedure : ProcedureBase
+    {
+        public BasicInfoUpdateProcedure() : base()
+        {
+            Name = "Basic Intlize";
+            Content = "Set and check Model Name,SerilNumber,DateTime.";
+        }
+
+        internal override async Task<bool> Run()
+        {
+            if (!await base.CheckAndCreateSocket())
+            {
+                InfoLog += "EVSE connect failed\n";
+                return false;
+            }
+
+            //base.serialPortocol.OnMsgReceived += SerialPortocol_OnMsgReceived; 
+            if (!await serialPortocol.SetModelName(UpdateData.ModelName))
+            {
+                InfoLog += "Model Name update failed\n";
+                Logger.Print("Model Name update Failed", isError: true);
+                return false;
+            }
+            else
+            {
+                Logger.Print("Model Name write Success");
+            }
+
+            if (!await serialPortocol.SetSerialNumber(UpdateData.SerialNumber))
+            {
+                InfoLog += "Serial Number update failed\n";
+                Logger.Print("Serial Number update Failed", isError: true);
+                return false;
+            }
+            else
+            {
+                Logger.Print("Serial Number write Success");
+            }
+
+            var setDateTime = DateTime.Now.ToUniversalTime();
+
+            if (!await serialPortocol.SetUTCTime(setDateTime))
+            {
+                InfoLog += "RTC update failed\n";
+                Logger.Print("RTC update Failed", isError: true);
+                return false;
+            }
+            else
+            {
+                Logger.Print("RTC update write Success");
+            }
+
+            if (!await serialPortocol.SettingChangeConfirm())
+            {
+                InfoLog += "Setting save request failed\n";
+                Logger.Print("Setting save Failed", isError: true);
+                return false;
+            }
+            else
+            {
+                Logger.Print("Setting save Success");
+            }
+
+            Logger.Print("Waiting EVSE reboot...");
+            serialPortocol.Close();
+            await Task.Delay(TimeSpan.FromMinutes(1));
+
+            if (!await base.CheckAndCreateSocket())
+            {
+                InfoLog += "EVSE not found after reboot\n";
+                Logger.Print("EVSE reboot timeout", isError: true);
+                return false;
+            }
+
+            var receivedModelName = await serialPortocol.GetModelName();
+            if (string.IsNullOrEmpty(receivedModelName))
+            {
+                InfoLog += "Model name get failed after reboot\n";
+                Logger.Print("Model Name read Failed", isError: true);
+                return false;
+            }
+            else
+            {
+                InfoLog += $"Get Updated Model Name { receivedModelName }\n";
+                if (receivedModelName != UpdateData.ModelName)
+                {
+                    InfoLog += "Updated Model Name Mismatched\n";
+                    Logger.Print("Stored Model Name Mismatched", isError: true);
+                    return false;
+                }
+                Logger.Print("Model Name update Success");
+            }
+
+            var receivedSeerialNumber = await serialPortocol.GetSerialNumber();
+            if (string.IsNullOrEmpty(receivedSeerialNumber))
+            {
+                InfoLog += "Serial number get failed after reboot\n";
+                Logger.Print("Stored Serial read Failed", isError: true);
+                return false;
+            }
+            else
+            {
+                InfoLog += $"Get Updated serial number { receivedSeerialNumber }\n";
+                if (receivedSeerialNumber != UpdateData.SerialNumber)
+                {
+                    InfoLog += "Updated serial number mismatched\n";
+                    Logger.Print("Stored Serial Number Mismatched", isError: true);
+                    return false;
+                }
+                Logger.Print("Serial Number update Success");
+            }
+
+            var receivedDateTime = await serialPortocol.GetUTCTime();
+            if (string.IsNullOrEmpty(receivedModelName))
+            {
+                InfoLog += "UTC Time receive failed after reboot\n";
+                Logger.Print("UTC Time receive failed", isError: true);
+                return false;
+            }
+            else
+            {
+                InfoLog += $"UTC Time received : {receivedDateTime.Value.ToString("yyyyMMddHHmmss")}\n";
+                var diff = receivedDateTime.Value - DateTime.Now.ToUniversalTime();
+                if (Math.Abs(diff.TotalSeconds) > 10)
+                {
+                    InfoLog += "Stored UTC time Mismatched\n";
+                    Logger.Print("Stored UTC time Mismatched", isError: true);
+                    return false;
+                }
+                else
+                {
+                    Logger.Print("Model Name update Success");
+                }
+            }
+
+            return true;
+        }
+    }
+}

+ 222 - 0
AwInitilizer/Procedure/ButtonStatusCheckPorcedure.cs

@@ -0,0 +1,222 @@
+using AwInitilizer.Assist;
+using AwInitilizer.Model;
+using Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.Collections.Specialized;
+using System.IO;
+using System.Linq;
+using System.Net;
+using System.Security.AccessControl;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+
+namespace AwInitilizer.Procedure
+{
+    public class ButtonStatusCheckPorcedure : ProcedureBase
+    {
+        public ButtonStatusCheckPorcedure() : base()
+        {
+            Name = "Button press test";
+            Content = "Interaction to test button status";
+        }
+
+        internal override async Task<bool> Run()
+        {
+            Logger.Print("Button Unpress Status check Start");
+            //stage 1 - unpress all
+            MessageBox.Show("Please make sure All button is Unpressed\nPress Ok while complete", "Starting Button test");
+            ButtonStatus status = await GetButtonStatus();
+
+            if (status == null)
+            {
+                InfoLog += "Get Butoon state failed\n";
+                Logger.Print("Get Butoon state failed");
+                return false;
+            }
+
+            InfoLog += "Unpress check result\n";
+            InfoLog += $"Button1:{status.Button1},Button2:{status.Button2},EmgerncyButton:{status.EmergencyButton}\n";
+
+            bool isAllMatched = true;
+            if (status != null)
+            {
+                isAllMatched = true;
+                if (status.Button1 != 1)
+                {
+                    Logger.Print("Button1 status ERROR, unpress is ecpected", isError: true);
+                    isAllMatched = false;
+                }
+                if (status.Button2 != 1)
+                {
+                    Logger.Print("Button3 status ERROR, unpress is ecpected", isError: true);
+                    isAllMatched = false;
+                }
+                if (status.EmergencyButton != 1)
+                {
+                    Logger.Print("EmergencyButton status ERROR, unpress is ecpected", isError: true);
+                    isAllMatched = false;
+                }
+
+                if (isAllMatched)
+                {
+                    Logger.Print("Unpress Check passed");
+                }
+                else
+                {
+                    return false;
+                }
+            }
+            else
+            {
+                Logger.Print("Get button press status Failed", isError: true);
+                return false;
+            }
+
+            //stage 2 - check press sequence
+            Logger.Print("Button Unpress Status check Start");
+            MessageBox.Show("Press Button1,Button2,EmergencyButton in order\neach press continuous 2 secondes\nPress Ok to start", "Starting Button test");
+
+            bool isError = false;
+            //Button1,Button2,EmergencyButton in order 0,1,2
+            ButtonStatus pressStatus = null;
+            for (int testType = 0; testType < 3; testType++)
+            {
+                //retry 20 times, 20*0.5 = 10 seconds 
+                int testCnt;
+                for (testCnt = 0; testCnt < 20; testCnt++)
+                {
+                    await Task.Delay(500);
+                    pressStatus = await GetButtonStatus();
+                    if (pressStatus == null)
+                    {
+                        InfoLog += "Get Butoon state failed\n";
+                        Logger.Print("Get Butoon state failed");
+                        return false;
+                    }
+
+                    //if any button is pressed
+                    if (pressStatus.Button1 != 0 ||
+                        pressStatus.Button2 != 0 ||
+                        pressStatus.EmergencyButton != 0)
+                    {
+                        if (pressStatus.Button1 == (testType == 0 ? 1 : 0) &&
+                            pressStatus.Button2 == (testType == 1 ? 1 : 0) &&
+                            pressStatus.EmergencyButton == (testType == 2 ? 1 : 0))
+                        {
+                            //Status correct
+                        }
+                        else
+                        {
+                            //Status error
+                            isError = true;
+                            break;
+                        }
+
+                        //wait release
+                        for (testCnt = 0; testCnt < 20; testCnt++)
+                        {
+                            await Task.Delay(500);
+                            status = await GetButtonStatus();
+                            if (status == null)
+                            {
+                                InfoLog += "Get Butoon state failed\n";
+                                Logger.Print("Get Butoon state failed");
+                                return false;
+                            }
+                            if (status.Button1 == 0 &&
+                                status.Button2 == 0 &&
+                                status.EmergencyButton == 0)
+                            {
+                                break;
+                            }
+                        }
+                    }
+                }
+
+                string btn;
+                switch (testType)
+                {
+                    case 0:
+                        btn = "Button1";
+                        break;
+                    case 1:
+                        btn = "Button2";
+                        break;
+                    case 2:
+                        btn = "EmergencyButton";
+                        break;
+                    default:
+                        btn = "";
+                        break;
+                };
+
+                InfoLog += $"Press check stage {btn} result\n";
+                InfoLog += $"Button1:{pressStatus.Button1},Button2:{pressStatus.Button2},EmgerncyButton:{pressStatus.EmergencyButton}\n";
+
+                if (testCnt >= 20)
+                {
+                    Logger.Print($"{btn} press TIMEOUT", isError: true);
+                    break;
+                }
+                else if (isError)
+                {
+                    Logger.Print($"{btn} press state ERROR", isError: true);
+                    Logger.Print($"Button1 {GetBtnStatusString(pressStatus.Button1)}, Button2 {GetBtnStatusString(pressStatus.Button2)}, EmergencyButton {GetBtnStatusString(pressStatus.EmergencyButton)}", isError: true);
+                    break;
+                }
+                else
+                {
+                    Logger.Print($"{btn} press state passed");
+                }
+            }
+
+            if(isError)
+                return false;
+            return true;
+        }
+
+        internal async Task<ButtonStatus> GetButtonStatus()
+        {
+            try
+            {
+                using (WebClientTimeout webClient = new WebClientTimeout())
+                {
+                    using (Stream stream = await webClient.OpenReadTaskAsync($"https://{ServerIpAddress}/get_button_action.php"))
+                    // 使用 StreamReader 讀取 stream 內的字元
+                    using (StreamReader reader = new StreamReader(stream))
+                    {
+                        // 將 StreamReader 所讀到的字元轉為 string
+                        string request = reader.ReadToEnd();
+                        InfoLog += $"Get respone : {request}\n";
+                        var values = JsonConvert.DeserializeObject<ButtonStatus>(request);
+
+                        return values;
+                    }
+                }
+            }
+            catch (Exception e)
+            {
+                InfoLog += "Get Button Status Failed\n";
+                InfoLog += e.Message;
+                InfoLog += "\n";
+
+                Logger.Print("Get Button Status Failed", isError: true);
+                Logger.Print(e.Message + "", isError: true);
+            }
+
+            return null;
+        }
+
+        private string GetBtnStatusString(int status)
+        {
+            if (status == 1)
+                return "Pressed";
+            else if (status == 0)
+                return "Unpressed";
+            else
+                return status.ToString();
+        }
+    }
+}

+ 370 - 0
AwInitilizer/Procedure/FirmwareUpdateProcedure.cs

@@ -0,0 +1,370 @@
+using AwInitilizer.Model;
+using Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.Collections.Specialized;
+using System.ComponentModel;
+using System.Globalization;
+using System.IO;
+using System.Linq;
+using System.Net;
+using System.Text;
+using System.Threading.Tasks;
+using System.Web;
+using System.Windows.Ink;
+
+namespace AwInitilizer.Procedure
+{
+    public class FirmwareUpdateProcedure : ProcedureBase
+    {
+        internal string Version;
+        internal string fileName;
+        internal string module;
+        internal int SleepMinuts = 6;
+
+        private FirmwareUpdateModel _model;
+
+        public FirmwareUpdateProcedure(FirmwareUpdateModel model) :base()
+        {
+            _model = model;
+
+            Name = string.Format("Firmware {0}", model.Module);
+            Content = string.Format("Update {0} Firemware and check version matched", model.Module);
+
+            Version = model.Version;
+            fileName = model.FirmwareFileName;
+            module = model.Module;
+        }
+
+        internal override async Task<bool> Run()
+        {
+            var oldVersion = await GetSpecificVersion();
+            if (string.IsNullOrEmpty(oldVersion))
+            {
+                InfoLog += $"Get {Name} version failed\n";
+                Logger.Print($"Get {Name} version failed",isError:true);
+                return false;
+            }
+            InfoLog += $"version before update : {oldVersion}\n";
+            if (oldVersion == Version)
+            {
+                Logger.Print("Updated version detected");
+            }
+            Logger.Print("Firmware Uploading...");
+            var uploadResult = await Uploadfiremware(fileName);
+            if (uploadResult)
+            {
+                //wait restart
+                Logger.Print("Waiting restart..");
+                await Task.Delay(TimeSpan.FromMinutes(SleepMinuts));
+            }
+            else
+            {
+                InfoLog += $"Upload {Name} failed\n";
+                Logger.Print($"Upload {Name} failed", isError: true);
+                return false;
+            }
+            var updatedVersion = await GetSpecificVersion();
+            if (string.IsNullOrEmpty(updatedVersion))
+            {
+                InfoLog += $"Get updated {Name} version failed\n";
+                Logger.Print($"Get updated {Name} version failed", isError: true);
+                return false;
+            }
+            InfoLog += $"Get updated version : {updatedVersion}\n";
+            if (updatedVersion != Version)
+            {
+                InfoLog += $"{Name}:Updated Version mismatched\n";
+                Logger.Print($"{Name}:Updated Version mismatched", isError: true);
+                return false;
+            }
+            else
+            {
+                Logger.Print($"{Name}:updated success");
+            }
+
+            return true;
+        }
+
+        internal virtual async Task<string> GetSpecificVersion()
+        {
+            var versions = await GetVersion();
+            if(!versions.ContainsKey(module))
+            {
+                return "";
+            }
+            return versions[module];
+        }
+
+        internal async Task<Dictionary<string,string>> GetVersion()
+        {
+            try
+            {
+                using (WebClient webClient = new WebClient())
+                {
+                    NameValueCollection parameters = new NameValueCollection();
+                    parameters.Add("opt", "1");
+                    webClient.QueryString = parameters;
+
+                    using (Stream stream = await webClient.OpenReadTaskAsync($"https://{ServerIpAddress}/get_query_action.php"))
+                    // 使用 StreamReader 讀取 stream 內的字元
+                    using (StreamReader reader = new StreamReader(stream))
+                    {
+                        // 將 StreamReader 所讀到的字元轉為 string
+                        string request = reader.ReadToEnd();
+                        InfoLog += $"get version response:{request}\n";
+                        var values = JsonConvert.DeserializeObject<Dictionary<string, object>>(request);
+
+                        var toReturn = new Dictionary<string, string>();
+                        foreach(var pair in values)
+                        {
+                            if (pair.Value is string v)
+                            {
+                                toReturn.Add(pair.Key, v);
+                            }
+                            else if(pair.Value is Newtonsoft.Json.Linq.JArray a)
+                            {
+                                try
+                                {
+                                    var versionList = JsonConvert.DeserializeObject<List<string>>(a.ToString());
+                                    for (int index = 0; index < versionList.Count; index++)
+                                    {
+                                        toReturn.Add(string.Format("{0}{1}", pair.Key, index), versionList[index]);
+                                    }
+                                }
+                                catch
+                                {
+
+                                }
+                            }
+                        }
+
+                        return toReturn;
+                    }
+                }
+            }
+            catch(Exception e)
+            {
+                Logger.Print("Get Version Failed", isError: true);
+                Logger.Print(e.Message+"", isError: true);
+
+                InfoLog += "Get Version Failed\n";
+                InfoLog += e.Message;
+                InfoLog += "\n";
+
+                return null;
+            }
+        }
+
+        internal async Task<bool> Uploadfiremware(string fileName)
+        {
+            try
+            {
+                //using (var stream = File.Open(fileName, FileMode.Open))
+                //{
+                //    UploadFileAsync(
+                //    new NameValueCollection()
+                //    {
+                //        {"fw_tag","iso" }
+                //    },
+                //    new UploadFile()
+                //    {
+                //        Name = "file",
+                //        Filename = Path.GetFileName(fileName),
+                //        Stream = stream
+                //    }
+                //    );
+                //}
+
+                //return true;
+                using (var stream = File.Open(fileName, FileMode.Open))
+                {
+                    var response = await UploadFiles(
+                    $"https://{ServerIpAddress}/upgrade_iso_action.php",
+                    new List<UploadFile>() {
+                        new UploadFile()
+                        {
+                            Name="file",
+                            Filename= Path.GetFileName(fileName),
+                            Stream = stream
+                        }
+                    },
+                    new NameValueCollection() {
+                        {"fw_tag","iso" }
+                    }
+                    );
+
+                    var responseStr = Encoding.ASCII.GetString(response).ToLower();
+                    InfoLog += $"get firmware update response {responseStr}\n";
+                    if (responseStr.Contains("file is uploaded"))
+                        return true;
+                    return false;
+                }
+                return true;
+                //using (WebClient webClient = new WebClient())
+                //{
+                //    NameValueCollection parameters = new NameValueCollection();
+                //    parameters.Add("fw_tag", "iso");
+                //    webClient.QueryString = parameters;
+
+                //    var responseBytes = await webClient.UploadFileTaskAsync($"https://{ServerIpAddress}/upgrade_iso_action.php", fileName);
+                //    string responseString = Encoding.ASCII.GetString(responseBytes);
+                //    return true;
+                //}
+            }
+            catch(Exception e)
+            {
+                Logger.Print("Upload Firmware Failed", isError: true);
+                Logger.Print(e.Message + "", isError: true);
+
+                InfoLog += "Upload Firmware Failed\n";
+                InfoLog += e.Message;
+                InfoLog += "\n";
+
+                return false;
+            }
+        }
+
+        public async Task<byte[]> UploadFiles(string address, IEnumerable<UploadFile> files, NameValueCollection values)
+        {
+            var request = (HttpWebRequest) HttpWebRequest.Create(address);
+            request.KeepAlive = true;
+            request.Accept = "*/*";
+            request.Method = "POST";
+            request.Referer = address;
+            request.Expect = "";
+            var boundary = "---------------------------" + DateTime.Now.Ticks.ToString("x", NumberFormatInfo.InvariantInfo);
+            request.ContentType = "multipart/form-data; boundary=" + boundary;
+            boundary = "--" + boundary;
+
+            using (var requestStream = request.GetRequestStream())
+            {
+                // Write the values
+                foreach (string name in values.Keys)
+                {
+                    var buffer = Encoding.ASCII.GetBytes(boundary + Environment.NewLine);
+                    requestStream.Write(buffer, 0, buffer.Length);
+                    buffer = Encoding.ASCII.GetBytes(string.Format("Content-Disposition: form-data; name=\"{0}\"{1}{1}", name, Environment.NewLine));
+                    requestStream.Write(buffer, 0, buffer.Length);
+                    buffer = Encoding.UTF8.GetBytes(values[name] + Environment.NewLine);
+                    requestStream.Write(buffer, 0, buffer.Length);
+                }
+
+                // Write the files
+                foreach (var file in files)
+                {
+                    var buffer = Encoding.ASCII.GetBytes(boundary + Environment.NewLine);
+                    requestStream.Write(buffer, 0, buffer.Length);
+                    buffer = Encoding.UTF8.GetBytes(string.Format("Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"{2}", file.Name, file.Filename, Environment.NewLine));
+                    requestStream.Write(buffer, 0, buffer.Length);
+                    var ctype = MimeMapping.GetMimeMapping(file.Filename);
+                    buffer = Encoding.ASCII.GetBytes(string.Format("Content-Type: {0}{1}{1}", MimeMapping.GetMimeMapping(file.Filename), Environment.NewLine));
+                    requestStream.Write(buffer, 0, buffer.Length);
+                    file.Stream.CopyTo(requestStream);
+                    buffer = Encoding.ASCII.GetBytes(Environment.NewLine);
+                    requestStream.Write(buffer, 0, buffer.Length);
+                }
+
+                var boundaryBuffer = Encoding.ASCII.GetBytes(boundary + "--");
+                requestStream.Write(boundaryBuffer, 0, boundaryBuffer.Length);
+            }
+
+            using (var response = await request.GetResponseAsync())
+            using (var responseStream = response.GetResponseStream())
+            using (var stream = new MemoryStream())
+            {
+                responseStream.CopyTo(stream);
+                return stream.ToArray();
+            }
+        }
+
+        [Obsolete]
+        public void UploadFileAsync(NameValueCollection values, UploadFile file )
+        {
+            //to fire events on the calling thread
+            var _asyncOperation = AsyncOperationManager.CreateOperation(null);
+            var ms = new MemoryStream();
+            //make a copy of the input stream in case sb uses disposable stream
+            file.Stream.CopyTo(ms);
+            //you cannot set stream position often enough to zero
+            ms.Position = 0;
+
+            Task.Factory.StartNew(() =>
+            {
+                try
+                {
+                    const string contentType = "application/octet-stream";
+
+                    var request = WebRequest.Create($"https://{ServerIpAddress}/get_query_action.php");
+                    request.Method = "POST";
+                    var boundary = "---------------------------" + DateTime.Now.Ticks.ToString("x", NumberFormatInfo.InvariantInfo);
+                    request.ContentType = "multipart/form-data; boundary=" + boundary;
+                    boundary = "--" + boundary;
+
+                    var dataStream = new MemoryStream();
+                    byte[] buffer;
+                    // Write the values
+                    foreach (string name in values.Keys)
+                    {
+                        buffer = Encoding.ASCII.GetBytes(boundary + Environment.NewLine);
+                        dataStream.Write(buffer, 0, buffer.Length);
+                        buffer = Encoding.ASCII.GetBytes(string.Format("Content-Disposition: form-data; name=\"{0}\"{1}{1}", name, Environment.NewLine));
+                        dataStream.Write(buffer, 0, buffer.Length);
+                        buffer = Encoding.UTF8.GetBytes(values[name] + Environment.NewLine);
+                        dataStream.Write(buffer, 0, buffer.Length);
+                    }
+
+                    // Write the file
+                    buffer = Encoding.ASCII.GetBytes(boundary + Environment.NewLine);
+                    dataStream.Write(buffer, 0, buffer.Length);
+                    buffer = Encoding.UTF8.GetBytes($"Content-Disposition: form-data; name=\"{file.Name}\"; filename=\"{file.Filename}\"{Environment.NewLine}");
+                    dataStream.Write(buffer, 0, buffer.Length);
+                    buffer = Encoding.ASCII.GetBytes(string.Format("Content-Type: {0}{1}{1}", MimeMapping.GetMimeMapping(file.Filename), Environment.NewLine));
+                    dataStream.Write(buffer, 0, buffer.Length);
+                    ms.CopyTo(dataStream);
+                    buffer = Encoding.ASCII.GetBytes(Environment.NewLine);
+                    dataStream.Write(buffer, 0, buffer.Length);
+
+                    buffer = Encoding.ASCII.GetBytes(boundary + "--");
+                    dataStream.Write(buffer, 0, buffer.Length);
+
+
+                    dataStream.Position = 0;
+                    //IMPORTANT: set content length to directly write to network socket
+                    request.ContentLength = dataStream.Length;
+                    var requestStream = request.GetRequestStream();
+
+                    //Write data in chunks and report progress
+                    var size = dataStream.Length;
+                    const int chunkSize = 64 * 1024;
+                    buffer = new byte[chunkSize];
+                    long bytesSent = 0;
+                    int readBytes;
+                    while ((readBytes = dataStream.Read(buffer, 0, buffer.Length)) > 0)
+                    {
+                        requestStream.Write(buffer, 0, readBytes);
+                        bytesSent += readBytes;
+
+                        var status = "Uploading... " + bytesSent / 1024 + "KB of " + size / 1024 + "KB";
+                        Console.WriteLine(status);
+                    }
+
+                    //get response
+                    using (var response = request.GetResponse())
+                    using (var responseStream = response.GetResponseStream())
+                    using (var stream = new MemoryStream())
+                    {
+                        // ReSharper disable once PossibleNullReferenceException - exception would get catched anyway
+                        responseStream.CopyTo(stream);
+                        var result = Encoding.Default.GetString(stream.ToArray());
+                        Console.WriteLine(result);
+                    }
+                }
+                catch (Exception e )
+                {
+                    Console.WriteLine(e);
+                }
+            }, System.Threading.CancellationToken.None, TaskCreationOptions.LongRunning, TaskScheduler.Default);
+        }
+    }
+}

+ 111 - 0
AwInitilizer/Procedure/FourGenModuleCheckProcedure.cs

@@ -0,0 +1,111 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace AwInitilizer.Procedure
+{
+    public class FourGenModuleCheckProcedure : ProcedureBase
+    {
+        public FourGenModuleCheckProcedure() : base()
+        {
+            Name = "4G Check";
+            Content = "Check 4G module version and SIM card information matches user input";
+        }
+
+        internal override async Task<bool> Run()
+        {
+            Logger.Print("Connecting to EVSE");
+            if (!await base.CheckAndCreateSocket())
+            {
+                InfoLog += "EVSE connect failed\n";
+                return false;
+            }
+
+            if (!UpdateData.SystemID.ModelName.Network.ToString().Contains("4G"))
+            {
+                //if does not support 4G then end init
+                InfoLog += "model name does not support 4g ,skip update process\n";
+                return true;
+            }
+
+            var fourthGenModuleVersion = await serialPortocol.GetFourGenModuleVersion();
+            if (string.IsNullOrEmpty(fourthGenModuleVersion))
+            {
+                InfoLog += "4G module version read error\n";
+                Logger.Print("4G module version read error", isError: true);
+                return false;
+            }
+            else
+            {
+                InfoLog += $"Get 4G Module version :{fourthGenModuleVersion}\n";
+                if (fourthGenModuleVersion != UpdateData.FourGenModuleVersion)
+                {
+                    InfoLog += "4G module version not matched\n";
+                    Logger.Print("4G module version not matched", isError: true);
+                    return false;
+                }
+            }
+
+            var simstatus = await serialPortocol.GetSimStatus();
+            if (simstatus == null)
+            {
+                InfoLog += "Get sim status failed\n";
+                Logger.Print("Get sim status failed", isError: true);
+                return false;
+            }
+            else
+            {
+                if (simstatus.IsInstalled != UpdateData.IsSimInsert)
+                {
+                    Logger.Print("sim install status not matched", isError: true);
+                    return false;
+                }
+                else
+                {
+                    if (simstatus.IsInstalled)
+                    {
+                        var ICCIDstring = Encoding.ASCII.GetString(simstatus.ICCID);
+                        var IMSIstring = Encoding.ASCII.GetString(simstatus.IMSI);
+
+                        InfoLog += $"Get sim info, inserted:{simstatus.IsInstalled},ICCID:{ICCIDstring},IMSI:{IMSIstring}\n";
+
+                        if (ICCIDstring != UpdateData.ICCID)
+                        {
+                            Logger.Print("sim card ICCID not matched", isError: true);
+                            return false;
+                        }
+
+                        if (IMSIstring != UpdateData.IMSI)
+                        {
+                            Logger.Print("sim card IMSI not matched", isError: true);
+                            return false;
+                        }
+                    }
+                    else
+                    {
+                        InfoLog += $"Get sim info, inserted:{simstatus.IsInstalled}\n";
+
+                        if (!simstatus.ICCID.SequenceEqual(new byte[22]))
+                        {
+                            InfoLog += $"ICCID not empty : { BitConverter.ToString(simstatus.ICCID).Replace("-", " ")}\n";
+                            Logger.Print("sim card ICCID not empty", isError: true);
+                            return false;
+                        }
+
+                        if (!simstatus.IMSI.SequenceEqual(new byte[16]))
+                        {
+                            InfoLog += $"IMSI not empty : { BitConverter.ToString(simstatus.IMSI).Replace("-", " ")}\n";
+                            Logger.Print("sim card IMSI not empty", isError: true);
+                            return false;
+                        }
+                    }
+                }
+
+            }
+
+            return true;
+        }
+    }
+}

+ 91 - 0
AwInitilizer/Procedure/ProcedureBase.cs

@@ -0,0 +1,91 @@
+using AwInitilizer.Assist;
+using AwInitilizer.Interface;
+using AwInitilizer.Model;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Net.Sockets;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace AwInitilizer.Procedure
+{
+    public enum ProcedureStatus
+    {
+        Idle,Success,Failed
+    }
+
+    public class ProcedureBase
+    {
+        public string Name { get; set; }
+        public string Content { get; set; }
+        public bool IsActivated { get; set; } = true;
+
+        public ProcedureStatus Status { get; private set; }
+        public string InfoLog { get; internal set; }
+
+        public static UpdateData UpdateData { get; set; }
+        public static IIogger Logger { get; set; }
+
+        internal SerialPortocol serialPortocol { get; private set; }
+
+        internal static string ServerIpAddress = "192.168.1.10";
+
+        public async Task<bool> DoWork() {
+            if (!IsActivated)
+                return false;
+            InfoLog = "";
+            Logger.Print(Name + "Started");
+            var result = await Run();
+            Dispose();
+            Status = result ? ProcedureStatus.Success : ProcedureStatus.Failed;
+            Logger.Print(Name + "Complete");
+            return result;
+        }
+
+        internal virtual async Task<bool> Run()
+        {
+            return true;
+        }
+
+        public void Reset()
+        {
+            Status = ProcedureStatus.Idle;
+            InfoLog = "";
+        }
+
+        internal async Task<bool> CheckAndCreateSocket()
+        {
+            TcpSerializer socketConnection = null;
+            if (socketConnection == null || socketConnection.ConnectStatus == ConnectStatus.ConnectionFail ||
+                socketConnection.ConnectStatus == ConnectStatus.DisConnected)
+            {
+                socketConnection = new Assist.TcpSerializer(ip:ServerIpAddress);
+                await socketConnection.OpenAsync();
+                if(socketConnection.ConnectStatus != ConnectStatus.Connected)
+                {
+                    Logger.Print("EVSE tcp connection Failed,Check EVSE is connected", isError: true);
+                    return false;
+                }
+                Logger.Print("Connected");
+
+                serialPortocol = new SerialPortocol(socketConnection);
+                return true;
+            }
+            return true;
+        }
+
+        private void Dispose()
+        {
+            if(serialPortocol!=null)
+            {
+                try
+                {
+                    serialPortocol.Close();
+                }catch
+                { 
+                }
+            }
+        }
+    }
+}

+ 150 - 0
AwInitilizer/Procedure/RestarttoIdelProcedure.cs

@@ -0,0 +1,150 @@
+using Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.Collections.Specialized;
+using System.Diagnostics;
+using System.IO;
+using System.Linq;
+using System.Net;
+using System.Text;
+using System.Text.RegularExpressions;
+using System.Threading.Tasks;
+
+namespace AwInitilizer.Procedure
+{
+    public class RestarttoIdelProcedure : ProcedureBase
+    {
+        public RestarttoIdelProcedure() : base()
+        {
+            Name = "Restart to Idel";
+            Content = "Restart EVSSE and check status back to Idel";
+        }
+
+        internal override async Task<bool> Run()
+        {
+            var result = await FactorySet();
+            if (!result)
+            {
+                return false;
+            }
+            else
+            {
+                Logger.Print("Waiting Factory reset complete...");
+                await Task.Delay(TimeSpan.FromMinutes(2));
+                if(await CheckAllIdel())
+                {
+                    Logger.Print("All Connetor is Idel");
+                }
+                else
+                {
+                    return false;
+                }
+            }
+
+            return true;
+        }
+
+        private async Task<bool> FactorySet()
+        {
+            try
+            {
+                using (WebClient webClient = new WebClient())
+                {
+                    NameValueCollection parameters = new NameValueCollection();
+                    parameters.Add("SystemId", "");
+                    parameters.Add("SystemDateTime", "");
+                    parameters.Add("PhaseLossPolicy", "");
+                    parameters.Add("FactoryConfiguration", "1");
+                    parameters.Add("AuthorisationMode", "");
+                    parameters.Add("isAPP", "");
+                    parameters.Add("isQRCode", "");
+                    parameters.Add("isRFID", "");
+                    parameters.Add("QRCodeMadeMode", "");
+                    parameters.Add("QRCodeContent", "");
+                    parameters.Add("Intensity", "");
+                    parameters.Add("RfidCardNumEndian", "");
+                    parameters.Add("PsuAcInputType", "");
+                    webClient.QueryString = parameters;
+
+                    using (Stream stream = await webClient.OpenReadTaskAsync($"https://{ServerIpAddress}/set_system_action.php"))
+                    // 使用 StreamReader 讀取 stream 內的字元
+                    using (StreamReader reader = new StreamReader(stream))
+                    {
+                        // 將 StreamReader 所讀到的字元轉為 string
+                        string request = reader.ReadToEnd();
+                        InfoLog += $"factory set respons:\n{request}\n";
+                        var values = JsonConvert.DeserializeObject<Dictionary<string, string>>(request);
+                    }
+                }
+                return true;
+            }
+            catch(Exception e)
+            {
+                InfoLog += "Factory reset command failed\n";
+                InfoLog += e.Message;
+                InfoLog += "\n";
+
+                Logger.Print("Factory reset command failed", isError: true);
+                Logger.Print(e.Message, isError: true);
+                return false;
+            }
+        }
+
+        private async Task<bool> CheckAllIdel()
+        {
+            try
+            {
+                using (WebClient webClient = new WebClient())
+                {
+                    NameValueCollection parameters = new NameValueCollection();
+                    parameters.Add("opt", "2");
+                    webClient.QueryString = parameters;
+
+                    using (Stream stream = await webClient.OpenReadTaskAsync($"https://{ServerIpAddress}/get_query_action.php"))
+                    // 使用 StreamReader 讀取 stream 內的字元
+                    using (StreamReader reader = new StreamReader(stream))
+                    {
+                        // 將 StreamReader 所讀到的字元轉為 string
+                        string request = reader.ReadToEnd();
+                        InfoLog += $"get status respons:\n{request}\n";
+                        Regex rx = new Regex("(SystemStatus)\\\": (\\d)");
+                        var matches = rx.Matches(request);
+                        bool isAllPassed = true;
+                        for(int matchIndex=0; matchIndex< matches.Count; matchIndex++)
+                        {
+                            var match = matches[matchIndex];
+                            if (match.Groups.Count != 3)
+                            {
+                                InfoLog += $"Connector {matchIndex} status string mismatched\n";
+                                Logger.Print($"Connector {matchIndex} status string mismatched", isError:true);
+                                isAllPassed = false;
+                            }
+                            else
+                            {
+                                if(match.Groups[2].Value != "1")
+                                {
+                                    InfoLog += $"Connector {matchIndex} status not Idel\n";
+                                    Logger.Print($"Connector {matchIndex} status not Idel", isError: true);
+                                    isAllPassed = false;
+                                }
+                            }
+                        }
+
+                        return isAllPassed;
+                    }
+                }
+                return true;
+            }
+            catch (Exception e)
+            {
+                InfoLog += "Check all idel command failed\n";
+                InfoLog += e.Message;
+                InfoLog += "\n";
+
+                Logger.Print("Check all idel command failed", isError:true);
+                Logger.Print(e.Message, isError: true);
+                return false;
+            }
+        }
+    }
+}

+ 55 - 0
AwInitilizer/Properties/AssemblyInfo.cs

@@ -0,0 +1,55 @@
+using System.Reflection;
+using System.Resources;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Windows;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("AwInitilizer")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("AwInitilizer")]
+[assembly: AssemblyCopyright("Copyright ©  2020")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components.  If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+//In order to begin building localizable applications, set
+//<UICulture>CultureYouAreCodingWith</UICulture> in your .csproj file
+//inside a <PropertyGroup>.  For example, if you are using US english
+//in your source files, set the <UICulture> to en-US.  Then uncomment
+//the NeutralResourceLanguage attribute below.  Update the "en-US" in
+//the line below to match the UICulture setting in the project file.
+
+//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
+
+
+[assembly: ThemeInfo(
+    ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
+                                     //(used if a resource is not found in the page,
+                                     // or application resource dictionaries)
+    ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
+                                              //(used if a resource is not found in the page,
+                                              // app, or any theme specific resource dictionaries)
+)]
+
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]

+ 63 - 0
AwInitilizer/Properties/Resources.Designer.cs

@@ -0,0 +1,63 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+//     This code was generated by a tool.
+//     Runtime Version:4.0.30319.42000
+//
+//     Changes to this file may cause incorrect behavior and will be lost if
+//     the code is regenerated.
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+namespace AwInitilizer.Properties {
+    using System;
+    
+    
+    /// <summary>
+    ///   A strongly-typed resource class, for looking up localized strings, etc.
+    /// </summary>
+    // This class was auto-generated by the StronglyTypedResourceBuilder
+    // class via a tool like ResGen or Visual Studio.
+    // To add or remove a member, edit your .ResX file then rerun ResGen
+    // with the /str option, or rebuild your VS project.
+    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")]
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+    internal class Resources {
+        
+        private static global::System.Resources.ResourceManager resourceMan;
+        
+        private static global::System.Globalization.CultureInfo resourceCulture;
+        
+        [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+        internal Resources() {
+        }
+        
+        /// <summary>
+        ///   Returns the cached ResourceManager instance used by this class.
+        /// </summary>
+        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+        internal static global::System.Resources.ResourceManager ResourceManager {
+            get {
+                if (object.ReferenceEquals(resourceMan, null)) {
+                    global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("AwInitilizer.Properties.Resources", typeof(Resources).Assembly);
+                    resourceMan = temp;
+                }
+                return resourceMan;
+            }
+        }
+        
+        /// <summary>
+        ///   Overrides the current thread's CurrentUICulture property for all
+        ///   resource lookups using this strongly typed resource class.
+        /// </summary>
+        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+        internal static global::System.Globalization.CultureInfo Culture {
+            get {
+                return resourceCulture;
+            }
+            set {
+                resourceCulture = value;
+            }
+        }
+    }
+}

+ 117 - 0
AwInitilizer/Properties/Resources.resx

@@ -0,0 +1,117 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+</root>

+ 26 - 0
AwInitilizer/Properties/Settings.Designer.cs

@@ -0,0 +1,26 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+//     This code was generated by a tool.
+//     Runtime Version:4.0.30319.42000
+//
+//     Changes to this file may cause incorrect behavior and will be lost if
+//     the code is regenerated.
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+namespace AwInitilizer.Properties {
+    
+    
+    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.7.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 {
+                return defaultInstance;
+            }
+        }
+    }
+}

+ 7 - 0
AwInitilizer/Properties/Settings.settings

@@ -0,0 +1,7 @@
+<?xml version='1.0' encoding='utf-8'?>
+<SettingsFile xmlns="uri:settings" CurrentProfile="(Default)">
+  <Profiles>
+    <Profile Name="(Default)" />
+  </Profiles>
+  <Settings />
+</SettingsFile>

+ 76 - 0
AwInitilizer/app.manifest

@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="utf-8"?>
+<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
+  <assemblyIdentity version="1.0.0.0" name="MyApplication.app"/>
+  <trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
+    <security>
+      <requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
+        <!-- UAC Manifest Options
+             If you want to change the Windows User Account Control level replace the 
+             requestedExecutionLevel node with one of the following.
+
+        <requestedExecutionLevel  level="asInvoker" uiAccess="false" />
+        <requestedExecutionLevel  level="requireAdministrator" uiAccess="false" />
+        <requestedExecutionLevel  level="highestAvailable" uiAccess="false" />
+
+            Specifying requestedExecutionLevel element will disable file and registry virtualization. 
+            Remove this element if your application requires this virtualization for backwards
+            compatibility.
+        -->
+        <requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
+      </requestedPrivileges>
+    </security>
+  </trustInfo>
+
+  <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
+    <application>
+      <!-- A list of the Windows versions that this application has been tested on
+           and is designed to work with. Uncomment the appropriate elements
+           and Windows will automatically select the most compatible environment. -->
+
+      <!-- Windows Vista -->
+      <!--<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}" />-->
+
+      <!-- Windows 7 -->
+      <!--<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}" />-->
+
+      <!-- Windows 8 -->
+      <!--<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}" />-->
+
+      <!-- Windows 8.1 -->
+      <!--<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}" />-->
+
+      <!-- Windows 10 -->
+      <!--<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />-->
+
+    </application>
+  </compatibility>
+
+  <!-- Indicates that the application is DPI-aware and will not be automatically scaled by Windows at higher
+       DPIs. Windows Presentation Foundation (WPF) applications are automatically DPI-aware and do not need 
+       to opt in. Windows Forms applications targeting .NET Framework 4.6 that opt into this setting, should 
+       also set the 'EnableWindowsFormsHighDpiAutoResizing' setting to 'true' in their app.config. -->
+  <!--
+  <application xmlns="urn:schemas-microsoft-com:asm.v3">
+    <windowsSettings>
+      <dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true</dpiAware>
+    </windowsSettings>
+  </application>
+  -->
+
+  <!-- Enable themes for Windows common controls and dialogs (Windows XP and later) -->
+  <!--
+  <dependency>
+    <dependentAssembly>
+      <assemblyIdentity
+          type="win32"
+          name="Microsoft.Windows.Common-Controls"
+          version="6.0.0.0"
+          processorArchitecture="*"
+          publicKeyToken="6595b64144ccf1df"
+          language="*"
+        />
+    </dependentAssembly>
+  </dependency>
+  -->
+
+</assembly>

+ 4 - 0
AwInitilizer/packages.config

@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<packages>
+  <package id="Newtonsoft.Json" version="12.0.3" targetFramework="net48" />
+</packages>

+ 849 - 0
AwInitlizerInstaller/AwInitlizerInstaller.vdproj

@@ -0,0 +1,849 @@
+"DeployProject"
+{
+"VSVersion" = "3:800"
+"ProjectType" = "8:{978C614F-708E-4E1A-B201-565925725DBA}"
+"IsWebType" = "8:FALSE"
+"ProjectName" = "8:InitlizerInstaller"
+"LanguageId" = "3:1033"
+"CodePage" = "3:1252"
+"UILanguageId" = "3:1033"
+"SccProjectName" = "8:"
+"SccLocalPath" = "8:"
+"SccAuxPath" = "8:"
+"SccProvider" = "8:"
+    "Hierarchy"
+    {
+        "Entry"
+        {
+        "MsmKey" = "8:_67ED0F9CA2B2410084704C63C8FB5CE2"
+        "OwnerKey" = "8:_UNDEFINED"
+        "MsmSig" = "8:_UNDEFINED"
+        }
+        "Entry"
+        {
+        "MsmKey" = "8:_757BA0BD19C3D246BA621DB64DE2384D"
+        "OwnerKey" = "8:_67ED0F9CA2B2410084704C63C8FB5CE2"
+        "MsmSig" = "8:_UNDEFINED"
+        }
+        "Entry"
+        {
+        "MsmKey" = "8:_78ADCBE0D92EA001CDA0D5ECE8D69FA4"
+        "OwnerKey" = "8:_67ED0F9CA2B2410084704C63C8FB5CE2"
+        "MsmSig" = "8:_UNDEFINED"
+        }
+        "Entry"
+        {
+        "MsmKey" = "8:_UNDEFINED"
+        "OwnerKey" = "8:_67ED0F9CA2B2410084704C63C8FB5CE2"
+        "MsmSig" = "8:_UNDEFINED"
+        }
+        "Entry"
+        {
+        "MsmKey" = "8:_UNDEFINED"
+        "OwnerKey" = "8:_78ADCBE0D92EA001CDA0D5ECE8D69FA4"
+        "MsmSig" = "8:_UNDEFINED"
+        }
+        "Entry"
+        {
+        "MsmKey" = "8:_UNDEFINED"
+        "OwnerKey" = "8:_757BA0BD19C3D246BA621DB64DE2384D"
+        "MsmSig" = "8:_UNDEFINED"
+        }
+    }
+    "Configurations"
+    {
+        "Debug"
+        {
+        "DisplayName" = "8:Debug"
+        "IsDebugOnly" = "11:TRUE"
+        "IsReleaseOnly" = "11:FALSE"
+        "OutputFilename" = "8:Debug\\AwInitlizerInstaller.msi"
+        "PackageFilesAs" = "3:2"
+        "PackageFileSize" = "3:-2147483648"
+        "CabType" = "3:1"
+        "Compression" = "3:2"
+        "SignOutput" = "11:FALSE"
+        "CertificateFile" = "8:"
+        "PrivateKeyFile" = "8:"
+        "TimeStampServer" = "8:"
+        "InstallerBootstrapper" = "3:2"
+            "BootstrapperCfg:{63ACBE69-63AA-4F98-B2B6-99F9E24495F2}"
+            {
+            "Enabled" = "11:TRUE"
+            "PromptEnabled" = "11:TRUE"
+            "PrerequisitesLocation" = "2:1"
+            "Url" = "8:"
+            "ComponentsUrl" = "8:"
+                "Items"
+                {
+                    "{EDC2488A-8267-493A-A98E-7D9C3B36CDF3}:.NETFramework,Version=v4.7.2"
+                    {
+                    "Name" = "8:Microsoft .NET Framework 4.7.2 (x86 and x64)"
+                    "ProductCode" = "8:.NETFramework,Version=v4.7.2"
+                    }
+                    "{EDC2488A-8267-493A-A98E-7D9C3B36CDF3}:Microsoft.NetCore.CoreRuntime.3.1.x64"
+                    {
+                    "Name" = "8:.NET Core Runtime 3.1 (x64)"
+                    "ProductCode" = "8:Microsoft.NetCore.CoreRuntime.3.1.x64"
+                    }
+                    "{EDC2488A-8267-493A-A98E-7D9C3B36CDF3}:Microsoft.NetCore.CoreRuntime.3.1.x86"
+                    {
+                    "Name" = "8:.NET Core Runtime 3.1 (x86)"
+                    "ProductCode" = "8:Microsoft.NetCore.CoreRuntime.3.1.x86"
+                    }
+                }
+            }
+        }
+        "Release"
+        {
+        "DisplayName" = "8:Release"
+        "IsDebugOnly" = "11:FALSE"
+        "IsReleaseOnly" = "11:TRUE"
+        "OutputFilename" = "8:Release\\DCInitializerr.msi"
+        "PackageFilesAs" = "3:2"
+        "PackageFileSize" = "3:-2147483648"
+        "CabType" = "3:1"
+        "Compression" = "3:2"
+        "SignOutput" = "11:FALSE"
+        "CertificateFile" = "8:"
+        "PrivateKeyFile" = "8:"
+        "TimeStampServer" = "8:"
+        "InstallerBootstrapper" = "3:2"
+            "BootstrapperCfg:{63ACBE69-63AA-4F98-B2B6-99F9E24495F2}"
+            {
+            "Enabled" = "11:FALSE"
+            "PromptEnabled" = "11:TRUE"
+            "PrerequisitesLocation" = "2:2"
+            "Url" = "8:"
+            "ComponentsUrl" = "8:"
+                "Items"
+                {
+                    "{EDC2488A-8267-493A-A98E-7D9C3B36CDF3}:.NETFramework,Version=v4.7.2"
+                    {
+                    "Name" = "8:Microsoft .NET Framework 4.7.2 (x86 and x64)"
+                    "ProductCode" = "8:.NETFramework,Version=v4.7.2"
+                    }
+                }
+            }
+        }
+    }
+    "Deployable"
+    {
+        "CustomAction"
+        {
+        }
+        "DefaultFeature"
+        {
+        "Name" = "8:DefaultFeature"
+        "Title" = "8:"
+        "Description" = "8:"
+        }
+        "ExternalPersistence"
+        {
+            "LaunchCondition"
+            {
+                "{A06ECF26-33A3-4562-8140-9B0E340D4F24}:_10AB054652B047A293D239715AB90C86"
+                {
+                "Name" = "8:.NET Core"
+                "Message" = "8:[VSDNETCOREMSG]"
+                "AllowLaterVersions" = "11:FALSE"
+                "InstallUrl" = "8:https://dotnet.microsoft.com/download/dotnet-core/[NetCoreVerMajorDotMinor]"
+                "IsNETCore" = "11:TRUE"
+                "Architecture" = "2:0"
+                "Runtime" = "2:0"
+                }
+                "{A06ECF26-33A3-4562-8140-9B0E340D4F24}:_BD309AB8CB6A46AF977164CAF7BDF362"
+                {
+                "Name" = "8:.NET Framework"
+                "Message" = "8:[VSDNETMSG]"
+                "FrameworkVersion" = "8:.NETFramework,Version=v4.7.2"
+                "AllowLaterVersions" = "11:FALSE"
+                "InstallUrl" = "8:http://go.microsoft.com/fwlink/?LinkId=863262"
+                }
+            }
+        }
+        "File"
+        {
+            "{9F6F8455-1EF1-4B85-886A-4223BCC8E7F7}:_757BA0BD19C3D246BA621DB64DE2384D"
+            {
+            "AssemblyRegister" = "3:1"
+            "AssemblyIsInGAC" = "11:FALSE"
+            "AssemblyAsmDisplayName" = "8:System.Net.Http, Version=4.2.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
+                "ScatterAssemblies"
+                {
+                    "_757BA0BD19C3D246BA621DB64DE2384D"
+                    {
+                    "Name" = "8:System.Net.Http.dll"
+                    "Attributes" = "3:512"
+                    }
+                }
+            "SourcePath" = "8:System.Net.Http.dll"
+            "TargetName" = "8:"
+            "Tag" = "8:"
+            "Folder" = "8:_DE11C1EA8CD74CA9820344EFA2A02676"
+            "Condition" = "8:"
+            "Transitive" = "11:FALSE"
+            "Vital" = "11:TRUE"
+            "ReadOnly" = "11:FALSE"
+            "Hidden" = "11:FALSE"
+            "System" = "11:FALSE"
+            "Permanent" = "11:FALSE"
+            "SharedLegacy" = "11:FALSE"
+            "PackageAs" = "3:1"
+            "Register" = "3:1"
+            "Exclude" = "11:FALSE"
+            "IsDependency" = "11:TRUE"
+            "IsolateTo" = "8:"
+            }
+            "{9F6F8455-1EF1-4B85-886A-4223BCC8E7F7}:_78ADCBE0D92EA001CDA0D5ECE8D69FA4"
+            {
+            "AssemblyRegister" = "3:1"
+            "AssemblyIsInGAC" = "11:FALSE"
+            "AssemblyAsmDisplayName" = "8:Newtonsoft.Json, Version=12.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL"
+                "ScatterAssemblies"
+                {
+                    "_78ADCBE0D92EA001CDA0D5ECE8D69FA4"
+                    {
+                    "Name" = "8:Newtonsoft.Json.dll"
+                    "Attributes" = "3:512"
+                    }
+                }
+            "SourcePath" = "8:Newtonsoft.Json.dll"
+            "TargetName" = "8:"
+            "Tag" = "8:"
+            "Folder" = "8:_DE11C1EA8CD74CA9820344EFA2A02676"
+            "Condition" = "8:"
+            "Transitive" = "11:FALSE"
+            "Vital" = "11:TRUE"
+            "ReadOnly" = "11:FALSE"
+            "Hidden" = "11:FALSE"
+            "System" = "11:FALSE"
+            "Permanent" = "11:FALSE"
+            "SharedLegacy" = "11:FALSE"
+            "PackageAs" = "3:1"
+            "Register" = "3:1"
+            "Exclude" = "11:FALSE"
+            "IsDependency" = "11:TRUE"
+            "IsolateTo" = "8:"
+            }
+        }
+        "FileType"
+        {
+        }
+        "Folder"
+        {
+            "{1525181F-901A-416C-8A58-119130FE478E}:_5D843E07890C4EEA8A900CE8C1AA8C33"
+            {
+            "Name" = "8:#1916"
+            "AlwaysCreate" = "11:FALSE"
+            "Condition" = "8:"
+            "Transitive" = "11:FALSE"
+            "Property" = "8:DesktopFolder"
+                "Folders"
+                {
+                }
+            }
+            "{1525181F-901A-416C-8A58-119130FE478E}:_DB6D2134535C495EB36F82997F6BD5FC"
+            {
+            "Name" = "8:#1919"
+            "AlwaysCreate" = "11:FALSE"
+            "Condition" = "8:"
+            "Transitive" = "11:FALSE"
+            "Property" = "8:ProgramMenuFolder"
+                "Folders"
+                {
+                }
+            }
+            "{3C67513D-01DD-4637-8A68-80971EB9504F}:_DE11C1EA8CD74CA9820344EFA2A02676"
+            {
+            "DefaultLocation" = "8:[ProgramFiles64Folder][Manufacturer]\\[ProductName]"
+            "Name" = "8:#1925"
+            "AlwaysCreate" = "11:FALSE"
+            "Condition" = "8:"
+            "Transitive" = "11:FALSE"
+            "Property" = "8:TARGETDIR"
+                "Folders"
+                {
+                }
+            }
+        }
+        "LaunchCondition"
+        {
+        }
+        "Locator"
+        {
+        }
+        "MsiBootstrapper"
+        {
+        "LangId" = "3:1033"
+        "RequiresElevation" = "11:FALSE"
+        }
+        "Product"
+        {
+        "Name" = "8:Microsoft Visual Studio"
+        "ProductName" = "8:DCInitializerr"
+        "ProductCode" = "8:{57BF893C-BD30-40C3-8C04-55FFFC6E3FFE}"
+        "PackageCode" = "8:{17D0AC44-C1E0-48D8-B99F-B41743507E59}"
+        "UpgradeCode" = "8:{926B8A82-19A1-436D-A0E4-216EF638690B}"
+        "AspNetVersion" = "8:4.0.30319.0"
+        "RestartWWWService" = "11:FALSE"
+        "RemovePreviousVersions" = "11:FALSE"
+        "DetectNewerInstalledVersion" = "11:TRUE"
+        "InstallAllUsers" = "11:FALSE"
+        "ProductVersion" = "8:1.0.0"
+        "Manufacturer" = "8:8019"
+        "ARPHELPTELEPHONE" = "8:"
+        "ARPHELPLINK" = "8:"
+        "Title" = "8:DCInitializerr"
+        "Subject" = "8:"
+        "ARPCONTACT" = "8:8019"
+        "Keywords" = "8:"
+        "ARPCOMMENTS" = "8:"
+        "ARPURLINFOABOUT" = "8:"
+        "ARPPRODUCTICON" = "8:"
+        "ARPIconIndex" = "3:0"
+        "SearchPath" = "8:"
+        "UseSystemSearchPath" = "11:TRUE"
+        "TargetPlatform" = "3:1"
+        "PreBuildEvent" = "8:"
+        "PostBuildEvent" = "8:"
+        "RunPostBuildEvent" = "3:0"
+        }
+        "Registry"
+        {
+            "HKLM"
+            {
+                "Keys"
+                {
+                    "{60EA8692-D2D5-43EB-80DC-7906BF13D6EF}:_17B89C226D6C4EB5A6FF1ED7FDD0E25F"
+                    {
+                    "Name" = "8:Software"
+                    "Condition" = "8:"
+                    "AlwaysCreate" = "11:FALSE"
+                    "DeleteAtUninstall" = "11:FALSE"
+                    "Transitive" = "11:FALSE"
+                        "Keys"
+                        {
+                            "{60EA8692-D2D5-43EB-80DC-7906BF13D6EF}:_0A0DC6423FE34C32A1CD864F2CB1B5A0"
+                            {
+                            "Name" = "8:[Manufacturer]"
+                            "Condition" = "8:"
+                            "AlwaysCreate" = "11:FALSE"
+                            "DeleteAtUninstall" = "11:FALSE"
+                            "Transitive" = "11:FALSE"
+                                "Keys"
+                                {
+                                }
+                                "Values"
+                                {
+                                }
+                            }
+                        }
+                        "Values"
+                        {
+                        }
+                    }
+                }
+            }
+            "HKCU"
+            {
+                "Keys"
+                {
+                    "{60EA8692-D2D5-43EB-80DC-7906BF13D6EF}:_CFCFC0DBDD6748B3A3544EEAF668F0CD"
+                    {
+                    "Name" = "8:Software"
+                    "Condition" = "8:"
+                    "AlwaysCreate" = "11:FALSE"
+                    "DeleteAtUninstall" = "11:FALSE"
+                    "Transitive" = "11:FALSE"
+                        "Keys"
+                        {
+                            "{60EA8692-D2D5-43EB-80DC-7906BF13D6EF}:_CAF5704912144E62A27E7A8701449E91"
+                            {
+                            "Name" = "8:[Manufacturer]"
+                            "Condition" = "8:"
+                            "AlwaysCreate" = "11:FALSE"
+                            "DeleteAtUninstall" = "11:FALSE"
+                            "Transitive" = "11:FALSE"
+                                "Keys"
+                                {
+                                }
+                                "Values"
+                                {
+                                }
+                            }
+                        }
+                        "Values"
+                        {
+                        }
+                    }
+                }
+            }
+            "HKCR"
+            {
+                "Keys"
+                {
+                }
+            }
+            "HKU"
+            {
+                "Keys"
+                {
+                }
+            }
+            "HKPU"
+            {
+                "Keys"
+                {
+                }
+            }
+        }
+        "Sequences"
+        {
+        }
+        "Shortcut"
+        {
+            "{970C0BB2-C7D0-45D7-ABFA-7EC378858BC0}:_0029D7AF50AB41009B85628C3EF86FBC"
+            {
+            "Name" = "8:DCInitlizer"
+            "Arguments" = "8:"
+            "Description" = "8:"
+            "ShowCmd" = "3:1"
+            "IconIndex" = "3:0"
+            "Transitive" = "11:FALSE"
+            "Target" = "8:_67ED0F9CA2B2410084704C63C8FB5CE2"
+            "Folder" = "8:_5D843E07890C4EEA8A900CE8C1AA8C33"
+            "WorkingFolder" = "8:_DE11C1EA8CD74CA9820344EFA2A02676"
+            "Icon" = "8:"
+            "Feature" = "8:"
+            }
+        }
+        "UserInterface"
+        {
+            "{2479F3F5-0309-486D-8047-8187E2CE5BA0}:_06B6D267F4E94BE5B425D30AB4731E67"
+            {
+            "UseDynamicProperties" = "11:FALSE"
+            "IsDependency" = "11:FALSE"
+            "SourcePath" = "8:<VsdDialogDir>\\VsdUserInterface.wim"
+            }
+            "{DF760B10-853B-4699-99F2-AFF7185B4A62}:_11C821D245024749A30BCA5D0F3EFE2A"
+            {
+            "Name" = "8:#1900"
+            "Sequence" = "3:2"
+            "Attributes" = "3:1"
+                "Dialogs"
+                {
+                    "{688940B3-5CA9-4162-8DEE-2993FA9D8CBC}:_382FAC5B9172407CB8C32A56B66A9257"
+                    {
+                    "Sequence" = "3:200"
+                    "DisplayName" = "8:Installation Folder"
+                    "UseDynamicProperties" = "11:TRUE"
+                    "IsDependency" = "11:FALSE"
+                    "SourcePath" = "8:<VsdDialogDir>\\VsdAdminFolderDlg.wid"
+                        "Properties"
+                        {
+                            "BannerBitmap"
+                            {
+                            "Name" = "8:BannerBitmap"
+                            "DisplayName" = "8:#1001"
+                            "Description" = "8:#1101"
+                            "Type" = "3:8"
+                            "ContextData" = "8:Bitmap"
+                            "Attributes" = "3:4"
+                            "Setting" = "3:1"
+                            "UsePlugInResources" = "11:TRUE"
+                            }
+                        }
+                    }
+                    "{688940B3-5CA9-4162-8DEE-2993FA9D8CBC}:_8FDA95A71D3C48EEAD1B0075AF17E068"
+                    {
+                    "Sequence" = "3:100"
+                    "DisplayName" = "8:Welcome"
+                    "UseDynamicProperties" = "11:TRUE"
+                    "IsDependency" = "11:FALSE"
+                    "SourcePath" = "8:<VsdDialogDir>\\VsdAdminWelcomeDlg.wid"
+                        "Properties"
+                        {
+                            "BannerBitmap"
+                            {
+                            "Name" = "8:BannerBitmap"
+                            "DisplayName" = "8:#1001"
+                            "Description" = "8:#1101"
+                            "Type" = "3:8"
+                            "ContextData" = "8:Bitmap"
+                            "Attributes" = "3:4"
+                            "Setting" = "3:1"
+                            "UsePlugInResources" = "11:TRUE"
+                            }
+                            "CopyrightWarning"
+                            {
+                            "Name" = "8:CopyrightWarning"
+                            "DisplayName" = "8:#1002"
+                            "Description" = "8:#1102"
+                            "Type" = "3:3"
+                            "ContextData" = "8:"
+                            "Attributes" = "3:0"
+                            "Setting" = "3:1"
+                            "Value" = "8:#1202"
+                            "DefaultValue" = "8:#1202"
+                            "UsePlugInResources" = "11:TRUE"
+                            }
+                            "Welcome"
+                            {
+                            "Name" = "8:Welcome"
+                            "DisplayName" = "8:#1003"
+                            "Description" = "8:#1103"
+                            "Type" = "3:3"
+                            "ContextData" = "8:"
+                            "Attributes" = "3:0"
+                            "Setting" = "3:1"
+                            "Value" = "8:#1203"
+                            "DefaultValue" = "8:#1203"
+                            "UsePlugInResources" = "11:TRUE"
+                            }
+                        }
+                    }
+                    "{688940B3-5CA9-4162-8DEE-2993FA9D8CBC}:_EB7B70C73D8A467999FC732E05E00E46"
+                    {
+                    "Sequence" = "3:300"
+                    "DisplayName" = "8:Confirm Installation"
+                    "UseDynamicProperties" = "11:TRUE"
+                    "IsDependency" = "11:FALSE"
+                    "SourcePath" = "8:<VsdDialogDir>\\VsdAdminConfirmDlg.wid"
+                        "Properties"
+                        {
+                            "BannerBitmap"
+                            {
+                            "Name" = "8:BannerBitmap"
+                            "DisplayName" = "8:#1001"
+                            "Description" = "8:#1101"
+                            "Type" = "3:8"
+                            "ContextData" = "8:Bitmap"
+                            "Attributes" = "3:4"
+                            "Setting" = "3:1"
+                            "UsePlugInResources" = "11:TRUE"
+                            }
+                        }
+                    }
+                }
+            }
+            "{DF760B10-853B-4699-99F2-AFF7185B4A62}:_197810A4CE9A4933BE1D260892BC9EB1"
+            {
+            "Name" = "8:#1902"
+            "Sequence" = "3:1"
+            "Attributes" = "3:3"
+                "Dialogs"
+                {
+                    "{688940B3-5CA9-4162-8DEE-2993FA9D8CBC}:_B4E6D2822F744BB283A55F8080139BB3"
+                    {
+                    "Sequence" = "3:100"
+                    "DisplayName" = "8:Finished"
+                    "UseDynamicProperties" = "11:TRUE"
+                    "IsDependency" = "11:FALSE"
+                    "SourcePath" = "8:<VsdDialogDir>\\VsdFinishedDlg.wid"
+                        "Properties"
+                        {
+                            "BannerBitmap"
+                            {
+                            "Name" = "8:BannerBitmap"
+                            "DisplayName" = "8:#1001"
+                            "Description" = "8:#1101"
+                            "Type" = "3:8"
+                            "ContextData" = "8:Bitmap"
+                            "Attributes" = "3:4"
+                            "Setting" = "3:1"
+                            "UsePlugInResources" = "11:TRUE"
+                            }
+                            "UpdateText"
+                            {
+                            "Name" = "8:UpdateText"
+                            "DisplayName" = "8:#1058"
+                            "Description" = "8:#1158"
+                            "Type" = "3:15"
+                            "ContextData" = "8:"
+                            "Attributes" = "3:0"
+                            "Setting" = "3:1"
+                            "Value" = "8:#1258"
+                            "DefaultValue" = "8:#1258"
+                            "UsePlugInResources" = "11:TRUE"
+                            }
+                        }
+                    }
+                }
+            }
+            "{2479F3F5-0309-486D-8047-8187E2CE5BA0}:_58B0B576C36C4F93BCC853F919FAFB00"
+            {
+            "UseDynamicProperties" = "11:FALSE"
+            "IsDependency" = "11:FALSE"
+            "SourcePath" = "8:<VsdDialogDir>\\VsdBasicDialogs.wim"
+            }
+            "{DF760B10-853B-4699-99F2-AFF7185B4A62}:_6D2887B2FB1E44A98409BB0855469F6E"
+            {
+            "Name" = "8:#1900"
+            "Sequence" = "3:1"
+            "Attributes" = "3:1"
+                "Dialogs"
+                {
+                    "{688940B3-5CA9-4162-8DEE-2993FA9D8CBC}:_6114B5A02ACD4C91B4E0B00C00E5CB02"
+                    {
+                    "Sequence" = "3:210"
+                    "DisplayName" = "8:Installation Folder"
+                    "UseDynamicProperties" = "11:TRUE"
+                    "IsDependency" = "11:FALSE"
+                    "SourcePath" = "8:<VsdDialogDir>\\VsdFolderDlg.wid"
+                        "Properties"
+                        {
+                            "BannerBitmap"
+                            {
+                            "Name" = "8:BannerBitmap"
+                            "DisplayName" = "8:#1001"
+                            "Description" = "8:#1101"
+                            "Type" = "3:8"
+                            "ContextData" = "8:Bitmap"
+                            "Attributes" = "3:4"
+                            "Setting" = "3:1"
+                            "UsePlugInResources" = "11:TRUE"
+                            }
+                            "InstallAllUsersVisible"
+                            {
+                            "Name" = "8:InstallAllUsersVisible"
+                            "DisplayName" = "8:#1059"
+                            "Description" = "8:#1159"
+                            "Type" = "3:5"
+                            "ContextData" = "8:1;True=1;False=0"
+                            "Attributes" = "3:0"
+                            "Setting" = "3:0"
+                            "Value" = "3:1"
+                            "DefaultValue" = "3:1"
+                            "UsePlugInResources" = "11:TRUE"
+                            }
+                        }
+                    }
+                    "{688940B3-5CA9-4162-8DEE-2993FA9D8CBC}:_F9B783E6180B435EB0E312FCE0CBD325"
+                    {
+                    "Sequence" = "3:300"
+                    "DisplayName" = "8:Confirm Installation"
+                    "UseDynamicProperties" = "11:TRUE"
+                    "IsDependency" = "11:FALSE"
+                    "SourcePath" = "8:<VsdDialogDir>\\VsdConfirmDlg.wid"
+                        "Properties"
+                        {
+                            "BannerBitmap"
+                            {
+                            "Name" = "8:BannerBitmap"
+                            "DisplayName" = "8:#1001"
+                            "Description" = "8:#1101"
+                            "Type" = "3:8"
+                            "ContextData" = "8:Bitmap"
+                            "Attributes" = "3:4"
+                            "Setting" = "3:1"
+                            "UsePlugInResources" = "11:TRUE"
+                            }
+                        }
+                    }
+                    "{688940B3-5CA9-4162-8DEE-2993FA9D8CBC}:_FC12A22254AB4D858289B87A3D8D8C16"
+                    {
+                    "Sequence" = "3:200"
+                    "DisplayName" = "8:Welcome"
+                    "UseDynamicProperties" = "11:TRUE"
+                    "IsDependency" = "11:FALSE"
+                    "SourcePath" = "8:<VsdDialogDir>\\VsdWelcomeDlg.wid"
+                        "Properties"
+                        {
+                            "BannerBitmap"
+                            {
+                            "Name" = "8:BannerBitmap"
+                            "DisplayName" = "8:#1001"
+                            "Description" = "8:#1101"
+                            "Type" = "3:8"
+                            "ContextData" = "8:Bitmap"
+                            "Attributes" = "3:4"
+                            "Setting" = "3:1"
+                            "UsePlugInResources" = "11:TRUE"
+                            }
+                            "CopyrightWarning"
+                            {
+                            "Name" = "8:CopyrightWarning"
+                            "DisplayName" = "8:#1002"
+                            "Description" = "8:#1102"
+                            "Type" = "3:3"
+                            "ContextData" = "8:"
+                            "Attributes" = "3:0"
+                            "Setting" = "3:1"
+                            "Value" = "8:#1202"
+                            "DefaultValue" = "8:#1202"
+                            "UsePlugInResources" = "11:TRUE"
+                            }
+                            "Welcome"
+                            {
+                            "Name" = "8:Welcome"
+                            "DisplayName" = "8:#1003"
+                            "Description" = "8:#1103"
+                            "Type" = "3:3"
+                            "ContextData" = "8:"
+                            "Attributes" = "3:0"
+                            "Setting" = "3:1"
+                            "Value" = "8:#1203"
+                            "DefaultValue" = "8:#1203"
+                            "UsePlugInResources" = "11:TRUE"
+                            }
+                        }
+                    }
+                }
+            }
+            "{DF760B10-853B-4699-99F2-AFF7185B4A62}:_9D40FD712F6347DEAAAACBE1518231AE"
+            {
+            "Name" = "8:#1901"
+            "Sequence" = "3:2"
+            "Attributes" = "3:2"
+                "Dialogs"
+                {
+                    "{688940B3-5CA9-4162-8DEE-2993FA9D8CBC}:_2A2E22C10C584BEF9C06EA4D0FA97D01"
+                    {
+                    "Sequence" = "3:100"
+                    "DisplayName" = "8:Progress"
+                    "UseDynamicProperties" = "11:TRUE"
+                    "IsDependency" = "11:FALSE"
+                    "SourcePath" = "8:<VsdDialogDir>\\VsdAdminProgressDlg.wid"
+                        "Properties"
+                        {
+                            "BannerBitmap"
+                            {
+                            "Name" = "8:BannerBitmap"
+                            "DisplayName" = "8:#1001"
+                            "Description" = "8:#1101"
+                            "Type" = "3:8"
+                            "ContextData" = "8:Bitmap"
+                            "Attributes" = "3:4"
+                            "Setting" = "3:1"
+                            "UsePlugInResources" = "11:TRUE"
+                            }
+                            "ShowProgress"
+                            {
+                            "Name" = "8:ShowProgress"
+                            "DisplayName" = "8:#1009"
+                            "Description" = "8:#1109"
+                            "Type" = "3:5"
+                            "ContextData" = "8:1;True=1;False=0"
+                            "Attributes" = "3:0"
+                            "Setting" = "3:0"
+                            "Value" = "3:1"
+                            "DefaultValue" = "3:1"
+                            "UsePlugInResources" = "11:TRUE"
+                            }
+                        }
+                    }
+                }
+            }
+            "{DF760B10-853B-4699-99F2-AFF7185B4A62}:_A2A033ED28E649819E0194D4FF1FDE82"
+            {
+            "Name" = "8:#1902"
+            "Sequence" = "3:2"
+            "Attributes" = "3:3"
+                "Dialogs"
+                {
+                    "{688940B3-5CA9-4162-8DEE-2993FA9D8CBC}:_56B01EEFD27A43B494E43ECB4D911FC9"
+                    {
+                    "Sequence" = "3:100"
+                    "DisplayName" = "8:Finished"
+                    "UseDynamicProperties" = "11:TRUE"
+                    "IsDependency" = "11:FALSE"
+                    "SourcePath" = "8:<VsdDialogDir>\\VsdAdminFinishedDlg.wid"
+                        "Properties"
+                        {
+                            "BannerBitmap"
+                            {
+                            "Name" = "8:BannerBitmap"
+                            "DisplayName" = "8:#1001"
+                            "Description" = "8:#1101"
+                            "Type" = "3:8"
+                            "ContextData" = "8:Bitmap"
+                            "Attributes" = "3:4"
+                            "Setting" = "3:1"
+                            "UsePlugInResources" = "11:TRUE"
+                            }
+                        }
+                    }
+                }
+            }
+            "{DF760B10-853B-4699-99F2-AFF7185B4A62}:_A9002406B7E245889212FA2336B41A3B"
+            {
+            "Name" = "8:#1901"
+            "Sequence" = "3:1"
+            "Attributes" = "3:2"
+                "Dialogs"
+                {
+                    "{688940B3-5CA9-4162-8DEE-2993FA9D8CBC}:_3EC5FDC9ACBF4FF58132B7390516C1DA"
+                    {
+                    "Sequence" = "3:100"
+                    "DisplayName" = "8:Progress"
+                    "UseDynamicProperties" = "11:TRUE"
+                    "IsDependency" = "11:FALSE"
+                    "SourcePath" = "8:<VsdDialogDir>\\VsdProgressDlg.wid"
+                        "Properties"
+                        {
+                            "BannerBitmap"
+                            {
+                            "Name" = "8:BannerBitmap"
+                            "DisplayName" = "8:#1001"
+                            "Description" = "8:#1101"
+                            "Type" = "3:8"
+                            "ContextData" = "8:Bitmap"
+                            "Attributes" = "3:4"
+                            "Setting" = "3:1"
+                            "UsePlugInResources" = "11:TRUE"
+                            }
+                            "ShowProgress"
+                            {
+                            "Name" = "8:ShowProgress"
+                            "DisplayName" = "8:#1009"
+                            "Description" = "8:#1109"
+                            "Type" = "3:5"
+                            "ContextData" = "8:1;True=1;False=0"
+                            "Attributes" = "3:0"
+                            "Setting" = "3:0"
+                            "Value" = "3:1"
+                            "DefaultValue" = "3:1"
+                            "UsePlugInResources" = "11:TRUE"
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        "MergeModule"
+        {
+        }
+        "ProjectOutput"
+        {
+            "{5259A561-127C-4D43-A0A1-72F10C7B3BF8}:_67ED0F9CA2B2410084704C63C8FB5CE2"
+            {
+            "SourcePath" = "8:..\\AwInitilizer\\obj\\Release\\AwInitilizer.exe"
+            "TargetName" = "8:"
+            "Tag" = "8:"
+            "Folder" = "8:_DE11C1EA8CD74CA9820344EFA2A02676"
+            "Condition" = "8:"
+            "Transitive" = "11:FALSE"
+            "Vital" = "11:TRUE"
+            "ReadOnly" = "11:FALSE"
+            "Hidden" = "11:FALSE"
+            "System" = "11:FALSE"
+            "Permanent" = "11:FALSE"
+            "SharedLegacy" = "11:FALSE"
+            "PackageAs" = "3:1"
+            "Register" = "3:1"
+            "Exclude" = "11:FALSE"
+            "IsDependency" = "11:FALSE"
+            "IsolateTo" = "8:"
+            "ProjectOutputGroupRegister" = "3:1"
+            "OutputConfiguration" = "8:"
+            "OutputGroupCanonicalName" = "8:Built"
+            "OutputProjectGuid" = "8:{7A23D514-38E1-423E-9238-464B0E2AFCC0}"
+            "ShowKeyOutput" = "11:TRUE"
+                "ExcludeFilters"
+                {
+                }
+            }
+        }
+    }
+}

+ 9 - 0
Initilizer/App.xaml

@@ -0,0 +1,9 @@
+<Application x:Class="Initilizer.App"
+             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+             xmlns:local="clr-namespace:Initilizer"
+             StartupUri="MainWindow.xaml">
+    <Application.Resources>
+         
+    </Application.Resources>
+</Application>

+ 17 - 0
Initilizer/App.xaml.cs

@@ -0,0 +1,17 @@
+using System;
+using System.Collections.Generic;
+using System.Configuration;
+using System.Data;
+using System.Linq;
+using System.Threading.Tasks;
+using System.Windows;
+
+namespace Initilizer
+{
+    /// <summary>
+    /// Interaction logic for App.xaml
+    /// </summary>
+    public partial class App : Application
+    {
+    }
+}

+ 10 - 0
Initilizer/AssemblyInfo.cs

@@ -0,0 +1,10 @@
+using System.Windows;
+
+[assembly: ThemeInfo(
+    ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
+                                     //(used if a resource is not found in the page,
+                                     // or application resource dictionaries)
+    ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
+                                              //(used if a resource is not found in the page,
+                                              // app, or any theme specific resource dictionaries)
+)]

+ 9 - 0
Initilizer/Initilizer.csproj

@@ -0,0 +1,9 @@
+<Project Sdk="Microsoft.NET.Sdk.WindowsDesktop">
+
+  <PropertyGroup>
+    <OutputType>WinExe</OutputType>
+    <TargetFramework>netcoreapp3.1</TargetFramework>
+    <UseWPF>true</UseWPF>
+  </PropertyGroup>
+
+</Project>

+ 12 - 0
Initilizer/MainWindow.xaml

@@ -0,0 +1,12 @@
+<Window x:Class="Initilizer.MainWindow"
+        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
+        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+        xmlns:local="clr-namespace:Initilizer"
+        mc:Ignorable="d"
+        Title="MainWindow" Height="450" Width="800">
+    <Grid>
+        <Label Content="Test"/>
+    </Grid>
+</Window>

+ 28 - 0
Initilizer/MainWindow.xaml.cs

@@ -0,0 +1,28 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Navigation;
+using System.Windows.Shapes;
+
+namespace Initilizer
+{
+    /// <summary>
+    /// Interaction logic for MainWindow.xaml
+    /// </summary>
+    public partial class MainWindow : Window
+    {
+        public MainWindow()
+        {
+            InitializeComponent();
+        }
+    }
+}