하. 드디어 여기까지 왔다. opc ua를 설치하면 자동화 기기에서 정보를 쉽게 읽을 수 있다. 여기에서 여러 오픈소스 프로그램을 찾았다. 소개한 홈페이지와 마찬가지로 가볍게 C로 작성한 open62541를 설치하기로 했다.
3달 전만해도 PLC가 당연히 OPC를 지원할 줄 알았으나, 지멘스 S7-1500 최신 제품, MELSEC 정도나 OPCUA를 지원한다. 나름 최신 기술인가보다. OPC 솔루션을 가진 회사에 연락하면 쉽게 지원받을 수 있는데 가격대가 높다. 7만원 짜리 라즈베리 하드웨어에 몇 천만원 소프트웨어를 올리면 미친 짓이다. 쓸 사람도 없고. 이런 기능을 PLC 메이커가 좀 쉽게 해줘야 하는데, 아쉽다.
설치는 정말 그대로 따라하면 된다. 컴파일 후 open62541.c와 open62541.h 파일을 현재 폴더에 넣고 #include “open62541.c”로 하던가, gcc 표준 라이브러리 경로를 찾아 디렉토리 구조째 넣어주고 <>으로 감싸도 된다. tutorial은 뭔가 잘못되었는지 잘 실행되지 않는다. 참조한 사이트 작성자가 했듯이 주석처리하면 된다. 실행하면 서버가 열리고 접속할 수 있다. 웹 브라우저가 아닌 OPC 클라이언트가 필요하다.
pi@raspberrypi:~/OPCUA/sample $ ./myServer [2020-09-04 07:01:39.438 (UTC+0900)] warn/server AccessControl: Unconfigured AccessControl. Users have all permissions. [2020-09-04 07:01:39.438 (UTC+0900)] info/server AccessControl: Anonymous login is enabled [2020-09-04 07:01:39.438 (UTC+0900)] warn/server Username/Password configured, but no encrypting SecurityPolicy. This can leak credentials on the network. [2020-09-04 07:01:39.438 (UTC+0900)] warn/userland AcceptAll Certificate Verification. Any remote certificate will be accepted. [2020-09-04 07:01:39.439 (UTC+0900)] info/network TCP network layer listening on opc.tcp://raspberrypi:4840/
PLC가 opcua를 지원하면 서버, 클라이언트 양쪽 다 지원할 듯 하다. 여기를 보고 다음단계로 가보자.
동영상 다 보고, 코드 몇 개 실행하면 자가격리 끝나 있겠다. 아 허리야.
이어서…
위 방법대로 sample 코드를 컴파일하면 에러가 무지하게 뜬다. 아마도 중복으로 선언되어 문제인 듯 하다. 여기에 있는 raspberry용 파일을 받아 압축을 푼 뒤, include에 해당하는 c, h 파일을 gcc 경로에 넣어주면 된다. 혹시나 해서 build한 버전의 c, h 파일을 모두 찾아 되는지 해보았지만 실패했다. 다음 3개 경로에서 찾을 수 있는데, raspberry용 파일과 linux 파일이 조금 다르다. raspberry는 헤더를 포함하는 부분이 좀 간략하게 되어 있다. server.h를 예를 들면.
pi@raspberrypi:~/OPCUA/open62541 $ find ./ -type d -iname open62541 ./include/open62541 ./plugins/include/open62541 ./build/src_generated/open62541 ./build/CMakeFiles/open62541-object.dir/src_generated/open62541 ./build/CMakeFiles/Export/lib/cmake/open62541
결국 라즈베리용 파일을 해당 경로에 넣어준다. library는 build 아래 bin에 디렉토리에 libopen62541.so을 만든다. 라즈베리용 라이브러리보다 좀 작다. 이 linux용 build 라이브러리를 사용하면 오류난다. 라즈베리용 라이브러리를 사용해야 한다. raspberry에서 컴파일 할 수도 있어 보이지만, readme에 표시되지 않았다. 결국 되니 패스하겠다.
정리하면.
open62541 컴파일하여 open62541.c, open62541.h를 얻음.라즈베리용 파일을 구하여 압축 해제.(build 후 header를 중복으로 선언한 부분을 수정한 듯 함. 조금씩 다름)include에 포함된 c, h를 해당 경로로 이동.lib에 포함된 .so를 각 환경에 맞는 경로로 이동.gcc -std=c99 -lopen62541 sample.c -o target이런 형식으로 컴파일.
라면 끝인 줄 알았으나, 아래 두 방법 중 하나를 선택하면 된다.
- 컴파일 한 open62541.c, open62541.h 사용.
- ccmake 중 UA_ENABLE_AMALGAMATION=on 을 선택하여 open62541.c open62541.h를 만들면 끝나도록 한다.
- 라이브러리를 만들면 해당 디렉토리에 복사.
In CMake, select freertosLWIP using the variable UA_ARCHITECTURE, enable amalgamation using the UA_ENABLE_AMALGAMATION variable and just select the native compilers. Then try to compile as always. The compilation will fail, but the open62541.h and open62541.c will be generated.
- 라즈베리용 헤더, 라이브러리 사용.
- 컴파일 필요 없음.
- 적당히 include, lib 파일을 찾아 복사해 줌.
- tutorial 코드를 그대로 사용할 수 있음.
#include <open62541/plugin/log_stdout.h> #include <open62541/server.h> #include <open62541/server_config_default.h> //#include <open62541/open62541.h> #include <signal.h> #include <stdlib.h> static volatile UA_Boolean running = true; static void stopHandler(int sig) { UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "received ctrl-c"); running = false; } int main(void) { signal(SIGINT, stopHandler); signal(SIGTERM, stopHandler); UA_Server *server = UA_Server_new(); UA_ServerConfig_setDefault(UA_Server_getConfig(server)); UA_StatusCode retval = UA_Server_run(server, &running); UA_Server_delete(server); return retval == UA_STATUSCODE_GOOD ? EXIT_SUCCESS : EXIT_FAILURE; }
위 코드에서 open62541/open62541.h를 주석 처리했다. open62541.h 파일을 현재 디렉토리로 옮긴 후 #include “open62541.h”으로 쓰고, 위 앞 3줄을 주석처리해도 컴파일 된다. 끝.