예제 #1
0
        protected internal virtual string imm_get_json_path(string json, string path)
        {
            YJSONObject jsonObject = null;

            jsonObject = new YJSONObject(json);
            jsonObject.parse();
            string[] split = path.Split(new char[] { '\\', '|' });
            return(imm_get_json_path_struct(jsonObject, split, 0));
        }
예제 #2
0
        //--- (end of generated code: YWlanRecord definitions)

        internal YWlanRecord(string json_str)
        {
            YJSONObject json = new YJSONObject(json_str);

            json.parse();
            _ssid    = json.getString("ssid");
            _channel = json.getInt("channel");
            _sec     = json.getString("sec");
            _rssi    = json.getInt("rssi");
        }
예제 #3
0
        //--- (end of generated code: YFileRecord definitions)

        public YFileRecord(string json_str)
        {
            YJSONObject json;

            json = new YJSONObject(json_str);
            json.parse();
            _name = json.getString("name");
            _crc  = json.getInt("crc");
            _size = json.getInt("size");
        }
예제 #4
0
        //--- (end of generated code: YSnoopingRecord definitions)

        internal YSnoopingRecord(string json_str)
        {
            YJSONObject json = new YJSONObject(json_str);

            json.parse();
            _tim = json.getInt("t");
            string m = json.getString("m");

            _dir = (m[0] == '<' ? 1 : 0);
            _msg = m.Substring(1);
        }
예제 #5
0
        // YDataSet parser for stream list
        protected internal virtual async Task <int> _parse(string json_str)
        {
            YJSONObject json;
            YJSONArray  jstreams;
            double      streamStartTime;
            double      streamEndTime;

            json = new YJSONObject(json_str);
            json.parse();
            _functionId = json.getString("id");
            _unit       = json.getString("unit");
            if (json.has("calib"))
            {
                _calib    = YAPIContext.imm_decodeFloats(json.getString("calib"));
                _calib[0] = _calib[0] / 1000;
            }
            else
            {
                _calib = YAPIContext.imm_decodeWords(json.getString("cal"));
            }
            _streams  = new List <YDataStream>();
            _preview  = new List <YMeasure>();
            _measures = new List <YMeasure>();
            jstreams  = json.getYJSONArray("streams");
            for (int i = 0; i < jstreams.Length; i++)
            {
                YDataStream stream = _parent.imm_findDataStream(this, jstreams.getString(i));
                // the timestamp in the data streams is the end of the measure, so the actual
                // measurement start time is computed as one interval before the first timestamp
                streamStartTime = await stream.get_realStartTimeUTC() * 1000;

                streamEndTime = streamStartTime + await stream.get_realDuration() * 1000;

                if (_startTimeMs > 0 && streamEndTime <= _startTimeMs)
                {
                    // this stream is too early, drop it
                }
                else if (_endTimeMs > 0 && streamStartTime >= _endTimeMs)
                {
                    // this stream is too late, drop it
                }
                else
                {
                    _streams.Add(stream);
                }
            }
            _progress = 0;
            return(await this.get_progress());
        }
예제 #6
0
        protected internal virtual string imm_json_get_key(byte[] json, string key)
        {
            YJSONObject obj = new YJSONObject(YAPI.DefaultEncoding.GetString(json));

            obj.parse();
            if (obj.has(key))
            {
                string val = obj.getString(key);
                if (val == null)
                {
                    val = obj.ToString();
                }
                return(val);
            }
            throw new YAPI_Exception(YAPI.INVALID_ARGUMENT, "No key " + key + "in JSON struct");
        }
예제 #7
0
        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);
        }
예제 #8
0
        // Load and parse the REST API for a function given by class name and
        // identifier, possibly applying changes
        // Device cache will be preloaded when loading function "module" and
        // leveraged for other modules
        internal virtual async Task <YJSONObject> _devRequest(string extra)
        {
            YDevice dev = await getYDevice();

            _hwId = _yapi._yHash.imm_resolveHwID(_className, _func);
            string[] split = _hwId.Split(new char[] { '\\', '.' });
            _funId  = split[1];
            _serial = split[0];
            YJSONObject loadval = null;

            if (extra.Equals(""))
            {
                // use a cached API string, without reloading unless module is
                // requested
                YJSONObject jsonval = await dev.requestAPI();

                loadval = jsonval.getYJSONObject(_funId);
            }
            else
            {
                dev.imm_clearCache();
            }
            if (loadval == null)
            {
                // request specified function only to minimize traffic
                if (extra.Equals(""))
                {
                    string httpreq = "GET /api/" + _funId + ".json";
                    string yreq    = await dev.requestHTTPSyncAsString(httpreq, null);

                    loadval = new YJSONObject(yreq);
                    loadval.parse();
                }
                else
                {
                    string httpreq = "GET /api/" + _funId + extra;
                    await dev.requestHTTPAsync(httpreq, null, null, null);

                    return(null);
                }
            }
            return(loadval);
        }
