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);
}
}
}
///
/// Read Sensor serial number
///
///
/// Return the Serial number
/// Will throw an exception if failing
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;
}
///
/// Write Sensor serial number (Also check with a read back)
///
/// what dut to write to
/// New serial number
/// Will throw an exception if failing
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);
}
}
///
/// Read Sensor DN
///
///
/// Return DN [mm]
/// Will throw an exception if failing
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;
}
///
/// Write Sensor DN size (Also check with a read back)
///
/// what dut to write to
/// New DN [mm]
/// Will throw an exception if failing
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);
}
}
///
/// save and load what is read from device
///
///
///
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 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 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;
}
}
}
}
///
/// Load Calibrations
///
///
///
private static void LOAD_CAL(List duts, List 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;
}
}
}
}
///
/// Set DN and SN in device
///
/// Device to write it to
/// DN size in [mm]
/// Sensor serial number
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 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 {
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 {
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 {
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 comports;
public int? baudrate;
public Parity? parity;
public List loadedCalibrations;
public UInt16? DN_mm;
public UInt32? sensor_sn;
public args_inputs()
{
comports = new List();
baudrate = null;
parity = null;
loadedCalibrations = new List();
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
///
/// For unit testing setup
///
///
static void Main(string[] args)
{
int ret_error = 0; // Is okay
List duts = new List();
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
}
}
}
}