first commit
This commit is contained in:
384
ChamChat/Client_PLxKPH/Client.PLxKPH.cs
Normal file
384
ChamChat/Client_PLxKPH/Client.PLxKPH.cs
Normal file
@@ -0,0 +1,384 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using ChamChat.Models;
|
||||
|
||||
namespace ChamChat
|
||||
{
|
||||
public partial class PLxKPH_Client : Client
|
||||
{
|
||||
private const Int32 _OptionRange = 2000;
|
||||
private const int _RAM = 1;
|
||||
private const Int32 _ReturnDataWaitms = 300; // Time out for client to prepare and return data
|
||||
private DateTime _ReadyToSend = DateTime.Now; // Timestamp when client is ready to communicate
|
||||
|
||||
|
||||
public PLxKPH_Client(Int32 MIDS, ClientType Type)
|
||||
: base(MIDS, Type)
|
||||
{
|
||||
|
||||
// Set options available in client
|
||||
_Parameters = new List<Parameter>();
|
||||
_Parameters.Add(Parameter.T);
|
||||
_Parameters.Add(Parameter.RH);
|
||||
_Parameters.Add(Parameter.RampT);
|
||||
_Parameters.Add(Parameter.RampRH);
|
||||
|
||||
|
||||
// Add option range
|
||||
_ClientOptions = new List<ProfileOption>();
|
||||
foreach (ProfileOption o in Enum.GetValues(typeof(ProfileOption)))
|
||||
if ((int)o >= _OptionRange && (int)o < _OptionRange + 999)
|
||||
_ClientOptions.Add(o);
|
||||
|
||||
// Set availabel addresses for programming
|
||||
_AvailableRAMs = new List<int>();
|
||||
for (int i = 1; i < 21; i++)
|
||||
_AvailableRAMs.Add(i);
|
||||
|
||||
_InterfaceType = InterfaceType.FDTI_USB_COM422;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// To do
|
||||
public override Profile ReadProfile(int RAM, ref System.ComponentModel.BackgroundWorker bgw)
|
||||
{
|
||||
Profile profile = new Profile();
|
||||
return profile;
|
||||
}
|
||||
|
||||
|
||||
public override Boolean WriteProfile(Profile profile)
|
||||
{
|
||||
return WriteProfile(profile, _RAM);
|
||||
}
|
||||
|
||||
public override Boolean WriteProfile(Profile profile, int RAM)
|
||||
{
|
||||
// Only stand alone profiles allowed!
|
||||
if( !IsProgrammable(profile))
|
||||
return false;
|
||||
|
||||
string title = profile.Title.Substring(0, (int)Math.Min(14, profile.Title.Length)).Trim();
|
||||
|
||||
string sRAM = string.Format("{0:0}", RAM);
|
||||
|
||||
string sAddr = _Address.ToString();
|
||||
string cmd;
|
||||
string read;
|
||||
string cmd_pre = sAddr + ", PRGM DATA WRITE, PGM" + sRAM + ", ";
|
||||
|
||||
|
||||
|
||||
// Cancel RAM program editing
|
||||
cmd = cmd_pre + "EDIT CANCEL";
|
||||
DataTransfer(cmd, out read, _ReturnDataWaitms,1);
|
||||
if( !read.Contains("ERR-3"))
|
||||
DataTransfer(cmd, out read, _ReturnDataWaitms, 3);
|
||||
|
||||
|
||||
|
||||
// Open RAM program
|
||||
cmd = cmd_pre + "EDIT START";
|
||||
DataTransfer(cmd,out read, _ReturnDataWaitms);
|
||||
|
||||
|
||||
// Steps
|
||||
try
|
||||
{
|
||||
for (int i = 0; i < profile.Steps.Count; i++)
|
||||
{
|
||||
Step step = profile.Steps[i];
|
||||
cmd = cmd_pre;
|
||||
cmd += String.Format("STEP{0:0}, ", i + 1);
|
||||
cmd += String.Format("TEMP{0:0.0}, ", step.T);
|
||||
cmd += step.RampCtrlT ? "TRAMPON, " : "TRAMPOFF, ";
|
||||
cmd += step.HasRH ? String.Format("HUMI{0:0}, ", step.RH) : "HUMI OFF, ";
|
||||
cmd += step.RampCtrlRH ? "HRAMPON, " : "HRAMPOFF, ";
|
||||
cmd += String.Format("TIME{0:00}:{1:00}, ", step.Hours, step.Minutes);
|
||||
cmd += "GRANTY OFF, ";
|
||||
cmd += "PAUSE OFF";
|
||||
DataTransfer(cmd, out read, _ReturnDataWaitms);
|
||||
}
|
||||
}
|
||||
catch (Exception ex) { throw new Exception("writing steps - " + ex.Message); }
|
||||
|
||||
|
||||
try
|
||||
{
|
||||
|
||||
// Loops
|
||||
if (profile.Loops.Count > 0)
|
||||
{
|
||||
Loop loop = profile.Loops[0];
|
||||
cmd = cmd_pre;
|
||||
cmd += String.Format("COUNT, A({0}.{1}.{2})", loop.N - 1, loop.Last + 1, loop.First + 1);
|
||||
|
||||
if (profile.Loops.Count > 1)
|
||||
{
|
||||
loop = profile.Loops[1];
|
||||
cmd += String.Format(", B({0}.{1}.{2})", loop.N - 1, loop.Last + 1, loop.First + 1);
|
||||
}
|
||||
DataTransfer(cmd, out read, _ReturnDataWaitms);
|
||||
}
|
||||
}
|
||||
catch (Exception ex) { throw new Exception("writing loops - " + ex.Message); }
|
||||
|
||||
|
||||
|
||||
// End mode
|
||||
try
|
||||
{
|
||||
cmd = profile.Options.Contains(ProfileOption.PLxKPH_EndModeHold) ? cmd_pre + "END, HOLD" : cmd_pre + "END, OFF";
|
||||
DataTransfer(cmd, out read, _ReturnDataWaitms);
|
||||
}
|
||||
catch (Exception ex) { throw new Exception("writing end mode - " + ex.Message); }
|
||||
|
||||
|
||||
|
||||
// Name of program
|
||||
cmd = cmd_pre + "NAME, " + title;
|
||||
DataTransfer(cmd, out read, _ReturnDataWaitms);
|
||||
|
||||
|
||||
// Close and save RAM program
|
||||
cmd = cmd_pre + "EDIT END";
|
||||
DataTransfer(cmd, out read, _ReturnDataWaitms);
|
||||
|
||||
// Wait 3 seconds to close program
|
||||
System.Threading.Thread.Sleep(3000);
|
||||
|
||||
Boolean result = false;
|
||||
if (_Interface.InterfaceStatus == null)
|
||||
result = true;
|
||||
|
||||
_Profile = profile;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
public override Boolean IsProgrammable(Profile profile)
|
||||
{
|
||||
// Profile is programmable if all below applies
|
||||
// number of profile steps 99
|
||||
// number of loops < 3
|
||||
// -40 < t < 150
|
||||
|
||||
if(profile.Steps.Count > 99)
|
||||
return false;
|
||||
|
||||
if (profile.Loops.Count > 2)
|
||||
return false;
|
||||
|
||||
foreach (Loop loop in profile.Loops)
|
||||
if (loop.N > 99 || loop.N < 2)
|
||||
return false;
|
||||
|
||||
foreach (Step step in profile.Steps)
|
||||
{
|
||||
if (step.T < -40 || step.T > 150)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
public override Boolean HasAlarm(out List<Alarm> alarms)
|
||||
{
|
||||
alarms = new List<Alarm>();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
public override Boolean IsIdle()
|
||||
{
|
||||
// IsIdle() returns true if status of chamber is 'Standby'. See page 36 MODE?.
|
||||
|
||||
string sAddr = _Address.ToString();
|
||||
string cmd;
|
||||
string read;
|
||||
|
||||
cmd = sAddr + ", MODE?";
|
||||
DataTransfer(cmd,out read, _ReturnDataWaitms);
|
||||
|
||||
if (read.Contains("STANDBY"))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
public override Boolean Start()
|
||||
{
|
||||
if (_Profile == null)
|
||||
return false;
|
||||
|
||||
string sAddr = _Address.ToString();
|
||||
string cmd;
|
||||
string read;
|
||||
|
||||
cmd = sAddr + ", PRGM, RUN, RAM:" + _RAM+", STEP1"; // See page 56
|
||||
|
||||
return DataTransfer(cmd,out read, _ReturnDataWaitms);
|
||||
}
|
||||
|
||||
|
||||
public override Boolean IsFinished()
|
||||
{
|
||||
// Finished() returns true if chamber is not running. See page 36 MODE?.
|
||||
string sAddr = _Address.ToString();
|
||||
string cmd;
|
||||
string read;
|
||||
|
||||
cmd = sAddr + ", MON?";
|
||||
DataTransfer(cmd, out read, _ReturnDataWaitms);
|
||||
|
||||
try
|
||||
{
|
||||
double t = Double.Parse(read.Split(',')[0]);
|
||||
double RH = Double.Parse(read.Split(',')[1]);
|
||||
_Progress = String.Format("Current conditions are {0:0.0} °C and {1:0} %rh", t, RH);
|
||||
_LastProgressUpdate = DateTime.Now;
|
||||
}
|
||||
catch { _Progress = DateTime.Now.ToString("yyyy-MM-dd @ hh:mm"); }
|
||||
|
||||
|
||||
if (read.Contains("STANDBY"))
|
||||
return true;
|
||||
|
||||
if (read.Contains("OFF"))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
public override Boolean Stop()
|
||||
{
|
||||
string sAddr = _Address.ToString();
|
||||
string cmd;
|
||||
string read;
|
||||
cmd = sAddr + ", MODE, STANDBY";
|
||||
return DataTransfer(cmd, out read, _ReturnDataWaitms);
|
||||
}
|
||||
|
||||
|
||||
public override Boolean IsOnline()
|
||||
{
|
||||
try
|
||||
{
|
||||
string sAddr = _Address.ToString();
|
||||
string cmd;
|
||||
string read;
|
||||
cmd = sAddr + ", TYPE?";
|
||||
DataTransfer(cmd, out read, _ReturnDataWaitms);
|
||||
return (read.ToLower().Contains("scp220") );
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
private string _Progress = "";
|
||||
private DateTime _LastProgressUpdate = DateTime.Now;
|
||||
public override String Progress()
|
||||
{
|
||||
if(_LastProgressUpdate.AddMinutes(3) < DateTime.Now)
|
||||
IsFinished();
|
||||
return _Progress;
|
||||
}
|
||||
|
||||
|
||||
|
||||
private bool TxRxSucces(string cmd, string read)
|
||||
{
|
||||
// Command not correctly processed
|
||||
if (read.StartsWith("NA:"))
|
||||
return false;
|
||||
|
||||
// No response received
|
||||
if (read.Trim().Length < 1)
|
||||
return false;
|
||||
|
||||
// Handle monitoring commands
|
||||
if (cmd.Trim().Contains("?"))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (read.Trim().StartsWith("OK:"))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
private Boolean DataTransfer(string cmd, out string read, int ReturnDataWaitms)
|
||||
{
|
||||
// If no maximum number of attempts is given, it defaults to 4.
|
||||
return DataTransfer(cmd, out read, ReturnDataWaitms,4);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Performs transfer and adds interface logs to list in Client parent class
|
||||
private Boolean DataTransfer(string cmd, out string read, int ReturnDataWaitms, int MaxNumOfAttempts)
|
||||
{
|
||||
// Construct command to send
|
||||
cmd += (char)13; // CR
|
||||
cmd += (char)10; // LF
|
||||
cmd = cmd.Replace(" ", "");
|
||||
|
||||
|
||||
// Wait for _ReadyToSend or max 1 seconds
|
||||
DateTime go = DateTime.Now.AddSeconds(1);
|
||||
while (DateTime.Now < _ReadyToSend && DateTime.Now < go)
|
||||
System.Threading.Thread.Sleep(10);
|
||||
|
||||
read = "";
|
||||
bool success = false;
|
||||
int attempt = 0;
|
||||
while (!success && attempt < MaxNumOfAttempts)
|
||||
{
|
||||
DataTransferLog log = _Interface.DataTransfer(cmd, out read, ReturnDataWaitms);
|
||||
success = TxRxSucces(cmd, read);
|
||||
attempt++;
|
||||
|
||||
// Mask for showing in GUI
|
||||
if (cmd.Contains("MON?") || cmd.Contains("EDIT CANCEL") || cmd.Contains("EDITCANCEL"))
|
||||
log.ShowInGUI = false;
|
||||
|
||||
|
||||
// Notify user via GUI of failed attempts
|
||||
if (attempt > 1)
|
||||
log.Command += string.Format(" [Attempt {0:0}]", attempt);
|
||||
|
||||
// Add to logs
|
||||
AppendDataTransferLog(log);
|
||||
|
||||
|
||||
// Set _ReadyToSend acc. manual specs
|
||||
if (cmd.Contains("?"))
|
||||
_ReadyToSend = DateTime.Now.AddMilliseconds(500);
|
||||
else
|
||||
_ReadyToSend = DateTime.Now.AddMilliseconds(1200);
|
||||
|
||||
|
||||
// Sleeps
|
||||
if (!success)
|
||||
System.Threading.Thread.Sleep(5000); // Sleep 5 seconds before resending if failed
|
||||
}
|
||||
return success;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user