뼈민
고급 개발자가 꿈인 코린이
뼈민
전체 방문자
오늘
어제
  • 분류 전체보기 (73)
    • QT and QML (40)
    • C++ (22)
      • C++심화 (21)
      • C++기본 (1)
    • 리눅스 (5)
      • 쉘스크립트 (0)
      • 자주쓰는 리눅스 명령어 (5)
    • 프로그래머이야기 (2)
    • 블로그 운영 (1)
    • 삼성전자투자기 (3)

블로그 메뉴

  • 홈
  • QT/QML

공지사항

인기 글

태그

  • QML
  • Qt
  • device to device
  • C++
  • stylev파일
  • someip
  • vsomeip

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
뼈민

고급 개발자가 꿈인 코린이

[C++,QT/Qml]39.Qt 프로세스간의 통신(IPC) 구현하기8(broadcast,attribute 이벤트)
QT and QML

[C++,QT/Qml]39.Qt 프로세스간의 통신(IPC) 구현하기8(broadcast,attribute 이벤트)

2020. 4. 12. 12:31
반응형

 

 

 

 

[C++,QT/Qml]39.Qt 프로세스간의 통신(IPC) 구현하기8(broadcast,attribute 이벤트)

 

 

안녕하세요 고급 개발자가 꿈인 코린이 입니다.

 

오늘은 vsomeip를 이용한 프로세스간의 통신 중에서 broadcast와 attribute이벤트를 다루어 보도록 하겠습니다.

 

아래의 사이트에서 나온 내용 중에 service와 client간의 통신 방법 중에는 method call과 broadcast ,attribute등이 

 

있는데요 여기서 method call은 말그대로 함수를 호출하는 내용이고 broadcast는 Event를 날려주는 내용

 

attribute는 field값이 변경 되었을때 noti event를 날려주는 내용 입니다.

 

이 내용중에 broadcast와 attribute이벤트를 이용해서 통신하는 방법을 코드상으로 다루어 보겠습니다.

 

GENIVI/vsomeip

An implementation of Scalable service-Oriented MiddlewarE over IP - GENIVI/vsomeip

github.com

아래의 이미지는 genivi의 vsomeip 통신 설명에서 서버와 클라이언트의 통신 방법에 대해서 설명한 내용입니다.

 

 

nivi

 

이 이미지 중에서 method call은 vsomeip 기본 예제를 이용해서 포스팅한 아래의 urI에서  다루어 보았구요

 

나머지 Event-Callback과 Notification-Callback에 대해서 코드상으로 설명 드리겠습니다.

 

[C++,QT/Qml]37.Qt 프로세스간의 통신(IPC) 구현하기6(commonapi some/ip)

[C++,QT/Qml]37.Qt 프로세스간의 통신(IPC) 구현하기6(commonapi some/ip) 안녕하세요 고급 개발자가 꿈인 코린이 입니다. 오늘은 commonapi dbus 가 아닌 commonapi someip를 이용한 프로세스간 통신에 대한 내용..

youonlyliveonce1.tistory.com

아래의 Helloworld.fidl 파일을 보시면 attribute와 method, broadcast를 사용하기 위해서 인터페이스를 

 

등록해준 내용입니다. 그리고 Helloworld.fdepl에서도 사용하기 위한 각 api들을 설정해 주었습니다.

 

아래처럼 적어주신후에 code generator를 이용해서 자동으로 통신이 가능한 코드로 설정이 가능합니다.

 

Helloworld.fidl

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package commonapi
  
interface HelloWorld {
  version {major 1 minor 0}
 
  attribute Boolean HelloState readonly
 
  method sayHello {
    in {
      String name
    }
    out {
      String message
    }
  }
 
  broadcast HelloBroadcast {
        out {
            String message
        }
    }
} 
 
 
http://colorscripter.com/info#e" target="_blank" style="color:#4f4f4ftext-decoration:none">Colored by Color Scripter
 

Helloworld.fdepl

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
import "platform:/plugin/org.genivi.commonapi.someip/deployment/CommonAPI-SOMEIP_deployment_spec.fdepl"
import "HelloWorld.fidl"
define org.genivi.commonapi.someip.deployment for interface commonapi.HelloWorld {
    SomeIpServiceID = 4660
     
    attribute HelloState {
        SomeIpGetterID = 8199
        SomeIpNotifierID = 40965
        SomeIpEventGroups = {
            4097
        }
 
    }
    method sayHello {
        SomeIpMethodID = 32000
        out {
            message {}
        }
    }
 
 
    broadcast HelloBroadcast {
        SomeIpEventID = 33333
        SomeIpEventGroups = {
            4098
        }
        out {
            message {}
        }
    }
 
}
  
define org.genivi.commonapi.someip.deployment for provider MyService {
    instance commonapi.HelloWorld {
        InstanceId = "test"
        SomeIpInstanceID = 22136
    }
} 
 
 
http://colorscripter.com/info#e" target="_blank" style="color:#4f4f4ftext-decoration:none">Colored by Color Scripter
 

