Пример #1
0
        // Remove a device from YAPI after an unplug detected by device refresh
        internal virtual void imm_forgetDevice(string serial)
        {
            YDevice dev = _devs[serial];

            if (dev == null)
            {
                return;
            }
            string lname = dev.imm_getLogicalName();

            _devs.Remove(serial);
            if (_snByName.ContainsKey(lname) && _snByName[lname].Equals(serial))
            {
                _snByName.Remove(lname);
            }
            YFunctionType module = _fnByType["Module"];

            module.imm_forgetFunction(serial + ".module");
            int count = dev.imm_functionCount();

            for (int i = 0; i < count; i++)
            {
                YPEntry yp = dev.imm_getYPEntryFromOfs(i);
                if (_fnByType.ContainsKey(yp.Classname))
                {
                    YFunctionType functionType = _fnByType[yp.Classname];
                    functionType.imm_forgetFunction(yp.HardwareId);
                }
            }
        }
Пример #2
0
        // Reindex a device in YAPI after a name change detected by device refresh
        internal virtual void imm_reindexDevice(YDevice dev)
        {
            string serial = dev.imm_getSerialNumber();
            string lname  = dev.imm_getLogicalName();

            _devs[serial] = dev;

            if (!lname.Equals(""))
            {
                _snByName[lname] = serial;
            }

            YFunctionType module        = _fnByType["Module"];
            YPEntry       moduleYPEntry = dev.ModuleYPEntry;

            module.imm_reindexFunction(moduleYPEntry);
            int count = dev.imm_functionCount();

            for (int i = 0; i < count; i++)
            {
                YPEntry       yp        = dev.imm_getYPEntryFromOfs(i);
                string        classname = yp.Classname;
                YFunctionType functionType;
                if (_fnByType.ContainsKey(classname))
                {
                    functionType = _fnByType[classname];
                }
                else
                {
                    functionType         = new YFunctionType(classname, _yctx);
                    _fnByType[classname] = functionType;
                }
                functionType.imm_reindexFunction(yp);
            }
        }
Пример #3
0
 // Find the hardwareId for the first instance of a given function class
 internal virtual string imm_getFirstHardwareId(string className)
 {
     if (!_yctx._BaseType.ContainsKey(className))
     {
         YFunctionType ft = imm_getFnByType(className);
         YPEntry       yp = ft.imm_getFirstYPEntry();
         if (yp == null)
         {
             return(null);
         }
         return(yp.HardwareId);
     }
     else
     {
         // using an abstract baseType
         YPEntry.BaseClass baseType = _yctx._BaseType[className];
         foreach (YFunctionType subClassType in _fnByType.Values)
         {
             YPEntry yp = subClassType.imm_getFirstYPEntry();
             if (yp != null && yp.getBaseClass().Equals(baseType))
             {
                 return(yp.HardwareId);
             }
         }
         return(null);
     }
 }
