public override async Task <List <string> > getBootloaders() { List <string> res = new List <string>(); byte[] raw_data = await _notificationHandler.hubRequestSync("GET /flash.json?a=list", null, YIO_DEFAULT_TCP_TIMEOUT); string jsonstr = YAPI.DefaultEncoding.GetString(raw_data); YJSONObject flashres = new YJSONObject(jsonstr); flashres.parse(); YJSONArray list = flashres.getYJSONArray("list"); for (int i = 0; i < list.Length; i++) { res.Add(list.getString(i)); } return(res); }
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); }