#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);
        }
        public override int parse()
        {
            string current_name = "";
            int    name_start   = _data_start;
            int    cur_pos      = SkipGarbage(_data, _data_start, _data_boundary);

            if (_data.Length <= cur_pos || _data[cur_pos] != '{')
            {
                throw new System.Exception(FormatError("Opening braces was expected", cur_pos));
            }
            cur_pos++;
            Tjstate state = Tjstate.JWAITFORNAME;


            while (cur_pos < _data_boundary)
            {
                char sti = _data[cur_pos];
                switch (state)
                {
                case Tjstate.JWAITFORNAME:
                    if (sti == '"')
                    {
                        state      = Tjstate.JWAITFORENDOFNAME;
                        name_start = cur_pos + 1;
                    }
                    else if (sti == '}')
                    {
                        _data_len = cur_pos + 1 - _data_start;
                        return(_data_len);
                    }
                    else
                    {
                        if (sti != ' ' && sti != '\n' && sti != '\r')
                        {
                            throw new System.Exception(FormatError("invalid char: was expecting \"", cur_pos));
                        }
                    }
                    break;

                case Tjstate.JWAITFORENDOFNAME:
                    if (sti == '"')
                    {
                        current_name = _data.Substring(name_start, cur_pos - name_start);
                        state        = Tjstate.JWAITFORCOLON;
                    }
                    else
                    {
                        if (sti < 32)
                        {
                            throw new System.Exception(FormatError("invalid char: was expecting an identifier compliant char", cur_pos));
                        }
                    }
                    break;

                case Tjstate.JWAITFORCOLON:
                    if (sti == ':')
                    {
                        state = Tjstate.JWAITFORDATA;
                    }
                    else
                    {
                        if (sti != ' ' && sti != '\n' && sti != '\r')
                        {
                            throw new System.Exception(
                                      FormatError("invalid char: was expecting \"", cur_pos));
                        }
                    }
                    break;

                case Tjstate.JWAITFORDATA:
                    if (sti == '{')
                    {
                        YJSONObject jobj = new YJSONObject(_data, cur_pos, _data_boundary);
                        int         len  = jobj.parse();
                        cur_pos += len;
                        parsed.Add(current_name, jobj);
                        _keys.Add(current_name);
                        state = Tjstate.JWAITFORNEXTSTRUCTMEMBER;
                        //cur_pos is already incremented
                        continue;
                    }
                    else if (sti == '[')
                    {
                        YJSONArray jobj = new YJSONArray(_data, cur_pos, _data_boundary);
                        int        len  = jobj.parse();
                        cur_pos += len;
                        parsed.Add(current_name, jobj);
                        _keys.Add(current_name);
                        state = Tjstate.JWAITFORNEXTSTRUCTMEMBER;
                        //cur_pos is already incremented
                        continue;
                    }
                    else if (sti == '"')
                    {
                        YJSONString jobj = new YJSONString(_data, cur_pos, _data_boundary);
                        int         len  = jobj.parse();
                        cur_pos += len;
                        parsed.Add(current_name, jobj);
                        _keys.Add(current_name);
                        state = Tjstate.JWAITFORNEXTSTRUCTMEMBER;
                        //cur_pos is already incremented
                        continue;
                    }
                    else if (sti == '-' || (sti >= '0' && sti <= '9'))
                    {
                        YJSONNumber jobj = new YJSONNumber(_data, cur_pos, _data_boundary);
                        int         len  = jobj.parse();
                        cur_pos += len;
                        parsed.Add(current_name, jobj);
                        _keys.Add(current_name);
                        state = Tjstate.JWAITFORNEXTSTRUCTMEMBER;
                        //cur_pos is already incremented
                        continue;
                    }
                    else if (sti != ' ' && sti != '\n' && sti != '\r')
                    {
                        throw new System.Exception(FormatError("invalid char: was expecting  \",0..9,t or f", cur_pos));
                    }
                    break;

                case Tjstate.JWAITFORNEXTSTRUCTMEMBER:
                    if (sti == ',')
                    {
                        state      = Tjstate.JWAITFORNAME;
                        name_start = cur_pos + 1;
                    }
                    else if (sti == '}')
                    {
                        _data_len = cur_pos + 1 - _data_start;
                        return(_data_len);
                    }
                    else
                    {
                        if (sti != ' ' && sti != '\n' && sti != '\r')
                        {
                            throw new System.Exception(FormatError("invalid char: was expecting ,", cur_pos));
                        }
                    }
                    break;

                case Tjstate.JWAITFORNEXTARRAYITEM:
                case Tjstate.JWAITFORSTRINGVALUE:
                case Tjstate.JWAITFORINTVALUE:
                case Tjstate.JWAITFORBOOLVALUE:
                    throw new System.Exception(FormatError("invalid state for YJSONObject", cur_pos));
                }
                cur_pos++;
            }
            throw new System.Exception(FormatError("unexpected end of data", cur_pos));
        }
        public override int parse()
        {
            int cur_pos = SkipGarbage(_data, _data_start, _data_boundary);

            if (_data[cur_pos] != '[')
            {
                throw new System.Exception(FormatError("Opening braces was expected", cur_pos));
            }
            cur_pos++;
            Tjstate state = Tjstate.JWAITFORDATA;

            while (cur_pos < _data_boundary)
            {
                char sti = _data[cur_pos];
                switch (state)
                {
                case Tjstate.JWAITFORDATA:
                    if (sti == '{')
                    {
                        YJSONObject jobj = new YJSONObject(_data, cur_pos, _data_boundary);
                        int         len  = jobj.parse();
                        cur_pos += len;
                        _arrayValue.Add(jobj);
                        state = Tjstate.JWAITFORNEXTARRAYITEM;
                        //cur_pos is already incremented
                        continue;
                    }
                    else if (sti == '[')
                    {
                        YJSONArray jobj = new YJSONArray(_data, cur_pos, _data_boundary);
                        int        len  = jobj.parse();
                        cur_pos += len;
                        _arrayValue.Add(jobj);
                        state = Tjstate.JWAITFORNEXTARRAYITEM;
                        //cur_pos is already incremented
                        continue;
                    }
                    else if (sti == '"')
                    {
                        YJSONString jobj = new YJSONString(_data, cur_pos, _data_boundary);
                        int         len  = jobj.parse();
                        cur_pos += len;
                        _arrayValue.Add(jobj);
                        state = Tjstate.JWAITFORNEXTARRAYITEM;
                        //cur_pos is already incremented
                        continue;
                    }
                    else if (sti == '-' || (sti >= '0' && sti <= '9'))
                    {
                        YJSONNumber jobj = new YJSONNumber(_data, cur_pos, _data_boundary);
                        int         len  = jobj.parse();
                        cur_pos += len;
                        _arrayValue.Add(jobj);
                        state = Tjstate.JWAITFORNEXTARRAYITEM;
                        //cur_pos is already incremented
                        continue;
                    }
                    else if (sti == ']')
                    {
                        _data_len = cur_pos + 1 - _data_start;
                        return(_data_len);
                    }
                    else if (sti != ' ' && sti != '\n' && sti != '\r')
                    {
                        throw new System.Exception(FormatError("invalid char: was expecting  \",0..9,t or f", cur_pos));
                    }
                    break;

                case Tjstate.JWAITFORNEXTARRAYITEM:
                    if (sti == ',')
                    {
                        state = Tjstate.JWAITFORDATA;
                    }
                    else if (sti == ']')
                    {
                        _data_len = cur_pos + 1 - _data_start;
                        return(_data_len);
                    }
                    else
                    {
                        if (sti != ' ' && sti != '\n' && sti != '\r')
                        {
                            throw new System.Exception(FormatError("invalid char: was expecting ,", cur_pos));
                        }
                    }
                    break;

                default:
                    throw new System.Exception(FormatError("invalid state for YJSONObject", cur_pos));
                }
                cur_pos++;
            }
            throw new System.Exception(FormatError("unexpected end of data", cur_pos));
        }