Пример #4
0
 // Find the exact Hardware Id of the specified function, if currently connected
 // If device is not known as connected, return a clean error
 // This function will not cause any network access
 public virtual string getFriendlyName(YAPIContext ctx)
 {
     if (_classname.Equals("Module"))
     {
         if (_logicalName.Equals(""))
         {
             return(_serial + ".module");
         }
         else
         {
             return(_logicalName + ".module");
         }
     }
     else
     {
         YPEntry moduleYP = ctx._yHash.imm_resolveFunction("Module", _serial);
         string  module   = moduleYP.getFriendlyName(ctx);
         int     pos      = module.IndexOf(".", StringComparison.Ordinal);
         module = module.Substring(0, pos);
         if (_logicalName.Equals(""))
         {
             return(module + "." + _funcId);
         }
         else
         {
             return(module + "." + _logicalName);
         }
     }
 }
        public void imm_handleTimedNotification(YPktStreamHead data)
        {
            uint    pos  = 0;
            YDevice ydev = _yctx._yHash.imm_getDevice(SerialNumber);

            if (ydev == null)
            {
                // device has not been registered;
                return;
            }

            while (pos < data.Len)
            {
                int  funYdx = data.imm_GetByte(pos) & 0xf;
                bool isAvg  = (data.imm_GetByte(pos) & 0x80) != 0;
                uint len    = (uint)(1 + ((data.imm_GetByte(pos) >> 4) & 0x7));
                pos++;
                if (data.Len < pos + len)
                {
                    _yctx._Log("drop invalid timedNotification");
                    return;
                }

                if (funYdx == 0xf)
                {
                    byte[] intData = new byte[len];
                    for (uint i = 0; i < len; i++)
                    {
                        intData[i] = data.imm_GetByte(pos + i);
                    }

                    ydev.imm_setDeviceTime(intData);
                }
                else
                {
                    YPEntry yp = imm_getYPEntryFromYdx(funYdx);
                    if (yp != null)
                    {
                        List <int> report = new List <int>((int)(len + 1));
                        report.Add(isAvg ? 1 : 0);
                        for (uint i = 0; i < len; i++)
                        {
                            int b = data.imm_GetByte(pos + i) & 0xff;
                            report.Add(b);
                        }

                        _hub.imm_handleTimedNotification(yp.Serial, yp.FuncId, ydev.imm_getDeviceTime(), report);
                    }
                }

                pos += len;
            }
        }
Пример #6
0
        // Retrieve a function advertised value by hardware id
        public virtual void imm_setFunctionValue(string hwid, string pubval)
        {
            if (!_ypEntries.ContainsKey(hwid))
            {
                // device has not been correctly registered
                return;
            }
            YPEntry yp = _ypEntries[hwid];

            if (yp.AdvertisedValue.Equals(pubval))
            {
                return;
            }
            yp.AdvertisedValue = pubval;
        }
        public void handleTimedNotificationV2(YPktStreamHead data)
        {
            uint    pos  = 0;
            YDevice ydev = _yctx._yHash.imm_getDevice(SerialNumber);

            if (ydev == null)
            {
                // device has not been registered;
                return;
            }

            while (pos < data.Len)
            {
                int  funYdx   = data.imm_GetByte(pos) & 0xf;
                uint extralen = (uint)((data.imm_GetByte(pos) >> 4) & 0xf);
                uint len      = extralen + 1;
                pos++; // consume generic header
                if (funYdx == 0xf)
                {
                    byte[] intData = new byte[len];
                    for (uint i = 0; i < len; i++)
                    {
                        intData[i] = data.imm_GetByte(pos + i);
                    }

                    ydev.imm_setDeviceTime(intData);
                }
                else
                {
                    YPEntry yp = imm_getYPEntryFromYdx(funYdx);
                    if (yp != null)
                    {
                        List <int> report = new List <int>((int)(len + 1));
                        report.Add(2);
                        for (uint i = 0; i < len; i++)
                        {
                            int b = data.imm_GetByte(pos + i) & 0xff;
                            report.Add(b);
                        }

                        _hub.imm_handleTimedNotification(yp.Serial, yp.FuncId, ydev.imm_getDeviceTime(), report);
                    }
                }

                pos += len;
            }
        }
Пример #8
0
 // Find the hardwareId for the next instance of a given function class
 internal virtual string imm_getNextHardwareId(string className, string hwid)
 {
     if (!_yctx._BaseType.ContainsKey(className))
     {
         YFunctionType ft = imm_getFnByType(className);
         YPEntry       yp = ft.imm_getNextYPEntry(hwid);
         if (yp == null)
         {
             return(null);
         }
         return(yp.HardwareId);
     }
     else
     {
         // enumeration of an abstract class
         YPEntry.BaseClass baseType  = _yctx._BaseType[className];
         string            prevclass = YAPIContext.imm_functionClass(hwid);
         YPEntry           res       = imm_getFnByType(prevclass).imm_getNextYPEntry(hwid);
         if (res != null)
         {
             return(res.HardwareId);
         }
         foreach (string altClassName in _fnByType.Keys)
         {
             if (!prevclass.Equals(""))
             {
                 if (!altClassName.Equals(prevclass))
                 {
                     continue;
                 }
                 prevclass = "";
                 continue;
             }
             YFunctionType functionType = _fnByType[altClassName];
             res = functionType.imm_getFirstYPEntry();
             if (res != null && res.getBaseClass().Equals(baseType))
             {
                 return(res.HardwareId);
             }
         }
         return(null);
     }
 }
