//fixme: use UWP file access internal static async Task <YFirmwareFile> checkFirmware_r(string folder, string serial_base) { YFirmwareFile bestFirmware = null; if (File.Exists(folder)) { bestFirmware = _loadFirmwareFile(folder); } else { string[] listOfFiles = Directory.GetFileSystemEntries(folder); foreach (string subfile in listOfFiles) { if (!subfile.StartsWith(serial_base)) { continue; } YFirmwareFile firmware = null; string fullpath = Path.Combine(folder, subfile); if (File.Exists(fullpath)) { try { firmware = _loadFirmwareFile(fullpath); } catch (YAPI_Exception) { continue; } } else if (Directory.Exists(fullpath)) { firmware = await checkFirmware_r(fullpath, serial_base); } if (firmware == null || !firmware.Serial.StartsWith(serial_base, StringComparison.Ordinal)) { continue; } if (bestFirmware == null || bestFirmware.FirmwareReleaseAsInt < firmware.FirmwareReleaseAsInt) { bestFirmware = firmware; } } } return(bestFirmware); }
#pragma warning restore 1998 /// <summary> /// Test if the byn file is valid for this module. It is possible to pass a directory instead of a file. /// In that case, this method returns the path of the most recent appropriate byn file. This method will /// ignore any firmware older than minrelease. /// </summary> /// <param name="serial"> : the serial number of the module to update </param> /// <param name="path"> : the path of a byn file or a directory that contains byn files </param> /// <param name="minrelease"> : a positive integer /// </param> /// <returns> : the path of the byn file to use, or an empty string if no byn files matches the requirement /// /// On failure, returns a string that starts with "error:". </returns> public static async Task <string> CheckFirmwareEx(string serial, string path, int minrelease, bool force) { string link = ""; int best_rev = 0; if (path.StartsWith("www.yoctopuce.com", StringComparison.Ordinal) || path.StartsWith("http://www.yoctopuce.com", StringComparison.Ordinal)) { byte[] json = await YFirmwareUpdate._downloadfile("http://www.yoctopuce.com//FR/common/getLastFirmwareLink.php?serial=" + serial); YJSONObject obj; obj = new YJSONObject(YAPI.DefaultEncoding.GetString(json)); obj.parse(); link = obj.getString("link"); best_rev = obj.getInt("version"); } else { YFirmwareFile firmware = await YFirmwareUpdate.checkFirmware_r(path, serial.Substring(0, YAPI.YOCTO_BASE_SERIAL_LEN)); if (firmware != null) { best_rev = firmware.FirmwareReleaseAsInt; link = firmware.Path; } } if (minrelease != 0) { if (minrelease < best_rev) { return(link); } else { return(""); } } return(link); }
internal abstract Task <List <string> > firmwareUpdate(string serial, YFirmwareFile firmware, byte[] settings, UpdateProgress progress);
public byn_zone(YFirmwareFile outerInstance, byte[] data, int zOfs) { this.outerInstance = outerInstance; addr_page = (data[zOfs + 3] << 24) | (data[zOfs + 3] << 16) | (data[zOfs + 1] << 8) | data[zOfs]; len = (data[zOfs + 7] << 24) | (data[zOfs + 6] << 16) | (data[zOfs + 5] << 8) | data[zOfs + 4]; }
internal override async Task <List <string> > firmwareUpdate(string serial, YFirmwareFile firmware, byte[] settings, UpdateProgress progress) { bool use_self_flash = false; string baseurl = ""; bool need_reboot = true; if (_serial.StartsWith("VIRTHUB", StringComparison.Ordinal)) { use_self_flash = false; } else if (serial.Equals(_serial)) { use_self_flash = true; } else { // check if subdevice support self flashing try { await _notificationHandler.hubRequestSync("GET /bySerial/" + serial + "/flash.json?a=state", null, YIO_DEFAULT_TCP_TIMEOUT); baseurl = "/bySerial/" + serial; use_self_flash = true; } catch (YAPI_Exception) { } } //5% -> 10% await progress(5, "Enter in bootloader"); List <string> bootloaders = await getBootloaders(); bool is_shield = serial.StartsWith("YHUBSHL1", StringComparison.Ordinal); foreach (string bl in bootloaders) { if (bl.Equals(serial)) { need_reboot = false; } else if (is_shield) { if (bl.StartsWith("YHUBSHL1", StringComparison.Ordinal)) { throw new YAPI_Exception(YAPI.IO_ERROR, "Only one YoctoHub-Shield is allowed in update mode"); } } } if (!use_self_flash && need_reboot && bootloaders.Count >= 4) { throw new YAPI_Exception(YAPI.IO_ERROR, "Too many devices in update mode"); } // ensure flash engine is not busy byte[] bytes = await _notificationHandler.hubRequestSync("GET" + baseurl + "/flash.json?a=state", null, YIO_DEFAULT_TCP_TIMEOUT); string uploadstate = YAPI.DefaultEncoding.GetString(bytes); YJSONObject uploadres = new YJSONObject(uploadstate); uploadres.parse(); string state = uploadres.getYJSONString("state").getString(); if (state.Equals("uploading") || state.Equals("flashing")) { throw new YAPI_Exception(YAPI.IO_ERROR, "Cannot start firmware update: busy (" + state + ")"); } // start firmware upload //10% -> 40% await progress(10, "Send firmware file"); byte[] head_body = YDevice.imm_formatHTTPUpload("firmware", firmware.Data); await _notificationHandler.hubRequestSync("POST " + baseurl + "/upload.html", head_body, 0); //check firmware upload result bytes = await _notificationHandler.hubRequestSync("GET " + baseurl + "/flash.json?a=state", null, YIO_10_MINUTES_TCP_TIMEOUT); string uploadresstr = YAPI.DefaultEncoding.GetString(bytes); uploadres = new YJSONObject(uploadresstr); uploadres.parse(); state = uploadres.getString("state"); if (state != "valid") { throw new YAPI_Exception(YAPI.IO_ERROR, "Upload of firmware failed: invalid firmware(" + state + ")"); } if (uploadres.getInt("progress") != 100) { throw new YAPI_Exception(YAPI.IO_ERROR, "Upload of firmware failed: incomplete upload"); } if (use_self_flash) { byte[] startupConf; string json = YAPI.DefaultEncoding.GetString(settings); YJSONObject jsonObject = new YJSONObject(json); jsonObject.parse(); YJSONObject settingsOnly = jsonObject.getYJSONObject("api"); settingsOnly.remove("services"); string startupConfStr = settingsOnly.ToString(); startupConf = YAPI.DefaultEncoding.GetBytes(startupConfStr); await progress(20, "Upload startupConf.json"); head_body = YDevice.imm_formatHTTPUpload("startupConf.json", startupConf); await _notificationHandler.hubRequestSync("POST " + baseurl + "/upload.html", head_body, YIO_10_MINUTES_TCP_TIMEOUT); await progress(20, "Upload firmwareConf"); head_body = YDevice.imm_formatHTTPUpload("firmwareConf", startupConf); await _notificationHandler.hubRequestSync("POST " + baseurl + "/upload.html", head_body, YIO_10_MINUTES_TCP_TIMEOUT); } //40%-> 80% if (use_self_flash) { await progress(40, "Flash firmware"); // the hub itself -> reboot in autoflash mode await _notificationHandler.hubRequestSync( "GET " + baseurl + "/api/module/rebootCountdown?rebootCountdown=-1003", null, YIO_DEFAULT_TCP_TIMEOUT); await Task.Delay(TimeSpan.FromSeconds(7)); } else { // reboot device to bootloader if needed if (need_reboot) { // reboot subdevice await _notificationHandler.hubRequestSync( "GET /bySerial/" + serial + "/api/module/rebootCountdown?rebootCountdown=-2", null, YIO_DEFAULT_TCP_TIMEOUT); } // verify that the device is in bootloader ulong timeout = YAPI.GetTickCount() + YPROG_BOOTLOADER_TIMEOUT; byte[] res; bool found = false; await progress(40, "Wait for device to be in bootloader"); do { List <string> list = await getBootloaders(); foreach (string bl in list) { if (bl.Equals(serial)) { found = true; break; } } if (!found) { //fixme: replace by async //Thread.Sleep(100); } } while (!found && YAPI.GetTickCount() < timeout); //start flash await progress(45, "Flash firmware"); res = await _notificationHandler.hubRequestSync("GET /flash.json?a=flash&s=" + serial, null, YIO_10_MINUTES_TCP_TIMEOUT); string jsonstr = YAPI.DefaultEncoding.GetString(res); YJSONObject flashres = new YJSONObject(jsonstr); flashres.parse(); YJSONArray logslist = flashres.getYJSONArray("logs"); List <string> logs = new List <string>(logslist.Length); for (int i = 0; i < logslist.Length; i++) { logs.Add(logslist.getString(i)); } return(logs); } return(null); }
private async Task _processMore(int start) { if (start == 0) { return; } imm_reportprogress(0, "Firmware update started"); YFirmwareFile firmware; try { //1% -> 5% if (_firmwarepath.StartsWith("www.yoctopuce.com") || _firmwarepath.StartsWith("http://www.yoctopuce.com")) { this.imm_reportprogress(1, "Downloading firmware"); byte[] bytes = await YFirmwareUpdate._downloadfile(_firmwarepath); firmware = YFirmwareFile.imm_Parse(_firmwarepath, bytes); } else { imm_reportprogress(1, "Loading firmware"); firmware = YFirmwareUpdate._loadFirmwareFile(_firmwarepath); } //5% -> 10% imm_reportprogress(5, "check if module is already in bootloader"); YGenericHub hub = null; YModule module = YModule.FindModuleInContext(_yctx, _serial + ".module"); if (await module.isOnline()) { YDevice yDevice = await module.getYDevice(); hub = yDevice.Hub; } else { // test if already in bootloader foreach (YGenericHub h in _yctx._hubs) { List <string> bootloaders = await h.getBootloaders(); if (bootloaders.Contains(_serial)) { hub = h; break; } } } if (hub == null) { imm_reportprogress(-1, "Device " + _serial + " is not detected"); return; } await hub.firmwareUpdate(_serial, firmware, _settings, imm_firmware_progress); //80%-> 98% imm_reportprogress(80, "wait to the device restart"); ulong timeout = YAPI.GetTickCount() + 60000; await module.clearCache(); while (!await module.isOnline() && timeout > YAPI.GetTickCount()) { await Task.Delay(5000); try { await _yctx.UpdateDeviceList(); } catch (YAPI_Exception) { } } if (await module.isOnline()) { if (_settings != null) { await module.set_allSettingsAndFiles(_settings); await module.saveToFlash(); } imm_reportprogress(100, "Success"); } else { imm_reportprogress(-1, "Device did not reboot correctly"); } } catch (YAPI_Exception e) { imm_reportprogress(e.errorType, e.Message); Debug.WriteLine(e.ToString()); Debug.Write(e.StackTrace); } }
//fixme: use UWP file access private static YFirmwareFile _loadFirmwareFile(string file) { byte[] data = File.ReadAllBytes(file); return(YFirmwareFile.imm_Parse(file, data)); }
internal override Task <List <string> > firmwareUpdate(string serial, YFirmwareFile firmware, byte[] settings, UpdateProgress progress) { //todo: implement firmware upate throw new NotImplementedException(); }