private static void TransmitFileInfoToExtFlash(MeadowSerialDevice meadow, HcomMeadowRequestType requestType, string sourceFileName, string targetFileName, int partition, uint mcuAddr, bool deleteFile, bool lastInSeries = false) { var sw = new Stopwatch(); var sendTargetData = new SendTargetData(meadow, false); try { //---------------------------------------------- if (deleteFile == true) { // No data packets, no end-of-file message and no mcu address sendTargetData.BuildAndSendFileRelatedCommand(requestType, (UInt32)partition, 0, 0, 0, string.Empty, sourceFileName); return; } // If ESP32 file we must also send the MD5 has of the file string md5Hash = string.Empty; if (mcuAddr != 0) { using (var md5 = MD5.Create()) { using (var stream = File.OpenRead(sourceFileName)) { var hash = md5.ComputeHash(stream); md5Hash = BitConverter.ToString(hash).Replace("-", "").ToLowerInvariant(); } } } // Open, read and close the data file var fileBytes = File.ReadAllBytes(sourceFileName); var fileCrc32 = CrcTools.Crc32part(fileBytes, fileBytes.Length, 0); var fileLength = fileBytes.Length; sw.Start(); sw.Restart(); sendTargetData.SendTheEntireFile(requestType, targetFileName, (uint)partition, fileBytes, mcuAddr, fileCrc32, md5Hash, lastInSeries); sw.Stop(); if (sendTargetData.Verbose) { Console.WriteLine($"It took {sw.ElapsedMilliseconds:N0} millisec to send {fileLength:N0} bytes. FileCrc:{fileCrc32:x08}"); } } catch (Exception ex) { Debug.WriteLine($"TransmitFileInfoToExtFlash threw :{ex}"); throw; } }
/// <summary> /// Write a file to the Meadow /// </summary> /// <param name="sourceFileName">The name of the file</param> /// <param name="destinationFileName">The path to the file</param> /// <param name="timeout">The amount of time to wait to write the file</param> /// <param name="cancellationToken">The <see cref="CancellationToken"/> to cancel the operation</param> /// <returns></returns> public async Task <FileTransferResult> WriteFileAsync(string sourceFileName, string destinationFileName, TimeSpan timeout, CancellationToken cancellationToken = default) { if (IsDeviceInitialized() == false) { throw new Exception("Device is not initialized"); } var fi = new FileInfo(sourceFileName); if (!fi.Exists) { throw new FileNotFoundException("Cannot find source file", fi.FullName); } // If ESP32 file we must also send the MD5 has of the file using var md5 = MD5.Create(); var fileBytes = File.ReadAllBytes(sourceFileName); var hash = md5.ComputeHash(fileBytes); string md5Hash = BitConverter.ToString(hash) .Replace("-", "") .ToLowerInvariant(); var fileCrc32 = CrcTools.Crc32part(fileBytes, fileBytes.Length, 0); var command = await new FileCommandBuilder( HcomMeadowRequestType.HCOM_MDOW_REQUEST_START_FILE_TRANSFER) .WithSourceFileName(sourceFileName) .WithDestinationFileName(destinationFileName) .WithTimeout(timeout) .WithPartition(0) .BuildAsync(); var sw = Stopwatch.StartNew(); await SendTheEntireFile(command, true, cancellationToken) .ConfigureAwait(false); sw.Stop(); return(new FileTransferResult(sw.ElapsedMilliseconds, fileBytes.Length, fileCrc32)); }
async Task <(List <string> files, List <UInt32> crcs)> GetLocalFiles(TextWriter outputPaneWriter, CancellationToken cts, string folder) { // get list of files in folder // var files = Directory.GetFiles(folder, "*.dll"); var paths = Directory.EnumerateFiles(folder, "*.*", SearchOption.TopDirectoryOnly) .Where(s => s.EndsWith(".exe") || s.EndsWith(".dll") || s.EndsWith(".bmp") || s.EndsWith(".jpg") || s.EndsWith(".jpeg") || s.EndsWith(".txt")); var files = new List <string>(); var crcs = new List <UInt32>(); foreach (var file in paths) { if (cts.IsCancellationRequested) { break; } using (FileStream fs = File.Open(file, FileMode.Open)) { var len = (int)fs.Length; var bytes = new byte[len]; fs.Read(bytes, 0, len); //0x var crc = CrcTools.Crc32part(bytes, len, 0);// 0x04C11DB7); Console.WriteLine($"{file} crc is {crc}"); files.Add(Path.GetFileName(file)); crcs.Add(crc); } } return(files, crcs); }
public async Task DeployAppAsync(string applicationFilePath, string osVersion, bool includePdbs = false, CancellationToken cancellationToken = default) { if (!File.Exists(applicationFilePath)) { Console.WriteLine($"{applicationFilePath} not found."); return; } await DeleteTemporaryFiles(cancellationToken); var fi = new FileInfo(applicationFilePath); var deviceFiles = await GetFilesAndCrcsAsync( DefaultTimeout, cancellationToken : cancellationToken) .ConfigureAwait(false); //rename App.dll to App.exe var fileNameDll = Path.Combine(fi.DirectoryName, "App.dll"); var fileNameExe = Path.Combine(fi.DirectoryName, "App.exe"); var fileNamePdb = Path.Combine(fi.DirectoryName, "App.pdb"); if (File.Exists(fileNameDll)) { if (File.Exists(fileNameExe)) { File.Delete(fileNameExe); } File.Copy(fileNameDll, fileNameExe); } foreach (var f in deviceFiles) { Logger.LogInformation("Found {file} (CRC: {crc})", f.Key, f.Value); } var binaries = Directory.EnumerateFiles(fi.DirectoryName, "*.*", SearchOption.TopDirectoryOnly) .Where(s => new FileInfo(s).Extension != ".dll") .Where(s => new FileInfo(s).Extension != ".pdb"); // .Where(s => extensions.Contains(new FileInfo(s).Extension)); var files = new Dictionary <string, uint>(); if (includePdbs) { await AddFile(fileNamePdb, false); } async Task AddFile(string file, bool includePdbs) { if (files.ContainsKey(Path.GetFileName(file))) { return; } using FileStream fs = File.Open(file, FileMode.Open); var len = (int)fs.Length; var bytes = new byte[len]; await fs.ReadAsync(bytes, 0, len, cancellationToken); //0x var crc = CrcTools.Crc32part(bytes, len, 0); // 0x04C11DB7); Logger.LogDebug("{file} crc is {crc:X8}", file, crc); files.Add(file, crc); if (includePdbs) { var pdbFile = Path.ChangeExtension(file, "pdb"); if (File.Exists(pdbFile)) { await AddFile(pdbFile, false) .ConfigureAwait(false); } } } var dependencies = AssemblyManager.GetDependencies(fi.Name, fi.DirectoryName, osVersion) .Where(x => x.Contains("App.") == false).ToList(); //add local files (this includes App.exe) foreach (var file in binaries) { await AddFile(file, false); } //crawl dependencies foreach (var file in dependencies) { await AddFile(file, includePdbs); } // delete unused files foreach (var devicefile in deviceFiles.Keys) { bool found = false; foreach (var localfile in files.Keys) { if (Path.GetFileName(localfile).Equals(devicefile)) { found = true; } } if (!found) { await DeleteFileAsync(devicefile, cancellationToken : cancellationToken) .ConfigureAwait(false); Logger.LogInformation("Removing file: {file}", devicefile); } } // write new files foreach (var file in files) { var filename = Path.GetFileName(file.Key); if (deviceFiles.ContainsKey(filename) && deviceFiles[filename] == file.Value) { Logger.LogInformation("Skipping file (hash match): {file}", filename); continue; } if (!File.Exists(file.Key)) { Logger.LogInformation("{file} not found", filename); continue; } Logger.LogInformation("Writing file: {file}", filename); await WriteFileAsync( file.Key, filename, DefaultTimeout, cancellationToken) .ConfigureAwait(false); Logger.LogInformation("Wrote file: {file}", file.Key); } Logger.LogInformation("{file} deploy complete", fi.Name); }
public static async Task DeployApp(MeadowSerialDevice meadow, string applicationFilePath) { if (!File.Exists(applicationFilePath)) { Console.WriteLine($"{applicationFilePath} not found."); return; } FileInfo fi = new FileInfo(applicationFilePath); if (Environment.OSVersion.Platform == PlatformID.Win32NT) { // for some strange reason, System.Net.Http.dll doesn't get copied to the output folder in VS. // so, we need to copy it over from the meadow assemblies nuget. CopySystemNetHttpDll(fi.DirectoryName); } var deviceFile = await meadow.GetFilesAndCrcs(); var extensions = new List <string> { ".exe", ".bmp", ".jpg", ".jpeg", ".json", ".xml", ".yml", ".txt" }; var paths = Directory.EnumerateFiles(fi.DirectoryName, "*.*", SearchOption.TopDirectoryOnly) .Where(s => extensions.Contains(new FileInfo(s).Extension)); var files = new List <string>(); var crcs = new List <UInt32>(); foreach (var file in paths) { using (FileStream fs = File.Open(file, FileMode.Open)) { var len = (int)fs.Length; var bytes = new byte[len]; fs.Read(bytes, 0, len); //0x var crc = CrcTools.Crc32part(bytes, len, 0);// 0x04C11DB7); //Console.WriteLine($"{file} crc is {crc}"); files.Add(Path.GetFileName(file)); crcs.Add(crc); } } var dependences = AssemblyManager.GetDependencies(fi.Name, fi.DirectoryName); //crawl dependences foreach (var file in dependences) { using (FileStream fs = File.Open(Path.Combine(fi.DirectoryName, file), FileMode.Open)) { var len = (int)fs.Length; var bytes = new byte[len]; fs.Read(bytes, 0, len); //0x var crc = CrcTools.Crc32part(bytes, len, 0);// 0x04C11DB7); Console.WriteLine($"{file} crc is {crc}"); files.Add(Path.GetFileName(file)); crcs.Add(crc); } } // delete unused filed foreach (var file in deviceFile.files) { if (files.Contains(file) == false) { await meadow.DeleteFile(file).ConfigureAwait(false); Console.WriteLine($"Removing file: {file}"); } } // write new files for (int i = 0; i < files.Count; i++) { if (deviceFile.crcs.Contains(crcs[i])) { Console.WriteLine($"Skipping file: {files[i]}"); continue; } if (!File.Exists(Path.Combine(fi.DirectoryName, files[i]))) { Console.WriteLine($"{files[i]} not found"); continue; } await meadow.WriteFile(files[i], fi.DirectoryName); Console.WriteLine($"Writing file: {files[i]}"); } Console.WriteLine($"{fi.Name} deploy complete"); }
async Task <(List <string> files, List <UInt32> crcs)> GetLocalFiles(IOutputPaneWriter outputPaneWriter, CancellationToken cts, string folder) { // get list of files in folder // var files = Directory.GetFiles(folder, "*.dll"); CopySystemNetHttpDll(); var extensions = new List <string> { ".exe", ".bmp", ".jpg", ".jpeg", ".json", ".xml", ".yml", ".txt" }; var paths = Directory.EnumerateFiles(folder, "*.*", SearchOption.TopDirectoryOnly) .Where(s => extensions.Contains(new FileInfo(s).Extension)); var files = new List <string>(); var crcs = new List <UInt32>(); foreach (var file in paths) { if (cts.IsCancellationRequested) { break; } using (FileStream fs = File.Open(file, FileMode.Open)) { var len = (int)fs.Length; var bytes = new byte[len]; fs.Read(bytes, 0, len); //0x var crc = CrcTools.Crc32part(bytes, len, 0);// 0x04C11DB7); Console.WriteLine($"{file} crc is {crc}"); files.Add(Path.GetFileName(file)); crcs.Add(crc); } } var dependences = AssemblyManager.GetDependencies("App.exe", folder); //crawl dependences foreach (var file in dependences) { if (cts.IsCancellationRequested) { break; } using (FileStream fs = File.Open(Path.Combine(folder, file), FileMode.Open)) { var len = (int)fs.Length; var bytes = new byte[len]; fs.Read(bytes, 0, len); //0x var crc = CrcTools.Crc32part(bytes, len, 0);// 0x04C11DB7); Console.WriteLine($"{file} crc is {crc}"); files.Add(Path.GetFileName(file)); crcs.Add(crc); } } return(files, crcs); }
private async Task EncodeAndSendPacket(byte[] messageBytes, int messageOffset, int messageSize, CancellationToken cancellationToken) { try { // For testing calculate the crc including the sequence number _packetCrc32 = CrcTools.Crc32part(messageBytes, messageSize, 0, _packetCrc32); // Add 2, first to account for start delimiter and second for end byte[] encodedBytes = new byte[MeadowDeviceManager.MaxEstimatedSizeOfEncodedPayload + 2]; // Skip first byte so it can be a start delimiter int encodedToSend = CobsTools.CobsEncoding( messageBytes, messageOffset, messageSize, ref encodedBytes, 1); // Verify COBS - any delimiters left? Skip first byte for (int i = 1; i < encodedToSend; i++) { if (encodedBytes[i] == 0x00) { throw new InvalidProgramException( "All zeros should have been removed. There's one at offset of {i}"); } } // Terminate packet with delimiter so packet boundaries can be more easily found encodedBytes[0] = 0; // Start delimiter encodedToSend++; encodedBytes[encodedToSend] = 0; // End delimiter encodedToSend++; try { using var cts = new CancellationTokenSource(DefaultTimeout); cts.Token.Register(() => throw new TimeoutException("Timeout while writing to serial port")); var combinedCts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, cts.Token); await WriteAsync(encodedBytes, encodedToSend, combinedCts.Token) .ConfigureAwait(false); } catch (InvalidOperationException ioe) // Port not opened { Logger.LogError(ioe, "Write but port not opened"); throw; } catch (ArgumentOutOfRangeException aore) // offset or count don't match buffer { Logger.LogError(aore, "Write buffer, offset and count don't line up"); throw; } catch (ArgumentException ae) // offset plus count > buffer length { Logger.LogError(ae, "Write offset plus count > buffer length"); throw; } catch (TimeoutException te) // Took too long to send { Logger.LogError(te, "Write took too long to send"); throw; } } catch (Exception except) { Logger.LogTrace(except, "EncodeAndSendPacket threw"); throw; } }
public async Task <FileCommand> BuildAsync() { if (RequestType != HcomMeadowRequestType.HCOM_MDOW_REQUEST_DELETE_FILE_BY_NAME) { if (string.IsNullOrWhiteSpace(SourceFileName)) { throw new ArgumentNullException(SourceFileName); } if (FileBytes == null) { var fi = new FileInfo(SourceFileName); if (!fi.Exists) { throw new FileNotFoundException("Cannot find source file", fi.FullName); } FileBytes = File.ReadAllBytes(SourceFileName); } FileSize = FileBytes.Length; if (Md5Hash == null) { // Calculate the file hashes using var md5 = MD5.Create(); var hash = md5.ComputeHash(FileBytes); if (McuAddress != 0) { Md5Hash = BitConverter.ToString(hash) .Replace("-", "") .ToLowerInvariant(); } } if (Crc32 == 0) { Crc32 = CrcTools.Crc32part(FileBytes, FileBytes.Length, 0); } } else { SourceFileName ??= DestinationFileName; } DestinationFileName ??= Path.GetFileName(SourceFileName); if (ResponsePredicate == null) { if (ResponseMessageType != null) { ResponsePredicate = e => e.MessageType == ResponseMessageType; } else { ResponsePredicate = e => e.MessageType == MeadowMessageType.Concluded; } } if (CompletionPredicate == null) { if (CompletionMessageType != null) { CompletionPredicate = e => e.MessageType == CompletionMessageType; } else { CompletionPredicate = e => e.MessageType == MeadowMessageType.Concluded; } } return(new FileCommand( RequestType, Timeout ?? DefaultTimeout, SourceFileName, DestinationFileName, Md5Hash, Crc32, FileSize, Partition, McuAddress, FileBytes, ResponsePredicate, CompletionPredicate, ToString())); }