예제 #12
0
        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);
        }
예제 #13
0
        internal override async Task updateDeviceListAsync(bool forceupdate)
        {
            ulong now = YAPI.GetTickCount();

            if (forceupdate)
            {
                _devListExpires = 0;
            }
            if (_devListExpires > now)
            {
                return;
            }
            if (!_notificationHandler.Connected)
            {
                if (_reportConnnectionLost)
                {
                    throw new YAPI_Exception(YAPI.TIMEOUT, "hub " + _http_params.Url + " is not reachable");
                }
                else
                {
                    return;
                }
            }

            string json_data;

            try {
                byte[] data = await _notificationHandler.hubRequestSync("GET /api.json", null,
                                                                        YIO_DEFAULT_TCP_TIMEOUT);

                json_data = YAPI.DefaultEncoding.GetString(data);
            } catch (YAPI_Exception) {
                if (_reportConnnectionLost)
                {
                    throw;
                }
                return;
            }

            Dictionary <string, List <YPEntry> > yellowPages = new Dictionary <string, List <YPEntry> >();
            List <WPEntry> whitePages = new List <WPEntry>();

            YJSONObject loadval = new YJSONObject(json_data);

            loadval.parse();
            if (!loadval.has("services") || !loadval.getYJSONObject("services").has("whitePages"))
            {
                throw new YAPI_Exception(YAPI.INVALID_ARGUMENT, "Device " + _http_params.Host + " is not a hub");
            }
            _serial = loadval.getYJSONObject("module").getString("serialNumber");
            YJSONArray  whitePages_json  = loadval.getYJSONObject("services").getYJSONArray("whitePages");
            YJSONObject yellowPages_json = loadval.getYJSONObject("services").getYJSONObject("yellowPages");

            if (loadval.has("network"))
            {
                string adminpass = loadval.getYJSONObject("network").getString("adminPassword");
                _writeProtected = adminpass.Length > 0;
            }
            // Reindex all functions from yellow pages
            //HashMap<String, Boolean> refresh = new HashMap<String, Boolean>();
            List <string> keys = yellowPages_json.keys();

            foreach (string classname in keys)
            {
                YJSONArray     yprecs_json = yellowPages_json.getYJSONArray(classname);
                List <YPEntry> yprecs_arr  = new List <YPEntry>(yprecs_json.Length);
                for (int i = 0; i < yprecs_json.Length; i++)
                {
                    YPEntry yprec = new YPEntry(yprecs_json.getYJSONObject(i));
                    yprecs_arr.Add(yprec);
                }
                yellowPages[classname] = yprecs_arr;
            }

            _serialByYdx.Clear();
            // Reindex all devices from white pages
            for (int i = 0; i < whitePages_json.Length; i++)
            {
                YJSONObject jsonObject = whitePages_json.getYJSONObject(i);
                WPEntry     devinfo    = new WPEntry(jsonObject);
                int         index      = jsonObject.getInt("index");
                _serialByYdx[index] = devinfo.SerialNumber;
                whitePages.Add(devinfo);
            }
            await updateFromWpAndYp(whitePages, yellowPages);

            // reset device list cache timeout for this hub
            now             = YAPI.GetTickCount();
            _devListExpires = now + _devListValidity;
        }