vsomeip_server.json 에서 서버와 클라이언트간의 통신을 위해서

 

아래와 같이 서비스의 서비스 id와 인스턴스 아이디를 등록해 줍니다.

  

서비스 id와 인스턴스 아이디는 Helloworld.fdepl 에 보시면 SomeIpServiceID와 SomeIpInstanceID를 이용하시면 됩니다.

 

service = SomeIpServiceID , instance = SomeIpInstanceID 이런식으로 설정해 주시면 됩니다.

 

vsomeip_server.json

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
{ 
    "unicast" : "10.0.2.15",
    "logging" :
    {
        "level" : "debug",
        "console" : "true",
        "file" : { "enable" : "false" },
        "dlt" : "false"
    },
    "applications" :
    [
        {
            "name" : "HelloWorldService",
            "id" : "0x1277"
        }
    ],
 
            "services" :
            [
                {
                    "service" : "4660",
                    "instance" : "22136",
                    "unreliable" : "30490"
                }
            ],
 
    "routing" : "HelloWorldService",
    "service-discovery" :
    {
        "enable" : "true",
        "multicast" : "224.244.224.245",
        "port" : "30490",
        "protocol" : "udp"
    }
}  
 
 
http://colorscripter.com/info#e" target="_blank" style="color:#4f4f4ftext-decoration:none">Colored by Color Scripter
 

 

vsomeip_client.json

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
{ 
    "unicast" : "local",
    "logging" :
    {
        "level" : "debug",
        "console" : "true",
        "file" : { "enable" : "false" },
        "dlt" : "false"
    },
    "applications" :
    [
        {
            "name" : "HelloWorldClient",
            "id" : "0x1343"
        }
    ],
    "routing" : "HelloWorldService",
    "service-discovery" :
    {
        "enable" : "true",
        "multicast" : "224.244.224.245",
        "port" : "30490",
        "protocol" : "udp"
    }
}  
 
 
http://colorscripter.com/info#e" target="_blank" style="color:#4f4f4ftext-decoration:none">Colored by Color Scripter
 

HelloWorldService.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#include <iostream>
#include <thread>
#include <CommonAPI/CommonAPI.hpp>
#include "HelloWorldStubImpl.hpp"
  
using namespace std;
  
int main() {
    std::shared_ptr<CommonAPI::Runtime> runtime = CommonAPI::Runtime::get();
    std::shared_ptr<HelloWorldStubImpl> myService = std::make_shared<HelloWorldStubImpl>();
    bool test = true;
    runtime->registerService("local", "test", myService);
    std::cout << "Successfully Registered Service!" << std::endl;
 
    while (true) {
        std::cout << "Waiting for calls... (Abort with CTRL+C)" << std::endl;
        if(test){
            test = false;
            std::cout << "Send Attribute!!!" << std::endl;
            myService->setHelloStateAttribute(true);//while 문이 5초에 한번씩 돌면서 attribute를 set해준다.
        }else{
            test = true;
            std::cout << "Send BoradCastEvent!!!" << std::endl;
            myService->setHelloStateAttribute(false);//while 문이 5초에 한번씩 돌면서 attribute를 set해준다.
            myService->fireHelloBroadcastEvent("broadCast MSG");//while 문이 5초에 한번씩 BroadcstEvent를 발생 시킨다.
        }
        std::this_thread::sleep_for(std::chrono::seconds(5));
    }
  
    return 0;
 } 
 
 
 
http://colorscripter.com/info#e" target="_blank" style="color:#4f4f4ftext-decoration:none">Colored by Color Scripter
 

HelloWorldClient.cpp

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#include <iostream>
#include <string>
#include <unistd.h>
#include <CommonAPI/CommonAPI.hpp>
#include <v1/commonapi/HelloWorldProxy.hpp>
  
using namespace v1::commonapi;
  
int main() {
    std::shared_ptr <CommonAPI::Runtime > runtime = CommonAPI::Runtime::get();
    std::shared_ptr<HelloWorldProxy<>> myProxy = runtime->buildProxy<HelloWorldProxy>("local", "test");
  
    std::cout << "Checking availability!" << std::endl;
    while (!myProxy->isAvailable())
        usleep(10);
    std::cout << "Available..." << std::endl;
  
    CommonAPI::CallStatus callStatus;
    std::string returnMessage;
    myProxy->sayHello("Bob", callStatus, returnMessage);//서버의 함수를 호출 (method call)
    std::cout << "Got message: '" << returnMessage << "'\n";
 
    myProxy->getHelloStateAttribute().getChangedEvent().subscribe([&](const bool value) {//attribute 이벤트를 등록시킴
        std::cout << "getHelloStateAttribute value : " << value << std::endl;
    });
    myProxy->getHelloBroadcastEvent().subscribe([&](const std::string &value) {//broadcast 이벤트를 등록시킴
        std::cout << "getHelloBroadcastEvent value : " << value << std::endl;
    });
 
    while (true) {
        std::cout << "client Waiting for calls... (Abort with CTRL+C)" << std::endl;
 
        std::this_thread::sleep_for(std::chrono::seconds(1));
    }
     
    return 0;
} 
 
 
 
