using log4net; using log4net.Repository.Hierarchy; using NetTaste; using Prism.Events; using Prism.Ioc; using SqlSugar; using System; using System.Collections.Generic; using System.ComponentModel.Design; using System.Configuration; using System.IO.Ports; using System.Linq; using System.Reflection.Metadata; using System.Speech.Synthesis; using System.Text; using System.Threading.Channels; using System.Threading.Tasks; using System.Timers; using System.Windows; using System.Windows.Markup; using System.Windows.Media.Animation; using Unity; using DM_Weight.msg; using DM_Weight.Views; using System.Reflection; using System.Text.RegularExpressions; using DM_Weight.Common; using System.Threading; namespace DM_Weight.Port { public class PortUtil { private readonly ILog logger = LogManager.GetLogger(typeof(PortUtil)); // 抽屉串口 public SerialPort drawerSerial; // can总线串口 public SerialPort canBusSerial; // 条码枪串口 public SerialPort scanCodeSerial; // 冰箱串口 public SerialPort fridgeSerial; // 抽屉串口协议232 | 485 private int _drawerProtocol = Convert.ToInt32(ConfigurationManager.AppSettings["DrawerProtocol"]); // can总线耗材板地址 private int _doorAddr = Convert.ToInt32(ConfigurationManager.AppSettings["DoorAddr"]); // 储物箱地址 private int _storageBoxAddr = Convert.ToInt32(ConfigurationManager.AppSettings["StorageBoxAddr"]); // can总线串口是否存在 public bool _canBusExsit = Convert.ToBoolean(ConfigurationManager.AppSettings["CanBusExsit"]); // 当前操作的抽屉号 public int DrawerNo { get; set; } // 当前操作的库位号列表 public int[] ColNos { get; set; } = new int[] { }; // 当前操作查数的库位号列表 public List ColNoLst { get; set; } = new List(); // 当前操作开药盒的库位号 public int OpenBoxColNo { get; set; } = 0; // 当前操作的窗口 public string WindowName { get; set; } // 取药操作的窗口名【处方取药、抽屉取药、自选取药、调拨出库】 private string[] TakeNames = new string[] { "DrawerTakeDrugWindow", "OrderTakeDrugWindow", "SelfTakeDrugWindow", "InvoiceTakeDrugWindow" }; // 加药操作的窗口名【自选加药、抽屉加药、还药】 private string[] AddNames = new string[] { "SelfAddWindow", "ReturnDrugWindow", "ReturnDrug1Window", "DrawerAddDrugWindow" }; // 盘点操作的窗口名【盘点】 private string[] CheckNames = new string[] { "CheckStockWindow" }; // 归还空瓶操作的窗口名【盘点】 private string[] ReturnEmptyNames = new string[] { "ReturnEmptyWindow" }; public int BoardType { get; set; } = (Int32)BoardTypeEnum.separation; public int DrawerType { get; set; } = (Int32)DrawerTypeEnum.drawerTypeOne; private int[] BeforeQuantity { get; set; } = new int[9]; private int[] AfterQuantity { get; set; } = new int[] { }; // 整体流程状态 private int statue { get; set; } = 0; // 是否正在操作中 public bool Operate { get; set; } //冰箱是否正在操作中 public bool FridgeOperate { get; set; } public DateTime dateTime { get; set; } = DateTime.Now; public async void ResetData() { logger.Info($"重新设置串口数据状态【{statue}】,抽屉【{DrawerNo}】"); if (!"HomeWindow".Equals(WindowName) && statue == 1) { if (BoardType == (Int32)BoardTypeEnum.single) { // 灭灯 AllLightOff(); } if (BoardType == (Int32)BoardTypeEnum.box) { // 失能 await BoxLockLightOff(); } if (BoardType == (Int32)BoardTypeEnum.storage) { // 失能 CloseStorage(); } //if (BoardType == (Int32)BoardTypeEnum.weigh) //{ // // 失能 // await BoxLockLightOff2(); //} //if (BoardType == (Int32)BoardTypeEnum.weighSmartBox || BoardType == (Int32)BoardTypeEnum.weighBox) //{ // // 失能 // await BoxLockLightOff(); // // 失能 // await BoxLockLightOff2(); //} } Operate = false; dateTime = DateTime.Now; statue = 0; BeforeQuantity = new int[9]; AfterQuantity = new int[9]; BoardType = (Int32)BoardTypeEnum.separation; DrawerType = (Int32)DrawerTypeEnum.drawerTypeOne; WindowName = ""; DrawerNo = 0; ColNos = new int[] { }; } public async void Start() { logger.Info($"进行抽屉操作抽屉号【{DrawerNo}】类型【{BoardType}】库位【{string.Join(",", ColNos)}】窗口【{WindowName}】"); Operate = true; try { // 储物箱直接开 if (BoardType == 4) { byte[] result = await OpenStorage(); int[] r = result.Select(it => Convert.ToInt32(it)).ToArray(); if (r[4] != 0) { logger.Info($"储物箱使能成功"); // 查询锁状态 GetBackDoorState(); } else { string _WindowName = WindowName; logger.Info($"储物箱使能失败"); // 重新初始化数据 ResetData(); // 指令发送错误,未打开 // 返回消息 抽屉打开失败 _eventAggregator.GetEvent().Publish(new util.DeviceMsg() { EventType = util.EventType.OPENERROR, WindowName = WindowName, Message = "储物箱使能失败" }); } } else { // 外置抽屉 if (DrawerType == (Int32)DrawerTypeEnum.recyle) { if (BoardType == (Int32)BoardTypeEnum.single) { byte[] buffer = await OpenRecover(); int[] r = buffer.Select(it => Convert.ToInt32(it)).ToArray(); if ((ColNos[0] > 3 && r[4] == 1) || (ColNos[0] < 4 && r[3] == 1)) { // 告诉前台打开成功 _eventAggregator.GetEvent().Publish(new util.DeviceMsg() { EventType = util.EventType.DRAWEROPEN, WindowName = WindowName, }); logger.Info($"回收箱打开成功"); // 查询是否关闭状态 GeRecoverStatus(); } else { string _WindowName = WindowName; logger.Info($"回收箱打开失败"); // 重新初始化数据 ResetData(); // 返回消息开启失败 // 返回消息 抽屉打开失败 _eventAggregator.GetEvent().Publish(new util.DeviceMsg() { EventType = util.EventType.OPENERROR, WindowName = WindowName, Message = "回收箱打开失败" }); } } } // 内置抽屉 else { if (BoardType == (Int32)BoardTypeEnum.single) { byte[] quantity = await CheckQuantityByDrawer(); BeforeQuantity = quantity.Select(it => Convert.ToInt32(it)).ToArray().Skip(3).Take(9).ToArray(); logger.Info($"BeforeQuantity{string.Join(",", BeforeQuantity)}"); } if (BoardType == (Int32)BoardTypeEnum.weigh || BoardType == (Int32)BoardTypeEnum.weighSmartBox || BoardType == (Int32)BoardTypeEnum.weighBox) { if (WindowName != "DrawerTakeDrugWindow" && WindowName != "DrawerAddDrugWindow") { int[] quantity = await CheckQuantityByAddr2(); BeforeQuantity = quantity.Select(it => Convert.ToInt32(it)).ToArray(); logger.Info($"BeforeQuantity{string.Join(",", BeforeQuantity)}"); } else { logger.Info($"{WindowName}开锁前先不查数"); } } byte[] buffer = await OpenDrawer(); int[] r = buffer.Select(it => Convert.ToInt32(it)).ToArray(); logger.Info($"OpenDrawer{string.Join(",", r)}"); if (DrawerState(r)) { statue = 1; // 是不是单支抽屉 if (BoardType == (Int32)BoardTypeEnum.single) { // 取药 if (Array.IndexOf(TakeNames, WindowName) > -1) { // 有药位置亮灯 await HasLightOnByCol(); } // 加药 if (Array.IndexOf(AddNames, WindowName) > -1) { // 无药位置亮灯 await NoLightOnByCol(); } // 盘点 if (Array.IndexOf(CheckNames, WindowName) > -1) { // 不亮灯 } // 空瓶 if (Array.IndexOf(ReturnEmptyNames, WindowName) > -1) { // 无药位置亮灯 await NoLightOnByCol(); } } // 药盒 //if (BoardType == (Int32)BoardTypeEnum.box) //{ // //抽屉加药和抽屉取药不开药盒锁(单独开) // if (WindowName != "DrawerTakeDrugWindow" || WindowName != "DrawerAddDrugWindow") // { // logger.Info("开锁后药盒自动打开"); // //// 药盒指示灯使能 // //await BoxLockLightOn(); // await OpenBox(); // } // else // { // logger.Info("开锁后先不开药盒"); // //抽屉加药和抽屉取药根据点的开药盒按钮的库位查数 // ColNos = null; // } //} if (BoardType == (Int32)BoardTypeEnum.box || BoardType == (Int32)BoardTypeEnum.weighSmartBox || BoardType == (Int32)BoardTypeEnum.weighBox) { //抽屉加药和抽屉取药不开药盒锁(单独开) if (WindowName != "DrawerTakeDrugWindow" && WindowName != "DrawerAddDrugWindow") { logger.Info($"开锁后药盒自动打开{WindowName}"); // 药盒指示灯使能 await OpenBox(); } else { logger.Info($"{WindowName}开锁后先不开药盒"); //抽屉加药和抽屉取药根据点的开药盒按钮的库位查数 ColNos = null; } } // 返回消息 抽屉已经打开 _eventAggregator.GetEvent().Publish(new util.DeviceMsg() { EventType = util.EventType.DRAWEROPEN, WindowName = WindowName, }); logger.Info($"抽屉【{DrawerNo}】打开成功"); // 查询抽屉状态 await Task.Delay(200); GetDrawerStatus(); } else { string _WindowName = WindowName; logger.Info($"抽屉【{DrawerNo}】打开失败"); // 重新初始化数据 ResetData(); // 返回消息 抽屉打开失败 _eventAggregator.GetEvent().Publish(new util.DeviceMsg() { EventType = util.EventType.OPENERROR, WindowName = WindowName, Message = $"抽屉【{DrawerNo}】打开失败" }); } } } } catch (Exception ex) { string _WindowName = WindowName; // 重新初始化数据 ResetData(); // 返回消息 抽屉打开失败 _eventAggregator.GetEvent().Publish(new util.DeviceMsg() { EventType = util.EventType.OPENERROR, WindowName = _WindowName, Message = $"操作异常{ex.Message}" }); logger.Info(ex.Message); } } public async void GetDrawerStatus() { try { if (Operate) { // 查询抽屉状态 byte[] buffer = await CheckDrawerStatus(); int[] r = buffer.Select(it => Convert.ToInt32(it)).ToArray(); logger.Info($"GetDrawerStatus{string.Join(",", r)}"); // 抽屉没有关闭 if (DrawerState(r)) { if (BoardType == (Int32)BoardTypeEnum.single) { // 继续查询抽屉药品数量 // 查询抽屉药品数量 byte[] quantity = await CheckQuantityByDrawer(); AfterQuantity = quantity.Select(it => Convert.ToInt32(it)).ToArray().Skip(3).Take(9).ToArray(); logger.Info($"AfterQuantity{string.Join(",", AfterQuantity)}"); int[] Quantitys = new int[BeforeQuantity.Length]; for (int i = 0; i < BeforeQuantity.Length; i++) { // 取药 if (Array.IndexOf(TakeNames, WindowName) > -1) { Quantitys[i] = BeforeQuantity[i] - AfterQuantity[i]; } // 加药 if (Array.IndexOf(AddNames, WindowName) > -1) { Quantitys[i] = AfterQuantity[i] - BeforeQuantity[i]; } // 盘点 if (Array.IndexOf(CheckNames, WindowName) > -1) { Quantitys[i] = AfterQuantity[i] - BeforeQuantity[i]; } // 空瓶 if (Array.IndexOf(CheckNames, WindowName) > -1) { Quantitys[i] = AfterQuantity[i] - BeforeQuantity[i]; } } // 告诉前台数据变化 _eventAggregator.GetEvent().Publish(new util.DeviceMsg() { EventType = util.EventType.UPDATEQUANTITY, WindowName = WindowName, Quantitys = Quantitys }); logger.Info($"数量变化【{string.Join(",", Quantitys)}】"); } if (BoardType == (Int32)BoardTypeEnum.weigh || BoardType == (Int32)BoardTypeEnum.weighSmartBox || BoardType == (Int32)BoardTypeEnum.weighBox) { // 继续查询抽屉药品数量 // 查询抽屉药品数量 if (ColNos != null && ColNos.Length > 0 || OpenBoxColNo > 0) { //开药盒锁 if (OpenBoxColNo > 0 && (WindowName == "DrawerTakeDrugWindow" || WindowName == "DrawerAddDrugWindow")) { //开药盒锁前先查数 int beforeQuantity = await CheckQuantityForSingle(OpenBoxColNo); BeforeQuantity[OpenBoxColNo - 1] = beforeQuantity; logger.Info($"BeforeQuantity:{OpenBoxColNo}-{beforeQuantity}数量{string.Join(",", BeforeQuantity)}"); OpenBoxByColNo(OpenBoxColNo); OpenBoxColNo = 0; await Task.Delay(TimeSpan.FromMilliseconds(20)); } int[] quantity = await CheckQuantityByAddr2(); AfterQuantity = quantity.Select(it => Convert.ToInt32(it)).ToArray(); logger.Info($"AfterQuantity{string.Join(",", AfterQuantity)}"); int[] Quantitys = new int[BeforeQuantity.Length]; for (int i = 0; i < BeforeQuantity.Length; i++) { // 取药 if (Array.IndexOf(TakeNames, WindowName) > -1) { Quantitys[i] = BeforeQuantity[i] - AfterQuantity[i]; } // 加药 if (Array.IndexOf(AddNames, WindowName) > -1) { Quantitys[i] = AfterQuantity[i] - BeforeQuantity[i]; } // 盘点 if (Array.IndexOf(CheckNames, WindowName) > -1) { Quantitys[i] = AfterQuantity[i] - BeforeQuantity[i]; } // 空瓶 if (Array.IndexOf(CheckNames, WindowName) > -1) { Quantitys[i] = AfterQuantity[i] - BeforeQuantity[i]; } } // 告诉前台数据变化 _eventAggregator.GetEvent().Publish(new util.DeviceMsg() { EventType = util.EventType.UPDATEQUANTITY, WindowName = WindowName, Quantitys = Quantitys }); logger.Info($"数量变化【{string.Join(",", Quantitys)}】"); } else { logger.Info("无库位,不查数"); } } // 继续监听抽屉状态 await Task.Delay(200); GetDrawerStatus(); } else { statue = 2; if (BoardType == (Int32)BoardTypeEnum.single) { // 关灯 AllLightOff(); } // 药盒 //if (BoardType == (Int32)BoardTypeEnum.box) //{ // // 药盒指示灯失能 // await BoxLockLightOff(); //} //if (BoardType == (Int32)BoardTypeEnum.weigh || BoardType == (Int32)BoardTypeEnum.weighSmartBox) //{ // // 药盒指示灯使能 // await BoxLockLightOff2(); //} string _WindowName = WindowName; logger.Info($"抽屉【{DrawerNo}】已关闭"); // 重新初始化数据 ResetData(); // 返回消息 抽屉已经关闭 _eventAggregator.GetEvent().Publish(new util.DeviceMsg() { EventType = util.EventType.DRAWERCLOSE, WindowName = _WindowName, }); } } } catch (Exception ex) { _eventAggregator.GetEvent().Publish(new util.DeviceMsg() { EventType = util.EventType.OPENERROR, WindowName = WindowName, Message = $"GetDrawerStatus异常:{ex.Message}" }); logger.Info($"GetDrawerStatus异常:{ex.Message}"); } } public async void GeRecoverStatus() { if (Operate) { byte[] buffer = await CheckRecoverStatus(); int[] r = buffer.Select(it => Convert.ToInt32(it)).ToArray(); logger.Info($"GeRecoverStatus{string.Join(",", r)}"); // 回收箱关闭成功 if ((ColNos[0] > 3 && r[4] == 0) || (ColNos[0] < 4 && r[3] == 0)) { logger.Info($"回收箱关闭"); // 查询数量 byte[] bytes = await CheckRecoverQuantity(); int[] r1 = bytes.Select(it => Convert.ToInt32(it)).ToArray(); // 返回消息库位关闭,放入空瓶数量 int[] quantitys = r1.Skip(3).Take(3).ToArray(); int index = ColNos[0] % 3 > 0 ? ColNos[0] % 3 - 1 : 2; // 指定库位放入的药品数量 int InCount = quantitys[index]; string _WindowName = WindowName; // 重新初始化数据 ResetData(); _eventAggregator.GetEvent().Publish(new util.DeviceMsg() { EventType = util.EventType.DRAWERCLOSE, Quantitys = new int[] { InCount }, WindowName = _WindowName, }); logger.Info($"回收板数量变化【{string.Join(",", quantitys)}】"); } else { // 查询是否关闭状态 await Task.Delay(200); GeRecoverStatus(); } } } /// ///未操作串口时进行监测后门(与单支回收箱用同一块板子的)是否打开 /// public async Task GetSingleBoardBackDoorState() { try { if (!Operate) { byte[] buffer = await CheckRecoverStatus(); int[] r = buffer.Select(it => Convert.ToInt32(it)).ToArray(); logger.Info($"GetSingleBoardBackDoorState{string.Join(",", r)}"); // 后门关闭 if ((r[5] == 0 && r[6] == 0)) { logger.Info($"后门关闭"); } else { //后门打开 logger.Info($"后门打开"); // 查询是否关闭状态 await Task.Delay(200); } } } catch (Exception ex) { logger.Info($"GetSingleBoardBackDoorState{ex.Message}"); } } public async void GetBackDoorState() { try { if (Operate) { byte[] result = await BackDoorState(); int[] r = result.Select(it => Convert.ToInt32(it)).ToArray(); int[] lockStates = CheckStorageStatus(r.Skip(3).Take(2).ToArray()); int[] lightStates = CheckStorageStatus(r.Skip(5).Take(2).ToArray()); // 锁处于关闭状态 if (lockStates[_storageBoxAddr - 1] == 0) { // 锁还未打开过 if (statue == 0) { // 指示灯不闪烁了,说明规定时间内没有开锁,需要给前台提示 if (lightStates[_storageBoxAddr - 1] == 0) { // 打开失败 logger.Info($"储物箱指示灯不闪烁,使能过期"); } else { // 灯在闪烁继续监听状态 GetBackDoorState(); } } else if (statue == 1) { // 锁是打开状态现在关闭了,说明操作完成了,告诉前台锁已关闭 statue = 2; string _WindowName = WindowName; logger.Info($"储物箱关闭"); // 重新初始化数据 ResetData(); _eventAggregator.GetEvent().Publish(new util.DeviceMsg() { EventType = util.EventType.DRAWERCLOSE, WindowName = WindowName, }); } } // 锁处于打开状态 if (lockStates[_storageBoxAddr - 1] == 1) { // 锁还未打开过,说明打开成功了 if (statue == 0) { statue = 1; // 告诉前台打开成功 _eventAggregator.GetEvent().Publish(new util.DeviceMsg() { EventType = util.EventType.DRAWEROPEN, WindowName = WindowName, }); logger.Info($"储物箱打开成功"); } // 灯在闪烁继续监听状态 GetBackDoorState(); } } } catch (Exception ex) { logger.Info($"GetBackDoorState异常{ex.Message}"); } } private readonly IEventAggregator _eventAggregator; public PortUtil(IEventAggregator eventAggregator) { _eventAggregator = eventAggregator; try { string DrawerPortPath = ConfigurationManager.AppSettings["DrawerPortPath"]; logger.Info($"打开抽屉串口【{DrawerPortPath}】"); drawerSerial = new SerialPort(DrawerPortPath, 9600, Parity.None, 8); drawerSerial.Open(); logger.Info($"抽屉串口打开结果【{drawerSerial.IsOpen}】"); } catch (Exception e) { logger.Error("抽屉串口打开错误" + e.Message); } try { string ScanCodePortPath = ConfigurationManager.AppSettings["ScanCodePortPath"]; logger.Info($"打开条码枪串口【{ScanCodePortPath}】"); scanCodeSerial = new SerialPort(ScanCodePortPath, 9600, Parity.None, 8); scanCodeSerial.DataReceived += (object sender, System.IO.Ports.SerialDataReceivedEventArgs e) => { string code = scanCodeSerial.ReadExisting(); _eventAggregator.GetEvent().Publish(new util.DeviceMsg() { EventType = util.EventType.CODESCAN, Code = code, }); }; scanCodeSerial.Open(); logger.Info($"条码枪串口打开结果【{scanCodeSerial.IsOpen}】"); } catch (Exception e) { logger.Error("条码枪串口打开错误" + e.Message); } try { string FridgePortPath = ConfigurationManager.AppSettings["FridgePortPath"]; logger.Info($"打开冰箱串口【{FridgePortPath}】"); fridgeSerial = new SerialPort(FridgePortPath, 9600, Parity.None, 8); fridgeSerial.Open(); logger.Info($"冰箱串口打开结果【{fridgeSerial.IsOpen}】"); } catch (Exception e) { logger.Error("冰箱串口打开错误" + e.Message); } if (_canBusExsit) { try { string CanBusPortPath = ConfigurationManager.AppSettings["CanBusPortPath"]; logger.Info($"打开can总线串口【{CanBusPortPath}】"); canBusSerial = new SerialPort(CanBusPortPath, 57600, Parity.None, 8); canBusSerial.Open(); logger.Info($"can总线串口打开结果【{canBusSerial.IsOpen}】"); } catch (Exception e) { logger.Error("can总线串口打开错误" + e.Message); } } } private byte[] GetBufferByPort(SerialPort serialPort, int length, int timeout) { byte[] buffer = new byte[length]; // try // { int _length = 0; DateTime start = DateTime.Now; DateTime end = DateTime.Now; while (_length != length && end.Subtract(start).TotalMilliseconds < timeout) { _length = serialPort.BytesToRead; end = DateTime.Now; } if (_length != length) { logger.Info($"串口【{serialPort.PortName}】交互超时;{_length}-{length};{end.Subtract(start).TotalMilliseconds}-{timeout}"); throw new TimeoutException($"串口【{serialPort.PortName}】交互超时"); } serialPort.Read(buffer, 0, length); // } // catch (Exception ex) // { // logger.Error($"GetBufferByPort:{ex.Message}"); // } return buffer; } private Task GetBufferByPort(SerialPort serialPort, int length) { return Task.Run(() => GetBufferByPort(serialPort, length, 3000)); } public static SpeechSynthesizer speechSynthesizer = new SpeechSynthesizer(); public void SpeakAsync(string textinfo) { speechSynthesizer.SpeakAsync(textinfo); } #region 抽屉串口操作 // 打开抽屉 public async Task OpenDrawer() { try { logger.Info($"开抽屉"); drawerSerial.DiscardInBuffer(); byte[] buffer = new byte[] { 0xaa, 0x41, (byte)DrawerNo, 0xee }; if (_drawerProtocol == 485) { if (DrawerNo > 8) { buffer = new byte[] { 0xaa, 0x21, (byte)(DrawerNo - 8), 0xee }; } else { buffer = new byte[] { 0xaa, 0x11, (byte)DrawerNo, 0xee }; } } logger.Info($"打开抽屉,串口数据:{Convert.ToHexString(buffer)}"); drawerSerial.Write(buffer, 0, 4); return await GetBufferByPort(drawerSerial, 11); } catch (Exception ex) { logger.Info($"抽屉【{DrawerNo}】打开失败"); // 返回消息 抽屉打开失败 _eventAggregator.GetEvent().Publish(new util.DeviceMsg() { EventType = util.EventType.OPENERROR, WindowName = WindowName, Message = $"抽屉【{DrawerNo}】打开失败" }); // 重新初始化数据 ResetData(); return null; } } public bool DrawerState(int[] r) { int index = DrawerNo > 8 ? DrawerNo - 7 : DrawerNo + 1; return r[index] == 0; } // 查询抽屉状态 public async Task CheckDrawerStatus() { drawerSerial.DiscardInBuffer(); byte[] buffer = new byte[] { 0xaa, 0x42, 0xee }; if (_drawerProtocol == 485) { if (DrawerNo > 8) { buffer = new byte[] { 0xaa, 0x22, 0xee }; } else { buffer = new byte[] { 0xaa, 0x12, 0xee }; } } logger.Info($"查询抽屉状态,串口数据:{Convert.ToHexString(buffer)}"); drawerSerial.Write(buffer, 0, 3); return await GetBufferByPort(drawerSerial, 11); } #endregion #region can总线串口操作 #region 耗材板操作 // 后门状态 public async Task BackDoorState() { canBusSerial.DiscardInBuffer(); byte[] buffer = new byte[] { 0xaa, (byte)(_doorAddr), 0x02, 0x00, 0x00, 0x00, 0x00, 0xee }; canBusSerial.Write(buffer, 0, 8); return await GetBufferByPort(canBusSerial, 8); } // 打开电控门储物箱(有灯使能) public async Task OpenStorage() { canBusSerial.DiscardInBuffer(); byte[] buffer = new byte[] { 0xaa, (byte)(_doorAddr), 0x01, (byte)_storageBoxAddr, 0x00, 0x00, 0x00, 0xee }; canBusSerial.Write(buffer, 0, 8); return await GetBufferByPort(canBusSerial, 8); } // 关闭电控门储物箱(有灯失能) public void CloseStorage() { byte[] buffer = new byte[] { 0xaa, (byte)(_doorAddr), 0x04, 0x00, 0x00, 0x00, 0x00, 0xee }; canBusSerial.Write(buffer, 0, 8); } // 打开普通储物箱(无灯) public void OpenStorageBox() { byte[] buffer = new byte[] { 0xaa, (byte)(_storageBoxAddr), 0x03, 0x00, 0x00, 0x00, 0x00, 0xee }; canBusSerial.Write(buffer, 0, 8); } // 关闭普通储物箱(无灯) public void CloseStorageBox() { byte[] buffer = new byte[] { 0xaa, (byte)(_storageBoxAddr), 0x04, 0x00, 0x00, 0x00, 0x00, 0xee }; canBusSerial.Write(buffer, 0, 8); } private int[] CheckStorageStatus(int[] data) { int a = data[0]; int b = data[1]; int[] intA = Decimal2Chunks(a); int[] intB = Decimal2Chunks(b); int[] r = new int[intA.Length + intB.Length]; Array.Copy(intA, 0, r, 0, intA.Length); Array.Copy(intB, 0, r, intA.Length, intB.Length); return r; } private int[] Decimal2Chunks(int d) { string s = Convert.ToString(d, 2); int[] chars = new int[8]; char[] schar = s.ToCharArray(); Array.Reverse(schar); int[] iArray = Array.ConvertAll(schar, c => (int)Char.GetNumericValue(c)); int[] addArray = new int[8 - iArray.Length]; if (iArray.Length < 8) { for (int i = 0; i < 8 - iArray.Length; i++) { addArray[i] = 0; } chars = iArray.Concat(addArray).ToArray(); } else { chars = iArray[0..iArray.Length]; } return chars; //List t = s.Split().Select(it => Convert.ToInt32(it)).Reverse().ToList(); //while (t.Count < 8) //{ // t.Add(0); //} //return t.ToArray(); } #endregion #region 单支操作 // 以抽屉为单位获取抽屉内所有库位的药品数量 public async Task CheckQuantityByDrawer() { canBusSerial.DiscardInBuffer(); byte[] buffer = new byte[] { 0xaa, (byte)(0xf0 + DrawerNo), 0x01, 0x00, 0x00, 0x00, 0x00, 0xee }; logger.Info($"单支板发送库位数量查询【{string.Join(",", buffer)}】"); canBusSerial.Write(buffer, 0, 8); return await GetBufferByPort(canBusSerial, 13); } // 获取单个单支板药品数量 public async Task CheckQuantityByCol(int DrawerNo, int colNo) { canBusSerial.DiscardInBuffer(); var channel = Convert.ToInt32((DrawerNo * 10 + colNo).ToString(), 16); byte[] buffer = new byte[] { 0xaa, (byte)channel, 0x08, 0x00, 0x00, 0x00, 0x00, 0xee }; canBusSerial.Write(buffer, 0, 8); return await GetBufferByPort(canBusSerial, 8); } // 以抽屉为单位有药位置亮灯 public void HasLightOnByDrawer() { byte[] buffer = new byte[] { 0xaa, (byte)(0xf0 + DrawerNo), 0x02, 0x00, 0x00, 0x00, 0x00, 0xee }; canBusSerial.Write(buffer, 0, 8); } // 以抽屉为单位无药位置亮灯 public void NoLightOnByDrawer() { byte[] buffer = new byte[] { 0xaa, (byte)(0xf0 + DrawerNo), 0x03, 0x00, 0x00, 0x00, 0x00, 0xee }; canBusSerial.Write(buffer, 0, 8); } // 以抽屉为单位灭灯 public void LightOffByDrawer() { byte[] buffer = new byte[] { 0xaa, (byte)(0xf0 + DrawerNo), 0x06, 0x00, 0x00, 0x00, 0x00, 0xee }; canBusSerial.Write(buffer, 0, 8); } // 以单支板为单位有药位置亮灯 public async Task HasLightOnByCol() { for (int i = 0; i < ColNos.Length; i++) { var channel = Convert.ToInt32((DrawerNo * 10 + ColNos[i]).ToString(), 16); byte[] buffer = new byte[] { 0xaa, (byte)channel, 0x0a, 0x00, 0x00, 0x00, 0x00, 0xee }; canBusSerial.Write(buffer, 0, 8); await Task.Delay(TimeSpan.FromMilliseconds(20)); } } // 以单支板为单位无药位置亮灯 public async Task NoLightOnByCol() { for (int i = 0; i < ColNos.Length; i++) { var channel = Convert.ToInt32((DrawerNo * 10 + ColNos[i]).ToString(), 16); byte[] buffer = new byte[] { 0xaa, (byte)channel, 0x0b, 0x00, 0x00, 0x00, 0x00, 0xee }; canBusSerial.Write(buffer, 0, 8); await Task.Delay(TimeSpan.FromMilliseconds(20)); } } // 广播灭灯 public void AllLightOff() { byte[] buffer = new byte[] { 0xaa, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0xee }; canBusSerial.Write(buffer, 0, 8); } #endregion #region 药盒操作 //无按钮开药盒 /// /// 开指定库位的药盒 /// /// /// public async Task OpenBoxByColNo(int colNo) { if (colNo > 0) { canBusSerial.DiscardInBuffer(); int ColNo = colNo; int[] iNum = new int[] { 4, 2, 1 }; var colNo2 = ColNo % 3 > 0 ? (ColNo % 3) - 1 : 2; var bColNo = iNum[colNo2]; decimal decolNO = (decimal)ColNo; var channel = Convert.ToInt32((DrawerNo * 10 + Math.Ceiling(decolNO / 3)).ToString(), 16); byte[] buffer = new byte[] { 0xaa, (byte)channel, 5, (byte)bColNo, 0x00, 0x00, 0x00, 0xee }; //byte[] buffer = new byte[] { 0xaa, 0x11, 0x05,0x01, 0x00,0x00,0x00,0xee}; logger.Info($"开药盒{ColNo}【{Convert.ToHexString(buffer)}】"); canBusSerial.Write(buffer, 0, 8); byte[] retBuffer = await GetBufferByPort(canBusSerial, 8); logger.Info($"开药盒返回{ColNo}【{Convert.ToHexString(retBuffer)}】"); int[] r = retBuffer.Select(it => Convert.ToInt32(it)).ToArray(); if (r[4] > 0) { return true; } else { return false; } } return false; } /// /// 打开药盒 /// /// /// public async Task OpenBox() { for (int i = 0; i < ColNos.Length; i++) { canBusSerial.DiscardInBuffer(); int ColNo = ColNos[i]; int[] iNum = new int[] { 4, 2, 1 }; var colNo2 = ColNo % 3 > 0 ? (ColNo % 3) - 1 : 2; var bColNo = iNum[colNo2]; decimal decolNO = (decimal)ColNo; var channel = Convert.ToInt32((DrawerNo * 10 + Math.Ceiling(decolNO / 3)).ToString(), 16); byte[] buffer = new byte[] { 0xaa, (byte)channel, 5, (byte)bColNo, 0x00, 0x00, 0x00, 0xee }; //byte[] buffer = new byte[] { 0xaa, 0x11, 0x05,0x01, 0x00,0x00,0x00,0xee}; logger.Info($"{Convert.ToHexString(buffer)}"); canBusSerial.Write(buffer, 0, 8); await Task.Delay(800); } } // 指定药盒指示灯开启使能开锁 public async Task BoxLockLightOn() { for (int i = 0; i < ColNos.Length; i++) { var channel = Convert.ToInt32((DrawerNo * 10 + ColNos[i]).ToString(), 16); byte[] buffer = new byte[] { 0xaa, (byte)channel, 0x03, 0x00, 0x00, 0x00, 0x00, 0xee }; canBusSerial.Write(buffer, 0, 8); await Task.Delay(TimeSpan.FromMilliseconds(20)); } } // 指定药盒指示灯开启失能开锁 public async Task BoxLockLightOff() { if (ColNos != null) { for (int i = 0; i < ColNos.Length; i++) { var channel = Convert.ToInt32((DrawerNo * 10 + ColNos[i]).ToString(), 16); byte[] buffer = new byte[] { 0xaa, (byte)channel, 0x04, 0x00, 0x00, 0x00, 0x00, 0xee }; canBusSerial.Write(buffer, 0, 8); await Task.Delay(TimeSpan.FromMilliseconds(20)); } } } // 指定药盒状态查询 public async Task BoxLockState(int ColNo) { canBusSerial.DiscardInBuffer(); var channel = Convert.ToInt32((DrawerNo * 10 + ColNo).ToString(), 16); byte[] buffer = new byte[] { 0xaa, (byte)channel, 0x02, 0x00, 0x00, 0x00, 0x00, 0xee }; canBusSerial.Write(buffer, 0, 8); return await GetBufferByPort(canBusSerial, 8); } // 以抽屉为单位药盒指示灯开启使能开锁 public async Task BoxLockLightOnByDrawer() { canBusSerial.DiscardInBuffer(); byte[] buffer = new byte[] { 0xaa, (byte)(0xf0 + DrawerNo), 0x04, 0x00, 0x00, 0x00, 0x00, 0xee }; canBusSerial.Write(buffer, 0, 8); } // 以抽屉为单位药盒指示灯开启失能开锁 public async Task BoxLockLightOffByDrawer() { canBusSerial.DiscardInBuffer(); byte[] buffer = new byte[] { 0xaa, (byte)(0xf0 + DrawerNo), 0x05, 0x00, 0x00, 0x00, 0x00, 0xee }; canBusSerial.Write(buffer, 0, 8); } #endregion private string trim(string text) { //此处使用了转义字符如:\',\",\\,分别表示单引号,双引号,反斜杠 char[] TrimChar = { ' ', '-', '\'', '\"', '\\', '(', ')', '(', ')', '①', '②' }; return text.Trim(TrimChar); } #region 2.4寸汉显屏 // 基础数据写入方法 public async void WriteChannelInfo(int type, string content, int drawerNo, int colNo) { try { canBusSerial.DiscardInBuffer(); Encoding.RegisterProvider(CodePagesEncodingProvider.Instance); byte[] contentBuf = Encoding.GetEncoding("gb2312").GetBytes(trim(content)); int channel = (drawerNo * 10 + colNo); if (contentBuf.Length % 2 != 0) { Array.Resize(ref contentBuf, contentBuf.Length + 1); } byte[] buffer = new byte[] { 0xaa, (byte)channel, 1, (byte)type, 0, 0, 0, 0xee }; canBusSerial.Write(buffer, 0, 8); await Task.Delay(20); buffer[4] = 1; for (int i = 0; i < contentBuf.Length; i += 2) { buffer[5] = contentBuf[i]; buffer[6] = contentBuf[i + 1]; canBusSerial.Write(buffer, 0, 8); await Task.Delay(20); } buffer[4] = 2; buffer[5] = 0; buffer[6] = 0; canBusSerial.Write(buffer, 0, 8); await Task.Delay(20); } catch (Exception ex) { _eventAggregator.GetEvent().Publish(new util.DeviceMsg() { EventType = util.EventType.OPENERROR, WindowName = WindowName, Message = $"2.4寸汉显屏异常{ex.Message}" }); logger.Info($"2.4寸汉显屏异常:ex:{ex.Message}"); } } // 清除显示内容 public async Task ClearContent(int drawerNo, int colNo) { canBusSerial.DiscardInBuffer(); int channel = (drawerNo * 10 + colNo); byte[] buffer = new byte[] { 0xaa, (byte)channel, 4, 0, 0, 0, 0, 0xee }; canBusSerial.Write(buffer, 0, 8); } // 刷新显示内容 public async Task ShowContent(int drawerNo, int colNo) { try { canBusSerial.DiscardInBuffer(); int channel = (drawerNo * 10 + colNo); byte[] buffer = new byte[] { 0xaa, (byte)channel, 2, 0, 0, 0, 0, 0xee }; canBusSerial.Write(buffer, 0, 8); } catch (Exception ex) { _eventAggregator.GetEvent().Publish(new util.DeviceMsg() { EventType = util.EventType.OPENERROR, WindowName = WindowName, Message = $"刷新显示内容异常{ex.Message}" }); logger.Info($"刷新显示内容异常:ex:{ex.Message}"); } } // 取药或者加药亮灯 public void TakeQuantity(int drawerNo, int colNo, int quantity, int stock) { try { canBusSerial.DiscardInBuffer(); int channel = Convert.ToInt32((drawerNo * 10 + colNo).ToString(), 16); byte[] buffer = new byte[] { 0xaa, (byte)channel, 6, 0, 0, 0, 0, 0xee }; buffer[3] = (byte)(quantity >> 8); buffer[4] = (byte)(quantity & 0xff); buffer[5] = (byte)(stock >> 8); buffer[6] = (byte)(stock & 0xff); canBusSerial.Write(buffer, 0, 8); } catch (Exception ex) { _eventAggregator.GetEvent().Publish(new util.DeviceMsg() { EventType = util.EventType.OPENERROR, WindowName = WindowName, Message = $"操作发生异常{ex.Message}" }); logger.Info($"操作发生异常:ex:{ex.Message}"); } } // 写入数量 public void WriteQuantity(int drawerNo, int colNo, int quantity) { try { canBusSerial.DiscardInBuffer(); int channel = (drawerNo * 10 + colNo); byte[] buffer = new byte[] { 0xaa, (byte)channel, 0x21, 0, 0, 0, 0, 0xee }; buffer[5] = (byte)(quantity >> 8); buffer[6] = (byte)(quantity & 0xff); canBusSerial.Write(buffer, 0, 8); } catch (Exception ex) { _eventAggregator.GetEvent().Publish(new util.DeviceMsg() { EventType = util.EventType.OPENERROR, WindowName = WindowName, Message = $"操作发生异常{ex.Message}" }); logger.Info($"操作发生异常:ex:{ex.Message}"); } } #endregion #region 药盒标签显示屏 //清屏 public void ClearContentMethod(int drawerNo, int colNo) { decimal deColNo = colNo; //var channel = drawerNo * 10 + Math.Ceiling(deColNo / 3); int[] iNum = new int[] { 3, 2, 1 }; var colNo2 = colNo % 3 > 0 ? (colNo % 3) - 1 : 2; var bColNo = Convert.ToInt32((iNum[colNo2] + 10).ToString(), 16); //var index = Convert.ToInt32(((colNo % 3 == 0 ? 3 : colNo % 3)+10).ToString(),16); int channel = Convert.ToInt32((drawerNo * 10 + Math.Ceiling((decimal)colNo / 3)).ToString(), 16); byte[] buffer = new byte[] { 0xaa, (byte)channel, 0x09, (byte)bColNo, 0, 0, 0, 0xee }; canBusSerial.Write(buffer, 0, 8); logger.Info($"清屏指令:{Convert.ToHexString(buffer)}"); } //刷新内容 public async Task ShowContentMethod(int drawerNo, int colNo) { int channel = Convert.ToInt32((drawerNo * 10 + Math.Ceiling((decimal)colNo / 3)).ToString(), 16); byte[] buffer = new byte[] { 0xaa, (byte)channel, 0x0c, 0x00, 0x00, 0x00, 0x00, 0xee }; logger.Info($"刷新内容指令:{Convert.ToHexString(buffer)}"); canBusSerial.Write(buffer, 0, 8); } // 基础数据写入方法 public async Task WriteChannelInfoMethod(int type, string content, int drawerNo, int colNo) { try { canBusSerial.DiscardInBuffer(); Encoding.RegisterProvider(CodePagesEncodingProvider.Instance); if (content.Length > 10) { content = content.Substring(0, 10); } byte[] contentBuf = Encoding.GetEncoding("gb2312").GetBytes(trim(content)); int channel = Convert.ToInt32((drawerNo * 10 + Math.Ceiling((decimal)colNo / 3)).ToString(), 16); int[] iNum = new int[] { 3, 2, 1 }; var colNo2 = colNo % 3 > 0 ? (colNo % 3) - 1 : 2; var bColNo = iNum[colNo2] + 160; //var index = (colNo % 3 == 0 ? 3 : colNo % 3)+160; if (contentBuf.Length % 2 != 0) { Array.Resize(ref contentBuf, contentBuf.Length + 1); } byte[] buffer = new byte[] { 0xaa, (byte)channel, (byte)bColNo, (byte)type, 0, 0, 0, 0xee }; canBusSerial.Write(buffer, 0, 8); logger.Info($"开始写标签指令:{Convert.ToHexString(buffer)}"); Thread.Sleep(20); buffer[4] = 1; for (int i = 0; i < contentBuf.Length; i += 2) { buffer[5] = contentBuf[i]; buffer[6] = contentBuf[i + 1]; canBusSerial.Write(buffer, 0, 8); logger.Info($"写标签指令:{Convert.ToHexString(buffer)}"); Thread.Sleep(50); } buffer[4] = 2; buffer[5] = 0; buffer[6] = 0; canBusSerial.Write(buffer, 0, 8); logger.Info($"结束写标签指令:{Convert.ToHexString(buffer)}"); Thread.Sleep(20); } catch (Exception ex) { _eventAggregator.GetEvent().Publish(new util.DeviceMsg() { EventType = util.EventType.OPENERROR, WindowName = WindowName, Message = $"2.4寸汉显屏异常{ex.Message}" }); logger.Info($"2.4寸汉显屏异常:ex:{ex.Message}"); } } public async Task WriteQuantityMethod(int quantity, int drawerNo, int colNo) { try { logger.Info($"写数量:{drawerNo}-{colNo}:{quantity}"); canBusSerial.DiscardInBuffer(); Encoding.RegisterProvider(CodePagesEncodingProvider.Instance); string strQuantity = quantity.ToString("X"); if (strQuantity.Length % 2 != 0) { strQuantity = "0" + strQuantity; } int channel = Convert.ToInt32((drawerNo * 10 + Math.Ceiling((decimal)colNo / 3)).ToString(), 16); int[] iNum = new int[] { 3, 2, 1 }; var colNo2 = colNo % 3 > 0 ? (colNo % 3) - 1 : 2; var bColNo = iNum[colNo2] + 160; byte[] buffer = new byte[] { 0xaa, (byte)channel, (byte)bColNo, 0xf2, 01, 0, 0, 0xee }; if (strQuantity.Length >= 4) { buffer[5] = Convert.ToByte(strQuantity.Substring(0, 2), 16); buffer[6] = Convert.ToByte(strQuantity.Substring(2, 2), 16); } else { buffer[6] = Convert.ToByte(strQuantity.Substring(0, 2), 16); } canBusSerial.Write(buffer, 0, 8); logger.Info($"写标签指令:{Convert.ToHexString(buffer)}"); } catch (Exception ex) { _eventAggregator.GetEvent().Publish(new util.DeviceMsg() { EventType = util.EventType.OPENERROR, WindowName = WindowName, Message = $"写标签数量异常{ex.Message}" }); logger.Info($"写标签数量异常:ex:{ex.Message}"); } } #endregion #region 回收箱操作 // 打开回收箱 public async Task OpenRecover() { try { byte[] buffer = null; canBusSerial.DiscardInBuffer(); if (ColNos.Length > 0) { if (ColNos.Contains(1) || ColNos.Contains(2) || ColNos.Contains(3)) { buffer = new byte[] { 0xAA, 0x9A, 0x04, 0x01, 0x00, 0x00, 0x00, 0xEE }; } else { buffer = new byte[] { 0xAA, 0x9A, 0x04, 0x02, 0x00, 0x00, 0x00, 0xEE }; } } else { buffer = new byte[] { 0xAA, 0x9A, 0x04, 0x00, 0x00, 0x00, 0x00, 0xEE }; } canBusSerial.Write(buffer, 0, 8); return await GetBufferByPort(canBusSerial, 8); } catch (Exception ex) { _eventAggregator.GetEvent().Publish(new util.DeviceMsg() { EventType = util.EventType.OPENERROR, WindowName = WindowName, Message = $"操作发生异常{ex.Message}" }); logger.Info($"操作发生异常:ex:{ex.Message}"); return null; } } // 回收箱状态查询 public async Task CheckRecoverStatus() { try { canBusSerial.DiscardInBuffer(); byte[] buffer = new byte[] { 0xAA, 0x9A, 0x03, 0x00, 0x00, 0x00, 0x00, 0xEE }; canBusSerial.Write(buffer, 0, 8); return await GetBufferByPort(canBusSerial, 8); } catch (Exception ex) { _eventAggregator.GetEvent().Publish(new util.DeviceMsg() { EventType = util.EventType.OPENERROR, WindowName = WindowName, Message = $"操作发生异常{ex.Message}" }); logger.Info($"操作发生异常:ex:{ex.Message}"); return null; } } // 回收箱回收数量查询 public async Task CheckRecoverQuantity() { try { canBusSerial.DiscardInBuffer(); byte[] buffer = new byte[] { 0xAA, 0x9A, (byte)(ColNos[0] > 3 ? 2 : 1), 0x00, 0x00, 0x00, 0x00, 0xEE }; //byte[] buffer = new byte[] { 0xAA, 0x9A, 01, (byte)(ColNos[0] > 3 ? 2 : 1), 0x00, 0x00, 0x00, 0xEE }; canBusSerial.Write(buffer, 0, 8); return await GetBufferByPort(canBusSerial, 8); } catch (Exception ex) { _eventAggregator.GetEvent().Publish(new util.DeviceMsg() { EventType = util.EventType.OPENERROR, WindowName = WindowName, Message = $"操作发生异常{ex.Message}" }); logger.Info($"操作发生异常:ex:{ex.Message}"); return null; } } #endregion #region 称重操作 // 以板子为单位获取抽屉内所有库位的药品数量 public async Task CheckQuantityByAddr() { canBusSerial.DiscardInBuffer(); var channel = Convert.ToInt32((DrawerNo * 10 + 1).ToString(), 16); byte[] buffer = new byte[] { 0xaa, (byte)(channel), 0x28, 0x00, 0x00, 0x00, 0x00, 0xee }; logger.Info($"称重发送库位数量查询1【{Convert.ToHexString(buffer)}】"); canBusSerial.Write(buffer, 0, 8); byte[] result1 = await GetBufferByPort(canBusSerial, 8); var channel2 = Convert.ToInt32((DrawerNo * 10 + 2).ToString(), 16); byte[] buffer2 = new byte[] { 0xaa, (byte)(channel2), 0x28, 0x00, 0x00, 0x00, 0x00, 0xee }; logger.Info($"称重发送库位数量查询2【{Convert.ToHexString(buffer2)}】"); canBusSerial.Write(buffer2, 0, 8); byte[] result2 = await GetBufferByPort(canBusSerial, 8); byte[] res = new byte[6]; Array.Copy(result1, 3, res, 0, 3); Array.Copy(result2, 3, res, 3, 3); return res; } // 以板子为单位获取抽屉内所有库位的药品数量 public async Task CheckQuantityByAddrForMulti() { int[] res = new int[9]; for (int i = 0; i < ColNoLst.Count; i++) { Thread.Sleep(200); canBusSerial.DiscardInBuffer(); int colNo = ColNoLst[i]; int[] iNum = new int[] { 3, 2, 1 }; var colNo2 = colNo % 3 > 0 ? (colNo % 3) - 1 : 2; var bColNo = iNum[colNo2]; decimal decolNO = (decimal)colNo; var channel = Convert.ToInt32((DrawerNo * 10 + Math.Ceiling(decolNO / 3)).ToString(), 16); byte[] buffer = new byte[] { 0xaa, (byte)(channel), 0x27, (byte)bColNo, 0x00, 0x00, 0x00, 0xee }; logger.Info($"称重发送库位数量查询{ColNoLst[i]}【{Convert.ToHexString(buffer)}】"); canBusSerial.Write(buffer, 0, 8); byte[] result = await GetBufferByPort(canBusSerial, 8); logger.Info($"称重发送库位数量查询返回结果【{Convert.ToHexString(result)}】"); byte[] hl = result.Skip(4).Take(2).ToArray(); var r = Convert.ToHexString(result).Substring(8, 1); int quantity = 0; if (r == "8") { hl[0] -= 0x80; quantity = BitConverter.ToInt16(hl.Reverse().ToArray(), 0); logger.Info($"获取值为负数{quantity}"); quantity = 0 - quantity; } else { quantity = BitConverter.ToInt16(hl.Reverse().ToArray(), 0); logger.Info($"获取值为正数{quantity}"); } res[ColNoLst[i] - 1] = quantity; } return res; } //获取单个称重药合的药品数量 --查数 public async Task CheckQuantityForSingle(int colNo) { //await Task.Delay(300); //canBusSerial.DiscardInBuffer(); //var index = colNo % 3 == 0 ? 3 : colNo % 3; //var lock1 = colNo <= 3 ? 3 : colNo >= 7 ? 1 : 2; //var channel = Convert.ToInt32((DrawerNo * 10 + index).ToString(), 16); canBusSerial.DiscardInBuffer(); int[] iNum = new int[] { 3, 2, 1 }; var colNo2 = colNo % 3 > 0 ? (colNo % 3) - 1 : 2; var bColNo = iNum[colNo2]; decimal decolNO = (decimal)colNo; var channel = Convert.ToInt32((DrawerNo * 10 + Math.Ceiling(decolNO / 3)).ToString(), 16); byte[] buffer = new byte[] { 0xaa, (byte)(channel), 0x27, (byte)bColNo, 0x00, 0x00, 0x00, 0xee }; logger.Info($"称重发送库位数量查询{colNo}【{Convert.ToHexString(buffer)}】"); canBusSerial.Write(buffer, 0, 8); byte[] result = await GetBufferByPort(canBusSerial, 8); byte[] hl = result.Skip(4).Take(2).ToArray(); var r = Convert.ToHexString(result).Substring(8, 1); logger.Info($"称重发送库位数量查询返回结果【{Convert.ToHexString(result)}】"); if (r == "8") { hl[0] -= 0x80; int quantity = BitConverter.ToInt16(hl.Reverse().ToArray(), 0); logger.Info($"获取值为负数{quantity}"); return 0 - quantity; } else { int quantity = BitConverter.ToInt16(hl.Reverse().ToArray(), 0); logger.Info($"获取值为正数{quantity}"); return quantity; } } //获取单个称重药合的药品数量---标定 public async Task CheckQuantityForBiaoDing(int colNo) { //await Task.Delay(300); //canBusSerial.DiscardInBuffer(); //var index = colNo % 3 == 0 ? 3 : colNo % 3; //var lock1 = colNo <= 3 ? 3 : colNo >= 7 ? 1 : 2; //var channel = Convert.ToInt32((DrawerNo * 10 + index).ToString(), 16); canBusSerial.DiscardInBuffer(); int[] iNum = new int[] { 3, 2, 1 }; var colNo2 = colNo % 3 > 0 ? (colNo % 3) - 1 : 2; var bColNo = iNum[colNo2]; decimal decolNO = (decimal)colNo; var channel = Convert.ToInt32((DrawerNo * 10 + Math.Ceiling(decolNO / 3)).ToString(), 16); byte[] buffer = new byte[] { 0xaa, (byte)(channel), 0x27, (byte)bColNo, 0x00, 0x00, 0x00, 0xee }; logger.Info($"称重发送库位数量查询{colNo}【{Convert.ToHexString(buffer)}】"); canBusSerial.Write(buffer, 0, 8); byte[] result = await GetBufferByPort(canBusSerial, 8); logger.Info($"称重发送库位数量查询返回结果【{Convert.ToHexString(result)}】"); byte[] hl = result.Skip(4).Take(2).ToArray(); int quantity = BitConverter.ToInt16(hl.Reverse().ToArray(), 0); return quantity; } // 以板子为单位获取抽屉内所有库位的药品数量 public async Task CheckQuantityByAddr2() { int[] res = new int[9]; for (int i = 0; i < ColNos.Length; i++) { await Task.Delay(300); canBusSerial.DiscardInBuffer(); int colNo = ColNos[i]; int[] iNum = new int[] { 3, 2, 1 }; var colNo2 = colNo % 3 > 0 ? (colNo % 3) - 1 : 2; var bColNo = iNum[colNo2]; decimal decolNO = (decimal)colNo; var channel = Convert.ToInt32((DrawerNo * 10 + Math.Ceiling(decolNO / 3)).ToString(), 16); byte[] buffer = new byte[] { 0xaa, (byte)(channel), 0x27, (byte)bColNo, 0x00, 0x00, 0x00, 0xee }; logger.Info($"称重发送库位数量查询{ColNos[i]}【{Convert.ToHexString(buffer)}】"); canBusSerial.Write(buffer, 0, 8); byte[] result = await GetBufferByPort(canBusSerial, 8); logger.Info($"称重发送库位数量查询返回结果【{Convert.ToHexString(result)}】"); byte[] hl = result.Skip(4).Take(2).ToArray(); //int quantity = BitConverter.ToInt16(hl.Reverse().ToArray(), 0); var r = Convert.ToHexString(result).Substring(8, 1); int quantity = 0; if (r == "8") { hl[0] -= 0x80; quantity = BitConverter.ToInt16(hl.Reverse().ToArray(), 0); logger.Info($"获取值为负数{quantity}"); quantity = 0 - quantity; } else { quantity = BitConverter.ToInt16(hl.Reverse().ToArray(), 0); logger.Info($"获取值为正数{quantity}"); } res[ColNos[i] - 1] = quantity; } return res; } // 指定药盒指示灯开启使能开锁 public async Task BoxLockLightOn2() { for (int i = 0; i < ColNos.Length; i++) { int colNo = ColNos[i]; int[] iNum = new int[] { 3, 2, 1 }; var colNo2 = colNo % 3 > 0 ? (colNo % 3) - 1 : 2; var bColNo = iNum[colNo2]; decimal decolNO = (decimal)colNo; var channel = Convert.ToInt32((DrawerNo * 10 + Math.Ceiling(decolNO / 3)).ToString(), 16); byte[] buffer = new byte[] { 0xaa, (byte)(channel), 0x03, (byte)bColNo, 0x00, 0x00, 0x00, 0xee }; logger.Info($"称重发送药盒使能【{Convert.ToHexString(buffer)}】"); canBusSerial.Write(buffer, 0, 8); await Task.Delay(TimeSpan.FromMilliseconds(500)); } } // 指定药盒指示灯开启失能开锁 public async Task BoxLockLightOff2() { canBusSerial.DiscardInBuffer(); for (int i = 0; i < ColNos.Length; i++) { int colNo = ColNos[i]; int[] iNum = new int[] { 3, 2, 1 }; var colNo2 = colNo % 3 > 0 ? (colNo % 3) - 1 : 2; var bColNo = iNum[colNo2]; decimal decolNO = (decimal)colNo; var channel = Convert.ToInt32((DrawerNo * 10 + Math.Ceiling(decolNO / 3)).ToString(), 16); byte[] buffer = new byte[] { 0xaa, (byte)(channel), 0x04, (byte)bColNo, 0x00, 0x00, 0x00, 0xee }; logger.Info($"称重发送药盒失能【{Convert.ToHexString(buffer)}】"); canBusSerial.Write(buffer, 0, 8); await Task.Delay(TimeSpan.FromMilliseconds(50)); } } //计数请零 public async Task ClearCount(int DrawerNo, int ColNo) { try { canBusSerial.DiscardInBuffer(); int[] iNum = new int[] { 3, 2, 1 }; var colNo2 = ColNo % 3 > 0 ? (ColNo % 3) - 1 : 2; var bColNo = iNum[colNo2]; decimal decolNO = (decimal)ColNo; var channel = Convert.ToInt32((DrawerNo * 10 + Math.Ceiling(decolNO / 3)).ToString(), 16); byte[] buffer = new byte[] { 0xaa, (byte)(channel), 0x25, (byte)bColNo, 0x00, 0x00, 0x00, 0xee }; logger.Info($"称重发送清空计数【{Convert.ToHexString(buffer)}】"); canBusSerial.Write(buffer, 0, 8); } catch (Exception ex) { _eventAggregator.GetEvent().Publish(new util.DeviceMsg() { EventType = util.EventType.OPENERROR, WindowName = WindowName, Message = $"操作发生异常{ex.Message}" }); logger.Info($"操作发生异常:ex:{ex.Message},方法名:ClearCount;参数:{DrawerNo},{ColNo}"); } } public async Task SetNumCount(int DrawerNo, int ColNo, int Quantity) { try { canBusSerial.DiscardInBuffer(); int[] iNum = new int[] { 3, 2, 1 }; var colNo2 = ColNo % 3 > 0 ? (ColNo % 3) - 1 : 2; var bColNo = iNum[colNo2]; decimal decolNO = (decimal)ColNo; var channel = Convert.ToInt32((DrawerNo * 10 + Math.Ceiling(decolNO / 3)).ToString(), 16); byte[] buffer = new byte[] { 0xaa, (byte)(channel), 0x26, (byte)bColNo, 0x00, 0x00, 0x00, 0xee }; buffer[4] = (byte)(Quantity & 0xff); //buffer[4] = (byte)(Quantity >> 8); //buffer[5] = (byte)(Quantity & 0xff); logger.Info($"标定数量【{Convert.ToHexString(buffer)}】"); canBusSerial.Write(buffer, 0, 8); } catch (Exception ex) { _eventAggregator.GetEvent().Publish(new util.DeviceMsg() { EventType = util.EventType.OPENERROR, WindowName = WindowName, Message = $"操作发生异常{ex.Message}" }); logger.Info($"操作发生异常:ex:{ex.Message},方法名:SetNumCount;参数:{DrawerNo},{ColNo},{Quantity}"); } } /// /// 冰箱使能 /// /// public async Task FridegOpen() { try { fridgeSerial.DiscardInBuffer(); byte[] buffer = new byte[] { 0x01, 0x06, 0x10, 0xD4, 0x00, 0x01, 0x0C, 0xF2 }; //byte[] buffer = new byte[] { 0x01, 0x06, 0x10, 0xD4, 0x00, 0x01 }; ////获取数组CRC校验码 //byte[] byteDate = CRC16MODBUS.CrcModBus(buffer); ////Array.Reverse(byteDate); //int dataLength = buffer.Length; //Array.Resize(ref buffer, dataLength + byteDate.Length); //for (int i = 0; i < byteDate.Length; i++) //{ // buffer[dataLength + i] = byteDate[i]; //} logger.Info($"冰箱使能【{Convert.ToHexString(buffer)}】"); fridgeSerial.Write(buffer, 0, 8); await Task.Delay(80); } catch (Exception ex) { logger.Info($"冰箱使能发生异常:ex:{ex.Message}"); } FridgeOperate = false; } /// /// 冰箱失能 /// /// public async Task FridgeOff() { try { fridgeSerial.DiscardInBuffer(); byte[] buffer = new byte[] { 0x01, 0x06, 0x10, 0xD4, 0x00, 0x00, 0xCD, 0x32 }; //byte[] buffer = new byte[] { 0x01, 0x06, 0x10, 0xD4, 0x00, 0x01 }; ////获取数组CRC校验码 //byte[] byteDate = CRC16MODBUS.CrcModBus(buffer); ////Array.Reverse(byteDate); //int dataLength = buffer.Length; //Array.Resize(ref buffer, dataLength + byteDate.Length); //for (int i = 0; i < byteDate.Length; i++) //{ // buffer[dataLength + i] = byteDate[i]; //} logger.Info($"冰箱失能【{Convert.ToHexString(buffer)}】"); fridgeSerial.Write(buffer, 0, 8); await Task.Delay(80); } catch (Exception ex) { logger.Info($"冰箱失能发生异常:ex:{ex.Message}"); } FridgeOperate = false; } /// /// 冰箱报警使能 /// /// public async Task FridgeAlarmOn() { try { fridgeSerial.DiscardInBuffer(); byte[] buffer = new byte[] { 0x01, 0x06, 0x10, 0xD5, 0x00, 0x01, 0x5D, 0x32 }; //byte[] buffer = new byte[] { 0x01, 0x06, 0x10, 0xD5, 0x00, 0x01 }; ////获取数组CRC校验码 //byte[] byteDate = CRC16MODBUS.CrcModBus(buffer); ////Array.Reverse(byteDate); //int dataLength = buffer.Length; //Array.Resize(ref buffer, dataLength + byteDate.Length); //for (int i = 0; i < byteDate.Length; i++) //{ // buffer[dataLength + i] = byteDate[i]; //} logger.Info($"冰箱报警使能【{Convert.ToHexString(buffer)}】"); fridgeSerial.Write(buffer, 0, 8); await Task.Delay(80); } catch (Exception ex) { logger.Info($"冰箱报警使能发生异常:ex:{ex.Message}"); } FridgeOperate = false; } /// /// 冰箱报警失能 /// /// public async Task FridgeAlarmOff() { try { fridgeSerial.DiscardInBuffer(); byte[] buffer = new byte[] { 0x01, 0x06, 0x10, 0xD5, 0x00, 0x00, 0x9C, 0xF2 }; //byte[] buffer = new byte[] { 0x01, 0x06, 0x10, 0xD5, 0x00, 0x00 }; ////获取数组CRC校验码 //byte[] byteDate = CRC16MODBUS.CrcModBus(buffer); ////Array.Reverse(byteDate); //int dataLength = buffer.Length; //Array.Resize(ref buffer, dataLength + byteDate.Length); //for (int i = 0; i < byteDate.Length; i++) //{ // buffer[dataLength + i] = byteDate[i]; //} logger.Info($"冰箱报警失能【{Convert.ToHexString(buffer)}】"); fridgeSerial.Write(buffer, 0, 8); await Task.Delay(80); } catch (Exception ex) { logger.Info($"冰箱报警失能发生异常:ex:{ex.Message}"); } FridgeOperate = false; } /// /// 冰箱温度设定最小 /// /// public async Task FridgeMinSetting(float min) { try { int iMix = Convert.ToInt32(min * 10); fridgeSerial.DiscardInBuffer(); //byte[] bufferMin = new byte[] { 0x01, 0x06, 0x10, 0xC9, 0x00, 0x15, 0x9C, 0xFB }; byte[] bufferMin = new byte[] { 0x01, 0x06, 0x10, 0xC9, 0x00, (byte)(iMix & 0xff) }; //获取数组CRC校验码 byte[] byteDate = CRC16MODBUS.CrcModBus(bufferMin); //Array.Reverse(byteDate); int dataLength = bufferMin.Length; Array.Resize(ref bufferMin, dataLength + byteDate.Length); for (int i = 0; i < byteDate.Length; i++) { bufferMin[dataLength + i] = byteDate[i]; } logger.Info($"冰箱温度设定Min:【{Convert.ToHexString(bufferMin)}】"); fridgeSerial.Write(bufferMin, 0, 8); } catch (Exception ex) { logger.Info($"获取冰箱温度发生异常:ex:{ex.Message}"); } } /// /// 冰箱温度设定最大 /// /// public async Task FridgeMaxSetting(float max) { try { int iMax = Convert.ToInt32(max * 10); fridgeSerial.DiscardInBuffer(); //byte[] bufferMin = new byte[] { 0x01, 0x06, 0x10, 0xC9, 0x00, 0x15, 0x9C, 0xFB }; byte[] bufferMax = new byte[] { 0x01, 0x06, 0x10, 0xC8, 0x00, (byte)(iMax & 0xff) }; //获取数组CRC校验码 byte[] byteDate = CRC16MODBUS.CrcModBus(bufferMax); //Array.Reverse(byteDate); int dataLength = bufferMax.Length; Array.Resize(ref bufferMax, dataLength + byteDate.Length); for (int i = 0; i < byteDate.Length; i++) { bufferMax[dataLength + i] = byteDate[i]; } logger.Info($"冰箱温度设定Max:【{Convert.ToHexString(bufferMax)}】"); fridgeSerial.Write(bufferMax, 0, 8); } catch (Exception ex) { logger.Info($"获取冰箱温度发生异常:ex:{ex.Message}"); } } /// /// 获取冰箱温度 /// /// public async Task GetFridgeTemperature() { float temperature = 0.0f; try { fridgeSerial.DiscardInBuffer(); byte[] buffer = new byte[] { 0x01, 0x03, 0x10, 0x02, 0x00, 0x01, 0x21, 0x0A }; //byte[] buffer = new byte[] { 0x01, 0x03, 0x10, 0x02, 0x00, 0x01 }; ////获取数组CRC校验码 //byte[] byteDate = CRC16MODBUS.CrcModBus(buffer); ////Array.Reverse(byteDate); //int dataLength = buffer.Length; //Array.Resize(ref buffer, dataLength + byteDate.Length); //for (int i = 0; i < byteDate.Length; i++) //{ // buffer[dataLength + i] = byteDate[i]; //} logger.Info($"获取冰箱温度【{Convert.ToHexString(buffer)}】"); fridgeSerial.Write(buffer, 0, 8); byte[] retByte = await GetBufferByPort(fridgeSerial, 7); logger.Info($"获取冰箱温度返回【{Convert.ToHexString(retByte)}】"); if (retByte != null && retByte.Length >= 7) { var hight = retByte[3]; var low = retByte[4]; int iHight = Convert.ToInt32(hight << 8); int iLow = Convert.ToInt32(retByte[4]); temperature = Convert.ToSingle(iHight + iLow) / 10; } } catch (Exception ex) { logger.Info($"获取冰箱温度发生异常:ex:{ex.Message}"); } return temperature; } //读制冷片温度 public async Task GetFridgeTemperature2() { float temperature = 0.0f; try { fridgeSerial.DiscardInBuffer(); byte bAddress; byte[] buffer = new byte[] { 0x01, 0x03, 0x10, 0x0C, 0x00, 0x01, 0x40, 0xC9 }; //byte[] buffer = new byte[] { 0x01, 0x03, 0x10, 0x02, 0x00, 0x01 }; ////获取数组CRC校验码 //byte[] byteDate = CRC16MODBUS.CrcModBus(buffer); ////Array.Reverse(byteDate); //int dataLength = buffer.Length; //Array.Resize(ref buffer, dataLength + byteDate.Length); //for (int i = 0; i < byteDate.Length; i++) //{ // buffer[dataLength + i] = byteDate[i]; //} logger.Info($"获制冷片温度【{Convert.ToHexString(buffer)}】"); fridgeSerial.Write(buffer, 0, 8); byte[] retByte = await GetBufferByPort(fridgeSerial, 7); logger.Info($"获取制冷片温度返回【{Convert.ToHexString(retByte)}】"); if (retByte != null && retByte.Length >= 7) { var hight = retByte[3]; var low = retByte[4]; int iHight = Convert.ToInt32(hight << 8); int iLow = Convert.ToInt32(retByte[4]); temperature = Convert.ToSingle(iHight + iLow) / 10; } } catch (Exception ex) { logger.Info($"获取制冷片温度发生异常:ex:{ex.Message}"); } return temperature; } /// /// 设置冰箱温度 /// /// public async Task SetFridgeTemperature(float temperature) { int tpt = (int)temperature * 10; byte Temperature = (byte)(tpt & 0xff); try { //if (!FridgeOperate) { fridgeSerial.DiscardInBuffer(); //byte[] buffer = new byte[] { 0x01, 0x03, 0x10, 0x02, 0x00, 0x01, 0x21,0x0A }; byte[] buffer = new byte[] { 0x01, 0x06, 0x10, 0x02, 0x00, (byte)Temperature }; //获取数组CRC校验码 byte[] byteDate = CRC16MODBUS.CrcModBus(buffer); //Array.Reverse(byteDate); int dataLength = buffer.Length; Array.Resize(ref buffer, dataLength + byteDate.Length); for (int i = 0; i < byteDate.Length; i++) { buffer[dataLength + i] = byteDate[i]; } logger.Info($"设置冰箱温度【{Convert.ToHexString(buffer)}】"); fridgeSerial.Write(buffer, 0, 8); await GetBufferByPort(fridgeSerial, 8); } } catch (Exception ex) { logger.Info($"获取冰箱温度发生异常:ex:{ex.Message}"); } return temperature; } /// /// 冰箱延迟报警 /// /// public async Task FridgeDelayWarm() { try { //if (!FridgeOperate) { fridgeSerial.DiscardInBuffer(); byte[] buffer = new byte[] { 0x01, 0x06, 0x10, 0xCD, 0x00, 0x01, 0xDD, 0x35 }; //byte[] buffer = new byte[] { 0x01, 0x06, 0x10, 0xCD, 0x00, 0x01 }; ////获取数组CRC校验码 //byte[] byteDate = CRC16MODBUS.CrcModBus(buffer); ////Array.Reverse(byteDate); //int dataLength = buffer.Length; //Array.Resize(ref buffer, dataLength + byteDate.Length); //for (int i = 0; i < byteDate.Length; i++) //{ // buffer[dataLength + i] = byteDate[i]; //} logger.Info($"冰箱延迟报警【{Convert.ToHexString(buffer)}】"); fridgeSerial.Write(buffer, 0, 8); } } catch (Exception ex) { logger.Info($"获取冰箱温度发生异常:ex:{ex.Message}"); } //FridgeOperate = false; } #endregion #endregion //标定获取药盒数量 private byte[] GetBufferByPortForBiaoDing(SerialPort serialPort, int length, int timeout) { byte[] buffer = new byte[length]; int _length = 0; DateTime start = DateTime.Now; DateTime end = DateTime.Now; while (_length != length && end.Subtract(start).TotalMilliseconds < timeout) { _length = serialPort.BytesToRead; end = DateTime.Now; } if (_length != length) { //throw new TimeoutException($"串口【{serialPort.PortName}】交互超时"); //_length = serialPort.BytesToRead; //end = DateTime.Now; //logger.Info($"读到数据{}"); } serialPort.Read(buffer, 0, length); return buffer; } } }