334 lines
10 KiB
C#
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 ---------------------
|
|
}
|
|
} |