From 5355d1b0482f114793ec4e335e3da6ff1efcf634 Mon Sep 17 00:00:00 2001 From: ehofman Date: Tue, 25 Mar 2003 18:47:30 +0000 Subject: [PATCH] Add a generic, configurable communiction output option --- docs-mini/README.IO | 44 +++++++++ src/Main/fg_io.cxx | 4 + src/Main/options.cxx | 1 + src/Network/Makefile.am | 3 +- src/Network/generic.cxx | 202 ++++++++++++++++++++++++++++++++++++++++ src/Network/generic.hxx | 82 ++++++++++++++++ 6 files changed, 335 insertions(+), 1 deletion(-) create mode 100644 src/Network/generic.cxx create mode 100644 src/Network/generic.hxx diff --git a/docs-mini/README.IO b/docs-mini/README.IO index 6e838c6e9..f5b45799d 100644 --- a/docs-mini/README.IO +++ b/docs-mini/README.IO @@ -15,6 +15,50 @@ The general form of the command line option is as follows: hz = number of times to process channel per second (floating point values are ok. +Generic Communction: + + --generic=params + + With this option it is possible to output a pre-configured + ASCII string using a predefined seperator. The configuration is + defined in an XML file located in the Protocol directiory of + the base package. + + params can be: + serial port communication: serial,dir,hz,device,baud,protocol + socket communication: socket,dir,hz,machine,port,style,protocol + output to a file: file,dir,hz,filename,,protocol + + + The confinfiguration file is defined as follows: + + + + + + + \n + + + speed + int + V=%d + /velocities/speed + 0.0 + 1.0 + + + + ... + + + ... + + + + + + Serial Port Communication: --nmea=serial,dir,hz,device,baud diff --git a/src/Main/fg_io.cxx b/src/Main/fg_io.cxx index 9cac0c7d8..997fa36b1 100644 --- a/src/Main/fg_io.cxx +++ b/src/Main/fg_io.cxx @@ -56,6 +56,7 @@ #include #include #include +#include #ifdef FG_MPLAYER_AS #include @@ -159,6 +160,9 @@ FGIO::parse_port_config( const string& config ) } else if ( protocol == "rul" ) { FGRUL *rul = new FGRUL; io = rul; + } else if ( protocol == "generic" ) { + FGGeneric *generic = new FGGeneric( tokens[6] ); + io = generic; #ifdef FG_MPLAYER_AS } else if ( protocol == "multiplay" ) {\ diff --git a/src/Main/options.cxx b/src/Main/options.cxx index 3cadc4467..e4b273bfd 100644 --- a/src/Main/options.cxx +++ b/src/Main/options.cxx @@ -1166,6 +1166,7 @@ struct OptionDesc { {"opengc", true, OPTION_CHANNEL, "", false, "", 0 }, {"garmin", true, OPTION_CHANNEL, "", false, "", 0 }, {"nmea", true, OPTION_CHANNEL, "", false, "", 0 }, + {"generic", true, OPTION_CHANNEL, "", false, "", 0 }, {"props", true, OPTION_CHANNEL, "", false, "", 0 }, {"telnet", true, OPTION_CHANNEL, "", false, "", 0 }, {"pve", true, OPTION_CHANNEL, "", false, "", 0 }, diff --git a/src/Network/Makefile.am b/src/Network/Makefile.am index e4af55a6f..1bc452801 100644 --- a/src/Network/Makefile.am +++ b/src/Network/Makefile.am @@ -31,6 +31,7 @@ libNetwork_a_SOURCES = \ props.cxx props.hxx \ pve.cxx pve.hxx \ ray.cxx ray.hxx \ - rul.cxx rul.hxx + rul.cxx rul.hxx \ + generic.hxx generic.cxx INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/src diff --git a/src/Network/generic.cxx b/src/Network/generic.cxx new file mode 100644 index 000000000..8aaa77d6b --- /dev/null +++ b/src/Network/generic.cxx @@ -0,0 +1,202 @@ +// generic.cxx -- generic protocal class +// +// Written by Curtis Olson, started November 1999. +// +// Copyright (C) 1999 Curtis L. Olson - curt@flightgear.org +// +// 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., 675 Mass Ave, Cambridge, MA 02139, USA. +// +// $Id$ + + +#include +#include +#include +#include +#include +#include + +#include
+#include
+ +#include "generic.hxx" + + +FGGeneric::FGGeneric(string& config) { + + string file = config+".xml"; + + SGPath path( globals->get_fg_root() ); + path.append("Protocol"); + path.append(file.c_str()); + SG_LOG(SG_GENERAL, SG_INFO, "Reading communication protocol from " + << path.str()); + + SGPropertyNode root; + try { + readProperties(path.str(), &root); + } catch (const sg_exception &e) { + SG_LOG(SG_GENERAL, SG_ALERT, + "Unable to load the protocol configuration file"); + return; + } + + SGPropertyNode *output = root.getNode("generic/output"); + seperator = output->getStringValue("seperator"); + + vector chunks = output->getChildren("chunk"); + for (unsigned int i = 0; i < chunks.size(); i++) { + + _serial_prot chunk; + + // chunk.name = chunks[i]->getStringValue("name"); + chunk.format = chunks[i]->getStringValue("format", "%d"); + chunk.offset = chunks[i]->getDoubleValue("offset"); + chunk.factor = chunks[i]->getDoubleValue("offset", 1.0); + + string node = chunks[i]->getStringValue("node"); + chunk.prop = fgGetNode(node.c_str(), true); + + string type = chunks[i]->getStringValue("type"); + if (type == "bool") + chunk.type = FG_BOOL; + else if (type == "float") + chunk.type = FG_DOUBLE; + else if (type == "string") + chunk.type = FG_STRING; + else + chunk.type = FG_INT; + + _message.push_back(chunk); + + } + +} + +FGGeneric::~FGGeneric() { + _message.clear(); +} + + +// generate the message +bool FGGeneric::gen_message() { + + string generic_sentence; + char tmp[255]; + + int v; + double d; + + for (unsigned int i = 0; i < _message.size(); i++) { + + if (i > 0) + generic_sentence += seperator; + + switch (_message[i].type) { + case FG_INT: + v = _message[i].offset + + _message[i].prop->getIntValue() * _message[i].factor; + snprintf(tmp, 255, _message[i].format.c_str(), v); + break; + + case FG_BOOL: + snprintf(tmp, 255, _message[i].format.c_str(), + _message[i].prop->getBoolValue()); + break; + + case FG_DOUBLE: + d = _message[i].offset + + _message[i].prop->getDoubleValue() * _message[i].factor; + snprintf(tmp, 255, _message[i].format.c_str(), d); + break; + + default: // SG_STRING + snprintf(tmp, 255, _message[i].format.c_str(), + _message[i].prop->getStringValue()); + } + + generic_sentence += tmp; + } + + + length = generic_sentence.length(); + strncpy( buf, generic_sentence.c_str(), length ); + + return true; +} + +bool FGGeneric::parse_message() { + return true; +} + + + +// open hailing frequencies +bool FGGeneric::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(); + + if ( ! io->open( get_direction() ) ) { + SG_LOG( SG_IO, SG_ALERT, "Error opening channel communication layer." ); + return false; + } + + set_enabled( true ); + + return true; +} + + +// process work for this port +bool FGGeneric::process() { + SGIOChannel *io = get_io_channel(); + + if ( get_direction() == SG_IO_OUT ) { + gen_message(); + if ( ! io->write( buf, length ) ) { + SG_LOG( SG_IO, SG_ALERT, "Error writing data." ); + return false; + } + } else if ( get_direction() == SG_IO_IN ) { + // Temporarliy disable this as output only! + //if ( (length = io->readline( buf, FG_MAX_MSG_SIZE )) > 0 ) { + // parse_message(); + //} else { + // SG_LOG( SG_IO, SG_ALERT, "Error reading data." ); + // return false; + //} + } + + return true; +} + + +// close the channel +bool FGGeneric::close() { + SGIOChannel *io = get_io_channel(); + + set_enabled( false ); + + if ( ! io->close() ) { + return false; + } + + return true; +} diff --git a/src/Network/generic.hxx b/src/Network/generic.hxx new file mode 100644 index 000000000..f12a3ee29 --- /dev/null +++ b/src/Network/generic.hxx @@ -0,0 +1,82 @@ +// generic.hxx -- generic protocol class +// +// Written by Curtis Olson, started November 1999. +// +// Copyright (C) 1999 Curtis L. Olson - curt@flightgear.org +// +// 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., 675 Mass Ave, Cambridge, MA 02139, USA. +// +// $Id$ + + +#ifndef _FG_SERIAL_HXX +#define _FG_SERIAL_HXX + + +#include + +#include STL_STRING + +#include "protocol.hxx" + +SG_USING_STD(string); + + +class FGGeneric : public FGProtocol { + +public: + + FGGeneric(string&); + ~FGGeneric(); + + bool gen_message(); + bool parse_message(); + + // open hailing frequencies + bool open(); + + // process work for this port + bool process(); + + // close the channel + bool close(); + +protected: + + enum e_type { FG_BOOL=0, FG_INT, FG_DOUBLE, FG_STRING }; + + typedef struct { + // string name; + string format; + e_type type; + double offset; + double factor; + SGPropertyNode *prop; + } _serial_prot; + +private: + + int length; + char buf[ FG_MAX_MSG_SIZE ]; + + string seperator; + vector<_serial_prot> _message; + +}; + + +#endif // _FG_SERIAL_HXX + +