473 lines
20 KiB
C#
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);
|
|
}
|
|
}
|
|
}
|