From 815c6c2b17ed12cea49613dd4bf9907276ccacf2 Mon Sep 17 00:00:00 2001 From: dan-du-car <62157949+dan-du-car@users.noreply.github.com> Date: Thu, 28 Apr 2022 13:58:41 -0400 Subject: [PATCH 1/7] add unit test for PSM (#365) * add unit test * add unit test * init --- src/tmx/TmxUtils/test/J2735MessageTest.cpp | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/tmx/TmxUtils/test/J2735MessageTest.cpp b/src/tmx/TmxUtils/test/J2735MessageTest.cpp index 44d0f4afc..a5bb3642e 100644 --- a/src/tmx/TmxUtils/test/J2735MessageTest.cpp +++ b/src/tmx/TmxUtils/test/J2735MessageTest.cpp @@ -484,7 +484,7 @@ TEST_F(J2735MessageTest, EncodeMobilityResponse) TEST_F(J2735MessageTest, EncodeBasicSafetyMessage) { - BasicSafetyMessage_t* message = (BasicSafetyMessage_t*) malloc( sizeof(BasicSafetyMessage_t) ); + BasicSafetyMessage_t* message = (BasicSafetyMessage_t*) calloc(1, sizeof(BasicSafetyMessage_t) ); /** * Populate BSMcoreData @@ -542,4 +542,17 @@ TEST_F(J2735MessageTest, EncodeBasicSafetyMessage) } +TEST_F(J2735MessageTest, EncodePersonalSafetyMessage){ + string psm="1090115eadf0389549376-771491840255255655350160100001"; + std::stringstream ss; + PsmMessage psmmessage; + PsmEncodedMessage psmENC; + tmx::message_container_type container; + ss<(ss); + psmmessage.set_contents(container.get_storage().get_tree()); + psmENC.encode_j2735_message(psmmessage); + std::cout << psmENC.get_payload_str()< Date: Thu, 12 May 2022 14:50:02 -0400 Subject: [PATCH 2/7] Issue-369:Added automated release image push (#370) --- .circleci/config.yml | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index d90ebb815..225d7bcf0 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -207,6 +207,40 @@ jobs: docker push usdotfhwaops/v2xhubarm:latest docker push usdotfhwaops/port-drayage-webservice_arm:latest docker push usdotfhwaops/php_arm:latest + automated_release : + machine: + image: ubuntu-2004:202201-02 + steps: + - run: + name: Docker Pull Release + # Pull all built images associated with github tag + command: | + docker pull usdotfhwaops/php:master + docker pull usdotfhwaops/port-drayage-webservice:master + docker pull usdotfhwaops/v2xhubamd:master + docker pull usdotfhwaops/php_arm:master + docker pull usdotfhwaops/port-drayage-webservice_arm:master + docker pull usdotfhwaops/v2xhubarm:master + - run: + name: Docker Tag Release + # Tag all pulled images with github tag name + command: | + docker tag usdotfhwaops/php:master usdotfhwaops/php:${CIRCLE_TAG} + docker tag usdotfhwaops/port-drayage-webservice:master usdotfhwaops/port-drayage-webservice:${CIRCLE_TAG} + docker tag usdotfhwaops/v2xhubamd:master usdotfhwaops/v2xhubamd:${CIRCLE_TAG} + docker tag usdotfhwaops/php_arm:master usdotfhwaops/php_arm:${CIRCLE_TAG} + docker tag usdotfhwaops/port-drayage-webservice_arm:master usdotfhwaops/port-drayage-webservice_arm:${CIRCLE_TAG} + docker tag usdotfhwaops/v2xhubarm:master usdotfhwaops/v2xhubarm:${CIRCLE_TAG} + - run: + name: Docker Push Release Tag + # Push all tagged images + command: | + docker push usdotfhwaops/php:${CIRCLE_TAG} + docker push usdotfhwaops/port-drayage-webservice:${CIRCLE_TAG} + docker push usdotfhwaops/v2xhubamd:${CIRCLE_TAG} + docker push usdotfhwaops/php_arm:${CIRCLE_TAG} + docker push usdotfhwaops/port-drayage-webservice_arm:${CIRCLE_TAG} + docker push usdotfhwaops/v2xhubarm:${CIRCLE_TAG} workflows: version: 2 build: @@ -233,5 +267,14 @@ workflows: - sonar-scanner_develop: requires: - docker_build_push_develop + - automated_release: + requires: + - docker_build_push + - arm_build_push + filters: + tags: + only: ^[\.0-9]*$ + branches: + only: master From c1358c60aeaa594ec1ca54b49cccba70bda1bfbf Mon Sep 17 00:00:00 2001 From: abey-yoseph <59704440+abey-yoseph@users.noreply.github.com> Date: Thu, 12 May 2022 22:15:35 +0000 Subject: [PATCH 3/7] 345 ped flir api interface (#366) * Initial FLIR interface implementation * fix buffer string copy issue and websocket not starting * able to connect to camera, plugin breaks when receiving flir response * able to subscribe to ped data, errors thrown upon consuming * build error * can subscibe, receive, parse ped data, and generate xml * adding psm broadcast functionality * broadcast functionality working * additional fields added to PSM * add psm xml mutex and fix for char arr to string * Address PR comments and sonarcloud code smells * remove log of every new MAP message * fix for incorrec lat/long in psm xml * PR comments and sonar scanner code smells * More PR comments addressed Co-authored-by: Sudhakar Nallamothu --- src/v2i-hub/PedestrianPlugin/CMakeLists.txt | 108 ++--- src/v2i-hub/PedestrianPlugin/manifest.json | 28 +- .../src/FLIRWebSockAsyncClnSession.cpp | 373 ++++++++++++++++++ .../PedestrianPlugin/src/PedestrianPlugin.cpp | 149 +++++-- .../include/FLIRWebSockAsyncClnSession.hpp | 148 +++++++ .../src/include/PedestrianPlugin.hpp | 19 +- 6 files changed, 737 insertions(+), 88 deletions(-) mode change 100644 => 100755 src/v2i-hub/PedestrianPlugin/CMakeLists.txt create mode 100644 src/v2i-hub/PedestrianPlugin/src/FLIRWebSockAsyncClnSession.cpp create mode 100644 src/v2i-hub/PedestrianPlugin/src/include/FLIRWebSockAsyncClnSession.hpp diff --git a/src/v2i-hub/PedestrianPlugin/CMakeLists.txt b/src/v2i-hub/PedestrianPlugin/CMakeLists.txt old mode 100644 new mode 100755 index 5d7624998..8783a975c --- a/src/v2i-hub/PedestrianPlugin/CMakeLists.txt +++ b/src/v2i-hub/PedestrianPlugin/CMakeLists.txt @@ -1,54 +1,54 @@ -PROJECT ( PedestrianPlugin VERSION 5.0 LANGUAGES CXX ) - -SET (TMX_PLUGIN_NAME "Pedestrian") -add_compile_options(-fPIC) -FIND_PACKAGE (XercesC REQUIRED) -FIND_PACKAGE (NetSNMP REQUIRED) -#FIND_PACKAGE (QHttpEngine REQUIRED) - -find_package(Qt5Core REQUIRED) -find_package(Qt5Widgets REQUIRED) -find_package(Qt5Network REQUIRED) - -#set(qserverPedestrian_DIR "/usr/local/share/qserverPedestrian/cmake") -find_package(qserverPedestrian REQUIRED) - -include_directories(${Qt5Widgets_INCLUDE_DIRS}) - -include_directories(${EXTERNAL_INSTALL_LOCATION}/include) -link_directories(${EXTERNAL_INSTALL_LOCATION}/lib) - -find_library(libasn1c .) - - - -include_directories( - ${Qt5Core_INCLUDE_DIRS} - ${Qt5Network_INCLUDE_DIRS} -) - - -BuildTmxPlugin () - - - -TARGET_INCLUDE_DIRECTORIES ( ${PROJECT_NAME} PUBLIC ${XercesC_INCLUDE_DIRS} ${NETSNMP_INCLUDE_DIRS} ${Qt5Core_INCLUDE_DIRS} ${Qt5Network_INCLUDE_DIRS}) - -TARGET_LINK_LIBRARIES ( ${PROJECT_NAME} PUBLIC tmxutils ${XercesC_LIBRARY} ${NETSNMP_LIBRARIES} ${QHttpEngine_LIBRARY} Qt5Widgets Qt5Core Qt5Network ssl crypto qhttpengine qserverPedestrian) - - -link_directories(${CMAKE_PREFIX_PATH}/lib) - -# Locate GTest -find_package(GTest REQUIRED) -include_directories(${GTEST_INCLUDE_DIRS}) - -set(runPedestrianTests_sources - test/PedestrianTest.cpp - test/Main.cpp -) - -# Link runTests with what we want to test and the GTest and pthread library -add_executable(runPedestrianTests ${runPedestrianTests_sources}) - -target_link_libraries(runPedestrianTests ${GTEST_LIBRARIES} pthread ${QHttpEngine_LIBRARY} Qt5::Widgets Qt5Core Qt5Network ssl crypto qhttpengine) \ No newline at end of file +PROJECT ( PedestrianPlugin VERSION 5.0 LANGUAGES CXX ) + +SET (TMX_PLUGIN_NAME "Pedestrian") +add_compile_options(-fPIC) +FIND_PACKAGE (XercesC REQUIRED) +FIND_PACKAGE (NetSNMP REQUIRED) +#FIND_PACKAGE (QHttpEngine REQUIRED) + +find_package(Qt5Core REQUIRED) +find_package(Qt5Widgets REQUIRED) +find_package(Qt5Network REQUIRED) + +#set(qserverPedestrian_DIR "/usr/local/share/qserverPedestrian/cmake") +find_package(qserverPedestrian REQUIRED) + +include_directories(${Qt5Widgets_INCLUDE_DIRS}) + +include_directories(${EXTERNAL_INSTALL_LOCATION}/include) +link_directories(${EXTERNAL_INSTALL_LOCATION}/lib) + +find_library(libasn1c .) + + + +include_directories( + ${Qt5Core_INCLUDE_DIRS} + ${Qt5Network_INCLUDE_DIRS} +) + + +BuildTmxPlugin () + + + +TARGET_INCLUDE_DIRECTORIES ( ${PROJECT_NAME} PUBLIC ${XercesC_INCLUDE_DIRS} ${NETSNMP_INCLUDE_DIRS} ${Qt5Core_INCLUDE_DIRS} ${Qt5Network_INCLUDE_DIRS}) + +TARGET_LINK_LIBRARIES ( ${PROJECT_NAME} PUBLIC tmxutils ${XercesC_LIBRARY} ${NETSNMP_LIBRARIES} ${QHttpEngine_LIBRARY} Qt5Widgets Qt5Core Qt5Network ssl crypto qhttpengine qserverPedestrian) + + +link_directories(${CMAKE_PREFIX_PATH}/lib) + +# Locate GTest +find_package(GTest REQUIRED) +include_directories(${GTEST_INCLUDE_DIRS}) + +set(runPedestrianTests_sources + test/PedestrianTest.cpp + test/Main.cpp +) + +# Link runTests with what we want to test and the GTest and pthread library +add_executable(runPedestrianTests ${runPedestrianTests_sources}) + +target_link_libraries(runPedestrianTests ${GTEST_LIBRARIES} pthread ${QHttpEngine_LIBRARY} Qt5::Widgets Qt5Core Qt5Network ssl crypto qhttpengine) diff --git a/src/v2i-hub/PedestrianPlugin/manifest.json b/src/v2i-hub/PedestrianPlugin/manifest.json index d02ca868f..9c5ae0f13 100644 --- a/src/v2i-hub/PedestrianPlugin/manifest.json +++ b/src/v2i-hub/PedestrianPlugin/manifest.json @@ -32,6 +32,32 @@ "key":"WebServicePort", "default":"9000", "description":"Port at which Web service exists" - } + }, + { + "key":"DataProvider", + "default":"FLIR", + "description":"Possible data providers we handle - FLIR (websocket) or PSM (REST request)" + }, + { + "key":"WebSocketHost", + "default":"192.168.55.183", + "description":"IP address of the camera to connect to for data" + + }, + { + "key":"WebSocketPort", + "default":"80", + "description":"Extension/port for FLIR camera subscription" + }, + { + "key":"FLIRCameraRotation", + "default":"16.13", + "description":"Measured camera rotation from true north (in degrees) used for heading conversion" + }, + { + "key":"LogLevel", + "default":"DEBUG", + "description":"The log level for this plugin" + } ] } diff --git a/src/v2i-hub/PedestrianPlugin/src/FLIRWebSockAsyncClnSession.cpp b/src/v2i-hub/PedestrianPlugin/src/FLIRWebSockAsyncClnSession.cpp new file mode 100644 index 000000000..7b821d952 --- /dev/null +++ b/src/v2i-hub/PedestrianPlugin/src/FLIRWebSockAsyncClnSession.cpp @@ -0,0 +1,373 @@ +#include "include/FLIRWebSockAsyncClnSession.hpp" + +using namespace tmx::utils; +using namespace std; +using namespace boost::property_tree; + +namespace PedestrianPlugin +{ + void + FLIRWebSockAsyncClnSession::fail(beast::error_code ec, char const* what) const + { + PLOG(logDEBUG) << what << ": " << ec.message() << std::endl; + } + + void + FLIRWebSockAsyncClnSession::run( + char const* host, + char const* port, + float cameraRotation) + { + + PLOG(logDEBUG) << "In FLIRWebSockAsyncClnSession::run " << std::endl; + // Save these for later + host_ = host; + cameraRotation_ = cameraRotation; + + PLOG(logDEBUG) << "Host: "<< host <<" ; port: "<< port << std::endl; + + // Look up the domain name + resolver_.async_resolve( + host, + port, + beast::bind_front_handler( + &FLIRWebSockAsyncClnSession::on_resolve, + shared_from_this())); + } + + void + FLIRWebSockAsyncClnSession::on_resolve( + beast::error_code ec, + tcp::resolver::results_type results) + { + PLOG(logDEBUG) << "In FLIRWebSockAsyncClnSession::on_resolve " << std::endl; + if(ec) + return fail(ec, "resolve"); + + // Set the timeout for the operation + beast::get_lowest_layer(ws_).expires_after(std::chrono::seconds(30)); + + // Make the connection on the IP address we get from a lookup + beast::get_lowest_layer(ws_).async_connect( + results, + beast::bind_front_handler( + &FLIRWebSockAsyncClnSession::on_connect, + shared_from_this())); + } + + + void + FLIRWebSockAsyncClnSession::on_connect(beast::error_code ec, tcp::resolver::results_type::endpoint_type ep) + { + PLOG(logDEBUG) << "In FLIRWebSockAsyncClnSession::on_connect " << std::endl; + if(ec) + return fail(ec, "connect"); + + // Turn off the timeout on the tcp_stream, because + // the websocket stream has its own timeout system. + beast::get_lowest_layer(ws_).expires_never(); + + // Set suggested timeout settings for the websocket + ws_.set_option( + websocket::stream_base::timeout::suggested( + beast::role_type::client)); + + // Set a decorator to change the User-Agent of the handshake + ws_.set_option(websocket::stream_base::decorator( + [](websocket::request_type& req) + { + req.set(http::field::user_agent, + std::string(BOOST_BEAST_VERSION_STRING) + + " websocket-client-async"); + })); + + // Update the host_ string. This will provide the value of the + // Host HTTP header during the WebSocket handshake. + // See https://tools.ietf.org/html/rfc7230#section-5.4 + + PLOG(logDEBUG) << "host_: " << host_ << std::endl; + + // Perform the websocket handshake + ws_.async_handshake(host_, "/api/subscriptions", + beast::bind_front_handler( + &FLIRWebSockAsyncClnSession::on_handshake, + shared_from_this())); + } + + void + FLIRWebSockAsyncClnSession::on_handshake(beast::error_code ec) + { + PLOG(logDEBUG) << "In FLIRWebSockAsyncClnSession::on_handshake " << std::endl; + if(ec) + return fail(ec, "handshake"); + + // Send the message + ws_.async_write( + net::buffer(pedPresenceTrackingReq), + beast::bind_front_handler( + &FLIRWebSockAsyncClnSession::on_write, + shared_from_this())); + } + + void + FLIRWebSockAsyncClnSession::on_write( + beast::error_code ec, + std::size_t bytes_transferred) + { + PLOG(logDEBUG) << "In FLIRWebSockAsyncClnSession::on_write " << std::endl; + boost::ignore_unused(bytes_transferred); + + if(ec) + return fail(ec, "write"); + + // Read a message into our buffer, + // this should be the response to the subscribe message + ws_.async_read( + buffer_, + beast::bind_front_handler( + &FLIRWebSockAsyncClnSession::on_read, + shared_from_this())); + } + + void + FLIRWebSockAsyncClnSession::on_read( + beast::error_code ec, + std::size_t bytes_transferred) + { + PLOG(logDEBUG) << "In FLIRWebSockAsyncClnSession::on_read " << std::endl; + boost::ignore_unused(bytes_transferred); + + if(ec) + return fail(ec, "read"); + + // parse the buffer + std::stringstream ss; + ptree pr; + std::string text(beast::buffers_to_string(buffer_.data())); + ss<(); + std::string time = ""; + std::string type = ""; + float angle = 0; + int alpha = 0; + std::string lat = ""; + std::string lon = ""; + float speed = 0; + std::string timeString = ""; + int id = 0; + std::string idResult; + + if (messageType.compare("Subscription") == 0) + { + std::string subscrStatus = pr.get_child("subscription").get_child("returnValue").get_value(); + PLOG(logDEBUG) << "Ped presence data subscription status: " << subscrStatus << std::endl; + + } + //Example received pedestrian tracking data + //{"dataNumber": "473085", "messageType": "Data", "time": "2022-04-20T15:25:51.001-04:00", + //"track": [{"angle": "263.00000000", "class": "Pedestrian", "iD": "15968646", "latitude": "38.95499217", + //"longitude": "-77.14920953", "speed": "1.41873741", "x": "0.09458912", "y": "14.80903757"}], "type": "PedestrianPresenceTracking"} + else if (messageType.compare("Data") == 0) + { + time = pr.get_child("time").get_value(); + type = pr.get_child("type").get_value(); + + PLOG(logINFO) << "Received " << type << " data at time: " << time << std::endl; + + if (type.compare("PedestrianPresenceTracking") == 0) + { + try + { + for (auto it: pr.get_child("track")) + { + + if (!it.second.get_child("angle").data().empty()) + { + //angle only reported in whole number increments, so int is fine + angle = std::stoi(it.second.get_child("angle").data()); + //convert camera reference frame angle + alpha = cameraRotation_ - angle - 270; + + if (alpha < 0) + { + alpha = (alpha % 360) + 360; + } + + //divide by 0.0125 for J2735 format + alpha /= 0.0125; + } + if (!it.second.get_child("iD").data().empty()) + { + id = std::stoi(it.second.get_child("iD").data()); + + //need to convert the id to 4 octet string + std::stringstream idstream; + idstream << std::hex << id; + std::string result(idstream.str()); + + idResult = result; + int str_length_diff = 8 - idResult.length(); + idResult.append(str_length_diff, '0'); + + } + if (!it.second.get_child("latitude").data().empty()) + { + //converting lat/lon to J2735 lat/lon format + lat = it.second.get_child("latitude").data(); + lat.erase(std::remove(lat.begin(), lat.end(), '.'), lat.end()); + lat.pop_back(); + } + if (!it.second.get_child("longitude").data().empty()) + { + //converting lat/lon to J2735 lat/lon format + lon = it.second.get_child("longitude").data(); + lon.erase(std::remove(lon.begin(), lon.end(), '.'), lon.end()); + lon.pop_back(); + } + if (!it.second.get_child("speed").data().empty()) + { + //speed from the FLIR camera is reported in m/s, need to convert to units of 0.02 m/s + speed = std::stof(it.second.get_child("speed").data()) / 0.02; + } + //need to parse out seconds from datetime string + std::vector dateTimeArr = timeStringParser(time); + + msgCount += 1; + if (msgCount > 127){ + msgCount = 0; + } + + PLOG(logINFO) << "Received FLIR camera data at: " << dateTimeArr[0] << "/" << dateTimeArr[1] << "/" << dateTimeArr[2] + << " " << dateTimeArr[3] << ":" << dateTimeArr[4] << ":" << dateTimeArr[5] << ":" << dateTimeArr[6] << std::endl; + + PLOG(logINFO) << "Received FLIR camera data for pedestrian " << idResult << " at location: (" << lat << ", " << lon << + ")" << ", travelling at speed: " << speed << ", with heading: " << alpha << " degrees" << std::endl; + + PLOG(logINFO) << "PSM message count: " << msgCount << std::endl; + + //constructing xml to send to BroadcastPSM function + char psm_xml_char[10000]; + snprintf(psm_xml_char,10000,"" + "%i%i%s%s%s" + "25525565535" + "%.0f%i%i%i" + "%i%i%i%i" + "000" + "001" + "", dateTimeArr[6], msgCount, idResult.c_str(), lat.c_str(), lon.c_str(), speed, alpha, dateTimeArr[0], dateTimeArr[1], + dateTimeArr[2], dateTimeArr[3], dateTimeArr[4], dateTimeArr[6]); + + std::string psm_xml_str(psm_xml_char, sizeof(psm_xml_char) / sizeof(psm_xml_char[0])); + + std::lock_guard lock(_psmLock); + psmxml = psm_xml_str; + + PLOG(logDEBUG) << "Sending PSM xml to BroadcastPsm: " << psmxml.c_str() < FLIRWebSockAsyncClnSession::timeStringParser(string dateTimeStr) const + { + std::string delimiter1 = "."; + std::string delimiter2 = "-"; + std::string delimiter3 = "T"; + std::string delimiter4 = ":"; + std::vector parsedArr; + + std::string year = dateTimeStr.substr(0, dateTimeStr.find(delimiter2)); + year.erase(0, std::min(year.find_first_not_of('0'), year.size()-1)); + dateTimeStr.erase(0, dateTimeStr.find(delimiter2) + delimiter2.length()); + + std::string month = dateTimeStr.substr(0, dateTimeStr.find(delimiter2)); + month.erase(0, std::min(month.find_first_not_of('0'), month.size()-1)); + dateTimeStr.erase(0, dateTimeStr.find(delimiter2) + delimiter2.length()); + + std::string day = dateTimeStr.substr(0, dateTimeStr.find(delimiter3)); + day.erase(0, std::min(day.find_first_not_of('0'), day.size()-1)); + dateTimeStr.erase(0, dateTimeStr.find(delimiter3) + delimiter3.length()); + + std::string hour = dateTimeStr.substr(0, dateTimeStr.find(delimiter4)); + hour.erase(0, std::min(hour.find_first_not_of('0'), hour.size()-1)); + dateTimeStr.erase(0, dateTimeStr.find(delimiter4) + delimiter4.length()); + + std::string mins = dateTimeStr.substr(0, dateTimeStr.find(delimiter4)); + mins.erase(0, std::min(mins.find_first_not_of('0'), mins.size()-1)); + dateTimeStr.erase(0, dateTimeStr.find(delimiter4) + delimiter4.length()); + + std::string sec = dateTimeStr.substr(0, dateTimeStr.find(delimiter1)); + sec.erase(0, std::min(sec.find_first_not_of('0'), sec.size()-1)); + dateTimeStr.erase(0, dateTimeStr.find(delimiter1) + delimiter1.length()); + + std::string milliseconds = dateTimeStr.substr(0, dateTimeStr.find(delimiter2)); + milliseconds.erase(0, std::min(milliseconds.find_first_not_of('0'), milliseconds.size()-1)); + + parsedArr.push_back(std::stoi(year)); + parsedArr.push_back(std::stoi(month)); + parsedArr.push_back(std::stoi(day)); + parsedArr.push_back(std::stoi(hour)); + parsedArr.push_back(std::stoi(mins)); + parsedArr.push_back(std::stoi(sec)); + parsedArr.push_back(std::stoi(milliseconds)); + + return parsedArr; + } + + +} \ No newline at end of file diff --git a/src/v2i-hub/PedestrianPlugin/src/PedestrianPlugin.cpp b/src/v2i-hub/PedestrianPlugin/src/PedestrianPlugin.cpp index ebae2742e..b2f0c71ca 100644 --- a/src/v2i-hub/PedestrianPlugin/src/PedestrianPlugin.cpp +++ b/src/v2i-hub/PedestrianPlugin/src/PedestrianPlugin.cpp @@ -8,6 +8,7 @@ #include "include/PedestrianPlugin.hpp" + namespace PedestrianPlugin { @@ -31,13 +32,48 @@ PedestrianPlugin::PedestrianPlugin(string name): PluginClient(name) // fire up the web service on a thread PROTECTION required std::lock_guard lock(_cfgLock); - GetConfigValue("WebServiceIP",webip); - GetConfigValue("WebServicePort",webport); + GetConfigValue("IPAddress",webip); + GetConfigValue("WebPort",webport); + GetConfigValue("DataProvider",dataprovider); + GetConfigValue("WebSocketHost",webSocketIP); + GetConfigValue("WebSocketPort",webSocketURLExt); + GetConfigValue("FLIRCameraRotation",cameraRotation); + + + PLOG(logDEBUG) << "Pedestrian data provider: "<< dataprovider.c_str() << std::endl; + + + PLOG(logDEBUG) << "Before creating websocket to: " << webSocketIP.c_str() << " on port: " << webSocketURLExt.c_str() << std::endl; + + if (dataprovider.compare("FLIR") == 0) + { + try + { + std::thread webthread(&PedestrianPlugin::StartWebSocket,this); + PLOG(logDEBUG) << "Thread started!!: " << std::endl; + + webthread.detach(); // wait for the thread to finish + std::thread xmlThread(&PedestrianPlugin::checkXML,this); + PLOG(logDEBUG) << "XML Thread started!!: " << std::endl; + + xmlThread.detach(); // wait for the thread to finish + + } + catch(const std::exception& e) + { + PLOG(logERROR) << "Error connecting to websocket: " << e.what() << std::endl; + } + + + } + else // default if PSM XML data consumed using the webservice implementation + { + std::thread webthread(&PedestrianPlugin::StartWebService,this); + webthread.detach(); // wait for the thread to finish + } - std::thread webthread(&PedestrianPlugin::StartWebService,this); - webthread.detach(); // wait for the thread to finish } @@ -63,6 +99,54 @@ void PedestrianPlugin::PedestrianRequestHandler(QHttpEngine::Socket *socket) } } +int PedestrianPlugin::StartWebSocket() +{ + PLOG(logDEBUG) << "In PedestrianPlugin::StartWebSocket " << std::endl; + // The io_context is required for all I/O + net::io_context ioc; + + flirSession = std::make_shared(ioc); + + // Launch the asynchronous operation + flirSession->run(webSocketIP.c_str(), webSocketURLExt.c_str(), cameraRotation); + + PLOG(logDEBUG) << "Successfully running the I/O service" << std::endl; + + // Run the I/O service. The call will return when + // the socket is closed. + ioc.run(); + + return EXIT_SUCCESS; +} + +int PedestrianPlugin::checkXML() +{ + //first xml will be empty string + std::string lastGeneratedXML = ""; + + //if a new psm xml has been generated the FLIR web socket, send it to the BroadcastPSM function + while (true) + { + if (flirSession == nullptr) + { + PLOG(logDEBUG) << "flir session not yet initialized: " << std::endl; + } + else + { + std::string currentXML = flirSession->getPSMXML(); + + if (currentXML.compare(lastGeneratedXML) != 0) + { + PLOG(logINFO) << "CheckXML: Broadcasting new CP PSM!" << std::endl; + + BroadcastPsm(const_cast(currentXML.c_str())); + lastGeneratedXML = currentXML; + } + } + + } + return EXIT_SUCCESS; +} int PedestrianPlugin::StartWebService() { @@ -110,8 +194,11 @@ void PedestrianPlugin::UpdateConfigSettings() GetConfigValue("WebServiceIP",webip); GetConfigValue("WebServicePort",webport); + GetConfigValue("WebSocketHost",webSocketIP); + GetConfigValue("WebSocketURLExt",webSocketURLExt); GetConfigValue("Instance", instance); - + GetConfigValue("DataProvider", dataprovider); + GetConfigValue("FLIRCameraRotation",cameraRotation); } @@ -137,8 +224,6 @@ void PedestrianPlugin::HandleMapDataMessage(MapDataMessage &msg, routeable_messa { static std::atomic count {0}; - PLOG(logINFO) << "New MAP: " << msg; - int mapCount = count; SetStatus("ReceivedMaps", mapCount); } @@ -156,39 +241,43 @@ void PedestrianPlugin::BroadcastPsm(char * psmJson) { //overloaded PsmMessage psmmessage; PsmEncodedMessage psmENC; tmx::message_container_type container; - std::unique_ptr msg; - - - std::stringstream ss; - ss << psmJson; - - container.load(ss); - psmmessage.set_contents(container.get_storage().get_tree()); - - const std::string psmString(psmJson); - psmENC.encode_j2735_message(psmmessage); + std::unique_ptr msg; + try + { + std::stringstream ss; + ss << psmJson; - msg.reset(); - msg.reset(dynamic_cast(factory.NewMessage(api::MSGSUBTYPE_PERSONALSAFETYMESSAGE_STRING))); + container.load(ss); + psmmessage.set_contents(container.get_storage().get_tree()); + const std::string psmString(psmJson); - string enc = psmENC.get_encoding(); - msg->refresh_timestamp(); - msg->set_payload(psmENC.get_payload_str()); - msg->set_encoding(enc); - msg->set_flags(IvpMsgFlags_RouteDSRC); - msg->addDsrcMetadata(172, 0x8002); - msg->refresh_timestamp(); + psmENC.encode_j2735_message(psmmessage); + msg.reset(); + msg.reset(dynamic_cast(factory.NewMessage(api::MSGSUBTYPE_PERSONALSAFETYMESSAGE_STRING))); + string enc = psmENC.get_encoding(); + msg->refresh_timestamp(); + msg->set_payload(psmENC.get_payload_str()); + msg->set_encoding(enc); + msg->set_flags(IvpMsgFlags_RouteDSRC); + msg->addDsrcMetadata(172, 0x8002); + msg->refresh_timestamp(); - routeable_message *rMsg = dynamic_cast(msg.get()); - BroadcastMessage(*rMsg); + routeable_message *rMsg = dynamic_cast(msg.get()); + BroadcastMessage(*rMsg); + PLOG(logINFO) << " Pedestrian Plugin :: Broadcast PSM:: " << psmENC.get_payload_str() << std::endl; + } + catch(const std::exception& e) + { + PLOG(logWARNING) << "Error: " << e.what() << " broadcasting PSM for xml: " << psmJson << std::endl; + } - PLOG(logINFO) << " Pedestrian Plugin :: Broadcast PSM:: " << psmENC.get_payload_str(); + } diff --git a/src/v2i-hub/PedestrianPlugin/src/include/FLIRWebSockAsyncClnSession.hpp b/src/v2i-hub/PedestrianPlugin/src/include/FLIRWebSockAsyncClnSession.hpp new file mode 100644 index 000000000..bd68b8c55 --- /dev/null +++ b/src/v2i-hub/PedestrianPlugin/src/include/FLIRWebSockAsyncClnSession.hpp @@ -0,0 +1,148 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +namespace beast = boost::beast; // from +namespace http = beast::http; // from +namespace websocket = beast::websocket; // from +namespace net = boost::asio; // from +namespace pt = boost::property_tree; // from +using tcp = boost::asio::ip::tcp; // from + +//------------------------------------------------------------------------------ + +namespace PedestrianPlugin +{ + // Sends a WebSocket message and prints the response + class FLIRWebSockAsyncClnSession : public std::enable_shared_from_this + { + tcp::resolver resolver_; + websocket::stream ws_; + beast::flat_buffer buffer_; + std::string host_; + std::string pedPresenceTrackingReq = std::string("{\"messageType\":\"Subscription\", \"subscription\":{ \"type\":\"Data\", \"action\":\"Subscribe\", \"inclusions\":[{\"type\":\"PedestrianPresenceTracking\"}]}}"); + float cameraRotation_; + std::string psmxml = ""; + std::mutex _psmLock; + int msgCount = 0; + public: + + // Resolver and socket require an io_context + explicit + FLIRWebSockAsyncClnSession(net::io_context& ioc) + : resolver_(net::make_strand(ioc)) + , ws_(net::make_strand(ioc)) + { + + }; + + /** + * @brief Reports a failure with any of the websocket functions below + * + * @param: the error code for the specific function + * @param: description of the error + */ + void + fail(beast::error_code ec, char const* what) const; + + /** + * @brief Start the asynchronous web socket connection to the camera. Each function will call the + * function below it. + * + * @param: ip address of camera to connect to + * @param: port to connect to + * @param: calculated camera rotation + */ + void + run( + char const* host, + char const* port, + float cameraRotation); + + /** + * @brief Lookup the domain name of the IP address from run function. + * + * @param: error code containing information describing resolve issue + * @param: result of domain name lookup + */ + void + on_resolve( + beast::error_code ec, + tcp::resolver::results_type results); + + /** + * @brief Configures websocket settings and initiates handshake + * + * @param: error code containing information describing connection issue + */ + void + on_connect(beast::error_code ec, tcp::resolver::results_type::endpoint_type ep); + + /** + * @brief Performs the websocket handshake and calls write function + * + * @param: error code containing information describing handshake issue + */ + void + on_handshake(beast::error_code ec); + + /** + * @brief Sends the subscription request json to the camera and calls read function for camera response + * + * @param: error code containing information describing issue with json send + * @param: the bytes of the json + */ + void + on_write( + beast::error_code ec, + std::size_t bytes_transferred); + + /** + * @brief Used to read in all messages from the camera and parse out desired fields + * + * @param: error code containing information describing issue with reading camera data + * @param: the bytes of the received camera data + */ + void + on_read( + beast::error_code ec, + std::size_t bytes_transferred); + + /** + * @brief Closes the websocket connection to the camera + * + * @param: error code containing information describing issue with closing websocket + */ + void + on_close(beast::error_code ec); + + /** + * @brief Get method for xml containing psm data + * + * @return std::string the psm xml + */ + std::string getPSMXML() const; + + /** + * @brief Parses the datetime string that the camera returns into a vector containing each component + * + * @param: datetime string from camera + * @return: vector with all components + */ + std::vector timeStringParser(std::string dateTimeStr) const; + }; +}; + diff --git a/src/v2i-hub/PedestrianPlugin/src/include/PedestrianPlugin.hpp b/src/v2i-hub/PedestrianPlugin/src/include/PedestrianPlugin.hpp index 6d0c688d6..a1a8c0e8a 100644 --- a/src/v2i-hub/PedestrianPlugin/src/include/PedestrianPlugin.hpp +++ b/src/v2i-hub/PedestrianPlugin/src/include/PedestrianPlugin.hpp @@ -5,7 +5,6 @@ // Copyright : Copyright (c) 2019 FHWA Saxton Transportation Operations Laboratory. All rights reserved. // Description : Pedestrian Plugin //========================================================================== - #include #include "PluginClient.h" @@ -25,6 +24,7 @@ #include #include "PedestrianPluginWorker.hpp" +#include "FLIRWebSockAsyncClnSession.hpp" #include @@ -66,7 +66,11 @@ class PedestrianPlugin: public PluginClient int Main(); uint16_t webport; std::string webip; - + std::string webSocketIP; + std::string webSocketURLExt; + std::string dataprovider; + float cameraRotation; + std::shared_ptr flirSession; protected: void UpdateConfigSettings(); @@ -83,14 +87,23 @@ class PedestrianPlugin: public PluginClient void PedestrianRequestHandler(QHttpEngine::Socket *socket); void writeResponse(int responseCode , QHttpEngine::Socket *socket); + int StartWebSocket(); + + void OnWebSocketConnected(); + void OnWebSocketDataReceived(QString message); + void OnWebSocketClosed(); + + int checkXML(); + private: tmx::utils::UdpClient *_signSimClient = NULL; J2735MessageFactory factory; - + }; std::mutex _cfgLock; }; + From d20299619dcef47d30b23b223acaf59c0bacfc93 Mon Sep 17 00:00:00 2001 From: saxtonlab2 Date: Wed, 18 May 2022 16:29:36 -0400 Subject: [PATCH 4/7] fix for multiple pedestrian handling --- .../src/FLIRWebSockAsyncClnSession.cpp | 7 ++++--- .../PedestrianPlugin/src/PedestrianPlugin.cpp | 19 +++++++++---------- .../include/FLIRWebSockAsyncClnSession.hpp | 8 +++++--- .../src/include/PedestrianPlugin.hpp | 1 + 4 files changed, 19 insertions(+), 16 deletions(-) diff --git a/src/v2i-hub/PedestrianPlugin/src/FLIRWebSockAsyncClnSession.cpp b/src/v2i-hub/PedestrianPlugin/src/FLIRWebSockAsyncClnSession.cpp index 7b821d952..eedb291ab 100644 --- a/src/v2i-hub/PedestrianPlugin/src/FLIRWebSockAsyncClnSession.cpp +++ b/src/v2i-hub/PedestrianPlugin/src/FLIRWebSockAsyncClnSession.cpp @@ -276,6 +276,7 @@ namespace PedestrianPlugin std::lock_guard lock(_psmLock); psmxml = psm_xml_str; + psmQueue.push(psmxml); PLOG(logDEBUG) << "Sending PSM xml to BroadcastPsm: " << psmxml.c_str() <& FLIRWebSockAsyncClnSession::getPSMQueue() { - return psmxml; + std::lock_guard lock(_psmLock); + return psmQueue; } vector FLIRWebSockAsyncClnSession::timeStringParser(string dateTimeStr) const diff --git a/src/v2i-hub/PedestrianPlugin/src/PedestrianPlugin.cpp b/src/v2i-hub/PedestrianPlugin/src/PedestrianPlugin.cpp index b2f0c71ca..26efbf5a1 100644 --- a/src/v2i-hub/PedestrianPlugin/src/PedestrianPlugin.cpp +++ b/src/v2i-hub/PedestrianPlugin/src/PedestrianPlugin.cpp @@ -132,16 +132,15 @@ int PedestrianPlugin::checkXML() PLOG(logDEBUG) << "flir session not yet initialized: " << std::endl; } else - { - std::string currentXML = flirSession->getPSMXML(); - - if (currentXML.compare(lastGeneratedXML) != 0) - { - PLOG(logINFO) << "CheckXML: Broadcasting new CP PSM!" << std::endl; - - BroadcastPsm(const_cast(currentXML.c_str())); - lastGeneratedXML = currentXML; - } + { + //retrieve the PSM queue and send each one to be broadcast, then pop + std::queue ¤tPSMQueue = flirSession->getPSMQueue(); + + for (int i = 0; i < currentPSMQueue.size(); i++) + { + BroadcastPsm(const_cast(currentPSMQueue.front().c_str())); + currentPSMQueue.pop(); + } } } diff --git a/src/v2i-hub/PedestrianPlugin/src/include/FLIRWebSockAsyncClnSession.hpp b/src/v2i-hub/PedestrianPlugin/src/include/FLIRWebSockAsyncClnSession.hpp index bd68b8c55..63c795a2e 100644 --- a/src/v2i-hub/PedestrianPlugin/src/include/FLIRWebSockAsyncClnSession.hpp +++ b/src/v2i-hub/PedestrianPlugin/src/include/FLIRWebSockAsyncClnSession.hpp @@ -14,6 +14,7 @@ #include #include #include +#include namespace beast = boost::beast; // from namespace http = beast::http; // from @@ -36,6 +37,7 @@ namespace PedestrianPlugin std::string pedPresenceTrackingReq = std::string("{\"messageType\":\"Subscription\", \"subscription\":{ \"type\":\"Data\", \"action\":\"Subscribe\", \"inclusions\":[{\"type\":\"PedestrianPresenceTracking\"}]}}"); float cameraRotation_; std::string psmxml = ""; + std::queue psmQueue; std::mutex _psmLock; int msgCount = 0; public: @@ -130,11 +132,11 @@ namespace PedestrianPlugin on_close(beast::error_code ec); /** - * @brief Get method for xml containing psm data + * @brief Get method for queue containing psm for all tracked pedestrians * - * @return std::string the psm xml + * @return std::queue the psm queue */ - std::string getPSMXML() const; + std::queue &getPSMQueue(); /** * @brief Parses the datetime string that the camera returns into a vector containing each component diff --git a/src/v2i-hub/PedestrianPlugin/src/include/PedestrianPlugin.hpp b/src/v2i-hub/PedestrianPlugin/src/include/PedestrianPlugin.hpp index a1a8c0e8a..7f8e7554e 100644 --- a/src/v2i-hub/PedestrianPlugin/src/include/PedestrianPlugin.hpp +++ b/src/v2i-hub/PedestrianPlugin/src/include/PedestrianPlugin.hpp @@ -43,6 +43,7 @@ #include #include #include +#include using namespace std; From 38f203416ad37e907cba0443dc2b078296b3ef05 Mon Sep 17 00:00:00 2001 From: abey-yoseph <59704440+abey-yoseph@users.noreply.github.com> Date: Thu, 19 May 2022 17:26:58 +0000 Subject: [PATCH 5/7] 374 multiple pedestrians fix (#378) * pass copy of queue instead of reference, clear queue in get * removing comment from timeStringParser description * small change to clear queue functionality --- .../src/FLIRWebSockAsyncClnSession.cpp | 16 ++++++++++++---- .../PedestrianPlugin/src/PedestrianPlugin.cpp | 17 ++++++++++------- .../src/include/FLIRWebSockAsyncClnSession.hpp | 8 +++++--- 3 files changed, 27 insertions(+), 14 deletions(-) diff --git a/src/v2i-hub/PedestrianPlugin/src/FLIRWebSockAsyncClnSession.cpp b/src/v2i-hub/PedestrianPlugin/src/FLIRWebSockAsyncClnSession.cpp index eedb291ab..1ab432dfc 100644 --- a/src/v2i-hub/PedestrianPlugin/src/FLIRWebSockAsyncClnSession.cpp +++ b/src/v2i-hub/PedestrianPlugin/src/FLIRWebSockAsyncClnSession.cpp @@ -318,10 +318,19 @@ namespace PedestrianPlugin std::cout << beast::make_printable(buffer_.data()) << std::endl; } - std::queue& FLIRWebSockAsyncClnSession::getPSMQueue() + std::queue FLIRWebSockAsyncClnSession::getPSMQueue() { std::lock_guard lock(_psmLock); - return psmQueue; + + //pass copy of the queue to Pedestrian Plugin + std::queue queueToPass = psmQueue; + + //empty the queue internally + std::queue empty; + std::swap(psmQueue, empty); + + return queueToPass; + } vector FLIRWebSockAsyncClnSession::timeStringParser(string dateTimeStr) const @@ -368,7 +377,6 @@ namespace PedestrianPlugin parsedArr.push_back(std::stoi(milliseconds)); return parsedArr; - } - + } } \ No newline at end of file diff --git a/src/v2i-hub/PedestrianPlugin/src/PedestrianPlugin.cpp b/src/v2i-hub/PedestrianPlugin/src/PedestrianPlugin.cpp index 26efbf5a1..eb257c29b 100644 --- a/src/v2i-hub/PedestrianPlugin/src/PedestrianPlugin.cpp +++ b/src/v2i-hub/PedestrianPlugin/src/PedestrianPlugin.cpp @@ -134,13 +134,16 @@ int PedestrianPlugin::checkXML() else { //retrieve the PSM queue and send each one to be broadcast, then pop - std::queue ¤tPSMQueue = flirSession->getPSMQueue(); - - for (int i = 0; i < currentPSMQueue.size(); i++) - { - BroadcastPsm(const_cast(currentPSMQueue.front().c_str())); - currentPSMQueue.pop(); - } + std::queue currentPSMQueue = flirSession->getPSMQueue(); + + if (currentPSMQueue.size() > 0) + { + for (int i = 0; i < currentPSMQueue.size(); i++) + { + BroadcastPsm(const_cast(currentPSMQueue.front().c_str())); + currentPSMQueue.pop(); + } + } } } diff --git a/src/v2i-hub/PedestrianPlugin/src/include/FLIRWebSockAsyncClnSession.hpp b/src/v2i-hub/PedestrianPlugin/src/include/FLIRWebSockAsyncClnSession.hpp index 63c795a2e..41448e3af 100644 --- a/src/v2i-hub/PedestrianPlugin/src/include/FLIRWebSockAsyncClnSession.hpp +++ b/src/v2i-hub/PedestrianPlugin/src/include/FLIRWebSockAsyncClnSession.hpp @@ -132,11 +132,12 @@ namespace PedestrianPlugin on_close(beast::error_code ec); /** - * @brief Get method for queue containing psm for all tracked pedestrians + * @brief Get method for queue containing psm for all tracked pedestrians. Copies the queue into + * a temporary queue and returns temporary queue. Clears the original queue. * * @return std::queue the psm queue */ - std::queue &getPSMQueue(); + std::queue getPSMQueue(); /** * @brief Parses the datetime string that the camera returns into a vector containing each component @@ -145,6 +146,7 @@ namespace PedestrianPlugin * @return: vector with all components */ std::vector timeStringParser(std::string dateTimeStr) const; - }; + }; + }; From ca393f1df4a6138e8f5dc1c71afa59e991f073f7 Mon Sep 17 00:00:00 2001 From: abey-yoseph <59704440+abey-yoseph@users.noreply.github.com> Date: Mon, 6 Jun 2022 14:28:16 +0000 Subject: [PATCH 6/7] fix second field in generated PSM (#384) * fix second field in generated PSM * code smell fix for broadcast psm functionality --- .../src/FLIRWebSockAsyncClnSession.cpp | 5 +++-- .../PedestrianPlugin/src/PedestrianPlugin.cpp | 13 ++++++------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/v2i-hub/PedestrianPlugin/src/FLIRWebSockAsyncClnSession.cpp b/src/v2i-hub/PedestrianPlugin/src/FLIRWebSockAsyncClnSession.cpp index 1ab432dfc..afebbca1f 100644 --- a/src/v2i-hub/PedestrianPlugin/src/FLIRWebSockAsyncClnSession.cpp +++ b/src/v2i-hub/PedestrianPlugin/src/FLIRWebSockAsyncClnSession.cpp @@ -367,14 +367,15 @@ namespace PedestrianPlugin std::string milliseconds = dateTimeStr.substr(0, dateTimeStr.find(delimiter2)); milliseconds.erase(0, std::min(milliseconds.find_first_not_of('0'), milliseconds.size()-1)); - + + int millisecondsTotal = (std::stoi(sec) * 1000) + std::stoi(milliseconds); parsedArr.push_back(std::stoi(year)); parsedArr.push_back(std::stoi(month)); parsedArr.push_back(std::stoi(day)); parsedArr.push_back(std::stoi(hour)); parsedArr.push_back(std::stoi(mins)); parsedArr.push_back(std::stoi(sec)); - parsedArr.push_back(std::stoi(milliseconds)); + parsedArr.push_back(millisecondsTotal); return parsedArr; } diff --git a/src/v2i-hub/PedestrianPlugin/src/PedestrianPlugin.cpp b/src/v2i-hub/PedestrianPlugin/src/PedestrianPlugin.cpp index eb257c29b..ee1a6330e 100644 --- a/src/v2i-hub/PedestrianPlugin/src/PedestrianPlugin.cpp +++ b/src/v2i-hub/PedestrianPlugin/src/PedestrianPlugin.cpp @@ -136,13 +136,12 @@ int PedestrianPlugin::checkXML() //retrieve the PSM queue and send each one to be broadcast, then pop std::queue currentPSMQueue = flirSession->getPSMQueue(); - if (currentPSMQueue.size() > 0) - { - for (int i = 0; i < currentPSMQueue.size(); i++) - { - BroadcastPsm(const_cast(currentPSMQueue.front().c_str())); - currentPSMQueue.pop(); - } + while(!currentPSMQueue.empty()) + { + char* char_arr = ¤tPSMQueue.front()[0]; + + BroadcastPsm(char_arr); + currentPSMQueue.pop(); } } From 16bb40a06e5a5406162982db311f20bbebefcfa9 Mon Sep 17 00:00:00 2001 From: paulbourelly999 <77466294+paulbourelly999@users.noreply.github.com> Date: Tue, 14 Jun 2022 10:11:40 -0400 Subject: [PATCH 7/7] Updated release notes and docker-compose files (#385) * Updated release notes and docker-compose files * Updated Release Notes --- configuration/amd64/docker-compose.yml | 6 +++--- configuration/arm64/docker-compose.yml | 6 +++--- docs/Release_notes.md | 8 ++++++++ 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/configuration/amd64/docker-compose.yml b/configuration/amd64/docker-compose.yml index ab2b4f489..0583520ef 100755 --- a/configuration/amd64/docker-compose.yml +++ b/configuration/amd64/docker-compose.yml @@ -19,7 +19,7 @@ services: - ./mysql/port_drayage.sql:/docker-entrypoint-initdb.d/port_drayage.sql php: - image: usdotfhwaops/php:7.2.2 + image: usdotfhwaops/php:7.3.0 container_name: php network_mode: host depends_on: @@ -29,7 +29,7 @@ services: tty: true v2xhub: - image: usdotfhwaops/v2xhubamd:7.2.2 + image: usdotfhwaops/v2xhubamd:7.3.0 container_name: v2xhub network_mode: host restart: always @@ -43,7 +43,7 @@ services: - ./logs:/var/log/tmx - ./MAP:/var/www/plugins/MAP port_drayage_webservice: - image: usdotfhwaops/port-drayage-webservice:7.2.2 + image: usdotfhwaops/port-drayage-webservice:7.3.0 container_name: port_drayage_webservice network_mode: host secrets: diff --git a/configuration/arm64/docker-compose.yml b/configuration/arm64/docker-compose.yml index d614cf150..8b208bba8 100644 --- a/configuration/arm64/docker-compose.yml +++ b/configuration/arm64/docker-compose.yml @@ -19,7 +19,7 @@ services: - ./mysql/port_drayage.sql:/docker-entrypoint-initdb.d/port_drayage.sql php: - image: usdotfhwaops/php_arm:7.2.2 + image: usdotfhwaops/php_arm:7.3.0 container_name: php network_mode: host depends_on: @@ -29,7 +29,7 @@ services: tty: true v2xhub: - image: usdotfhwaops/v2xhubarm:7.2.2 + image: usdotfhwaops/v2xhubarm:7.3.0 container_name: v2xhub network_mode: host restart: always @@ -43,7 +43,7 @@ services: - ./logs:/var/log/tmx - ./MAP:/var/www/plugins/MAP port_drayage_webservice: - image: usdotfhwaops/port-drayage-webservice_arm:7.2.2 + image: usdotfhwaops/port-drayage-webservice_arm:7.3.0 container_name: port_drayage_webservice network_mode: host secrets: diff --git a/docs/Release_notes.md b/docs/Release_notes.md index f2d87f99a..050bf9cc3 100644 --- a/docs/Release_notes.md +++ b/docs/Release_notes.md @@ -1,4 +1,12 @@ V2X-Hub Release Notes +--------------------------------- +Version 7.3.0, released June 14th, 2022 +-------------------------------------------------------- +**Summary:** +V2X Hub release 7.3.0 includes added functionality for subscribing to FLIR camera for Pedestrian tracking and PSM broadcast to vehicles in the Pedestrian Plugin. The new FLIR functionality subscribes to the websocket output of the FLIR tracking feed and will generate a PSM for each new track the camera picks up. To use new FLIR websocket data, set `DataProvider` for the PedestrianPlugin to FLIR and configure the `WebSocketHost` and `WebSocketPort` for the FLIR camera. Additional you must set the `FLIRCameraRotation` in degrees, which is a measure of the camera's rotation from true north. To use the REST PedestrianPlugin functionality simply set the `DataProvider` to PSM. + +Enhancements in this release: + - Issue 345: Added Websocket client to consume FLIR data and publish PSM ---------------------------- Version 7.2.2, released May 9th, 2022 --------------------------------------------------------