FirmwareUpdateProcedure.cs 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407
  1. using AwInitilizer.Assist;
  2. using AwInitilizer.Model;
  3. using Newtonsoft.Json;
  4. using System;
  5. using System.Collections.Generic;
  6. using System.Collections.Specialized;
  7. using System.ComponentModel;
  8. using System.Globalization;
  9. using System.IO;
  10. using System.Linq;
  11. using System.Net;
  12. using System.Text;
  13. using System.Threading.Tasks;
  14. using System.Web;
  15. using System.Windows.Ink;
  16. namespace AwInitilizer.Procedure
  17. {
  18. public class FirmwareUpdateProcedure : ProcedureBase
  19. {
  20. internal string Version;
  21. internal string fileName;
  22. internal string module;
  23. //internal int SleepMinuts = 6;
  24. private FirmwareUpdateModel _model;
  25. public FirmwareUpdateProcedure(FirmwareUpdateModel model) :base()
  26. {
  27. _model = model;
  28. Name = string.Format("Firmware {0}", model.Module);
  29. Content = string.Format("Update {0} Firemware and check version matched", model.Module);
  30. Version = model.Version;
  31. fileName = model.FirmwareFileName;
  32. module = model.Module;
  33. }
  34. internal override async Task<bool> Run()
  35. {
  36. var oldVersion = await GetSpecificVersion();
  37. MesLogData.Add($"{module}OldVersion", oldVersion, true);
  38. if (string.IsNullOrEmpty(oldVersion))
  39. {
  40. InfoLog += $"Get {Name} version failed\n";
  41. Logger.Print($"Get {Name} version failed",isError:true);
  42. return false;
  43. }
  44. InfoLog += $"version before update : {oldVersion}\n";
  45. if (oldVersion == Version)
  46. {
  47. Logger.Print("Updated version detected");
  48. }
  49. Logger.Print("Firmware Uploading...");
  50. var uploadResult = await Uploadfiremware(fileName);
  51. MesLogData.Add($"{module}Upload", uploadResult.ToString(), true);
  52. if (uploadResult)
  53. {
  54. //wait restart
  55. Logger.Print("Waiting restart..");
  56. bool response = false;
  57. int pollinfCnt = 0;
  58. await Task.Delay(TimeSpan.FromMinutes(2));
  59. for (pollinfCnt = 0; pollinfCnt < 28; pollinfCnt++)
  60. {
  61. await Task.Delay(TimeSpan.FromSeconds(15));
  62. response = await ChekCsuBootCompelete();
  63. if (response)
  64. break;
  65. }
  66. //timeout
  67. if(pollinfCnt>=28)
  68. {
  69. Logger.Print("Wait restart timeout",isError:true);
  70. return false;
  71. }
  72. }
  73. else
  74. {
  75. InfoLog += $"Upload {Name} failed\n";
  76. Logger.Print($"Upload {Name} failed", isError: true);
  77. return false;
  78. }
  79. var updatedVersion = await GetSpecificVersion();
  80. //MesLogData.Add($"{module}NewVersion", updatedVersion);
  81. if (string.IsNullOrEmpty(updatedVersion))
  82. {
  83. InfoLog += $"Get updated {Name} version failed\n";
  84. Logger.Print($"Get updated {Name} version failed", isError: true);
  85. MesLogData.Add($"{module}NewVersion", "empty" , false);
  86. return false;
  87. }
  88. InfoLog += $"Get updated version : {updatedVersion}\n";
  89. bool isVersionMatched = false;
  90. if(module== "CsuRootFsFwRev")
  91. {
  92. isVersionMatched = updatedVersion.StartsWith(Version);
  93. }
  94. else
  95. {
  96. isVersionMatched = updatedVersion == Version;
  97. }
  98. if (isVersionMatched)
  99. {
  100. InfoLog += $"{Name}:Updated Version mismatched\n";
  101. Logger.Print($"{Name}:Updated Version mismatched", isError: true);
  102. MesLogData.Add($"{module}NewVersion", updatedVersion, false);
  103. return false;
  104. }
  105. else
  106. {
  107. MesLogData.Add($"{module}NewVersion", updatedVersion, true);
  108. Logger.Print($"{Name}:updated success");
  109. }
  110. return true;
  111. }
  112. internal virtual async Task<string> GetSpecificVersion()
  113. {
  114. var versions = await GetVersion();
  115. if(!versions.ContainsKey(module))
  116. {
  117. return "";
  118. }
  119. return versions[module];
  120. }
  121. internal async Task<Dictionary<string,string>> GetVersion(bool isConnectTest = false)
  122. {
  123. try
  124. {
  125. using (WebClientTimeout webClient = new WebClientTimeout())
  126. {
  127. NameValueCollection parameters = new NameValueCollection();
  128. parameters.Add("opt", "1");
  129. webClient.QueryString = parameters;
  130. using (Stream stream = await webClient.OpenReadTaskAsync($"https://{ServerIpAddress}/get_query_action.php"))
  131. // 使用 StreamReader 讀取 stream 內的字元
  132. using (StreamReader reader = new StreamReader(stream))
  133. {
  134. // 將 StreamReader 所讀到的字元轉為 string
  135. string request = reader.ReadToEnd();
  136. InfoLog += $"get version response:{request}\n";
  137. var values = JsonConvert.DeserializeObject<Dictionary<string, object>>(request);
  138. var toReturn = new Dictionary<string, string>();
  139. foreach(var pair in values)
  140. {
  141. if (pair.Value is string v)
  142. {
  143. toReturn.Add(pair.Key, v);
  144. }
  145. else if(pair.Value is Newtonsoft.Json.Linq.JArray a)
  146. {
  147. try
  148. {
  149. var versionList = JsonConvert.DeserializeObject<List<string>>(a.ToString());
  150. for (int index = 0; index < versionList.Count; index++)
  151. {
  152. toReturn.Add(string.Format("{0}{1}", pair.Key, index), versionList[index]);
  153. }
  154. }
  155. catch
  156. {
  157. }
  158. }
  159. }
  160. return toReturn;
  161. }
  162. }
  163. }
  164. catch(Exception e)
  165. {
  166. if (!isConnectTest)
  167. {
  168. Logger.Print("Get Version Failed", isError: true);
  169. Logger.Print(e.Message + "", isError: true);
  170. InfoLog += "Get Version Failed\n";
  171. InfoLog += e.Message;
  172. InfoLog += "\n";
  173. }
  174. return null;
  175. }
  176. }
  177. internal async Task<bool> Uploadfiremware(string fileName)
  178. {
  179. try
  180. {
  181. //using (var stream = File.Open(fileName, FileMode.Open))
  182. //{
  183. // UploadFileAsync(
  184. // new NameValueCollection()
  185. // {
  186. // {"fw_tag","iso" }
  187. // },
  188. // new UploadFile()
  189. // {
  190. // Name = "file",
  191. // Filename = Path.GetFileName(fileName),
  192. // Stream = stream
  193. // }
  194. // );
  195. //}
  196. //return true;
  197. using (var stream = File.Open(fileName, FileMode.Open))
  198. {
  199. var response = await UploadFiles(
  200. $"https://{ServerIpAddress}/upgrade_iso_action.php",
  201. new List<UploadFile>() {
  202. new UploadFile()
  203. {
  204. Name="file",
  205. Filename= Path.GetFileName(fileName),
  206. Stream = stream
  207. }
  208. },
  209. new NameValueCollection() {
  210. {"fw_tag","iso" }
  211. }
  212. );
  213. var responseStr = Encoding.ASCII.GetString(response).ToLower();
  214. InfoLog += $"get firmware update response {responseStr}\n";
  215. if (responseStr.Contains("file is uploaded"))
  216. return true;
  217. return false;
  218. }
  219. return true;
  220. //using (WebClient webClient = new WebClient())
  221. //{
  222. // NameValueCollection parameters = new NameValueCollection();
  223. // parameters.Add("fw_tag", "iso");
  224. // webClient.QueryString = parameters;
  225. // var responseBytes = await webClient.UploadFileTaskAsync($"https://{ServerIpAddress}/upgrade_iso_action.php", fileName);
  226. // string responseString = Encoding.ASCII.GetString(responseBytes);
  227. // return true;
  228. //}
  229. }
  230. catch(Exception e)
  231. {
  232. Logger.Print("Upload Firmware Failed", isError: true);
  233. Logger.Print(e.Message + "", isError: true);
  234. InfoLog += "Upload Firmware Failed\n";
  235. InfoLog += e.Message;
  236. InfoLog += "\n";
  237. return false;
  238. }
  239. }
  240. public async Task<byte[]> UploadFiles(string address, IEnumerable<UploadFile> files, NameValueCollection values)
  241. {
  242. var request = (HttpWebRequest) HttpWebRequest.Create(address);
  243. //request.Timeout = 10 * 1000;
  244. request.KeepAlive = true;
  245. request.Accept = "*/*";
  246. request.Method = "POST";
  247. request.Referer = address;
  248. request.Expect = "";
  249. var boundary = "---------------------------" + DateTime.Now.Ticks.ToString("x", NumberFormatInfo.InvariantInfo);
  250. request.ContentType = "multipart/form-data; boundary=" + boundary;
  251. boundary = "--" + boundary;
  252. using (var requestStream = request.GetRequestStream())
  253. {
  254. // Write the values
  255. foreach (string name in values.Keys)
  256. {
  257. var buffer = Encoding.ASCII.GetBytes(boundary + Environment.NewLine);
  258. requestStream.Write(buffer, 0, buffer.Length);
  259. buffer = Encoding.ASCII.GetBytes(string.Format("Content-Disposition: form-data; name=\"{0}\"{1}{1}", name, Environment.NewLine));
  260. requestStream.Write(buffer, 0, buffer.Length);
  261. buffer = Encoding.UTF8.GetBytes(values[name] + Environment.NewLine);
  262. requestStream.Write(buffer, 0, buffer.Length);
  263. }
  264. // Write the files
  265. foreach (var file in files)
  266. {
  267. var buffer = Encoding.ASCII.GetBytes(boundary + Environment.NewLine);
  268. requestStream.Write(buffer, 0, buffer.Length);
  269. buffer = Encoding.UTF8.GetBytes(string.Format("Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"{2}", file.Name, file.Filename, Environment.NewLine));
  270. requestStream.Write(buffer, 0, buffer.Length);
  271. var ctype = MimeMapping.GetMimeMapping(file.Filename);
  272. buffer = Encoding.ASCII.GetBytes(string.Format("Content-Type: {0}{1}{1}", MimeMapping.GetMimeMapping(file.Filename), Environment.NewLine));
  273. requestStream.Write(buffer, 0, buffer.Length);
  274. file.Stream.CopyTo(requestStream);
  275. buffer = Encoding.ASCII.GetBytes(Environment.NewLine);
  276. requestStream.Write(buffer, 0, buffer.Length);
  277. }
  278. var boundaryBuffer = Encoding.ASCII.GetBytes(boundary + "--");
  279. requestStream.Write(boundaryBuffer, 0, boundaryBuffer.Length);
  280. }
  281. using (var response = await request.GetResponseAsync())
  282. using (var responseStream = response.GetResponseStream())
  283. using (var stream = new MemoryStream())
  284. {
  285. responseStream.CopyTo(stream);
  286. return stream.ToArray();
  287. }
  288. }
  289. [Obsolete]
  290. public void UploadFileAsync(NameValueCollection values, UploadFile file )
  291. {
  292. //to fire events on the calling thread
  293. var _asyncOperation = AsyncOperationManager.CreateOperation(null);
  294. var ms = new MemoryStream();
  295. //make a copy of the input stream in case sb uses disposable stream
  296. file.Stream.CopyTo(ms);
  297. //you cannot set stream position often enough to zero
  298. ms.Position = 0;
  299. Task.Factory.StartNew(() =>
  300. {
  301. try
  302. {
  303. const string contentType = "application/octet-stream";
  304. var request = WebRequest.Create($"https://{ServerIpAddress}/get_query_action.php");
  305. request.Method = "POST";
  306. var boundary = "---------------------------" + DateTime.Now.Ticks.ToString("x", NumberFormatInfo.InvariantInfo);
  307. request.ContentType = "multipart/form-data; boundary=" + boundary;
  308. boundary = "--" + boundary;
  309. var dataStream = new MemoryStream();
  310. byte[] buffer;
  311. // Write the values
  312. foreach (string name in values.Keys)
  313. {
  314. buffer = Encoding.ASCII.GetBytes(boundary + Environment.NewLine);
  315. dataStream.Write(buffer, 0, buffer.Length);
  316. buffer = Encoding.ASCII.GetBytes(string.Format("Content-Disposition: form-data; name=\"{0}\"{1}{1}", name, Environment.NewLine));
  317. dataStream.Write(buffer, 0, buffer.Length);
  318. buffer = Encoding.UTF8.GetBytes(values[name] + Environment.NewLine);
  319. dataStream.Write(buffer, 0, buffer.Length);
  320. }
  321. // Write the file
  322. buffer = Encoding.ASCII.GetBytes(boundary + Environment.NewLine);
  323. dataStream.Write(buffer, 0, buffer.Length);
  324. buffer = Encoding.UTF8.GetBytes($"Content-Disposition: form-data; name=\"{file.Name}\"; filename=\"{file.Filename}\"{Environment.NewLine}");
  325. dataStream.Write(buffer, 0, buffer.Length);
  326. buffer = Encoding.ASCII.GetBytes(string.Format("Content-Type: {0}{1}{1}", MimeMapping.GetMimeMapping(file.Filename), Environment.NewLine));
  327. dataStream.Write(buffer, 0, buffer.Length);
  328. ms.CopyTo(dataStream);
  329. buffer = Encoding.ASCII.GetBytes(Environment.NewLine);
  330. dataStream.Write(buffer, 0, buffer.Length);
  331. buffer = Encoding.ASCII.GetBytes(boundary + "--");
  332. dataStream.Write(buffer, 0, buffer.Length);
  333. dataStream.Position = 0;
  334. //IMPORTANT: set content length to directly write to network socket
  335. request.ContentLength = dataStream.Length;
  336. var requestStream = request.GetRequestStream();
  337. //Write data in chunks and report progress
  338. var size = dataStream.Length;
  339. const int chunkSize = 64 * 1024;
  340. buffer = new byte[chunkSize];
  341. long bytesSent = 0;
  342. int readBytes;
  343. while ((readBytes = dataStream.Read(buffer, 0, buffer.Length)) > 0)
  344. {
  345. requestStream.Write(buffer, 0, readBytes);
  346. bytesSent += readBytes;
  347. var status = "Uploading... " + bytesSent / 1024 + "KB of " + size / 1024 + "KB";
  348. Console.WriteLine(status);
  349. }
  350. //get response
  351. using (var response = request.GetResponse())
  352. using (var responseStream = response.GetResponseStream())
  353. using (var stream = new MemoryStream())
  354. {
  355. // ReSharper disable once PossibleNullReferenceException - exception would get catched anyway
  356. responseStream.CopyTo(stream);
  357. var result = Encoding.Default.GetString(stream.ToArray());
  358. Console.WriteLine(result);
  359. }
  360. }
  361. catch (Exception e )
  362. {
  363. Console.WriteLine(e);
  364. }
  365. }, System.Threading.CancellationToken.None, TaskCreationOptions.LongRunning, TaskScheduler.Default);
  366. }
  367. }
  368. }