198 lines
6.5 KiB
C#
198 lines
6.5 KiB
C#
///
|
|
/// Copyright (c) 2015-2019 Sensus Slovensko a.s.
|
|
///
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Diagnostics;
|
|
using System.Text;
|
|
using log4net;
|
|
using Config.Entities;
|
|
using TBF.BenchControl.Generic;
|
|
using TBF.Boxes;
|
|
|
|
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;
|
|
public QuidoVariant Variant { get { return quidoRSCfg.Variant; } }
|
|
|
|
readonly GenericDevices.IModbus modbus;
|
|
|
|
ushort watchdogBitMask;
|
|
|
|
private ushort currentOutputs;
|
|
private DateTime lastOutputsChange;
|
|
|
|
|
|
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");
|
|
}
|
|
|
|
/// <summary>Initialize this device</summary>
|
|
public override void Initialize()
|
|
{
|
|
watchdogBitMask = (ushort)(quidoRSCfg.WatchdogEnabled ? (1 << quidoRSCfg.WatchdogBitNr) : 0);
|
|
|
|
if (quidoRSCfg.DebugLevel == DebugMode.Simulate)
|
|
log.FatalFormat("{0} simulated: {1}", Name, this);
|
|
else
|
|
log.FatalFormat("{0} initialized: {1}", Name, this);
|
|
}
|
|
|
|
/// <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(ushort 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(ushort 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(ushort bitMask)
|
|
{
|
|
lock (this)
|
|
{
|
|
currentOutputs = (UInt16)((Int32)currentOutputs & (~(Int32)bitMask));
|
|
if (watchdogBitMask != 0)
|
|
{
|
|
currentOutputs = (UInt16)((Int32)currentOutputs ^ (Int32)watchdogBitMask);
|
|
}
|
|
SendOutputs(currentOutputs);
|
|
}
|
|
}
|
|
|
|
private void SendOutputs(ushort outputs)
|
|
{
|
|
byte addr = quidoRSCfg.ModbusAddress;
|
|
byte cmd = (byte)Function.ForceMultipleCoils;
|
|
byte dataLo = (byte)(outputs & 0xFF);
|
|
byte dataHi = (byte)(outputs >> 8);
|
|
|
|
if (quidoRSCfg.Variant == QuidoVariant.QuidoRS_2_16)
|
|
{
|
|
modbus.SendMessage(new byte[] { addr, cmd, 0, 0, 0, 16, 2, dataLo, dataHi, 0, 0 });
|
|
}
|
|
else 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 });
|
|
}
|
|
|
|
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(ushort 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);
|
|
}
|
|
}
|
|
}
|