// Reload a device API (store in cache), and update YAPI function lists accordingly
        // Intended to be called within UpdateDeviceList only
        public virtual async Task <int> refresh()
        {
            YJSONObject loadval = await requestAPI();

            bool reindex = false;

            try {
                // parse module and refresh names if needed
                List <string> keys = loadval.keys();
                foreach (string key in keys)
                {
                    if (key.Equals("module"))
                    {
                        YJSONObject module = loadval.getYJSONObject("module");
                        if (!_wpRec.LogicalName.Equals(module.getString("logicalName")))
                        {
                            _wpRec.LogicalName         = module.getString("logicalName");
                            _moduleYPEntry.LogicalName = _wpRec.LogicalName;
                            reindex = true;
                        }

                        _wpRec.Beacon = module.getInt("beacon");
                    }
                    else if (!key.Equals("services"))
                    {
                        YJSONObject func = loadval.getYJSONObject(key);
                        string      name;
                        if (func.has("logicalName"))
                        {
                            name = func.getString("logicalName");
                        }
                        else
                        {
                            name = _wpRec.LogicalName;
                        }

                        if (func.has("advertisedValue"))
                        {
                            string pubval = func.getString("advertisedValue");
                            _hub._yctx._yHash.imm_setFunctionValue(_wpRec.SerialNumber + "." + key, pubval);
                        }

                        for (int f = 0; f < _ypRecs.Count; f++)
                        {
                            if (_ypRecs[f].FuncId.Equals(key))
                            {
                                if (!_ypRecs[f].LogicalName.Equals(name))
                                {
                                    _ypRecs[f].LogicalName = name;
                                    reindex = true;
                                }

                                break;
                            }
                        }
                    }
                }
            } catch (Exception e) {
                throw new YAPI_Exception(YAPI.IO_ERROR, "Request failed, could not parse API result (" + e.Message + ")");
            }

            if (reindex)
            {
                _hub._yctx._yHash.imm_reindexDevice(this);
            }

            return(YAPI.SUCCESS);
        }
        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;
        }