📄 mprreader.cs
字号:
//==========================================================================================
//
// WJ.MPR.Reader.MPRReader
// Copyright (c) 2006, WJ Communications, Inc.
//
//==========================================================================================
using System;
using System.Collections;
using System.Threading;
using System.IO;
using WJ.MPR.WinAPI;
using WJ.MPR.Util;
using WJ.Serial;
namespace WJ.MPR.Reader
{
/// <summary>
/// This is the main class instantiated by Applications.
/// - Manages a single WJ Multi-Protocol Reader.
/// - Provides properties and methods for accessing features of the MPR.
/// - Talks to the MPR via an MPRComm object.
/// - Generates request frame payloads for MPR API commands.
/// - Parses response frame payloads from MPR API commands.
/// - Fires events when MPR public properties change
/// - Manages an Inventory of Tags in the MPRs field of view.
/// - Inventory can consist of Class 0, Class 1 and/or Gen 2 tags.
/// - Periodically polls the MPR for its current Inventory to:
/// 1) add new tags when found
/// 2) expire old tags
/// - Old Tags are expired if they have not been seen for at least "PersistTime"
/// - InventoryUpdateGap is how long to wait between inventory requests to the MPR.
/// - Has methods to enable bootloading new FW to the MPR.
/// - Exposes MPR methods to Read/Program/Erase/Kill/Lock for 3 EPC Tag standards.
/// </summary>
public class MPRReader : IDisposable
{
#region Events
/// <summary>
/// Raised when the communication state changes
/// </summary>
public event EventHandler DisconnectEvent;
/// <summary>
/// Fired when a new tag is added to the MPRReader's inventory.
/// </summary>
public event TagEventHandler TagAdded;
/// <summary>
/// Fired when a tag on the list is read again.
/// </summary>
public event TagEventHandler TagReRead;
/// <summary>
/// Fired when a tag expires, ie hasn't been read for the persist time period.
/// </summary>
public event TagEventHandler TagRemoved;
/// <summary>
/// Fired when the Active Antenna changes.
/// </summary>
public event EventHandler ActiveAntennaChanged;
/// <summary>
/// Fired when the Tx Power changes.
/// </summary>
public event EventHandler TxPowerChanged;
/// <summary>
/// Fired when the Class 0 Singulation Field changes.
/// </summary>
public event EventHandler Class0SingulationFieldChanged;
/// <summary>
/// Fired when the Class 1 Inventory Type changes.
/// </summary>
public event EventHandler Class1InventoryTypeChanged;
/// <summary>
/// Fired when the Tag Length Option changes.
/// </summary>
public event EventHandler TagLengthOptionChanged;
/// <summary>
/// Fired when the Persist Time changes.
/// </summary>
public event EventHandler PersistTimeChanged;
/// <summary>
/// Fired when the Inventory Update Period changes.
/// </summary>
public event EventHandler InvUpdateGapChanged;
/// <summary>
/// Fired when the Inventory Timer Enabled property changes.
/// </summary>
public event EventHandler InvTimerEnabledChanged;
/// <summary>
/// Fired when manufacturing information is read from the MPR.
/// </summary>
public event EventHandler ManufacturingInformationChanged;
/// <summary>
/// Fired when an Inventory Update occurs.
/// </summary>
public event EventHandler InvPollEvent;
/// <summary>
/// Fired when a message is recevied from the bootloader.
/// </summary>
public event StringEventHandler BootloaderBytesReceivedEvent;
/// <summary>
/// Fired when a string message is generated.
/// These messages are generated contain:
/// - Communication log information
/// - Command results
/// - Error Messages
/// </summary>
public event StringEventHandler StatusEvent;
#endregion
#region Constructor
/// <summary>
/// Construct a new MPRReader.
/// </summary>
public MPRReader()
{
try
{
InventoryUpdateTimer = new System.Threading.Timer(
new TimerCallback(InventoryUpdateCallback), null, Timeout.Infinite, Timeout.Infinite);
}
catch(ApplicationException ex)
{
LogIt(ex.Message);
}
}
#endregion
#region Public Functions
/// <summary>
/// Destroys any existing connection,
/// then starts the attempt to connect to an MPR at the requested Serial Port and Baud Rate.
/// </summary>
/// <param name="SerialPortName">"COMx" style serial port name</param>
/// <param name="BaudRate">The Baud Rate at which to connect (usually 57600)</param>
/// <returns>Whether an MPR was found at requested Port and BaudRate</returns>
public bool Connect(string SerialPortName, string BaudRate)
{
this.SerialPortName = SerialPortName;
this.BaudRate = BaudRate;
isConnected = false;
// First destroy the existing comm
if (comm != null)
comm.Dispose();
// Then, make a new one
comm = new MPRComm(SerialPortName, BaudRate);
// Define MPRComm event handlers
comm.IsOpenChanged += new BoolEventHandler(comm_IsOpenChanged);
comm.BLDataArrived += new StringEventHandler(comm_BLDataArrived);
// Open the serial port connection to the MPR.
comm.Open();
// Wait MPR_BOOTUP_TIME msec between powering on (opening COM port) and
// querying the MPR
Thread.Sleep(MPRBootupTime);
// Try to read the Reader Information,
// if successfull, set isConnected to true.
isConnected = comm.IsOpen;
comm.appModeSetup();
if (isConnected)
{
isConnected &= UpdateReaderInfo();
}
return isConnected;
}
/// <summary>
/// Connect using the last (or default) SerialPortName and BaudRate
/// </summary>
/// <returns>Whether an MPR was found at default Port and BaudRate</returns>
public bool Connect() { return Connect(this.SerialPortName, this.BaudRate); }
/// <summary>
/// Destroys any existing connection,
/// then starts the attempt to connect to an MPR at the requested Serial Port and Baud Rate.
/// </summary>
/// <param name="SerialPortName">"COMx" style serial port name</param>
/// <param name="BaudRate">The Baud Rate at which to connect (usually 57600)</param>
/// <returns>Whether an MPR was found at requested Port and BaudRate</returns>
public bool ConnectBL(string SerialPortName, string BaudRate)
{
this.SerialPortName = SerialPortName;
this.BaudRate = BaudRate;
isConnected = false;
// First destroy the existing comm
if (comm != null)
comm.Dispose();
// Then, make a new one
comm = new MPRComm(SerialPortName, BaudRate);
// Define MPRComm event handlers
comm.IsOpenChanged += new BoolEventHandler(comm_IsOpenChanged);
comm.BLDataArrived += new StringEventHandler(comm_BLDataArrived);
// Open the serial port connection to the MPR.
comm.Open();
isConnected = comm.IsOpen;
comm.blModeSetup();
return isConnected;
}
/// <summary>
/// Connect to the MPR's bootloader, using the current serial port,
/// and default (115200) baud rate.
/// </summary>
/// <returns></returns>
public bool ConnectBL() { return ConnectBL(this.SerialPortName, "115200"); }
/// <summary>
/// Disable Inventory Timer and close MPRComm.
/// </summary>
public void Disconnect()
{
InvTimerEnabled = false;
isConnected = false;
if (comm != null)
comm.Close();
}
/// <summary>
/// Close MPRComm, but record that we should reconnect on Resume.
/// </summary>
public void Suspend()
{
ReconnectOnResume = IsConnected;
comm.Close();
}
/// <summary>
/// Re-connect to the MPR if we were supposed to (as recorded in Suspend())
/// </summary>
public void Resume()
{
if (ReconnectOnResume)
Connect();
}
#region Class0 Commands
#region Matrics Class0+
/// <summary>
/// Read bits from a Matrics Class 0+ Tag.
/// </summary>
/// <param name="filter">a TagFilter specifying the tags to read from.</param>
/// <param name="ReadBitCount">How many bits to read.</param>
/// <param name="ReadPage">The page to read from.</param>
/// <param name="TagBits">A bytelist in which to return the bits read.</param>
/// <returns></returns>
public int Class0PlusRead(TagFilter filter, byte ReadBitCount, byte ReadPage, out byteList TagBits)
{
TagBits = new byteList();
// Can read at most 120 bits
if (ReadBitCount > 120) return 0;
byteList Params = new byteList(
new byte[] { ActiveAntenna, TxPower, Class0SingulationField, ReadPage, ReadBitCount } );
Params.Add(filter.Length);
Params.Add(filter.Bits);
MPRMsg aMsg = comm.Send(CmdCode.Class0PlusRead, Params);
if (!ProcMsgStat(aMsg))
return 0;
return Class0PlusReadParse(out TagBits, aMsg.DataBytes, ReadBitCount);
}
/// <summary>
/// Write a Row of data to a Matrics Class 0+ Tag.
/// </summary>
/// <param name="filter">A Filter to match the Tags to write.</param>
/// <param name="programData">The bits to write to the Tags.</param>
/// <param name="IDPage">The IDPage (ID0-ID15) to Write.</param>
/// <param name="StartBit">The bit in the page at which to start writing.</param>
/// <param name="eraseFirst">Whether to Erase the IDPage first.</param>
/// <param name="lockAfter">Whether to Lock the IDPage after writing.</param>
/// <param name="clearTIB">Clear the Traversal Inhibit Bit (ID2 only).</param>
/// <param name="setTIB">Set the Traversal Inhibit Bit (ID2 only).</param>
/// <returns>The Number of Tags written.</returns>
public int Class0PlusWrite(TagFilter filter, TagFilter programData, byte IDPage,
byte StartBit, bool eraseFirst, bool lockAfter, bool clearTIB, bool setTIB)
{
// Can write at most 120 bits
if (programData.Length > 120) return 0;
if (IDPage > 15) return 0;
byteList Params = new byteList(
new byte[] { ActiveAntenna, TxPower, Class0SingulationField } );
byte options = (byte)(IDPage & 0x0F);
if (eraseFirst) options |= 0x10;
if (lockAfter) options |= 0x20;
if (clearTIB) options |= 0x40;
if (setTIB) options |= 0x80;
Params.Add(options);
Params.Add(StartBit);
Params.Add(programData.Length);
Params.Add(programData.Bits);
Params.Add(filter.Length);
Params.Add(filter.Bits);
MPRMsg aMsg = comm.Send(CmdCode.Class0PlusWrite, Params);
if (!ProcMsgStat(aMsg))
return 0;
return ProcessSummary(aMsg.DataBytes.subList(aMsg.DataBytes.Count - 6));
}
/// <summary>
/// Read bits from a Matrics Class 0+ Tag in global mode.
/// </summary>
/// <param name="ReadBitCount">Number of bits to read.</param>
/// <param name="ReadPage">Page to read from.</param>
/// <param name="TagBits">The bits read from the tag.</param>
/// <returns></returns>
public int Class0PlusGlobalRead(byte ReadBitCount, byte ReadPage, out byteList TagBits)
{
TagBits = new byteList();
// Can read at most 120 bits
if (ReadBitCount > 120) return 0;
byteList Params = new byteList(
new byte[] { ActiveAntenna, TxPower, ReadPage, ReadBitCount } );
MPRMsg aMsg = comm.Send(CmdCode.Class0PlusGlobalRead, Params);
if (!ProcMsgStat(aMsg))
return 0;
return Class0PlusReadParse(out TagBits, aMsg.DataBytes, ReadBitCount);
}
/// <summary>
/// Program an EPC into a Matrics Class0+ tag.
/// </summary>
/// <param name="programData"></param>
/// <param name="eraseFirst"></param>
/// <param name="lockAfter"></param>
/// <param name="clearTIB"></param>
/// <param name="setTIB"></param>
/// <returns>0 if error; otherwise # tags programmed.</returns>
public int Class0PlusProgram(TagFilter programData,
bool eraseFirst, bool lockAfter, bool clearTIB, bool setTIB)
{
// Can write at most 120 bits
if (programData.Length > 120) return 0;
// if (IDPage > 15) return 0;
byte options = 0;
if (eraseFirst) options |= 0x10;
if (lockAfter) options |= 0x20;
if (clearTIB) options |= 0x40;
if (setTIB) options |= 0x80;
byteList Params = new byteList(
new byte[] { ActiveAntenna, TxPower, options} );
Params.Add(programData.Length);
Params.Add(programData.Bits);
MPRMsg aMsg = comm.Send(CmdCode.Class0PlusProgram, Params);
if (!ProcMsgStat(aMsg))
return 0;
return ProcessSummary(aMsg.DataBytes.subList(aMsg.DataBytes.Count - 6));
}
/// <summary>
/// Erase a page of a Matrics Class 0+ tag's Internal Tag Memory (ITM).
/// </summary>
/// <param name="filter">A filter to match the tag ID of the tag to Erase.</param>
/// <param name="page">The page (0-15) to erase.</param>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -