Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
wisp
GitHub Repository: wisp/impinj-reader-app
Path: blob/master/LLRP/CustomParameter.cs
179 views
/*
 ***************************************************************************
 *  Copyright 2007 Impinj, Inc.
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 ***************************************************************************
 */

/*
***************************************************************************
 * File Name:       CustomParameter.cs
 * 
 * Author:          Impinj
 * Organization:    Impinj
 * Date:            September, 2007
 * 
 * Description:     This file contains interfaces, base classes and parser 
 *                  for custom parameters
***************************************************************************
*/

using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.Reflection;
using System.IO;

using LLRP.DataType;

namespace LLRP
{
    //LLRP Custom Parameters definitions
    public interface ICustom_Parameter : IParameter { }

    /// <summary>
    /// Custom parameter class
    /// </summary>
    public class PARAM_Custom : Parameter, ICustom_Parameter
    {
        protected UInt32 VendorIdentifier;
        protected UInt32 ParameterSubtype;
        protected ByteArray Data;

        private Int16 VendorIdentifier_len = 0;
        private Int16 ParameterSubtype_len = 0;
        private Int16 Data_len;

        public PARAM_Custom()
        {
            typeID = 1023;
        }

        public UInt32 VendorID
        {
            get { return VendorIdentifier; }
        }

        public UInt32 SubType
        {
            get { return ParameterSubtype; }
        }
        
        /// <summary>
        /// Convert to string
        /// </summary>
        /// <returns></returns>
        public override string ToString()
        {
            string xml_str = "<Custom>";
            xml_str += "<VendorIdentifier>" + VendorIdentifier.ToString() + "</VendorIdentifier>";
            xml_str += "<ParameterSubtype>" + ParameterSubtype.ToString() + "</ParameterSubtype>";
            xml_str += "<Data>" + Data.ToHexString() + "</Data>";
            xml_str += "</Custom>";
            return xml_str;
        }

        /// <summary>
        /// Convert and copy to a exist to bit array. updates position indicator
        /// </summary>
        /// <param name="bit_array">bit array to be copied to</param>
        /// <param name="cursor">position to be updated</param>
        public override void ToBitArray(ref bool[] bit_array, ref int cursor)
        {
            int cursor_old = cursor;
            BitArray bArr;

            if (tvCoding)
            {
                bit_array[cursor] = true;
                cursor++;
                bArr = Util.ConvertIntToBitArray(typeID, 7);
                bArr.CopyTo(bit_array, cursor);
                cursor += 7;
            }
            else
            {
                cursor += 6;
                bArr = Util.ConvertIntToBitArray(typeID, 10);
                bArr.CopyTo(bit_array, cursor);
                cursor += 10;
                cursor += 16;
            }

            try
            {
                BitArray tempBitArr = Util.ConvertObjToBitArray(VendorIdentifier, VendorIdentifier_len);
                tempBitArr.CopyTo(bit_array, cursor);
                cursor += tempBitArr.Length;
            }
            catch { }

            try
            {
                BitArray tempBitArr = Util.ConvertObjToBitArray(ParameterSubtype, ParameterSubtype_len);
                tempBitArr.CopyTo(bit_array, cursor);
                cursor += tempBitArr.Length;
            }
            catch { }

            try
            {
                int temp_cursor = cursor;
                BitArray tempBitArr = Util.ConvertIntToBitArray((UInt32)(Data.Count), 16);
                tempBitArr.CopyTo(bit_array, cursor);
                cursor += 16;
                tempBitArr = Util.ConvertObjToBitArray(Data, Data_len);
                tempBitArr.CopyTo(bit_array, cursor);
                cursor += tempBitArr.Length;
            }
            catch { }

            if (!tvCoding)
            {
                UInt32 param_len = (UInt32)(cursor - cursor_old) / 8;
                bArr = Util.ConvertIntToBitArray(param_len, 16);
                bArr.CopyTo(bit_array, cursor_old + 16);
            }
        }

