Ingo Fritz - Add rest client for security server

This commit is contained in:
Jan Augustin 2024-07-25 12:14:58 +02:00
parent 334d43fbda
commit 13bf73104f
9 changed files with 557 additions and 437 deletions

Binary file not shown.

Binary file not shown.

BIN
Doc/scheme.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

View File

@ -1,249 +1,249 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Timers;
using System.IO.Ports;
//*****************************************************************************
// Copyright 2020 Sensus GmbH Ludwigshafen. All rights reserved.
// Author: Venkat, Rajeshwar
//*****************************************************************************
namespace Sensus.iPerl.NfcHandler
{
public class CR95HF_Reader
{
private readonly byte [] CR95HF_CMD_ECHO = { 0x55 };
private readonly byte[] CR95HF_CMD_IDN = { 0x01, 0x00 }; //CommandCode(0x01), Length(0x00)
private readonly byte[] CR95HF_CMD_PROTOCOL_SELECT_ON = { 0x02, 0x02, 0x01, 0x0D }; //CommandCode(0x02), Length(0x02), ISO/IEC 15693(0x01), 26 Kbps H, Wait for SOF, 10% modulation, Single subcarrier S, CRC appended (0x0D)
private readonly byte[] CR95HF_CMD_PROTOCOL_SELECT_OFF = { 0x02, 0x02, 0x00, 0x00 }; //CommandCode(0x02), Length(0x02), Protocol off (0x00), Protocol off (0x00)
private List<byte> CR95HF_CMD_SEND_RECEIVE = new List<byte>(); // Command code (0x04), Length (this is number of bytes after this length byte), REQUEST_FLAGS(0x02) and payload (this varies based on device command)
private readonly byte REQUEST_FLAGS = 0x02; // Single subcarrier freq, High data rate, No Inventory/ProtExtn/Select/Address/Option flags
private SERIAL_Driver _SERIAL_Driver;
public event DelNfc_CR95HF_MessageHandler MessageEvent;
private static readonly Dictionary<byte, string> CR95HF_ErrorCodes = new Dictionary<byte, string>
{
{ 0x00 , "Success, No error" },
{ 0x80 , "Success, No error" },
{ 0xA0 , "Success, No error" },
{ 0xC0 , "Success, No error" },
{ 0x82 , "Invalid command length" },
{ 0x83 , "Invalid protocol"},
{ 0x63 , "EEmdSOFerror23, SOF error in high part(duration 2 to 3 etu) in ISO/IEC 14443B"},
{ 0x65 , "EEmdSOFerror10, SOF error in low part(duration 10 to 11 etu) in ISO/IEC 14443B"},
{ 0x66 , "EEmdEgt error, Extended Guard Time error in ISO/IEC 14443B"},
{ 0x67 , "ETr1 Too Big Too long, TR1 send by the card, reception stopped in ISO/IEC 14443BT"},
{ 0x68 , "ETr1Too small Too small, TR1 send by the card in ISO/IEC 14443B"},
{ 0x71 , "EinternalError, Wrong frame format decoded"},
{ 0x85 , "EUserStop, Stopped by user(used only in Card mode)"},
{ 0x86 , "ECommError, Hardware communication error"},
{ 0x87 , "EFrameWaitTOut,Frame wait time out (no valid reception)"},
{ 0x88 , "EInvalidSof,Invalid SOF" },
{ 0x89 , "EBufOverflow,Too many bytes received and data still arriving" },
{ 0x8A , "EFramingError,if start bit = 1 or stop bit = 0"},
{ 0x8B , "EEgtError,EGT time out" },
{ 0x8C , "EInvalidLen,Valid for ISO/IEC 18092, if Length<3" },
{ 0x8D , "ECrcError,CRC error, Valid only for ISO/IEC 18092" },
{ 0x8E , "ERecvLost,CRC error,When reception is lost without EOF received(or subcarrier was lost)"},
{ 0x8F , "ENoField,CRC error,When Listen command detects the absence of external field)"},
{ 0x90 , "EUnintByte,Residual bits in last byte. Useful for ACK/NAK reception of ISO/IEC 14443 Type A"},
{ 0xFF , "Invalid COM port, request Failed" },
};
public CR95HF_Reader(SERIAL_Driver serialdriver)
{
_SERIAL_Driver = serialdriver;
}
#region Message Event
private void OnMessageEvent(string message)
{
NfcMessageEventArgs e = new NfcMessageEventArgs();
e.Message = message;
if (MessageEvent != null)
{
MessageEvent(this, e);
}
e = null;
}
#endregion
public bool OpenConnection(string comport, int baudrate, int databits, Parity parity, StopBits stopbits)
{
return _SERIAL_Driver.OpenConnection(comport, baudrate, databits, parity, stopbits);//Port Intialization and Port Open;
}
public bool CR95HF_Connect()
{
byte[] bytesReceived;
if (_SERIAL_Driver.isOpen())
{
//OnMessageEvent("Tx- " + Tools.ByteArrayToHexString(CR95HF_CMD_IDN));
_SERIAL_Driver.SendMessage(CR95HF_CMD_IDN, CR95HF_CMD_IDN.Length);
if (_SERIAL_Driver.GetRawData().Length == 0) return false;
bytesReceived = _SERIAL_Driver.GetRawData();
//OnMessageEvent("Rx- " + Tools.ByteArrayToHexString(bytesReceived));
if (bytesReceived.Length == 17 && (bytesReceived[0] == 0x00 || bytesReceived[0] == 0x80))
{
string strReader = System.Text.Encoding.ASCII.GetString(bytesReceived);
strReader = strReader.Substring(2, 12);
OnMessageEvent("CombiHead '" + strReader + "'");
}
else
{
if (CR95HF_ErrorCodes.ContainsKey(bytesReceived[0]))
OnMessageEvent("NFC CR95HF error: " + CR95HF_ErrorCodes[bytesReceived[0]]);
else
OnMessageEvent("NFC CR95HF error: Unidentified");
return false;
}
//OnMessageEvent("Tx- " + Tools.ByteArrayToHexString(CR95HF_CMD_PROTOCOL_SELECT_ON));
_SERIAL_Driver.SendMessage(CR95HF_CMD_PROTOCOL_SELECT_ON, CR95HF_CMD_PROTOCOL_SELECT_ON.Length);
if (_SERIAL_Driver.GetRawData().Length == 0) return false;
bytesReceived = _SERIAL_Driver.GetRawData();
//OnMessageEvent("Rx- " + Tools.ByteArrayToHexString(bytesReceived));
if ((bytesReceived[0] != 0x00) && (bytesReceived[0] != 0x80))
{
if (CR95HF_ErrorCodes.ContainsKey(bytesReceived[0]))
OnMessageEvent("NFC CR95HF error: " + CR95HF_ErrorCodes[bytesReceived[0]]);
else
OnMessageEvent("NFC CR95HF error: Unidentified");
return false;
}
}
else
{
OnMessageEvent(_SERIAL_Driver.ErrorMessage);
return false;
}
OnMessageEvent("NFC CR95HF: Protocol ON");
return true;
}
public bool CR95HF_RFProtocolOn()
{
byte[] bytesReceived;
if (_SERIAL_Driver.isOpen())
{
//OnMessageEvent("Tx- " + Tools.ByteArrayToHexString(CR95HF_CMD_PROTOCOL_SELECT_ON));
_SERIAL_Driver.SendMessage(CR95HF_CMD_PROTOCOL_SELECT_ON, CR95HF_CMD_PROTOCOL_SELECT_ON.Length);
if (_SERIAL_Driver.GetRawData().Length == 0) return false;
bytesReceived = _SERIAL_Driver.GetRawData();
//OnMessageEvent("Rx- " + Tools.ByteArrayToHexString(bytesReceived));
if ((bytesReceived[0] != 0x00) && (bytesReceived[0] != 0x80))
{
if (CR95HF_ErrorCodes.ContainsKey(bytesReceived[0]))
OnMessageEvent("NFC CR95HF error: " + CR95HF_ErrorCodes[bytesReceived[0]]);
else
OnMessageEvent("NFC CR95HF error: Unidentified");
return false;
}
}
else
{
OnMessageEvent(_SERIAL_Driver.ErrorMessage);
return false;
}
return true;
}
public bool CR95HF_RFProtocolOff()
{
byte[] bytesReceived;
if (_SERIAL_Driver.isOpen())
{
//OnMessageEvent("Tx- " + Tools.ByteArrayToHexString(CR95HF_CMD_PROTOCOL_SELECT_OFF));
_SERIAL_Driver.SendMessage(CR95HF_CMD_PROTOCOL_SELECT_OFF, CR95HF_CMD_PROTOCOL_SELECT_OFF.Length);
if (_SERIAL_Driver.GetRawData().Length == 0) return false;
bytesReceived = _SERIAL_Driver.GetRawData();
//OnMessageEvent("Rx- " + Tools.ByteArrayToHexString(bytesReceived));
if ((bytesReceived[0] != 0x00) && (bytesReceived[0] != 0x80))
{
if (CR95HF_ErrorCodes.ContainsKey(bytesReceived[0]))
OnMessageEvent("NFC CR95HF error: " + CR95HF_ErrorCodes[bytesReceived[0]]);
else
OnMessageEvent("NFC CR95HF error: Unidentified");
return false;
}
}
else
{
OnMessageEvent(_SERIAL_Driver.ErrorMessage);
return false;
}
return true;
}
public bool CR95HF_SendRecv(byte[] fromDevice, out byte[] toDevice)
{
CR95HF_CMD_SEND_RECEIVE = new List<byte>();
toDevice = null;
if (_SERIAL_Driver.isOpen())
{
CR95HF_CMD_SEND_RECEIVE.Add(0x04);//Command Code
CR95HF_CMD_SEND_RECEIVE.Add((byte)(1 + fromDevice.Length)); // This is bytes from device + 1 (because request flags byte added here)
CR95HF_CMD_SEND_RECEIVE.Add(REQUEST_FLAGS);
CR95HF_CMD_SEND_RECEIVE.AddRange(fromDevice);
//OnMessageEvent("Tx- " + Tools.ByteArrayToHexString(CR95HF_CMD_SEND_RECEIVE.ToArray()));
_SERIAL_Driver.SendMessage(CR95HF_CMD_SEND_RECEIVE.ToArray(), (3 + fromDevice.Length)); // This is bytes from device + 3 (because request flags + length + reader command)
if (_SERIAL_Driver.GetRawData().Length == 0) return false;
byte[] bytesReceived = _SERIAL_Driver.GetRawData();
//OnMessageEvent("Rx- " + Tools.ByteArrayToHexString(bytesReceived));
if ((bytesReceived[0] == 0x00) || (bytesReceived[0] == 0x80) || (bytesReceived[0] == 0xA0) || (bytesReceived[0] == 0xC0))
{
toDevice = new byte[bytesReceived[1]];
for (int i = 0; i < Convert.ToInt32(bytesReceived[1]); i++)
{
toDevice[i] = bytesReceived[2 + i];
}
}
else
{
if (CR95HF_ErrorCodes.ContainsKey(bytesReceived[0]))
OnMessageEvent("NFC CR95HF error: " + CR95HF_ErrorCodes[bytesReceived[0]]);
else
OnMessageEvent("NFC CR95HF error: Unidentified");
return false;
}
}
else
{
OnMessageEvent(_SERIAL_Driver.ErrorMessage);
return false;
}
return true;
}
public bool CR95HF_Echo()
{
if (_SERIAL_Driver.isOpen())
{
if (_SERIAL_Driver.SendMessage(CR95HF_CMD_ECHO, 1))
{
if (_SERIAL_Driver.GetRawData().Length == 0) return false;
byte[] bytesReceived = _SERIAL_Driver.GetRawData();
if ((bytesReceived.Length == 1) && (bytesReceived[0] == CR95HF_CMD_ECHO[0]))
return true;
}
}
else
{
OnMessageEvent(_SERIAL_Driver.ErrorMessage);
return false;
}
return false;
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Timers;
using System.IO.Ports;
//*****************************************************************************
// Copyright 2020 Sensus GmbH Ludwigshafen. All rights reserved.
// Author: Venkat, Rajeshwar
//*****************************************************************************
namespace Sensus.iPerl.NfcHandler
{
public class CR95HF_Reader
{
private readonly byte [] CR95HF_CMD_ECHO = { 0x55 };
private readonly byte[] CR95HF_CMD_IDN = { 0x01, 0x00 }; //CommandCode(0x01), Length(0x00)
private readonly byte[] CR95HF_CMD_PROTOCOL_SELECT_ON = { 0x02, 0x02, 0x01, 0x0D }; //CommandCode(0x02), Length(0x02), ISO/IEC 15693(0x01), 26 Kbps H, Wait for SOF, 10% modulation, Single subcarrier S, CRC appended (0x0D)
private readonly byte[] CR95HF_CMD_PROTOCOL_SELECT_OFF = { 0x02, 0x02, 0x00, 0x00 }; //CommandCode(0x02), Length(0x02), Protocol off (0x00), Protocol off (0x00)
private List<byte> CR95HF_CMD_SEND_RECEIVE = new List<byte>(); // Command code (0x04), Length (this is number of bytes after this length byte), REQUEST_FLAGS(0x02) and payload (this varies based on device command)
private readonly byte REQUEST_FLAGS = 0x02; // Single subcarrier freq, High data rate, No Inventory/ProtExtn/Select/Address/Option flags
private SERIAL_Driver _SERIAL_Driver;
public event DelNfc_CR95HF_MessageHandler MessageEvent;
private static readonly Dictionary<byte, string> CR95HF_ErrorCodes = new Dictionary<byte, string>
{
{ 0x00 , "Success, No error" },
{ 0x80 , "Success, No error" },
{ 0xA0 , "Success, No error" },
{ 0xC0 , "Success, No error" },
{ 0x82 , "Invalid command length" },
{ 0x83 , "Invalid protocol"},
{ 0x63 , "EEmdSOFerror23, SOF error in high part(duration 2 to 3 etu) in ISO/IEC 14443B"},
{ 0x65 , "EEmdSOFerror10, SOF error in low part(duration 10 to 11 etu) in ISO/IEC 14443B"},
{ 0x66 , "EEmdEgt error, Extended Guard Time error in ISO/IEC 14443B"},
{ 0x67 , "ETr1 Too Big Too long, TR1 send by the card, reception stopped in ISO/IEC 14443BT"},
{ 0x68 , "ETr1Too small Too small, TR1 send by the card in ISO/IEC 14443B"},
{ 0x71 , "EinternalError, Wrong frame format decoded"},
{ 0x85 , "EUserStop, Stopped by user(used only in Card mode)"},
{ 0x86 , "ECommError, Hardware communication error"},
{ 0x87 , "EFrameWaitTOut,Frame wait time out (no valid reception)"},
{ 0x88 , "EInvalidSof,Invalid SOF" },
{ 0x89 , "EBufOverflow,Too many bytes received and data still arriving" },
{ 0x8A , "EFramingError,if start bit = 1 or stop bit = 0"},
{ 0x8B , "EEgtError,EGT time out" },
{ 0x8C , "EInvalidLen,Valid for ISO/IEC 18092, if Length<3" },
{ 0x8D , "ECrcError,CRC error, Valid only for ISO/IEC 18092" },
{ 0x8E , "ERecvLost,CRC error,When reception is lost without EOF received(or subcarrier was lost)"},
{ 0x8F , "ENoField,CRC error,When Listen command detects the absence of external field)"},
{ 0x90 , "EUnintByte,Residual bits in last byte. Useful for ACK/NAK reception of ISO/IEC 14443 Type A"},
{ 0xFF , "Invalid COM port, request Failed" },
};
public CR95HF_Reader(SERIAL_Driver serialdriver)
{
_SERIAL_Driver = serialdriver;
}
#region Message Event
private void OnMessageEvent(string message)
{
NfcMessageEventArgs e = new NfcMessageEventArgs();
e.Message = message;
if (MessageEvent != null)
{
MessageEvent(this, e);
}
e = null;
}
#endregion
public bool OpenConnection(string comport, int baudrate, int databits, Parity parity, StopBits stopbits)
{
return _SERIAL_Driver.OpenConnection(comport, baudrate, databits, parity, stopbits);//Port Intialization and Port Open;
}
public bool CR95HF_Connect()
{
byte[] bytesReceived;
if (_SERIAL_Driver.isOpen())
{
//OnMessageEvent("Tx- " + Tools.ByteArrayToHexString(CR95HF_CMD_IDN));
_SERIAL_Driver.SendMessage(CR95HF_CMD_IDN, CR95HF_CMD_IDN.Length);
if (_SERIAL_Driver.GetRawData().Length == 0) return false;
bytesReceived = _SERIAL_Driver.GetRawData();
//OnMessageEvent("Rx- " + Tools.ByteArrayToHexString(bytesReceived));
if (bytesReceived.Length == 17 && (bytesReceived[0] == 0x00 || bytesReceived[0] == 0x80))
{
string strReader = System.Text.Encoding.ASCII.GetString(bytesReceived);
strReader = strReader.Substring(2, 12);
OnMessageEvent("CombiHead '" + strReader + "'");
}
else
{
if (CR95HF_ErrorCodes.ContainsKey(bytesReceived[0]))
OnMessageEvent("NFC CR95HF error: " + CR95HF_ErrorCodes[bytesReceived[0]]);
else
OnMessageEvent("NFC CR95HF error: Unidentified");
return false;
}
//OnMessageEvent("Tx- " + Tools.ByteArrayToHexString(CR95HF_CMD_PROTOCOL_SELECT_ON));
_SERIAL_Driver.SendMessage(CR95HF_CMD_PROTOCOL_SELECT_ON, CR95HF_CMD_PROTOCOL_SELECT_ON.Length);
if (_SERIAL_Driver.GetRawData().Length == 0) return false;
bytesReceived = _SERIAL_Driver.GetRawData();
//OnMessageEvent("Rx- " + Tools.ByteArrayToHexString(bytesReceived));
if ((bytesReceived[0] != 0x00) && (bytesReceived[0] != 0x80))
{
if (CR95HF_ErrorCodes.ContainsKey(bytesReceived[0]))
OnMessageEvent("NFC CR95HF error: " + CR95HF_ErrorCodes[bytesReceived[0]]);
else
OnMessageEvent("NFC CR95HF error: Unidentified");
return false;
}
}
else
{
OnMessageEvent(_SERIAL_Driver.ErrorMessage);
return false;
}
OnMessageEvent("NFC CR95HF: Protocol ON");
return true;
}
public bool CR95HF_RFProtocolOn()
{
byte[] bytesReceived;
if (_SERIAL_Driver.isOpen())
{
//OnMessageEvent("Tx- " + Tools.ByteArrayToHexString(CR95HF_CMD_PROTOCOL_SELECT_ON));
_SERIAL_Driver.SendMessage(CR95HF_CMD_PROTOCOL_SELECT_ON, CR95HF_CMD_PROTOCOL_SELECT_ON.Length);
if (_SERIAL_Driver.GetRawData().Length == 0) return false;
bytesReceived = _SERIAL_Driver.GetRawData();
//OnMessageEvent("Rx- " + Tools.ByteArrayToHexString(bytesReceived));
if ((bytesReceived[0] != 0x00) && (bytesReceived[0] != 0x80))
{
if (CR95HF_ErrorCodes.ContainsKey(bytesReceived[0]))
OnMessageEvent("NFC CR95HF error: " + CR95HF_ErrorCodes[bytesReceived[0]]);
else
OnMessageEvent("NFC CR95HF error: Unidentified");
return false;
}
}
else
{
OnMessageEvent(_SERIAL_Driver.ErrorMessage);
return false;
}
return true;
}
public bool CR95HF_RFProtocolOff()
{
byte[] bytesReceived;
if (_SERIAL_Driver.isOpen())
{
//OnMessageEvent("Tx- " + Tools.ByteArrayToHexString(CR95HF_CMD_PROTOCOL_SELECT_OFF));
_SERIAL_Driver.SendMessage(CR95HF_CMD_PROTOCOL_SELECT_OFF, CR95HF_CMD_PROTOCOL_SELECT_OFF.Length);
if (_SERIAL_Driver.GetRawData().Length == 0) return false;
bytesReceived = _SERIAL_Driver.GetRawData();
//OnMessageEvent("Rx- " + Tools.ByteArrayToHexString(bytesReceived));
if ((bytesReceived[0] != 0x00) && (bytesReceived[0] != 0x80))
{
if (CR95HF_ErrorCodes.ContainsKey(bytesReceived[0]))
OnMessageEvent("NFC CR95HF error: " + CR95HF_ErrorCodes[bytesReceived[0]]);
else
OnMessageEvent("NFC CR95HF error: Unidentified");
return false;
}
}
else
{
OnMessageEvent(_SERIAL_Driver.ErrorMessage);
return false;
}
return true;
}
public bool CR95HF_SendRecv(byte[] fromDevice, out byte[] toDevice)
{
CR95HF_CMD_SEND_RECEIVE = new List<byte>();
toDevice = null;
if (_SERIAL_Driver.isOpen())
{
CR95HF_CMD_SEND_RECEIVE.Add(0x04);//Command Code
CR95HF_CMD_SEND_RECEIVE.Add((byte)(1 + fromDevice.Length)); // This is bytes from device + 1 (because request flags byte added here)
CR95HF_CMD_SEND_RECEIVE.Add(REQUEST_FLAGS);
CR95HF_CMD_SEND_RECEIVE.AddRange(fromDevice);
//OnMessageEvent("Tx- " + Tools.ByteArrayToHexString(CR95HF_CMD_SEND_RECEIVE.ToArray()));
_SERIAL_Driver.SendMessage(CR95HF_CMD_SEND_RECEIVE.ToArray(), CR95HF_CMD_SEND_RECEIVE.Count);
if (_SERIAL_Driver.GetRawData().Length == 0) return false;
byte[] bytesReceived = _SERIAL_Driver.GetRawData();
//OnMessageEvent("Rx- " + Tools.ByteArrayToHexString(bytesReceived));
if ((bytesReceived[0] == 0x00) || (bytesReceived[0] == 0x80) || (bytesReceived[0] == 0xA0) || (bytesReceived[0] == 0xC0))
{
toDevice = new byte[bytesReceived[1]];
for (int i = 0; i < Convert.ToInt32(bytesReceived[1]); i++)
{
toDevice[i] = bytesReceived[2 + i];
}
}
else
{
if (CR95HF_ErrorCodes.ContainsKey(bytesReceived[0]))
OnMessageEvent("NFC CR95HF error: " + CR95HF_ErrorCodes[bytesReceived[0]]);
else
OnMessageEvent("NFC CR95HF error: Unidentified");
return false;
}
}
else
{
OnMessageEvent(_SERIAL_Driver.ErrorMessage);
return false;
}
return true;
}
public bool CR95HF_Echo()
{
if (_SERIAL_Driver.isOpen())
{
if (_SERIAL_Driver.SendMessage(CR95HF_CMD_ECHO, 1))
{
if (_SERIAL_Driver.GetRawData().Length == 0) return false;
byte[] bytesReceived = _SERIAL_Driver.GetRawData();
if ((bytesReceived.Length == 1) && (bytesReceived[0] == CR95HF_CMD_ECHO[0]))
return true;
}
}
else
{
OnMessageEvent(_SERIAL_Driver.ErrorMessage);
return false;
}
return false;
}
}
}

View File

@ -7,6 +7,7 @@ using System.Threading;
using System.Diagnostics;
using System.IO.Ports;
using System.Timers;
using System.Runtime.CompilerServices;
//*****************************************************************************
// Copyright 2020 Sensus GmbH Ludwigshafen. All rights reserved.
@ -22,7 +23,6 @@ namespace Sensus.iPerl.NfcHandler
private readonly byte STX = (byte) 0x02;
private readonly byte ETX = (byte) 0x03;
private readonly byte RX_ACK_RESPONSE_MSG_ID = (byte) 0xC9;
private readonly byte RX_ACK_PASSTHROUGH_MSG_ID = (byte)0xCE;
private readonly ushort[] MciPasswords = { 0x0000, 0x55AA, 0x1234, 0x97D1 };
public event DelNfc_MCI_MessageHandler MessageEvent;
@ -286,6 +286,7 @@ namespace Sensus.iPerl.NfcHandler
byte[] valueNfcSecurityUnsignedReadResponse = { 0xD4, 0xD1, 0x97 };
MCI_ReadResponse_Info.Add(16, valueNfcSecurityUnsignedReadResponse);//NFC Security non-signed message response - while reading
}
public bool MCI_Write(StructName StName, ushort offset, byte payloadlength, byte[] inBuffer, int timeoutMs,
out byte errorCode)
{
@ -296,33 +297,27 @@ namespace Sensus.iPerl.NfcHandler
errorCode = (byte) MCI_ErrorCodes.Success_No_error;
if (payloadlength != inBuffer.Length)
{
OnMessageEvent("Insufficient Payload !, Payload length given as: " + inBuffer.Length);
{
// Insufficient Payload length
errorCode = (byte)MCI_ErrorCodes.MCI_Error_Host_Bad_Payload_Len;
return false;
}
if (StName == StructName.Command)
{
if (MCI_Protocol.MCI_CmdCodes.ContainsKey(inBuffer[0]))
if (! MCI_Protocol.MCI_CmdCodes.ContainsKey(inBuffer[0]))
{
OnMessageEvent("Write " + MCI_Protocol.MCI_CmdCodes[inBuffer[0]]);
}
else
{
OnMessageEvent("Command: Not supported");
// Command not supported
errorCode = (byte)MCI_ErrorCodes.MCI_Error_Host_CommandNotInCmdCodeList;
return false;
}
}
else
else // not a command => should be struct
{
if (!IsValidStruct(StName))
{
errorCode = (byte)MCI_ErrorCodes.MCI_Error_Host_InvalidStructureID_CannotSendMsg;
OnMessageEvent("Write request:" + MCI_Protocol.GetMCIErrorMessage(errorCode));
return false;
}
OnMessageEvent("Write " + StructToStr(StName) + ": " + Tools.BytesToHex(inBuffer));
}
byte[] MsgId_Password = MCI_Write_Info[(int)StName];
@ -347,12 +342,10 @@ namespace Sensus.iPerl.NfcHandler
RequestMessage.Add(crcValue[1]);
RequestMessage.Add(ETX);
OnMessageEvent("Write Request: " + Tools.BytesToHex(RequestMessage.ToArray()));
OnMessageEvent("Write " + StructToStr(StName) + "Request: " + Tools.BytesToHex(RequestMessage.ToArray()));
errorCode = MCI_TxRequest_RxResponse(RequestMessage.ToArray(), out ResponseMessage, timeoutMs);
if (errorCode != (byte)MCI_ErrorCodes.Success_No_error)
{
OnMessageEvent("WriteReq denied");
errorCode = (byte)MCI_ErrorCodes.MCI_Error_Host_WriteReq_denied;
return false;
}
//Response message received
@ -360,33 +353,159 @@ namespace Sensus.iPerl.NfcHandler
byte[] RxCrcMeter = new byte[2];
// CRC starts at length + STX(1) + lenbyte(1) = RespMsg[1] + 2.
Array.Copy(ResponseMessage, ResponseMessage[1] + 2, RxCrcMeter, 0, 2);
OnMessageEvent(Crc.commentCRC(RxCrcMeter, RxCrcComputed));
if (!Crc.crc_do_match(RxCrcMeter, RxCrcComputed))
{
OnMessageEvent("CRC from Meter and PC do not match!");
OnMessageEvent(Crc.commentCRC(RxCrcMeter, RxCrcComputed));
errorCode = (byte) MCI_ErrorCodes.MCI_Error_Host_MeterCRCDoesNotMatch;
return false;
}
if ((ResponseMessage[0] == STX)
&& (ResponseMessage[1] == 0x07)
&& (ResponseMessage[2] == RX_ACK_PASSTHROUGH_MSG_ID || ResponseMessage[2] == RX_ACK_RESPONSE_MSG_ID)
if ((ResponseMessage[0] == STX)
&& (ResponseMessage[1] == 0x07)
&& (ResponseMessage[2] == RX_ACK_RESPONSE_MSG_ID)
&& (ResponseMessage[11] == ETX))
{
errorCode = ResponseMessage[6]; // meter error. Must be between 0..8
OnMessageEvent("Write " + StructToStr(StName) + "Request Response: " + Tools.BytesToHex(ResponseMessage));
errorCode = ResponseMessage[6]; // meter error. Must be between 0..8.
// Will be converted to errormessage string from the calling method.
if (errorCode != 0)
{
OnMessageEvent("Write Calibration: Failed with error " + Tools.ByteToHexString(errorCode));
OnMessageEvent("Write " + StructToStr(StName) + " failed. Request Response: " + Tools.BytesToHex(ResponseMessage));
return false;
}
OnMessageEvent("Write : Success");
return true;
}
OnMessageEvent("WriteReq bad device ans");
errorCode = (byte) MCI_ErrorCodes.MCI_Error_Host_WriteReq_bad_device_ans;
return false;
}
public bool MCI_Write_Read(StructName StName, ushort offset, byte payloadlength, byte[] inBuffer, out byte[] outBuffer, int timeoutMs,
out byte errorCode)
{
List<byte> RequestMessage = new List<byte>();
byte[] ResponseMessage = null;
byte[] crcValue = new byte[2];
byte RxMsgLength;
byte RxMsgId;
byte[] RxOffset = new byte[2];
byte RxPayloadlength;
byte[] RxCrcMeter = new byte[2];
outBuffer = null;
errorCode = (byte)MCI_ErrorCodes.Success_No_error;
if (payloadlength != inBuffer.Length)
{
// Insufficient Payload length
errorCode = (byte)MCI_ErrorCodes.MCI_Error_Host_Bad_Payload_Len;
return false;
}
if (StName == StructName.Command)
{
if (!MCI_Protocol.MCI_CmdCodes.ContainsKey(inBuffer[0]))
{
// Command not supported
errorCode = (byte)MCI_ErrorCodes.MCI_Error_Host_CommandNotInCmdCodeList;
return false;
}
}
else // not a command => should be struct
{
if (!IsValidStruct(StName))
{
errorCode = (byte)MCI_ErrorCodes.MCI_Error_Host_InvalidStructureID_CannotSendMsg;
return false;
}
}
byte[] MsgId_Password = MCI_Write_Info[(int)StName];
RequestMessage.Add(STX);
RequestMessage.Add(Convert.ToByte(6 + payloadlength));
RequestMessage.Add(MsgId_Password[0]);
RequestMessage.Add((byte)(offset & 0x00FF));
RequestMessage.Add((byte)((offset & 0xFF00) >> 8));
RequestMessage.Add(payloadlength);
for (int i = 0; i < payloadlength; i++) // copy Buffer -> Request Payload
{
RequestMessage.Add(inBuffer[i]);
}
RequestMessage.Add(MsgId_Password[1]);
RequestMessage.Add(MsgId_Password[2]);
// calc CRC and add to request
crcValue = Crc.calcCRCfromMessage(RequestMessage.ToArray());
RequestMessage.Add(crcValue[0]);
RequestMessage.Add(crcValue[1]);
RequestMessage.Add(ETX);
OnMessageEvent("Write " + StructToStr(StName) + "Request: " + Tools.BytesToHex(RequestMessage.ToArray()));
errorCode = MCI_TxRequest_RxResponse(RequestMessage.ToArray(), out ResponseMessage, timeoutMs);
if (errorCode != (byte)MCI_ErrorCodes.Success_No_error)
{
return false;
}
if ((ResponseMessage[0] == STX) && (ResponseMessage[11] == ETX)
&& (ResponseMessage[1] == 0x07)
&& (ResponseMessage[2] == RX_ACK_RESPONSE_MSG_ID))
{
//Ack message received, not served the read request
errorCode = ResponseMessage[6]; // forward error message from meter
OnMessageEvent("Read " + StructToStr(StName) + ": Failed with error "
+ Tools.ByteToHexString(errorCode));
return false;
}
//Response message received
RxMsgLength = ResponseMessage[1];
RxMsgId = ResponseMessage[2];
// RxOffset[0] = ResponseMessage[3];
// RxOffset[1] = ResponseMessage[4];
RxPayloadlength = ResponseMessage[5];
// RxPassword[0] = ResponseMessage[6 + RxPayloadlength];
// RxPassword[1] = ResponseMessage[7 + RxPayloadlength];
RxCrcMeter[0] = ResponseMessage[8 + RxPayloadlength];
RxCrcMeter[1] = ResponseMessage[9 + RxPayloadlength];
byte[] RxCrcComputed = Crc.calcCRCfromMessage(ResponseMessage);
// OnMessageEvent(Crc.commentCRC(RxCrcMeter, RxCrcComputed));
if (!Crc.crc_do_match(RxCrcMeter, RxCrcComputed))
{
errorCode = (byte)MCI_ErrorCodes.MCI_Error_Host_MeterCRCDoesNotMatch;
return false;
}
//TODO, verify received password matches with expected password or not?
if (!((ResponseMessage[0] == STX) && (ResponseMessage[10 + RxPayloadlength] == ETX)
&& ((ResponseMessage[2] & 0x3F) == (MsgId_Password[0] & 0x3F))))
{
errorCode = (byte)MCI_ErrorCodes.MCI_Error_Host_ReadReqBadResponseStructure;
return false;
}
outBuffer = new byte[RxPayloadlength];
for (int i = 0; i < RxPayloadlength; i++)
{
outBuffer[i] = (ResponseMessage[6 + i]);
}
if (IsValidStruct(StName))
{
OnMessageEvent("Read " + StructToStr(StName) + ": " + Tools.BytesToHex(outBuffer)
+ " Success");
}
else
{
OnMessageEvent("Read Failed! Unknown MCI ID: " + Convert.ToByte(StName));
errorCode = (byte)MCI_ErrorCodes.MCI_Error_Host_Bad_MCI_ID;
return false;
}
errorCode = (byte)0x00; //Success, No error
return true;
}
public bool MCI_Read(StructName StName, ushort offset, byte payloadlength, int timeoutMs,
out byte[] outBuffer, out byte errorCode)
{
@ -409,9 +528,8 @@ namespace Sensus.iPerl.NfcHandler
{
errorCode = (byte)MCI_ErrorCodes.MCI_Error_Host_InvalidStructureID_CannotSendMsg;
OnMessageEvent("Read request:" + MCI_Protocol.GetMCIErrorMessage(errorCode));
return false;
return false;
}
OnMessageEvent("Read " + StructToStr(StName));
RequestMessage.Add(STX);
RequestMessage.Add(0x06);
@ -430,12 +548,11 @@ namespace Sensus.iPerl.NfcHandler
errorCode = MCI_TxRequest_RxResponse(RequestMessage.ToArray(), out ResponseMessage, timeoutMs);
if (errorCode != (byte) MCI_ErrorCodes.Success_No_error)
{
OnMessageEvent("Read Request:" + MCI_Protocol.GetMCIErrorMessage(errorCode));
return false;
}
if ((ResponseMessage[0] == STX) && (ResponseMessage[11] == ETX)
&& (ResponseMessage[1] == 0x07)
&& (ResponseMessage[2] == RX_ACK_PASSTHROUGH_MSG_ID || ResponseMessage[2] == RX_ACK_RESPONSE_MSG_ID) )
&& (ResponseMessage[2] == RX_ACK_RESPONSE_MSG_ID))
{
//Ack message received, not served the read request
errorCode = ResponseMessage[6]; // forward error message from meter
@ -456,7 +573,7 @@ namespace Sensus.iPerl.NfcHandler
byte[] RxCrcComputed = Crc.calcCRCfromMessage(ResponseMessage);
OnMessageEvent(Crc.commentCRC(RxCrcMeter, RxCrcComputed));
// OnMessageEvent(Crc.commentCRC(RxCrcMeter, RxCrcComputed));
if (!Crc.crc_do_match(RxCrcMeter, RxCrcComputed))
{
errorCode = (byte) MCI_ErrorCodes.MCI_Error_Host_MeterCRCDoesNotMatch;
@ -476,7 +593,6 @@ namespace Sensus.iPerl.NfcHandler
{
outBuffer[i] = (ResponseMessage[6 + i]);
}
OnMessageEvent("Read Request Response: " + Tools.BytesToHex(ResponseMessage));
if (IsValidStruct(StName))
@ -505,7 +621,6 @@ namespace Sensus.iPerl.NfcHandler
if (!_ST25DV_Device.ST25DV_ReadMailboxControlReg(out MB_Ctrl_Reg_Value))
{
OnMessageEvent("NFC DLL Error: MB CTRL Reg read (1) failed");
MCI_CycleResponseMsgTimeoutFlag = false;
stopReqResCycleTimeoutTimer();
return (byte) MCI_ErrorCodes.MCI_Error_Host_MB_CTRL_Reg_Read1;
@ -513,10 +628,10 @@ namespace Sensus.iPerl.NfcHandler
//Mailbox enable/disable check, proceed further only if enabled
if ((MB_Ctrl_Reg_Value & 0x01) == 0x00)
{
OnMessageEvent("NFC DLL Error: MB feature (1) disabled");
MCI_CycleResponseMsgTimeoutFlag = false;
stopReqResCycleTimeoutTimer();
return (byte)MCI_ErrorCodes.MCI_Error_Host_MB_disabled1;
stopReqResCycleTimeoutTimer();
OnMessageEvent(">> REMARK: Check if Metorlogy firmware-version is at least: 5.1.24 <<");
return (byte)MCI_ErrorCodes.MCI_Error_Host_MB_disabled1;
}
//Checking iPERL previous message is in mailbox or not, if present then read it and return failure
if ((MB_Ctrl_Reg_Value & 0x02) == 0x02)
@ -525,7 +640,6 @@ namespace Sensus.iPerl.NfcHandler
OnMessageEvent("NFC DLL Error: Previous message not read, reading now !");
if (!_ST25DV_Device.ST25DV_ReadMailboxMessageLength(out MB_LEN_Dyn_Register))
{
OnMessageEvent("NFC DLL Error: MB LEN Reg read (1) failed");
returnError = (byte)MCI_ErrorCodes.MCI_Error_Host_MB_LEN_Reg_read1;
}
else
@ -533,7 +647,6 @@ namespace Sensus.iPerl.NfcHandler
OnMessageEvent("NFC DLL Error: Previous message length " + MB_LEN_Dyn_Register);
if (!_ST25DV_Device.ST25DV_ReadMessage(MB_LEN_Dyn_Register, out responseMsg))
{
OnMessageEvent("NFC DLL Error: MB message read (1) failed");
returnError = (byte)MCI_ErrorCodes.MCI_Error_Host_MB_msg_read1;
}
else
@ -551,7 +664,7 @@ namespace Sensus.iPerl.NfcHandler
//Checking previous app message is in mailbox or not, if present then return failure !
if ((MB_Ctrl_Reg_Value & 0x04) == 0x04)
{
OnMessageEvent("NFC DLL Error: Previous sent request is not read by iPERL. So, present request will not be sent, retry again !");
// Previous sent request is not read by iPERL
MCI_CycleResponseMsgTimeoutFlag = false;
stopReqResCycleTimeoutTimer();
return (byte)MCI_ErrorCodes.MCI_Error_Host_req_not_read_by_iperl;
@ -563,7 +676,6 @@ namespace Sensus.iPerl.NfcHandler
{
if (!_ST25DV_Device.ST25DV_ReadMailboxControlReg(out MB_Ctrl_Reg_Value))
{
OnMessageEvent("NFC DLL Error: MB CTRL Reg read (2) failed");
MCI_CycleResponseMsgTimeoutFlag = false;
stopReqResCycleTimeoutTimer();
return (byte)MCI_ErrorCodes.MCI_Error_Host_MB_CTRL_Reg_Read2;
@ -571,7 +683,6 @@ namespace Sensus.iPerl.NfcHandler
//Mailbox enable/disable check, proceed further only if enabled
if ((MB_Ctrl_Reg_Value & 0x01) == 0x00)
{
OnMessageEvent("NFC DLL Error: MB feature (2) disabled");
MCI_CycleResponseMsgTimeoutFlag = false;
stopReqResCycleTimeoutTimer();
return (byte)MCI_ErrorCodes.MCI_Error_Host_MB_disabled2;
@ -582,7 +693,6 @@ namespace Sensus.iPerl.NfcHandler
{
if (!_ST25DV_Device.ST25DV_ReadMailboxMessageLength(out MB_LEN_Dyn_Register))
{
OnMessageEvent("NFC DLL Error: MB LEN Reg read (2) failed");
MCI_CycleResponseMsgTimeoutFlag = false;
stopReqResCycleTimeoutTimer();
return (byte)MCI_ErrorCodes.MCI_Error_Host_MB_LEN_Reg_read2;
@ -591,7 +701,6 @@ namespace Sensus.iPerl.NfcHandler
{
if (!_ST25DV_Device.ST25DV_ReadMessage(MB_LEN_Dyn_Register, out responseMsg))
{
OnMessageEvent("NFC DLL Error: MB message read (2) failed");
MCI_CycleResponseMsgTimeoutFlag = false;
stopReqResCycleTimeoutTimer();
return (byte)MCI_ErrorCodes.MCI_Error_Host_MB_msg_read2;
@ -609,7 +718,6 @@ namespace Sensus.iPerl.NfcHandler
//Checking timeout occured or not
if(MCI_CycleResponseMsgTimeoutFlag)
{
OnMessageEvent("NFC DLL Error: Timeout");
MCI_CycleResponseMsgTimeoutFlag = false;
stopReqResCycleTimeoutTimer();
return (byte)MCI_ErrorCodes.MCI_Error_Host_Timeout;
@ -618,7 +726,6 @@ namespace Sensus.iPerl.NfcHandler
}
else
{
OnMessageEvent("NFC DLL Error: MB Msg write failed");
MCI_CycleResponseMsgTimeoutFlag = false;
stopReqResCycleTimeoutTimer();
return (byte)MCI_ErrorCodes.MCI_Error_Host_msg_write;

View File

@ -1,7 +1,8 @@
using System;
using System.IO.Ports;
using System.Diagnostics;
using System.Text;
using System.Threading;
//*****************************************************************************
// Copyright 2020 Sensus GmbH Ludwigshafen. All rights reserved.
@ -12,6 +13,8 @@ namespace Sensus.iPerl.NfcHandler
{
public sealed class NfcDataHandler
{
private string _ComPort = "";
private readonly byte[] readCommand = { 0x80, 0x08, 0x00, 0x03, 0x00, 0x00 };
public SERIAL_Driver _SERIAL_Driver;
public SERIAL_Driver _SERIAL_Driver_Head_Config;
@ -27,8 +30,6 @@ namespace Sensus.iPerl.NfcHandler
public event DelNfcMessageHandler MessageEvent;
private string _ComPort = "";
public NfcDataHandler()
{
_SERIAL_Driver = new SERIAL_Driver();
@ -37,14 +38,14 @@ namespace Sensus.iPerl.NfcHandler
_ST25DV_Device = new ST25DV_Device(_CR95HF_Reader);
_MCI_Protocol = new MCI_Protocol(_ST25DV_Device);
_NFCHead_Config = new NFCHeadConfig(_SERIAL_Driver_Head_Config);
LastErrorCode = 0;
LastErrorCode = 0;
}
public bool OpenConnection(string comport, int baudrate, int databits, Parity parity, StopBits stopbits)
{
_ComPort = comport;
bool isopen = _SERIAL_Driver.OpenConnection(comport, baudrate, databits, parity, stopbits);
if(!isopen)OnMessageEvent(_SERIAL_Driver.ErrorMessage);
if (!isopen) OnMessageEvent(_SERIAL_Driver.ErrorMessage);
return isopen;
}
@ -75,7 +76,7 @@ namespace Sensus.iPerl.NfcHandler
OnMessageEvent(comport + "......... Already in use ");
return false;
}
bool isopen = _SERIAL_Driver_Head_Config.OpenConnection(comport, 9600, 8, Parity.None, StopBits.Two);
OnMessageEvent(_SERIAL_Driver_Head_Config.ErrorMessage);
return isopen;
@ -140,7 +141,7 @@ namespace Sensus.iPerl.NfcHandler
public bool ConnectDevice()
{
byte[] responseData;
if (_CR95HF_Reader.CR95HF_RFProtocolOn())
{
if (GetSystemInfo())
@ -188,7 +189,7 @@ namespace Sensus.iPerl.NfcHandler
OnMessageEvent(ex.Message);
}
return false;
}
}
public bool ST25DV_ReadSingleBlock(byte blockNumber, out byte[] outBuffer)
{
@ -256,18 +257,17 @@ namespace Sensus.iPerl.NfcHandler
if (!worked)
{
SetLastErrorMesage();
ST25DV_MailboxCommStop();
return false;
}
return ST25DV_MailboxCommStop();
return true;
}
return false;
}
// This function-header is needed for calls to the DLL without need for using enums.
// In python 3.11 the module pythonnet (v3.x) does not support casting 'int' to 'enum' aynmore,
// so this workaround is needed.
public bool MCI_Write_pythonwrapper_enum(int STIndex, ushort offset, byte payloadlength, byte[] payload, int timeoutMs)
// This function-header is needed for calls to the DLL without need for using enums.
// In python 3.11 the module pythonnet (v3.x) does not support casting 'int' to 'enum' aynmore,
// so this workaround is needed.
public bool MCI_Write_pythonwrapper_enum(int STIndex, ushort offset, byte payloadlength, byte[] payload, int timeoutMs)
{
return MCI_Write((MCI_Protocol.StructName)STIndex, offset, payloadlength, payload, timeoutMs);
}
@ -284,140 +284,74 @@ namespace Sensus.iPerl.NfcHandler
if (!ans)
{
SetLastErrorMesage();
ST25DV_MailboxCommStop();
return false;
}
return ST25DV_MailboxCommStop();
return true;
}
return false;
}
public bool MCI_Read(byte msgId, ushort offset, byte payloadlength, int timeoutMs)
public bool MCI_Write_Read(MCI_Protocol.StructName StName, ushort offset, byte payloadlength, byte[] payload, int timeoutMs)
{
LastErrorMessage = string.Empty;
LastData = null;
byte[] response;
byte errorCode = 0;
if (ST25DV_MailboxCommStart())
{
bool ans = _MCI_Protocol.MCI_Read((MCI_Protocol.StructName) msgId, offset, payloadlength, timeoutMs,
out response, out errorCode);
bool ans = _MCI_Protocol.MCI_Write_Read(StName, offset, payloadlength, payload, out response, timeoutMs, out errorCode);
LastErrorCode = errorCode;
LastData = response;
if (!ans)
{
SetLastErrorMesage();
ST25DV_MailboxCommStop();
return false;
}
return ST25DV_MailboxCommStop();
}
return false;
}
public bool MCI_Write(byte msgId, ushort offset, byte payloadlength, byte[] payload, int timeoutMs)
{
LastErrorMessage = string.Empty;
LastData = null;
byte errorCode = 0;
if (ST25DV_MailboxCommStart())
{
bool ans = _MCI_Protocol.MCI_Write((MCI_Protocol.StructName) msgId, offset, payloadlength, payload,
timeoutMs, out errorCode);
LastErrorCode = errorCode;
if (!ans)
{
SetLastErrorMesage();
ST25DV_MailboxCommStop();
return false;
}
return ST25DV_MailboxCommStop();
return true;
}
return false;
}
private bool ST25DV_MailboxCommStart()
{
bool success = false;
byte[] EepromBlockRead = { 0, 0, 0, 0 };
byte[] EepromBlockWrite = { 0, 0, 0, 0 };
//Byte-2 in block-2 represent the EEPROM I2C interface status ->
//0xA5-EEPROM I2C Interface Idle, 0x5A-EEPROM I2C Interface Active
success = _ST25DV_Device.ST25DV_ReadSingleBlock(2, out EepromBlockRead, false);
if (success)
// wake up the ST25DV by setting the GPO pin to output a pulse -> INT on Metro (set highest bit to one -> causes a pulse on GPO)
if (_ST25DV_Device.ST25DV_WriteGPOManageCommand(_ST25DV_Device.GPO_MANAGE_SET_PULSE, false))
{
if (EepromBlockRead[1] == 0xA5) //0xA5-EEPROM I2C Interface Idle
{
//Byte-1 in block-64 represent the Mailbox RF interface status ->
//0xA5-Mailbox RF Interface Idle, 0x5A-Mailbox RF Interface Active
EepromBlockWrite[0] = 0x5A; //Raising Mailbox RF interface Active flag to avoid collisions with host interface
success = _ST25DV_Device.ST25DV_WriteSingleBlock(64, EepromBlockWrite, false);
if (success)
{
//Sets 0x01 (MB_EN) in the register (MB_CTRL_Dyn) with address 0x0D
if (_ST25DV_Device.ST25DV_WriteDynamicConfiguration(0x0D, 0x01, false))
{
return true; //With this we proceed for mailbox communication with ST25
}
else
{
LastErrorCode = 0x08; //MCI Error: Unidentified
LastErrorMessage = "MB_CTRL_Dyn writing failed(ST25DV_MailboxCommStart), try again";
return false;
}
}
else
{
LastErrorCode = 0x08; //MCI Error: Unidentified
LastErrorMessage = "Mailbox RF interface status writing failed(ST25DV_MailboxCommStart), try again";
return false;
}
}
else
{
LastErrorCode = 0x08; //MCI Error: Unidentified
LastErrorMessage = "EEPROM interface busy(ST25DV_MailboxCommStart), try again";
return false;
}
Thread.Sleep(10); // wait 10ms to give metro some time
byte MB_Ctrl_Reg_Value = 0x00;
for (int i = 0; i < 20; i++) // do 20 retries max (20 times 100ms = 2sec, which should be more than enough)
{
if (_ST25DV_Device.ST25DV_ReadMailboxControlReg(out MB_Ctrl_Reg_Value))
{
if ((MB_Ctrl_Reg_Value & 0x01) == 0x01)
{
return true; //With this we proceed for mailbox communication with ST25
}
else
{
Thread.Sleep(100); // wait 100ms, then try again
LastErrorMessage = "Mailbox was not activated by Firmware (ST25DV_MailboxCommStart), try again";
}
}
else
{
Thread.Sleep(100); // wait 100ms, then try again
LastErrorMessage = "Mailbox state could not be read (ST25DV_MailboxCommStart), try again";
}
}
LastErrorCode = 0x08; //MCI Error: Unidentified
OnMessageEvent(">> REMARK: Check if Metorlogy firmware-version is at least: 5.1.24 <<");
return false;
}
else
{
LastErrorCode = 0x08; //MCI Error: Unidentified
LastErrorMessage = "EEPROM interface status reading failed(ST25DV_MailboxCommStart), try again";
LastErrorMessage = "GPO config writing failed(ST25DV_MailboxCommStart), try again";
return false;
}
}
private bool ST25DV_MailboxCommStop()
{
bool success = false;
byte[] EepromBlockWrite = { 0, 0, 0, 0 };
//Sets 0x00 (MB_EN) in the register (MB_CTRL_Dyn) with address 0x0D
if (_ST25DV_Device.ST25DV_WriteDynamicConfiguration(0x0D, 0x00, false))
{
//Byte-1 in block-64 represent the Mailbox RF interface status ->
//0xA5-Mailbox RF Interface Idle, 0x5A-Mailbox RF Interface Active
EepromBlockWrite[0] = 0xA5; //Raising Mailbox RF interface Idle flag to avoid collisions with host interface
success = _ST25DV_Device.ST25DV_WriteSingleBlock(64, EepromBlockWrite, false);
if (success)
{
return true; //With this we proceed for interpreting the communication happened with ST25
}
else
{
LastErrorCode = 0x08; //MCI Error: Unidentified
LastErrorMessage = "Mailbox RF interface status writing failed(ST25DV_MailboxCommStop), try again";
return false;
}
}
else
{
LastErrorCode = 0x08; //MCI Error: Unidentified
LastErrorMessage = "MB_CTRL_Dyn writing failed(ST25DV_MailboxCommStop), try again";
return false;
}
}
private void SetLastErrorMesage()
{
@ -430,7 +364,7 @@ namespace Sensus.iPerl.NfcHandler
LastErrorMessage = "MCI Error: The Errorcode '" + LastErrorCode as string +
"' couldn't be converted to string with the enum MCI_ErrorCodes!";
}
}
public bool NFCHeadConfig_PulseLedOutputEnable()
@ -480,7 +414,7 @@ namespace Sensus.iPerl.NfcHandler
try
{
if ( (!MCI_Write(MCI_Protocol.StructName.NfcSecurity, offset, payloadLength, payload, timeoutMs)) || (LastErrorCode != 0x00))
if ((!MCI_Write(MCI_Protocol.StructName.NfcSecurity, offset, payloadLength, payload, timeoutMs)) || (LastErrorCode != 0x00))
{
return false;
}
@ -492,11 +426,68 @@ namespace Sensus.iPerl.NfcHandler
return true; // true - success, false - failed
}
public string NFCSecurity_Read_EndpointId(int timeoutMs)
{
string result = string.Empty;
byte[] payload = readCommand;
byte payloadLength = Convert.ToByte(payload.Length);
ushort offset = 0;
try
{
if ((!MCI_Write_Read(MCI_Protocol.StructName.NfcSecurity, offset, payloadLength, payload, timeoutMs)) || (LastErrorCode != 0x00))
{
return string.Empty;
}
}
catch (Exception ex)
{
OnMessageEvent(ex.Message);
return string.Empty;
}
//Check response header
if (LastData[0] != 0x05 || LastData[1] != 0x00)
{
LastErrorMessage = "Wrong response header";
return string.Empty;
}
//Check length byte
if (LastData[2] == 0x00)
{
LastErrorMessage = "Response length is 0";
return string.Empty;
}
//Check length of message
int lengthMessage = LastData[2] + 3; // two header bytes and one length byte
if (LastData.Length != lengthMessage)
{
LastErrorMessage = "Response length is wrong";
return string.Empty;
}
//Check identifier for information
if (LastData[3] != 0x00 || LastData[4] != 0x00)
{
LastErrorMessage = "Wrong identifier";
return string.Empty;
}
int lengthEndpointId = LastData[2] - 2; //Identifier bytes
byte[] id = new byte[lengthEndpointId];
Array.Copy(LastData, 5, id, 0, lengthEndpointId);
result = Encoding.ASCII.GetString(id);
return result;
}
public byte NFCSecurity_ReadPrivilegeLevel(int timeoutMs)
{
ushort offset = 0;
byte payloadLength = 1;
byte payload = 4;
byte payload = 4;
try
{
if ((!MCI_Read(MCI_Protocol.StructName.NfcSecurity, offset, payloadLength, timeoutMs)) || (LastErrorCode != 0x00))
@ -520,7 +511,7 @@ namespace Sensus.iPerl.NfcHandler
{
ushort offset = 0;
byte payloadLength = 1;
byte [] payload = { 0x23 }; // 0x23 - Command code for 'NFC Security reset access level'
byte[] payload = { 0x23 }; // 0x23 - Command code for 'NFC Security reset access level'
try
{
@ -536,13 +527,11 @@ namespace Sensus.iPerl.NfcHandler
return true; // true - success, false - failed
}
public string GetDllVersion()
{
System.Reflection.Assembly assembly = System.Reflection.Assembly.GetExecutingAssembly();
FileVersionInfo fvi = FileVersionInfo.GetVersionInfo(assembly.Location);
string str = "NfcS5 DLL v" + fvi.FileVersion;
return str.Remove(str.Length - 2); // only show x.y.z version, hide 4th number
}
public string GetDllVersion()
{
Version dll_version = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version;
return "NfcS5 DLL v" + String.Format("{0}.{1}.{2}", dll_version.Major, dll_version.Minor, dll_version.Build); //, dll_version.MajorRevision);
}
#region Message Event
private void OnMessageEvent(string message)

View File

@ -22,8 +22,10 @@ namespace Sensus.iPerl.NfcHandler
private byte[] ST25DV_CMD_WRITE_DYNAMIC_CONFIG = { 0xAE, 0x02, 0x00, 0x00 }; //Command code, IC Mfg Code, Register address, register value to be written
private readonly byte[] ST25DV_CMD_READ_MAILBOX_CONTROL_REG = { 0xAD, 0x02, 0x0D }; //Command code, IC Mfg Code, MB_CTRL_Dyn Register address
private readonly byte[] ST25DV_CMD_READ_MAILBOX_MESSAGE_LENGTH = { 0xAB, 0x02 }; //Command code, IC Mfg Code
private byte[] ST25DV_CMD_READ_MESSAGE = { 0xAC, 0x02, 0x00, 0x00 }; //Command code, IC Mfg Code, Mailbox pointer(mostly this is 0), NumberofBytesToRead (this will be received from caller)
private byte[] ST25DV_CMD_READ_MESSAGE = { 0xAC, 0x02, 0x00, 0x00 }; //Command code, IC Mfg Code, Mailbox pointer(mostly this is 0), NumberofBytesToRead (this will be received from caller)
private byte[] ST25DV_CMD_MANAGE_GPO = { 0xA9, 0x02, 0x00 }; //Command code, IC Mfg Code, GPO value
public readonly byte GPO_MANAGE_SET_PULSE = 0x80; // Command code to set a pulse on the GPO pin (if enabled by FW in the Meter)
private CR95HF_Reader _CR95HF_Reader;
private System.Timers.Timer _CycleTimeoutTimer = new System.Timers.Timer();
@ -42,8 +44,8 @@ namespace Sensus.iPerl.NfcHandler
{0x15 , "The specified block is protected in read" }
};
public event DelNfc_ST25DV_MessageHandler MessageEvent;
public event DelNfc_ST25DV_MessageHandler MessageEvent;
public ST25DV_Device(CR95HF_Reader CR95HFReader)
{
_CR95HF_Reader = CR95HFReader;
@ -265,12 +267,39 @@ namespace Sensus.iPerl.NfcHandler
return false;
}
public bool ST25DV_WriteGPOManageCommand(byte regValue, bool logEnabled)
{
byte[] response = null;
ST25DV_CMD_MANAGE_GPO[2] = regValue;
if (_CR95HF_Reader.CR95HF_SendRecv(ST25DV_CMD_MANAGE_GPO, out response))
{
//Success - ResponseFlags = 0x00, success
//Error - ResponseFlags = 0x01, 1 byte error code
if (response[0] == 0x00)
{
if (logEnabled)
{
OnMessageEvent("Write GPO Manage: Success");
}
return true;
}
else
{
if ((response[0] == 0x01) && (ST25DV_ErrorCodes.ContainsKey(response[1])))
OnMessageEvent("Write GPO Manage: Failed with ST25DV error - " + ST25DV_ErrorCodes[response[1]]);
}
}
OnMessageEvent("Write GPO Manage: Failed with ST25DV Unidentified error");
return false;
}
public bool ST25DV_WriteDynamicConfiguration(byte regAddress, byte regValue, bool logEnabled)
{
byte[] response = null;
byte[] response = null;
ST25DV_CMD_WRITE_DYNAMIC_CONFIG[2] = regAddress;
ST25DV_CMD_WRITE_DYNAMIC_CONFIG[3] = regValue;
ST25DV_CMD_WRITE_DYNAMIC_CONFIG[3] = regValue;
if (_CR95HF_Reader.CR95HF_SendRecv(ST25DV_CMD_WRITE_DYNAMIC_CONFIG, out response))
{
//Success - ResponseFlags = 0x00, success
@ -365,14 +394,11 @@ namespace Sensus.iPerl.NfcHandler
{
outBuffer[i] = response[1 + i];
}
//OnMessageEvent("Read Message: " + Tools.ByteArrayToHexString(outBuffer));
OnMessageEvent("Read Message: " + Tools.BytesToHex(outBuffer));
return true;
}
else
{
if ((response[0] == 0x01) && (ST25DV_ErrorCodes.ContainsKey(response[1])))
OnMessageEvent("Read Message Failed: With ST25DV error - " + ST25DV_ErrorCodes[response[1]]);
}
if ((response[0] == 0x01) && ST25DV_ErrorCodes.ContainsKey(response[1]))
OnMessageEvent("Read Message Failed: With ST25DV error - " + ST25DV_ErrorCodes[response[1]]);
}
OnMessageEvent("Read Message Failed: With ST25DV Unidentified error");
return false;
@ -397,11 +423,8 @@ namespace Sensus.iPerl.NfcHandler
//OnMessageEvent("Write Message: " + Tools.ByteArrayToHexString(inBuffer));
return true;
}
else
{
if ((response[0] == 0x01) && (ST25DV_ErrorCodes.ContainsKey(response[1])))
OnMessageEvent("Write Message Failed: With ST25DV error - " + ST25DV_ErrorCodes[response[1]]);
}
if ((response[0] == 0x01) && ST25DV_ErrorCodes.ContainsKey(response[1]))
OnMessageEvent("Write Message Failed: With ST25DV error - " + ST25DV_ErrorCodes[response[1]]);
}
OnMessageEvent("Write Message Failed: With ST25DV Unidentified error");
return false;

View File

@ -11,6 +11,7 @@
<AssemblyName>NfcS5_DLL</AssemblyName>
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>

View File

@ -10,7 +10,7 @@ using System.Runtime.InteropServices;
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("NfcS5_DLL")]
[assembly: AssemblyCopyright("Copyright © 2022")]
[assembly: AssemblyCopyright("Copyright © 2024")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.14.0.0")]
[assembly: AssemblyFileVersion("1.14.0.0")]
[assembly: AssemblyVersion("1.18.0.0")]
[assembly: AssemblyFileVersion("1.18.0.0")]