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));
        }
Beispiel #3
0
        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);
        }
Beispiel #5
0
        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);
        }
Beispiel #7
0
        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()));
        }