using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.Runtime.InteropServices;
using System.Threading;
using System.IO;
using System.Net;
using System.Diagnostics;
using System.Xml;
using LLRP;
using ReaderLibrary;
using LLRP.DataType;
namespace ReaderLibrary
{
public class ReaderManager
{
private RFIDReader reader;
private ITagHandler handleTags;
//Create an instance of LLRP client client.
//public LLRPClient client = new LLRPClient();
// Store reader-capable modulation modes
public ReaderMode[] readerModes;
//Configuration
public ReaderConfig readerconfig = new ReaderConfig();
protected InventoryConfig inventoryconfig = new InventoryConfig();
protected ReadCmdSettings readcmdsettings = new ReadCmdSettings();
private GuiModes currentMode;
public enum GuiModes
{
Idle, // reader disconnected.
Ready, // reader is connected.
UserInventory,
AttenuatorTest
}
// Read/Write access settings can be added from ready or userinventory states.
// So just keep as a separate variable.
private bool readConfigured = false;
private IRFIDGUI gui;
public ReaderManager(IRFIDGUI newgui, ITagHandler handleTagNew)
{
gui = newgui;
SetDefaultReaderConfig();
SetDefaultInventoryConfig();
reader = new RFIDReader(this);
handleTags = handleTagNew;
}
// Helper method to connect Reader to MainForm
public void HandleTagReceived(MyTag tag)
{
if (tag == null)
{
// todo - some gui display thing
//AppendToMainTextBox("No Tags Seen");
}
else if (IsInventoryRunning()) // if reader is running
{
handleTags.HandleTagReceived(tag);
}
}
public void AppendToDebugTextBox(string message)
{
gui.AppendToDebugTextBox(message);
}
#region Public Reader Interfaces
public GuiModes getCurrentMode()
{
return currentMode;
}
public void SetMode(GuiModes newMode, string txtIPAddress)
{
// Set current mode = new Mode,
// this will be changed if there is an error.
GuiModes oldMode = currentMode;
if(newMode == GuiModes.AttenuatorTest)
throw new Exception("Can't set mode to AttenuatorTest!");
// Switch performs the action
switch (newMode)
{
case GuiModes.Idle:
if (IsConnected())
{
Disconnect();
}
break;
case GuiModes.Ready:
// If we were disconnected, connect.
if (oldMode == GuiModes.Idle || oldMode == GuiModes.Ready)
{
if (!IsConnected())
{
// CONNECT!
Connect(txtIPAddress);
// if connect fails, an exception will be thrown
// if success, currentMode will be set after this switch statement
}
}
// If we were running, stop various modes:
else if (oldMode == GuiModes.UserInventory)
{
if (IsConnected())
{
StopInventory();
}
}
break;
case GuiModes.UserInventory:
if (!IsConnected())
{
currentMode = GuiModes.Idle;
}
else if (oldMode == GuiModes.Ready)
{
StartInventory();
}
break;
default:
throw new Exception("Can't set mode to unknown state!");
//break;
}
// if no exceptions have interrupted us, we successfully got to the new mode:
currentMode = newMode;
}
/// <summary>
/// Connect to Reader
/// </summary>
public void Connect(string ipAddress)
{
// check for dumb errors.
if (IsConnected())
throw new Exception("Already connected");
if (ipAddress.Length == 0)
throw new Exception("Bad IP");
IPAddress address = null;
// look for url-based addresses
if (ipAddress.ToLower().Contains("speedway"))
{
IPAddress[] addresses;
addresses = Dns.GetHostEntry(ipAddress).AddressList;
if (addresses.Length >= 1)
address = addresses[0];
else
throw new Exception("Hostname not found.");
}
else
{
if (!System.Net.IPAddress.TryParse(ipAddress, out address))
throw new Exception("Bad IP Address");
address = System.Net.IPAddress.Parse(ipAddress);
}
if (address != null)
{
bool connect = reader.connectTo(ipAddress);
if (connect)
{
currentMode = GuiModes.Ready;
readerModes = reader.Get_Reader_Capability();
SetDefaultReaderConfig();
SetDefaultInventoryConfig();
//WriteMessage(status.ToString());
reader.Initialize();
}
else
{
throw new Exception("Bad IP or Reader in use.");
}
}
else
{
// MessageBox.Show("Need IP address to connect to client", "LLRP Test", MessageBoxButtons.OK, MessageBoxIcon.Error);
// txtIPAddress.Focus();
throw new Exception("Need IP address to connect to client");
}
}
/// <summary>
/// disconnect from Reader
/// </summary>
public void Disconnect()
{
// check if doing inventory
if (IsInventoryRunning())
{
StopInventory();
}
// check if doing read
if (IsReadRunning())
{
StopRead();
}
if(IsConnected())
{
reader.CleanSubscriptionClient();
}
currentMode = GuiModes.Idle;
}
public void StartInventory()
{
if (!IsConnected())
{
gui.AppendToDebugTextBox("Can't start inventory: Reader not connected.");
return;
}
//reader.DELETE_ACCESSSPEC(); // clear out any old read commands
reader.Set_Reader_Config(readerconfig); // Sets the client configuration
currentMode = GuiModes.UserInventory;
// Add a ROSpec
reader.Add_RoSpec(inventoryconfig, readerconfig);
reader.Enable_RoSpec();
}
// This guy checks to see if cmd is different than last time before executing.
public void RestartRead(ReadCmdSettings cmd)
{
if (!IsConnected())
{
gui.AppendToDebugTextBox("Can't start read: Reader not connected.");
return;
}
if (IsReadRunning() && !cmd.Equals(readcmdsettings))
{
StopRead();
StartRead(cmd);
}
else if (!IsReadRunning()) // idiot proof
{
StartRead(cmd);
}
}
public void StartRead(ReadCmdSettings cmd)
{
if(IsReadRunning())
{
gui.AppendToDebugTextBox("Read already configured - use ReStart Read");
}
else if(!IsConnected())
{
gui.AppendToDebugTextBox("Can't start read: Reader not connected.");
}
else
{
//AddReadAccessSpec("0D00", "0000000000000000", 1, 0);
reader.AddReadAccessSpec(cmd.tagID, cmd.mask, cmd.wordCount, cmd.wordPtr, readerconfig);
reader.ENABLE_ACCESSSPEC();
readcmdsettings = cmd;
readConfigured = true;
}
/*
Set_Reader_Config(); // Sets the client configuration
readmode = true; // this flag is used for special settings in the Add_RoSpec method
// stop all Specs
Delete_RoSpec();
DELETE_ACCESSSPEC();
// add new roSpec and accessSpec
AddReadAccessSpec("0D00", "0000000000000000", 1, 1);
Add_RoSpec();
// enable new accessSpec and RoSpec
ENABLE_ACCESSSPEC();
Enable_RoSpec();
*/
}
public void StopInventory()
{
if (IsInventoryRunning())
{
reader.Stop_RoSpec();
reader.Delete_RoSpec();
currentMode = GuiModes.Ready;
}
}
public void StopRead()
{
if (IsReadRunning())
{
//Stop_RoSpec();
//Delete_RoSpec();
reader.DELETE_ACCESSSPEC();
readConfigured = false;
}
}
public bool IsInventoryRunning()
{
return (currentMode == GuiModes.UserInventory);
}
public bool IsReadRunning()
{
return readConfigured;
}
public bool IsConnected()
{
return (currentMode != GuiModes.Idle);
}
public ReaderConfig getReaderConfig()
{
return readerconfig;
}
public InventoryConfig getInventoryConfig()
{
return inventoryconfig;
}
public ReaderMode[] GetReaderModulationModes()
{
return readerModes;
}
public ReaderMode FindMode(uint modeIdentifier)
{
for (int i = 0; i < readerModes.Length; i++)
if (readerModes[i].GetModeIdentifier() == modeIdentifier)
return readerModes[i];
return null;
}
#endregion
#region Data Structures
public struct ReaderConfig
{
public ushort attenuation;
public ushort modeIndex;
public ushort tagPopulation;
public ushort tagTransitTime;
public bool[] antennaID;
public ushort readerSensitivity;
public ushort channelIndex;
public ushort hopTableIndex;
public ushort periodicTriggerValue;
}
public struct InventoryConfig
{
public LLRP.ENUM_ROSpecStartTriggerType startTrigger;
public LLRP.ENUM_ROSpecStopTriggerType stopTrigger;
public LLRP.ENUM_AISpecStopTriggerType AITriggerType;
public ushort duration;
public ushort numAttempts;
public ushort numTags;
public LLRP.ENUM_ROReportTriggerType reportTrigger;
public ushort reportN;
public uint AITimeout;
}
public void SetDefaultReaderConfig()
{
readerconfig.attenuation = 0;
readerconfig.modeIndex = 2;
readerconfig.tagPopulation = 1;
readerconfig.tagTransitTime = 0;
readerconfig.antennaID = new bool[] { true, false, false, false };
readerconfig.readerSensitivity = 1;
readerconfig.channelIndex = 0;
readerconfig.hopTableIndex = 1;
readerconfig.periodicTriggerValue = 0;
}
public void setReaderConfig(ReaderConfig config)
{
readerconfig.attenuation = config.attenuation;
readerconfig.modeIndex = config.modeIndex;
readerconfig.tagPopulation = config.tagPopulation;
readerconfig.tagTransitTime = config.tagTransitTime;
readerconfig.antennaID = config.antennaID;
readerconfig.readerSensitivity = config.readerSensitivity;
readerconfig.channelIndex = config.channelIndex;
readerconfig.hopTableIndex = config.hopTableIndex;
readerconfig.periodicTriggerValue = config.periodicTriggerValue;
}
public void SetDefaultInventoryConfig()
{
inventoryconfig.startTrigger = ENUM_ROSpecStartTriggerType.Immediate;
inventoryconfig.stopTrigger = ENUM_ROSpecStopTriggerType.Null;
inventoryconfig.AITriggerType = ENUM_AISpecStopTriggerType.Duration;
inventoryconfig.duration = 100;
inventoryconfig.numAttempts = 1;
inventoryconfig.numTags = 1;
inventoryconfig.reportTrigger = ENUM_ROReportTriggerType.Upon_N_Tags_Or_End_Of_AISpec;
inventoryconfig.reportN = 1;
inventoryconfig.AITimeout = 0;
}
public void setInventoryConfig(InventoryConfig config)
{
inventoryconfig.startTrigger = config.startTrigger;
inventoryconfig.stopTrigger = config.stopTrigger;
inventoryconfig.AITriggerType = config.AITriggerType;
inventoryconfig.duration = config.duration;
inventoryconfig.numAttempts = config.numAttempts;
inventoryconfig.numTags = config.numTags;
inventoryconfig.reportTrigger = config.reportTrigger;
inventoryconfig.reportN = config.reportN;
inventoryconfig.AITimeout = config.AITimeout;
}
public class ReaderMode
{
uint modeIndentifier;
ENUM_C1G2DRValue dr;
ENUM_C1G2MValue m;
uint tagRate;
ENUM_C1G2ForwardLinkModulation linkModulation;
uint pie;
uint minTari;
uint maxTari;
public ReaderMode(PARAM_C1G2UHFRFModeTableEntry mode)
{
modeIndentifier = mode.ModeIdentifier;
dr = mode.DRValue;
m = mode.MValue;
tagRate = mode.BDRValue;
linkModulation = mode.ForwardLinkModulation;
pie = mode.PIEValue;
minTari = mode.MinTariValue;
maxTari = mode.MaxTariValue;
}
public uint GetModeIdentifier()
{
return modeIndentifier;
}
override public string ToString()
{
const int stop1 = 13;
const int stop2 = stop1 + 8;
const int stop3 = stop2 + 15;
// Mode Identifier
string outstr = "[" + modeIndentifier.ToString() + "]";
outstr = PadSpaces(stop1, outstr);
// Miller
switch (m)
{
case ENUM_C1G2MValue.MV_FM0:
outstr += "FM0";
break;
case ENUM_C1G2MValue.MV_2:
outstr += "M2";
break;
case ENUM_C1G2MValue.MV_4:
outstr += "M4";
break;
case ENUM_C1G2MValue.MV_8:
outstr += "M8";
break;
}
outstr = PadSpaces(stop2, outstr);
// Divide Ratio
switch (dr)
{
case ENUM_C1G2DRValue.DRV_8:
outstr += "DR 64/3";
break;
case ENUM_C1G2DRValue.DRV_64_3:
outstr += "DR 8";
break;
}
outstr = PadSpaces(stop3, outstr);
// Tari
outstr += "Tari = " + ((double)(minTari / 1000.0)).ToString() + " us";
return outstr;
}
private string PadSpaces(int desiredTotalLength, string input)
{
for (int i = input.Length; i < desiredTotalLength; i++)
input += " ";
return input;
}
}
public struct ReadCmdSettings
{
public string tagID;
public string mask;
public ushort wordPtr;
public ushort wordCount;
public ReadCmdSettings(string tagID, string mask, ushort wordCount, ushort wordPtr)
{
this.tagID = tagID;
this.mask = mask;
this.wordPtr = wordPtr;
this.wordCount = wordCount;
}
public override bool Equals(object obj)
{
if (obj.GetType().Name != "ReadCmdSettings") return false;
ReadCmdSettings compareTo = (ReadCmdSettings)obj;
if (compareTo.tagID != this.tagID) return false;
if (compareTo.mask != this.mask) return false;
if (compareTo.wordPtr != this.wordPtr) return false;
if (compareTo.wordCount != this.wordCount) return false;
return true;
}
public override int GetHashCode()
{
return base.GetHashCode();
}
}
#endregion
#region Printing and Debugging Methods
private void WriteMessage(string rsp)
{
WriteMessage(rsp, null);
}
public void WriteMessage(string rsp, string source)
{
// Clear textbox
//textBox2.clear();
//gui.AppendToDebugTextBox("\r\n===================================\r\n");
gui.AppendToDebugTextBox(source + "\r\n");
// let user know operation completed
gui.AppendToDebugTextBox(parseXML(rsp));
gui.AppendToDebugTextBox("===================================\r\n");
}
public void WriteString(string info)
{
gui.AppendToDebugTextBox(info);
gui.AppendToDebugTextBox("===================================\r\n");
}
private string parseXML(string msg)
{
// divide XML message into chunks
string str = msg.ToString();
string[] strArr = str.Split(new string[] { "><" }, StringSplitOptions.None);
string message = null;
// parse relevant string
for (int i = 0; i < strArr.Length; i++)
{
if (strArr[i].Contains("</"))
{
string[] temp = strArr[i].Split(new char[] { '>' });
message = message + temp[0] + " = " + (temp[1].Split(new string[] { "</" }, StringSplitOptions.None))[0] + "\r\n";
}
}
return message;
}
#endregion
}
}