1128 lines
50 KiB
C#
1128 lines
50 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
using System.IO.Ports;
|
|
using XYLEM.Communication;
|
|
using System.Xml.Linq;
|
|
using XYLEM.Base;
|
|
using XYLEM.Communication.ValueEncoders;
|
|
using System.Linq.Expressions;
|
|
using System.Threading;
|
|
using MagFlux6200_metrology_reg_list;
|
|
using XYLEM.Device;
|
|
using static modbus_master_csharp.Program;
|
|
using System.Diagnostics.Contracts;
|
|
using System.Security.Policy;
|
|
using System.IO;
|
|
using System.Diagnostics;
|
|
using System.Xml.Schema;
|
|
using System.Net.NetworkInformation;
|
|
|
|
namespace modbus_master_csharp
|
|
{
|
|
internal class Program
|
|
{
|
|
/*For testing directly to metrology */
|
|
static string[] argsDefault1 = new string[] { "TEST", "COM200", "115200", "N" };
|
|
/*For metrology RS485 when transparent to metrology*/
|
|
static string[] argsDefault2 = new string[] { "SAVE_CAL", "COM38" };
|
|
|
|
static string[] argsDefault2b = new string[] { "SAVE_CAL", "COM200", "115200", "N" };
|
|
|
|
static string[] argsDefault2c = new string[] { "SAVE_CAL", "COM200", "COM200", "115200", "N" };
|
|
|
|
// Having more ports
|
|
static string[] argsDefault3 = new string[] { "TEST", "COM38", "COM200" };
|
|
|
|
/*For metrology RS485 when transparent to metrology*/
|
|
static string[] argsDefault4 = new string[] { "LOAD_CAL=\"0_sensor_cal_for_testing.xml\"", "COM38" };
|
|
|
|
/*For metrology RS485 when transparent to metrology*/
|
|
static string[] argsDefault5 = new string[] { "SET_DN_SN=25,999999", "COM38" };
|
|
|
|
/*For metrology RS485 when transparent to metrology*/
|
|
static string[] argsDebugLiveRun = new string[] { "TEST", "COM200" };
|
|
|
|
/*For metrology RS485 when transparent to metrology*/
|
|
static string[] args_ExAbortCal = new string[] { "ABORT_CAL", "COM200" };
|
|
|
|
#if (DEBUG)
|
|
static bool LIVE_RUN = true; // Default = "true" to run with DUT communication or "false" to run without any DUT for communication and mock values
|
|
|
|
/* Preload with program argument used for debugging*/
|
|
static bool MAIN_ARGS_OVERWRITE = true; // true to overwrite run with "argsDebugLiveRun" [Default = false]
|
|
static string[] MAIN_ARGS_OVERWRITE_WITH = argsDebugLiveRun; //testing arguments in debug Default = "argsDebugLiveRun"
|
|
#else
|
|
static bool LIVE_RUN = true; //
|
|
#endif
|
|
|
|
private static string GetArgHelpMessage(bool isArgErrorMessage, string[] args)
|
|
{
|
|
var name_exe = System.AppDomain.CurrentDomain.FriendlyName;
|
|
var message = $@"
|
|
Example of from command line:
|
|
Save calibrations only include COMx to use standard baudrate and parity setup:
|
|
""{name_exe} {argsDefault2.ToSingleString(false)}""
|
|
|
|
or run functional test for 2 MagFlux
|
|
""{name_exe} {argsDefault3.ToSingleString(false)}""
|
|
|
|
To run functional test and configure both COMx, baudrate, parity. (Used for com directly to Metrology)
|
|
""{name_exe} {argsDefault1.ToSingleString(false)}""
|
|
|
|
To Load calibrations only include COMx to use standard baudrate and parity setup:
|
|
""{name_exe} {argsDefault4.ToSingleString(false)}""
|
|
|
|
To Set DN [mm] and Sensor Serial number, only include COMx to use standard baudrate and parity setup:
|
|
""{name_exe} {argsDefault5.ToSingleString(false)}""
|
|
|
|
To Abort calibrations only include COMx to use standard baudrate and parity setup:
|
|
""{name_exe} {args_ExAbortCal.ToSingleString(false)}""
|
|
";
|
|
if (isArgErrorMessage)
|
|
{
|
|
var argsTxt = args != null ? args.ToSingleString(" ") : "";
|
|
message = $"{new string('!', 50)}\nThere is errors in the Arguments list!\n{new string('!', 50)}\nWas: {name_exe} {argsTxt}\n" + message;
|
|
}
|
|
return message;
|
|
}
|
|
|
|
#region Reused functions for testing
|
|
private static bool GetDeviceHealthy(IMagFluxRequestProtocol dut)
|
|
{
|
|
var name = nameof(dut.GetDeviceHealthy);
|
|
var isOkay = dut.GetDeviceHealthy();
|
|
var message = $"{name}: {(isOkay ? "Is okay" : "Has errors")}";
|
|
if (!isOkay)
|
|
{
|
|
if (dut.GetDeviceErrorMessages(out var errorList))
|
|
{
|
|
Console.WriteLine(message + "\nError List:\n" + errorList.ToSingleString(false));
|
|
}
|
|
else
|
|
{
|
|
Console.WriteLine(message);
|
|
}
|
|
}
|
|
return isOkay;
|
|
}
|
|
|
|
private static void GetBasicDeviceInfo(IMagFluxRequestProtocol dut)
|
|
{
|
|
{
|
|
var name = nameof(dut.GetFwGitHash);
|
|
var isOkay = dut.GetFwGitHash(out var value_out);
|
|
var message = $"{name}: {(isOkay ? value_out : "!Read failed!")}";
|
|
Console.WriteLine(message);
|
|
if (!isOkay)
|
|
{
|
|
throw new Exception(message);
|
|
}
|
|
}
|
|
{
|
|
var name = nameof(dut.GetSensorSerialNo);
|
|
var isOkay = dut.GetSensorSerialNo(out var value_out);
|
|
var message = $"{name}: {(isOkay ? value_out : "!Read failed!")}";
|
|
Console.WriteLine(message);
|
|
if (!isOkay)
|
|
{
|
|
throw new Exception(message);
|
|
}
|
|
}
|
|
{
|
|
var name = nameof(dut.GetUniqueId);
|
|
var isOkay = dut.GetUniqueId(out var value_out);
|
|
var message = $"{name}: {(isOkay ? value_out : "!Read failed!")}";
|
|
Console.WriteLine(message);
|
|
if (!isOkay)
|
|
{
|
|
throw new Exception(message);
|
|
}
|
|
}
|
|
{
|
|
var name = nameof(dut.GetFirmwareVersion);
|
|
var isOkay = dut.GetFirmwareVersion(out var value_out);
|
|
var message = $"{name}: {(isOkay ? value_out : "!Read failed!")}";
|
|
Console.WriteLine(message);
|
|
if (!isOkay)
|
|
{
|
|
throw new Exception(message);
|
|
}
|
|
}
|
|
{
|
|
var name = nameof(dut.GetFwBuildDate);
|
|
var isOkay = dut.GetFwBuildDate(out var value_out);
|
|
var message = $"{name}: {(isOkay ? value_out : "!Read failed!")}";
|
|
Console.WriteLine(message);
|
|
if (!isOkay)
|
|
{
|
|
throw new Exception(message);
|
|
}
|
|
}
|
|
}
|
|
|
|
private static void GetBasicSensorInfo(IMagFluxRequestProtocol dut)
|
|
{
|
|
{
|
|
var name = nameof(dut.GetDn_mm);
|
|
var isOkay = dut.GetDn_mm(out var dn_mm_out);
|
|
var message = $"{name}: {(isOkay ? $"{dn_mm_out}mm" : "!Read failed!")}";
|
|
Console.WriteLine(message);
|
|
if (!isOkay)
|
|
{
|
|
throw new Exception(message);
|
|
}
|
|
}
|
|
{
|
|
GetDeviceHealthy(dut);
|
|
}
|
|
}
|
|
|
|
private static void AbortDeviceCalibration(IMagFluxRequestProtocol dut)
|
|
{
|
|
{
|
|
var name = nameof(dut.AbortDeviceForCalibration);
|
|
var isOkay = dut.AbortDeviceForCalibration();
|
|
var message = $"{name}: {(isOkay ? "Done" : "!Abort failed!")}";
|
|
Console.WriteLine(message);
|
|
if (!isOkay)
|
|
{
|
|
throw new Exception(message);
|
|
}
|
|
}
|
|
}
|
|
|
|
private static bool GetCalibrationPoints(IMagFluxRequestProtocol dut, out CalibrationPoints value_out, bool printoutPoints)
|
|
{
|
|
var name = nameof(dut.GetCalibrationPoints);
|
|
var isOkay = dut.GetCalibrationPoints(out value_out);
|
|
if (printoutPoints)
|
|
{
|
|
Console.WriteLine($"{name}: Read points-> {(isOkay ? "\n"+value_out.ToString() : "!Read failed!")}");
|
|
}
|
|
else
|
|
{
|
|
Console.WriteLine($"{name}: Reading calibration points {(isOkay ? "Okay" : "!Read failed!")}");
|
|
}
|
|
return isOkay;
|
|
}
|
|
|
|
private static bool SetCalibrationPoints(IMagFluxRequestProtocol dut, CalibrationPoints new_calibration_points)
|
|
{
|
|
var isOkay = dut.SetCalibrationPoints(new_calibration_points);
|
|
Console.WriteLine($"{nameof(dut.SetCalibrationPoints)}: {(isOkay ? "Okay" : "Failed")}\n{new_calibration_points}");
|
|
return isOkay;
|
|
}
|
|
|
|
private static bool PrepareDeviceForCalibration(IMagFluxRequestProtocol dut)
|
|
{
|
|
{ // --- Test setting the device ready for the first measurement used for calibrations ---
|
|
{
|
|
var isOkay = dut.PrepareDeviceForCalibration();
|
|
Console.WriteLine($"{nameof(dut.PrepareDeviceForCalibration)}: {(isOkay ? "Okay" : "Failed")}");
|
|
if (!isOkay || !GetCalibrationPoints(dut, out var value_out, true/*printout points*/))
|
|
{
|
|
GetDeviceHealthy(dut);
|
|
throw new Exception("Failed Setting device up for calibration");
|
|
}
|
|
return isOkay;
|
|
}
|
|
}
|
|
}
|
|
|
|
private static void RunTestCalibrationPoints(IMagFluxRequestProtocol dut, CalibrationPoints new_calibration_points)
|
|
{
|
|
{ // Write calibrations
|
|
var isOkay = SetCalibrationPoints(dut, new_calibration_points);
|
|
if (!isOkay)
|
|
{
|
|
GetDeviceHealthy(dut);
|
|
throw new Exception("Failed writing the calibration to device");
|
|
}
|
|
}
|
|
{ // Get calibrations and check it
|
|
if (!GetCalibrationPoints(dut, out var value_out, false/*Don't printout*/) || (new_calibration_points != value_out))
|
|
{
|
|
GetDeviceHealthy(dut);
|
|
var msg = $"Failed! Calibration is not the same read as written to device\nWritten:\n{new_calibration_points}\nRead:\n{value_out}";
|
|
Console.WriteLine(msg);
|
|
throw new Exception(msg);
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Read Sensor serial number
|
|
/// </summary>
|
|
/// <param name="dut"></param>
|
|
/// <returns>Return the Serial number</returns>
|
|
/// <exception cref="Exception">Will throw an exception if failing</exception>
|
|
private static UInt32 GetSensorSerialNo(IMagFluxRequestProtocol dut)
|
|
{
|
|
var isOkay = dut.GetSensorSerialNo(out var read_out);
|
|
UInt32 ret = 0;
|
|
if (isOkay)
|
|
{
|
|
isOkay = UInt32.TryParse(read_out, out var passed);
|
|
ret = passed;
|
|
}
|
|
{ // Handle result
|
|
var name = nameof(dut.GetSensorSerialNo);
|
|
var message = $"Read {name}: {(isOkay ? ret.ToString() : "!failed!")}";
|
|
Console.WriteLine(message);
|
|
if (!isOkay)
|
|
{
|
|
throw new Exception(message);
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Write Sensor serial number (Also check with a read back)
|
|
/// </summary>
|
|
/// <param name="dut">what dut to write to</param>
|
|
/// <param name="new_SN">New serial number</param>
|
|
/// <exception cref="Exception">Will throw an exception if failing</exception>
|
|
private static void SetSensorSerialNo(IMagFluxRequestProtocol dut, UInt32 new_SN)
|
|
{
|
|
var name = nameof(dut.SetSensorSerialNo);
|
|
Console.WriteLine($"Write of {name}: {new_SN.ToString()}");
|
|
var isOkay = dut.SetSensorSerialNo(new_SN);
|
|
var read = GetSensorSerialNo(dut);
|
|
isOkay &= (read == new_SN); // Is the same as read ?
|
|
// Handle result
|
|
if (!isOkay)
|
|
{
|
|
var message = $"Write of {name}:!failed!";
|
|
Console.WriteLine(message);
|
|
throw new Exception(message);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Read Sensor DN
|
|
/// </summary>
|
|
/// <param name="dut"></param>
|
|
/// <returns>Return DN [mm]</returns>
|
|
/// <exception cref="Exception">Will throw an exception if failing</exception>
|
|
private static UInt16 GetDn_mm(IMagFluxRequestProtocol dut)
|
|
{
|
|
var isOkay = dut.GetDn_mm(out var read_out);
|
|
UInt16 ret = 0;
|
|
if (isOkay)
|
|
{
|
|
isOkay = UInt16.TryParse(read_out.ToString(), out var passed);
|
|
ret = passed;
|
|
}
|
|
{ // Handle result
|
|
var name = nameof(dut.GetDn_mm);
|
|
var message = $"Read {name}: {(isOkay ? ret.ToString() : "!failed!")}";
|
|
Console.WriteLine(message);
|
|
if (!isOkay)
|
|
{
|
|
throw new Exception(message);
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Write Sensor DN size (Also check with a read back)
|
|
/// </summary>
|
|
/// <param name="dut">what dut to write to</param>
|
|
/// <param name="new_DN_mm">New DN [mm]</param>
|
|
/// <exception cref="Exception">Will throw an exception if failing</exception>
|
|
private static void SetDn_mm(IMagFluxRequestProtocol dut, UInt16 new_DN_mm)
|
|
{
|
|
var name = nameof(dut.SetDn_mm);
|
|
Console.WriteLine($"Write of {name}: {new_DN_mm.ToString()}");
|
|
var isOkay = dut.SetDn_mm(new_DN_mm);
|
|
var read = GetDn_mm(dut);
|
|
isOkay &= (read == new_DN_mm); // Is the same as read ?
|
|
// Handle result
|
|
if (!isOkay)
|
|
{
|
|
var message = $"Write of {name}:!failed!";
|
|
Console.WriteLine(message);
|
|
throw new Exception(message);
|
|
}
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// save and load what is read from device
|
|
/// </summary>
|
|
/// <param name="dut"></param>
|
|
/// <param name="value_out"></param>
|
|
private static void SaveCalPointsToTempFolder(IMagFluxRequestProtocol dut, CalibrationPoints value_out)
|
|
{
|
|
var tempSaveFolder = Environment.GetEnvironmentVariable("USERPROFILE")+@"\Downloads\";
|
|
if (dut.GetSensorSerialNo(out var sensorSerial))
|
|
{
|
|
dut.GetUniqueId(out var id);
|
|
var sensor_cal_file = tempSaveFolder+$"{sensorSerial}_sensor_cal_id_{id}_{DateTime.Now.ToFileTimeTxt()}.xml";
|
|
Console.WriteLine($"Save to:\n{sensor_cal_file}");
|
|
value_out.SaveToFile(sensor_cal_file);
|
|
// Check saved data
|
|
var to_saved_points = value_out.calibrations.ToArray();
|
|
value_out.LoadFromFile(sensor_cal_file);
|
|
var loaded_points = value_out.calibrations.ToArray();
|
|
if (!to_saved_points.SequenceEqual(loaded_points))
|
|
{
|
|
var msg = $"Failed save of calibrations\nSaved:\n{to_saved_points}\nLoaded:\n{loaded_points}";
|
|
Console.WriteLine(msg);
|
|
throw new Exception(msg);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
private static void SAVE_CAL(List<IMagFluxRequestProtocol> duts)
|
|
{
|
|
{ // Check Save all calibrations one DUT at a time
|
|
for (var dutIdx = 0; dutIdx < duts.Count(); dutIdx++)
|
|
{
|
|
var dut = duts[dutIdx];
|
|
Console.WriteLine($"------------------- DUT{dutIdx+1} --------------------");
|
|
try
|
|
{
|
|
GetBasicDeviceInfo(dut);
|
|
GetBasicSensorInfo(dut);
|
|
if (!GetCalibrationPoints(dut, out var value_out, true/*printout points*/))
|
|
{
|
|
GetDeviceHealthy(dut);
|
|
throw new Exception("Failed saving device calibration");
|
|
}
|
|
else
|
|
{
|
|
// save and load what is read from device
|
|
SaveCalPointsToTempFolder(dut, value_out);
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
dut.OpenLogFile();
|
|
throw ex;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
private static void ABORT_CAL(List<IMagFluxRequestProtocol> duts)
|
|
{
|
|
{ // Check Save all calibrations one DUT at a time
|
|
for (var dutIdx = 0; dutIdx < duts.Count(); dutIdx++)
|
|
{
|
|
var dut = duts[dutIdx];
|
|
Console.WriteLine($"------------------- DUT{dutIdx+1} --------------------");
|
|
try
|
|
{
|
|
GetBasicDeviceInfo(dut);
|
|
AbortDeviceCalibration(dut);
|
|
GetBasicSensorInfo(dut);
|
|
if (!GetCalibrationPoints(dut, out var value_out, true/*printout points*/))
|
|
{
|
|
if (!PrepareDeviceForCalibration(dut))
|
|
{
|
|
throw new Exception("Failed abort of device calibration");
|
|
}
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
dut.OpenLogFile();
|
|
throw ex;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Load Calibrations
|
|
/// </summary>
|
|
/// <param name="duts"></param>
|
|
/// <param name="loadedCalibrations"></param>
|
|
private static void LOAD_CAL(List<IMagFluxRequestProtocol> duts, List<CalibrationPoints> loadedCalibrations)
|
|
{
|
|
{ // Check all Values one by one a DUT at a time
|
|
if (duts.Count() != loadedCalibrations.Count())
|
|
{
|
|
throw new Exception("The number of calibrations is not the same as DUT's to load it in");
|
|
}
|
|
Console.WriteLine("\nSave Calibrations before starting writing new calibrations\n");
|
|
SAVE_CAL(duts);
|
|
Console.WriteLine("\nStarting writing new calibrations\n");
|
|
for (var dutIdx = 0; dutIdx < duts.Count(); dutIdx++)
|
|
{
|
|
var dut = duts[dutIdx];
|
|
Console.WriteLine($"------------------- DUT{dutIdx+1} --------------------");
|
|
try
|
|
{
|
|
var new_calibration_points = loadedCalibrations[dutIdx];
|
|
var isOkay = SetCalibrationPoints(dut, new_calibration_points);
|
|
if (!isOkay)
|
|
{
|
|
throw new Exception($"Writing calibration Fail!\n{new_calibration_points}");
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
dut.OpenLogFile();
|
|
throw ex;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Set DN and SN in device
|
|
/// </summary>
|
|
/// <param name="dut">Device to write it to</param>
|
|
/// <param name="DN_mm">DN size in [mm]</param>
|
|
/// <param name="sensor_sn">Sensor serial number</param>
|
|
static void SET_DN_SN(IMagFluxRequestProtocol dut, UInt16 DN_mm, UInt32 sensor_sn)
|
|
{
|
|
Console.WriteLine($"------------------- Read current DUT Sensor DN and SN --------------------");
|
|
try
|
|
{
|
|
GetDn_mm(dut);
|
|
GetSensorSerialNo(dut);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
dut.OpenLogFile();
|
|
throw ex;
|
|
}
|
|
|
|
Console.WriteLine($"------------------- Set DUT Sensor DN and SN --------------------");
|
|
try
|
|
{
|
|
SetDn_mm(dut, DN_mm);
|
|
SetSensorSerialNo(dut, sensor_sn);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
dut.OpenLogFile();
|
|
throw ex;
|
|
}
|
|
}
|
|
|
|
static void TEST(List<IMagFluxRequestProtocol> duts)
|
|
{
|
|
{ // Check all Values one by one a DUT at a time
|
|
for (var dutIdx = 0; dutIdx < duts.Count(); dutIdx++)
|
|
{
|
|
Console.WriteLine($"------------------- DUT{dutIdx+1} --------------------");
|
|
var dut = duts[dutIdx];
|
|
try
|
|
{
|
|
//if (false) // Don't do basic reads
|
|
if (true) // Do basic read test
|
|
{
|
|
GetBasicDeviceInfo(dut);
|
|
{
|
|
var name = nameof(dut.GetFlowRate_lps);
|
|
var isOkay = dut.GetFlowRate_lps(out var value_out);
|
|
var message = $"{name}: {(isOkay ? $"{value_out} l/s or {value_out*3.6} m3/h" : "!Read failed!")}";
|
|
Console.WriteLine(message);
|
|
if (!isOkay)
|
|
{
|
|
throw new Exception(message);
|
|
}
|
|
}
|
|
GetBasicSensorInfo(dut);
|
|
{ // Always check that GetDeviceErrorMessages() even when there is not error, to test function
|
|
// Is only run in GetBasicSensorInfo() when there is an error
|
|
var name = nameof(dut.GetDeviceErrorMessages);
|
|
var isOkay = dut.GetDeviceErrorMessages(out var value_out);
|
|
var message = $"{name}: \n{(isOkay ? String.Join("\n", value_out) : "!Read failed!")}";
|
|
Console.WriteLine(message);
|
|
if (!isOkay)
|
|
{
|
|
throw new Exception(message);
|
|
}
|
|
}
|
|
AbortDeviceCalibration(dut);
|
|
{
|
|
if (!GetCalibrationPoints(dut, out var value_out, true/*printout points*/))
|
|
{
|
|
GetDeviceHealthy(dut);
|
|
}
|
|
else
|
|
{
|
|
// save and load what is read from device
|
|
SaveCalPointsToTempFolder(dut, value_out);
|
|
}
|
|
}
|
|
}
|
|
//if (false) // Do not execute calibration test
|
|
if (LIVE_RUN && true) // execute calibration test
|
|
{ // A single calibration Test
|
|
PrepareDeviceForCalibration(dut);
|
|
{ // --- Do a simple 2 point calibration with zero ---
|
|
var new_calibration_points = new CalibrationPoints(
|
|
new List<CalibrationPoint> {
|
|
new CalibrationPoint(0,0.001f), // 0
|
|
new CalibrationPoint(1,1.002f), // 1
|
|
new CalibrationPoint(2,2.003f), // 2
|
|
},
|
|
dut.CalibrationPointsMax // Extend to
|
|
);
|
|
RunTestCalibrationPoints(dut, new_calibration_points);
|
|
}
|
|
{ // --- Do a 6 point calibration with negative zero ---
|
|
var new_calibration_points = new CalibrationPoints(
|
|
new List<CalibrationPoint> {
|
|
new CalibrationPoint(0,-0.001f), // 0
|
|
new CalibrationPoint(1,1.002f), // 1
|
|
new CalibrationPoint(2,2.003f), // 2
|
|
new CalibrationPoint(3,3.004f), // 3
|
|
new CalibrationPoint(4,4.005f), // 4
|
|
new CalibrationPoint(5,5.006f), // 5
|
|
},
|
|
dut.CalibrationPointsMax // Extend to
|
|
);
|
|
RunTestCalibrationPoints(dut, new_calibration_points);
|
|
// save and load what is read from device
|
|
SaveCalPointsToTempFolder(dut, new_calibration_points);
|
|
}
|
|
{ // --- Do a check of write of calibrations points that is not ordered correct ---
|
|
Console.WriteLine($"Test writing calibration in wrong order is failing and Background check service is running");
|
|
{
|
|
var new_calibration_points = new CalibrationPoints(
|
|
new List<CalibrationPoint> {
|
|
new CalibrationPoint(0,-0.001f), // 0
|
|
new CalibrationPoint(3,3.002f), // 1 Error this an error in order and need to brake calibrations
|
|
new CalibrationPoint(2,2.003f), // 2
|
|
},
|
|
dut.CalibrationPointsMax // Extend to
|
|
);
|
|
var isOkay = SetCalibrationPoints(dut, new_calibration_points);
|
|
if (isOkay)
|
|
{
|
|
throw new Exception($"Writing calibration in wrong order needs to Fail!\n{new_calibration_points}");
|
|
}
|
|
int maxWait_s = 5;
|
|
while (maxWait_s-- > 0)
|
|
{
|
|
Console.Write($"\rWait timer out in {maxWait_s}s for getting Device Healthy is returning showing error: ");
|
|
if (!dut.GetFlowRate_lps(out var value_out))
|
|
{
|
|
throw new Exception($"read of flow failed during polling Device Healthy!");
|
|
}
|
|
if (!GetDeviceHealthy(dut))
|
|
{
|
|
Console.WriteLine($"\nGot correct replay that is Device healthy is \"false\"");
|
|
break; // Exit
|
|
}
|
|
Task.Delay(1000).GetAwaiter().GetResult();
|
|
}
|
|
if (maxWait_s <= 0)
|
|
{
|
|
throw new Exception($"Device Healthy was returning \"false\" when calibration was failing!\n{new_calibration_points}");
|
|
}
|
|
}
|
|
{// Cleanup by returning calibration to default
|
|
var isOkay = dut.PrepareDeviceForCalibration();
|
|
if (!isOkay)
|
|
{
|
|
throw new Exception("Failing returning calibration to default!");
|
|
}
|
|
}
|
|
}
|
|
{ // --- Test Sensor new_SN test ---
|
|
Console.WriteLine($"--- Test Write a changed Sensor SN ---");
|
|
// Read Sensor new_SN
|
|
Console.WriteLine($"1)Read current Sensor SN");
|
|
UInt32 current = GetSensorSerialNo(dut);
|
|
// Create a new Sensor new_SN
|
|
var write_new = current + 1;
|
|
// Write function also check with a read and throw exception if failed
|
|
Console.WriteLine($"2)Change Sensor SN to {write_new}");
|
|
SetSensorSerialNo(dut, write_new);
|
|
// Restore Sensor new_SN
|
|
Console.WriteLine($"3)Restore Sensor SN to {write_new}");
|
|
SetSensorSerialNo(dut, current);
|
|
Console.WriteLine($"--- Finish Test ---");
|
|
}
|
|
{ // --- Test Sensor DN test ---
|
|
Console.WriteLine($"--- Test Write a changed Sensor DN Size ---");
|
|
// SetDn_mm(dut, 20); // Insure a valid DN
|
|
|
|
UInt16[] tests_dn_mm = { 50, 100 };
|
|
|
|
// Read Sensor DN
|
|
Console.WriteLine($"1)Read current Sensor DN Size");
|
|
UInt16 current = GetDn_mm(dut);
|
|
|
|
// Create a new Sensor DN
|
|
var write_new = tests_dn_mm.FirstOrDefault(dn => dn != current);
|
|
// Write function also check with a read and throw exception if failed
|
|
Console.WriteLine($"2)Change Sensor DN Size as {write_new}");
|
|
SetDn_mm(dut, write_new);
|
|
// Restore Sensor DN
|
|
Console.WriteLine($"3)Restore original Sensor DN Size as {current}");
|
|
SetDn_mm(dut, current);
|
|
Console.WriteLine($"--- Finish Test ---");
|
|
}
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
dut.OpenLogFile();
|
|
throw ex;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
enum RUN_ACTION
|
|
{
|
|
UNKNOWN,
|
|
TEST,
|
|
SAVE_CAL,
|
|
LOAD_CAL,
|
|
ABORT_CAL,
|
|
SET_DN_SN,
|
|
SHOW_HELP,
|
|
}
|
|
|
|
class args_inputs
|
|
{
|
|
public List<string> comports;
|
|
public int? baudrate;
|
|
public Parity? parity;
|
|
public List<CalibrationPoints> loadedCalibrations;
|
|
public UInt16? DN_mm;
|
|
public UInt32? sensor_sn;
|
|
|
|
public args_inputs()
|
|
{
|
|
comports = new List<string>();
|
|
baudrate = null;
|
|
parity = null;
|
|
loadedCalibrations = new List<CalibrationPoints>();
|
|
sensor_sn = null;
|
|
}
|
|
}
|
|
|
|
|
|
#region Handle if arguments
|
|
static RUN_ACTION parse_arguments(string[] args, ref args_inputs ret_args_input)
|
|
{
|
|
bool gotArgs = (args.Length >= 1);
|
|
var run_task = RUN_ACTION.UNKNOWN;
|
|
var argErrors = gotArgs ? false : true;
|
|
// Use Default connection if nothing is provided by arguments
|
|
var arg_offset = 0;
|
|
if (args.Length > arg_offset)
|
|
{
|
|
{ /*--------- Parse What task to do ---------*/
|
|
if (args.Length > arg_offset)
|
|
{
|
|
if ("-H" == args[arg_offset].ToUpper())
|
|
{
|
|
run_task = RUN_ACTION.SHOW_HELP;
|
|
}
|
|
else if ("TEST" == args[arg_offset].ToUpper())
|
|
{
|
|
run_task = RUN_ACTION.TEST;
|
|
}
|
|
else if ("SAVE_CAL" == args[arg_offset].ToUpper())
|
|
{
|
|
run_task = RUN_ACTION.SAVE_CAL;
|
|
}
|
|
else if ("ABORT_CAL" == args[arg_offset].ToUpper())
|
|
{
|
|
run_task = RUN_ACTION.ABORT_CAL;
|
|
}
|
|
else if (args[arg_offset].ToUpper().StartsWith("SET_DN_SN="))
|
|
{
|
|
run_task = RUN_ACTION.SET_DN_SN;
|
|
var values_as_txt = args[arg_offset].Split('=').Last().Split(',');
|
|
int value_offset = 0;
|
|
{ // parse DN
|
|
var dn_mm_txt = values_as_txt[value_offset++];
|
|
if (!UInt16.TryParse(dn_mm_txt, out var dn_mm))
|
|
{
|
|
throw new InvalidDataException($"Error parsing DN \n{dn_mm_txt} as [mm]\n{GetArgHelpMessage(true, args)}");
|
|
}
|
|
if ((dn_mm < 3) || (dn_mm > 3000))
|
|
{
|
|
throw new InvalidDataException($"Error parsing DN \n{dn_mm}[mm] only 3 - 3000mm is allowed\n{GetArgHelpMessage(true, args)}");
|
|
}
|
|
// Is okay
|
|
ret_args_input.DN_mm = dn_mm;
|
|
}
|
|
{ // parse Sensor SN
|
|
var sn_txt = values_as_txt[value_offset++];
|
|
if (!UInt32.TryParse(sn_txt, out var SN))
|
|
{
|
|
throw new InvalidDataException($"Error parsing Sensor SN \n{sn_txt}\n{GetArgHelpMessage(true, args)}");
|
|
}
|
|
// Is okay
|
|
ret_args_input.sensor_sn = SN;
|
|
}
|
|
|
|
}
|
|
else if (args[arg_offset].ToUpper().StartsWith("LOAD_CAL="))
|
|
{
|
|
run_task = RUN_ACTION.LOAD_CAL;
|
|
var calFilePath = args[arg_offset].Split('=').Last();
|
|
var cal = new CalibrationPoints();
|
|
if (!File.Exists(calFilePath) || !cal.LoadFromFile(calFilePath))
|
|
{
|
|
throw new InvalidDataException($"Error load calibrations from\n {calFilePath}\n{GetArgHelpMessage(true, args)}");
|
|
}
|
|
ret_args_input.loadedCalibrations.Add(cal);
|
|
}
|
|
else
|
|
{
|
|
throw new NotImplementedException($"Missing support for parameter {args[arg_offset]}\n{GetArgHelpMessage(true, args)}");
|
|
}
|
|
}
|
|
}
|
|
arg_offset++; // Check next argument
|
|
{ /*--------- Parse com port / ports ---------*/
|
|
var exit = false;
|
|
var com_check_arg_offset = arg_offset;
|
|
while (!exit)
|
|
{
|
|
if (args.Length > com_check_arg_offset)
|
|
{
|
|
var arg = args[com_check_arg_offset].ToUpper();
|
|
if ("COM" == arg.Remove(3))
|
|
{
|
|
ret_args_input.comports.Add(arg);
|
|
arg_offset = com_check_arg_offset; // Save ret location for last added com
|
|
}
|
|
else if (ret_args_input.comports.Count <= 0)
|
|
{
|
|
Console.WriteLine($"Com port {arg} not understood.");
|
|
argErrors = true;
|
|
exit = true;
|
|
}
|
|
else
|
|
{
|
|
exit = true; // No more com to connect to
|
|
}
|
|
com_check_arg_offset++; // Check next argument
|
|
}
|
|
else
|
|
{
|
|
exit = true; // No more com to connect to
|
|
}
|
|
}
|
|
}
|
|
arg_offset++; // Check next argument
|
|
{ /*--------- Parse Baud rate ---------*/
|
|
if (args.Length > arg_offset)
|
|
{
|
|
var arg = args[arg_offset].ToUpper();
|
|
var allowed_baudrate = new string[] { "9600", "19200", "38400", "57600", "115200", "230400" };
|
|
if (allowed_baudrate.Contains(arg))
|
|
{
|
|
ret_args_input.baudrate = int.Parse(arg);
|
|
}
|
|
else
|
|
{
|
|
Console.WriteLine($"Baud rate {arg} not known.");
|
|
ret_args_input.baudrate = -1;
|
|
argErrors = true;
|
|
}
|
|
}
|
|
}
|
|
arg_offset++; // Check next argument
|
|
{ /*--------- Parse Parity ---------*/
|
|
if (args.Length > arg_offset)
|
|
{
|
|
var arg = args[arg_offset].ToUpper();
|
|
if (arg == "E")
|
|
{
|
|
ret_args_input.parity = Parity.Even;
|
|
}
|
|
else if (arg == "N")
|
|
{
|
|
ret_args_input.parity = Parity.None;
|
|
}
|
|
else if (arg == "O")
|
|
{
|
|
ret_args_input.parity = Parity.Odd;
|
|
}
|
|
else
|
|
{
|
|
Console.WriteLine($"Parity {arg} not known.");
|
|
ret_args_input.parity = Parity.None;
|
|
argErrors = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (argErrors)
|
|
{
|
|
string message = GetArgHelpMessage(argErrors, args);
|
|
Console.WriteLine(message);
|
|
if (argErrors)
|
|
{
|
|
throw new Exception(message); // exit main
|
|
}
|
|
}
|
|
return run_task;
|
|
}
|
|
#endregion
|
|
|
|
/// <summary>
|
|
/// For unit testing setup
|
|
/// </summary>
|
|
/// <param name="args"></param>
|
|
static void Main(string[] args)
|
|
{
|
|
int ret_error = 0; // Is okay
|
|
List<IMagFluxRequestProtocol> duts = new List<IMagFluxRequestProtocol>();
|
|
try
|
|
{
|
|
var runMode = RUN_TYPE.Mock;
|
|
if (LIVE_RUN)
|
|
{
|
|
runMode = RUN_TYPE.Normal;
|
|
}
|
|
|
|
// Just for internal testing
|
|
#if (DEBUG)
|
|
if (args.Length <= 0)
|
|
{
|
|
if (MAIN_ARGS_OVERWRITE)
|
|
{
|
|
args = MAIN_ARGS_OVERWRITE_WITH; //testing directly to metrology
|
|
}
|
|
}
|
|
#endif
|
|
var run_task = RUN_ACTION.UNKNOWN;
|
|
bool gotArgs = ((args != null) && (args.Length >= 1));
|
|
var inputs = new args_inputs();
|
|
if (gotArgs)
|
|
{
|
|
run_task = parse_arguments(args, ref inputs);
|
|
}
|
|
else
|
|
{
|
|
run_task = RUN_ACTION.SHOW_HELP;
|
|
}
|
|
if (run_task == RUN_ACTION.SHOW_HELP)
|
|
{
|
|
string message = GetArgHelpMessage(false, null);
|
|
Console.WriteLine(message);
|
|
return;
|
|
}
|
|
|
|
// Set window to max size to better fit content
|
|
// Not needed for now! Console.SetWindowSize(Console.LargestWindowWidth, Console.LargestWindowHeight);
|
|
#region Setup Communication to dut's
|
|
foreach (var comport in inputs.comports)
|
|
{
|
|
if (runMode != RUN_TYPE.Normal)
|
|
{
|
|
Console.WriteLine($"{new string('!', 50)}\n Warning is in running in {runMode} mode\n{new string('!', 50)}");
|
|
}
|
|
MagFlux6200 dut = null;
|
|
try
|
|
{ // Set up on DUT
|
|
dut = new MagFlux6200(runMode);
|
|
var log_path = Environment.GetEnvironmentVariable("USERPROFILE")+@"\Downloads\";
|
|
var isOkay = dut.SetLogLocation(log_path, "logs_"+comport);
|
|
Console.WriteLine($"Using program log path:\n{log_path}");
|
|
isOkay &=gotArgs;
|
|
if (isOkay)
|
|
{ // Use standard and just setup as port
|
|
if (inputs.baudrate == null)
|
|
{
|
|
isOkay &=dut.Connect(comport);
|
|
}
|
|
else if ((inputs.baudrate != null) && (inputs.parity != null))
|
|
{
|
|
isOkay &=dut.Connect(comport, inputs.baudrate.Value, inputs.parity.Value);
|
|
}
|
|
else
|
|
{
|
|
isOkay = false; // Error in settings
|
|
}
|
|
}
|
|
|
|
if (isOkay)
|
|
{
|
|
duts.Add(dut);
|
|
}
|
|
else
|
|
{
|
|
var port = comport;
|
|
if (String.IsNullOrEmpty(port))
|
|
{
|
|
port = "COM ?";
|
|
}
|
|
throw new Exception($"Fail to setup device for {port}");
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
if (dut!=null)
|
|
{
|
|
dut.OpenLogFile();
|
|
}
|
|
throw ex;
|
|
}
|
|
}
|
|
#endregion //#region Setup Communication to dut's
|
|
switch (run_task)
|
|
{
|
|
case RUN_ACTION.TEST:
|
|
TEST(duts);
|
|
break;
|
|
case RUN_ACTION.SAVE_CAL:
|
|
{
|
|
SAVE_CAL(duts);
|
|
}
|
|
break;
|
|
case RUN_ACTION.SET_DN_SN:
|
|
{
|
|
if(duts.Count() > 1)
|
|
{
|
|
throw new InvalidDataException($"Error support only a single device for setting DN and SN \n{GetArgHelpMessage(true, args)}");
|
|
}
|
|
SET_DN_SN(duts.First(), inputs.DN_mm.Value, inputs.sensor_sn.Value);
|
|
int wait_ms = 15000;
|
|
Console.WriteLine($"Wait {wait_ms/1000} for device to reset after a possible DN change");
|
|
Task.Delay(15000).GetAwaiter().GetResult();
|
|
}
|
|
break;
|
|
case RUN_ACTION.LOAD_CAL:
|
|
{
|
|
LOAD_CAL(duts, inputs.loadedCalibrations);
|
|
}
|
|
break;
|
|
case RUN_ACTION.ABORT_CAL:
|
|
{
|
|
ABORT_CAL(duts);
|
|
}
|
|
break;
|
|
default:
|
|
{
|
|
throw new NotImplementedException($"Missing support run mode {run_task}");
|
|
}
|
|
}
|
|
Console.WriteLine("finished functional testing");
|
|
// Is set to true when the monitoring values also needs to stop
|
|
bool exitMonitoringLoop = false, pauseMonitoringLoop = false, _LastPauseMonitoringLoop = false;
|
|
// Start a task for monitoring a key for exit
|
|
Console.WriteLine("Press key 'x' exit, 'p' for pause read, 'c' continue read");
|
|
Task.Run(() =>
|
|
{
|
|
ConsoleKeyInfo keyinfo;
|
|
do
|
|
{
|
|
keyinfo = Console.ReadKey();
|
|
if (keyinfo.Key == ConsoleKey.P)
|
|
{
|
|
pauseMonitoringLoop = true;
|
|
}
|
|
else if (keyinfo.Key == ConsoleKey.C)
|
|
{
|
|
pauseMonitoringLoop = false;
|
|
}
|
|
else
|
|
{
|
|
Console.WriteLine($"\n{keyinfo.Key} was pressed. Press key 'x' exit");
|
|
}
|
|
}
|
|
while (keyinfo.Key != ConsoleKey.X);
|
|
exitMonitoringLoop = true;
|
|
});
|
|
// Just read flow and other values for testing general measurement
|
|
int count = 0;
|
|
// "Structure of an interpolated string"
|
|
// https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/tokens/interpolated
|
|
while (!exitMonitoringLoop)
|
|
{
|
|
if (!pauseMonitoringLoop)
|
|
{
|
|
var message = "\r";
|
|
var dutNum = 1;
|
|
foreach (var dut in duts)
|
|
{
|
|
{ // Read Flow
|
|
var isOkay = dut.GetFlowRate_lps(out var value_out);
|
|
if (dutNum > 1)
|
|
{
|
|
message += " | ";
|
|
}
|
|
message += $"DUT{dutNum++}: ";
|
|
if (!dut.GetDeviceHealthy())
|
|
{
|
|
message += $"Error:";
|
|
if (dut.GetDeviceErrorMessages(out var errorList))
|
|
{
|
|
message += $"{errorList.ToSingleString(false)} ";
|
|
}
|
|
else
|
|
{
|
|
message += $"No Text to display!";
|
|
}
|
|
}
|
|
else
|
|
{
|
|
const int w = 9;
|
|
message += $"{(isOkay ? $"{value_out*3.6,w:F3} m3/h" : $"!Read failed!")} {dut.GetComCounters()}\t";
|
|
if (!isOkay)
|
|
{
|
|
throw new Exception(message);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
Console.Write(message + $" msg={++count}\t");
|
|
}
|
|
{ // Print out if paused read
|
|
if (_LastPauseMonitoringLoop != pauseMonitoringLoop)
|
|
{
|
|
_LastPauseMonitoringLoop = pauseMonitoringLoop;
|
|
if (pauseMonitoringLoop)
|
|
{
|
|
Console.Write("\rRead is Paused!\t\t\t\t\t\t\t\t");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
var name_exe = System.AppDomain.CurrentDomain.FriendlyName;
|
|
AppConst.Logger.AddFuncLog(true, name_exe, "main()", ex);
|
|
AppConst.Logger.OpenProgramLogFile();
|
|
ret_error = -1; //https://learn.microsoft.com/en-us/windows/win32/debug/system-error-codes
|
|
}
|
|
finally
|
|
{
|
|
// Close connection before exit
|
|
try
|
|
{
|
|
if (duts.Count != 0)
|
|
{
|
|
foreach (var dut in duts)
|
|
{
|
|
dut.CloseConnection();
|
|
}
|
|
}
|
|
}
|
|
catch { }
|
|
Environment.Exit(ret_error); //https://learn.microsoft.com/en-us/windows/win32/debug/system-error-codes
|
|
}
|
|
}
|
|
}
|
|
}
|