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 { /// /// Interaction logic for MainWindow.xaml /// 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 FSMSIID { get; set; } // untuk values di Combobox VX3K ID dan CIN public ObservableCollection VX3KID { get; set; } public ObservableCollection VX3KCIN { get; set; } // untuk values di Combobox Modbus Registers public ObservableCollection ModbusRegisters { get; set; } public ObservableCollection NetGroupList { get; set; } public ObservableCollection NetNodeList { get; set; } public ObservableCollection PNAList { get; set; } public ObservableCollection SINumberList { get; set; } public ObservableCollection SISubList { get; set; } ObservableCollection FsmTableMember { get; set; } ObservableCollection ModbusTableMember { get; set; } ObservableCollection VXTableMember { get; set; } FSMEvent fsmEvent; public MainWindow() { InitializeComponent(); // Di-isi dengan user input di Tab Fire Alarm FSMSIID = new ObservableCollection(); // Isinya ada di Window_Loaded ModbusRegisters = new ObservableCollection(); FsmTableMember = new ObservableCollection(); ModbusTableMember = new ObservableCollection(); VXTableMember = new ObservableCollection(); // Set default value for VX3KID and VX3KCIN VX3KID = new ObservableCollection(); for (int i = 0; i < 40; i++) { VX3KID.Add(i); } VX3KCIN = new ObservableCollection(); for (int i = 0; i < 16; i++) { VX3KCIN.Add(i); } NetGroupList = new ObservableCollection(); NetNodeList = new ObservableCollection(); PNAList = new ObservableCollection(); SINumberList = new ObservableCollection(); SISubList = new ObservableCollection(); 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().ToList(); this.DataContext = this; } 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)); 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); } // 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)); fsm.AddListener(new VXTriggerFromFSM(FsmTableMember, VXTableMember, vx3k)); } 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) { 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) { SIID selected = GetSIID(); if (selected != null) { MessageBoxResult result = MessageBox.Show("Delete SIID " + selected.ToString() + " ?", "Delete SIID", MessageBoxButton.YesNo); if (result == MessageBoxResult.Yes) { if (database != null) { if (database.RemoveFSMDatabySIID(selected.ToString())) { FSMTable.ItemsSource = database.GetFSMDatas(); FSMSIID.Remove(selected.ToString()); } else MessageBox.Show("Failed to delete from database"); } else MessageBox.Show("Database is null"); } } else MessageBox.Show("Invalid Selection"); } private void btnClearSIID_Click(object sender, RoutedEventArgs e) { MessageBoxResult result = MessageBox.Show("Clear all SIID ?", "Clear SIID", MessageBoxButton.YesNo); if (result == MessageBoxResult.Yes) { if (database != null) { if (database.ClearFSMTable()) { FSMTable.ItemsSource = database.GetFSMDatas(); FSMSIID.Clear(); } else MessageBox.Show("Failed to clear database"); } else MessageBox.Show("Database is null"); } } 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) { String ssid = ""; String reg = ""; if (ModbusSIIDComboBox.SelectedItem != null) { ssid = (string)ModbusSIIDComboBox.SelectedItem; } else { MessageBox.Show("Invalid SIID"); return; } if (ModbusRegister.SelectedItem != null) { reg = (String)ModbusRegister.SelectedItem; } else { MessageBox.Show("Invalid Register"); return; } MessageBoxResult result = MessageBox.Show("Delete SIID " + ssid + " Link with Register " + reg + " ?", "Delete Modbus Linkage", MessageBoxButton.YesNo); if (result == MessageBoxResult.Yes) { if (database != null) { if (database.RemoveModbusDatabySIID(ssid)) { ModbusTable.ItemsSource = database.GetModbusDatas(); } else MessageBox.Show("Failed to delete from database"); } else MessageBox.Show("Database is null"); } } 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) { if (database != null) { if (database.ClearModbusTable()) { ModbusTable.ItemsSource = database.GetModbusDatas(); } else MessageBox.Show("Failed to clear database"); } else MessageBox.Show("Database is null"); } } 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) { 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("Delete SIID " + ssid + " Link with Frame " + id + " CIN " + cin + " ?", "Delete VX Linkage", MessageBoxButton.YesNo); if (result == MessageBoxResult.Yes) { if (database != null) { if (database.RemoveVXDatabySIID(ssid)) { VXTable.ItemsSource = database.GetVXDatas(); } else MessageBox.Show("Failed to delete from database"); } else MessageBox.Show("Database is null"); } } 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) { if (database != null) { if (database.ClearVXTable()) { VXTable.ItemsSource = database.GetVXDatas(); } else MessageBox.Show("Failed to clear database"); } else MessageBox.Show("Database is null"); } } private void FSMTable_AutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e) { Debug.WriteLine("FSMTable_AutoGeneratingColumn : " + e.PropertyName); switch (e.PropertyName) { case "SIID": e.Column.Width = new DataGridLength(0, DataGridLengthUnitType.Auto); break; case "Enable": e.Column.Width = new DataGridLength(0, DataGridLengthUnitType.Auto); break; case "Description": e.Column.Width = new DataGridLength(1, DataGridLengthUnitType.Star); break; case "Value": e.Column.Width = new DataGridLength(0, DataGridLengthUnitType.Auto); break; case "LastUpdate": e.Column.Width = new DataGridLength(0, DataGridLengthUnitType.Auto); break; } } private void ModbusTable_AutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e) { Debug.WriteLine("ModbusTable_AutoGeneratingColumn : " + e.PropertyName); switch (e.PropertyName) { case "SIID": e.Column.Width = new DataGridLength(0, DataGridLengthUnitType.Auto); break; case "Register": e.Column.Width = new DataGridLength(0, DataGridLengthUnitType.Auto); break; case "Description": e.Column.Width = new DataGridLength(1, DataGridLengthUnitType.Star); break; case "Value": e.Column.Width = new DataGridLength(0, DataGridLengthUnitType.Auto); break; case "LastUpdate": e.Column.Width = new DataGridLength(0, DataGridLengthUnitType.Auto); break; } } private void VXTable_AutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e) { Debug.WriteLine("VXTable_AutoGeneratingColumn : " + e.PropertyName); switch (e.PropertyName) { case "SIID": e.Column.Width = new DataGridLength(0, DataGridLengthUnitType.Auto); break; case "ID": e.Column.Width = new DataGridLength(0, DataGridLengthUnitType.Auto); break; case "CIN": e.Column.Width = new DataGridLength(0, DataGridLengthUnitType.Auto); break; case "Description": e.Column.Width = new DataGridLength(1, DataGridLengthUnitType.Star); break; case "Value": e.Column.Width = new DataGridLength(0, DataGridLengthUnitType.Auto); break; case "LastUpdate": e.Column.Width = new DataGridLength(0, DataGridLengthUnitType.Auto); break; } } } // 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 ModbusSlave; public ModbusEvent(TextBlock statusbar, ListBox connectedlist, Label connectedcount) { this.statusbar = statusbar; this.connectedlist = connectedlist; this.connectedcount = connectedcount; ModbusSlave = new ObservableCollection(); ModbusSlave.CollectionChanged += (sender, e) => refresh_connectedlist(); } private void refresh_connectedlist() { 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); 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) { 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; } } 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 { ObservableCollection data; ListBox listbox; Label countlabel; int count = 0; public FSMTableUpdater(ObservableCollection 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 + " Type : " + type); count++; countlabel.Dispatcher.Invoke(() => countlabel.Content = "Count : " + count); listbox.Dispatcher.Invoke(() => listbox.Items.Add(new Label() { Content = SIID + " : " + type.ToString() })); } public void NewState(string SIID, NodeState previous, NodeState current) { Debug.WriteLine("New State : " + SIID + " Previous : " + previous + " Current : " + current); //FSMData dd = data.First(d => d.SIID == SIID); //if (dd != null) //{ // dd.LastUpdate = DateTime.Now.ToString(); // dd.Value = current.LogicalState ?? "Unknown"; //} } } // Class ini untuk Update Modbus Register dari FSM Update class ModbusTriggerFromFSM : FSMResultInterface { ObservableCollection source; ObservableCollection data; ModbusSlave slave; public ModbusTriggerFromFSM(ObservableCollection source, ObservableCollection data, ModbusSlave slave) { this.source = source; this.data = data; this.slave = slave; } public void DiscoveredSIID(string SIID, NodeData type) { } public void NewState(string SIID, NodeState previous, NodeState current) { //FSMData src = source.First(d => d.SIID == SIID); //ModbusData dt = data.First(d => d.SIID == SIID); //if (src != null && dt != null) //{ // if (src.Enable) // { // if (dt.Register >= 0) // { // dt.LastUpdate = DateTime.Now.ToString(); // dt.Value = current.LogicalState ?? "Unknown"; // if (slave != null) // { // switch (current.LogicalState) // { // case "ON": // slave.SetRegister(dt.Register, 1); // break; // case "NORMAL": // case "OFF": // slave.SetRegister(dt.Register, 0); // break; // } // } // } // } //} } } // Class ini untuk Trigger VX3K dari FSM Update class VXTriggerFromFSM : FSMResultInterface { ObservableCollection data; ObservableCollection source; VX3K vx; public VXTriggerFromFSM(ObservableCollection source, ObservableCollection data, VX3K vx) { this.source = source; this.data = data; this.vx = vx; } public void DiscoveredSIID(string SIID, NodeData type) { } public void NewState(string SIID, NodeState previous, NodeState current) { //FSMData src = source.First(d => d.SIID == SIID); //VXData dt = data.First(d => d.SIID == SIID); //if (src != null && dt != null) //{ // if (src.Enable) // { // dt.LastUpdate = DateTime.Now.ToString(); // dt.Value = current.LogicalState ?? "Unknown"; // if (vx != null && vx.IsConnected()) // { // switch (current.LogicalState) // { // case "ON": // vx.Virtual_Contact_Input(dt.FrameID, dt.CIN, true); // break; // case "NORMAL": // case "OFF": // vx.Virtual_Contact_Input(dt.FrameID, dt.CIN, false); // break; // } // } // } //} } } }