1
0
Fork 0

Add a new network protocol: dds-props which for now only operates in the output mode: request a propery value using de FG_DDS_prop scheme and provide either it's path or property index id. UsageL fgfs --dds-props=dds,out,<hz>. Testing is possible with src/Network/DDS/fg_dds_prop to request a propery path/id or src/Network/DDS/fg_dds_log to log all propery samples passed over the DDS layer.

This commit is contained in:
Erik Hofman 2021-04-16 11:26:21 +02:00
parent 1aeef58ded
commit 5118009d44
10 changed files with 81 additions and 56 deletions

View file

@ -55,6 +55,7 @@
#include <Network/native_ctrls.hxx> #include <Network/native_ctrls.hxx>
#include <Network/native_fdm.hxx> #include <Network/native_fdm.hxx>
#include <Network/native_gui.hxx> #include <Network/native_gui.hxx>
#include <Network/dds_props.hxx>
#include <Network/opengc.hxx> #include <Network/opengc.hxx>
#include <Network/nmea.hxx> #include <Network/nmea.hxx>
#include <Network/props.hxx> #include <Network/props.hxx>
@ -155,6 +156,10 @@ FGIO::parse_port_config( const string_list& tokens, bool& o_ok )
io = new FGNativeGUI; io = new FGNativeGUI;
} else if ( protocol == "nmea" ) { } else if ( protocol == "nmea" ) {
io = new FGNMEA(); io = new FGNMEA();
#if FG_HAVE_DDS
} else if ( protocol == "dds-props") {
io = new FGDDSProps;
#endif
} else if ( protocol == "props" || protocol == "telnet" ) { } else if ( protocol == "props" || protocol == "telnet" ) {
io = new FGProps( tokens ); io = new FGProps( tokens );
o_ok = true; o_ok = true;
@ -233,7 +238,13 @@ FGIO::parse_port_config( const string_list& tokens, bool& o_ok )
if (tokens.size() < 4) { if (tokens.size() < 4) {
SG_LOG( SG_IO, SG_ALERT, "Too few arguments for network protocol. At least 3 arguments required. " << SG_LOG( SG_IO, SG_ALERT, "Too few arguments for network protocol. At least 3 arguments required. " <<
"Usage: --" << protocol << "=(file|socket|serial), (in|out|bi), hertz"); "Usage: --" << protocol <<
#if FG_HAVE_DDS
"=(file|socket|serial|dds)" <<
#else
"=(file|socket|serial)" <<
#endif
", (in|out|bi), hertz");
delete io; delete io;
return NULL; return NULL;
} }

View file

@ -1929,6 +1929,7 @@ struct OptionDesc {
{"native-ctrls", true, OPTION_CHANNEL | OPTION_MULTI, "", false, "", 0 }, {"native-ctrls", true, OPTION_CHANNEL | OPTION_MULTI, "", false, "", 0 },
{"native-fdm", true, OPTION_CHANNEL | OPTION_MULTI, "", false, "", 0 }, {"native-fdm", true, OPTION_CHANNEL | OPTION_MULTI, "", false, "", 0 },
{"native-gui", true, OPTION_CHANNEL | OPTION_MULTI, "", false, "", 0 }, {"native-gui", true, OPTION_CHANNEL | OPTION_MULTI, "", false, "", 0 },
{"dds-props", true, OPTION_CHANNEL | OPTION_MULTI, "", false, "", 0 },
{"opengc", true, OPTION_CHANNEL | OPTION_MULTI, "", false, "", 0 }, {"opengc", true, OPTION_CHANNEL | OPTION_MULTI, "", false, "", 0 },
{"AV400", true, OPTION_CHANNEL | OPTION_MULTI, "", false, "", 0 }, {"AV400", true, OPTION_CHANNEL | OPTION_MULTI, "", false, "", 0 },
{"AV400Sim", true, OPTION_CHANNEL | OPTION_MULTI, "", false, "", 0 }, {"AV400Sim", true, OPTION_CHANNEL | OPTION_MULTI, "", false, "", 0 },

View file

@ -63,8 +63,13 @@ set(HEADERS
) )
if (CycloneDDS_FOUND) if (CycloneDDS_FOUND)
set(SOURCES ${SOURCES} dds_props.cxx) list(APPEND SOURCES
set(HEADERS ${HEADERS} dds_props.hxx) dds_props.cxx
)
list(APPEND HEADERS
dds_props.hxx
)
endif() endif()
if(ENABLE_IAX) if(ENABLE_IAX)

View file

@ -9,39 +9,39 @@
#include "dds_props.h" #include "dds_props.h"
static const dds_key_descriptor_t FG_DDS_PROP_keys[1] = static const dds_key_descriptor_t FG_DDS_prop_keys[1] =
{ {
{ "id", 0 } { "id", 0 }
}; };
static const uint32_t FG_DDS_PROP_ops [] = static const uint32_t FG_DDS_prop_ops [] =
{ {
DDS_OP_ADR | DDS_OP_TYPE_4BY | DDS_OP_FLAG_SGN | DDS_OP_FLAG_KEY, offsetof (FG_DDS_PROP, id), DDS_OP_ADR | DDS_OP_TYPE_4BY | DDS_OP_FLAG_SGN | DDS_OP_FLAG_KEY, offsetof (FG_DDS_prop, id),
DDS_OP_ADR | DDS_OP_TYPE_1BY, offsetof (FG_DDS_PROP, version), DDS_OP_ADR | DDS_OP_TYPE_1BY, offsetof (FG_DDS_prop, version),
DDS_OP_ADR | DDS_OP_TYPE_BOO, offsetof (FG_DDS_PROP, mode), DDS_OP_ADR | DDS_OP_TYPE_BOO, offsetof (FG_DDS_prop, mode),
DDS_OP_ADR | DDS_OP_TYPE_UNI | DDS_OP_SUBTYPE_4BY | DDS_OP_FLAG_SGN, offsetof (FG_DDS_PROP, val._d), 9u, (31u << 16) + 4u, DDS_OP_ADR | DDS_OP_TYPE_UNI | DDS_OP_SUBTYPE_4BY | DDS_OP_FLAG_SGN, offsetof (FG_DDS_prop, val._d), 9u, (31u << 16) + 4u,
DDS_OP_JEQ | DDS_OP_TYPE_BOO | 0, FG_DDS_BOOL, offsetof (FG_DDS_PROP, val._u.Bool), DDS_OP_JEQ | DDS_OP_TYPE_BOO | 0, FG_DDS_BOOL, offsetof (FG_DDS_prop, val._u.Bool),
DDS_OP_JEQ | DDS_OP_TYPE_4BY | DDS_OP_FLAG_SGN | 0, FG_DDS_NONE, offsetof (FG_DDS_PROP, val._u.Int32), DDS_OP_JEQ | DDS_OP_TYPE_4BY | DDS_OP_FLAG_SGN | 0, FG_DDS_NONE, offsetof (FG_DDS_prop, val._u.Int32),
DDS_OP_JEQ | DDS_OP_TYPE_4BY | DDS_OP_FLAG_SGN | 0, FG_DDS_INT, offsetof (FG_DDS_PROP, val._u.Int32), DDS_OP_JEQ | DDS_OP_TYPE_4BY | DDS_OP_FLAG_SGN | 0, FG_DDS_INT, offsetof (FG_DDS_prop, val._u.Int32),
DDS_OP_JEQ | DDS_OP_TYPE_8BY | DDS_OP_FLAG_SGN | 0, FG_DDS_LONG, offsetof (FG_DDS_PROP, val._u.Int64), DDS_OP_JEQ | DDS_OP_TYPE_8BY | DDS_OP_FLAG_SGN | 0, FG_DDS_LONG, offsetof (FG_DDS_prop, val._u.Int64),
DDS_OP_JEQ | DDS_OP_TYPE_4BY | DDS_OP_FLAG_FP | 0, FG_DDS_FLOAT, offsetof (FG_DDS_PROP, val._u.Float32), DDS_OP_JEQ | DDS_OP_TYPE_4BY | DDS_OP_FLAG_FP | 0, FG_DDS_FLOAT, offsetof (FG_DDS_prop, val._u.Float32),
DDS_OP_JEQ | DDS_OP_TYPE_8BY | DDS_OP_FLAG_FP | 0, FG_DDS_DOUBLE, offsetof (FG_DDS_PROP, val._u.Float64), DDS_OP_JEQ | DDS_OP_TYPE_8BY | DDS_OP_FLAG_FP | 0, FG_DDS_DOUBLE, offsetof (FG_DDS_prop, val._u.Float64),
DDS_OP_JEQ | DDS_OP_TYPE_STR | 0, FG_DDS_ALIAS, offsetof (FG_DDS_PROP, val._u.String), DDS_OP_JEQ | DDS_OP_TYPE_STR | 0, FG_DDS_ALIAS, offsetof (FG_DDS_prop, val._u.String),
DDS_OP_JEQ | DDS_OP_TYPE_STR | 0, FG_DDS_STRING, offsetof (FG_DDS_PROP, val._u.String), DDS_OP_JEQ | DDS_OP_TYPE_STR | 0, FG_DDS_STRING, offsetof (FG_DDS_prop, val._u.String),
DDS_OP_JEQ | DDS_OP_TYPE_STR | 0, FG_DDS_UNSPECIFIED, offsetof (FG_DDS_PROP, val._u.String), DDS_OP_JEQ | DDS_OP_TYPE_STR | 0, FG_DDS_UNSPECIFIED, offsetof (FG_DDS_prop, val._u.String),
DDS_OP_ADR | DDS_OP_TYPE_ARR | DDS_OP_SUBTYPE_1BY, offsetof (FG_DDS_PROP, guid), 16, DDS_OP_ADR | DDS_OP_TYPE_ARR | DDS_OP_SUBTYPE_1BY, offsetof (FG_DDS_prop, guid), 16,
DDS_OP_RTS DDS_OP_RTS
}; };
const dds_topic_descriptor_t FG_DDS_PROP_desc = const dds_topic_descriptor_t FG_DDS_prop_desc =
{ {
sizeof (FG_DDS_PROP), sizeof (FG_DDS_prop),
8u, 8u,
DDS_TOPIC_FIXED_KEY | DDS_TOPIC_NO_OPTIMIZE | DDS_TOPIC_CONTAINS_UNION, DDS_TOPIC_FIXED_KEY | DDS_TOPIC_NO_OPTIMIZE | DDS_TOPIC_CONTAINS_UNION,
1u, 1u,
"FG::DDS_PROP", "FG::DDS_prop",
FG_DDS_PROP_keys, FG_DDS_prop_keys,
15, 15,
FG_DDS_PROP_ops, FG_DDS_prop_ops,
"<MetaData version=\"1.0.0\"><Module name=\"FG\"><Enum name=\"propType\"><Element name=\"DDS_NONE\" value=\"0\"/><Element name=\"DDS_ALIAS\" value=\"1\"/><Element name=\"DDS_BOOL\" value=\"2\"/><Element name=\"DDS_INT\" value=\"3\"/><Element name=\"DDS_LONG\" value=\"4\"/><Element name=\"DDS_FLOAT\" value=\"5\"/><Element name=\"DDS_DOUBLE\" value=\"6\"/><Element name=\"DDS_STRING\" value=\"7\"/><Element name=\"DDS_UNSPECIFIED\" value=\"8\"/></Enum><Union name=\"propValue\"><SwitchType><Type name=\"propType\"/></SwitchType><Case name=\"Bool\"><Boolean/><Label value=\"DDS_BOOL\"/></Case><Case name=\"Int32\"><Long/><Label value=\"DDS_NONE\"/><Label value=\"DDS_INT\"/></Case><Case name=\"Int64\"><LongLong/><Label value=\"DDS_LONG\"/></Case><Case name=\"Float32\"><Float/><Label value=\"DDS_FLOAT\"/></Case><Case name=\"Float64\"><Double/><Label value=\"DDS_DOUBLE\"/></Case><Case name=\"String\"><String/><Label value=\"DDS_ALIAS\"/><Label value=\"DDS_STRING\"/><Label value=\"DDS_UNSPECIFIED\"/></Case></Union><Struct name=\"DDS_PROP\"><Member name=\"id\"><Long/></Member><Member name=\"version\"><Octet/></Member><Member name=\"mode\"><Boolean/></Member><Member name=\"val\"><Type name=\"propValue\"/></Member><Member name=\"guid\"><Array size=\"16\"><Octet/></Array></Member></Struct></Module></MetaData>" "<MetaData version=\"1.0.0\"><Module name=\"FG\"><Enum name=\"propType\"><Element name=\"DDS_NONE\" value=\"0\"/><Element name=\"DDS_ALIAS\" value=\"1\"/><Element name=\"DDS_BOOL\" value=\"2\"/><Element name=\"DDS_INT\" value=\"3\"/><Element name=\"DDS_LONG\" value=\"4\"/><Element name=\"DDS_FLOAT\" value=\"5\"/><Element name=\"DDS_DOUBLE\" value=\"6\"/><Element name=\"DDS_STRING\" value=\"7\"/><Element name=\"DDS_UNSPECIFIED\" value=\"8\"/></Enum><Union name=\"propValue\"><SwitchType><Type name=\"propType\"/></SwitchType><Case name=\"Bool\"><Boolean/><Label value=\"DDS_BOOL\"/></Case><Case name=\"Int32\"><Long/><Label value=\"DDS_NONE\"/><Label value=\"DDS_INT\"/></Case><Case name=\"Int64\"><LongLong/><Label value=\"DDS_LONG\"/></Case><Case name=\"Float32\"><Float/><Label value=\"DDS_FLOAT\"/></Case><Case name=\"Float64\"><Double/><Label value=\"DDS_DOUBLE\"/></Case><Case name=\"String\"><String/><Label value=\"DDS_ALIAS\"/><Label value=\"DDS_STRING\"/><Label value=\"DDS_UNSPECIFIED\"/></Case></Union><Struct name=\"DDS_prop\"><Member name=\"id\"><Long/></Member><Member name=\"version\"><Octet/></Member><Member name=\"mode\"><Boolean/></Member><Member name=\"val\"><Type name=\"propValue\"/></Member><Member name=\"guid\"><Array size=\"16\"><Octet/></Array></Member></Struct></Module></MetaData>"
}; };

View file

@ -56,22 +56,22 @@ typedef struct FG_propValue
((FG_propValue*) dds_alloc (sizeof (FG_propValue))); ((FG_propValue*) dds_alloc (sizeof (FG_propValue)));
typedef struct FG_DDS_PROP typedef struct FG_DDS_prop
{ {
int32_t id; int32_t id;
uint8_t version; uint8_t version;
bool mode; bool mode;
FG_propValue val; FG_propValue val;
uint8_t guid[16]; uint8_t guid[16];
} FG_DDS_PROP; } FG_DDS_prop;
extern const dds_topic_descriptor_t FG_DDS_PROP_desc; extern const dds_topic_descriptor_t FG_DDS_prop_desc;
#define FG_DDS_PROP__alloc() \ #define FG_DDS_prop__alloc() \
((FG_DDS_PROP*) dds_alloc (sizeof (FG_DDS_PROP))); ((FG_DDS_prop*) dds_alloc (sizeof (FG_DDS_prop)));
#define FG_DDS_PROP_free(d,o) \ #define FG_DDS_prop_free(d,o) \
dds_sample_free ((d), &FG_DDS_PROP_desc, (o)) dds_sample_free ((d), &FG_DDS_prop_desc, (o))
#ifdef __cplusplus #ifdef __cplusplus
} }