        /// <summary>
        /// Convert from a BitArray
        /// </summary>
        /// <param name="bit_array"></param>
        /// <param name="cursor"></param>
        /// <param name="length"></param>
        /// <returns></returns>
        public new static PARAM_Custom FromBitArray(ref BitArray bit_array, ref int cursor, int length)
        {
            if (cursor >= length) return null;

            int field_len = 0;
            object obj_val;
            ArrayList param_list = new ArrayList();

            PARAM_Custom obj = new PARAM_Custom();

            int param_type = 0;

            if (bit_array[cursor]) obj.tvCoding = true;
            if (obj.tvCoding)
            {
                cursor++;
                param_type = (int)(UInt64)Util.CalculateVal(ref bit_array, ref cursor, 7);

                if (param_type != obj.TypeID)
                {
                    cursor -= 8;
                    return null;
                }
            }
            else
            {
                cursor += 6;
                param_type = (int)(UInt64)Util.CalculateVal(ref bit_array, ref cursor, 10);

                if (param_type != obj.TypeID)
                {
                    cursor -= 16;
                    return null;
                }
                obj.length = (UInt16)(int)Util.DetermineFieldLength(ref bit_array, ref cursor);
            }


            if (cursor > length) throw new Exception("Input data is not complete message");

            field_len = 32;

            Util.ConvertBitArrayToObj(ref bit_array, ref cursor, out obj_val, typeof(UInt32), field_len);
            obj.VendorIdentifier = (UInt32)obj_val;

            if (cursor > length) throw new Exception("Input data is not complete message");

            field_len = 32;

            Util.ConvertBitArrayToObj(ref bit_array, ref cursor, out obj_val, typeof(UInt32), field_len);
            obj.ParameterSubtype = (UInt32)obj_val;

            if (cursor > length) throw new Exception("Input data is not complete message");

            field_len = (bit_array.Length - cursor)/8;

            Util.ConvertBitArrayToObj(ref bit_array, ref cursor, out obj_val, typeof(ByteArray), field_len);
            obj.Data = (ByteArray)obj_val;

            return obj;
        }

        /// <summary>
        /// Convert from a xml node
        /// </summary>
        /// <param name="node"></param>
        /// <returns></returns>
        public static PARAM_Custom FromXmlNode(XmlNode node)
        {
            string val;
            PARAM_Custom param = new PARAM_Custom();


            val = XmlUtil.GetNodeValue(node, "VendorIdentifier");

            param.VendorIdentifier = Convert.ToUInt32(val);

            val = XmlUtil.GetNodeValue(node, "ParameterSubtype");

            param.ParameterSubtype = Convert.ToUInt32(val);

            val = XmlUtil.GetNodeValue(node, "Data");

            param.Data = ByteArray.FromString(val);

            return param;
        }
    }

    /// <summary>
    /// Class for dynamic load vendor extended classes
    /// </summary>
    public class CustomParamDecodeFactory
    {
        public static Hashtable vendorExtensionIDTypeHash;
        public static Hashtable vendorExtensionNameTypeHash;

