Files
tbf/NfcC7_DLL/NfcHanler/MeterTestHatLink.cs
T

573 lines
23 KiB
C#

using System;
using System.Linq;
using System.IO.Ports;
using System.Threading;
using System.Collections.Generic;
using Sensus;
using Sensus.Protocols.FlexNet;
using Sensus.CommunicationDevices;
using Sensus.Protocols.FlexNet.Serial;
using Sensus.Protocols.FlexNet.Serial.FNv2;
using Sensus.Protocols.FlexNet.FNv2;
using Serial = Sensus.Protocols.FlexNet.Serial;
using Sensus.Protocols;
using Sensus.Protocols.FlexNet.FNv2.NA2WParameters;
using System.ComponentModel;
using Sensus.Protocols.FlexNet.Transactions;
using Sensus.Protocols.SensusRF;
using System.Windows.Markup;
using NA2WNFC;
using NfcC7_DLL.NfcHanler;
using NfcC7_DLL.NfcHanler.Protocols;
using NfcC7_DLL.NfcHanler.Utils;
using Log = NfcC7_DLL.NfcHanler.Utils.Log;
namespace GlobalIPerlUtility
{
class MeterTestHatLink : ISerialConnection, IDisposable
{
private SerialManager serialManager = null;
private UInt16 sessionId = 0;
public MeterTestHatLink(string comPortString)
{
serialManager = new SerialManager(comPortString);
}
public bool IsConnected { get { return (serialManager != null ? serialManager.FactoryUart.IsConnected : false); } }
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
public void Dispose(bool isDisposing)
{
if (isDisposing)
{
// eventThread.Abort();
}
}
private BackgroundWorker openBackgroundWorker;
private void OpenDoWork(object sender, DoWorkEventArgs e)
{
bool isOpen = false;
// windowViewModel.IsBusy = true;
Log.Write("Opening connection on " + serialManager.ComPortString + "." + System.Environment.NewLine);
try
{
serialManager.Open();
if (serialManager.FactoryUart.IsConnected)
{
serialManager.FactoryUart.MessageReceived += MessageReceived;
CommDeviceSessionOpen commDeviceSessionOpen = new CommDeviceSessionOpen();
commDeviceSessionOpen.HostParsed = "GlobalIPerlUtility";
NA2WSerialFrame response = SendNa2wSerialToHat(commDeviceSessionOpen, true);
isOpen = (response != null);
if (response == null)
{
serialManager.Close();
serialManager = null;
Log.Write("MTH session open failed. Is device MTH?" + System.Environment.NewLine);
}
else
{
String version = "Unknown version ";
NetworkResponse networkResponse = (NetworkResponse)response.Payload;
if (networkResponse.Payload is Sensus.Protocols.FlexNet.FNv2.CommDeviceSessionBegin)
{
var sessionBegin = (Sensus.Protocols.FlexNet.FNv2.CommDeviceSessionBegin)networkResponse.Payload;
version = String.Format("{0}{1}.{2}.{3}", (sessionBegin.ProductVersionBeta ? "B" : "R"), sessionBegin.ProductVersionMajor, sessionBegin.ProductVersionMinor, sessionBegin.ProductVersionPatch);
sessionId = sessionBegin.SessionID;
}
else if (networkResponse.Payload is Sensus.Protocols.FlexNet.FNv2.CommDeviceSessionBeginV1)
{
var sessionBegin = (Sensus.Protocols.FlexNet.FNv2.CommDeviceSessionBeginV1)networkResponse.Payload;
version = String.Format("{0}{1}.{2}.{3}", (sessionBegin.ProductVersionBeta ? "B" : "R"), sessionBegin.ProductVersionMajor, sessionBegin.ProductVersionMinor, sessionBegin.ProductVersionPatch);
sessionId = sessionBegin.SessionID;
}
Log.Write("MTH session opened: " + version + " supporting NFC" + "." + System.Environment.NewLine);
}
}
else
{
Log.Write("Serial port open failed. Check device." + System.Environment.NewLine);
}
}
catch (Exception ex)
{
isOpen = false;
serialManager = null;
Log.Write("Serial port open failed (" + ex.ToString() + ")." + System.Environment.NewLine);
}
e.Result = isOpen;
if (isOpen)
{
serialManager.FactoryUart.MessageReceived += SerialMessageReceived;
}
if (isOpen)
{
NfcCommand("Inventory");
// windowViewModel.IsBusy = false;
}
}
public void NfcCommand(String type)
{
if (type.Equals("Inventory"))
{
NfcCommand_InventoryRead nfcCommand = new NfcCommand_InventoryRead();
SendNa2wSerialToHat(nfcCommand, false);
}
else if (type.Equals("NDEF Read"))
{
NfcCommand_NdefRead nfcCommand = new NfcCommand_NdefRead();
SendNa2wSerialToHat(nfcCommand, false);
}
}
private void OpenRunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
// windowViewModel.IsOpen = (bool)e.Result;
}
public void Open()
{
// openBackgroundWorker = new BackgroundWorker();
// openBackgroundWorker.DoWork += new DoWorkEventHandler(OpenDoWork);
// openBackgroundWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(OpenRunWorkerCompleted);
// openBackgroundWorker.RunWorkerAsync();
OpenDoWork(this, new DoWorkEventArgs(this));
}
public void Close()
{
CommDeviceSessionClose commDeviceSessionClose = new CommDeviceSessionClose();
commDeviceSessionClose.SessionID = sessionId;
SendNa2wSerialToHat(commDeviceSessionClose, false);
serialManager.Close();
serialManager = null;
Log.Write("MTH session closed." + System.Environment.NewLine);
}
public event EventHandler<ReceptionEventArgs<ISerialMessageFrame>> MessageReceived;
public event EventHandler<EventArgs> Disconnected;
public ClassicSerialMessageFrame SendFlexNetSerial(ISerialCommandFrame cmd, bool responseExpected, UInt32 timeoutMs)
{
return null;
}
private byte transactionId = 0;
public NA2WSerialFrame SendNa2wSerialToHat(ISerialCommand cmd, bool responseExpected)
{
NA2WSerialFrame cmdFrame = new NA2WSerialFrame(cmd);
INetworkLayer networkLayer = cmdFrame.Unwrap<INetworkLayer>();
networkLayer.PWNs.Set(new TransactionPWN() { TransactionID = transactionId++ });
cmdFrame.Bake();
// LogOutgoing(cmdFrame);
return serialManager.SendNa2wSerial(cmdFrame, responseExpected);
}
// State to track expected response when routing through NFC
private bool lookingForCommandCode = false;
private byte expectedResponseCommandCode = 0;
private NA2WSerialFrame foundResponse = null;
private AutoResetEvent autoResetEvent = null;
public NA2WSerialFrame SendNa2wSerialToNfc(ISerialCommandFrame cmdFrame, bool responseExpected, UInt32 timeoutMs)
{
// Harden command frame
cmdFrame.Bake();
// Place serial frame in Serial Transmit command
SerialTransmitCommandV1 serialTransmitCommandV1 = new SerialTransmitCommandV1();
serialTransmitCommandV1.Payload = new Frame(cmdFrame.ToBytes());
serialTransmitCommandV1.PortId = 0x02; // NFC port
serialTransmitCommandV1.Bake();
// Place Serial Transmit command in serial frame. Set transaction id
NA2WSerialFrame serialTransmitCmdFrame = new NA2WSerialFrame(serialTransmitCommandV1);
INetworkLayer networkLayer = serialTransmitCmdFrame.Unwrap<INetworkLayer>();
networkLayer.PWNs.Set(new TransactionPWN() { TransactionID = transactionId++ });
serialTransmitCmdFrame.Bake();
// Setup response tracking which is done in SerialMessageReceived
NA2WSerialFrame responseFrame = null;
if (responseExpected)
{
lookingForCommandCode = false;
autoResetEvent = new AutoResetEvent(false);
}
// Serial Transmit command should have response (Command Ack) which is thrown away. Caller
// doesn't care about messaging to hat.
serialManager.SendNa2wSerial(serialTransmitCmdFrame, CommandAckResponse._Code);
// Wait for response
if (null != autoResetEvent)
{
// Utility.Log.Write("Waiting" + System.Environment.NewLine);
if (autoResetEvent.WaitOne(TimeSpan.FromMilliseconds(timeoutMs)))
{
// Utility.Log.Write("Event" + System.Environment.NewLine);
responseFrame = foundResponse;
}
autoResetEvent = null;
foundResponse = null;
}
return responseFrame;
}
public NA2WSerialFrame SendNa2wSerialToNfc(ISerialCommandFrame cmdFrame, bool responseExpected)
{
return SendNa2wSerialToNfc(cmdFrame, responseExpected, 8000);
}
public NA2WSerialFrame SendNa2wSerialToNfc(ISerialCommand cmd, bool responseExpected)
{
// Make serial frame from command
NA2WSerialFrame cmdFrame = new NA2WSerialFrame(cmd);
return SendNa2wSerialToNfc(cmdFrame, responseExpected);
}
public NA2WSerialFrame SendNa2wSerial(ISerialCommand cmd, bool responseExpected)
{
// Route command through Hat's NFC
return SendNa2wSerialToNfc(cmd, responseExpected);
}
public NA2WSerialFrame SendNa2wSerial(ISerialCommandFrame cmdFrame, bool responseExpected)
{
// Route command through Hat's NFC
return SendNa2wSerialToNfc(cmdFrame, responseExpected);
}
public NA2WSerialFrame SendNa2wSerialToNfc(ISerialCommandFrame cmdFrame, byte responseCommandCode)
{
// Harden command frame
cmdFrame.Bake();
// Place serial frame in Serial Transmit command
SerialTransmitCommandV1 serialTransmitCommandV1 = new SerialTransmitCommandV1();
serialTransmitCommandV1.Payload = new Frame(cmdFrame.ToBytes());
serialTransmitCommandV1.PortId = 0x02; // NFC port
serialTransmitCommandV1.Bake();
// Place Serial Transmit command in serial frame. Set transaction id
NA2WSerialFrame serialTransmitCmdFrame = new NA2WSerialFrame(serialTransmitCommandV1);
INetworkLayer networkLayer = serialTransmitCmdFrame.Unwrap<INetworkLayer>();
networkLayer.PWNs.Set(new TransactionPWN() { TransactionID = transactionId++ });
serialTransmitCommandV1.Bake();
return serialManager.SendNa2wSerial(serialTransmitCmdFrame, responseCommandCode);
}
public NA2WSerialFrame SendNa2wSerialToNfc(ISerialCommand cmd, byte responseCommandCode)
{
// Make serial frame from command
NA2WSerialFrame cmdFrame = new NA2WSerialFrame(cmd);
return SendNa2wSerialToNfc(cmdFrame, responseCommandCode);
}
public NA2WSerialFrame SendNa2wSerial(ISerialCommand cmd, byte responseCommandCode)
{
// Route command through Hat's NFC
return SendNa2wSerialToNfc(cmd, responseCommandCode);
}
public NA2WSerialFrame SendNa2wSerial(ISerialCommandFrame cmdFrame, bool responseExpected, UInt32 timeoutMs)
{
// Ignore time out. Polling built into reader.
return SendNa2wSerialToNfc(cmdFrame, responseExpected, timeoutMs);
}
public NA2WSerialFrame SendNa2wSerial(ISerialCommandFrame cmdFrame, byte responseCommandCode)
{
// Route command through Hat's NFC
return SendNa2wSerialToNfc(cmdFrame, responseCommandCode);
}
void SerialMessageReceived(object sender, ReceptionEventArgs<ISerialMessageFrame> args)
{
ISerialMessageFrame message = args.Frame;
bool pushMessageUp = false;
// LogIncoming(message);
if (message.Payload is UnknownResponse)
{
UnknownResponse unknownResponse = message.Unwrap<UnknownResponse>();
// Serial Receive - extract and push up frame in payload
byte[] newFrame = unknownResponse.ToBytes();
try
{
NA2WSerialFrame na2wSerialFrame = NA2WSerialFrame.Parse(newFrame, 10, (uint)newFrame.Length - 10);
args.Frame = na2wSerialFrame;
message = na2wSerialFrame;
// If waiting for response, trigger found if content is expected
if (null != autoResetEvent)
{
// Utility.Log.Write("Response Found: " + System.Environment.NewLine);
foundResponse = na2wSerialFrame;
autoResetEvent.Set();
}
else
{
pushMessageUp = true;
}
}
catch { }
}
if (message.Payload is UnknownMessage)
{
UnknownMessage unknownMessage = message.Unwrap<UnknownMessage>();
// Serial Receive - extract and push up frame in payload
byte[] newFrame = unknownMessage.ToBytes();
try
{
NA2WSerialFrame na2wSerialFrame = NA2WSerialFrame.Parse(newFrame, 10, (uint)newFrame.Length - 10);
args.Frame = na2wSerialFrame;
message = na2wSerialFrame;
// If waiting for response, trigger found if content is expected
if (null != autoResetEvent)
{
// Utility.Log.Write("Message Found" + System.Environment.NewLine);
foundResponse = na2wSerialFrame;
autoResetEvent.Set();
}
else
{
pushMessageUp = true;
}
}
catch { }
}
else if (message.Payload is CommandAckResponse)
{
// Throw away. Hat ACKing a command. For example, Serial Transmit command will ack.
CommandAckResponse commandAckResponse = (CommandAckResponse)message.Payload;
// Utility.Log.Write(String.Format("Command to Hat returned ack: {0}\n", commandAckResponse.AckCommandCode));
}
else if (message.Payload is CommandErrorResponse)
{
// Throw away. Hat ACKing a command. For example, Serial Transmit command will ack.
CommandErrorResponse commandErrorResponse = (CommandErrorResponse)message.Payload;
Log.Write(String.Format("Command to Hat returned error: {0} {1}\n", commandErrorResponse.ErrorCommandCode, commandErrorResponse.ErrorCode));
}
else if (message.Payload is CommDeviceSessionBegin)
{
CommDeviceSessionBegin commDeviceSessionBegin = (CommDeviceSessionBegin)message.Payload;
sessionId = commDeviceSessionBegin.SessionID;
}
else if (message.Payload is CommDeviceSessionBeginV1)
{
CommDeviceSessionBeginV1 commDeviceSessionBegin = (CommDeviceSessionBeginV1)message.Payload;
sessionId = commDeviceSessionBegin.SessionID;
}
else if (message.Payload is SerialEventNotification)
{
SerialEventNotification serialEventNotification = (SerialEventNotification)message.Payload;
if (serialEventNotification.EventMap == 0x00) // CmdLinkII
{
Frame notification = (Frame)(serialEventNotification.Payload);
byte[] notificationBytes = notification.ToBytes();
SByte idNum = notificationBytes.Read<SByte>((0 * 8) + 0, 8);
// UInt64 timeStamp = notificationBytes.Read<UInt64>((1 * 8) + 0, 64);
// UInt16 numDataBytes = notificationBytes.Read<UInt16>((9 * 8) + 0, 16);
// UInt16 eventDataLength = (UInt16)((numDataBytes <= notificationBytes.Length - 11) ? numDataBytes : (notificationBytes.Length - 11));
// byte[] eventData = new byte[eventDataLength];
// Array.Copy(notificationBytes, 11, eventData, 0, eventDataLength);
if (idNum == 5) // ButtonClick
{
NfcCommand_InventoryRead nfcCommand = new NfcCommand_InventoryRead();
SendNa2wSerial(nfcCommand, false);
}
}
}
else if (message.Payload is NfcCommandResponse)
{
NfcCommandResponse commandResponse = (NfcCommandResponse)message.Payload;
String dataString = "";
bool readNDef = false;
if (0x00 == commandResponse.SubCommand)
{
// dataString = "Inventory -> Status = " + String.Format("{0:X2}", commandResponse.Status) + System.Environment.NewLine;
readNDef = (0x00 == commandResponse.SubCommand);
}
else if (0x01 == commandResponse.SubCommand)
{
// dataString = "NDEF Read -> Status = " + String.Format("{0:X2}", commandResponse.Status) + System.Environment.NewLine;
}
else
{
dataString = "Unknown -> Status = " + String.Format("{0:X2}", commandResponse.Status) + System.Environment.NewLine;
}
byte[] data = commandResponse.AdditionalData;
if ((data != null) && (data.Length > 0))
{
int numberOfBytes = data.Length;
uint index = 0;
while (numberOfBytes > 16)
{
byte[] lineData = data.Read<byte[]>(index * 8, 16 * 8);
// dataString += lineData.ToHexString() + System.Environment.NewLine;
index += 16;
numberOfBytes -= 16;
}
if (numberOfBytes > 0)
{
byte[] lineData = data.Read<byte[]>(index * 8, (uint)(8 * numberOfBytes));
// dataString += lineData.ToHexString();
}
if (0x00 == commandResponse.SubCommand)
{
// dataString += System.Environment.NewLine + System.Environment.NewLine + "----" + System.Environment.NewLine;
// AdditionData[0] is tag ID
// AdditionData[1 - 8] is UUID
// AdditionalData[9 - 28] is UUID String
tagId = System.Text.Encoding.ASCII.GetString(commandResponse.AdditionalData, 9, 20).TrimEnd('\0', '\n') ;
}
else if (0x01 == commandResponse.SubCommand)
{
// dataString += System.Environment.NewLine + System.Environment.NewLine + "----" + System.Environment.NewLine;
// dataString += System.Text.Encoding.ASCII.GetString(commandResponse.AdditionalData, 0, commandResponse.AdditionalData.Length);
ndefData = commandResponse.AdditionalData;
NdefMessage ndefMessage = new NdefMessage(ndefData);
foreach (NdefRecord record in ndefMessage.recordList)
{
if (record.RecordType == NdefRecord.SensusNdefRecordType.ProductDetailsRecord)
{
try
{
ProductDetailsRecord pdRecord = new ProductDetailsRecord(record.Payload.GetRawData());
nfcTargetDetails = new NfcTargetDetails()
{
TagId = tagId,
DeviceId = System.Text.Encoding.ASCII.GetString(pdRecord.ID1.ToArray()).Split(':')[1].Trim(),
ProductType = System.Text.Encoding.ASCII.GetString(pdRecord.ProductType.ToArray()).Split(':')[1].Trim(),
ProductVersion = System.Text.Encoding.ASCII.GetString(pdRecord.ProductTypeVersion.ToArray()).Split(':')[1].Trim(),
};
NfcTagDetected = true; // This uses nfcTargetDetails.
}
catch { }
}
}
}
}
Log.Write(dataString);
if (readNDef)
{
NfcCommand_NdefRead nfcCommand = new NfcCommand_NdefRead();
SendNa2wSerialToHat(nfcCommand, false);
}
}
else
{
pushMessageUp = true;
}
if (pushMessageUp)
{
try
{
this.MessageReceived.Raise(this, args);
}
catch (Exception ex)
{
Log.Write(String.Format("MessageReceived event handler threw: {0}", ex));
}
}
}
private bool nfcTagDetected;
private byte[] rmaData;
private byte[] ndefData;
private string tagId = "";
private NfcTargetDetails nfcTargetDetails;
public bool NfcTagDetected
{
get
{
return nfcTagDetected;
}
set
{
if (value != nfcTagDetected)
{
nfcTagDetected = value;
OnTagEvent(new TagEventArgs() { Present = value });
}
}
}
public event EventHandler<TagEventArgs> TagEvent;
public byte[] NDEF { get { return ndefData; } }
public byte[] RMA { get { return rmaData; } }
public NfcTargetDetails NfcTargetDetails { get { return nfcTargetDetails; } }
protected virtual void OnTagEvent(TagEventArgs e)
{
EventHandler<TagEventArgs> handler = TagEvent;
handler?.Invoke(this, e);
}
}
}