Implement the start of a property server using DDS.
This commit is contained in:
parent
e203336546
commit
202c69ad77
8 changed files with 448 additions and 1 deletions
|
@ -62,11 +62,16 @@ set(HEADERS
|
|||
rul.hxx
|
||||
)
|
||||
|
||||
if (CycloneDDS_FOUND)
|
||||
set(SOURCES ${SOURCES} dds_props.cxx)
|
||||
set(HEADERS ${HEADERS} dds_props.hxx)
|
||||
endif()
|
||||
|
||||
if(ENABLE_IAX)
|
||||
list(APPEND SOURCES fgcom.cxx)
|
||||
list(APPEND HEADERS fgcom.hxx)
|
||||
endif()
|
||||
|
||||
|
||||
flightgear_component(Network "${SOURCES}" "${HEADERS}")
|
||||
|
||||
if (CycloneDDS_FOUND)
|
||||
|
|
|
@ -4,12 +4,14 @@ set(SOURCES
|
|||
dds_ctrls.c
|
||||
dds_gui.c
|
||||
dds_fdm.c
|
||||
dds_props.c
|
||||
)
|
||||
|
||||
set(HEADERS
|
||||
dds_ctrls.h
|
||||
dds_fdm.h
|
||||
dds_gui.h
|
||||
dds_props.h
|
||||
)
|
||||
|
||||
add_executable(fg_dds_log
|
||||
|
|
10
src/Network/DDS/dds_fwd.hxx
Normal file
10
src/Network/DDS/dds_fwd.hxx
Normal file
|
@ -0,0 +1,10 @@
|
|||
// dds_fwd.hxx
|
||||
//
|
||||
// This file is in the Public Domain, and comes with no warranty.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "dds_gui.h"
|
||||
#include "dds_fdm.h"
|
||||
#include "dds_ctrls.h"
|
||||
|
46
src/Network/DDS/dds_props.c
Normal file
46
src/Network/DDS/dds_props.c
Normal file
|
@ -0,0 +1,46 @@
|
|||
/****************************************************************
|
||||
|
||||
Generated by Eclipse Cyclone DDS IDL to C Translator
|
||||
File name: dds_props.c
|
||||
Source: dds_props.idl
|
||||
Cyclone DDS: V0.7.0
|
||||
|
||||
*****************************************************************/
|
||||
#include "dds_props.h"
|
||||
|
||||
|
||||
static const dds_key_descriptor_t FG_DDS_PROP_keys[1] =
|
||||
{
|
||||
{ "id", 0 }
|
||||
};
|
||||
|
||||
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, offsetof (FG_DDS_PROP, type),
|
||||
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_STR, offsetof (FG_DDS_PROP, guid),
|
||||
DDS_OP_RTS
|
||||
};
|
||||
|
||||
const dds_topic_descriptor_t FG_DDS_PROP_desc =
|
||||
{
|
||||
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,
|
||||
14,
|
||||
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=\"type\"><Type name=\"propType\"/></Member><Member name=\"val\"><Type name=\"propValue\"/></Member><Member name=\"guid\"><String/></Member></Struct></Module></MetaData>"
|
||||
};
|
75
src/Network/DDS/dds_props.h
Normal file
75
src/Network/DDS/dds_props.h
Normal file
|
@ -0,0 +1,75 @@
|
|||
/****************************************************************
|
||||
|
||||
Generated by Eclipse Cyclone DDS IDL to C Translator
|
||||
File name: dds_props.h
|
||||
Source: dds_props.idl
|
||||
Cyclone DDS: V0.7.0
|
||||
|
||||
*****************************************************************/
|
||||
|
||||
#include "dds/ddsc/dds_public_impl.h"
|
||||
|
||||
#ifndef _DDSL_DDS_PROPS_H_
|
||||
#define _DDSL_DDS_PROPS_H_
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define FG_DDS_PROP_REQUEST -1
|
||||
typedef enum FG_propType
|
||||
{
|
||||
FG_DDS_NONE,
|
||||
FG_DDS_ALIAS,
|
||||
FG_DDS_BOOL,
|
||||
FG_DDS_INT,
|
||||
FG_DDS_LONG,
|
||||
FG_DDS_FLOAT,
|
||||
FG_DDS_DOUBLE,
|
||||
FG_DDS_STRING,
|
||||
FG_DDS_UNSPECIFIED
|
||||
} FG_propType;
|
||||
|
||||
#define FG_propType__alloc() \
|
||||
((FG_propType*) dds_alloc (sizeof (FG_propType)));
|
||||
|
||||
|
||||
typedef struct FG_propValue
|
||||
{
|
||||
FG_propType _d;
|
||||
union
|
||||
{
|
||||
bool Bool;
|
||||
int32_t Int32;
|
||||
int64_t Int64;
|
||||
float Float32;
|
||||
double Float64;
|
||||
char * String;
|
||||
} _u;
|
||||
} FG_propValue;
|
||||
|
||||
#define FG_propValue__alloc() \
|
||||
((FG_propValue*) dds_alloc (sizeof (FG_propValue)));
|
||||
|
||||
|
||||
typedef struct FG_DDS_PROP
|
||||
{
|
||||
int32_t id;
|
||||
FG_propType type;
|
||||
FG_propValue val;
|
||||
char * guid;
|
||||
} FG_DDS_PROP;
|
||||
|
||||
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_free(d,o) \
|
||||
dds_sample_free ((d), &FG_DDS_PROP_desc, (o))
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* _DDSL_DDS_PROPS_H_ */
|
85
src/Network/DDS/dds_props.idl
Normal file
85
src/Network/DDS/dds_props.idl
Normal file
|
@ -0,0 +1,85 @@
|
|||
// format dfescription: https://www.omg.org/spec/IDL/4.2/PDF
|
||||
|
||||
// Adapted from net_fdm.hxx
|
||||
module FG
|
||||
{
|
||||
|
||||
// defining it this way also generates accompanying #defines in the header file.
|
||||
const short DDS_PROP_REQUEST = -1;
|
||||
|
||||
enum propType
|
||||
{
|
||||
DDS_NONE, // The node hasn't been assigned a value yet
|
||||
DDS_ALIAS, // The node "points" to another node
|
||||
DDS_BOOL,
|
||||
DDS_INT, // 32-bit integer
|
||||
DDS_LONG, // 64-bit integer
|
||||
DDS_FLOAT, // 32-bit floating point number
|
||||
DDS_DOUBLE, // 64-bit floating point number
|
||||
DDS_STRING, // UTF-8 string
|
||||
DDS_UNSPECIFIED // Resolves to STRING
|
||||
};
|
||||
|
||||
union propValue switch ( propType )
|
||||
{
|
||||
case DDS_BOOL:
|
||||
boolean Bool;
|
||||
|
||||
case DDS_NONE:
|
||||
case DDS_INT:
|
||||
long Int32;
|
||||
|
||||
case DDS_LONG:
|
||||
long long Int64;
|
||||
|
||||
case DDS_FLOAT:
|
||||
float Float32;
|
||||
|
||||
case DDS_DOUBLE:
|
||||
double Float64;
|
||||
|
||||
case DDS_ALIAS:
|
||||
case DDS_STRING:
|
||||
case DDS_UNSPECIFIED:
|
||||
string String;
|
||||
};
|
||||
|
||||
// Initial property request sequence
|
||||
// for properties where the id is not yet known:
|
||||
// 1. Set id to FG_DDS_PROP_REQUEST
|
||||
// 2. set guid to the 16-byte participants GUID
|
||||
// 3. Set type to STRING
|
||||
// 4. Set val.String to the propery path
|
||||
// 5. Send the package.
|
||||
//
|
||||
// 6. wait for an answer
|
||||
// * Check whether guid matches the participants GUID.
|
||||
// * The index of the requested propery path is stored in the id variable
|
||||
// which should be used by successive request as the id for that property.
|
||||
// * The type variable indicates the type of the value of the property.
|
||||
// * The val union holds the value of the propery.
|
||||
//
|
||||
// Successive property request sequence:
|
||||
// 1. Set id to the id of the requested property
|
||||
// 2. Send the package.
|
||||
//
|
||||
// 3. wait for an answer
|
||||
// * Check whether id matches the requested property id.
|
||||
// * The type variable indicates the type of the value of the property.
|
||||
// * The val union holds the value of the propery.
|
||||
//
|
||||
// guid is not defined as an array of 16 unsigned characters to keep the
|
||||
// sample small for successive requests. This way only a FG_DDS_PROP_REQUEST
|
||||
// sample will reserve the full 16-bytes.
|
||||
struct DDS_PROP
|
||||
{
|
||||
long id; // property index and DDS id
|
||||
|
||||
propType type;
|
||||
propValue val;
|
||||
|
||||
string guid; // requesters globally unique identifier
|
||||
};
|
||||
#pragma keylist DDS_PROP id
|
||||
|
||||
}; // module FG
|
167
src/Network/dds_props.cxx
Normal file
167
src/Network/dds_props.cxx
Normal file
|
@ -0,0 +1,167 @@
|
|||
// dds_props.cxx -- FGFS "DDS" properties protocal class
|
||||
//
|
||||
// Written by Erik Hofman, started April 2021
|
||||
//
|
||||
// Copyright (C) 2021 by Erik Hofman <erik@ehofman.com>
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
// published by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful, but
|
||||
// WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
//
|
||||
// $Id$
|
||||
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <simgear/debug/logstream.hxx>
|
||||
#include <simgear/io/iochannel.hxx>
|
||||
#include <simgear/props/props.hxx>
|
||||
|
||||
#include <simgear/io/SGDataDistributionService.hxx>
|
||||
|
||||
#include <Main/fg_props.hxx>
|
||||
#include <Main/globals.hxx>
|
||||
|
||||
#include "dds_props.hxx"
|
||||
|
||||
// open hailing frequencies
|
||||
bool FGDDSProps::open() {
|
||||
if (is_enabled()) {
|
||||
SG_LOG(SG_IO, SG_ALERT, "This shouldn't happen, but the channel "
|
||||
<< "is already in use, ignoring");
|
||||
return false;
|
||||
}
|
||||
|
||||
SGIOChannel *io = get_io_channel();
|
||||
|
||||
SG_DDS_Topic *dds = static_cast<SG_DDS_Topic*>(io);
|
||||
dds->setup<FG_DDS_PROP>(&FG_DDS_PROP_desc);
|
||||
|
||||
// always send and recieve.
|
||||
if (! io->open(SG_IO_BI)) {
|
||||
SG_LOG(SG_IO, SG_ALERT, "Error opening channel communication layer.");
|
||||
return false;
|
||||
}
|
||||
|
||||
set_enabled(true);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// 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);
|
||||
|
||||
if (get_direction() == SG_IO_IN)
|
||||
{
|
||||
// act as a client: send a request and wait for an answer.
|
||||
|
||||
}
|
||||
else if (get_direction() == SG_IO_OUT)
|
||||
{
|
||||
// act as a server: read requests and send the results.
|
||||
while (io->read(buf, length) == length)
|
||||
{
|
||||
if (prop.id == FG_DDS_PROP_REQUEST)
|
||||
{
|
||||
auto it = by_path.find(prop.val._u.String);
|
||||
if (it == by_path.end())
|
||||
{
|
||||
SGPropertyNode_ptr props = globals->get_props();
|
||||
SGPropertyNode_ptr p = props->getNode(prop.val._u.String);
|
||||
if (p)
|
||||
{
|
||||
prop.id = by_id.size();
|
||||
by_id[prop.id] = p;
|
||||
by_path[prop.val._u.String] = p;
|
||||
}
|
||||
setProp(prop, p);
|
||||
}
|
||||
else
|
||||
{
|
||||
prop.id = std::distance(by_path.begin(), it);
|
||||
setProp(prop, it->second);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
SGPropertyNode_ptr p = by_id[prop.id];
|
||||
setProp(prop, p);
|
||||
}
|
||||
|
||||
// send the response.
|
||||
if (! io->write(buf, length)) {
|
||||
SG_LOG(SG_IO, SG_ALERT, "Error writing data.");
|
||||
}
|
||||
} // while
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// close the channel
|
||||
bool FGDDSProps::close() {
|
||||
SGIOChannel *io = get_io_channel();
|
||||
|
||||
set_enabled(false);
|
||||
|
||||
if (! io->close()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void FGDDSProps::setProp(FG_DDS_PROP& prop, SGPropertyNode_ptr p)
|
||||
{
|
||||
if (p)
|
||||
{
|
||||
simgear::props::Type type = p->getType();
|
||||
if (type == simgear::props::BOOL) {
|
||||
prop.type = FG_DDS_BOOL;
|
||||
prop.val._u.Bool = p->getBoolValue();
|
||||
} else if (type == simgear::props::INT) {
|
||||
prop.type = FG_DDS_INT;
|
||||
prop.val._u.Int32 = p->getIntValue();
|
||||
} else if (type == simgear::props::LONG) {
|
||||
prop.type = FG_DDS_LONG;
|
||||
prop.val._u.Int64 = p->getLongValue();
|
||||
} else if (type == simgear::props::FLOAT) {
|
||||
prop.type = FG_DDS_FLOAT;
|
||||
prop.val._u.Float32 = p->getFloatValue();
|
||||
} else if (type == simgear::props::DOUBLE) {
|
||||
prop.type = FG_DDS_DOUBLE;
|
||||
prop.val._u.Float64 = p->getDoubleValue();
|
||||
} else if (type == simgear::props::ALIAS) {
|
||||
prop.type = FG_DDS_ALIAS;
|
||||
prop.val._u.String = const_cast<char*>(p->getStringValue());
|
||||
} else if (type == simgear::props::STRING) {
|
||||
prop.type = FG_DDS_STRING;
|
||||
prop.val._u.String = const_cast<char*>(p->getStringValue());
|
||||
} else if (type == simgear::props::UNSPECIFIED) {
|
||||
prop.type = FG_DDS_UNSPECIFIED;
|
||||
prop.val._u.String = const_cast<char*>(p->getStringValue());
|
||||
} else {
|
||||
prop.type = FG_DDS_NONE;
|
||||
prop.val._u.Int32 = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
57
src/Network/dds_props.hxx
Normal file
57
src/Network/dds_props.hxx
Normal file
|
@ -0,0 +1,57 @@
|
|||
// dds_props.hxx -- FGFS "DDS" properties protocal class
|
||||
//
|
||||
// Written by Erik Hofman, started April 2021
|
||||
//
|
||||
// Copyright (C) 2021 by Erik Hofman <erik@ehofman.com>
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
// published by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful, but
|
||||
// WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
//
|
||||
// $Id$
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
||||
#include <simgear/compiler.h>
|
||||
|
||||
#include <simgear/props/propsfwd.hxx>
|
||||
|
||||
#include "protocol.hxx"
|
||||
#include "DDS/dds_props.h"
|
||||
|
||||
|
||||
class FGDDSProps : public FGProtocol {
|
||||
|
||||
std::map<uint32_t,SGPropertyNode_ptr> by_id;
|
||||
std::map<std::string,SGPropertyNode_ptr> by_path;
|
||||
|
||||
static void setProp(FG_DDS_PROP& prop, SGPropertyNode_ptr p);
|
||||
|
||||
public:
|
||||
|
||||
FGDDSProps() = default;
|
||||
~FGDDSProps() = default;
|
||||
|
||||
// open hailing frequencies
|
||||
bool open();
|
||||
|
||||
// process work for this port
|
||||
bool process();
|
||||
|
||||
// close the channel
|
||||
bool close();
|
||||
};
|
Loading…
Add table
Reference in a new issue