//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);
        }
Exemple #3
0
 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();
 }