[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 통신 설명에서 서버와 클라이언트의 통신 방법에 대해서 설명한 내용입니다.
이 이미지 중에서 method call은 vsomeip 기본 예제를 이용해서 포스팅한 아래의 urI에서 다루어 보았구요
나머지 Event-Callback과 Notification-Callback에 대해서 코드상으로 설명 드리겠습니다.
아래의 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 |