View file

@ -53,7 +53,7 @@ union propValue switch ( propType )
// 2. Set version to FG_DDS_PROP_VERSION // 2. Set version to FG_DDS_PROP_VERSION
// 3. Set mode to FG_DDS_MODE_READ // 3. Set mode to FG_DDS_MODE_READ
// 4. set guid to the 16-byte participants GUID // 4. set guid to the 16-byte participants GUID
// 5. Set val type to STRING // 5. Set val type to FG_DDS_STRING
// 6. Set val String to the propery path // 6. Set val String to the propery path
// 7. Send the package. // 7. Send the package.
// //
@ -73,7 +73,7 @@ union propValue switch ( propType )
// 5. Wait for an answer // 5. Wait for an answer
// * Check whether id matches the requested property id. // * Check whether id matches the requested property id.
// * The val union holds the value of the propery. // * The val union holds the value of the propery.
struct DDS_PROP struct DDS_prop
{ {
long id; // 32-bit property index and DDS id. long id; // 32-bit property index and DDS id.
octet version; // 8-bit sample-type version number. octet version; // 8-bit sample-type version number.
@ -85,6 +85,6 @@ struct DDS_PROP
// already is 10-bytes in size. // already is 10-bytes in size.
octet guid[16]; octet guid[16];
}; };
#pragma keylist DDS_PROP id #pragma keylist DDS_prop id
}; // module FG }; // module FG

