/// /// Copyright (c) 2015-2019 Sensus Slovensko a.s. /// using System; using System.Collections.Generic; using log4net; using TBF.Rig.Generic; using TBF.Boxes; using System.Text; using System.Diagnostics; namespace TBF.Rig.Modbus.QuidoRS { public class QuidoRS : ComponentBase, IDevice, GenericDevices.IParallelOutput { private static readonly ILog log = LogManager.GetLogger(typeof(QuidoRS)); public override string ToString() { return string.Format("{0}({1})", ClassName, Cfg.ToString(-1)); } readonly QuidoRSCfg quidoRSCfg; readonly GenericDevices.IModbus modbus; public QuidoVariant Variant { get { return quidoRSCfg.Variant; } } private UInt32 currentOutputs; private DateTime lastOutputsChange; UInt32 watchdogBitMask; public QuidoRS() { } public QuidoRS(Generic.IComponentCfg cfg, IList components) : base(cfg) { quidoRSCfg = cfg as QuidoRSCfg; modbus = (GenericDevices.IModbus)TbfComponents.FindComponent(cfg.ParentName, components); if (modbus == null) throw new Exception("Cannot find " + Name + " parent"); log.Warn(this.ToString()); } public override void Initialize() { watchdogBitMask = (ushort)(quidoRSCfg.WatchdogEnabled ? (1 << quidoRSCfg.WatchdogBitNr) : 0); } /// /// IDevice interface /// public void RunDeviceBefore() { if (quidoRSCfg.DebugLevel == Config.Entities.DebugMode.Simulate) return; lock (this) { if (watchdogBitMask != 0 && (DateTime.Now - lastOutputsChange) > new TimeSpan(0, 0, 0, 0, 3000)) /// Toggle after 1.5 sec (resulting in toggle period 2 sec) { currentOutputs = (UInt16)((Int32)currentOutputs ^ (Int32)watchdogBitMask); SendOutputs(currentOutputs); } } if (modbus.ReceivedTelegrams[quidoRSCfg.ModbusAddress].Count > 0) { byte[] telegram = modbus.ReceivedTelegrams[quidoRSCfg.ModbusAddress].Dequeue(); if ((telegram.Length >= 8) && (telegram[1] == 0x11) && (telegram[2] == telegram.Length - 5)) { int msgLen = telegram.Length - 7; byte modbusAddress = telegram[3]; string msg = Encoding.ASCII.GetString(telegram, 5, msgLen); string s = string.Format("QuidoRS detected: Address={0}, Message={1}", modbusAddress, msg); Debug.WriteLine(s); log.Warn(s); } } } public void RunDeviceAfter() { } public void StopDevice() { SendOutputs(0); } public void StopDevice2() { } /// /// Set outputs of QuidoRS board /// /// output value public void SetOutputs(UInt32 outputs) { lock (this) { currentOutputs = (UInt16)((Int32)outputs | ((Int32)currentOutputs & (Int32)watchdogBitMask)); if (watchdogBitMask != 0) { currentOutputs = (UInt16)((Int32)currentOutputs ^ (Int32)watchdogBitMask); } SendOutputs(currentOutputs); } } /// /// Set bit(s) specified by a bitMask. Leave other bits unaffeced. /// /// Specifies bit(s) to set /// output value public void SetBit(UInt32 bitMask) { lock (this) { currentOutputs = (UInt16)((Int32)currentOutputs | (Int32)bitMask); if (watchdogBitMask != 0) { currentOutputs = (UInt16)((Int32)currentOutputs ^ (Int32)watchdogBitMask); } SendOutputs(currentOutputs); } } /// /// Reset bit(s) specified by a bitMask. Leave other bits unaffeced. /// /// Specifies bit(s) to reset /// output value public void ResetBit(UInt32 bitMask) { lock (this) { currentOutputs = (UInt16)((Int32)currentOutputs & (~(Int32)bitMask)); if (watchdogBitMask != 0) { currentOutputs = (UInt16)((Int32)currentOutputs ^ (Int32)watchdogBitMask); } SendOutputs(currentOutputs); } } private void SendOutputs(UInt32 outputs) { byte addr = quidoRSCfg.ModbusAddress; byte cmd = (byte)Function.ForceMultipleCoils; byte dataLo = (byte)(outputs & 0xFF); byte data2 = (byte)(outputs >> 8); byte data3 = (byte)(outputs >> 16); byte dataHi = (byte)(outputs >> 24); if (quidoRSCfg.Variant == QuidoVariant.QuidoRS_4_4) { modbus.SendMessage(new byte[] { addr, cmd, 0, 0, 0, 4, 1, dataLo, 0, 0 }, Name); } else if (quidoRSCfg.Variant == QuidoVariant.QuidoRS_8_8) { modbus.SendMessage(new byte[] { addr, cmd, 0, 0, 0, 8, 1, dataLo, 0, 0 }, Name); } else if (quidoRSCfg.Variant == QuidoVariant.QuidoRS_2_16) { modbus.SendMessage(new byte[] { addr, cmd, 0, 0, 0, 16, 2, dataLo, data2, 0, 0 }, Name); } else if (quidoRSCfg.Variant == QuidoVariant.QuidoRS_2_32) { modbus.SendMessage(new byte[] { addr, cmd, 0, 0, 0, 32, 4, dataLo, data2, data3, dataHi, 0, 0 }, Name); } lastOutputsChange = DateTime.Now; } /// /// Events: SetOpututsDone, Error /// /// Parallel output data /// SetOutputsOp operation casted to IOperaton public IOperation SetOutputsOp(UInt32 outValue) { return new SetOutputsOp(this, outValue); } /// /// Events: Event.None /// /// ShowBenchWaitingOp operation casted to generic IOperaton public IOperation ShowBenchWaitingOp() { return new ShowBenchWaitingOp(this); } /// /// Events: Event.None /// /// ShowBenchErrorOp operation casted to generic IOperaton public IOperation ShowBenchErrorOp() { return new ShowBenchErrorOp(this); } } }