flightgear/utils/fgpanel/FGPanelProtocol.cxx
2022-10-20 20:29:11 +08:00

186 lines
5.4 KiB
C++

//
// Written and (c) Torsten Dreyer - Torsten(at)t3r_dot_de
//
// 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.
//
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#ifdef HAVE_WINDOWS_H
#include <windows.h>
#endif
#ifdef WIN32
#define strtof strtod
#endif
#include <simgear/io/sg_socket.hxx>
#include <simgear/misc/strutils.hxx>
#include "ApplicationProperties.hxx"
#include "FGPanelProtocol.hxx"
class PropertySetter {
public:
PropertySetter (SGPropertyNode_ptr node) : _node (node) {}
virtual void setValue (const char *value) = 0;
virtual ~PropertySetter () {};
protected:
SGPropertyNode_ptr _node;
};
class BoolPropertySetter : public PropertySetter {
public:
BoolPropertySetter (SGPropertyNode_ptr node) : PropertySetter (node) {}
virtual void setValue (const char *value) {
_node->setBoolValue (atoi (value) != 0 );
}
};
class IntPropertySetter : public PropertySetter {
public:
IntPropertySetter (SGPropertyNode_ptr node) : PropertySetter (node) {}
virtual void setValue (const char *value) {
_node->setIntValue (atol (value));
}
};
class FloatPropertySetter : public PropertySetter {
public:
FloatPropertySetter (SGPropertyNode_ptr node) : PropertySetter (node) {}
virtual void setValue (const char *value) {
_node->setFloatValue (strtof (value, NULL));
}
};
class DoublePropertySetter : public PropertySetter {
public:
DoublePropertySetter (SGPropertyNode_ptr node) : PropertySetter (node) {}
virtual void setValue (const char *value) {
_node->setDoubleValue (strtod (value, NULL));
}
};
class StringPropertySetter : public PropertySetter {
public:
StringPropertySetter (SGPropertyNode_ptr node) : PropertySetter (node) {}
virtual void setValue (const char *value) {
_node->setStringValue (value);
}
};
FGPanelProtocol::FGPanelProtocol (SGPropertyNode_ptr a_Root) :
SGSubsystem (),
root (a_Root),
io (NULL) {
const SGPropertyNode_ptr outputNode (root->getNode ("protocol/generic/output"));
if (outputNode) {
const vector<SGPropertyNode_ptr> chunks (outputNode->getChildren ("chunk"));
for (vector<SGPropertyNode_ptr>::size_type i = 0; i < chunks.size (); i++) {
const SGPropertyNode_ptr chunk (chunks[i]);
const SGPropertyNode_ptr nodeNode (chunk->getNode ("node", false));
if (nodeNode == NULL) {
continue;
}
const SGPropertyNode_ptr node (ApplicationProperties::Properties->getNode (nodeNode->getStringValue (), true));
string type;
const SGPropertyNode_ptr typeNode (chunk->getNode ("type", false));
if (typeNode != NULL) {
type = typeNode->getStringValue ();
}
if (type == "float") {
propertySetterVector.push_back (new FloatPropertySetter (node));
} else if (type == "double" || type == "fixed") {
propertySetterVector.push_back (new DoublePropertySetter (node));
} else if (type == "bool" || type == "boolean") {
propertySetterVector.push_back (new BoolPropertySetter (node));
} else if (type == "string") {
propertySetterVector.push_back (new StringPropertySetter (node));
} else {
propertySetterVector.push_back (new IntPropertySetter (node));
}
}
}
}
FGPanelProtocol::~FGPanelProtocol()
{
for (PropertySetterVector::size_type i = 0; i < propertySetterVector.size(); i++) {
delete propertySetterVector[i];
}
}
void
FGPanelProtocol::update (double dt) {
char buf[2][8192];
if (io == NULL) {
return;
}
// read all available lines, keep last one
int Page (0);
bool HaveData (false);
while (io->readline (buf[Page], sizeof (buf[Page]) - 1) > 0) {
HaveData = true;
Page ^= 1;
}
if (HaveData) {
// process most recent line of data
Page ^= 1;
buf[Page][sizeof (buf[Page]) - 1] = 0;
const vector<string> tokens (simgear::strutils::split (buf[Page], ","));
for (vector<string>::size_type i = 0; i < tokens.size (); i++) {
if (i < propertySetterVector.size ()) {
propertySetterVector[i]->setValue (tokens[i].c_str ());
}
}
}
}
void
FGPanelProtocol::init () {
const SGPropertyNode_ptr listenNode (root->getNode ("listen"));
if (listenNode == NULL) {
return;
}
const string hostname (listenNode->getNode ("host", true)->getStringValue ());
const string port (listenNode->getNode ("port", true)->getStringValue ());
const string style (listenNode->getNode ("style", true)->getStringValue ());
if (io != NULL) {
delete io;
}
io = new SGSocket (hostname, port, style);
if (!io->open (SG_IO_IN)) {
cerr << "can't open socket " << style << ":" << hostname << ":" << port << endl;
}
}
void
FGPanelProtocol::reinit () {
init ();
}
// Register the subsystem.
#if 0
SGSubsystemMgr::Registrant<FGPanelProtocol> registrantFGPanelProtocol;
#endif