using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; using Microsoft.Win32; using System.Net; using System.Diagnostics; using System.IO; using System.Collections; using System.Threading; using System.Media; // cyim 2015.7.29 수신반 모드 // 수신반의 경우의 환경설정은 아래와 같다 // 수신기와 마찬가지로 레지스트리를 읽어서 현재 DB 정보를 읽도록 한다. ini 파일에 의해 수신반이 될지, 수신기가 될지 결정된다. // 동작 기본 : 기존과 동일하게 레지스트리값을 읽어 DB 를 읽고, 이 DB 는 수신기의 아이디 리스트 및 기본 디바이스 설정 정보를 가져오기 위한 용도로만 사용한다 // 주의해야 될 점은 소스측면에서는 수신반의 레지스트리에서 지정된 경로로 데이타베이스에 접속할때는 수신기 아이디가 0 으로 조회를 하게 된다, // 실제 데이타베이스에 조회하는 경우가 있을때는 각 수신기의 실제 DB 에 접속하여 접속하여 사용한다. 데몬을 통하는 것은 카운터, 이벤트 정보뿐이다. // 다만, DB 백업 및 기타 동작은 무시해도 된다. 수신반은 모니터링이 주 목적이다. // 수신기별 프로젝트 및 DB 파일 위치 : 각각 아이디별로 틀리다. DB 경로와 프로젝트 파일이 동일한 파일을 각각 폴더에 셋팅해두도록 한다 (Config.ini 을 참고해야됨) // 프로그램 모드 : Config.ini 파일에 mode 가 1로 되어 있으면 수신반, ini 파일이 없다면 기본으로 수신기 프로그램으로 동작된다 // cyim 2015.8.4 수신반을 위한 static 클래스 정리 // 수신반을 위한 Static 클래스 정리 // -> Static 을 허용하는 것은 오직 _Data.cs 와 _Ini.cs _Timer.cs_Data.cs 와 _Ini.cs _Timer.cs // 기존코드를 많이 수정하였다. 이는 결국 MdiParent 클래스를 독립적으로 관리하게 수정하는 것을 최종 목표로한다 // cyim 2015.9.15 수신반 1차 버전 완료 : 2.0.1.0 // 수신기 상태 및 제어 기능 // 카운터 통합 모니터링 기능 // 개별 수신기 복구 // 통합 현재 이벤트 표시 기능 // 통합 과거 내역 조회 기능 // cyim 2015.9.30 수신반은 ini 파일을 이용해서 데이타베이스 접속 : 2.0.1.1 namespace FPER { public partial class FireDesk : Form { // 임시 아이디 리스트를 만들어서 폼을 load 완료하면 리스트에서 삭제하도록 하여 전체 폼을 다 미리 로드한다 public ArrayList LoadMdiparentFormList = new ArrayList(); // 폼을 로드한것이 진행중이라면 수신반 메인폼에서 계속 폼을 생성하지 못하게 한다 public bool FormLoadComplete = false; // 수신기폼을 로드시에 기다리는 팝업창을 생성 public frmWaitingMsg waitingForm_FireDesk = null; // cyim 2015.8.3 검토해본 결과 기존의 팝업창을 그대로 사용하도록 한다 // cyim 2015.8.4 수신반을 위한 static 클래스 정리 : 타이머 public _Timer_WindowBase Timer_WindowBase_FireDesk = new _Timer_WindowBase(); // cyim 2015.8.4 수신반을 위한 static 클래스 정리 : 이벤트 public _Event Event = new _Event(); // cyim 2015.9.1 1개의 수신기가 접속이 안되더라도 나머지는 접속시도할수 있도록 수정 public ArrayList CommErrorReceiver = new ArrayList(); // cyim 2015.9.15 수신반 하단 이벤트 표시 // 카운터 표시 (통합 카운터이다. 즉 모든 수신기의 카운터의 합이다) // // 아래의 변수 정보는 수신기로 부터 직접 전달받은 카운터를 합 한것이고, 일정 시간마다 갱신된다 public int fireCount = 0, facilityCount = 0, errorCount = 0, blockingCount = 0, cutCnt = 0; public int fireCount_Accumulation = 0; // 아래의 리스트 정보는 각각 수신기의 이벤트가 발생할때마다 갱신된다 public ArrayList PreFireList = new ArrayList(); public ArrayList FireList = new ArrayList(); public ArrayList FireList_Accumulation = new ArrayList(); public ArrayList EquipList = new ArrayList(); // 상태 라벨 카운트 (미사용) public int LEDCount = 0; public ArrayList LEDList = new ArrayList(); // cyim 2015.9.23 시간정보 표시 오류 (갱신을 안함) public string MyTime = null; // cyim 2016.06.15 : 화재 음원 출력 //public SoundPlayer SoundPlayer_AlarmPopupSound = new SoundPlayer(Properties.Resources.emergency); public SoundPlayer SoundPlayer_AlarmPopupSound = null; public int SoundPlayer_AlarmPopupSound_Count = 0; // 생성자 public FireDesk() { InitializeComponent(); // cyim 2016.11.11 : 비상 음원 출력 음원 파일 없을때 대응 코드 추가 if (File.Exists(Environment.CurrentDirectory + "\\emergency.wav") == true) SoundPlayer_AlarmPopupSound = new SoundPlayer(Environment.CurrentDirectory + "\\emergency.wav");// cyim 2016.06.24 : 음원 출력시 교체 가능 // 이벤트 this.FormClosing += new FormClosingEventHandler(FireDesk_FormClosing); this.Load += new EventHandler(FireDesk_Load); Event.FireDesk_Update_SendMessage_Event += new _Event.FireDesk_Update_SendMessage_Handler(_Event_FireDesk_Update_SendMessage_Event); // cyim 2015.8.4 수신반을 위한 static 클래스 정리 // UI for (int id = 1; id <= 16; id++) { // 수신기 버튼 Button button_Receiver = (Button)Util.FineControl(panel_Middle, "button_Receiver" + id.ToString()); button_Receiver.Tag = id.ToString(); button_Receiver.Click += new EventHandler(button_Receiver_Click); // 수신기 복구 버튼 Button button_Recover = (Button)Util.FineControl(panel_Middle, "button_Recover" + id.ToString()); button_Recover.Tag = id.ToString(); button_Recover.Click += new EventHandler(button_Recover_Click); } // cyim 2015.8.4 수신반을 위한 static 클래스 정리 ; 타이머 Timer_WindowBase_FireDesk.Create("timer_1000", 1000, timer_1000_Tick, true); Timer_WindowBase_FireDesk.Create("timer_500", 500, timer_500_Tick, true); } // 소멸자 private void FireDesk_FormClosing(object sender, FormClosingEventArgs e) { // 타이머 Timer_WindowBase_FireDesk.Delete("timerDateTime"); // cyim 2015.8.4 수신반을 위한 static 클래스 정리 // // cyim 2016.11.11 : 수신반 프로세스 종료 코드 추가 // // 스레드 종료 Application.ExitThread(); for (int i = 0; i < 1000000; i++) { ;} // 프로세스 종료 Application.Exit(); // 프로세스가 남아있다면 최종 종료 System.Diagnostics.Process[] mProcess = System.Diagnostics.Process.GetProcessesByName(Application.ProductName); foreach (System.Diagnostics.Process p in mProcess) p.Kill(); // 최종 정리 (보완코드 : 크로스 스레드 문제 발생 여지가 있으므로 사용주의) Environment.Exit(0); } // // 초기화 // private void FireDesk_Load(object sender, EventArgs e) { // cyim 2015.7.31 수신반 팝업창은 별도로 존재 ShowWaitingMsgForm("수신반을 시작합니다", 10); // cyim // 해당 DB 를 읽고 어떤 IP 에 어떤 수신기 ID 가 맵핑되어있는지 알아야한다 // 수신기에 원격으로 데몬이 붙어서 동작할수 있다. // 맨처음 가동단계는 현재 DB 를 읽어서 수신반 구동을 시작한다 // 현재 데이타베이스를 읽고 현재 설정된 수신기가 어떤 아이디들로 구성되어 있는지 알아야 한다 // 데이타베이스를 토대로 각각 수신기 정보를 알아야 되며, 레지스트리 값을 읽어서 쓰는 루틴은 그대로 이용하되, // 레지스트리 값중에 프로젝트 경로는 각 수신기별로 정보를 가지고 있도록 해야한다 // 수신반의 경우 중계기, 보드 정보, 수신기 설정값을 알필요가 없다. (물론 각 수신기에 접속하면 알수가 있지만 평상시에는 알 필요가 없다) // 수신기 아이디 해쉬 테이블 초기화 - Config.ini 기반 Initialize_Hash_Receiver(_Data.Hash_Receiver); // 수신기 아이디 키 배열 생성 _Data.Hash_Receiver_keys = new string[_Data.Hash_Receiver.Keys.Count]; _Data.Hash_Receiver.Keys.CopyTo(_Data.Hash_Receiver_keys, 0); // 수신기 아이디 해쉬 테이블 셋팅 - DB 기반 foreach (string id in _Data.Hash_Receiver_keys) { _FireDesk_Receiver FireDesk_Receiver = (_FireDesk_Receiver)_Data.Hash_Receiver[id]; // 특별처리 : 데이타베이스를 접근해야되는데 어차피 TB_CONFIG 테이블은 유일하게 수신반DB 에 사용되므로 // 수신반 DB를 이용하도록 한다. 수신반 DB 를 접근하려면 아이디가 0으로 되어있으면 수신반 DB 이다. // 경로는 레지스트리 값 경로를 이용하면 된다 DacReceiverConfig dacReceiverConfig = new DacReceiverConfig(0); DataTable dt = dacReceiverConfig.Config_Select(0); // 마스터 모드 foreach (DataRow dr in dt.Rows) { if (id == dr["RECEIVER_ID"].ToString()) { FireDesk_Receiver.MASTER_FLAG = dr["MASTER_FLAG"].ToString();//dt.Rows[0]["MASTER_FLAG"].ToString(); break; } } } // cyim 2015.9.11 : 과거내역 통합조회창에서 사용할 DB 에서 미리 읽은값을 사용하도록 수정함 // 공통정보를 데이타베이스에서 불러온다 ShowWaitingMsgForm("수신기 디바이스 DB를 읽고 있습니다..", 20); this.GetDeviceDB(); ShowWaitingMsgForm("수신기 중계기 DB를 읽고 있습니다..", 30); this.GetRepeaterDB(); //AnalogDetect.Get_TB_DAYTIME(0); // 수신반은 필요없다 this.GetAnalogDetecterLevelDB(); ShowWaitingMsgForm("수신기 통신 보드 설정을 읽고 있습니다..", 40); this.GetBoardDB(); ShowWaitingMsgForm("수신기 기본 설정값을 읽고 있습니다..", 50); // // UI // // 불필요한 수신기는 정리한다 for (int id = 1; id <= 16; id++) { // 사용하지 않는 수신기 if (_Data.Hash_Receiver.ContainsKey(id.ToString()) == false) { Panel p = (Panel)Util.FineControl(panel_Middle, "panel_Receiver" + id.ToString()); p.Enabled = false; p.ForeColor = Color.Gray; } else { // // 사용중인 수신기 // _FireDesk_Receiver FireDesk_Receiver = (_FireDesk_Receiver)_Data.Hash_Receiver[id.ToString()]; // cyim 2015.9.1 1개의 수신기가 접속이 안되더라도 나머지는 접속시도할수 있도록 수정 if (_Ethernet.Ping_SyncCheck(FireDesk_Receiver.DATABASE_NAME_IP) == true) { // 클래스를 생성한다, 단 Load, 즉 Show 는 하지 않는다 FireDesk_Receiver.mdi = new MDIParent(id, Event); // cyim 2015.8.4 수신반을 위한 static 클래스 정리 // 어레이리스트의 경우 int 값을 키로 하면 오류가 발생할 여지가 있다. LoadMdiparentFormList.Add(id.ToString()); } else { Panel p = (Panel)Util.FineControl(panel_Middle, "panel_Receiver" + id.ToString()); p.Enabled = false; p.BackColor = Color.Red; CommErrorReceiver.Add(id.ToString()); } } } // cyim 2015.9.1 1개의 수신기가 접속이 안되더라도 나머지는 접속시도할수 있도록 수정 : 활성화된 수신기를 개수를 표시한다 if(CommErrorReceiver.Count != 0) label_ReceiverCount.Text = string.Format("전체 수신기 대수 : {0} 개 , 통신 불량 수신기 아이디 : {1}", _Data.Hash_Receiver.Keys.Count, _Convert.ArrayList_to_String(CommErrorReceiver,",")); else label_ReceiverCount.Text = string.Format("전체 수신기 대수 : {0} 개", _Data.Hash_Receiver.Keys.Count); // 클래스를 미리 업로드 시킨다. 단, 팝업창을 포함해서 모두 숨긴채로 로드한다 while (true) { foreach (string id in _Data.Hash_Receiver_keys) { // 해쉬테이블에서 폼로드 진행을 변수에 저장 _FireDesk_Receiver FireDesk_Receiver = (_FireDesk_Receiver)_Data.Hash_Receiver[id]; // cyim 2015.9.1 1개의 수신기가 접속이 안되더라도 나머지는 접속시도할수 있도록 수정 if (_Ethernet.Ping_SyncCheck(FireDesk_Receiver.DATABASE_NAME_IP) == true) { if (FireDesk_Receiver.LoadStart == false && FormLoadComplete == false) { FormLoadComplete = true; // 하단의 mdi.show 함수에서 딜레이가 심하다. 코드 위치를 변경하면 안된다 FireDesk_Receiver.LoadStart = true; FireDesk_Receiver.mdi.Show(); // 실제로 수신기 메인폼을 올리는 주체는 여기다 } } } if (LoadMdiparentFormList.Count == 0) break; } // cyim 2015.7.31 수신반 팝업창은 별도로 존재 : 문구 출력 이후에 종료 ShowWaitingMsgForm("수신반을 시작합니다", 100); Thread.Sleep(2000); waitingForm_FireDesk.Close(); waitingForm_FireDesk = null; } // // 수신반 클래스 초기화 // private void Initialize_Hash_Receiver(Hashtable hashtable) { hashtable.Clear(); for (int i = 1; i <= 16; i++) { // USE 값이 1인 경우에만 읽도록 한다 string use = _Ini.Read_Ini("RECEIVER"+i.ToString(), "USE", 1024, Environment.CurrentDirectory + "\\Config.ini"); if (use == "1") { // 수신반 클래스 _FireDesk_Receiver firedesk_receiver = new _FireDesk_Receiver(); // 아이디 firedesk_receiver.RECEIVER_ID = i.ToString(); string Temp_DATABASE_NAME = _Ini.Read_Ini("RECEIVER" + i.ToString(), "DATABASE_NAME", 1024, Environment.CurrentDirectory + "\\Config.ini"); // IP + PATH firedesk_receiver.DATABASE_NAME = Temp_DATABASE_NAME; // IP firedesk_receiver.DATABASE_NAME_IP = Temp_DATABASE_NAME.Substring(0, Temp_DATABASE_NAME.IndexOf(":")); // PATH firedesk_receiver.DATABASE_NAME_PATH = Temp_DATABASE_NAME.Substring(Temp_DATABASE_NAME.IndexOf(":") + 1); string Temp_PROJECT_DIR = _Ini.Read_Ini("RECEIVER" + i.ToString(), "PROJECT_DIR", 1024, Environment.CurrentDirectory + "\\Config.ini"); // 프로젝트 경로 firedesk_receiver.PROJECT_DIRECTORY = Temp_PROJECT_DIR; // 해쉬에 추가 if (hashtable.ContainsKey(firedesk_receiver.RECEIVER_ID) == false) hashtable.Add(firedesk_receiver.RECEIVER_ID, firedesk_receiver); } } } // // 팝업창 // // cyim 2015.7.31 수신반 팝업창은 별도로 존재 // delegate void WaitingMsg_Callback(string msg, int processValue); public void ShowWaitingMsgForm(string msg, int processValue) { if (this.InvokeRequired) { WaitingMsg_Callback d = new WaitingMsg_Callback(ShowWaitingMsgForm); this.Invoke(d, new object[] { msg, processValue }); } else { if (this.waitingForm_FireDesk == null) { // cyim 2015.8.3 검토해본 결과 기존의 팝업창을 그대로 사용하도록 한다 // 다만 수신기별로 각각 팝업창이 계속 표시가 되면 될것같음. 즉 같은 팝업창의 진행도가 0~100 ->0~100 을 자동반복함 this.waitingForm_FireDesk = new frmWaitingMsg(); this.waitingForm_FireDesk.Text = Application.ProductName; this.waitingForm_FireDesk.TopMost = true; Point loc = new Point( (1280 - this.waitingForm_FireDesk.Size.Width) / 2 + this.Location.X, (1024 - this.waitingForm_FireDesk.Size.Height) / 2 + this.Location.Y ); this.waitingForm_FireDesk.Location = loc; this.waitingForm_FireDesk.Show(); } this.waitingForm_FireDesk.setMessage(msg, processValue); this.Update(); } } // // 타이머 // // 1000 ms 타이머 int timer_1000_Tick_Cnt = 0; private void timer_1000_Tick(object sende, EventArgs e) { // cyim 2015.9.23 시간정보 표시 오류 (갱신을 안함) MyTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"); // 초기화 팝업창때는 실행안됨 if (waitingForm_FireDesk != null && waitingForm_FireDesk.Visible == true) return; // 현재 상태 갱신 : 시간표시 this.label_Time.Text = string.Format("{0:yyyy}년 {0:MM}월 {0:dd}일 {0:HH}:{0:mm}:{0:ss}", DateTime.Now); // cyim 2015.9.15 주기적으로 수신기 통신상태를 점검 : 10 초에 한번 수신기 통신상태를 점검해본다 if (timer_1000_Tick_Cnt > 10) timer_1000_Tick_Cnt = 0; else timer_1000_Tick_Cnt++; if (timer_1000_Tick_Cnt == 0) { foreach (string id in _Data.Hash_Receiver_keys) { // 해쉬테이블에서 폼로드 진행을 변수에 저장 _FireDesk_Receiver FireDesk_Receiver = (_FireDesk_Receiver)_Data.Hash_Receiver[id]; if (_Ethernet.Ping_SyncCheck(FireDesk_Receiver.DATABASE_NAME_IP) == false) // cyim 2015.9.1 1개의 수신기가 접속이 안되더라도 나머지는 접속시도할수 있도록 수정 { FireDesk_Receiver.LoadStart = false; FireDesk_Receiver.mdi.Close(); // 통신이 안되면 종료시켜버린다. } else // 통신이 잘되는 경우 기존에 사용되지 않은 경우 { if (FireDesk_Receiver.LoadStart == false && FormLoadComplete == false) { FormLoadComplete = true; // 하단의 mdi.show 함수에서 딜레이가 심하다. 코드 위치를 변경하면 안된다 FireDesk_Receiver.LoadStart = true; FireDesk_Receiver.mdi.Show(); // 실제로 수신기 메인폼을 올리는 주체는 여기다 } } } } } // 알람 상태 표시 bool timer_500_toggle = false; // 500 ms 타이머 private void timer_500_Tick(object sende, EventArgs e) { // 초기화 팝업창때는 실행안됨 if (waitingForm_FireDesk != null && waitingForm_FireDesk.Visible == true) return; // 토글용 timer_500_toggle = !timer_500_toggle; // // 전체현황 카운터 표시 // fireCount = 0; facilityCount = 0; errorCount = 0; blockingCount = 0; cutCnt = 0; fireCount_Accumulation = 0; PreFireList = new ArrayList(); foreach (string id in _Data.Hash_Receiver_keys) { _FireDesk_Receiver FireDesk_Receiver = (_FireDesk_Receiver)_Data.Hash_Receiver[id]; // cyim 2015.9.1 1개의 수신기가 접속이 안되더라도 나머지는 접속시도할수 있도록 수정 if (FireDesk_Receiver.mdi != null) { // 화재 fireCount = fireCount + FireDesk_Receiver.mdi.fireCount; // 설비 facilityCount = facilityCount + FireDesk_Receiver.mdi.facilityCount; // 통신 errorCount = errorCount + FireDesk_Receiver.mdi.errorCount; // 단선 blockingCount = blockingCount + FireDesk_Receiver.mdi.blockingCount; // 차단 cutCnt = cutCnt + FireDesk_Receiver.mdi.CutCnt; // 축적화재 fireCount_Accumulation = fireCount_Accumulation + FireDesk_Receiver.mdi.fireCount_Accumulation; // 아날로그감지기의 PreFire foreach (string data in FireDesk_Receiver.mdi.PreFireList) PreFireList.Add(data); } } // 전체 현황의 경우 카운터가 0이상이면 깜빡거리게 만든다 Toggle_ControlForeColor(this.label_CurrentStatus_Fire, fireCount, string.Format("화재({0})", fireCount)); Toggle_ControlForeColor(this.label_CurrentStatus_Facility, facilityCount, string.Format("설비({0})", facilityCount)); Toggle_ControlForeColor(this.label_CurrentStatus_Error, errorCount, string.Format("통신({0})", errorCount)); Toggle_ControlForeColor(this.label_CurrentStatus_Blocking, blockingCount, string.Format("단선({0})", blockingCount)); Toggle_ControlForeColor(this.label_CurrentStatus_Cut, cutCnt, string.Format("차단({0})", cutCnt)); // // 점검 표시 // foreach (string id in _Data.Hash_Receiver_keys) { _FireDesk_Receiver FireDesk_Receiver = (_FireDesk_Receiver)_Data.Hash_Receiver[id]; Button btn = (Button)Util.FineControl(panel_Middle, "button_Check" + id.ToString()); // cyim 2015.9.1 1개의 수신기가 접속이 안되더라도 나머지는 접속시도할수 있도록 수정 if (FireDesk_Receiver.mdi != null) { // 점검 if (FireDesk_Receiver.mdi.CheckBtn_Current_Status == true || FireDesk_Receiver.mdi.lblEmergencyBoardStatus_Visible == true // 비상방송연결이상 || FireDesk_Receiver.mdi.socketUI.myCntLabel.Visible == true) // 통신데몬연결이상 { Toggle_ControlBackColor(btn, 1, null); } else Toggle_ControlBackColor(btn, 0, null); } } // cyim 2015.9.15 수신반 하단 이벤트 표시 : 화재 및 설비 표시 FireFacilityEventCheck(); // cyim 2016.06.15 : 화재 음원 출력 if (SoundPlayer_AlarmPopupSound_Count > 6) { SoundPlayer_AlarmPopupSound_Count = 0; // 3초마다 AlarmPopup_PlaySound_Check(); } else { SoundPlayer_AlarmPopupSound_Count++; } } // cyim 2016.06.15 : 화재 음원 출력 public void AlarmPopup_PlaySound_Check() { if (SoundPlayer_AlarmPopupSound != null) // cyim 2016.11.11 : 비상 음원 출력 음원 파일 없을때 대응 코드 추가 { if (this.label_FireAlert.Visible == true || this.label_FacilityAlert.Visible == true) // cyim 2016.06.16 : 설비동작 발생시 음원 출력 포함 SoundPlayer_AlarmPopupSound.Play(); else SoundPlayer_AlarmPopupSound.Stop(); } } // 글자색을 토글 private void Toggle_ControlForeColor(Label label, int count, string text) { if (count > 0) { if (timer_500_toggle == true) label.ForeColor = Color.White; else label.ForeColor = Color.Red; } else { if (label.ForeColor != Color.White) label.ForeColor = Color.White; } if (text != null) label.Text = text; } // 배경색을 토글 private void Toggle_ControlBackColor(Control ctrl, int count, string text) { if (count > 0) { if (timer_500_toggle == true) ctrl.BackColor = Color.Transparent; else ctrl.BackColor = Color.Red; } else { if (ctrl.BackColor != Color.Transparent) ctrl.BackColor = Color.Transparent; } if (text != null) ctrl.Text = text; } // // cyim 2015.9.15 수신반 하단 이벤트 표시 : 화재 및 설비 표시루틴을 그대로 이용하도록 한다 MdiParent.cs 와 동일함 // public void FireFacilityEventCheck() { { // // 화재 // if (this.fireCount > 0) { this.label_FireAlert.Visible = true; //this.labelFireAlert.Image = null;//sdkim, 20120129, [MTS-47] this.label_FireAlert_inform_1th.Visible = true; this.txtFirstFireWarnningMessage.Visible = true; if (this.fireCount > 1) { this.label_FireAlert_inform_2th.Visible = true; this.cboSecondFireWarnningMessage.Visible = true; } else { this.label_FireAlert_inform_2th.Visible = false; this.cboSecondFireWarnningMessage.Visible = false; } if (timer_500_toggle == false) { this.label_FireAlert.BackColor = Color.Red; this.label_FireAlert.ForeColor = Color.Black; } else { this.label_FireAlert.BackColor = Color.Transparent; this.label_FireAlert.ForeColor = Color.Red; } } // cyim 2014.7.10 : 축적화재 표시 : KFI 요청사항 else if (this.fireCount_Accumulation > 0) { // 상위 화재와 동일한 코드이다. 굳이 상위와 합치지 않은 이유는 우선순위는 무조건 일반 화재가 높기 때문이다. (위험도 고려) this.label_FireAlert.Visible = true; //this.labelFireAlert.Image = null;//sdkim, 20120129, [MTS-47] this.label_FireAlert_inform_1th.Visible = true; this.txtFirstFireWarnningMessage.Visible = true; if (this.fireCount_Accumulation > 1) { this.label_FireAlert_inform_2th.Visible = true; this.cboSecondFireWarnningMessage.Visible = true; } else { this.label_FireAlert_inform_2th.Visible = false; this.cboSecondFireWarnningMessage.Visible = false; } if (timer_500_toggle == false) { this.label_FireAlert.BackColor = Color.Red; this.label_FireAlert.ForeColor = Color.Black; } else { this.label_FireAlert.BackColor = Color.Transparent; this.label_FireAlert.ForeColor = Color.Red; } } else { this.label_FireAlert.Visible = false; this.txtFirstFireWarnningMessage.Visible = false; this.label_FireAlert_inform_1th.Visible = false; this.cboSecondFireWarnningMessage.Visible = false; this.cboSecondFireWarnningMessage.Items.Clear(); this.label_FireAlert_inform_2th.Visible = false; } // // cyim 2015.7.9 PreFire 표시 문제 : 아날로그 감지기는 PreFire 단계가 있다 // if (this.PreFireList.Count > 0) { this.labelPreFireAlert.Visible = true; this.cboPreFireWarnningMessage.Visible = true; if (timer_500_toggle == false) { this.labelPreFireAlert.BackColor = Color.Red; this.labelPreFireAlert.ForeColor = Color.Black; } else { this.labelPreFireAlert.BackColor = Color.Transparent; this.labelPreFireAlert.ForeColor = Color.Red; } } else { this.labelPreFireAlert.Visible = false; this.cboPreFireWarnningMessage.Visible = false; this.cboPreFireWarnningMessage.Items.Clear(); } // // 설비 // if (this.facilityCount > 0) { this.label_FacilityAlert.Visible = true; //this.labelFacilityAlert.Image = null;//sdkim, 20120129, [MTS-47] this.cboWriteWarningMessage.Visible = true; this.label_FacilityAlert_inform_1th.Visible = true; if (timer_500_toggle == false) { this.label_FacilityAlert.BackColor = Color.Blue; this.label_FacilityAlert.ForeColor = Color.White; } else { this.label_FacilityAlert.BackColor = Color.Transparent; this.label_FacilityAlert.ForeColor = Color.LightSkyBlue; } } else { this.label_FacilityAlert.Visible = false; this.cboWriteWarningMessage.Visible = false; this.cboWriteWarningMessage.Items.Clear(); this.label_FacilityAlert_inform_1th.Visible = false; } LEDCount = LEDList.Count; if (this.LEDCount > 0) { this.lblLEDText.Text = LEDList[LEDCount - 1].ToString(); this.lblLEDText.Visible = true; //this.labelFacilityAlert.Image = null;//sdkim, 20120129, [MTS-47] if (timer_500_toggle == false) { this.lblLEDText.BackColor = Color.LightPink; this.lblLEDText.ForeColor = Color.White; } else { this.lblLEDText.BackColor = Color.Transparent; this.lblLEDText.ForeColor = Color.LightPink; } } else { this.lblLEDText.Visible = false; } } } // // cyim 2015.9.15 수신반 하단 이벤트 표시 // 현재 접속되어있는 데몬을 기준으로 화재 정보를 처리한다 // 화재,축적,아날로그 Prefire,설비 의 경우 이벤트가 발생하면 아래의 함수에서 글자를 셋팅한다 // public void FireEventProcess() { // 일반화재 int iFireEventCount = FireList.Count; // 축적화재 int iFireEventCount_Accumulation = FireList_Accumulation.Count; try { if (this.cboSecondFireWarnningMessage.InvokeRequired) { dCommandFuctionCallEvent d = new dCommandFuctionCallEvent(FireEventProcess); this.cboSecondFireWarnningMessage.Invoke(d, new object[] { }); } else { this.Focus(); // cyim 2014.5.15 : OutofRangeException this.cboSecondFireWarnningMessage.Items.Clear(); this.cboSecondFireWarnningMessage.Text = ""; if (iFireEventCount > 0) { // 2보 정리 for (int iLoop = 1; iLoop < iFireEventCount; iLoop++) this.cboSecondFireWarnningMessage.Items.Add(FireList[iLoop].ToString()); if (this.cboSecondFireWarnningMessage.Items.Count > 0) this.cboSecondFireWarnningMessage.Text = this.cboSecondFireWarnningMessage.Items[0].ToString(); // 1보 정리 this.txtFirstFireWarnningMessage.Text = FireList[0].ToString(); // 화재 타입 this.label_FireAlert.Text = "화재발생"; } // cyim 2014.7.10 : 축적화재 표시 : KFI 요청사항 else if (iFireEventCount_Accumulation > 0) { // 2보 정리 for (int iLoop = 1; iLoop < iFireEventCount_Accumulation; iLoop++) this.cboSecondFireWarnningMessage.Items.Add(FireList_Accumulation[iLoop].ToString()); if (this.cboSecondFireWarnningMessage.Items.Count > 0) this.cboSecondFireWarnningMessage.Text = this.cboSecondFireWarnningMessage.Items[0].ToString(); // 1보 정리 this.txtFirstFireWarnningMessage.Text = FireList_Accumulation[0].ToString(); // 화재 타입 this.label_FireAlert.Text = "화재축적상태 발생"; } } } catch (Exception ex) { Util.UErrorMessage(ex, 0, 0); } } public delegate void dCommandFuctionCallEvent_PreFireEventProcess(); public void PreFireEventProcess() { // PreFire int iPreFireListCount = PreFireList.Count; if (this.cboPreFireWarnningMessage.InvokeRequired) { dCommandFuctionCallEvent_PreFireEventProcess d = new dCommandFuctionCallEvent_PreFireEventProcess(PreFireEventProcess); this.cboPreFireWarnningMessage.Invoke(d, new object[] { }); } else { this.Focus(); // OutofRangeException 문제 수정 this.cboPreFireWarnningMessage.Items.Clear(); this.cboPreFireWarnningMessage.Text = ""; if (PreFireList.Count > 0) { for (int i = 0; i < iPreFireListCount; i++) this.cboPreFireWarnningMessage.Items.Add(PreFireList[i].ToString()); this.cboPreFireWarnningMessage.Text = PreFireList[0].ToString(); } } } public delegate void dCommandFuctionCallEvent(); public void EquipEventProcess() { int iEquipEventCount = EquipList.Count; try { if (this.cboWriteWarningMessage.InvokeRequired) { dCommandFuctionCallEvent d = new dCommandFuctionCallEvent(EquipEventProcess); this.cboWriteWarningMessage.Invoke(d, new object[] { }); } else { this.Focus(); // cyim 2014.5.15 : OutofRangeException this.cboWriteWarningMessage.Items.Clear(); this.cboWriteWarningMessage.Text = ""; if (iEquipEventCount > 0) { for (int iLoop = 0; iLoop < iEquipEventCount; iLoop++) { this.cboWriteWarningMessage.Items.Add(EquipList[iLoop].ToString()); } if (this.cboWriteWarningMessage.Items.Count > 0) { this.cboWriteWarningMessage.Text = this.cboWriteWarningMessage.Items[0].ToString(); } } } } catch (Exception ex) { Util.UErrorMessage(ex, 0, 0); } } // // 이벤트 // // 외부에서 화면을 변경하는 경우 private void _Event_FireDesk_Update_SendMessage_Event(int id, string cmd, string type, int data) { // 카운터 업데이트 if (cmd == "Count") { // 화재 if (type == "FireDetect") { Button btn = (Button)Util.FineControl(panel_Middle, "button_FireDetect" + id.ToString()); btn.Text = string.Format("화재 : {0:0000}", data); if (data > 9999) btn.Text = String.Format("화재 : {0:00000}", data); else btn.Text = String.Format("화재 : {0:0000}", data); } // 설비 else if (type == "DeviceInput") { Button btn = (Button)Util.FineControl(panel_Middle, "button_DeviceInput" + id.ToString()); btn.Text = string.Format("설비 : {0:0000}", data); if (data > 9999) btn.Text = String.Format("설비 : {0:00000}", data); else btn.Text = String.Format("설비 : {0:0000}", data); } // 통신 else if (type == "RepeaterError") { Button btn = (Button)Util.FineControl(panel_Middle, "button_RepeaterError" + id.ToString()); btn.Text = string.Format("통신 : {0:0000}", data); if (data > 9999) btn.Text = String.Format("통신 : {0:00000}", data); else btn.Text = String.Format("통신 : {0:0000}", data); } // 단선 else if (type == "DeviceCut") { Button btn = (Button)Util.FineControl(panel_Middle, "button_DeviceCut" + id.ToString()); btn.Text = string.Format("단선 : {0:0000}", data); if (data > 9999) btn.Text = String.Format("단선 : {0:00000}", data); else btn.Text = String.Format("단선 : {0:0000}", data); } // 차단 else if (type == "DeviceNotuse") { Button btn = (Button)Util.FineControl(panel_Middle, "button_DeviceNotuse" + id.ToString()); btn.Text = string.Format("차단 : {0:0000}", data); if (data > 9999) btn.Text = String.Format("차단 : {0:00000}", data); else btn.Text = String.Format("차단 : {0:0000}", data); } } // 폼을 로드 else if (cmd == "FormLoad") { // 완료 if (type == "MDIParentComplete") { FormLoadComplete = false; LoadMdiparentFormList.Remove(id.ToString()); } } // 팝업창을 로드 else if (cmd == "Popup") { ShowWaitingMsgForm(string.Format("수신기 [{0}]:",id) + type, data); } // cyim 2015.9.15 : 일반화재,축적화재,PreFire,설비,복구 의 경우 이벤트로 처리 (참고로 카운터 표시는 주기적으로 함) else if (cmd == "EventProcess") { if (type == "Fire") // 일반화재, 축적화재 { FireList.Clear(); FireList_Accumulation.Clear(); foreach (string ID in _Data.Hash_Receiver_keys) { _FireDesk_Receiver FireDesk_Receiver = (_FireDesk_Receiver)_Data.Hash_Receiver[ID]; foreach (string item in FireDesk_Receiver.mdi.FireList) FireList.Add(item); foreach (string item in FireDesk_Receiver.mdi.FireList_Accumulation) FireList_Accumulation.Add(item); } FireEventProcess(); } else if (type == "PreFire") // PreFire { PreFireList.Clear(); foreach (string ID in _Data.Hash_Receiver_keys) { _FireDesk_Receiver FireDesk_Receiver = (_FireDesk_Receiver)_Data.Hash_Receiver[ID]; foreach (string item in FireDesk_Receiver.mdi.PreFireList) PreFireList.Add(item); } PreFireEventProcess(); } else if (type == "Equip") // 설비 { EquipList.Clear(); foreach (string ID in _Data.Hash_Receiver_keys) { _FireDesk_Receiver FireDesk_Receiver = (_FireDesk_Receiver)_Data.Hash_Receiver[ID]; foreach (string item in FireDesk_Receiver.mdi.EquipList) EquipList.Add(item); } EquipEventProcess(); } else if (type == "Reset") // 복구 { FireList.Clear(); FireList_Accumulation.Clear(); PreFireList.Clear(); EquipList.Clear(); // 복구할 때는 현재 복구하는 수신기만 제외하고 다시 불러 읽어들인다 foreach (string ID in _Data.Hash_Receiver_keys) { if (id.ToString() != ID) { _FireDesk_Receiver FireDesk_Receiver = (_FireDesk_Receiver)_Data.Hash_Receiver[ID]; foreach (string item in FireDesk_Receiver.mdi.FireList) FireList.Add(item); foreach (string item in FireDesk_Receiver.mdi.FireList_Accumulation) FireList_Accumulation.Add(item); foreach (string item in FireDesk_Receiver.mdi.PreFireList) PreFireList.Add(item); foreach (string item in FireDesk_Receiver.mdi.EquipList) EquipList.Add(item); } } FireEventProcess(); PreFireEventProcess(); EquipEventProcess(); } } } // 수신기 버튼 private void button_Receiver_Click(object sender, EventArgs e) { Button btn = (Button)sender; string id = btn.Tag.ToString(); _FireDesk_Receiver FireDesk_Receiver = (_FireDesk_Receiver)_Data.Hash_Receiver[id]; FireDesk_Receiver.mdi.Visible = true; } // 수신기 복구 버튼 private void button_Recover_Click(object sender, EventArgs e) { if (MessageBox.Show("수신기에 복구 명령을 수행하시겠습니까?", Application.ProductName, MessageBoxButtons.YesNo) == DialogResult.Yes) { Button btn = (Button)sender; string id = btn.Tag.ToString(); _FireDesk_Receiver FireDesk_Receiver = (_FireDesk_Receiver)_Data.Hash_Receiver[id]; FireDesk_Receiver.mdi.Visible = true; // cyim 2015.8.18 수신기복구 기능 추가 // 해당 수신기의 화면으로 자동으로 들어가서 수신기 복구 팝업창을 확인하고 나올수 있도록 수정한다 FireDesk_Receiver.mdi.FireReset_Process(); FireDesk_Receiver.mdi.socketUI.ReceiverDemonReset(); } } // 수신기 점검 버튼 // 주음향정지 private void button_MainSoundStop_Click(object sender, EventArgs e) { if (MessageBox.Show("모든 수신기에 주음향정지 명령을 수행하시겠습니까?", Application.ProductName, MessageBoxButtons.YesNo) == DialogResult.Yes) { foreach (string id in _Data.Hash_Receiver_keys) { _FireDesk_Receiver FireDesk_Receiver = (_FireDesk_Receiver)_Data.Hash_Receiver[id]; FireDesk_Receiver.mdi.ShowControlWrite(true); // cyim 2015.8.18 주경종정지 기능 추가 } } } // 연동상태조회 private void button_SearchControl_Click(object sender, EventArgs e) { if (_Data.FireDesk_Operation_Enable == false) // cyim 2015.8.3 수신반 연동기능 추가 { FireDesk_Operation Operation = new FireDesk_Operation(); Operation.Show(); } } // 과거내역통합조회 private void button_SearchHistory_Click(object sender, EventArgs e) { if (_Data.FireDesk_FormLogView_Enable == false) { FireDesk_FormLogView FormLogView = new FireDesk_FormLogView(this); FormLogView.Show(); } } // // cyim 2015.9.11 : 과거내역 통합조회창에서 사용할 DB 에서 미리 읽은값을 사용하도록 수정함 // DB 에서 보드, 중계기, 디바이스 정보를 가져온다 // // 보드 //DataTable dtBoardList = null; public void GetBoardDB() { DacBoardConfig dacBoardConfig = new DacBoardConfig(0); // cyim 2015.7.30 데이타베이스 접속 루틴 변경 _Data.dtBoardList = dacBoardConfig.SelectBoard(0); } // 중계기 //DataTable dtRepeaterList2 = null; public void GetRepeaterDB() { DacRepeaterConfig dacRepeaterConfig = new DacRepeaterConfig(0); // cyim 2015.7.30 데이타베이스 접속 루틴 변경 _Data.dtRepeaterList2 = dacRepeaterConfig.SelectRepeater2(0); } // 아날로그감지기 레벨 //DataTable dtAnalogDetecterLevel = null; public void GetAnalogDetecterLevelDB() { DacRepeaterConfig dacRepeaterConfig = new DacRepeaterConfig(0); // cyim 2015.7.30 데이타베이스 접속 루틴 변경 _Data.dtAnalogDetecterLevel = dacRepeaterConfig.SelectRepeater_AnalogDetecterLevel(0); } // 디바이스 //DataTable dtDeviceDBList2 = null; public void GetDeviceDB() { DacDeviceConfig dacDeviceConfig = new DacDeviceConfig(0); // cyim 2015.7.30 데이타베이스 접속 루틴 변경 _Data.dtDeviceDBList2 = dacDeviceConfig.SelectDevice2(0); } // cyim 2015.7.1 속도개선작업 // 데이타베이스 파일을 미리 읽도록 하되, DataTable 에 한해서 Foreach -> Select 으로 대체 // DataTable 에서 정보를 가져온다 // 중계기 이름을 얻어온다. public string GetDeviceName(int BOARD_ID, int LOOP_NO, int REPEATER_ID) { string ret = ""; if (_Data.dtRepeaterList2 != null) { // cyim 2015.7.1 속도개선작업 DataRow[] result = _Data.dtRepeaterList2.Select( string.Format("BOARD_ID={0} AND LOOP_NO={1} AND REPEATER_ID={2}", BOARD_ID, LOOP_NO, REPEATER_ID)); if (result != null && result.Length > 0) ret = result[0]["REPEATER_NAME"].ToString(); } return ret; } // 보드명을 가져온다 public string GetDeviceName(int BOARD_ID, int CommID) { string ret = ""; if (_Data.dtBoardList != null) { // cyim 2015.7.1 속도개선작업 DataRow[] result = _Data.dtBoardList.Select( string.Format("BOARD_ID={0} AND COMM_ID={1}", BOARD_ID, CommID)); if (result != null && result.Length > 0) ret = result[0]["BOARD_NAME"].ToString(); } return ret; } // 회로명을 가져온다 public string GetDeviceName(int BOARD_ID, int LOOP_NO, int REPEATER_ID, int DEVICE_ID, String INOUT_TYPE) { string ret = ""; if (_Data.dtDeviceDBList2 != null) { // cyim 2015.7.1 속도개선작업 DataRow[] result = _Data.dtDeviceDBList2.Select( string.Format("BOARD_ID={0} AND COMM_ID={1} AND LOOP_NO={2} AND REPEATER_ID={3} AND DEVICE_ID={4} AND INOUT_TYPE='{5}'", // cyim 2015.7.8 쿼리수정 , Inout 타입의 경우 ' ' 작은따옴표를 사용해야함, 이벤트로그가 안보이게됨 BOARD_ID, 1, LOOP_NO, REPEATER_ID, DEVICE_ID, INOUT_TYPE)); if (result != null && result.Length > 0) ret = result[0]["DEVICE_NAME"].ToString(); } return ret; } // 조건에 맞는 중계기의 위치명 / 위치 코드 / 중계기 명칭을 리턴한다. public string GetDevicePositionName(int BOARD_ID, int LOOP_NO, int REPEATER_ID) { string ret = ""; if (_Data.dtRepeaterList2 != null) { // cyim 2015.7.1 속도개선작업 DataRow[] result = _Data.dtRepeaterList2.Select( string.Format("BOARD_ID={0} AND LOOP_NO={2} AND REPEATER_ID={3}", BOARD_ID, 1, LOOP_NO, REPEATER_ID)); if (result != null && result.Length > 0) { // 만약 위치 명이 있으면, 위치명으로 리턴한다. if (result[0]["POSITION_NAME"].ToString() != "") ret = result[0]["POSITION_NAME"].ToString(); // 위치명이 없고.. 위치 코드가 있으면, 위치 코드를 리턴하도록 한다. else if (result[0]["POSITION_CODE"].ToString() != "") ret = result[0]["POSITION_CODE"].ToString(); // 기본값 RepeaterName을 리턴할 준비를 한다. else ret = result[0]["REPEATER_NAME"].ToString(); } } return ret; } // 디바이스 위치를 리턴한다. 만약 맞는 위치명이 없으면.. 위치 코드라도 리턴한다. public string GetDevicePositionName(int BOARD_ID, int LOOP_NO, int REPEATER_ID, int DEVICE_ID, String INOUT_TYPE) { string ret = ""; if (_Data.dtDeviceDBList2 != null) { // cyim 2015.7.1 속도개선작업 string SQL = string.Format("BOARD_ID={0} AND COMM_ID={1} AND LOOP_NO={2} AND REPEATER_ID={3} AND DEVICE_ID={4} AND INOUT_TYPE='{5}'", // cyim 2015.7.8 쿼리수정 , Inout 타입의 경우 ' ' 작은따옴표를 사용해야함, 이벤트로그가 안보이게됨 BOARD_ID, 1, LOOP_NO, REPEATER_ID, DEVICE_ID, INOUT_TYPE); DataRow[] result = _Data.dtDeviceDBList2.Select(SQL); if (result != null && result.Length > 0) { // 만약 위치 명이 있으면, 위치명으로 리턴한다. if (result[0]["POSITION_NAME"].ToString() != "") ret = result[0]["POSITION_NAME"].ToString(); // 위치명이 없고.. 위치 코드가 있으면, 위치 코드를 리턴하도록 한다. else if (result[0]["POSITION_CODE"].ToString() != "") ret = result[0]["POSITION_CODE"].ToString(); // 기본값 Device Name을 리턴할 준비를 한다. else ret = result[0]["DEVICE_NAME"].ToString(); } } return ret; } // cyim 2015.7.1 속도개선작업 // 해쉬테이블을 사용해서 아날로그 감지기를 미리 저장해두어야 한다 // 아날로그감지기 아이디를 모두 가져온다 (아이디로 구성된 키를 가지고, 데이터는 레벨값 FAULT_VALUE;PREFIRE_VALUE;FIRED_VALUE;FIREN_VALUE) public Hashtable GetAnalogDetecterRepeaterID(int RECEIVER_ID, int BOARD_ID, int LOOP_NO) { Hashtable ret = new Hashtable(); try { if (_Data.dtAnalogDetecterLevel != null) { DataRow[] result = _Data.dtAnalogDetecterLevel.Select( string.Format("RECEIVER_ID={0} AND BOARD_ID={1} AND LOOP_NO={2}", RECEIVER_ID, BOARD_ID, LOOP_NO)); if (result.Length > 0) { foreach (DataRow Data in result) { string key = Data["REPEATER_ID"].ToString(); AnalogLevel data = new AnalogLevel( Int32.Parse(Data["FAULT_VALUE"].ToString()), Int32.Parse(Data["PREFIRE_VALUE"].ToString()), Int32.Parse(Data["FIRED_VALUE"].ToString()), Int32.Parse(Data["FIREN_VALUE"].ToString())); ret.Add(key, data); } } } } catch (Exception ex) { Util.UErrorMessage(ex, 0, 0); } return ret; } // cyim 2016.01.07 아날로그 감지기 이력 조회시 표시 수정 : 중계기 타입을 조회할수 있도록 한다 public string GetRepeaterType(int BOARD_ID, int LOOP_NO, int REPEATER_ID) { string ret = ""; if (_Data.dtRepeaterList2 != null) { // cyim 2015.7.1 속도개선작업 DataRow[] result = _Data.dtRepeaterList2.Select( string.Format("BOARD_ID={0} AND LOOP_NO={2} AND REPEATER_ID={3}", BOARD_ID, 1, LOOP_NO, REPEATER_ID)); if (result != null && result.Length > 0) { ret = result[0]["REPEATER_TYPE"].ToString(); } } return ret; } } // // 수신반 전용 클래스 // 이 클래스는 범용으로 수신반에서 다른 수신기간의 데이터를 쉽게 공유할수 있게 만든 클래스이다. // 실제로 사용하는 데이터만 추가하도록 한다 // 자세한 정보는 결국 직접 접속해서 볼수 있는 화면으로 구성한다 public class _FireDesk_Receiver { // 수신기 기본정보 public string RECEIVER_ID = "1"; public string MASTER_FLAG = "N"; public string PROJECT_DIRECTORY; public string DATABASE_NAME; // IP + PATH public string DATABASE_NAME_IP; // PATH public string DATABASE_NAME_PATH; // PATH // 카운터 정보 public int FireDetect = 0; // 화재 public int DeviceInput = 0; // 설비 public int RepeaterError = 0; // 통신 public int DeviceCut = 0; // 단선 public int DeviceNotuse = 0; // 차단 // 클래스 정보 public bool LoadStart = false; public MDIParent mdi = null; } }