Пример #9
0
        // Device constructor. Automatically call the YAPI functin to reindex device
        internal YDevice(YGenericHub hub, WPEntry wpRec, Dictionary <string, List <YPEntry> > ypRecs)
        {
            // private attributes
            _hub                       = hub;
            _wpRec                     = wpRec;
            _cache_expiration          = 0;
            _cache_json                = null;
            _moduleYPEntry             = new YPEntry(wpRec.SerialNumber, "module", YPEntry.BaseClass.Function);
            _moduleYPEntry.LogicalName = wpRec.LogicalName;
            _ypRecs                    = new Dictionary <int?, YPEntry>();
            List <string> keySet = ypRecs.Keys.ToList();

            foreach (string categ in keySet)
            {
                foreach (YPEntry rec in ypRecs[categ])
                {
                    if (rec.Serial.Equals(wpRec.SerialNumber))
                    {
                        int funydx = rec.Index;
                        _ypRecs[funydx] = rec;
                    }
                }
            }
        }
Пример #10
0
        public virtual void imm_reindexFunction(YPEntry yp)
        {
            string oldLogicalName = "";

            string hardwareId = yp.HardwareId;

            if (_ypEntries.ContainsKey(hardwareId))
            {
                oldLogicalName = _ypEntries[hardwareId].LogicalName;
            }

            if (!oldLogicalName.Equals("") && !oldLogicalName.Equals(yp.LogicalName))
            {
                if (_hwIdByName[oldLogicalName].Equals(hardwareId))
                {
                    _hwIdByName.Remove(oldLogicalName);
                }
            }
            if (!yp.LogicalName.Equals(""))
            {
                _hwIdByName[yp.LogicalName] = hardwareId;
            }
            _ypEntries[yp.HardwareId] = yp;
        }
Пример #11
0
 // Find the best known identifier (hardware Id) for a given function
 internal virtual YPEntry imm_resolveFunction(string className, string func)
 {
     if (!_yctx._BaseType.ContainsKey(className))
     {
         return(imm_getFnByType(className).imm_getYPEntry(func));
     }
     else
     {
         // using an abstract baseType
         YPEntry.BaseClass baseType = _yctx._BaseType[className];
         foreach (YFunctionType subClassType in _fnByType.Values)
         {
             try {
                 YPEntry yp = subClassType.imm_getYPEntry(func);
                 if (yp.getBaseClass().Equals(baseType))
                 {
                     return(yp);
                 }
             } catch (YAPI_Exception) {
             }
         }
     }
     throw new YAPI_Exception(YAPI.DEVICE_NOT_FOUND, "No function of type " + className + " found");
 }
