123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516 |
- using Edge.Core.Parser;
- using Edge.Core.Parser.BinaryParser.Util;
- using Edge.Core.Processor;
- using Edge.Core.Processor.Communicator;
- using Edge.Core.Processor.Dispatcher.Attributes;
- using Edge.Core.UniversalApi;
- using Microsoft.Extensions.DependencyInjection;
- using Microsoft.Extensions.Logging;
- using Microsoft.Extensions.Logging.Abstractions;
- using ShengJu_CUT100_DES.MessageEntity.Incoming;
- using ShengJu_CUT100_DES.MessageEntity.Outgoing;
- using System;
- using System.Collections.Generic;
- using System.IO;
- using System.Linq;
- using System.Text;
- using System.Threading.Tasks;
- using System.Timers;
- using static ShengJu_CUT100_DES.MessageEntity.Outgoing.ModifyPredefinedFileKey;
- namespace ShengJu_CUT100_DES
- {
- /// <summary>
- /// at least at 2021.4, 这模块还不支持并线,因为模块内部并没有区分请求中的地址值。
- /// </summary>
- [MetaPartsRequired(typeof(HalfDuplexActivePollingDeviceProcessor<,>))]
- [MetaPartsRequired(typeof(ComPortCommunicator<>))]
- [MetaPartsRequired(typeof(TcpClientCommunicator<>))]
- [MetaPartsDescriptor(
- "lang-zh-cn:ShengJu CUT100_DES 感应卡读写卡模块lang-en-us:ShengJu CUT100_DES contactless card read&write module",
- "lang-zh-cn:用于驱动 盛炬CUT100_DES 感应卡读写卡模块, 波特率19200, None, 8, 1lang-en-us:Used for driven ShengJu CUT100_DES contactless card read&write module, BaudRate 19200, None, 8, 1",
- new[] { "lang-zh-cn:支付终端lang-en-us:Terminal" })]
- [UniversalApi(Name = GenericAlarm.UniversalApiEventName, EventDataType = typeof(GenericAlarm[]), Description = "Fire GenericAlarms to AlarmBar for attracting users.")]
- [UniversalApi(Name = OnCardTapEventName, EventDataType = typeof(object), Description = "Fired once a DesFire EV1 card detected by module and card UID is read")]
- public class GroupHandler : TestableActivePollingDeviceHandler<byte[], ShengJu_CUT100_DES.MessageEntity.MessageBase>
- {
- public const string OnCardTapEventName = "OnCardTap";
- public event EventHandler<ModuleStateChangeEventArg> OnModuleStateChange;
- public event EventHandler<CardTapEventArg> OnCardTap;
- private ILogger logger = NullLogger.Instance;
- private IServiceProvider services;
- protected IContext<byte[], MessageEntity.MessageBase> context;
- private DeviceConfigV1 deviceConfig;
- private IEnumerable<CardReaderModule> cardReaderModules;
- private const int singleModuleOfflineTimeThresholdByMs = 15000;
- //private Dictionary<byte, DateTime> boardsLastImcomingMsgReceivedTimes;
- private Timer singleModuleOfflineCheckTimer;
- [UniversalApi]
- public IEnumerable<CardReaderModule> CardReaderModuels => this.cardReaderModules;
- public class CardReaderModule
- {
- private ILogger logger = NullLogger.Instance;
- private IContext<byte[], MessageEntity.MessageBase> context;
- public enum CardReaderModuleStateEnum { Offline, Online }
- public string Name { get; set; }
- public string Description { get; set; }
- public byte PhysicalAddress { get; }
- public string HardwareFirmware { get; set; }
- public string UnderlyingCommunicatorIdentity { get; set; }
- public CardReaderModuleStateEnum ModuleState { get; set; }
- /// <summary>
- /// used for track the last received message which for caculate the offline state of this device.
- /// </summary>
- public DateTime? LastIncomingMessageReceivedTime { get; set; }
- internal CardReaderModule(byte physicalAddress, ILogger logger)
- {
- this.PhysicalAddress = physicalAddress;
- this.logger = logger;
- }
- internal void SetContext(IContext<byte[], MessageEntity.MessageBase> context)
- {
- this.context = context;
- }
- internal async Task<CardOperationResult> ReadCardUID(byte modulePhysicalAddress)
- {
- var readCardUidResponse = await this.context.Outgoing.WriteAsync(
- new ActivateATypeCardRequest() { ModulePhysicalAddress = modulePhysicalAddress },
- (_, testResponse) => testResponse.ModulePhysicalAddress == modulePhysicalAddress
- && (testResponse is GenericFailureResponse || testResponse is ActivateATypeCardResponse), 4000);
- if (readCardUidResponse is ActivateATypeCardResponse rp)
- {
- if (rp.UID.Any())
- return new CardOperationResult(200, rp.UID) { CardReaderModule = this };
- else
- return new CardOperationResult(404) { CardReaderModule = this, ModuleResultCode = "No UID was read" };
- }
- else if (readCardUidResponse is GenericFailureResponse failedResponse)
- {
- this.logger.LogInformation($"ReadCardUID failed with module code: {failedResponse.模块返回状态}, cpu code: {failedResponse.CpuCardState} for module with physical address: {failedResponse.ModulePhysicalAddress}");
- return new CardOperationResult(400) { CardReaderModule = this, ModuleResultCode = failedResponse.模块返回状态.ToString(), CpuCardResultCode = failedResponse.CpuCardState.ToString() };
- }
- else
- {
- this.logger.LogInformation($"ReadCardUID timed out for module (phyAdrs: {modulePhysicalAddress}, comm: {this.context.Communicator.Identity})");
- return new CardOperationResult(500) { CardReaderModule = this, ModuleResultCode = "Device response timed out" };
- }
- }
- internal async Task<CardOperationResult> FormatCardByResetToNewRootKeyAndBuildDefaultFileStructures(byte modulePhysicalAddress, byte[] oldRootKeyBytes, byte[] newRootKeyBytes)
- {
- if (oldRootKeyBytes == null || !oldRootKeyBytes.Any())
- throw new ArgumentException(nameof(oldRootKeyBytes));
- if (newRootKeyBytes == null || !newRootKeyBytes.Any())
- throw new ArgumentException(nameof(newRootKeyBytes));
- var formatCardResponse = await this.context.Outgoing.WriteAsync(
- new FormatCardRequest(oldRootKeyBytes, newRootKeyBytes) { ModulePhysicalAddress = modulePhysicalAddress },
- (_, testResponse) => testResponse.ModulePhysicalAddress == modulePhysicalAddress
- && (testResponse is GenericFailureResponse || testResponse is GenericSuccessResponse), 4000);
- if (formatCardResponse is GenericSuccessResponse)
- {
- this.logger.LogInformation($"Format Card successfully on module (phyAdrs: {modulePhysicalAddress}, comm: {this.context.Communicator.Identity}), will auto re-read card app dirs...");
- var readAppDirsResponse = await this.context.Outgoing.WriteAsync(
- new ReadAppDirsRequest(newRootKeyBytes) { ModulePhysicalAddress = modulePhysicalAddress },
- (_, testResponse) => testResponse.ModulePhysicalAddress == modulePhysicalAddress && (testResponse is GenericFailureResponse || testResponse is ReadAppDirsResponse), 4000);
- if (readAppDirsResponse is ReadAppDirsResponse successReadAppDirsResponse)
- {
- this.logger.LogInformation($" Read Card AppDirs, count: {successReadAppDirsResponse.DirCount}, " +
- $"dirIds: {successReadAppDirsResponse.DirIds.Select(did => did.Select(i => i.ToString("X2")).Aggregate("0x", (acc, n) => acc + " " + n)).Aggregate((acc, n) => acc + ", " + n)} " +
- $"on module (phyAdrs: {successReadAppDirsResponse.ModulePhysicalAddress}, comm: {this.context.Communicator.Identity})");
- }
- else if (readAppDirsResponse is GenericFailureResponse failedReadAppDirsResponse)
- {
- this.logger.LogInformation($" Read Card AppDirs failed with module code: {failedReadAppDirsResponse.模块返回状态}, cpu code: {failedReadAppDirsResponse.CpuCardState} for module (phyAdrs: {failedReadAppDirsResponse.ModulePhysicalAddress}, comm: {this.context.Communicator.Identity})");
- }
- else
- {
- this.logger.LogInformation($" Read Card AppDirs timed out for module (phyAdrs: {modulePhysicalAddress}, comm: {this.context.Communicator.Identity})");
- }
- return new CardOperationResult(200) { CardReaderModule = this };
- }
- else if (formatCardResponse is GenericFailureResponse failedFormatCardResponse)
- {
- this.logger.LogInformation($"Format Card failed with module code: {failedFormatCardResponse.模块返回状态}, cpu code: {failedFormatCardResponse.CpuCardState} for module with physical address: {failedFormatCardResponse.ModulePhysicalAddress}");
- return new CardOperationResult(400) { CardReaderModule = this, ModuleResultCode = failedFormatCardResponse.模块返回状态.ToString(), CpuCardResultCode = failedFormatCardResponse.CpuCardState.ToString() };
- }
- else
- {
- this.logger.LogInformation($"Format Card timed out for module with physical address: {modulePhysicalAddress}");
- return new CardOperationResult(500) { CardReaderModule = this, ModuleResultCode = "Device response timed out" };
- }
- }
- internal async Task<CardOperationResult> WriteCard(byte modulePhysicalAddress, byte fileId, byte blockAddress, byte[] dataBytes, byte[] writeKeyBytes)
- {
- if (writeKeyBytes == null || !writeKeyBytes.Any())
- throw new ArgumentException(nameof(writeKeyBytes));
- var writeAppFileRequestResponse = await this.context.Outgoing.WriteAsync(
- new WriteAppFileRequest(fileId, blockAddress, writeKeyBytes, dataBytes) { ModulePhysicalAddress = modulePhysicalAddress },
- (_, testResponse) => testResponse.ModulePhysicalAddress == modulePhysicalAddress
- && (testResponse is GenericFailureResponse || testResponse is GenericSuccessResponse), 4000);
- if (writeAppFileRequestResponse is GenericSuccessResponse successResponse)
- {
- return new CardOperationResult(200) { CardReaderModule = this };
- }
- else if (writeAppFileRequestResponse is GenericFailureResponse failedResponse)
- {
- this.logger.LogInformation($"Write Card failed with module code: {failedResponse.模块返回状态}, cpu code: {failedResponse.CpuCardState} for module with physical address: {failedResponse.ModulePhysicalAddress}");
- return new CardOperationResult(400) { CardReaderModule = this, ModuleResultCode = failedResponse.模块返回状态.ToString(), CpuCardResultCode = failedResponse.CpuCardState.ToString() };
- }
- else
- {
- this.logger.LogInformation($"Write Card timed out for module (phyAdrs: {modulePhysicalAddress}, comm: {this.context.Communicator.Identity})");
- return new CardOperationResult(500) { CardReaderModule = this, ModuleResultCode = "Device response timed out" };
- }
- }
- internal async Task<CardOperationResult> ReadCard(byte modulePhysicalAddress, byte fileId, byte blockAddress, byte[] readKeyBytes)
- {
- if (readKeyBytes == null || !readKeyBytes.Any())
- throw new ArgumentException(nameof(readKeyBytes));
- var readAppFileRequestResponse = await this.context.Outgoing.WriteAsync(
- new ReadAppFileRequest(fileId, blockAddress, readKeyBytes) { ModulePhysicalAddress = modulePhysicalAddress },
- (_, testResponse) => testResponse.ModulePhysicalAddress == modulePhysicalAddress
- && (testResponse is GenericFailureResponse || testResponse is ReadAppFileResponse), 4000);
- if (readAppFileRequestResponse is ReadAppFileResponse successResponse)
- {
- return new CardOperationResult(200, successResponse.Data) { CardReaderModule = this };
- }
- else if (readAppFileRequestResponse is GenericFailureResponse failedResponse)
- {
- this.logger.LogInformation($"Read Card failed with module code: {failedResponse.模块返回状态}, cpu code: {failedResponse.CpuCardState} for module with physical address: {failedResponse.ModulePhysicalAddress}");
- if (failedResponse.模块返回状态 == MessageEntity.IncomingMessageBase.ModuleStateEnum.读取CPU卡文件失败)
- return new CardOperationResult(400) { CardReaderModule = this, ModuleResultCode = failedResponse.模块返回状态.ToString() + ", 请保持卡片靠近读卡器", CpuCardResultCode = failedResponse.CpuCardState.ToString() };
- else
- return new CardOperationResult(400) { CardReaderModule = this, ModuleResultCode = failedResponse.模块返回状态.ToString(), CpuCardResultCode = failedResponse.CpuCardState.ToString() };
- }
- else
- {
- this.logger.LogInformation($"Read Card timed out for module (phyAdrs: {modulePhysicalAddress}, comm: {this.context.Communicator.Identity})");
- return new CardOperationResult(500) { CardReaderModule = this, ModuleResultCode = "与读卡器通讯超时" };
- }
- }
- internal async Task<CardOperationResult> ModifyPredefinedFileKey(byte modulePhysicalAddress, PredefinedFileKeyTypeEnum fileKeyType, byte[] oldKeyBytes, byte[] newKeyBytes)
- {
- if (oldKeyBytes == null || !oldKeyBytes.Any())
- throw new ArgumentException(nameof(oldKeyBytes));
- if (newKeyBytes == null || !newKeyBytes.Any())
- throw new ArgumentException(nameof(newKeyBytes));
- var modifyPredefinedFileKeyResponse = await this.context.Outgoing.WriteAsync(
- new ModifyPredefinedFileKey(fileKeyType, oldKeyBytes, newKeyBytes) { ModulePhysicalAddress = modulePhysicalAddress },
- (_, testResponse) => testResponse.ModulePhysicalAddress == modulePhysicalAddress
- && (testResponse is GenericFailureResponse || testResponse is GenericSuccessResponse), 4000);
- if (modifyPredefinedFileKeyResponse is GenericSuccessResponse successResponse)
- {
- return new CardOperationResult(200) { CardReaderModule = this };
- }
- else if (modifyPredefinedFileKeyResponse is GenericFailureResponse failedResponse)
- {
- this.logger.LogInformation($"Modify Predefined FileKey failed with module code: {failedResponse.模块返回状态}, cpu code: {failedResponse.CpuCardState} for module with physical address: {failedResponse.ModulePhysicalAddress}");
- return new CardOperationResult(400) { CardReaderModule = this, ModuleResultCode = failedResponse.模块返回状态.ToString(), CpuCardResultCode = failedResponse.CpuCardState.ToString() };
- }
- else
- {
- this.logger.LogInformation($"Modify Predefined FileKey timed out for module (phyAdrs: {modulePhysicalAddress}, comm: {this.context.Communicator.Identity})");
- return new CardOperationResult(500) { CardReaderModule = this, ModuleResultCode = "Device response timed out" };
- }
- }
- }
- public class CardOperationResult
- {
- public CardOperationResult(int overallResultCode, byte[] data)
- {
- this.OverallResultCode = overallResultCode;
- if (data != null && data.Any())
- {
- this.Data = data.Select(b => (int)b).ToArray();
- this.PrettyUTF8DecodedData = Encoding.UTF8.GetString(data);
- this.PrettyHexStrData = "0x" + data.ToHexLogString();
- }
- }
- public CardOperationResult(int overallResultCode) : this(overallResultCode, null)
- {
- }
- public int OverallResultCode { get; set; }
- public string ModuleResultCode { get; set; }
- public string CpuCardResultCode { get; set; }
- public CardReaderModule CardReaderModule { get; set; }
- /// <summary>
- /// for better serialize, here use int instead of byte.
- /// </summary>
- public int[] Data { get; }
- public string PrettyUTF8DecodedData { get; }
- /// <summary>
- /// like: 0x11 22 33 44
- /// </summary>
- public string PrettyHexStrData { get; }
- }
- #region device config
- public class CardReaderModuleConfigV1
- {
- public byte PhysicalAddress { get; set; }
- /// <summary>
- /// a meaningful name is required, and must be global unique
- /// </summary>
- public string Name { get; set; }
- public string Description { get; set; }
- }
- public class DeviceConfigV1
- {
- public List<CardReaderModuleConfigV1> CardReaderModuleConfigs { get; set; }
- }
- #endregion
- public GroupHandler(DeviceConfigV1 deviceConfig, IServiceProvider services)
- {
- this.services = services;
- var loggerFactory = services.GetRequiredService<ILoggerFactory>();
- this.logger = loggerFactory.CreateLogger("DynamicPrivate_ShengJu_CUT100_DES");
- if (deviceConfig.CardReaderModuleConfigs.Select(mc => mc.PhysicalAddress).GroupBy(pa => pa).Any(g => g.Count() >= 2))
- throw new ArgumentException("Duplicated PhysicalAddress for moduels were found, please make sure they're unique per comm channel");
- if (deviceConfig.CardReaderModuleConfigs.Select(mc => mc.Name).GroupBy(pa => pa).Any(g => g.Count() >= 2))
- throw new ArgumentException("Duplicated card module name were found, card module name is essential for tell the usage of it, please make sure they're unique");
- this.deviceConfig = deviceConfig;
- this.cardReaderModules = deviceConfig.CardReaderModuleConfigs.Select(mc => new CardReaderModule(mc.PhysicalAddress, this.logger)
- {
- Name = mc.Name,
- Description = mc.Description,
- ModuleState = CardReaderModule.CardReaderModuleStateEnum.Offline,
- }).ToList();
- }
- public override void Init(IContext<byte[], MessageEntity.MessageBase> context)
- {
- base.Init(context);
- this.context = context;
- this.context.Communicator.OnConnected += (sender, e) => { };
- this.context.Communicator.OnDisconnected += (sender, e) => { };
- foreach (var m in this.cardReaderModules)
- {
- m.SetContext(context);
- m.UnderlyingCommunicatorIdentity = this.context.Communicator.Identity;
- };
- //accuracy is 1000ms
- this.singleModuleOfflineCheckTimer = new Timer(1000);
- this.singleModuleOfflineCheckTimer.Elapsed += async (a, b) =>
- {
- var offlineModules = this.cardReaderModules.Where(b => DateTime.Now.Subtract(b.LastIncomingMessageReceivedTime ?? DateTime.MinValue).TotalMilliseconds >= singleModuleOfflineTimeThresholdByMs);
- foreach (var om in offlineModules)
- {
- if (om.ModuleState == CardReaderModule.CardReaderModuleStateEnum.Offline) continue;
- om.ModuleState = CardReaderModule.CardReaderModuleStateEnum.Offline;
- this.OnModuleStateChange?.Invoke(this, new ModuleStateChangeEventArg(om));
- var universalApiHub = this.services.GetRequiredService<UniversalApiHub>();
- await universalApiHub.FireEvent(this.context.Processor, GenericAlarm.UniversalApiEventName,
- new GenericAlarm[] {
- new GenericAlarm()
- {
- Category = $"单块读卡器模块通讯断开",
- Title = $"单块读卡器模块通讯断开",
- Detail = $"单块读卡器模块通讯断开, Module: {om.Name??""} with address: {om.PhysicalAddress}",
- Severity = GenericAlarmSeverity.Warning
- } });
- }
- };
- this.singleModuleOfflineCheckTimer.Start();
- var activePollingOutgoing =
- this.context.Outgoing as TimeWindowWithActivePollingOutgoing<byte[], MessageEntity.MessageBase>;
- int prePolledIndex = 0;
- activePollingOutgoing.PollingMsgProducer = () =>
- {
- var poll = new ActivateATypeCardRequest();
- poll.ModulePhysicalAddress = this.deviceConfig.CardReaderModuleConfigs[prePolledIndex].PhysicalAddress;
- prePolledIndex++;
- if (prePolledIndex == this.deviceConfig.CardReaderModuleConfigs.Count)
- prePolledIndex = 0;
- return poll;
- };
- this.context.Incoming.LongTimeNoSeeMessageTimeout = 12000;
- this.context.Incoming.OnLongTimeNoSeeMessage += async (a, b) =>
- {
- this.logger.LogInformation("ShengJu_CUT100_DES group is offline due to long time no see msg incoming");
- foreach (var m in this.CardReaderModuels)
- m.ModuleState = CardReaderModule.CardReaderModuleStateEnum.Offline;
- this.OnModuleStateChange?.Invoke(this, new ModuleStateChangeEventArg(this.cardReaderModules));
- var universalApiHub = this.services.GetRequiredService<UniversalApiHub>();
- await universalApiHub?.FireEvent(this.context.Processor, GenericAlarm.UniversalApiEventName, new[] {
- new GenericAlarm() {
- Title = "同一通讯组中的多个(如有)读卡器模块均离线",
- Detail=this.deviceConfig.CardReaderModuleConfigs.Select(mc=>$"Module: {mc.Name??""} with address: {mc.PhysicalAddress}").Aggregate("",(acc,n)=>acc+", "+n)+" are offline."
- } });
- };
- #region Load keys
- //this.blankCardDefaultRootKey = Enumerable.Repeat<byte>(0x00, 16).ToArray();
- //this.newRootKey = Enumerable.Repeat<byte>(0x11, 16).ToArray();
- //this.file1DefaultReadKey = Enumerable.Repeat<byte>(0x00, 16).ToArray();
- //this.file1DefaultWriteKey = Enumerable.Repeat<byte>(0x00, 16).ToArray();
- #endregion
- }
- public override async Task Process(IContext<byte[], MessageEntity.MessageBase> context)
- {
- if (!(this.cardReaderModules.FirstOrDefault(b => b.PhysicalAddress == context.Incoming.Message.ModulePhysicalAddress) is CardReaderModule operatingModule))
- {
- this.logger.LogInformation($"Could not find local defined module with physical address: {context.Incoming.Message.ModulePhysicalAddress}, please define it in device config, now will ignore this incoming device message");
- return;
- }
- operatingModule.LastIncomingMessageReceivedTime = DateTime.Now;
- if (operatingModule.ModuleState == CardReaderModule.CardReaderModuleStateEnum.Offline)
- {
- operatingModule.ModuleState = CardReaderModule.CardReaderModuleStateEnum.Online;
- var readModuleInfoResponse = await this.context.Outgoing.WriteAsync(
- new ReadModuleInfoRequest() { ModulePhysicalAddress = operatingModule.PhysicalAddress },
- (_, testResponse) => testResponse.ModulePhysicalAddress == operatingModule.PhysicalAddress && (testResponse is GenericFailureResponse || testResponse is ReadModuleInfoResponse), 4000);
- if (readModuleInfoResponse is ReadModuleInfoResponse successReadModuleInfoResponse)
- {
- operatingModule.HardwareFirmware = successReadModuleInfoResponse.ModelAndVersion;
- this.logger.LogInformation($"Module (phyAdrs: {operatingModule.PhysicalAddress}, comm: {operatingModule.UnderlyingCommunicatorIdentity}) is online, read module Info: {successReadModuleInfoResponse.ModelAndVersion}");
- }
- else if (readModuleInfoResponse is GenericFailureResponse failedReadModuleInfoResponse)
- {
- this.logger.LogInformation($"Module (phyAdrs: {operatingModule.PhysicalAddress}, comm: {operatingModule.UnderlyingCommunicatorIdentity}) is online, but read module info failed due to response: {failedReadModuleInfoResponse.模块返回状态}");
- }
- else
- {
- this.logger.LogInformation($"Module (phyAdrs: {operatingModule.PhysicalAddress}, comm: {operatingModule.UnderlyingCommunicatorIdentity}) is online, but read module info timed out");
- }
- this.OnModuleStateChange?.Invoke(this, new ModuleStateChangeEventArg(operatingModule));
- var universalApiHub = this.services.GetRequiredService<UniversalApiHub>();
- await universalApiHub.FireEvent(this.context.Processor, GenericAlarm.UniversalApiEventName,
- new GenericAlarm[] {
- new GenericAlarm()
- {
- Category = $"单块读卡器模块上线",
- Title = $"单块读卡器模块上线",
- Detail = $"单块读卡器模块上线, Module: {operatingModule.Name??""} with address: {operatingModule.PhysicalAddress} on comm: {operatingModule.UnderlyingCommunicatorIdentity}",
- Severity = GenericAlarmSeverity.Warning
- } });
- }
- if (context.Incoming.Message is ActivateATypeCardResponse activateATypeCardResponse && activateATypeCardResponse.UID.Any())
- {
- this.logger.LogDebug($"Card with UID: 0x{activateATypeCardResponse.UID.ToHexLogString()} is read on module (phyAdrs: {operatingModule.PhysicalAddress}, comm: {operatingModule.UnderlyingCommunicatorIdentity})");//, will auto read card app dirs...");
- this.OnCardTap?.Invoke(this, new CardTapEventArg(activateATypeCardResponse.UID, operatingModule));
- var universalApiHub = this.services.GetRequiredService<UniversalApiHub>();
- await universalApiHub?.FireEvent(this.context.Processor, OnCardTapEventName,
- new
- {
- Module = this.cardReaderModules.FirstOrDefault(b => b.PhysicalAddress == context.Incoming.Message.ModulePhysicalAddress),
- activateATypeCardResponse.UID
- });
- //var readAppDirsResponse = await this.context.Outgoing.WriteAsync(
- // new ReadAppDirsRequest(this.newRootKey) { ModulePhysicalAddress = md.PhysicalAddress },
- // (_, testResponse) => testResponse.ModulePhysicalAddress == md.PhysicalAddress && (testResponse is GenericFailureResponse || testResponse is ReadAppDirsResponse), 4000);
- //if (readAppDirsResponse is ReadAppDirsResponse successReadAppDirsResponse)
- //{
- // this.logger.LogInformation($" Read Card AppDirs, count: {successReadAppDirsResponse.DirCount}, " +
- // $"dirIds: {successReadAppDirsResponse.DirIds.Select(did => did.Select(i => i.ToString("X2")).Aggregate("0x", (acc, n) => acc + " " + n)).Aggregate((acc, n) => acc + ", " + n)} " +
- // $"for module with physical address: {successReadAppDirsResponse.ModulePhysicalAddress}");
- //}
- //else if (readAppDirsResponse is GenericFailureResponse failedReadAppDirsResponse)
- //{
- // this.logger.LogInformation($" Read Card AppDirs failed with module code: {failedReadAppDirsResponse.模块返回状态}, cpu code: {failedReadAppDirsResponse.CpuCardState} for module with physical address: {failedReadAppDirsResponse.ModulePhysicalAddress}");
- //}
- //else
- //{
- // this.logger.LogInformation($" Read Card AppDirs timed out for module with physical address: {md.PhysicalAddress}");
- //}
- }
- }
- public async Task<CardOperationResult[]> FormatCardByResetToNewRootKeyAndBuildDefaultFileStructures(string cardReaderModuleName, byte[] oldRootKeyBytes, byte[] newRootKeyBytes)
- {
- IEnumerable<CardReaderModule> targetModules;
- if (cardReaderModuleName != "*")
- targetModules = this.cardReaderModules.Where(m => m.Name == cardReaderModuleName);
- else
- targetModules = this.cardReaderModules;
- if (!targetModules.Any()) return new CardOperationResult[] { new CardOperationResult(404) { ModuleResultCode = $"找不到读卡器, 它的名称是: {cardReaderModuleName ?? ""}" } };
- var batchFormatTasks = targetModules.Select(m => m.FormatCardByResetToNewRootKeyAndBuildDefaultFileStructures(m.PhysicalAddress, oldRootKeyBytes.Take(16).ToArray(), newRootKeyBytes.Take(16).ToArray()));
- var results = await Task.WhenAll(batchFormatTasks);
- return results;
- }
- public async Task<CardOperationResult[]> WriteCard(string cardReaderModuleName, byte fileId, byte blockAddress, byte[] dataBytes, byte[] writeKeyBytes)
- {
- IEnumerable<CardReaderModule> targetModules;
- if (cardReaderModuleName != "*")
- targetModules = this.cardReaderModules.Where(m => m.Name == cardReaderModuleName);
- else
- targetModules = this.cardReaderModules;
- if (!targetModules.Any()) return new CardOperationResult[] { new CardOperationResult(404) { ModuleResultCode = $"找不到读卡器, 它的名称是: {cardReaderModuleName ?? ""}" } };
- var batchWriteTasks = targetModules.Select(m => m.WriteCard(m.PhysicalAddress, fileId, blockAddress, dataBytes, writeKeyBytes.Take(16).ToArray()));
- var results = await Task.WhenAll(batchWriteTasks);
- return results;
- }
- public async Task<CardOperationResult[]> ReadCard(string cardReaderModuleName, byte fileId, byte blockAddress, byte[] readKeyBytes)
- {
- IEnumerable<CardReaderModule> targetModules;
- if (cardReaderModuleName != "*")
- targetModules = this.cardReaderModules.Where(m => m.Name == cardReaderModuleName);
- else
- targetModules = this.cardReaderModules;
- if (!targetModules.Any()) return new CardOperationResult[] { new CardOperationResult(404) { ModuleResultCode = $"找不到读卡器, 它的名称是: {cardReaderModuleName ?? ""}" } };
- var batchReadTasks = targetModules.Select(m => m.ReadCard(m.PhysicalAddress, fileId, blockAddress, readKeyBytes.Take(16).ToArray()));
- var results = await Task.WhenAll(batchReadTasks);
- return results;
- }
- public async Task<CardOperationResult[]> ReadCardUID(string cardReaderModuleName)
- {
- IEnumerable<CardReaderModule> targetModules;
- if (cardReaderModuleName != "*")
- targetModules = this.cardReaderModules.Where(m => m.Name == cardReaderModuleName);
- else
- targetModules = this.cardReaderModules;
- if (!targetModules.Any()) return new CardOperationResult[] { new CardOperationResult(404) { ModuleResultCode = $"找不到读卡器, 它的名称是: {cardReaderModuleName ?? ""}" } };
- var batchTasks = targetModules.Select(m => m.ReadCardUID(m.PhysicalAddress));
- var results = await Task.WhenAll(batchTasks);
- return results;
- }
- public async Task<CardOperationResult[]> ModifyPredefinedFileKey(string cardReaderModuleName, PredefinedFileKeyTypeEnum fileKeyType, byte[] oldKeyBytes, byte[] newKeyBytes)
- {
- IEnumerable<CardReaderModule> targetModules;
- if (cardReaderModuleName != "*")
- targetModules = this.cardReaderModules.Where(m => m.Name == cardReaderModuleName);
- else
- targetModules = this.cardReaderModules;
- if (!targetModules.Any()) return new CardOperationResult[] { new CardOperationResult(404) { ModuleResultCode = $"找不到读卡器, 它的名称是: {cardReaderModuleName ?? ""}" } };
- var batchTasks = targetModules.Select(m => m.ModifyPredefinedFileKey(m.PhysicalAddress, fileKeyType, oldKeyBytes.Take(16).ToArray(), newKeyBytes.Take(16).ToArray()));
- var results = await Task.WhenAll(batchTasks);
- return results;
- }
- }
- }
|