FirmwareUpdateProcedure.cs 17 KB

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