+// 수신기와 마찬가지로 레지스트리를 읽어서 현재 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 클래스 정리
+ // 데이타베이스 파일을 미리 읽도록 하되, 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 타입의 경우 ' ' 작은따옴표를 사용해야함, 이벤트로그가 안보이게됨
+ 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 타입의 경우 ' ' 작은따옴표를 사용해야함, 이벤트로그가 안보이게됨
+ public DataTable SelectLastLog(int receviceID, int commID, int boardID, int loopNO, int repeaterID, int deviceID, string inoutType, string eventtype)
+ {
+ DataTable dt = null;
+ try
+ {
+ String SQL = "";
+ SQL += "SELECT FIRST 1 EVENT_ID,EVENT_TIME,EVENT_TYPE,RECEIVER_ID,COMM_ID,BOARD_ID,LOOP_NO,REPEATER_ID,DEVICE_ID,INOUT_TYPE,DATA_VALUE,EVENT_REMARK,SEND_FLAG";
+ SQL += " FROM TB_EVENT_LOG";
+ SQL += " WHERE EVENT_TYPE = '{0}' AND RECEIVER_ID = {1} AND COMM_ID = {2} AND BOARD_ID = {3} AND LOOP_NO = {4} AND REPEATER_ID = {5} AND DEVICE_ID = {6} AND INOUT_TYPE = '{7}'";
+ public void AddEventLogData(string EVENT_ID, string EVENT_TIME, string EVENT_TYPE, int RECEIVER_ID, int COMM_ID, int BOARD_ID, int LOOP_NO, int REPEATER_ID, int DEVICE_ID, string INOUT_TYPE, int DATA_VALUE, string EVENT_REMARK, string SEND_FLAG)
+ public void frmRepeaterGroup_FormClosing(object sender, FormClosingEventArgs e)
+ {
+ // cyim 2015.7.6 레벨값 갱신 이벤트 추가 : 해제
+ mdi.Event.AnalogLevel_Update_SendMessage_Event -= new _Event.AnalogLevel_Update_SendMessage_Handler(_Event_AnalogLevel_Update_SendMessage_Event); // cyim 2015.8.4 수신반을 위한 static 클래스 정리
+ mdi.Event.AnalogLevel_Update_SendMessage_Event += new _Event.AnalogLevel_Update_SendMessage_Handler(_Event_AnalogLevel_Update_SendMessage_Event); // cyim 2015.8.4 수신반을 위한 static 클래스 정리
+
+ // cyim 2015.7.23 NACK 응답이 최대 7.2초가 딜레이됨, 단 기본값은 4초
+ for (int i = 0; i < repinfo.Length; i++)//2010.11.22, k.s.d , #127 repeater information don't display bug fix. , for (int i = 0; i < repinfo.Length - 1;i++ )
+ SQL += " LEFT OUTER JOIN TB_DEVICE_TYPE B ON A.DEVICE_TYPE = B.DEVICE_TYPE";
+ SQL += " LEFT OUTER JOIN TB_POSITION_CODE C ON A.POSITION_CODE = C.POSITION_CODE";
+ SQL += String.Format(" WHERE A.RECEIVER_ID = {0} AND A.COMM_ID = 3 ", RECEIVER_ID);
+ if (BOARD_ID > 0) SQL += String.Format(" AND A.BOARD_ID = {0}", BOARD_ID);
+ SQL += " AND A.LOOP_NO = 0 AND A.REPEATER_ID = 0 ";
+ if (DEVICE_ID > 0) SQL += String.Format(" AND A.DEVICE_ID = {0}", DEVICE_ID);
+ if (INOUT_TYPE != null) SQL += String.Format(" AND A.INOUT_TYPE = '{0}'", INOUT_TYPE);
+ if (SEARCH_KEY != null) SQL += String.Format(" AND (A.DEVICE_NAME LIKE '%{0}%' OR B.DEVICE_TYPE_NAME LIKE '%{0}%' OR C.POSITION_NAME LIKE '%{0}%')", SEARCH_KEY);
+ SQL += " ORDER BY A.BOARD_ID,A.LOOP_NO,A.REPEATER_ID,A.INOUT_TYPE,A.DEVICE_ID";
+
+ DataSet dao = Select(SQL);
+
+ dt = dao.Tables[0];
+
+
+ }
+ catch (Exception ex)
+ {
+ Util.UErrorMessage(ex, 0, 0);
+ throw ex;
+ }
+
+
+ return dt;
+
+ }
+
+
+ //입출력 회로 타입명 조회
+ public String Device_Type_Name(String SYMBOL_TYPE, String DEVICE_TYPE)
+ {// say hell to io board , read io board status ,read io board data
+ public byte head;
+ public byte RPT_loop;
+ public byte BD_ID;
+ public byte length;
+ public byte cmd;
+ public byte IVK_ID;
+ public byte RCVR_ID;
+ public byte cs;
+ }
+
+ [StructLayout(LayoutKind.Sequential, Pack = 1)]
+ public struct PRTIO_Type2
+ {// none
+ public byte head;
+ public byte RPT_loop;
+ public byte BD_ID;
+ public byte length;
+ public byte cmd;
+ public byte IVK_ID;
+ public byte RCVR_ID;
+ public byte Option1;
+ public byte cs;
+ }
+
+ [StructLayout(LayoutKind.Sequential, Pack = 1)]
+ public struct PRTIO_Type3
+ {// write io board status , write io board data
+ public byte head;
+ public byte RPT_loop;
+ public byte BD_ID;
+ public byte length;
+ public byte cmd;
+ public byte IVK_ID;
+ public byte RCVR_ID;
+ public byte Option1;
+ public byte Option2;
+ public byte cs;
+ }
+
+ [StructLayout(LayoutKind.Sequential, Pack = 1)]
+ public struct PRTDemon_Type1
+ {// write io board status , write io board data
+ public byte head;
+ public byte RPT_loop;
+ public byte BD_ID;
+ public byte length;
+ public byte cmd;
+ public byte IVK_ID;
+ public byte RCVR_ID;
+ public byte cs;
+ }
+
+
+ [StructLayout(LayoutKind.Sequential, Pack = 1)]
+ public struct PRTReceiver_Type1
+ {// say hell to board , read board status
+ public byte head;
+ public byte RPT_loop;
+ public byte TBD_ID;
+ public byte length;
+ public byte cmd;
+ public byte IVK_ID;
+ public byte RCVR_ID;
+ public byte cs;
+ }
+
+ [StructLayout(LayoutKind.Sequential, Pack = 1)]
+ public struct PRTReceiver_Type2
+ {// resetrepeaterunit
+ public byte head;
+ public byte RPT_loop;
+ public byte TBD_ID;
+ public byte length;
+ public byte cmd;
+ public byte IVK_ID;
+ public byte RCVR_ID;
+ public byte Option1;
+ public byte cs;
+ }
+
+ [StructLayout(LayoutKind.Sequential, Pack = 1)]
+ public struct PRTReceiver_Type3
+ {//search repeater all, read repeaterpoint all, write repeater output unit ,read repeater info all, read repeater info unit, reset repeater all , write repeater input unit
+ public byte head;
+ public byte RPT_loop;
+ public byte TBD_ID;
+ public byte length;
+ public byte cmd;
+ public byte IVK_ID;
+ public byte RCVR_ID;
+ public byte Option1;
+ public byte Option2;
+ public byte cs;
+ }
+
+ [StructLayout(LayoutKind.Sequential, Pack = 1)]
+ public struct PRTReceiver_Type4
+ {// none
+ public byte head;
+ public byte RPT_loop;
+ public byte TBD_ID;
+ public byte length;
+ public byte cmd;
+ public byte IVK_ID;
+ public byte RCVR_ID;
+ public byte Option1;
+ public byte Option2;
+ public byte Option3;
+ public byte cs;
+ }
+
+ [StructLayout(LayoutKind.Sequential, Pack = 1)]
+ public struct PRTReceiver_Type5
+ {//none
+ public byte head;
+ public byte RPT_loop;
+ public byte TBD_ID;
+ public byte length;
+ public byte cmd;
+ public byte IVK_ID;
+ public byte RCVR_ID;
+ public byte Option1;
+ public byte Option2;
+ public byte Option3;
+ public byte Option4;
+ public byte cs;
+ }
+
+ [StructLayout(LayoutKind.Sequential, Pack = 1)]
+ public struct PRTReceiver_Type6
+ {//write board status
+ public byte head;
+ public byte RPT_loop;
+ public byte TBD_ID;
+ public byte length;
+ public byte cmd;
+ public byte IVK_ID;
+ public byte RCVR_ID;
+ public byte Option1;
+ public byte Option2;
+ public byte Option3;
+ public byte Option4;
+ public byte Option5;
+ public byte cs;
+ }
+ //데몬명령-누적카운트및사용자설정 변경
+ [StructLayout(LayoutKind.Sequential, Pack = 1)]
+ public struct PRTReceiver_Type_CommandStatus
+ {//write board status
+ public byte head; //0x02
+ public byte RPT_loop; //ID 하위 바이트 (Loop 번호)
+ public byte TBD_ID; //ID 상위 바이트 (통신보드 ID)
+ public byte length; //0x0D, 전체 Packet 길이
+ public byte cmd; //0x76, Status Command 명령
+ public byte IVK_ID; //Invoke ID
+ public byte RCVR_ID; //수신기 ID
+ public byte RepeaterID; //중계기 ID (1~ 127)
+ public byte Address; //ADDRESS (1 ~ 16) 회로ID
+ public byte InOut; //IN/OUT (I/O) C-comm,L-loop,B-board,R-repeater
+ public byte CommId; //1-front,3-io,4-keypad
+ public byte CommandType1; //Command Type 1 C:카운트읽기
+ public byte CommandType2; //Command Type 2 C:카운트읽기
+ public byte SubType; //SubType : Device Type
+ public byte ApplyRange; //ApplyRange : A-All,C-Comm,B-Board,L-Loop,R-중계기,D-회로,I-입력회로,O-출력회로
+ public byte Status; //Status
+ public byte cs;
+ }
+
+ // 아날로그 감지기 레벨값 쓰기 명령
+ [StructLayout(LayoutKind.Sequential, Pack = 1)]
+ public struct PRTReceiver_Type_AnalogDetecterLevel
+ {
+ public byte head; //0x02
+ public byte RPT_loop; //ID 하위 바이트 (Loop 번호)
+ public byte TBD_ID; //ID 상위 바이트 (통신보드 ID)
+ public byte length; //0x0C, 전체 Packet 길이
+ public byte cmd; //0x78, AnalogDetecterLevel Write 명령
+ public byte IVK_ID; //Invoke ID
+ public byte RCVR_ID; //수신기 ID
+ public byte RepeaterID; //중계기 ID (1~ 127) , 0xFF (BroadCast)
+ public byte Fault;
+ public byte PreFire;
+ public byte FireNight;
+ public byte FireDay;
+ public byte cs;
+ }
+
+ // cyim 2016.10.27 : 대용량 수신기 아날로그 감지기 트랜드 읽기
+ [StructLayout(LayoutKind.Sequential, Pack = 1)]
+ public struct PRTReceiver_Type_AnalogDetecterTrend
+ {
+ public byte head; //0x02
+ public byte RPT_loop; //ID 하위 바이트 (Loop 번호)
+ public byte TBD_ID; //ID 상위 바이트 (통신보드 ID)
+ public byte length; //0x08, 전체 Packet 길이
+ public byte cmd; //0x24, AnalogDetecterTrend Read 명령
+ SQL += " FROM TB_REPEATER R LEFT OUTER JOIN TB_ANALOG_DEVICE_2 P ";
+ SQL += " ON (R.RECEIVER_ID = P.RECEIVER_ID AND R.COMM_ID = P.COMM_ID AND R.BOARD_ID = P.BOARD_ID AND R.LOOP_NO = P.LOOP_NO AND R.REPEATER_ID = P.REPEATER_ID) ";
+ SQL += " WHERE R.RECEIVER_ID = {0} AND R.COMM_ID = 1 ";
+ SQL += " AND R.USE_FLAG = 'Y' AND (R.REPEATER_TYPE = 4 OR R.REPEATER_TYPE = 5)";
+ // cyim 2016.06.15 : 아날로그 감지기 출력 포인트 고려 : 레벨값은 입력포인트만 고려한다
+ // 출력포인트가 있을경우에는 레벨값 조회시 중계기 아이디가 중복되어 버린다
+ SQL += " AND INOUT_TYPE ='I' ";
+ SQL = String.Format(SQL, RECEIVER_ID);
+
+ DataSet dao = Select(SQL);
+ dt = dao.Tables[0];
+ }
+ catch (Exception ex)
+ {
+ Util.UErrorMessage(ex, 0, 0);
+ }
+ }
+ return dt;
+ }
+
+ //중계기저장
+ public void Repeater_Clear(int RECEIVER_ID)
+ {
+ try
+ {
+ //String SQL = "UPDATE TB_REPEATER SET USE_FLAG = 'N' WHERE RECEIVER_ID = {0} AND COMM_ID = 1";
+ //SQL = String.Format(SQL, RECEIVER_ID);
+
+ String SQL = "DELETE FROM TB_DEVICE WHERE RECEIVER_ID = {0} AND COMM_ID = 1";
+ SQL = String.Format(SQL, RECEIVER_ID);
+
+ ExecuteNonQuery(SQL);
+
+ SQL = "DELETE FROM TB_REPEATER WHERE RECEIVER_ID = {0} AND COMM_ID = 1";
+ SQL = String.Format(SQL, RECEIVER_ID);
+
+ ExecuteNonQuery(SQL);
+ }
+ catch (Exception ex)
+ {
+ Util.UErrorMessage(ex, 0, 0);
+ throw ex;
+ }
+ }
+
+ //중계기저장
+ public void Repeater_Update(QUERYMode cmd, int RECEIVER_ID, int BOARD_ID, int LOOP_NO, int REPEATER_ID