Пример #12
0
        // Find the exact Hardware Id of the specified function, if currently connected
        // If device is not known as connected, return a clean error
        // This function will not cause any network access
        public virtual HWID imm_resolve(string func)
        {
            // Try to resolve str_func to a known Function instance, if possible, without any device access
            int dotpos = func.IndexOf('.');

            if (dotpos < 0)
            {
                // First case: func is the logical name of a function
                if (_hwIdByName.ContainsKey(func))
                {
                    string hwid_str = _hwIdByName[func];
                    return(new HWID(hwid_str));
                }

                // fallback to assuming that func is a logical name or serial number of a module
                // with an implicit function name (like serial.module for instance)
                func += string.Format(".{0}{1}", char.ToLower(_className[0]), _className.Substring(1));
            }

            // Second case: func is in the form: device_id.function_id
            HWID hwid = new HWID(func);

            // quick lookup for a known pure hardware id
            if (_ypEntries.ContainsKey(hwid.ToString()))
            {
                return(hwid);
            }

            if (hwid.module.Length > 0)
            {
                // either the device id is a logical name, or the function is unknown
                YDevice dev = _yctx._yHash.imm_getDevice(hwid.module);
                if (dev == null)
                {
                    throw new YAPI_Exception(YAPI.DEVICE_NOT_FOUND, "Device [" + hwid.module + "] not online");
                }
                string serial = dev.imm_getSerialNumber();
                hwid = new HWID(serial, hwid.Function);
                if (_ypEntries.ContainsKey(hwid.ToString()))
                {
                    return(hwid);
                }
                // not found neither, may be funcid is a function logicalname
                int nfun = dev.imm_functionCount();
                for (int i = 0; i < nfun; i++)
                {
                    YPEntry yp = dev.imm_getYPEntryFromOfs(i);
                    if (yp.LogicalName.Equals(hwid.Function) && _ypEntries.ContainsValue(yp))
                    {
                        return(new HWID(serial, yp.FuncId));
                    }
                }
            }
            else
            {
                // only functionId  (ie ".temperature")
                foreach (string hwid_str in _connectedFns.Keys)
                {
                    HWID tmpid = new HWID(hwid_str);
                    if (tmpid.Function.Equals(hwid.Function))
                    {
                        return(tmpid);
                    }
                }
            }
            throw new YAPI_Exception(YAPI.DEVICE_NOT_FOUND, "No function [" + hwid.function + "] found on device [" + hwid.module + "]");
        }
Пример #13
0
        /// <summary>
        /// Returns a global identifier of the function in the format MODULE_NAME&#46;FUNCTION_NAME.
        /// The returned string uses the logical names of the module and of the function if they are defined,
        /// otherwise the serial number of the module and the hardware identifier of the function
        /// (for example: MyCustomName.relay1)
        /// </summary>
        /// <returns> a string that uniquely identifies the function using logical names
        ///         (ex: MyCustomName.relay1)
        /// </returns>
        /// <exception cref="YAPI_Exception"> on error </exception>
        public virtual async Task <string> get_friendlyName()
        {
            YPEntry yp = _yapi._yHash.imm_resolveFunction(_className, _func);

            return(yp.getFriendlyName(_yapi));
        }
