1517 lines
54 KiB
C#
1517 lines
54 KiB
C#
using FSM5000FSIAPI.Version3;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Collections.ObjectModel;
|
|
using System.Diagnostics;
|
|
using System.Linq;
|
|
using System.Net;
|
|
using System.Text;
|
|
using System.Text.RegularExpressions;
|
|
using System.Threading.Tasks;
|
|
using System.Windows;
|
|
using System.Windows.Controls;
|
|
using System.Windows.Data;
|
|
using System.Windows.Documents;
|
|
using System.Windows.Input;
|
|
using System.Windows.Media;
|
|
using System.Windows.Media.Imaging;
|
|
using System.Windows.Navigation;
|
|
using System.Windows.Shapes;
|
|
using System.Windows.Threading;
|
|
|
|
namespace FAtoPA.Net
|
|
{
|
|
/// <summary>
|
|
/// Interaction logic for MainWindow.xaml
|
|
/// </summary>
|
|
public partial class MainWindow : Window
|
|
{
|
|
private DispatcherTimer timer1s;
|
|
private Config config;
|
|
private Database database;
|
|
private FSM fsm;
|
|
private ModbusSlave modbusSlave;
|
|
private VX3K vx3k;
|
|
|
|
// untuk values di Combobox FSM SIID
|
|
public ObservableCollection<string> FSMSIID { get; set; }
|
|
// untuk values di Combobox VX3K ID dan CIN
|
|
public ObservableCollection<int> VX3KID { get; set; }
|
|
public ObservableCollection<int> VX3KCIN { get; set; }
|
|
// untuk values di Combobox Modbus Registers
|
|
public ObservableCollection<int> ModbusRegisters { get; set; }
|
|
|
|
// Untuk manual add SIID to FSM Table
|
|
public ObservableCollection<int> NetGroupList { get; set; }
|
|
public ObservableCollection<int> NetNodeList { get; set; }
|
|
public ObservableCollection<int> PNAList { get; set; }
|
|
public ObservableCollection<int> SINumberList { get; set; }
|
|
public ObservableCollection<int> SISubList { get; set; }
|
|
|
|
// Isi FSM Table
|
|
ObservableCollection<FSMData> FsmTableMember { get; set; }
|
|
// Isi Modbus Table
|
|
ObservableCollection<ModbusData> ModbusTableMember { get; set; }
|
|
// Isi VX Table
|
|
ObservableCollection<VXData> VXTableMember { get; set; }
|
|
|
|
public List<String> ConditionON;
|
|
public List<String> ConditionOFF;
|
|
|
|
FSMEvent fsmEvent;
|
|
public MainWindow()
|
|
{
|
|
InitializeComponent();
|
|
// Di-isi dengan user input di Tab Fire Alarm
|
|
FSMSIID = new ObservableCollection<string>();
|
|
|
|
// Isinya ada di Window_Loaded
|
|
ModbusRegisters = new ObservableCollection<int>();
|
|
FsmTableMember = new ObservableCollection<FSMData>();
|
|
ModbusTableMember = new ObservableCollection<ModbusData>();
|
|
VXTableMember = new ObservableCollection<VXData>();
|
|
|
|
|
|
|
|
// Set default value for VX3KID and VX3KCIN
|
|
VX3KID = new ObservableCollection<int>();
|
|
for (int i = 0; i < 40; i++)
|
|
{
|
|
VX3KID.Add(i);
|
|
}
|
|
|
|
VX3KCIN = new ObservableCollection<int>();
|
|
for (int i = 0; i < 16; i++)
|
|
{
|
|
VX3KCIN.Add(i);
|
|
}
|
|
|
|
NetGroupList = new ObservableCollection<int>();
|
|
NetNodeList = new ObservableCollection<int>();
|
|
PNAList = new ObservableCollection<int>();
|
|
|
|
SINumberList = new ObservableCollection<int>();
|
|
SISubList = new ObservableCollection<int>();
|
|
|
|
for (int ii = 1; ii < 256; ii++)
|
|
{
|
|
NetGroupList.Add(ii);
|
|
NetNodeList.Add(ii);
|
|
PNAList.Add(ii);
|
|
|
|
SINumberList.Add(ii);
|
|
SISubList.Add(ii);
|
|
}
|
|
|
|
siType.ItemsSource = Enum.GetValues(typeof(SIType)).Cast<SIType>().ToList();
|
|
|
|
this.DataContext = this;
|
|
|
|
//TODO : Add Condition for ON and OFF
|
|
ConditionON = new List<string>();
|
|
ConditionON.Add(SILogicalState.ACTIVATION.ToString());
|
|
ConditionON.Add(SILogicalState.FIRE.ToString());
|
|
|
|
ConditionOFF = new List<string>();
|
|
ConditionOFF.Add(SILogicalState.NORMAL.ToString());
|
|
}
|
|
|
|
private void Window_Loaded(object sender, RoutedEventArgs e)
|
|
{
|
|
Debug.WriteLine("Window Loaded");
|
|
// Timer untuk update datetimebar tiap 1 detik
|
|
timer1s = new DispatcherTimer();
|
|
timer1s.Interval = new TimeSpan(0, 0, 1);
|
|
timer1s.Tick += Timer1s_Tick;
|
|
|
|
timer1s.Start();
|
|
|
|
// Load Config
|
|
config = new Config();
|
|
config.Load();
|
|
FSMConfig_NetGroup.Text = config.FSM_NetGroup.ToString();
|
|
FSMConfig_NetNode.Text = config.FSM_NetNode.ToString();
|
|
FSMConfig_PNA.Text = config.FSM_PNA.ToString();
|
|
FSMConfig_LocalIP.Text = config.FSM_LocalIP;
|
|
FSM_UseMulticast.IsChecked = config.FSM_UseMulticast;
|
|
FSMConfig_MulticastAddress.Text = config.FSM_MulticastIP;
|
|
FSMConfig_MulticastPort.Text = config.FSM_MulticastPort.ToString();
|
|
Debug.WriteLine("NetGroup : " + config.FSM_NetGroup);
|
|
Debug.WriteLine("NetNode : " + config.FSM_NetNode);
|
|
Debug.WriteLine("PNA : " + config.FSM_PNA);
|
|
Debug.WriteLine("LocalIP : " + config.FSM_LocalIP);
|
|
Debug.WriteLine("UseMulticast : " + config.FSM_UseMulticast);
|
|
Debug.WriteLine("MulticastIP : " + config.FSM_MulticastIP);
|
|
Debug.WriteLine("MulticastPort : " + config.FSM_MulticastPort);
|
|
|
|
|
|
ModbusListenPort.Text = config.Modbus_ListenPort.ToString();
|
|
ModbusDeviceID.Text = config.Modbus_DeviceID.ToString();
|
|
ModbusMaxRegister.Text = config.Modbus_MaxRegister.ToString();
|
|
VX3K_IP.Text = config.VX_TargetIP;
|
|
VX3K_Port.Text = config.VX_TargetPort.ToString();
|
|
|
|
|
|
|
|
|
|
// Load Database
|
|
database = new Database();
|
|
database.GetFSMDatas().ForEach(f =>
|
|
{
|
|
FsmTableMember.Add(f);
|
|
FSMSIID.Add(f.SIID);
|
|
});
|
|
database.GetModbusDatas().ForEach(m => ModbusTableMember.Add(m));
|
|
database.GetVXDatas().ForEach(v => VXTableMember.Add(v));
|
|
|
|
FSMTable.ItemsSource = FsmTableMember;
|
|
ModbusTable.ItemsSource = ModbusTableMember;
|
|
VXTable.ItemsSource = VXTableMember;
|
|
|
|
// Load FSM
|
|
fsmEvent = new FSMEvent(this.firealarmstatusbar);
|
|
fsm = new FSM(fsmEvent, config.FSM_NetGroup, config.FSM_NetNode, config.FSM_PNA, IPAddress.Parse(config.FSM_LocalIP).GetAddressBytes());
|
|
if (config.FSM_UseMulticast)
|
|
{
|
|
fsm.MulticastConfig(config.FSM_UseMulticast, IPAddress.Parse(config.FSM_MulticastIP).GetAddressBytes(), config.FSM_MulticastPort);
|
|
}
|
|
|
|
|
|
ModbusRegisters.Clear();
|
|
|
|
for (int i = 0; i < config.Modbus_MaxRegister; i++)
|
|
{
|
|
ModbusRegisters.Add(i);
|
|
}
|
|
Debug.WriteLine($"Creating ModbusRegisters untuk Combobox, length={ModbusRegisters.Count}");
|
|
|
|
// Load Modbus Slave
|
|
modbusSlave = new ModbusSlave(new ModbusEvent(modbusstatusbar, ConnectedModbusClients, ConnectedModbusCount), config.Modbus_MaxRegister);
|
|
modbusSlave.ID = config.Modbus_DeviceID;
|
|
//modbusSlave.Start(config.Modbus_ListenPort);
|
|
|
|
// Connect with VX3000
|
|
vx3k = new VX3K(new VX3KEvent(this.vxstatusbar));
|
|
//vx3k.Connect(config.VX_TargetIP, config.VX_TargetPort);
|
|
|
|
|
|
fsm.AddListener(new FSMTableUpdater(FsmTableMember, DetectedSIID, DetectedSIIDCount));
|
|
fsm.AddListener(new ModbusTriggerFromFSM(FsmTableMember, ModbusTableMember, modbusSlave, ConditionON, ConditionOFF));
|
|
fsm.AddListener(new VXTriggerFromFSM(FsmTableMember, VXTableMember, vx3k, ConditionON, ConditionOFF));
|
|
}
|
|
|
|
private void Timer1s_Tick(object sender, EventArgs e)
|
|
{
|
|
datetimebar.Text = DateTime.Now.ToString();
|
|
}
|
|
|
|
private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
|
|
{
|
|
Debug.WriteLine("Window Closing");
|
|
timer1s.Stop();
|
|
fsm.Stop();
|
|
modbusSlave.Stop();
|
|
vx3k.Disconnect();
|
|
}
|
|
|
|
private void btnStartStopFSM_Click(object sender, RoutedEventArgs e)
|
|
{
|
|
if (FSM.Started)
|
|
{
|
|
fsm.Stop();
|
|
btnStartStopFSM.Content = "Start FSM Connection";
|
|
FSM.Started = false;
|
|
}
|
|
else
|
|
{
|
|
fsm.Start();
|
|
btnStartStopFSM.Content = "Stop FSM Connection";
|
|
FSM.Started = true;
|
|
}
|
|
}
|
|
|
|
private void btnStartStopModbus_Click(object sender, RoutedEventArgs e)
|
|
{
|
|
if (ModbusSlave.Started)
|
|
{
|
|
modbusSlave.Stop();
|
|
btnStartStopModbus.Content = "Start Modbus Connection";
|
|
ModbusSlave.Started = false;
|
|
}
|
|
else
|
|
{
|
|
if (config != null)
|
|
{
|
|
modbusSlave.Start(config.Modbus_ListenPort);
|
|
btnStartStopModbus.Content = "Stop Modbus Connection";
|
|
ModbusSlave.Started = true;
|
|
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
private void btnStartStopVX_Click(object sender, RoutedEventArgs e)
|
|
{
|
|
if (VX3K.Started)
|
|
{
|
|
vx3k.Disconnect();
|
|
btnStartStopVX.Content = "Start VX Connection";
|
|
VX3K.Started = false;
|
|
}
|
|
else
|
|
{
|
|
if (config != null)
|
|
{
|
|
vx3k.Connect(config.VX_TargetIP, config.VX_TargetPort);
|
|
btnStartStopVX.Content = "Stop VX Connection";
|
|
VX3K.Started = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
private void ApplyFSMConfig(object sender, RoutedEventArgs e)
|
|
{
|
|
if (config != null)
|
|
{
|
|
Boolean changed = false;
|
|
int netgroup = 0;
|
|
if (int.TryParse(FSMConfig_NetGroup.Text, out netgroup))
|
|
{
|
|
if (NetGroupList.Contains(netgroup))
|
|
{
|
|
if (netgroup != config.FSM_NetGroup)
|
|
{
|
|
config.FSM_NetGroup = (byte)netgroup;
|
|
changed = true;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
MessageBox.Show("Invalid Net Group");
|
|
return;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
MessageBox.Show("Invalid Net Group");
|
|
return;
|
|
}
|
|
int netnode = 0;
|
|
if (int.TryParse(FSMConfig_NetNode.Text, out netnode))
|
|
{
|
|
if (NetNodeList.Contains(netnode))
|
|
{
|
|
if (netnode != config.FSM_NetNode)
|
|
{
|
|
config.FSM_NetNode = (byte)netnode;
|
|
changed = true;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
MessageBox.Show("Invalid Net Node");
|
|
return;
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
MessageBox.Show("Invalid Net Node");
|
|
return;
|
|
}
|
|
int pna = 0;
|
|
if (int.TryParse(FSMConfig_PNA.Text, out pna))
|
|
{
|
|
if (PNAList.Contains(pna))
|
|
{
|
|
if (pna != config.FSM_PNA)
|
|
{
|
|
config.FSM_PNA = (byte)pna;
|
|
changed = true;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
MessageBox.Show("Invalid PNA");
|
|
return;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
MessageBox.Show("Invalid PNA");
|
|
return;
|
|
}
|
|
if (TextIsIPAddress(FSMConfig_LocalIP.Text))
|
|
{
|
|
if (FSMConfig_LocalIP.Text != config.FSM_LocalIP)
|
|
{
|
|
config.FSM_LocalIP = FSMConfig_LocalIP.Text;
|
|
changed = true;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
MessageBox.Show("Invalid Local IP");
|
|
return;
|
|
}
|
|
|
|
if (FSM_UseMulticast.IsChecked != null)
|
|
{
|
|
if (FSM_UseMulticast.IsChecked != config.FSM_UseMulticast)
|
|
{
|
|
config.FSM_UseMulticast = (bool)FSM_UseMulticast.IsChecked;
|
|
changed = true;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
MessageBox.Show("Invalid Multicast Use");
|
|
return;
|
|
}
|
|
|
|
if (TextIsIPAddress(FSMConfig_MulticastAddress.Text))
|
|
{
|
|
if (FSMConfig_MulticastAddress.Text != config.FSM_MulticastIP)
|
|
{
|
|
config.FSM_MulticastIP = FSMConfig_MulticastAddress.Text;
|
|
changed = true;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
MessageBox.Show("Invalid Multicast Address");
|
|
return;
|
|
}
|
|
int multicastport = 0;
|
|
if (int.TryParse(FSMConfig_MulticastPort.Text, out multicastport))
|
|
{
|
|
if (multicastport >= 0 && multicastport <= 65535)
|
|
{
|
|
if (multicastport != config.FSM_MulticastPort)
|
|
{
|
|
config.FSM_MulticastPort = (ushort)multicastport;
|
|
changed = true;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
MessageBox.Show("Invalid Multicast Port");
|
|
return;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
MessageBox.Show("Invalid Multicast Port");
|
|
return;
|
|
}
|
|
if (changed)
|
|
{
|
|
if (config.Save())
|
|
{
|
|
MessageBox.Show("FSM Config Saved");
|
|
//TODO : Restart FSM Connection
|
|
}
|
|
else MessageBox.Show("FSM Config Save Failed");
|
|
}
|
|
else MessageBox.Show("No changes in FSM Config");
|
|
}
|
|
else MessageBox.Show("Config is null");
|
|
}
|
|
|
|
private void ApplyModbusConfig(object sender, RoutedEventArgs e)
|
|
{
|
|
if (config != null)
|
|
{
|
|
Boolean changed = false;
|
|
int listenport = 0;
|
|
if (int.TryParse(ModbusListenPort.Text, out listenport))
|
|
{
|
|
if (listenport >= 0 && listenport <= 65535)
|
|
{
|
|
if (listenport != config.Modbus_ListenPort)
|
|
{
|
|
config.Modbus_ListenPort = (ushort)listenport;
|
|
changed = true;
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
MessageBox.Show("Invalid Listen Port");
|
|
return;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
MessageBox.Show("Invalid Listen Port");
|
|
return;
|
|
}
|
|
int devid = 0;
|
|
if (int.TryParse(ModbusDeviceID.Text, out devid))
|
|
{
|
|
if (devid >= 1 && devid <= 247)
|
|
{
|
|
if (devid != config.Modbus_DeviceID)
|
|
{
|
|
config.Modbus_DeviceID = (byte)devid;
|
|
changed = true;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
MessageBox.Show("Invalid Device ID");
|
|
return;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
MessageBox.Show("Invalid Device ID");
|
|
return;
|
|
}
|
|
int maxreg = 0;
|
|
if (int.TryParse(ModbusMaxRegister.Text, out maxreg))
|
|
{
|
|
if (maxreg >= 1 && maxreg <= 10000)
|
|
{
|
|
if (maxreg != config.Modbus_MaxRegister)
|
|
{
|
|
config.Modbus_MaxRegister = (ushort)maxreg;
|
|
changed = true;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
MessageBox.Show("Invalid Max Register");
|
|
return;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
MessageBox.Show("Invalid Max Register");
|
|
}
|
|
if (changed)
|
|
{
|
|
if (config.Save())
|
|
{
|
|
MessageBox.Show("Modbus Config Saved");
|
|
//TODO : Restart Modbus Connection
|
|
}
|
|
else MessageBox.Show("Modbus Config Save Failed");
|
|
}
|
|
else MessageBox.Show("No changes in Modbus Config");
|
|
}
|
|
else MessageBox.Show("Config is null");
|
|
|
|
}
|
|
|
|
private void ApplyVX3KConfig(object sender, RoutedEventArgs e)
|
|
{
|
|
if (config != null)
|
|
{
|
|
Boolean changed = false;
|
|
String ipaddress = "";
|
|
int port = 0;
|
|
try
|
|
{
|
|
IPAddress ip = IPAddress.Parse(VX3K_IP.Text);
|
|
ipaddress = ip.ToString();
|
|
if (ipaddress != config.VX_TargetIP)
|
|
{
|
|
config.VX_TargetIP = ipaddress;
|
|
changed = true;
|
|
}
|
|
}
|
|
catch (Exception)
|
|
{
|
|
MessageBox.Show("Invalid IP Address");
|
|
return;
|
|
}
|
|
if (int.TryParse(VX3K_Port.Text, out port))
|
|
{
|
|
if (port != config.VX_TargetPort)
|
|
{
|
|
config.VX_TargetPort = (ushort)port;
|
|
changed = true;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
MessageBox.Show("Invalid Port");
|
|
return;
|
|
}
|
|
|
|
if (changed)
|
|
{
|
|
if (config.Save())
|
|
{
|
|
MessageBox.Show("VX3K Config Saved");
|
|
//TODO : Restart VX3K Connection
|
|
}
|
|
else MessageBox.Show("VX3K Config Save Failed");
|
|
}
|
|
else MessageBox.Show("No changes in VX3K Config");
|
|
}
|
|
else MessageBox.Show("Config is null");
|
|
|
|
}
|
|
|
|
// Regex Protection for FSMConfig_NetGroup
|
|
private void FSMConfig_NetGroup_PreviewTextInput(object sender, TextCompositionEventArgs e)
|
|
{
|
|
TextBoxNumberOnly(e);
|
|
}
|
|
|
|
// Regex Protection for FSMConfig_NetNode
|
|
private void FSMConfig_NetNode_PreviewTextInput(object sender, TextCompositionEventArgs e)
|
|
{
|
|
TextBoxNumberOnly(e);
|
|
}
|
|
|
|
// Regex Protection for FSMConfig_PNA
|
|
private void FSMConfig_PNA_PreviewTextInput(object sender, TextCompositionEventArgs e)
|
|
{
|
|
TextBoxNumberOnly(e);
|
|
}
|
|
|
|
// Regex Protection for FSMConfig_LocalIP
|
|
private void FSMConfig_LocalIP_PreviewTextInput(object sender, TextCompositionEventArgs e)
|
|
{
|
|
TextBoxIPAddressOnly(e);
|
|
}
|
|
|
|
// Regex Protection for FSMConfig_MulticastAddress
|
|
private void FSMConfig_MulticastAddress_PreviewTextInput(object sender, TextCompositionEventArgs e)
|
|
{
|
|
TextBoxIPAddressOnly(e);
|
|
}
|
|
|
|
// Regex Protection for FSMConfig_MulticastPort
|
|
private void FSMConfig_MulticastPort_PreviewTextInput(object sender, TextCompositionEventArgs e)
|
|
{
|
|
TextBoxNumberOnly(e);
|
|
}
|
|
|
|
// If NetGroup value is changed, check for valid value. If not valid, change background to red
|
|
private void FSMConfig_NetGroup_TextChanged(object sender, TextChangedEventArgs e)
|
|
{
|
|
TextBox_FSMVerify(FSMConfig_NetGroup);
|
|
}
|
|
|
|
// If NetNode value is changed, check for valid value. If not valid, change background to red
|
|
private void FSMConfig_NetNode_TextChanged(object sender, TextChangedEventArgs e)
|
|
{
|
|
TextBox_FSMVerify(FSMConfig_NetNode);
|
|
}
|
|
|
|
// If PNA value is changed, check for valid value. If not valid, change background to red
|
|
private void FSMConfig_PNA_TextChanged(object sender, TextChangedEventArgs e)
|
|
{
|
|
TextBox_FSMVerify(FSMConfig_PNA);
|
|
}
|
|
|
|
// If LocalIP value is changed, check for valid value. If not valid, change background to red
|
|
private void FSMConfig_LocalIP_TextChanged(object sender, TextChangedEventArgs e)
|
|
{
|
|
TextBox_IPVerify(FSMConfig_LocalIP);
|
|
}
|
|
|
|
// If MulticastAddress value is changed, check for valid value. If not valid, change background to red
|
|
private void FSMConfig_MulticastAddress_TextChanged(object sender, TextChangedEventArgs e)
|
|
{
|
|
TextBox_IPVerify(FSMConfig_MulticastAddress);
|
|
}
|
|
|
|
// If MulticastPort value is changed, check for valid value. If not valid, change background to red
|
|
private void FSMConfig_MulticastPort_TextChanged(object sender, TextChangedEventArgs e)
|
|
{
|
|
TextBox_PortVerify(FSMConfig_MulticastPort);
|
|
}
|
|
|
|
// Only allow number input
|
|
private void TextBoxNumberOnly(TextCompositionEventArgs e)
|
|
{
|
|
Regex regex = new Regex("[^0-9]+");
|
|
e.Handled = regex.IsMatch(e.Text);
|
|
}
|
|
|
|
private void TextBoxIPAddressOnly(TextCompositionEventArgs e)
|
|
{
|
|
//string pattern = @"^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$";
|
|
//Regex regex = new Regex(pattern);
|
|
//e.Handled = regex.IsMatch(e.Text);
|
|
e.Handled = TextIsIPAddress(e.Text);
|
|
}
|
|
private Boolean TextIsIPAddress(String vv)
|
|
{
|
|
if (vv != null)
|
|
{
|
|
if (vv.Length > 0)
|
|
{
|
|
string pattern = @"^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$";
|
|
Regex regex = new Regex(pattern);
|
|
return regex.IsMatch(vv);
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
// Verify Textbox value for FSM, which mostly only accept number 1 - 255
|
|
private void TextBox_FSMVerify(TextBox e)
|
|
{
|
|
if (int.TryParse(e.Text, out int result))
|
|
{
|
|
if (result < 0 || result > 255)
|
|
{
|
|
e.Background = Brushes.Red;
|
|
}
|
|
else
|
|
{
|
|
e.Background = Brushes.Transparent;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
e.Background = Brushes.Red;
|
|
}
|
|
}
|
|
|
|
private void TextBox_IPVerify(TextBox e)
|
|
{
|
|
try
|
|
{
|
|
IPAddress.Parse(e.Text);
|
|
e.Background = Brushes.Transparent;
|
|
}
|
|
catch (Exception)
|
|
{
|
|
e.Background = Brushes.Red;
|
|
}
|
|
}
|
|
|
|
private void TextBox_PortVerify(TextBox e)
|
|
{
|
|
if (int.TryParse(e.Text, out int result))
|
|
{
|
|
if (result < 0 || result > 65535)
|
|
{
|
|
e.Background = Brushes.Red;
|
|
}
|
|
else
|
|
{
|
|
e.Background = Brushes.Transparent;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
e.Background = Brushes.Red;
|
|
}
|
|
}
|
|
|
|
private void VX3K_IP_PreviewTextInput(object sender, TextCompositionEventArgs e)
|
|
{
|
|
TextBoxIPAddressOnly(e);
|
|
}
|
|
|
|
private void VX3K_Port_PreviewTextInput(object sender, TextCompositionEventArgs e)
|
|
{
|
|
TextBoxNumberOnly(e);
|
|
}
|
|
|
|
private void ModbusListenPort_PreviewTextInput(object sender, TextCompositionEventArgs e)
|
|
{
|
|
TextBoxNumberOnly(e);
|
|
}
|
|
|
|
private void ModbusDeviceID_PreviewTextInput(object sender, TextCompositionEventArgs e)
|
|
{
|
|
TextBoxNumberOnly(e);
|
|
}
|
|
|
|
private void ModbusMaxRegister_PreviewTextInput(object sender, TextCompositionEventArgs e)
|
|
{
|
|
TextBoxNumberOnly(e);
|
|
}
|
|
|
|
private void ModbusListenPort_TextChanged(object sender, TextChangedEventArgs e)
|
|
{
|
|
TextBox_PortVerify(ModbusListenPort);
|
|
}
|
|
|
|
private void VX3K_Port_TextChanged(object sender, TextChangedEventArgs e)
|
|
{
|
|
TextBox_PortVerify(VX3K_Port);
|
|
}
|
|
|
|
private void VX3K_IP_TextChanged(object sender, TextChangedEventArgs e)
|
|
{
|
|
TextBox_IPVerify(VX3K_IP);
|
|
}
|
|
|
|
private void ModbusDeviceID_TextChanged(object sender, TextChangedEventArgs e)
|
|
{
|
|
int devid = 0;
|
|
if (int.TryParse(ModbusDeviceID.Text, out devid))
|
|
{
|
|
if (devid >= 1 && devid <= 247)
|
|
{
|
|
ModbusDeviceID.Background = Brushes.Transparent;
|
|
}
|
|
else
|
|
{
|
|
ModbusDeviceID.Background = Brushes.Red;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ModbusDeviceID.Background = Brushes.Red;
|
|
}
|
|
}
|
|
|
|
private void ModbusMaxRegister_TextChanged(object sender, TextChangedEventArgs e)
|
|
{
|
|
int maxreg = 0;
|
|
if (int.TryParse(ModbusMaxRegister.Text, out maxreg))
|
|
{
|
|
if (maxreg >= 1 && maxreg <= 10000)
|
|
{
|
|
ModbusMaxRegister.Background = Brushes.Transparent;
|
|
}
|
|
else
|
|
{
|
|
ModbusMaxRegister.Background = Brushes.Red;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ModbusMaxRegister.Background = Brushes.Red;
|
|
}
|
|
}
|
|
|
|
private void btnAddSIID_Click(object sender, RoutedEventArgs e)
|
|
{
|
|
SIID selected = GetSIID();
|
|
if (selected != null)
|
|
{
|
|
MessageBoxResult result = MessageBox.Show("Add SIID " + selected.ToString() + " ?", "Add SIID", MessageBoxButton.YesNo);
|
|
if (result == MessageBoxResult.Yes)
|
|
{
|
|
if (database != null)
|
|
{
|
|
//TODO Manual Add SIID, perlukah ?
|
|
|
|
//FSMData f = new FSMData(selected.ToString());
|
|
//if (database.AddFSMData(f))
|
|
//{
|
|
// FSMTable.ItemsSource = database.GetFSMDatas();
|
|
// FSMSIID.Add(selected.ToString());
|
|
//}
|
|
//else MessageBox.Show("Failed to add to database");
|
|
}
|
|
else MessageBox.Show("Database is null");
|
|
}
|
|
}
|
|
else MessageBox.Show("Invalid Selection");
|
|
|
|
}
|
|
|
|
private void btnDelSIID_Click(object sender, RoutedEventArgs e)
|
|
{
|
|
if (FSMTable != null)
|
|
{
|
|
var selected = FSMTable.SelectedItem as FSMData;
|
|
if (selected != null)
|
|
{
|
|
MessageBoxResult result = MessageBox.Show($"Are you sure want to delete SIID={selected.SIID}, Label={selected.Label}, Type={selected.Type} ?", "Delete SIID", MessageBoxButton.YesNo);
|
|
if (result == MessageBoxResult.Yes)
|
|
{
|
|
FsmTableMember.Remove(selected);
|
|
database.RemoveFSMDatabySIID(selected.SIID);
|
|
FSMSIID.Remove(selected.SIID);
|
|
}
|
|
}
|
|
else MessageBox.Show("Select a row in table to delete");
|
|
}
|
|
}
|
|
|
|
private void btnClearSIID_Click(object sender, RoutedEventArgs e)
|
|
{
|
|
MessageBoxResult result = MessageBox.Show("Clear all SIID ?", "Clear SIID", MessageBoxButton.YesNo);
|
|
if (result == MessageBoxResult.Yes)
|
|
{
|
|
FsmTableMember.Clear();
|
|
database.ClearFSMTable();
|
|
FSMSIID.Clear();
|
|
|
|
}
|
|
}
|
|
|
|
private SIID GetSIID()
|
|
{
|
|
int netgroup = 0;
|
|
int netnode = 0;
|
|
SIType sitype = 0;
|
|
int sinumber = 0;
|
|
int sisub = 0;
|
|
|
|
if (netGroupNumber.SelectedItem != null)
|
|
{
|
|
netgroup = (int)netGroupNumber.SelectedItem;
|
|
if (netNodeNumber.SelectedItem != null)
|
|
{
|
|
netnode = (int)netNodeNumber.SelectedItem;
|
|
if (siType.SelectedItem != null)
|
|
{
|
|
sitype = (SIType)siType.SelectedItem;
|
|
if (siNumber.SelectedItem != null)
|
|
{
|
|
sinumber = (int)siNumber.SelectedItem;
|
|
if (siSub.SelectedItem != null)
|
|
{
|
|
sisub = (int)siSub.SelectedItem;
|
|
|
|
return new SIID((byte)netgroup, (byte)netnode, sitype, (ushort)sinumber, (byte)sisub);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return null;
|
|
|
|
}
|
|
|
|
private void btnAddModbus_Click(object sender, RoutedEventArgs e)
|
|
{
|
|
String ssid = "";
|
|
int reg = 0;
|
|
if (ModbusSIIDComboBox.SelectedItem != null)
|
|
{
|
|
ssid = (string)ModbusSIIDComboBox.SelectedItem;
|
|
}
|
|
else
|
|
{
|
|
MessageBox.Show("Invalid SIID"); return;
|
|
}
|
|
if (ModbusRegister.SelectedItem != null)
|
|
{
|
|
reg = (int)ModbusRegister.SelectedItem;
|
|
}
|
|
else
|
|
{
|
|
MessageBox.Show("Invalid Register"); return;
|
|
}
|
|
|
|
MessageBoxResult result = MessageBox.Show("Add SIID " + ssid + " Link with Register " + reg + " ?", "Add Modbus Linkage", MessageBoxButton.YesNo);
|
|
if (result == MessageBoxResult.Yes)
|
|
{
|
|
if (database != null)
|
|
{
|
|
ModbusData m = new ModbusData(ssid, (ushort)reg);
|
|
if (database.AddModbusData(m))
|
|
{
|
|
ModbusTable.ItemsSource = database.GetModbusDatas();
|
|
}
|
|
else MessageBox.Show("Failed to add to database");
|
|
}
|
|
else MessageBox.Show("Database is null");
|
|
}
|
|
}
|
|
|
|
private void btnDelModbus_Click(object sender, RoutedEventArgs e)
|
|
{
|
|
if (ModbusTable != null)
|
|
{
|
|
var selected = ModbusTable.SelectedItem as ModbusData;
|
|
if (selected != null)
|
|
{
|
|
MessageBoxResult xx = MessageBox.Show($"Are you sure want to delete SIID={selected.SIID}, Register={selected.Register} ?", "Delete SIID", MessageBoxButton.YesNo);
|
|
if (xx == MessageBoxResult.Yes)
|
|
{
|
|
database.RemoveModbusDatabySIID(selected.SIID);
|
|
ModbusTableMember.Remove(selected);
|
|
}
|
|
}
|
|
else MessageBox.Show("Select a row in Table to delete");
|
|
}
|
|
|
|
}
|
|
|
|
private void btnClearModbus_Click(object sender, RoutedEventArgs e)
|
|
{
|
|
MessageBoxResult result = MessageBox.Show("Clear all Modbus Linkage ?", "Clear Modbus Linkage", MessageBoxButton.YesNo);
|
|
if (result == MessageBoxResult.Yes)
|
|
{
|
|
database.ClearModbusTable();
|
|
ModbusTableMember.Clear();
|
|
}
|
|
}
|
|
|
|
private void btnAddVX_Click(object sender, RoutedEventArgs e)
|
|
{
|
|
String ssid = "";
|
|
int id = 0;
|
|
int cin = 0;
|
|
if (VXSIIDComboBox.SelectedItem != null)
|
|
{
|
|
ssid = (string)VXSIIDComboBox.SelectedItem;
|
|
}
|
|
else
|
|
{
|
|
MessageBox.Show("Invalid SIID"); return;
|
|
}
|
|
if (VXFrame.SelectedItem != null)
|
|
{
|
|
id = (int)VXFrame.SelectedItem;
|
|
}
|
|
else
|
|
{
|
|
MessageBox.Show("Invalid ID"); return;
|
|
}
|
|
if (VXCIN.SelectedItem != null)
|
|
{
|
|
cin = (int)VXCIN.SelectedItem;
|
|
}
|
|
else
|
|
{
|
|
MessageBox.Show("Invalid CIN"); return;
|
|
}
|
|
|
|
MessageBoxResult result = MessageBox.Show("Add SIID " + ssid + " Link with Frame " + id + " CIN " + cin + " ?", "Add VX Linkage", MessageBoxButton.YesNo);
|
|
if (result == MessageBoxResult.Yes)
|
|
{
|
|
if (database != null)
|
|
{
|
|
VXData v = new VXData(ssid, (byte)id, (byte)cin);
|
|
if (database.AddVXData(v))
|
|
{
|
|
VXTable.ItemsSource = database.GetVXDatas();
|
|
}
|
|
else MessageBox.Show("Failed to add to database");
|
|
}
|
|
else MessageBox.Show("Database is null");
|
|
}
|
|
}
|
|
|
|
private void btnDelVX_Click(object sender, RoutedEventArgs e)
|
|
{
|
|
if (VXTable != null)
|
|
{
|
|
var selected = VXTable.SelectedItem as VXData;
|
|
if (selected != null)
|
|
{
|
|
var result = MessageBox.Show($"Delete SIID={selected.SIID}, ID={selected.FrameID}, CIN={selected.CIN} ?", "Delete SIID", MessageBoxButton.YesNo);
|
|
if (result == MessageBoxResult.Yes)
|
|
{
|
|
database.RemoveVXDatabySIID(selected.SIID);
|
|
VXTableMember.Remove(selected);
|
|
}
|
|
}
|
|
else MessageBox.Show("Select a row in Table to delete");
|
|
}
|
|
}
|
|
|
|
private void btnClearVX_Click(object sender, RoutedEventArgs e)
|
|
{
|
|
MessageBoxResult result = MessageBox.Show("Clear all VX Linkage ?", "Clear VX Linkage", MessageBoxButton.YesNo);
|
|
if (result == MessageBoxResult.Yes)
|
|
{
|
|
database.ClearVXTable();
|
|
VXTableMember.Clear();
|
|
}
|
|
}
|
|
|
|
private void FSMTable_AutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e)
|
|
{
|
|
Debug.WriteLine("FSMTable_AutoGeneratingColumn : " + e.PropertyName);
|
|
switch (e.PropertyName)
|
|
{
|
|
case "SIID":
|
|
e.Column.Width = DataGridLength.Auto;
|
|
break;
|
|
case "Enable":
|
|
e.Column.Width = DataGridLength.Auto;
|
|
break;
|
|
case "Description":
|
|
e.Column.Width = DataGridLength.Auto;
|
|
break;
|
|
case "Value":
|
|
e.Column.Width = DataGridLength.Auto;
|
|
break;
|
|
case "LastUpdate":
|
|
e.Column.Width = DataGridLength.Auto;
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
private void ModbusTable_AutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e)
|
|
{
|
|
Debug.WriteLine("ModbusTable_AutoGeneratingColumn : " + e.PropertyName);
|
|
switch (e.PropertyName)
|
|
{
|
|
case "SIID":
|
|
e.Column.Width = DataGridLength.Auto;
|
|
break;
|
|
case "Register":
|
|
e.Column.Width = DataGridLength.Auto;
|
|
break;
|
|
case "Description":
|
|
e.Column.Width = DataGridLength.Auto;
|
|
break;
|
|
case "Value":
|
|
e.Column.Width = DataGridLength.Auto;
|
|
break;
|
|
case "LastUpdate":
|
|
e.Column.Width = DataGridLength.Auto;
|
|
break;
|
|
}
|
|
}
|
|
|
|
private void VXTable_AutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e)
|
|
{
|
|
Debug.WriteLine("VXTable_AutoGeneratingColumn : " + e.PropertyName);
|
|
switch (e.PropertyName)
|
|
{
|
|
case "SIID":
|
|
e.Column.Width = DataGridLength.Auto;
|
|
break;
|
|
case "ID":
|
|
e.Column.Width = DataGridLength.Auto;
|
|
break;
|
|
case "CIN":
|
|
e.Column.Width = DataGridLength.Auto;
|
|
break;
|
|
case "Description":
|
|
e.Column.Width = DataGridLength.Auto;
|
|
break;
|
|
case "Value":
|
|
e.Column.Width = DataGridLength.Auto;
|
|
break;
|
|
case "LastUpdate":
|
|
e.Column.Width = DataGridLength.Auto;
|
|
break;
|
|
}
|
|
}
|
|
|
|
private void AddSelectedSIID(object sender, RoutedEventArgs e)
|
|
{
|
|
var lbl = DetectedSIID.SelectedItem;
|
|
if (lbl != null && lbl is Label)
|
|
{
|
|
Label selected = (Label)lbl;
|
|
if (selected.Tag is NodeData)
|
|
{
|
|
NodeData data = (NodeData)selected.Tag;
|
|
FSMData fSMData = new FSMData(data.SIID.ToString(), true, data.Label, data.Description);
|
|
|
|
|
|
if (database.FSMDataHaveSIID(fSMData.SIID)!=null)
|
|
{
|
|
Debug.WriteLine($"database already have SIID={fSMData.SIID}");
|
|
} else
|
|
{
|
|
if (database.AddFSMData(fSMData))
|
|
{
|
|
FsmTableMember.Add(fSMData);
|
|
FSMSIID.Add(fSMData.SIID);
|
|
Debug.WriteLine($"Added SIID={fSMData.SIID}, Label={fSMData.Label}, Type= {fSMData.Type} to database");
|
|
}
|
|
else MessageBox.Show($"Failed to add SIID={fSMData.SIID}, Label={fSMData.Label}, Type={fSMData.Type} to database");
|
|
}
|
|
|
|
}
|
|
else MessageBox.Show("Selected SIID dont have NodeData");
|
|
} else MessageBox.Show("No SIID Selected");
|
|
}
|
|
}
|
|
|
|
// event handler for VX3K
|
|
class VX3KEvent : EventInterface
|
|
{
|
|
private TextBlock statusbar;
|
|
public VX3KEvent(TextBlock statusbar)
|
|
{
|
|
this.statusbar = statusbar;
|
|
}
|
|
public void ConnectStatus(bool success, string message)
|
|
{
|
|
Debug.WriteLine("VX-3000 ConnectStatus: " + success + " " + message);
|
|
if (statusbar != null) statusbar.Background = success ? Brushes.Green : Brushes.Transparent;
|
|
}
|
|
|
|
public void StatisticUpdate(uint TXOK, uint RXOK, uint TXErr, uint RXerr, uint TXBytes, uint RXBytes)
|
|
{
|
|
if (statusbar != null) statusbar.Text = "VX-3000 : TXOK: " + TXOK + " RXOK: " + RXOK + " TXErr: " + TXErr + " RXErr: " + RXerr + " TXBytes: " + TXBytes + " RXBytes: " + RXBytes;
|
|
}
|
|
|
|
public void Log(string msg)
|
|
{
|
|
Debug.WriteLine("VX-3000 Log: " + msg);
|
|
}
|
|
}
|
|
|
|
class ModbusEvent : ModbusSlaveEvent
|
|
{
|
|
private TextBlock statusbar;
|
|
private ListBox connectedlist;
|
|
private Label connectedcount;
|
|
private ObservableCollection<ModbusClientRecord> ModbusSlave;
|
|
|
|
public ModbusEvent(TextBlock statusbar, ListBox connectedlist, Label connectedcount)
|
|
{
|
|
this.statusbar = statusbar;
|
|
this.connectedlist = connectedlist;
|
|
this.connectedcount = connectedcount;
|
|
ModbusSlave = new ObservableCollection<ModbusClientRecord>();
|
|
ModbusSlave.CollectionChanged += (sender, e) => refresh_connectedlist();
|
|
}
|
|
|
|
private void refresh_connectedlist()
|
|
{
|
|
Application.Current.Dispatcher.Invoke(() =>
|
|
{
|
|
connectedlist.Items.Clear();
|
|
foreach (ModbusClientRecord client in ModbusSlave)
|
|
{
|
|
TextBlock l = new TextBlock();
|
|
l.Width = connectedlist.Width;
|
|
l.Margin = new Thickness(5, 0, 5, 0);
|
|
l.TextWrapping = TextWrapping.Wrap;
|
|
UpdateLabel(l, client);
|
|
l.Tag = client;
|
|
connectedlist.Items.Add(l);
|
|
|
|
}
|
|
if (connectedcount != null) connectedcount.Content = "Connected : " + connectedlist.Items.Count;
|
|
});
|
|
|
|
|
|
}
|
|
|
|
void ModbusSlaveEvent.Log(string msg)
|
|
{
|
|
Debug.WriteLine("Modbus Log: " + msg);
|
|
}
|
|
|
|
void ModbusSlaveEvent.NewConnection(ModbusClientRecord client)
|
|
{
|
|
ModbusSlave.Add(client);
|
|
}
|
|
|
|
void ModbusSlaveEvent.CloseConnection(ModbusClientRecord client)
|
|
{
|
|
ModbusSlave.Remove(client);
|
|
}
|
|
|
|
void ModbusSlaveEvent.ConnectStatus(bool success, string message)
|
|
{
|
|
Debug.WriteLine("Modbus ConnectStatus: " + success + " " + message);
|
|
if (statusbar != null) statusbar.Background = success ? Brushes.Green : Brushes.Transparent;
|
|
}
|
|
|
|
public void TXRXStatusUpdate(ModbusClientRecord client)
|
|
{
|
|
connectedlist.Dispatcher.Invoke(() => {
|
|
foreach (var item in connectedlist.Items)
|
|
{
|
|
TextBlock l = (TextBlock)item;
|
|
if (l.Tag == client)
|
|
{
|
|
UpdateLabel(l, client);
|
|
return;
|
|
}
|
|
}
|
|
});
|
|
|
|
}
|
|
|
|
private void UpdateLabel(TextBlock l, ModbusClientRecord client)
|
|
{
|
|
|
|
l.Text = client.remoteEP + "/TX: " + client.TXBytes + "/RX: " + client.RXBytes + "/TXOK: " + client.TXResponse + "/RXOK: " + client.RXValidRequest+"/RXFAIL: "+client.RXInvalidRequest;
|
|
|
|
}
|
|
}
|
|
|
|
class FSMEvent : EventInterface
|
|
{
|
|
private TextBlock statusbar;
|
|
public FSMEvent(TextBlock statusbar)
|
|
{
|
|
this.statusbar = statusbar;
|
|
}
|
|
public void ConnectStatus(bool success, string message)
|
|
{
|
|
if (statusbar != null)
|
|
{
|
|
statusbar.Dispatcher.Invoke(() =>
|
|
{
|
|
statusbar.Background = success ? Brushes.Green : Brushes.Transparent;
|
|
statusbar.Text = "FSM : " + message;
|
|
});
|
|
|
|
}
|
|
Debug.WriteLine("FSM ConnectStatus: " + success + " " + message);
|
|
}
|
|
|
|
public void Log(string msg)
|
|
{
|
|
Debug.WriteLine("FSM Log: " + msg);
|
|
}
|
|
|
|
public void StatisticUpdate(uint TXOK, uint RXOK, uint TXErr, uint RXerr, uint TXBytes, uint RXBytes)
|
|
{
|
|
//if (statusbar != null)
|
|
//{
|
|
|
|
// statusbar.Dispatcher.Invoke(() =>
|
|
|
|
// {
|
|
// statusbar.Text = "FSM : TXOK: " + TXOK + " RXOK: " + RXOK + " TXErr: " + TXErr + " RXErr: " + RXerr + " TXBytes: " + TXBytes + " RXBytes: " + RXBytes;
|
|
// });
|
|
|
|
|
|
//}
|
|
}
|
|
}
|
|
|
|
// Class ini untuk update Table FSM
|
|
class FSMTableUpdater : FSMResultInterface
|
|
{
|
|
// dari database
|
|
ObservableCollection<FSMData> data;
|
|
ListBox listbox;
|
|
Label countlabel;
|
|
public FSMTableUpdater(ObservableCollection<FSMData> data, ListBox listbox, Label countlabel)
|
|
{
|
|
this.data = data;
|
|
this.listbox = listbox;
|
|
this.countlabel = countlabel;
|
|
}
|
|
|
|
public void DiscoveredSIID(string SIID, NodeData type)
|
|
{
|
|
Debug.WriteLine($"Discovered SIID={SIID} Label={type.Label} Type={type.Description}");
|
|
if (type.Label != null && type.Label.Length > 0)
|
|
{
|
|
if (type.Description != null && type.Description.Length > 0)
|
|
{
|
|
// yang punya Label dan Description saja yang masuk ke Listbox dan dihitung
|
|
Application.Current.Dispatcher.Invoke(() =>
|
|
{
|
|
listbox.Items.Add(new Label() { Content = $"{SIID} : {type.Label} : {type.Description}", Tag = type });
|
|
countlabel.Content = "Count : " + listbox.Items.Count;
|
|
});
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
public void NewState(string SIID, NodeState previous, NodeState current)
|
|
{
|
|
Debug.WriteLine("New State : " + SIID + " Previous : " + previous?.LogicalState + " Current : " + current.LogicalState);
|
|
|
|
if (data != null)
|
|
{
|
|
// update yang ada di FsmTable saja
|
|
foreach (var dd in data)
|
|
{
|
|
if (dd.SIID.Equals(SIID))
|
|
{
|
|
dd.LastUpdate = DateTime.Now.ToString();
|
|
dd.Value = current.LogicalState ?? "Unknown";
|
|
Debug.WriteLine($"Changing row in FSM Table for SIID={SIID} Value={dd.Value}");
|
|
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
Debug.WriteLine($"FSM Table dont have row with SIID={SIID}");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// Class ini untuk Update Modbus Register dari FSM Update
|
|
class ModbusTriggerFromFSM : FSMResultInterface
|
|
{
|
|
// dari database
|
|
ObservableCollection<FSMData> source;
|
|
ObservableCollection<ModbusData> data;
|
|
ModbusSlave slave;
|
|
List<String> ConditionON;
|
|
List<String> ConditionOFF;
|
|
public ModbusTriggerFromFSM(ObservableCollection<FSMData> source, ObservableCollection<ModbusData> data, ModbusSlave slave, List<string> conditionON, List<string> conditionOFF)
|
|
{
|
|
this.source = source;
|
|
this.data = data;
|
|
this.slave = slave;
|
|
ConditionON = conditionON;
|
|
ConditionOFF = conditionOFF;
|
|
}
|
|
public void DiscoveredSIID(string SIID, NodeData type)
|
|
{
|
|
|
|
}
|
|
|
|
|
|
public void NewState(string SIID, NodeState previous, NodeState current)
|
|
{
|
|
|
|
FSMData src = null;
|
|
ModbusData dt = null;
|
|
foreach(var x in source)
|
|
{
|
|
if (x.SIID.Equals(SIID))
|
|
{
|
|
src = x;
|
|
break;
|
|
}
|
|
}
|
|
foreach (var x in data)
|
|
{
|
|
if (x.SIID.Equals(SIID))
|
|
{
|
|
dt = x;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (src != null && dt != null)
|
|
{
|
|
if (src.Enable)
|
|
{
|
|
if (dt.Register >= 0)
|
|
{
|
|
if (slave != null)
|
|
{
|
|
if (ConditionON != null && ConditionOFF != null)
|
|
{
|
|
if (ConditionON.Contains(current.LogicalState))
|
|
{
|
|
Debug.WriteLine($"NewState for SIID={SIID} State={current.LogicalState} is ConditionON");
|
|
slave.SetRegister(dt.Register, 1);
|
|
dt.Value = "ON";
|
|
}
|
|
else if (ConditionOFF.Contains(current.LogicalState))
|
|
{
|
|
Debug.WriteLine($"NewState for SIID={SIID} State={current.LogicalState} is ConditionOFF");
|
|
slave.SetRegister(dt.Register, 0);
|
|
dt.Value = "OFF";
|
|
}
|
|
else
|
|
{
|
|
Debug.WriteLine($"NewState for SIID={SIID} in Modbus is ignored because Condition ON/OFF is not met");
|
|
dt.Value = "RULE NOT AVAILABLE";
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Debug.WriteLine($"Condition ON/OFF for SIID={SIID} in Modbus is not set");
|
|
dt.Value = "RULE NOT SET";
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Debug.WriteLine($"Not connected to Modbus Slave, NewState for SIID={SIID} in Modbus is ignored");
|
|
dt.Value = "NO MODBUS";
|
|
}
|
|
dt.LastUpdate = DateTime.Now.ToString();
|
|
|
|
|
|
} else Debug.WriteLine($"NewState for SIID={SIID} in Modbus is ignored because Register is not set");
|
|
} else Debug.WriteLine($"NewState for SIID={SIID} in Modbus is ignored because FSMData is Disabled");
|
|
} else Debug.WriteLine($"NewState for SIID={SIID} in Modbus is ignored because not registered in ModbusTable");
|
|
}
|
|
}
|
|
|
|
// Class ini untuk Trigger VX3K dari FSM Update
|
|
class VXTriggerFromFSM : FSMResultInterface
|
|
{
|
|
ObservableCollection<VXData> data;
|
|
ObservableCollection<FSMData> source;
|
|
VX3K vx;
|
|
List<String> ConditionON;
|
|
List<String> ConditionOFF;
|
|
public VXTriggerFromFSM(ObservableCollection<FSMData> source, ObservableCollection<VXData> data, VX3K vx, List<string> conditionON, List<string> conditionOFF)
|
|
{
|
|
this.source = source;
|
|
this.data = data;
|
|
this.vx = vx;
|
|
ConditionON = conditionON;
|
|
ConditionOFF = conditionOFF;
|
|
}
|
|
public void DiscoveredSIID(string SIID, NodeData type)
|
|
{
|
|
|
|
}
|
|
|
|
|
|
public void NewState(string SIID, NodeState previous, NodeState current)
|
|
{
|
|
FSMData src = null;
|
|
VXData dt = null;
|
|
foreach (var x in source)
|
|
{
|
|
if (x.SIID.Equals(SIID))
|
|
{
|
|
src = x;
|
|
break;
|
|
}
|
|
}
|
|
foreach (var x in data)
|
|
{
|
|
if (x.SIID.Equals(SIID))
|
|
{
|
|
dt = x;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (src != null && dt != null)
|
|
{
|
|
if (src.Enable)
|
|
{
|
|
if (vx != null && vx.IsConnected())
|
|
{
|
|
if (ConditionON != null && ConditionOFF != null)
|
|
{
|
|
if (ConditionON.Contains(current.LogicalState))
|
|
{
|
|
Debug.WriteLine($"NewState for SIID={SIID} State={current.LogicalState} is ConditionON");
|
|
vx.Virtual_Contact_Input(dt.FrameID, dt.CIN, true);
|
|
dt.Value = "ON";
|
|
}
|
|
else if (ConditionOFF.Contains(current.LogicalState))
|
|
{
|
|
Debug.WriteLine($"NewState for SIID={SIID} State={current.LogicalState} is ConditionOFF");
|
|
vx.Virtual_Contact_Input(dt.FrameID, dt.CIN, false);
|
|
dt.Value = "OFF";
|
|
}
|
|
else
|
|
{
|
|
Debug.WriteLine($"NewState for SIID={SIID} in VX3K is ignored because Condition ON/OFF is not met");
|
|
dt.Value = "RULE NOT AVAILABLE";
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Debug.WriteLine($"Condition ON/OFF for SIID={SIID} in VX3K is not set");
|
|
dt.Value = "RULE NOT SET";
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Debug.WriteLine($"Not connected to VX3K, NewState for SIID={SIID} in VX3K is ignored");
|
|
dt.Value = "NO VX";
|
|
}
|
|
dt.LastUpdate = DateTime.Now.ToString();
|
|
} else Debug.WriteLine($"NewState for SIID={SIID} in VX3K is ignored because FSMData is Disabled");
|
|
} else Debug.WriteLine($"NewState for SIID={SIID} in VX3K is ignored because not registered in VXTable");
|
|
|
|
}
|
|
}
|
|
}
|