http://colorscripter.com/info#e" target="_blank" style="color:#4f4f4ftext-decoration:none">Colored by Color Scripter
 

실행 결과 동영상

 

 

 

위의 HelloWorldService에서 broadcast이벤트와 attribute이벤트를 각각 5초에 한번씩 불려지도록 구현을 해놓았습니다.

 

broadcast 이벤트는 5초에 한번씩 불려지고 attribute이벤트는 5초에 한번씩 false 값과 true값이 번갈아 가면서

 

호출이 되도록 구현을 해놓았습니다.

 

클라이언트 쪽에서 attribute 이벤트를 받기위해서 이벤트를 등록하는 부분은 아래와 같습니다.

 

1
2
3
myProxy->getHelloStateAttribute().getChangedEvent().subscribe([&](const bool value) {//attribute 이벤트를 등록시킴
        std::cout << "getHelloStateAttribute value : " << value << std::endl;
    });
http://colorscripter.com/info#e" target="_blank" style="color:#4f4f4ftext-decoration:none">Colored by Color Scripter
 

 

그리고 클라이언트 쪽에서 broadcast 이벤트를 받기위해서 등록하는 부분은 아래와 같습니다.

 

1
2
3
myProxy->getHelloBroadcastEvent().subscribe([&](const std::string &value) {//broadcast 이벤트를 등록시킴
        std::cout << "getHelloBroadcastEvent value : " << value << std::endl;
    });
http://colorscripter.com/info#e" target="_blank" style="color:#4f4f4ftext-decoration:none">Colored by Color Scripter
http://colorscripter.com/info#e" target="_blank" style="text-decoration:none;color:white">cs

 

이 둘의 차이점은  attribute에서는 changedEvent를 등록하고 broadcast에서는 broadcast이벤트 자체를 등록해 줍니다.

 

서버에서 broadcast이벤트를 클라이언트로 보내기 위해서는 아래와 같이 fire함수를 이용해서 broadcast이벤트함수를

 

호출해 줍니다.

1
myService->fireHelloBroadcastEvent("broadCast MSG");
 

 

그리고 서버에서 클라이언트에게 attribute이벤트를 날려주기 위해서는 field 값을 세팅해 줍니다.

1
myService->setHelloStateAttribute(true);
 

이렇게 해주면 위에서 보여드린 Event-Callback과 Notification-Callback에 대한 코드가 완성이 되는 것입니다.

 

이미지에 보시면 event-callback 과 notification-callback들을 subscribe를 해주고 server측에서 

 

이벤트를 발생 시키거나 field값을 설정해주면 client쪽으로 알려주는 식으로 그림이 나와 있는데

 

이러한 플로우가 기본적으로 구현이 되는것 입니다.

 

여기 까지 vsomeip 를 이용한 프로세스간의 통신에 대한 내용을 다루어 보았습니다.

 

여기까지 읽어주셔서 감사합니다.

반응형

'QT and QML' 카테고리의 다른 글

[C++,QT/Qml]41.Qml프로그래밍 qml에서 함수를 js파일에서 선언하는 방법(함수를 한곳에서 선언하는 방법)  (0) 2020.07.26
[C++,QT/Qml]40.Qml프로그래밍 cpp qml 연동4(c++에서 qml 함수 호출하기)  (0) 2020.05.17
[C++,QT/Qml]38.Qt 프로세스간의 통신(IPC) 구현하기7(commonapi some/ip 두개의 디바이스간 통신 구현)  (2) 2020.03.01
[C++,QT/Qml]37.Qt 프로세스간의 통신(IPC) 구현하기6(commonapi some/ip)  (0) 2020.01.21
[C++,QT/Qml]36.Qt 프로세스간의 통신(IPC) 구현하기5(나의 qt프로젝트가 클라이언트인 ui앱 만들기)  (6) 2019.12.30
    'QT and QML' 카테고리의 다른 글
    • [C++,QT/Qml]41.Qml프로그래밍 qml에서 함수를 js파일에서 선언하는 방법(함수를 한곳에서 선언하는 방법)
    • [C++,QT/Qml]40.Qml프로그래밍 cpp qml 연동4(c++에서 qml 함수 호출하기)
    • [C++,QT/Qml]38.Qt 프로세스간의 통신(IPC) 구현하기7(commonapi some/ip 두개의 디바이스간 통신 구현)
    • [C++,QT/Qml]37.Qt 프로세스간의 통신(IPC) 구현하기6(commonapi some/ip)
    뼈민
    뼈민

    티스토리툴바