        /// <summary>
        /// Create vendor extended paramters from BitArray
        /// </summary>
        /// <param name="bit_array"></param>
        /// <param name="cursor"></param>
        /// <param name="length"></param>
        /// <returns></returns>
        public static ICustom_Parameter DecodeCustomParameter(ref BitArray bit_array, ref int cursor, int length)
        {
            if (cursor >= length) return null;

            if (vendorExtensionIDTypeHash == null || vendorExtensionNameTypeHash == null)
            {
                vendorExtensionIDTypeHash = new Hashtable();
                vendorExtensionNameTypeHash = new Hashtable();

                Assembly asm = Assembly.GetCallingAssembly();

                string fullName = asm.ManifestModule.FullyQualifiedName;
                string path = fullName.Substring(0, fullName.LastIndexOf("\\"));

                DirectoryInfo di = new DirectoryInfo(path);//Environment.CurrentDirectory);
                FileInfo[] f_infos = di.GetFiles("LLRP.*.dll");

                foreach (FileInfo fi in f_infos)
                {
                    asm = Assembly.LoadFile(fi.FullName);
                    Type[] types = asm.GetTypes();
                    foreach(Type tp in types)
                    {
                        if (tp.BaseType != typeof(PARAM_Custom)) continue;

                        string type_full_name = tp.Namespace + "." + tp.Name;
                        
                        object obj = asm.CreateInstance(type_full_name);
                        PARAM_Custom temp_param = (PARAM_Custom)obj;
                        string key = temp_param.VendorID + "-" + temp_param.SubType;
                        vendorExtensionIDTypeHash.Add(key, tp);
                        vendorExtensionNameTypeHash.Add(tp.Name, tp);
                    }
                }
            }

            int old_cursor = cursor;
            PARAM_Custom param = PARAM_Custom.FromBitArray(ref bit_array, ref cursor, length);
            if (param != null)
            {
                string key = param.VendorID + "-" + param.SubType;
                if (vendorExtensionIDTypeHash != null)
                {
                    cursor = old_cursor;
                    object[] parameters = new object[] { bit_array, cursor, length };

                    try
                    {
                        Type tp = (Type)vendorExtensionIDTypeHash[key];
                        MethodInfo mis = tp.GetMethod("FromBitArray");

                        if (mis == null) return null;

                        object obj = mis.Invoke(null, parameters);
                        cursor = (int)parameters[1];

                        return (ICustom_Parameter)obj;
                    }
                    catch
                    {
                        return param;
                    }
                }
                else
                    return param;
            }
            else
                return null;
        }

        /// <summary>
        /// Decode a general Xml node to vendor extended parameters.
        /// </summary>
        /// <param name="node"></param>
        /// <returns></returns>
        public static ICustom_Parameter DecodeXmlNodeToCustomParameter(XmlNode node)
        {
            if (vendorExtensionIDTypeHash == null || vendorExtensionNameTypeHash == null)
            {
                vendorExtensionIDTypeHash = new Hashtable();
                vendorExtensionNameTypeHash = new Hashtable();

                DirectoryInfo di = new DirectoryInfo(Environment.CurrentDirectory);
                FileInfo[] f_infos = di.GetFiles("LLRP.*.dll");

                foreach (FileInfo fi in f_infos)
                {
                    Assembly asm = Assembly.LoadFile(fi.FullName);
                    Type[] types = asm.GetTypes();
                    foreach (Type tp in types)
                    {
                        if (tp.BaseType != typeof(PARAM_Custom)) continue;

                        string type_full_name = tp.Namespace + "." + tp.Name;

                        object obj = asm.CreateInstance(type_full_name);
                        PARAM_Custom temp_param = (PARAM_Custom)obj;
                        string key = temp_param.VendorID + "-" + temp_param.SubType;
                        vendorExtensionIDTypeHash.Add(key, tp);
                        vendorExtensionNameTypeHash.Add(tp.Name, tp);
                    }
                }
            }

            ///This part is arbitrary and lack of flexibility
            string[] temp = node.Name.Split(new char[] {':'});
            string typeName = string.Empty;
            if (temp.Length == 2) typeName = temp[1];
            else
                typeName = temp[0];

            //
            string type_name = "PARAM_"+typeName;
            Type custom_tp = (Type)vendorExtensionNameTypeHash[type_name];
            if (custom_tp != null)
            {
                object[] parameters = new object[] { node };
                MethodInfo mis = custom_tp.GetMethod("FromXmlNode");

                if (mis == null) return null;
                object obj = mis.Invoke(null, parameters);

                return (ICustom_Parameter)obj;
            }
            else
                return null;
        }
    }
}