eclipse-cyclonedds / cyclonedds

Eclipse Cyclone DDS project
https://projects.eclipse.org/projects/iot.cyclonedds
Other
891 stars 363 forks source link

Checking handshake of a "topic" in a network? #2079

Closed kumar-gaurav-harman closed 2 months ago

kumar-gaurav-harman commented 3 months ago

Setup which I have:

Topic: "A_"

A window machine:

A Linux Machine:

Now problem is topic itself is not received by the window machine setup which we want to debug. In C implementation, we have idl defined under certain module, But In python, we can directly define a IDL class. Because of this reason, C implementation and Python Implementation end up having different names for the same IDL. Initially, we thought this could be a reason. But In case, publishing part is happening in python implementation and Listening part is happening in c implementation, we are able to see the messages getting exchanged. Therefore, IDL naming issue may not be the reason.

Note: We have same set of QoS and domain ID defined in both implementations.

Are we missing something here? Need guidance.

Here is code snippet of IDL:

C implementation

IDL:

module dds_data_types
{
struct 3D_
  {
    float x;
    float y;
    float z;
  };
}

Generated header:

typedef struct dds_data_types_3D_
{
  float x;
  float y;
  float z;
} dds_data_types_3D_;

Python implementation:

@dataclass
class 3D_(IdlStruct):
    x: float32
    y: float32
    z: float32
eboasson commented 3 months ago

If it does works in one direction and it doesn't work in the other direction, then my first suggestion would be the check the QoS because of the QoS matching rules in DDS (if the Python one uses a "stronger" QoS set than the C one, then you can write from Python to C, but not from C to Python). The trouble with that is of course:

Note: We have same set of QoS and domain ID defined in both implementations.

Still, it is easy to make a mistake and it would be good double-check it with, e.g., insight (binary). Otherwise, we're probably in the territory of getting a trace, by setting CYCLONEDDS_URI='<Tracing><Category>trace</Category><OutputFile>cdds.log.${CYCLONEDDS_PID}</OutputFile></Tracing>'. It is a bit painful to go that way if you don't have to ...

In C implementation, we have idl defined under certain module, But In python, we can directly define a IDL class. Because of this reason, C implementation and Python Implementation end up having different names for the same IDL.

The discovery data always includes a type name, but the DDS XTypes spec extended that by also adding a hash of the type definition. If the latter is available, it will ignore the name and compare the definitions instead. If the hashes are different, there'll type discovery work under the hood to get the other side's definition and then it actually compares the types. That's why it works đŸ™‚

(Technically, this one-way-traffic problem can also be introduced in the type checking. It doesn't check whether they are the same but whether they are "assignable". But your definitions are identical, and so I don't see how that could be an issue.)

That said ... I think it really is a very neat feature of our Python binding that you can do it this way, and it is ideal for all-Python things, testing, quick scripting, you name it. But if you have a larger system with C/C++ and Python components, then it probably makes more sense to use the IDL you wrote for the C code and pre-process it twice, once outputting C, and once outputting Python (with idlc -lpy). The generated Python code will be just like what you wrote by hand.

kumar-gaurav-harman commented 2 months ago

That said ... I think it really is a very neat feature of our Python binding that you can do it this way, and it is ideal for all-Python things, testing, quick scripting, you name it. But if you have a larger system with C/C++ and Python components, then it probably makes more sense to use the IDL you wrote for the C code and pre-process it twice, once outputting C, and once outputting Python (with idlc -lpy). The generated Python code will be just like what you wrote by hand.

==> Thanks for the command, sometimes we miss/ignore tiny details.

If it does works in one direction and it doesn't work in the other direction, then my first suggestion would be the check the QoS because of the QoS matching rules in DDS (if the Python one uses a "stronger" QoS set than the C one, then you can write from Python to C, but not from C to Python). The trouble with that is of course:

Yes, the issue was with QoS only. I'll add code snippet for other visitors.

Python side:

python
qos = Qos(Policy.Reliability.Reliable(duration(microseconds = 60)),
                  Policy.Deadline(duration(microseconds = 10)),
                  Policy.Durability.TransientLocal,
                  Policy.History.KeepLast(1))
c
dds_qos_t *qos = dds_create_qos();
    dds_qset_reliability(qos, DDS_RELIABILITY_RELIABLE, DDS_SECS(0.06));
    dds_qset_deadline(qos, DDS_SECS(0.01));
    dds_qset_durability(qos, DDS_DURABILITY_TRANSIENT_LOCAL);
    dds_qset_history(qos, DDS_HISTORY_KEEP_LAST, 1);

Value-wise both properties DDS_RELIABILITY_RELIABLE and dds_qset_deadline are holding same values. However, C code is not using microseconds macro which is DDS_SECS, it should use DDS_USECS instead to match with python implementation. By using right MACRO, it worked without any issue.

Thank you for your input btw.