Files
tbf/TBF/BenchControl/Modbus/QuidoRS/QuidoRS.cs
T

198 lines
6.6 KiB
C#

///
/// Copyright (c) 2015-2019 Sensus Slovensko a.s.
///
using System;
using System.Collections.Generic;
using log4net;
using TBF.BenchControl.Generic;
using TBF.Boxes;
using System.Text;
using System.Diagnostics;
namespace TBF.BenchControl.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<Generic.IComponent> 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");
watchdogBitMask = (ushort)(quidoRSCfg.WatchdogEnabled ? (1 << quidoRSCfg.WatchdogBitNr) : 0);
log.Warn(this.ToString());
}
///
/// IDevice interface
///
public void Initialize() { }
/// <summary>
/// Run this device
/// </summary>
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() { }
/// <summary>
/// Set outputs of QuidoRS board
/// </summary>
/// <param name="outputs">output value</param>
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);
}
}
/// <summary>
/// Set bit(s) specified by a bitMask. Leave other bits unaffeced.
/// </summary>
/// <param name="bitMask">Specifies bit(s) to set</param>
/// <param name="outputs">output value</param>
public void SetBit(UInt32 bitMask)
{
lock (this)
{
currentOutputs = (UInt16)((Int32)currentOutputs | (Int32)bitMask);
if (watchdogBitMask != 0)
{
currentOutputs = (UInt16)((Int32)currentOutputs ^ (Int32)watchdogBitMask);
}
SendOutputs(currentOutputs);
}
}
/// <summary>
/// Reset bit(s) specified by a bitMask. Leave other bits unaffeced.
/// </summary>
/// <param name="bitMask">Specifies bit(s) to reset</param>
/// <param name="outputs">output value</param>
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 });
}
else if (quidoRSCfg.Variant == QuidoVariant.QuidoRS_8_8)
{
modbus.SendMessage(new byte[] { addr, cmd, 0, 0, 0, 8, 1, dataLo, 0, 0 });
}
else if (quidoRSCfg.Variant == QuidoVariant.QuidoRS_2_16)
{
modbus.SendMessage(new byte[] { addr, cmd, 0, 0, 0, 16, 2, dataLo, data2, 0, 0 });
}
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 });
}
lastOutputsChange = DateTime.Now;
}
/// <summary>
/// Events: SetOpututsDone, Error
/// </summary>
/// <param name="outValue">Parallel output data</param>
/// <returns>SetOutputsOp operation casted to IOperaton</returns>
public IOperation SetOutputsOp(UInt32 outValue)
{
return new SetOutputsOp(this, outValue);
}
/// <summary>
/// Events: Event.None
/// </summary>
/// <returns>ShowBenchWaitingOp operation casted to generic IOperaton</returns>
public IOperation ShowBenchWaitingOp()
{
return new ShowBenchWaitingOp(this);
}
/// <summary>
/// Events: Event.None
/// </summary>
/// <returns>ShowBenchErrorOp operation casted to generic IOperaton</returns>
public IOperation ShowBenchErrorOp()
{
return new ShowBenchErrorOp(this);
}
}
}