콘텐츠로 바로가기

now0930 일지

이런저런 생각

  • 홈
  • 비공개
  • 강좌
  • 잔여 작업 조회
  • 위치

open62541 method call

튜토리얼에 method call이 있어 따라 해봤다. method를 서버에 설정하고, client에서 반응을 보고 싶었는데, 잘 안됬다. 두 시간 삽질만에 UA_VARINT에서 UA_String을 출력했다. 처음에는 몰랐는데 gdb로 구조를 보면 대략 알 수 있다. UA_String도 구조체라 data와 length로 구성된다. UA_Variant로 data를 출력하려면 UA_String으로 캐스팅하여 data의 data를 찾아야 한다.–;

(gdb) 
45		/* Call a remote method */
46		UA_Variant input;
47		UA_String argString = UA_STRING("Hello Server");
48		UA_Variant_init(&input);
49		//UA_Variant_setScalarCopy(&input, &argString, &UA_TYPES[UA_TYPES_STRING]);
50		UA_Variant_setScalarCopy(&input, &argString, &UA_TYPES[UA_TYPES_STRING]);
51		UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "input data is %s\n",(UA_String*)input.data);
52	
53		size_t outputSize;
54		UA_Variant *output;
(gdb) display input
1: input = {type = 0xbefff4c8, storageType = (unknown: 3070066356), arrayLength = 0, data = 0xb6ffd13c, arrayDimensionsSize = 4, 
  arrayDimensions = 0xb6ffd14c}
(gdb) n
48		UA_Variant_init(&input);
1: input = {type = 0xbefff4c8, storageType = (unknown: 3070066356), arrayLength = 0, data = 0xb6ffd13c, arrayDimensionsSize = 4, 
  arrayDimensions = 0xb6ffd14c}
(gdb) print argString
$1 = {length = 12, data = 0x10f0c "Hello Server"}
(gdb) print argString->data
$2 = (UA_Byte *) 0x10f0c "Hello Server"
(gdb) n
50		UA_Variant_setScalarCopy(&input, &argString, &UA_TYPES[UA_TYPES_STRING]);
1: input = {type = 0x0, storageType = UA_VARIANT_DATA, arrayLength = 0, data = 0x0, arrayDimensionsSize = 0, arrayDimensions = 0x0}
(gdb) n
51		UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "input data is %s\n",(UA_String*)input.data);
1: input = {type = 0x22250 <UA_TYPES+704>, storageType = UA_VARIANT_DATA, arrayLength = 0, data = 0x282d8, arrayDimensionsSize = 0, arrayDimensions = 0x0}
(gdb) print input->data
$3 = (void *) 0x282d8
(gdb) print input->data->data
Attempt to dereference a generic pointer.
(gdb) print (UA_String*)(input->data)->data
Attempt to dereference a generic pointer.
(gdb) print (UA_String*)(input.data)->data
Attempt to dereference a generic pointer.
(gdb) display argString
2: argString = {length = 12, data = 0x10f0c "Hello Server"}
(gdb) display
1: input = {type = 0x22250 <UA_TYPES+704>, storageType = UA_VARIANT_DATA, arrayLength = 0, data = 0x282d8, arrayDimensionsSize = 0, arrayDimensions = 0x0}
2: argString = {length = 12, data = 0x10f0c "Hello Server"}
(gdb) display &argString
3: &argString = (UA_String *) 0xbefff368
[2020-09-07 04:29:15.352 (UTC+0900)] info/userland	input data is Hello Server��
Method call was successful, and 1 returned values available.
[2020-09-07 04:29:15.352 (UTC+0900)] info/userland	output data is Hello Hello Server
[2020-09-07 04:29:15.353 (UTC+0900)] info/client	Client Status: ChannelState: Closed, SessionState: Closed, ConnectStatus: Good
int main(void) {
    UA_Client *client = UA_Client_new();
    UA_ClientConfig_setDefault(UA_Client_getConfig(client));
    UA_StatusCode retval = UA_Client_connect(client, "opc.tcp://localhost:4840");
	printf("retval is %d\n",retval);
    if(retval != UA_STATUSCODE_GOOD) {
        UA_Client_delete(client);
        return (int)retval;
    }
    /* Read attribute */
    UA_Int32 value2 = 0;
    printf("\nReading the value of node (1, \"Test Var:Me\"):\n");
    UA_Variant *val = UA_Variant_new();
    retval = UA_Client_readValueAttribute(client, UA_NODEID_STRING(1, "Test Var:Me"), val);
    if(retval == UA_STATUSCODE_GOOD && UA_Variant_isScalar(val) &&
			val->type == &UA_TYPES[UA_TYPES_INT32]) {
		value2 = *(UA_Int32*)val->data;
		//printf("the value is: %i\n", value2);
		UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND,"myData is %d",value2);

	}

	//method call