Пример #14
0
        private void imm_handleNotifcation(YPktStreamHead ystream)
        {
            string functionId;
            int    firstByte = ystream.imm_GetByte(0);
            bool   isV2      = ystream.StreamType == YGenericHub.YSTREAM_NOTICE_V2;

            if (isV2 || firstByte <= NOTIFY_1STBYTE_MAXTINY || firstByte >= NOTIFY_1STBYTE_MINSMALL)
            {
                int     funcvalType = (firstByte >> NOTIFY_V2_TYPE_OFS) & NOTIFY_V2_TYPE_MASK;
                int     funydx      = firstByte & NOTIFY_V2_FUNYDX_MASK;
                YPEntry ypEntry     = imm_getYPEntryFromYdx(funydx);
                if (ypEntry != null)
                {
                    if (ypEntry.Index == funydx)
                    {
                        if (funcvalType == YGenericHub.NOTIFY_V2_FLUSHGROUP)
                        {
                            // not yet used by devices
                        }
                        else
                        {
                            if ((firstByte & NOTIFY_V2_IS_SMALL_FLAG) != 0)
                            {
                                // added on 2015-02-25, remove code below when confirmed dead code
                                throw new YAPI_Exception(YAPI.IO_ERROR, "Hub Should not fwd notification");
                            }

                            int    len  = (int)ystream.Len;
                            byte[] data = new byte[len];
                            ystream.imm_CopyData(data, 0);
                            string funcval = YGenericHub.imm_decodePubVal(funcvalType, data, 1, len - 1);
                            _hub.imm_handleValueNotification(SerialNumber, ypEntry.FuncId, funcval);
                        }
                    }
                }
            }
            else
            {
                string serial = ystream.imm_GetString(0, YAPI.YOCTO_SERIAL_LEN);
                if (SerialNumber == null)
                {
                    SerialNumber = serial;
                }

                uint p    = YAPI.YOCTO_SERIAL_LEN;
                int  type = ystream.imm_GetByte(p++);
                switch (type)
                {
                case NOTIFY_PKT_NAME:
                    _logicalname = ystream.imm_GetString(p, YAPI.YOCTO_LOGICAL_LEN);
                    _beacon      = ystream.imm_GetByte(p + YAPI.YOCTO_LOGICAL_LEN);
                    break;

                case NOTIFY_PKT_PRODNAME:
                    _product = ystream.imm_GetString(p, YAPI.YOCTO_PRODUCTNAME_LEN);
                    break;

                case NOTIFY_PKT_CHILD:
                    break;

                case NOTIFY_PKT_FIRMWARE:
                    _firmware = ystream.imm_GetString(p, YAPI.YOCTO_FIRMWARE_LEN);
                    p        += YAPI.YOCTO_FIRMWARE_LEN;
                    p        += 2;
                    _deviceid = (ushort)(ystream.imm_GetByte(p) + (ystream.imm_GetByte(p + 1) << 8));
                    break;

                case NOTIFY_PKT_FUNCNAME:
                    functionId = ystream.imm_GetString(p, YAPI.YOCTO_FUNCTION_LEN);
                    p         += YAPI.YOCTO_FUNCTION_LEN;
                    string funcname = ystream.imm_GetString(p, YAPI.YOCTO_LOGICAL_LEN);
                    if (!_usbYP.ContainsKey(functionId))
                    {
                        _usbYP[functionId] = new YPEntry(serial, functionId, YPEntry.BaseClass.Function);
                    }

                    _usbYP[functionId].LogicalName = funcname;
                    break;

                case NOTIFY_PKT_FUNCVAL:
                    functionId = ystream.imm_GetString(p, YAPI.YOCTO_FUNCTION_LEN);
                    p         += YAPI.YOCTO_FUNCTION_LEN;
                    string funcval = ystream.imm_GetString(p, YAPI.YOCTO_PUBVAL_SIZE);
                    _hub.imm_handleValueNotification(serial, functionId, funcval);
                    break;

                case NOTIFY_PKT_STREAMREADY:
                    _devState = DevState.StreamReadyReceived;
                    _wp       = new WPEntry(_logicalname, _product, _deviceid, "", _beacon, SerialNumber);
                    _yctx._Log("Device " + SerialNumber + " ready.\n");
                    _currentTask.SetResult(true);
                    break;

                case NOTIFY_PKT_LOG:
                    //FIXME: handle log notification
                    break;

                case NOTIFY_PKT_FUNCNAMEYDX:
                    functionId = ystream.imm_GetString(p, YAPI.YOCTO_FUNCTION_LEN - 1);
                    p         += YAPI.YOCTO_FUNCTION_LEN - 1;
                    byte funclass = ystream.imm_GetByte(p++);
                    funcname = ystream.imm_GetString(p, YAPI.YOCTO_LOGICAL_LEN);
                    p       += YAPI.YOCTO_LOGICAL_LEN;
                    byte funydx = ystream.imm_GetByte(p);
                    if (!_usbYP.ContainsKey(functionId))
                    {
                        _usbYP[functionId] = new YPEntry(serial, functionId, YPEntry.BaseClass.forByte(funclass));
                    }

                    // update ydx
                    _usbYP[functionId].Index       = funydx;
                    _usbYP[functionId].LogicalName = funcname;
                    break;

                case NOTIFY_PKT_PRODINFO:
                    break;

                default:
                    //fixme: Find why this happening on my dev computer
                    throw new YAPI_Exception(YAPI.IO_ERROR, "Invalid Notification");
                }
            }
        }
Пример #15
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;
        }