/*
***************************************************************************
* 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;
}
}
}