#ifdef UA_ENABLE_METHODCALLS
	/* Call a remote method */
	UA_Variant input;
	UA_String argString = UA_STRING("Hello Server");
	UA_Variant_init(&input);
	//UA_Variant_setScalarCopy(&input, &argString, &UA_TYPES[UA_TYPES_STRING]);
	UA_Variant_setScalarCopy(&input, &argString, &UA_TYPES[UA_TYPES_STRING]);
	UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "input data is %s\n",((UA_String*)input.data)->data);
	size_t outputSize;
	UA_Variant *output;
	retval = UA_Client_call(client, UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER),
			UA_NODEID_NUMERIC(1, 62541), 1, &input, &outputSize, &output);

	if(retval == UA_STATUSCODE_GOOD) {
		printf("Method call was successful, and %lu returned values available.\n",
				(unsigned long)outputSize);

		UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "output data is %s\n",((UA_String*)output->data)->data);

		UA_Array_delete(output, outputSize, &UA_TYPES[UA_TYPES_VARIANT]);
	} else {
		printf("Method call was unsuccessful, and %x returned values available.\n", retval);
	}
	UA_Variant_clear(&input);
#endif

	UA_Variant_delete(val);
	/* Clean up */
	//	UA_Variant_clear(&value);
	UA_Variant_clear(&value2);

	UA_Client_delete(client); /* Disconnects the client internally */
	return EXIT_SUCCESS;
}

이 글 공유하기:

  • Tweet
발행일 2020-09-07글쓴이 이대원
카테고리 생활코딩 태그 opcua, open62541, plc, raspberry

댓글 남기기응답 취소

이 사이트는 Akismet을 사용하여 스팸을 줄입니다. 댓글 데이터가 어떻게 처리되는지 알아보세요.

글 탐색

이전 글

open62541 server – client variable 전달

다음 글

open62541 server 설정

2025 8월
일 월 화 수 목 금 토
 12
3456789
10111213141516
17181920212223
24252627282930
31  
7월    

최신 글

  • Unipolar, Bipolar 2025-07-08
  • DC 모터 모델링 2025-07-03
  • 모터 개론 2025-06-22
  • common mode, differential mode 2025-05-11
  • signal conditioner, 신호 처리기 2025-05-10

카테고리

  • 산업계측제어기술사
  • 삶 자국
    • 책과 영화
    • 투자
  • 생활코딩
    • LEGO
    • ROS
    • tensorflow
  • 전기기사
  • 피아노 악보

메타

  • 로그인
  • 입력 내용 피드
  • 댓글 피드
  • WordPress.org

페이지

  • 소개
  • 잔여 작업 조회
    • 작업 추가
    • 작업의 사진 조회
    • 작업 수정 페이지
  • 사진
    • GPS 입력된 사진
    • 사진 조회
  • 위치
    • 하기 휴가 방문지
    • 해외 출장

태그

android bash c docker driver FSM gps java kernel LEGO linux mysql network program opcua open62541 plc programmers python raspberry reinforcementLearning ros state space system program tensorflow transfer function 경제 미국 민수 삼국지 세계사 실기 에너지 역사 유전자 일본 임베디드 리눅스 전기기사 조선 중국 채윤 코딩 테스트 통계 한국사 한국어

팔로우하세요

  • Facebook
now0930 일지
WordPress로 제작.