using AI.Common.Interface; using AIDiagnosis.Common.Enums; using AIDiagnosis.Common.Models; using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.IO; using System.Threading; using VetHeartDiagnosisSDK.Enums; using Vinno.AI.CommonSDK.Enums; using Vinno.AI.CommonSDK.Models; using Vinno.AI.CommonSDK.Models.Data; using Vinno.AI.CommonSDK.Tools; using Vinno.AI.Service.Common.Interfaces; using Vinno.AI.Service.Common.Models; using Vinno.AI.Service.Common.Tools; using Vinno.AI.VetHeartDiagnosisSDK.Enums; using Vinno.AI.VetHeartDiagnosisSDK.Interfaces; using Vinno.AI.VetHeartDiagnosisSDK.Models; using Vinno.AI.VetHeartDiagnosisService.Tools; using VetHeartDiagnosis = VetHeartDiagnosisSDK.VetHeartDiagnosis; namespace Vinno.AI.VetHeartDiagnosisService { public class VetHeartDiagnosisService : IVetHeartDiagnosisService, IDisposable, IEngine { private readonly ConcurrentStack _singleImageCache; private readonly string _modelFolder = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Networks"); private PipeServer _singleImagePipeServer; private ImageProviderV2 _imageProvider; private VetHeartDiagnosis _vetHeartDiagnosis; private bool _disposed; public static List AllFunctions { get; } static VetHeartDiagnosisService() { AllFunctions = VetHeartDiagnosis.AllFunctions; } public static void Init(FunctionInfo enableFunction, FunctionInfo currentUsedFunction) { VetHeartDiagnosis.Init(enableFunction, currentUsedFunction); } public VetHeartDiagnosisService() { try { _singleImageCache = new ConcurrentStack(); _singleImagePipeServer = new PipeServer(AIDiagnosisSystemConsts.PipeForVetHeartDiagnosisSingleImage); _singleImagePipeServer.LogMsgThrow += OnLogMsgThrow; _singleImagePipeServer.DataReceived += OnDataReceived; _singleImagePipeServer.StartAndReceive(); _imageProvider = new ImageProviderV2(AIEnumType.VetHeartDiagnosis, AIEnumEngineType.VetHeartLVStudy); } catch (Exception ex) { Logger.Error($"VetHeartDiagnosisService-Constructor error:{ex}"); } } private void OnDataReceived(object sender, byte[] e) { try { _singleImageCache.Push(e); } catch (Exception ex) { Logger.Error($"VetHeartDiagnosisService-OnDataReceived error:{ex}"); } } public void Initialize(VetHeartDiagnosisParameter vetHeartMLineDiagnosisParameter, bool hasImageProvider) { try { CloseDiagnosis(); var cpuNumber = vetHeartMLineDiagnosisParameter.CPUNumber; var detectMode = (EnumDetectMode)vetHeartMLineDiagnosisParameter.DetectMode; var detectTps = vetHeartMLineDiagnosisParameter.DetectTps; var intervalTime = vetHeartMLineDiagnosisParameter.IntervalTime; _vetHeartDiagnosis = new VetHeartDiagnosis(); _vetHeartDiagnosis.StartEvaluation += OnStartEvaluation; _vetHeartDiagnosis.FinishEvaluation += OnFinishEvaluation; _vetHeartDiagnosis.NotifyLog += OnNotifyLog; _vetHeartDiagnosis.Init(Setting.Instance.IsSaveDetectImage, Setting.Instance.IsSaveAllImage, Logger.LogDir, hasImageProvider ? _imageProvider : null, cpuNumber, _modelFolder, detectMode, detectTps, intervalTime); } catch (Exception ex) { Logger.Error($"VetHeartDiagnosisService-Initialize error:{ex}"); } } public string StartProcess(AIEnumVetHeartEngineType engineType) { try { return _vetHeartDiagnosis.StartProcess((EnumVetHeartDiagnosisEngineType)engineType); } catch (Exception ex) { Logger.Error($"VetHeartDiagnosisService-StartProcess Error:{ex}"); return null; } } public List PushOnePieceOfData(string processId, AIEnumVetHeartEngineType engineType, AIImageDataId aiImageDataId, AIImageExtraInfo aiImageExtraInfo, TransAIUltrasoundImageRegion transAIUltrasoundImageRegion, int height, int width, AIEnumColorType colorType) { try { byte[] byteImage = null; int retryCount = 0; while (!_singleImageCache.TryPop(out byteImage) && retryCount < 50) { Thread.Sleep(10); retryCount++; } if (byteImage == null) { Logger.Error($"VetHeartDiagnosisService-DetectOneRawImage Get Image Cache Fail"); return null; } var rawImage = new RawImage(byteImage, width, height, (EnumColorType)colorType); Dictionary extraInfoList = new Dictionary(); var imageDataId = AICommonServiceConvertHelperV2.ConvertAIImageDataIdToImageDataId(aiImageDataId); if (aiImageExtraInfo != null) { extraInfoList.Add(nameof(aiImageExtraInfo.CmPerPixel), aiImageExtraInfo.CmPerPixel); } if (transAIUltrasoundImageRegion != null) { var ultrasoundImageRegion = AICommonServiceConvertHelperV2.ConvertTransAIUltrasoundImageRegionToIUltrasoundImageRegion(transAIUltrasoundImageRegion); if (ultrasoundImageRegion != null) { extraInfoList.Add("UltrasoundImageRegion", ultrasoundImageRegion); } } var imageInputData = new ImageInputData(rawImage, imageDataId, extraInfoList); var result = _vetHeartDiagnosis.DetectOneImage((EnumVetHeartDiagnosisEngineType)engineType, processId, imageInputData); return AIConvertHelper.ConvertResultDictToTransResultList(result); } catch (Exception ex) { Logger.Error($"VetHeartDiagnosisService-DetectOneRawImage error:{ex}"); return null; } } public void EndProcess(AIEnumVetHeartEngineType engineType, string processId) { try { _vetHeartDiagnosis.EndProcess((EnumVetHeartDiagnosisEngineType)engineType, processId); } catch (Exception ex) { Logger.Error($"VetHeartDiagnosisService-EndProcess Error:{ex}"); } } public void SetCurrentEngine(AIEnumVetHeartEngineType engineType) { try { if (_imageProvider != null) { _imageProvider.SetEngineType(engineType.ToString()); } } catch (Exception ex) { Logger.Error($"VetHeartDiagnosisService-SetCurrentEngine Error:{ex}"); } } private void OnFinishEvaluation(object sender, IReadOnlyDictionary> e) { var transResultList = AIConvertHelper.ConvertResultDictToTransResultList(e); NotificationSender.SendNotification(new AINotificationArgs { NotificationType = AIEnumNotificationType.VetHeartMLineDiagnosisFinishEvaluationRaised, Params = transResultList }); } /// /// 切换引擎 /// /// public void SwitchEngines(FunctionInfo functionInfo) { try { VetHeartDiagnosis.SwitchAIEngines(functionInfo); if (_vetHeartDiagnosis != null) { _vetHeartDiagnosis.SwitchAIEngines2(functionInfo); } } catch (Exception ex) { Logger.Error($"VetHeartDiagnosisService-SwitchEngines error:{ex}"); } } public void Start() { try { if (_vetHeartDiagnosis != null) { _vetHeartDiagnosis.Start(); } } catch (Exception ex) { Logger.Error($"VetHeartDiagnosisService-Start error:{ex}"); } } public void Stop() { try { if (_vetHeartDiagnosis != null) { _vetHeartDiagnosis.Stop(); } } catch (Exception ex) { Logger.Error($"VetHeartDiagnosisService-Stop error:{ex}"); } } public void SetDetectTps(int detectTps) { try { if (_vetHeartDiagnosis != null) { _vetHeartDiagnosis.DetectTps = detectTps; } } catch (Exception ex) { Logger.Error($"VetHeartDiagnosisService-SetDetectTps error:{ex}"); } } public void SetIntervalTime(int intervalTime) { try { if (_vetHeartDiagnosis != null) { _vetHeartDiagnosis.IntervalTime = intervalTime; } } catch (Exception ex) { Logger.Error($"VetHeartDiagnosisService-SetIntervalTime error:{ex}"); } } public void SetDetectMode(AIEnumDetectMode detectMode) { try { if (_vetHeartDiagnosis != null) { _vetHeartDiagnosis.DetectMode = (EnumDetectMode)detectMode; } } catch (Exception ex) { Logger.Error($"VetHeartDiagnosisService-SetDetectMode error:{ex}"); } } /// /// Send Raw Image Data For Pipe /// /// /// /// public void SendImageData(AIImageDataId imageDataId, AIImageExtraInfo imageExtraInfo, TransAIUltrasoundImageRegion ultrasoundImageRegion, int height, int width, AIEnumColorType colorType) { try { _imageProvider?.ReceiveImageData(height, width, colorType, imageDataId, imageExtraInfo, ultrasoundImageRegion); } catch (Exception ex) { Logger.Error($"VetHeartDiagnosisService-SendRawImageData error:{ex}"); } } public void Close() { try { Logger.Info($"VetHeartDiagnosisService-Close Invoke"); CloseDiagnosis(); } catch (Exception ex) { Logger.Error($"VetHeartDiagnosisService-Close error:{ex}"); } } private void CloseDiagnosis() { if (_vetHeartDiagnosis != null) { _vetHeartDiagnosis.StartEvaluation -= OnStartEvaluation; _vetHeartDiagnosis.NotifyLog -= OnNotifyLog; _vetHeartDiagnosis.Close(); _vetHeartDiagnosis = null; } } public void Dispose() { try { if (!_disposed) { Logger.Info($"VetHeartDiagnosisService-Start Dispose"); CloseDiagnosis(); if (_singleImagePipeServer != null) { _singleImagePipeServer.DataReceived -= OnDataReceived; _singleImagePipeServer.Dispose(); _singleImagePipeServer.LogMsgThrow -= OnLogMsgThrow; _singleImagePipeServer = null; } _imageProvider.Dispose(); _imageProvider = null; _disposed = true; Logger.Info($"VetHeartDiagnosisService Dispose End"); } } catch (Exception ex) { Logger.Error($"VetHeartDiagnosisService-Dispose error:{ex}"); } } private void OnStartEvaluation(object sender, EventArgs e) { NotificationSender.SendNotification(new AINotificationArgs() { NotificationType = AIEnumNotificationType.VetHeartMLineDiagnosisStartEvaluationRaised, Params = e }); } private void OnNotifyLog(object sender, LogEventArgs e) { if (e == null) { return; } switch (e.LogType) { case EnumLogType.InfoLog: Logger.Info($"VetHeartDiagnosisService OnNotifyLog:{e.Msg}"); break; case EnumLogType.WarnLog: Logger.Warning($"VetHeartDiagnosisService OnNotifyLog:{e.Msg}"); break; case EnumLogType.ErrorLog: case EnumLogType.FatalLog: default: Logger.Error($"VetHeartDiagnosisService OnNotifyLog:{e.Msg}"); break; } var logEventArgs = AICommonServiceConvertHelperV2.ConvertLogEventArgsToAILogEventArgs(e); NotificationSender.SendNotification(new AINotificationArgs() { NotificationType = AIEnumNotificationType.VetHeartMLineDiagnosisNotifyLogRaised, Params = logEventArgs }); } private void OnLogMsgThrow(object sender, AILogEventArgs e) { if (e == null) { return; } switch (e.LogType) { case AIEnumLogType.ErrorLog: case AIEnumLogType.FatalLog: Logger.Error(e.Msg); break; case AIEnumLogType.WarnLog: Logger.Warning(e.Msg); break; case AIEnumLogType.InfoLog: default: Logger.Info(e.Msg); break; } } } }