/// <summary> /// Download firmware file to slave. /// 1. All detected slaves are set to PREOP state. /// 2. Target slave is set to INIT state. /// 3. Target slave is set to BOOT state. /// 4. Firmware file is downloaded to target slave. /// 5. Target slave is set to INIT state regardless of whether /// the file download was successful or not. /// </summary> /// <param name="slaveIndex">Slave index.</param> /// <param name="fileName">Absolute path to firmware file.</param> /// <returns>True if operation was successful, false otherwise./returns> public bool DownloadFirmware(int slaveIndex, string fileName) { FileInfo fileInfo = new FileInfo(fileName); if (!fileInfo.Exists) { return(false); } bool success = false; if (EcHL.RequestCommonState(this.Context, (UInt16)SlaveState.PreOp) == 1) { UInt16 currentState = EcHL.RequestState(this.Context, slaveIndex, (UInt16)SlaveState.Init); if (currentState == (UInt16)SlaveState.Init) { currentState = EcHL.RequestState(this.Context, slaveIndex, (UInt16)SlaveState.Boot); if (currentState == (UInt16)SlaveState.Boot) { int currentPackageNumber = -1; int totalPackages = 0; int remainingSize = -1; EcHL.FOECallback callback = (slaveIndex, packageNumber, datasize) => { if (packageNumber == 0) { _logger.LogInformation($"FoE: Write {datasize} bytes to {slaveIndex}. slave"); } else { _logger.LogInformation($"FoE: {packageNumber}. package with {remainingSize - datasize} bytes written to {slaveIndex}. slave. Remaining data: {datasize} bytes"); } if (currentPackageNumber != packageNumber) { currentPackageNumber = packageNumber; if (packageNumber != 0) { totalPackages++; } } remainingSize = datasize; return(0); }; EcHL.RegisterFOECallback(this.Context, callback); GC.KeepAlive(callback); int wk = EcHL.DownloadFirmware(this.Context, slaveIndex, fileName, (int)fileInfo.Length); _logger.LogInformation($"FoE: {totalPackages} packages written"); success = (remainingSize == 0) && (wk > 0); EcHL.RequestState(this.Context, slaveIndex, (UInt16)SlaveState.Init); } } } return(success); }