Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Telematic bridge nats #567

Merged
merged 50 commits into from
Nov 30, 2023
Merged

Telematic bridge nats #567

merged 50 commits into from
Nov 30, 2023

Conversation

dan-du-car
Copy link
Collaborator

@dan-du-car dan-du-car commented Nov 22, 2023

PR Details

Description

This is the implementation story for the telematic bridge to stream J2735 data from V2xHub into the cloud at near real time. The module design refers to https://usdot-carma.atlassian.net/wiki/spaces/WFD2/pages/2640379977/V2xHub+WFD+Bridge+Design The following functionalities should be implemented for this module:

Able to forward the JSON message to telematic cloud when the message type is requested by end users through telematic UI.

Able to register itself with WFD cloud services.

Able to map each TMX message type to each individual topic.  

Able to provide available topics to telematic cloud.

Able to stream the requested TMX message in JSON format to telematic cloud.

Related Issue

#591
WDF-447

Motivation and Context

Telematic tool data collection

How Has This Been Tested?

Unit test and local integration testing

Types of changes

  • Defect fix (non-breaking change that fixes an issue)
  • New feature (non-breaking change that adds functionality)
  • Breaking change (fix or feature that cause existing functionality to change)

Checklist:

  • I have added any new packages to the sonar-scanner.properties file
  • My change requires a change to the documentation.
  • I have updated the documentation accordingly.
  • I have read the CONTRIBUTING document.
    V2XHUB Contributing Guide
  • I have added tests to cover my changes.
  • All new and existing tests passed.

},
{
"key": "UnitId",
"default": "v2xhub_id",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We are currently, in CDASim pulling and infrastructure ID from an environment variable. You may want to do the same here. See CDASimAdapter

Copy link
Collaborator Author

@dan-du-car dan-du-car Nov 28, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not the same concept as the infrastructure id. It is a unique identifier we give to a telematic unit to distinguish it from other units like streets and vehicle. Is there any rule when to use the UI configuration parameter and when to use the environment variables? All these parameters make sense when they are together.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, so part of the UC for this plugin is to disable health of different RSUs, and therefore infrastructure instances. Coming up with and ID that is completely different from the J2735 intersection ID and our infrastructure ID I think is bad practice. Then we will have 3 different IDs for the same instance, all which are completely indepedent.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this unit id value can be anything that makes sense to end user during their testing with v2xhub as long as it is unique in the telematic tool.

Copy link
Contributor

@paulbourelly999 paulbourelly999 Nov 29, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So then why don't we just re-use INFRASTRUCTURE ID here? The same environment variable we use for CDASimAdapter.

Copy link
Collaborator Author

@dan-du-car dan-du-car Nov 29, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the value of the infrastructure id? We also display this ID in the UI. Does it make sense to end users to use infrastructure id like 1079? Or use a more descriptive unit id, like east_intersection_1079 or v2xhub_1079?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Something like <rsu_21312>. We have not standardized this yet but I think if we say it has to be rsu_ then maybe we can minimize different ID

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The unit id is under the telematic tool context. They may share the same value. For debugging and ease of usability purpose, it might be more obvious if we keep both unit name and unit id in the same place like here on the V2xHub UI.

},
{
"key": "UnitType",
"default": "Infrastructure",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure about this field.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed e867876

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

UnitType does not make sense as a configurable parameter if it is sent to infrastructre. Every V2X-Hub falls under infrastructure. Maybe if we have types like intersection or highway it would make sense but like this is does not make sense.

Copy link
Collaborator Author

@dan-du-car dan-du-car Nov 29, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a category defined by telematic tool. It only has two categories platform and infrastructure. Carma-streets, carma-cloud, and v2xhub belong to infrastructure.

Copy link
Contributor

@paulbourelly999 paulbourelly999 Nov 29, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So then lets make this a constant and not configurable since there is no scenario in which we would have V2X-Hub have any other type.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed d5998cf

"description": "The log level for this plugin"
},
{
"key": "TopicExclusionList",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are not topics but messages

Copy link
Collaborator Author

@dan-du-car dan-du-car Nov 28, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The topic name consist of type_subtype_source. We create a topic for each message because v2xhub does not have a topic. For telematic users to select topics, we come up with this combination for each type of message.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So topics is not a familiar term for users of V2X-HUb. If we are making a connection between topics and message in telematics, I would recommend we use "message" to refer to the messages we are listening to in V2X-Hub and "topic" as the term of the topics we will create on telematics.

I suggest we call this messages here and the term topics is only used to send information to telematics about topics to create and in the telematics UI/Software.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed 71ac033

@@ -0,0 +1,94 @@
## NATS Publisher/Subscriber
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we make this file called README.md instead of readme.md

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@@ -4,6 +4,8 @@ namespace TelematicBridge
{
TelematicBridgePlugin::TelematicBridgePlugin(const string &name) : PluginClient(name)
{
_telematicUnitPtr = make_shared<TelematicUnit>();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can this be a unique pt?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a reason for this change?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it is best practice to limit pointer scope or reference scope where possible to avoid other users possibly unintentionally impacting the lifecycle of this pointer by holding a reference.

Copy link
Collaborator Author

@dan-du-car dan-du-car Nov 29, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This point is shared with this plugin. I cannot find a case where users will accidentally change the lifecycle of this pointer. This pointer should be sharing the same lifecycle of the plugin itself.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the plugin has a reference to this object but the telematics bridge is no longer in scope, the telematics bridge will still not get deleted because the plugin holds a reference to this pointer which will prevent the pointer from getting deleted

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why does the plugin need a reference to this pointer?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So that the plugin can use this pointer to send data into the telematic tool. It does not make sense for this plugin to subscribe messages but not forward them into the telematic tool.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

static CONSTEXPR const char *TOPIC_NAME = "topic_name"; // topic_name key used to find topic_name value from JSON
static CONSTEXPR const char *TIMESTAMP = "timestamp"; // timestamp key used to find timestamp value from JSON
static CONSTEXPR const char *PAYLOAD = "payload"; // payload key used to find payload value from JSON
static CONSTEXPR const char *TOPICS = "topics"; // topics key used to find topics value from JSON
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are not topics, I would refrain from using this language unless telematics requires it.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can change the variable name "TOPICS". We do need the value topics to find JSON value that match this topics key.

@@ -0,0 +1,94 @@
## NATS Publisher/Subscriber
### NATS Connections and registration
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

REAME file is misspelled

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed 71ac033

@@ -0,0 +1,94 @@
## NATS Publisher/Subscriber
### NATS Connections and registration
#### Telematic plugin sends registration request to telematic server
Copy link
Contributor

@paulbourelly999 paulbourelly999 Nov 29, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please update to include an overall plugin functional/usage description

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed 71ac033

@@ -3,21 +3,30 @@

#include "PluginClient.h"
#include "TelematicBridgeMsgWorker.h"
#include "TelematicUnit.h"

using namespace tmx::utils;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using namespace is bad practice especially in header files.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed 71ac033

}
else
{
throw TelematicBridgeException(natsStatus_GetText(s));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do this while loop and throw and exception. If the registration fails you throw an exception so the loop is exited. If you are successful the loop is exited. Is there any condition in which you will retry. Only if NAT_OK and the validateRegisterStatus fails? In which situation would this occur.
\

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only if we get an invalid registration reply json from telematics?

Copy link
Collaborator Author

@dan-du-car dan-du-car Nov 29, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The server can return response without an event information. In this case, this bridge continues to attempt to register. It throw error when NATS_OK check fails. This usually because the server is down.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the response without event information also a bug or error behavior or would reattempts ever fix that. Also do we want to limit connection attempts on invalid responses?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is neither of them. It requires user attention to double check the event and its assigned unit.

Copy link
Collaborator Author

@dan-du-car dan-du-car Nov 29, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we want to wait for the valid response, otherwise there is no point keeping this plugin running.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So if user input is required to make a valid response, then we should indicate to the user that something is wrong instead of silently indefinitely and continuously retrying a connection that has an issue that a user must resolve.

To me either we do a single register attempt and fail or succeed and notify the user on fails, or we have a loop that attempts the connection some finite amount of times before failing. To me reattempts on connections should ideally be used for connection issues that do not require user input to be resolved, like if the server is restarting or if there are network temporary issues.

Copy link
Contributor

@paulbourelly999 paulbourelly999 Nov 29, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the concern here is uptime of the resulting plugin, maybe this registration logic needs to be more complex and have some kind of failure recovery logic but this does not seem to me to satisfy that requirement

@paulbourelly999 Addressed 040a99b

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

message[LOCATION_KEY] = eventLocation;
message[TESTING_TYPE_KEY] = testingType;
message[EVENT_NAME_KEY] = eventName;
message[TIMESTAMP_KEY] = duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you do not extend PluginClientClockAware and use the carma-clock object this plugin will not support simulation.

Copy link
Collaborator Author

@dan-du-car dan-du-car Nov 29, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That is a different case. We will evaluate and address this later when we integrate this with simulation.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that is fine for now, but for future reference, every new plugin created should extend PluginClientClockAware. It is no additional work and it avoids having to integrated with simulation in the future.

},
{
"key": "UnitName",
"default": "East Intersection",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can this match J2735 intersection name or does it need to be separate. If it can match I suggest we just add in the description to set this to intersection name

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed 1c59a3e

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please specify J2735 MAP in the description. So should be set to MAP J2735 intersection name if available.

Copy link
Collaborator Author

@dan-du-car dan-du-car Nov 29, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not specific about MAP message nor intersection. If we deploy this v2xhub in Cav-in-a-box at roadside, there is no concept of intersection. This east intersection is just a default value I give cause I test it with east intersection.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know this is not MAP Message specific from an implementation stand point but we should not be creating unnecessary new IDs in our different pieces of functionality. For example INFRASTRUCTURE_ID is a unique string used for registration for simulation but if we can reuse the ID for say telematics or if we could relate that ID to the unique J2735 Intersection ID we decrease the number of separately managed ID parameters. This way they all relate to each other.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we table this for now? The unit id is something we used in the telematic tool context. The same design for this unit id is applied to carma-streets, carma-platform (vehicle), and carma-cloud. If this has some conflicts with IDs in a simulated environment, we probably want to decide and make the changes to all units to better fit the simulated environment.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we have unique IDs for carma streets, carma-cloud , carma-platform as well to register for the simulation?

Copy link
Contributor

@paulbourelly999 paulbourelly999 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Left some more comments do be address

},
{
"key": "UnitName",
"default": "East Intersection",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please specify J2735 MAP in the description. So should be set to MAP J2735 intersection name if available.

@@ -4,6 +4,8 @@ namespace TelematicBridge
{
TelematicBridgePlugin::TelematicBridgePlugin(const string &name) : PluginClient(name)
{
_telematicUnitPtr = make_shared<TelematicUnit>();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the plugin has a reference to this object but the telematics bridge is no longer in scope, the telematics bridge will still not get deleted because the plugin holds a reference to this pointer which will prevent the pointer from getting deleted

@@ -4,6 +4,8 @@ namespace TelematicBridge
{
TelematicBridgePlugin::TelematicBridgePlugin(const string &name) : PluginClient(name)
{
_telematicUnitPtr = make_shared<TelematicUnit>();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why does the plugin need a reference to this pointer?

}
else
{
throw TelematicBridgeException(natsStatus_GetText(s));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So if user input is required to make a valid response, then we should indicate to the user that something is wrong instead of silently indefinitely and continuously retrying a connection that has an issue that a user must resolve.

To me either we do a single register attempt and fail or succeed and notify the user on fails, or we have a loop that attempts the connection some finite amount of times before failing. To me reattempts on connections should ideally be used for connection issues that do not require user input to be resolved, like if the server is restarting or if there are network temporary issues.

}
else
{
throw TelematicBridgeException(natsStatus_GetText(s));
Copy link
Contributor

@paulbourelly999 paulbourelly999 Nov 29, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the concern here is uptime of the resulting plugin, maybe this registration logic needs to be more complex and have some kind of failure recovery logic but this does not seem to me to satisfy that requirement

@paulbourelly999 Addressed 040a99b

@paulbourelly999 paulbourelly999 merged commit 6b604b7 into develop Nov 30, 2023
9 checks passed
@paulbourelly999 paulbourelly999 deleted the telematic_bridge_nats branch November 30, 2023 19:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants