laatzen/Common/modbus_master_csharp/Device/ModbusDeviceCom.cs

334 lines
10 KiB
C#

using MagFlux6200_metrology_reg_list;
using System.Collections.Generic;
using System.Numerics;
using System;
using XYLEM.Communication;
using System.IO.Ports;
using XYLEM.Base.Files;
using System.Threading.Tasks;
using XYLEM.Base;
namespace XYLEM.Device
{
public abstract class ModbusDeviceCom
{
protected ProgramLogCSVFileClass _logger = null;
UInt16 _device_id = 1;
ModbusCom _md_com = null;
#if (!DEBUG)
public Boolean DoComDebugPrint = false;
#else
//public Boolean DoComDebugPrint = true;
public Boolean DoComDebugPrint = false;
#if (DoComDebugPrint)
#warning DoTxValuePrint is true!!!!!!!!!!!!!!!!
#endif
const int ch_lng_dv = -15;
const int ch_lng_Version = -3;
const int ch_lng_MD_adr = -7;
const int dig_value = 10;
#endif
public ModbusDeviceCom()
{
}
public Boolean SetLogLocation(string path, string filename)
{
try
{
// If already created a _logger then
if (_logger != null)
{
// TODO: nothing to do right now
throw new Exception("Logger path can only be set one time");
}
_logger = new ProgramLogCSVFileClass(path, filename);
return true; // Okay
}
catch (Exception ex)
{
Console.WriteLine($"Fail to setup program log path!\nPath:{path}\nMessage:{ex.Message}");
}
return false; // failed
}
public void OpenLogFile()
{
// If already created a _logger then
if (_logger != null)
{
_logger.OpenProgramLogFile();
}
}
public string GetComCounters()
{
if (_md_com == null)
{
return "T=? E=?";
}
return $"T={_md_com.MsgCount} E={_md_com.MsgErrorCount}";
}
public Boolean IsConnected()
{
if (_md_com == null)
{
return false;
}
return _md_com.IsConnected();
}
public Boolean CloseConnection()
{
try
{
StopBackgroundChecking();
if (_md_com != null)
{
/*There is nothing to close right now*/
}
return true; // is okay
}
catch (Exception ex)
{
_logger.AddFuncLog(true, this.ToString(), "CloseConnection", "Fail to close connection", ex);
}
return false; // failed
}
public virtual Boolean Connect(string comport, int baudRate, Parity parity)
{
try
{
{// Normal
if (IsConnected())
{
CloseConnection();
}
_md_com = new ModbusCom(comport, baudRate, parity);
return _md_com.IsConnected(); // return result
}
}
catch (Exception ex)
{
_logger.AddFuncLog(true, this.ToString(), "Connect", "Fail to open connection", ex);
}
return false; // failed
}
#region Background service
System.Timers.Timer _BackgroundCheckingTimer = null;
protected void StartBackgroundChecking()
{
StopBackgroundChecking(); // Make sure that a already running one is stopped
_BackgroundCheckingTimer = new System.Timers.Timer(1000);
_BackgroundCheckingTimer.Elapsed += (sender, e) => HandleBackgroundChecking();
_BackgroundCheckingTimer.Start();
}
protected void StopBackgroundChecking()
{
if (_BackgroundCheckingTimer != null)
{
_BackgroundCheckingTimer.Stop();
_BackgroundCheckingTimer.Close();
_BackgroundCheckingTimer = null;
}
}
/// <summary>
/// Handle checking DUT and background reading device values
/// </summary>
/// <returns></returns>
private void HandleBackgroundChecking()
{
// Don't continue background service before the first has been serviced
if (_BackgroundCheckingTimer != null)
{
_BackgroundCheckingTimer.Stop();
}
try
{
RunBackgroundReadServiceFunction();
}
catch (Exception ex)
{
#if (DEBUG)
var message = $"Fail background service handling";
Console.WriteLine(message);
AppConst.Logger.AddFuncLog(true, this.ToString(), "HandleBackgroundChecking()", message, ex);
#endif // #if (DEBUG)
}
// Don't continue background service before the first has been serviced
if (_BackgroundCheckingTimer != null)
{
_BackgroundCheckingTimer.Start();
}
}
/// <summary>
/// Need to be overwritten with a function for polling periodically read information from device for checking health etc.
/// </summary>
protected abstract void RunBackgroundReadServiceFunction();
#endregion // Background service
#region ---------------- Generic modbus communications ---------------------
protected UInt16? read_U16(Device_value dv)
{
var ret = _md_com.Read(_device_id, dv, new UInt16());
if (ret.IsOkay)
{
var value = ret.Data;
#if (DEBUG)
if (DoComDebugPrint)
{
Console.WriteLine($"Read={dv,ch_lng_dv}: Reg_Ver={dv.Version,ch_lng_Version} Adr={dv.MD_adr,ch_lng_MD_adr} value={value,dig_value}");
}
#endif // #if (DEBUG)
return value;
}
return null; // Error in reading
}
protected UInt32? read_U32(Device_value dv)
{
var ret = _md_com.Read(_device_id, dv, new UInt32());
if (ret.IsOkay)
{
var value = ret.Data;
#if (DEBUG)
if (DoComDebugPrint)
{
Console.WriteLine($"Read={dv,ch_lng_dv}: Reg_Ver={dv.Version,ch_lng_Version} Adr={dv.MD_adr,ch_lng_MD_adr} value={value,dig_value}");
}
#endif // #if (DEBUG)
return value;
}
return null; // Error in reading
}
protected Single? read_F32(Device_value dv)
{
var ret = _md_com.Read(_device_id, dv, new Single());
if (ret.IsOkay)
{
var value = ret.Data;
#if (DEBUG)
if (DoComDebugPrint)
{
Console.WriteLine($"Read={dv,ch_lng_dv}: Reg_Ver={dv.Version,ch_lng_Version} Adr={dv.MD_adr,ch_lng_MD_adr} value={value,dig_value}");
}
#endif // #if (DEBUG)
return value;
}
return null; // Error in reading
}
protected BigInteger? read_U128(Device_value dv)
{
var ret = _md_com.Read(_device_id, dv, new BigInteger());
if (ret.IsOkay)
{
var value = ret.Data;
#if (DEBUG)
if (DoComDebugPrint)
{
Console.WriteLine($"Read={dv,ch_lng_dv}: Reg_Ver={dv.Version,ch_lng_Version} Adr={dv.MD_adr,ch_lng_MD_adr} value={value,dig_value}");
}
#endif // #if (DEBUG)
return value;
}
return null; // Error in reading
}
protected List<ModbusDataRequest> read(List<Device_value> dvList)
{
var ret = _md_com.Read(_device_id, dvList);
if (ret.Count > 0)
{
#if (DEBUG)
foreach (var data in ret)
{
if (DoComDebugPrint)
{
var dv = data.Info;
Console.WriteLine($"Read={dv,ch_lng_dv}: Reg_Ver={dv.Version,ch_lng_Version} Adr={dv.MD_adr,ch_lng_MD_adr} value={data.Data,dig_value}");
}
}
#endif // #if (DEBUG)
return ret;
}
return null; // Error in reading
}
protected bool write_U16(Device_value dv, UInt16 value)
{
var isOkay = _md_com.Write(_device_id, dv, value);
if (!isOkay)
{
#if (DEBUG)
if (DoComDebugPrint)
{
Console.WriteLine($"Failed Write={dv,ch_lng_dv}: Reg_Ver={dv.Version,ch_lng_Version} Adr={dv.MD_adr,ch_lng_MD_adr} value={value,dig_value}");
}
#endif // #if (DEBUG)
}
return isOkay; // Error in reading
}
protected bool write_U32(Device_value dv, UInt32 value)
{
var isOkay = _md_com.Write(_device_id, dv, value);
if (!isOkay)
{
#if (DEBUG)
if (DoComDebugPrint)
{
Console.WriteLine($"Failed Write={dv,ch_lng_dv}: Reg_Ver={dv.Version,ch_lng_Version} Adr={dv.MD_adr,ch_lng_MD_adr} value={value,dig_value}");
}
#endif // #if (DEBUG)
}
return isOkay; // Error in reading
}
/// <summary>
/// Write multiple values in a optimized number of telegrams
/// </summary>
/// <param name="reqList"></param>
/// <returns></returns>
protected List<ModbusDataRequest> write(List<ModbusDataRequest> reqList)
{
var ret = _md_com.Write(_device_id, reqList);
if ((ret!=null) && (ret.Count > 0))
{
#if (DEBUG)
foreach (var data in ret)
{
if (DoComDebugPrint)
{
var dv = data.Info;
Console.WriteLine($"Write={dv,ch_lng_dv}: Reg_Ver={dv.Version,ch_lng_Version} Adr={dv.MD_adr,ch_lng_MD_adr} value={data.Data,dig_value} {data.IsOkay}");
}
}
#endif // #if (DEBUG)
return ret;
}
return null; // Error in reading
}
#endregion // #region ---------------- Generic modbus communications ---------------------
}
}