using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using AwInitilizer.Model; using AwInitilizer.Assist; using System.Collections.Specialized; using System.Globalization; using System.Net; using System.Web; using System.IO; using System.Runtime.InteropServices; namespace AwInitilizer.Procedure.FirmwareBundleUpload { public enum ErrorType { None, StartWaitTimeout, UploadFailed, SignalUpdateFailed } public enum LogEvent { UploadStartWait, FirmwareUpload } public class FirmwareBundleUploadProcedure : ProcedureBase { public ErrorType Error { get; set; } = ErrorType.None; private ProcedureLog.LogWriter LogWriter; private readonly static Dictionary ReportDict = new Dictionary() { { LogEvent.UploadStartWait, "UploadStartWait" }, { LogEvent.FirmwareUpload, "FirmwareUpload" }, }; private readonly static Dictionary LogDict = new Dictionary() { { LogEvent.UploadStartWait, "Wait restart {0}" }, { LogEvent.FirmwareUpload, "Firmware Upload {0}" }, }; public FirmwareBundleUploadProcedure() : base() { Name = string.Format("Firmware Upload"); Content = string.Format("Upload all Firemware"); LogWriter = new ProcedureLog.LogWriter(this) { ReportPair = ReportDict, LogPair = LogDict }; } internal override async Task Run() { bool response = false; int pollingCnt = 0; for (pollingCnt = 0; pollingCnt < 56; pollingCnt++) { await Task.Delay(TimeSpan.FromSeconds(15)); response = await CheckGetQueryAction(); if (response) break; } LogWriter.Log(string.Format("EVSE connet elapsed minute(s) : {0}, Expect:<14", pollingCnt * 0.25)); //timeout if (pollingCnt >= 56) { LogWriter.Report(LogEvent.UploadStartWait, "fail", isError: true); Error = ErrorType.StartWaitTimeout; return false; } LogWriter.Report(LogEvent.UploadStartWait, "success"); //upload firmware bool result = false; for (int tryCnt = 0; tryCnt < 10; tryCnt++) { //result = await UploadWithRestSharp(); result = await UploadWithApiClass(); if (result) break; else await Task.Delay(1000); } if(!result) { Error = ErrorType.UploadFailed; return false; } return result; } private async Task UploadWithHttpWebRequest() { var updateList = UpdateData.FirmwareUpdateModels; //open all file stream //List firmwareFileStream = new List(); List UploadFileList = new List(); try { for (int modelIndex = 0; modelIndex < updateList.Count; modelIndex++) //foreach (var model in updateList) { var model = updateList[modelIndex]; var stream = File.Open(model.FirmwareFileName, FileMode.Open); var uploadFile = new UploadFile() { Name = string.Format("files[]", modelIndex + 1), Filename = Path.GetFileName(model.FirmwareFileName), Stream = stream }; UploadFileList.Add(uploadFile); } } catch (Exception e) { LogWriter.Log("create file stream failed"); LogWriter.Report(LogEvent.FirmwareUpload, "fail", isError: true); return false; } Logger.Print("Uploading Firmware", isError: false); //upload try { var uploadResult = await UploadFiles( $"https://{ServerIpAddress}/upgrade_iso_action.php", files: UploadFileList, new NameValueCollection() { {"fw_tag","iso" } } ); var responseStr = Encoding.ASCII.GetString(uploadResult).ToLower(); //InfoLog += $"get firmware update response {responseStr}\n"; LogWriter.Log("get firmware update response {responseStr}"); if (responseStr.Contains("file is uploaded")) return true; return false; } catch { //InfoLog += $"file upload failed"; LogWriter.Log($"file upload failed"); MesLogData.Add($"FirmwareUpload", "0", false); } //Logger.Print("Firmware Upload Complete", isError: false); LogWriter.Log("Firmware Upload Complete"); MesLogData.Add($"FirmwareUpload", "1" , true); //release all foreach (var uploadFile in UploadFileList) { if (uploadFile != null && uploadFile.Stream != null) { Logger.Print($"Close {uploadFile.Filename}", isError: false); try { uploadFile.Stream.Close(); uploadFile.Stream.Dispose(); } catch { } } } return true; } private async Task UploadWithApiClass() { var updateList = UpdateData.FirmwareUpdateModels; var updateNameList = updateList .Where(x => !string.IsNullOrEmpty(x.FirmwareFileName)) .Select(x => x.FirmwareFileName) .ToList(); var uploadResult = await EvHttpClient.GetUploadfirmwareResultString(updateNameList); LogWriter.Log(uploadResult.Msg); return uploadResult.IsSuccess; } private async Task UploadWithRestSharp() { var updateList = UpdateData.FirmwareUpdateModels; var restClient = new RestSharp.RestClient($"https://{ServerIpAddress}"); restClient.ConfigureWebRequest((r) => { r.KeepAlive = true; }); var request = new RestSharp.RestRequest("upgrade_iso_action.php", RestSharp.Method.POST); request.AlwaysMultipartFormData = true; request.AddHeader("Content-Type", "multipart/form-data"); request.AddParameter("fw_tag", "iso"); foreach (var file in updateList) { request.AddFile("files[]", file.FirmwareFileName); } RestSharp.IRestResponse response = await restClient.ExecuteAsync(request); if (response.IsSuccessful) { LogWriter.Report(LogEvent.FirmwareUpload,"success"); return true; } else { LogWriter.Report(LogEvent.FirmwareUpload, "fail", isError: true); if (response.ErrorException!= null) { LogWriter.Log(response.ErrorException.Message,isError:true,isDebugLog: true); if (response.ErrorException.InnerException != null) { LogWriter.Log(response.ErrorException.InnerException.Message, isError: true, isDebugLog: true); } LogWriter.Log(response.StatusCode.ToString(), isError: true, isDebugLog: true); } return false; } } public async Task UploadFilesRestSharp(string address, IEnumerable files, NameValueCollection values) { var restClient = new RestSharp.RestClient(address); var request = new RestSharp.RestRequest(RestSharp.Method.POST); request.AlwaysMultipartFormData = true; request.AddHeader("Content-Type", "multipart/form-data"); request.AddParameter("fw_tag", "iso"); foreach (var file in files) { request.AddFile("files[]", file); } RestSharp.IRestResponse response = restClient.Execute(request); if(response.IsSuccessful) { } return response.RawBytes; } public async Task UploadFiles(string address, IEnumerable files, NameValueCollection values) { var request = (HttpWebRequest)HttpWebRequest.Create(address); request.Timeout = 2 * 60 * 1000; 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; string sendString = ""; 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.ASCII.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(); } } } }