예제 #14
0
        // YDataSet parser for stream list
        protected internal virtual async Task <int> _parse(string json_str)
        {
            YJSONObject json;
            YJSONArray  jstreams;
            double      summaryMinVal    = double.MaxValue;
            double      summaryMaxVal    = double.Epsilon;
            double      summaryTotalTime = 0;
            double      summaryTotalAvg  = 0;
            long        streamStartTime;
            long        streamEndTime;
            long        startTime = 0x7fffffff;
            long        endTime   = 0;

            json = new YJSONObject(json_str);
            json.parse();
            _functionId = json.getString("id");
            _unit       = json.getString("unit");
            if (json.has("calib"))
            {
                _calib    = YAPIContext.imm_decodeFloats(json.getString("calib"));
                _calib[0] = _calib[0] / 1000;
            }
            else
            {
                _calib = YAPIContext.imm_decodeWords(json.getString("cal"));
            }
            _streams  = new List <YDataStream>();
            _preview  = new List <YMeasure>();
            _measures = new List <YMeasure>();
            jstreams  = json.getYJSONArray("streams");
            for (int i = 0; i < jstreams.Length; i++)
            {
                YDataStream stream = _parent.imm_findDataStream(this, jstreams.getString(i));
                streamStartTime = await stream.get_startTimeUTC() - await stream.get_dataSamplesIntervalMs() / 1000;

                streamEndTime = await stream.get_startTimeUTC() + await stream.get_duration();

                if (_startTime > 0 && streamEndTime <= _startTime)
                {
                    // this stream is too early, drop it
                }
                else if (_endTime > 0 && await stream.get_startTimeUTC() > _endTime)
                {
                    // this stream is too late, drop it
                }
                else
                {
                    _streams.Add(stream);
                    if (startTime > streamStartTime)
                    {
                        startTime = streamStartTime;
                    }
                    if (endTime < streamEndTime)
                    {
                        endTime = streamEndTime;
                    }

                    if (await stream.isClosed() && await stream.get_startTimeUTC() >= _startTime && (_endTime == 0 || streamEndTime <= _endTime))
                    {
                        if (summaryMinVal > await stream.get_minValue())
                        {
                            summaryMinVal = await stream.get_minValue();
                        }
                        if (summaryMaxVal < await stream.get_maxValue())
                        {
                            summaryMaxVal = await stream.get_maxValue();
                        }
                        summaryTotalAvg += await stream.get_averageValue() * await stream.get_duration();

                        summaryTotalTime += await stream.get_duration();

                        YMeasure rec = new YMeasure(await stream.get_startTimeUTC(), streamEndTime, await stream.get_minValue(), await stream.get_averageValue(), await stream.get_maxValue());
                        _preview.Add(rec);
                    }
                }
            }
            if ((_streams.Count > 0) && (summaryTotalTime > 0))
            {
                // update time boundaries with actual data
                if (_startTime < startTime)
                {
                    _startTime = startTime;
                }
                if (_endTime == 0 || _endTime > endTime)
                {
                    _endTime = endTime;
                }
                _summary = new YMeasure(_startTime, _endTime, summaryMinVal, summaryTotalAvg / summaryTotalTime, summaryMaxVal);
            }
            _progress = 0;
            return(await this.get_progress());
        }