View file

@ -77,8 +77,8 @@ int main()
topics["ctrls"] = new SG_DDS_Topic(ctrls, &FG_DDS_Ctrls_desc); topics["ctrls"] = new SG_DDS_Topic(ctrls, &FG_DDS_Ctrls_desc);
participant.add(topics["ctrls"], SG_IO_IN); participant.add(topics["ctrls"], SG_IO_IN);
FG_DDS_PROP prop; FG_DDS_prop prop;
topics["prop"] = new SG_DDS_Topic(prop, &FG_DDS_PROP_desc); topics["prop"] = new SG_DDS_Topic(prop, &FG_DDS_prop_desc);
participant.add(topics["prop"], SG_IO_IN); participant.add(topics["prop"], SG_IO_IN);
set_mode(1); set_mode(1);
@ -118,6 +118,7 @@ int main()
printf("Prop Message:\n"); printf("Prop Message:\n");
printf(" version: %i\n", prop.version); printf(" version: %i\n", prop.version);
printf(" mode: %s\n", prop.mode ? "write" : "read"); printf(" mode: %s\n", prop.mode ? "write" : "read");
printf(" id: %i\n", prop.id);
if (prop.id == FG_DDS_PROP_REQUEST) { if (prop.id == FG_DDS_PROP_REQUEST) {
printf(" path: %s\n", prop.val._u.String); printf(" path: %s\n", prop.val._u.String);
printf("GUID: "); printf("GUID: ");

View file

@ -1,6 +1,6 @@
#include <stdio.h> #include <cstdio>
#include <string.h> #include <cstring>
#include <stdlib.h> #include <cstdlib>
#include <simgear/io/SGDataDistributionService.hxx> #include <simgear/io/SGDataDistributionService.hxx>
@ -13,8 +13,8 @@ int main()
{ {
SG_DDS participant; SG_DDS participant;
FG_DDS_PROP prop; FG_DDS_prop prop;
SG_DDS_Topic *topic = new SG_DDS_Topic(prop, &FG_DDS_PROP_desc); SG_DDS_Topic *topic = new SG_DDS_Topic(prop, &FG_DDS_prop_desc);
participant.add(topic, SG_IO_BI); participant.add(topic, SG_IO_BI);
@ -25,20 +25,22 @@ int main()
printf("%X ", prop.guid[i]); printf("%X ", prop.guid[i]);
printf("\n"); printf("\n");
prop.version = FG_DDS_PROP_VERSION;
prop.mode = FG_DDS_MODE_READ;
char path[256]; char path[256];
printf("\nType 'q' to quit\n"); printf("\nType 'q' to quit\n");
do do
{ {
printf("Property path: "); printf("Property path or id: ");
int len = scanf("%255s", path); int len = scanf("%255s", path);
if (len == EOF) continue; if (len == EOF) continue;
if (*path == 'q') break; if (*path == 'q') break;
prop.id = FG_DDS_PROP_REQUEST; char *end;
int id = strtol(path, &end, 10);
prop.id = (end == path) ? FG_DDS_PROP_REQUEST : id;
prop.version = FG_DDS_PROP_VERSION;
prop.mode = FG_DDS_MODE_READ;
prop.val._d = FG_DDS_STRING; prop.val._d = FG_DDS_STRING;
prop.val._u.String = path; prop.val._u.String = path;

View file

@ -48,10 +48,10 @@ bool FGDDSProps::open() {
SGIOChannel *io = get_io_channel(); SGIOChannel *io = get_io_channel();
SG_DDS_Topic *dds = static_cast<SG_DDS_Topic*>(io); SG_DDS_Topic *dds = static_cast<SG_DDS_Topic*>(io);
dds->setup<FG_DDS_PROP>(&FG_DDS_PROP_desc); dds->setup(prop, &FG_DDS_prop_desc);
// always send and recieve. // always send and recieve.
if (! io->open(SG_IO_BI)) { if (!io->open(SG_IO_BI)) {
SG_LOG(SG_IO, SG_ALERT, "Error opening channel communication layer."); SG_LOG(SG_IO, SG_ALERT, "Error opening channel communication layer.");
return false; return false;
} }
@ -64,7 +64,6 @@ bool FGDDSProps::open() {
// process work for this port // process work for this port
bool FGDDSProps::process() { bool FGDDSProps::process() {
SGIOChannel *io = get_io_channel(); SGIOChannel *io = get_io_channel();
FG_DDS_PROP prop;
int length = sizeof(prop); int length = sizeof(prop);
char *buf = reinterpret_cast<char*>(&prop); char *buf = reinterpret_cast<char*>(&prop);
@ -74,10 +73,12 @@ bool FGDDSProps::process() {
// act as a client: send a request and wait for an answer. // act as a client: send a request and wait for an answer.
} }
else if (get_direction() == SG_IO_OUT) else if (get_direction() == SG_IO_OUT || get_direction() == SG_IO_BI)
{ {
// act as a server: read requests and send the results. // act as a server: read requests and send the results.
while (io->read(buf, length) == length) while (io->read(buf, length) &&
prop.version == FG_DDS_PROP_VERSION &&
prop.mode == FG_DDS_MODE_READ)
{ {
if (prop.id == FG_DDS_PROP_REQUEST) if (prop.id == FG_DDS_PROP_REQUEST)
{ {
@ -92,7 +93,6 @@ bool FGDDSProps::process() {
if (p) if (p)
{ {
prop.id = prop_list.size(); prop.id = prop_list.size();
try { try {
prop_list.push_back(p); prop_list.push_back(p);
path_list[prop.val._u.String] = prop.id; path_list[prop.val._u.String] = prop.id;
@ -120,7 +120,7 @@ bool FGDDSProps::process() {
} }
// send the response. // send the response.
if (! io->write(buf, length)) { if (!io->write(buf, length)) {
SG_LOG(SG_IO, SG_ALERT, "Error writing data."); SG_LOG(SG_IO, SG_ALERT, "Error writing data.");
} }
} // while } // while
@ -142,8 +142,11 @@ bool FGDDSProps::close() {
return true; return true;
} }
void FGDDSProps::setProp(FG_DDS_PROP& prop, SGPropertyNode_ptr p) void FGDDSProps::setProp(FG_DDS_prop& prop, SGPropertyNode_ptr p)
{ {
// prop.id = FG_DDS_PROP_REQUEST;
prop.version = FG_DDS_PROP_VERSION;
prop.mode = FG_DDS_MODE_WRITE;
if (p) if (p)
{ {
simgear::props::Type type = p->getType(); simgear::props::Type type = p->getType();

View file

@ -36,10 +36,12 @@
class FGDDSProps : public FGProtocol { class FGDDSProps : public FGProtocol {
FG_DDS_prop prop;
simgear::PropertyList prop_list; simgear::PropertyList prop_list;
std::map<std::string,uint32_t> path_list; std::map<std::string,uint32_t> path_list;
static void setProp(FG_DDS_PROP& prop, SGPropertyNode_ptr p); static void setProp(FG_DDS_prop& prop, SGPropertyNode_ptr p);
public: public: