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_fdm.hxx>
#include <Network/native_gui.hxx>
#include <Network/dds_props.hxx>
#include <Network/opengc.hxx>
#include <Network/nmea.hxx>
#include <Network/props.hxx>
@ -155,6 +156,10 @@ FGIO::parse_port_config( const string_list& tokens, bool& o_ok )
io = new FGNativeGUI;
} else if ( protocol == "nmea" ) {
io = new FGNMEA();
#if FG_HAVE_DDS
} else if ( protocol == "dds-props") {
io = new FGDDSProps;
#endif
} else if ( protocol == "props" || protocol == "telnet" ) {
io = new FGProps( tokens );
o_ok = true;
@ -233,7 +238,13 @@ FGIO::parse_port_config( const string_list& tokens, bool& o_ok )
if (tokens.size() < 4) {
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;
return NULL;
}

View file

@ -1929,6 +1929,7 @@ struct OptionDesc {
{"native-ctrls", 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 },
{"dds-props", true, OPTION_CHANNEL | OPTION_MULTI, "", false, "", 0 },
{"opengc", true, OPTION_CHANNEL | OPTION_MULTI, "", false, "", 0 },
{"AV400", 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)
set(SOURCES ${SOURCES} dds_props.cxx)
set(HEADERS ${HEADERS} dds_props.hxx)
list(APPEND SOURCES
dds_props.cxx
)
list(APPEND HEADERS
dds_props.hxx
)
endif()
if(ENABLE_IAX)

View file

@ -9,39 +9,39 @@
#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 }
};
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_1BY, offsetof (FG_DDS_PROP, version),
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_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_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_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_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_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_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_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_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_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_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_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_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_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,
DDS_TOPIC_FIXED_KEY | DDS_TOPIC_NO_OPTIMIZE | DDS_TOPIC_CONTAINS_UNION,
1u,
"FG::DDS_PROP",
FG_DDS_PROP_keys,
"FG::DDS_prop",
FG_DDS_prop_keys,
15,
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>"
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>"
};

View file

@ -56,22 +56,22 @@ typedef struct FG_propValue
((FG_propValue*) dds_alloc (sizeof (FG_propValue)));
typedef struct FG_DDS_PROP
typedef struct FG_DDS_prop
{
int32_t id;
uint8_t version;
bool mode;
FG_propValue val;
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() \
((FG_DDS_PROP*) dds_alloc (sizeof (FG_DDS_PROP)));
#define FG_DDS_prop__alloc() \
((FG_DDS_prop*) dds_alloc (sizeof (FG_DDS_prop)));
#define FG_DDS_PROP_free(d,o) \
dds_sample_free ((d), &FG_DDS_PROP_desc, (o))
#define FG_DDS_prop_free(d,o) \
dds_sample_free ((d), &FG_DDS_prop_desc, (o))
#ifdef __cplusplus
}

View file

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

View file

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

View file

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

View file

@ -48,7 +48,7 @@ bool FGDDSProps::open() {
SGIOChannel *io = get_io_channel();
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.
if (!io->open(SG_IO_BI)) {
@ -64,7 +64,6 @@ bool FGDDSProps::open() {
// process work for this port
bool FGDDSProps::process() {
SGIOChannel *io = get_io_channel();
FG_DDS_PROP prop;
int length = sizeof(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.
}
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.
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)
{
@ -92,7 +93,6 @@ bool FGDDSProps::process() {
if (p)
{
prop.id = prop_list.size();
try {
prop_list.push_back(p);
path_list[prop.val._u.String] = prop.id;
@ -142,8 +142,11 @@ bool FGDDSProps::close() {
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)
{
simgear::props::Type type = p->getType();

View file

@ -36,10 +36,12 @@
class FGDDSProps : public FGProtocol {
FG_DDS_prop prop;
simgear::PropertyList prop_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: