Files
tbf/NfcC7_DLL/NfcHanler/CmdLinkGen2Link.cs
T

473 lines
20 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 CmdLinkGen2Link : ISerialConnection, IDisposable
{
private SerialManager serialManager = null;
private UInt16 sessionId = 0;
public CmdLinkGen2Link(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 = SendNa2wSerial(commDeviceSessionOpen, true);
isOpen = (response != null);
if (response == null)
{
serialManager.Close();
serialManager = null;
Log.Write("CLII session open failed. Is device CLII?" + System.Environment.NewLine);
}
else
{
String version = "Unknown version ";
String frequencySupport = "unknown frequency (Update CommandLink II firmware)";
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);
}
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);
// Look at FW version number to determine if prototype hardware.
if (sessionBegin.ProductVersionMajor >= 2)
{
// Read Radio variant tag (CLII tag 0x39).
ParameterReadCommand parameterReadCommand = new ParameterReadCommand(0, 0x39);
// Response code (0x10) is not same as read.
response = SendNa2wSerial(parameterReadCommand, 0x10);
if (response != null) // NA2W Serial ParameterData message
{
networkResponse = (NetworkResponse)response.Payload;
byte[] payload = networkResponse.Payload.ToBytes();
// NA2WSerialParameterData parameterData = (NA2WSerialParameterData)e.Frame.Payload;
// if (parameterData.TagMap == 0x00)
if (payload[0] == 0x00)
{
// byte[] tlvArray = parameterData.TlvArray;
// if (tlvArray[0] == 0x39)
if (payload[1] == 0x39)
{
// byte variantValue = tlvArray[2];
byte variantValue = payload[3];
if (variantValue == 2)
{
frequencySupport = "900 MHz";
}
else if (variantValue == 4)
{
frequencySupport = "400 MHz";
}
else if (variantValue == 6)
{
frequencySupport = "868 MHz";
}
}
}
}
}
}
Log.Write("CLII session opened: " + version + " supporting " + frequencySupport + "." + 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;
}
// windowViewModel.IsBusy = 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;
SendNa2wSerial(commDeviceSessionClose, false);
serialManager.Close();
serialManager = null;
Log.Write("CLII 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 SendNa2wSerial(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);
}
public NA2WSerialFrame SendNa2wSerial(ISerialCommandFrame cmdFrame, bool responseExpected, UInt32 timeoutMs)
{
// Route command through Hat's NFC
return SendNa2wSerial(cmdFrame, responseExpected);
}
public NA2WSerialFrame SendNa2wSerial(ISerialCommandFrame cmdFrame, bool responseExpected)
{
SerialTransmitCommandV1 serialTransmitCommandV1 = new SerialTransmitCommandV1();
cmdFrame.Bake();
serialTransmitCommandV1.Payload = new Frame(cmdFrame.ToBytes());
serialTransmitCommandV1.PortId = 0x02;
serialTransmitCommandV1.Bake();
return SendNa2wSerial(serialTransmitCommandV1, responseExpected);
}
public NA2WSerialFrame SendNa2wSerial(ISerialCommand cmd, byte responseCommandCode)
{
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, responseCommandCode);
}
public NA2WSerialFrame SendNa2wSerial(ISerialCommandFrame cmdFrame, byte responseCommandCode)
{
return serialManager.SendNa2wSerial(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>();
if (unknownResponse.CommandCode == 0x21)
{
// 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;
pushMessageUp = true;
}
catch { }
}
}
if (message.Payload is UnknownMessage)
{
UnknownMessage unknownMessage = message.Unwrap<UnknownMessage>();
if (unknownMessage.CommandCode == 0x21)
{
// 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;
pushMessageUp = true;
}
catch { }
}
}
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
dataString += System.Text.Encoding.ASCII.GetString(commandResponse.AdditionalData, 9, 20);
}
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()
{
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();
SendNa2wSerial(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 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);
}
}
}