퇴근5분전

  이번엔  프로그램을 제작할때 내가 사용하는 방법을 써보려 한다. 

글로 쓰면 얼마나 걸릴지 모르겠지만... 생각하는 데로 대충 끍적거리고 메모장에 요약해놓고 바로 코딩해버리지만... 

이건 비전공자들이 검색하다 우연히 볼까? 라는 생각으로 써보는 것이다. 

 이번 만들던 PLC모니터링 프로그램 구조도다.

알바형태로 하는 플젝이다 보니 문서가 없어 설명들을 듣고 내가 그렸다.

 

목적 ::: 이 프로그램의 목적은 PLC의 네가지 정보( 차단기, 수신, 위험수위, 해제수위 )를 모니터링 하는 것

 

## 주요 객체를 뽑으면 { 다리, PLC } 두개가 있다.  <옵션>에 대한건 제외... 

난 표현을 메모장 아래와 같이 쓰거나 직접 class를 구현한다.

#다리

{

        #[PLC]

        {

                  .차단기

                  .수위

                  .위험수위

                  .해제수위

                  .위치 { L, R }  // 옵션의 별도PLC와 타DB는 위치값을 C로 추가

        }

}

눈에 딱 보이는 것을 추려낸 내용이다

[] 기호는 n개를 표현한것이다.

 

/* 추가적으로 이해에 필요한 내용

     * PLC에 모드버스TCP라는 통신방식을 이용하여 요청하여 메모리값을 16bit(word)값을 응답받을 수 있다. 

     * 차단기, 수위, 위험수위, 해제수위는 각 메모리 주소값이 프로그래밍을 통하여 고정되어 있다.

       여기서 고민해볼 것이 다리는 1개 일까? - 현업과 얘기해보니 n개 였다. 현장마다 관리하는 다리 개수가 다르다. 

       PLC와 통신을 하려면 모드버스TCP라는 방식으로 통신을 하므로 PLC의 IP 정보가 필요하다. port는 502번 고정이다.

*/

 

#[다리]

{

        .다리위치명

        #[PLC]

        {

                  .IP

                  .차단기

                  .수위

                  .위험수위

                  .해제수위

                  .위치 { L, R }  // 옵션의 별도PLC와 타DB는 위치값을 C로 추가

        }

}

모니터링 대상이 여러개의 [다리]로 생각하고 배열 형태로 변경했다

 

실시간 모니터링이니 백그라운드에서 PLC에게 일정 주기마다 요청을 하고 응답을 받아야 한다. 

윈도우 서비스(Windows Service)를 구현해야 한다. 

 

#Service

{

            .OnStart( string[] args ) {

            }

            .OnStop() {

            }

}

윈도우 서비스를 .net으로 구현하면 초기 구현부가 위와 같은 형태로 나온다.

* OnStart, OnStop을 구현하면 되는데... 넘어가고.. 

 

모니터링을 하기 위해선 객체 관계를 생각해 볼 필요가 있다. 

일정 시간마다 PLC에 요청해서 응답을 받아야 한다.

핵심 의사코드를 작성해보면... 

무한 반복 

{

    반복( 다리 in 다리목록 ) {

          다리.PLC.요청( 차단기 ) : 응답

          DB업데이트(응답)

          다리.PLC.요청( 수위 ) : 응답

          DB업데이트(응답)

          다리.PLC.요청( 위험수위 ) : 응답

          DB업데이트(응답)

          다리.PLC.요청( 해제수위 ) : 응답

          DB업데이트(응답)

    }

}

위와 같은게 계속 반복하여 필요한 정보를 계속 요청하고, 응답받은건 DB에 업데이트 해주면 된다.

 

 이 프로그램은 개발 현장에서만 사용하는 것이 아니기에 다리정보, PLC정보를 별도 파일로 빼고

서비스 시작시 읽어서 객체화하여 종료시까지 요청/응답을 반복한다. 

 

환경설정 파일과 연계하기 위해 아래형태로 변경한다.

 

#다리정보

{

            ID : "BRD001"

            다리명 : 어디어디에 있는 다리

            L_ID  : "PLC_L00"

            R_ID  : "PLC_R00"

}

 

// PLC_L00.json, PLC_R00.json 으로 파일을 만들고 아래 형태로 읽고/쓰기를 한다.

#PLC_Device { 

       .ID

       .IP

       .WebTitle

       [모니터링]

       {

                타입 : { 차단기, 수위, 위험수위, 해제수위 }

                PLC_메모리주소 

                FunctionCode // Modbus TCP프로토콜에 함수코드 ( 0x03, 0x04 )

       }      

}

 

! 코드가 아래와 같이 추가 변경된다. 

//반복되기 전에 환경설정된 파일을 읽어서 만든다.

//다리정보 읽기

모니터링[] monitorings ;

반복 ( 다리 in 다리목록 )

{

          // { 다리정보. PLC_L_ID }.json 읽기

          monitorings.목록추가( PLC_L_Device.모니터링  )

          // { 다리정보. PLC_R_ID }.json 읽기

          monitorings.목록추가( PLC_R_Device.모니터링  )

}

 

무한 반복 

{  

    반복( 모니터링 in monitorings ) {

          모니터링.요청( ) : 응답

          DB업데이트(응답) 

    }

}

이런 형태로 바꾼다. 

보통 여기까지의 샘플 코드까지가 대략 반나절정도 걸린다. 좀더 규모가 큰 것들은 하루 이틀 정도?...

 

 이후 부터는

 1. 실제 PLC장비를 연결하고,

 2. 모드버스TCP프로토콜 샘플을 만들기 

     Read Write 샘플 및 테스트

 3. 서비스 프로젝트 생성 후 코드 반영.

 4. 로그 기록

 5. DB연결 및 스키마 생성 및 읽기/쓰기 쿼리문 작성 

 6. 간이 테스트 문서

 7. 상세코드 작성 및 디버깅

 1~7 정도 하면 1~2주 훌쩍 간다.

기존에 했던 작업들이면 1~2일 정도면 된다.

 

위 작업들을 보면 목적 프로그램의 주연들을 찾아내고 정의해서

관계를 설정하고 의사코드로 역할과 호출순서를 정한다. 

기본적으로 객체.할수있는일( 필요한 것들... ) : 결과값 정의해서 누가 뭘 할지 결정하고 

필요한 것들을 붙여나가면서 프로그래밍 하면 좋겠다.

 

어떤 기능을 구현한다 했을때 이런게 있겠지? 라고 생각하고 

해당 기능을 가진 객체를 구글링하면 대부분 존재한다. 그럼 그걸 가져다 샘플 만들어서 돌려보고 

코드에 반영하게 된다. 이럴때도 "할수 있는 일" 을 찾을때 도움이 된다.