Initial commit of files

This commit is contained in:
2021-01-22 10:16:20 -05:00
parent 32d165ec8f
commit ed92211680
534 changed files with 68563 additions and 19 deletions

7
daemons/.gitignore vendored Normal file
View File

@ -0,0 +1,7 @@
cand/cand
gpsd/gpsd
logd/logd
rtcmd/rtcmd
seriald/seriald
stdiod/stdiod
trackd/trackd

12
daemons/CMakeLists.txt Normal file
View File

@ -0,0 +1,12 @@
cmake_minimum_required(VERSION 3.7)
project(Cnomicon)
set(CMAKE_INSTALL_PREFIX ../bin)
# list of header files
set(SUB_DIRS
logd seriald stdiod cand gpsd rtcmd
)
foreach(SUB_DIR ${SUB_DIRS})
add_subdirectory(${SUB_DIR})
endforeach()

View File

@ -0,0 +1,25 @@
cmake_minimum_required(VERSION 3.7)
set(NAME cand)
project(Cnomicon-Daemon)
set(TARGET ${NAME})
set(CMAKE_INSTALL_PREFIX ..)
# includes
include_directories(
/usr/include/libxml2
../include/libcan++ ../include/libgps++ ../include/libnet++ ../include)
link_directories(../lib)
link_libraries(can++ gps++ net++ net emb kmlbase kmldom kmlengine xml2 pthread rt)
# sources
set(SRCS
CanDaemon.cpp
CanListener.cpp
CanRxListener.cpp
CanTxGenerator.cpp
)
# executables
add_executable(${TARGET} ${TARGET}.cpp ${SRCS})
install(TARGETS ${TARGET} DESTINATION sbin)

138
daemons/cand/CanDaemon.cpp Normal file
View File

@ -0,0 +1,138 @@
//****************************************************************************
// Copyright (C) 2007
// Nissan North America
// All Rights Reserved. Proprietary and Confidential.
//============================================================================
//****************************************************************************
// includes
//***************************************************************************/
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
#include <time.h>
#include <sys/timeb.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <sys/types.h>
#include "CanDaemon.h"
#include "netlib.h"
//****************************************************************************
// defines
//***************************************************************************/
//****************************************************************************
// macros
//***************************************************************************/
//****************************************************************************
// structs & typedefs
//***************************************************************************/
typedef struct _Can2DsrcMap {
int Signal;
double Scale;
int Offset;
} Can2DsrcMap;
//****************************************************************************
// global constants
//***************************************************************************/
//****************************************************************************
// global variables
//***************************************************************************/
//****************************************************************************
// static constants
//***************************************************************************/
//****************************************************************************
// static variables
//***************************************************************************/
//****************************************************************************
// static functions
//***************************************************************************/
//****************************************************************************
// C++ functions
//***************************************************************************/
CanDaemon::CanDaemon()
{
/* open a log file */
log_open( CAND_NAME );
SetTimeout( 1000000L );
}
CanDaemon::~CanDaemon()
{
}
/* Server *******************************************************************/
void CanDaemon::DaemonStartup(void)
{
// start threads and detach
Vehicle.Start( &Can, true ); // Receive CAN messages
Generator.Start( NULL, true ); // Send TX packets
Receiver.Caster = this;
Receiver.Start( NULL, true ); // Receive RX and TX Echo packets
}
void CanDaemon::DaemonShutdown(void)
{
Receiver.Stop();
Generator.Stop();
Vehicle.Stop();
}
int CanDaemon::ServerSocket(void)
{
int nrec=0;
return nrec;
}
int CanDaemon::ServerTimeout(void)
{
if ( NumClients() )
{
// status
// char str[128];
// int n = snprintf( str, sizeof(str), "CANd: %ld sent, %ld recv\n",
// Generator.SentCount(), Echo.RecvCount() );
// ClientCast( str, n );
}
return 0;
}
int CanDaemon::ClientIn( int sock, const char *buf, int n )
{
// commands?
return 0;
}
void CanDaemon::ClientCast( const char *buf, int n )
{
TcpServer::ClientCast( buf, n );
}
/* other stuff **************************************************************/
int CanDaemon::CanOpen( const char *uri )
{
return Can.CanOpen( uri );
}

76
daemons/cand/CanDaemon.h Normal file
View File

@ -0,0 +1,76 @@
//****************************************************************************
// Copyright (C) 2012
// Nissan North America
// All Rights Reserved. Proprietary and Confidential.
//============================================================================
/* prevent multiple inclusions */
#ifndef __CanDaemon__
#define __CanDaemon__
/* includes *****************************************************************/
#include "TcpDaemon.h"
#include "CanDatabase.h"
#include "UdpCaster.h"
#include "CanListener.h"
#include "CanTxGenerator.h"
#include "CanRxListener.h"
/* defines ******************************************************************/
/* BSMPd */
#define CAND_NAME "cand"
#define CAND_SERVICE "cand"
#define CAND_PORT "2946"
/* macros *******************************************************************/
/* structs & typedefs *******************************************************/
/* c class definitions ******************************************************/
//
// Uses the Peak Systems CAN Linux driver and Nissan CAN data
//
class CanDaemon : public TcpDaemon {
// public data
public:
CanTxGenerator Generator;
CanRxListener Receiver;
CanListener Vehicle;
CanSocket Can;
// private data
private:
// public methods
public:
// constructors
CanDaemon();
// destructor
virtual ~CanDaemon();
// virtual functions
void DaemonStartup(void);
void DaemonShutdown(void);
int ClientIn( int sock, const char *buf, int n );
void ClientCast( const char *buf, int n );
int ServerSocket( void );
int ServerTimeout( void );
// public methods
int CanOpen( const char *can );
// static methods
// private methods
private:
};
#endif

View File

@ -0,0 +1,321 @@
//
// Linux Daemon
//
//****************************************************************************
// includes
//***************************************************************************/
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdarg.h>
#include <fcntl.h>
#include <string.h>
#include <ctype.h>
#include <regex.h>
#include <time.h>
#include <sys/timeb.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/wait.h>
#include "libxml/parser.h"
#include "libxml/tree.h"
#include "CanSignal.h"
#include "CanListener.h"
#include "CanRxListener.h"
#include "CanTxGenerator.h"
#include "CAN_Packet.h"
//****************************************************************************
// defines
//***************************************************************************/
#define MAX_DSRC_PARSERS 32
//****************************************************************************
// macros
//***************************************************************************/
//****************************************************************************
// structs & typedefs
//***************************************************************************/
//****************************************************************************
// global constants
//***************************************************************************/
//****************************************************************************
// global variables
//***************************************************************************/
// write into the TX buffer
CAN_Packet Can = {};
//****************************************************************************
// static constants
//***************************************************************************/
//****************************************************************************
// static variables
//***************************************************************************/
static int num_parsers = 0;
//****************************************************************************
// static functions
//***************************************************************************/
//****************************************************************************
// C++ functions
//***************************************************************************/
CanListener::CanListener()
{
m_accel_from_speed = false;
m_debug = false;
m_reverse = false;
}
CanListener::~CanListener()
{
}
bool CanListener::CanParser( CanSignal *pSig, const unsigned char *data )
{
// successful and valid conversion with new data
if (!pSig->isNew)
return false;
// data has changed
// if ( m_debug )
// printf( "%s (%x) = %g (%ld)\n", pSig->Name.c_str(), pSig->Address, dValue, lValue );
// match CAN signal to CAN_Packet an copy
return true;
}
int CanListener::CanMapping( const char *file )
{
// parse XML
xmlDocPtr doc = NULL;
xmlNodePtr root = NULL;
/*parse the file and get the DOM */
if ( file )
{
if ( !(doc = xmlParseFile( file )) )
{
log_printf( "CANd: %s read error", file );
return -1;
}
}
else
{ // m/s^2
log_printf( "CANd: %s file not found", file );
return -1;
}
xmlChar *dbc = NULL;
int error = 0;
// Get the root element node
root = xmlDocGetRootElement(doc);
if ( !root )
return -1;
// <CANd> only
if ( xmlStrcmp( root->name, (const xmlChar *)"HeartBeat" ) != 0 )
return -1;
/* walk the tree */
xmlNodePtr node = root->xmlChildrenNode;
while ( node )
{
if ( xmlStrcmp( node->name, (const xmlChar *)"text" ) == 0 )
;
else if ( xmlStrcmp( node->name, (const xmlChar *)"HeartBeat" ) == 0 )
; // <!-- comment -->
else if ( xmlStrcmp( node->name, (const xmlChar *)"Description" ) == 0 )
;
else if ( xmlStrcmp( node->name, (const xmlChar *)"Database" ) == 0 )
{
// database file name
dbc = xmlNodeGetContent( node );
}
else if ( xmlStrcmp( node->name, (const xmlChar *)"CAN" ) == 0 )
{
xmlNodePtr item = node->xmlChildrenNode;
while ( item )
{
// CAN Signals
if ( xmlStrcmp( item->name, (const xmlChar *)"text" ) == 0 )
;
else if ( xmlStrcmp( item->name, (const xmlChar *)"Message" ) == 0 )
{
// get name and address
xmlNodePtr message = item->xmlChildrenNode;
xmlChar *name = NULL;
xmlChar *address = NULL;
u_long addr = 0;
while ( message )
{
if ( xmlStrcmp( message->name, (const xmlChar *)"text" ) == 0 )
;
else if ( xmlStrcmp( message->name, (const xmlChar *)"Name" ) == 0 )
name = xmlNodeGetContent( message );
else if ( xmlStrcmp( message->name, (const xmlChar *)"Address" ) == 0 )
address = xmlNodeGetContent( message );
message = message->next;
}
// add filter by name and address
if ( address )
addr = strtol( (char *)address, NULL, 10 );
if ( name )
AddMsgFilter( (char *)name, addr, addr );
}
else if ( xmlStrcmp( item->name, (const xmlChar *)"Signal" ) == 0 )
{
// get name and address
xmlNodePtr signal = item->xmlChildrenNode;
xmlChar *name = NULL;
xmlChar *address = NULL;
u_long addr = 0;
while ( signal )
{
if ( xmlStrcmp( signal->name, (const xmlChar *)"text" ) == 0 )
;
else if ( xmlStrcmp( signal->name, (const xmlChar *)"Name" ) == 0 )
name = xmlNodeGetContent( signal );
else if ( xmlStrcmp( signal->name, (const xmlChar *)"Address" ) == 0 )
address = xmlNodeGetContent( signal );
signal = signal->next;
}
// add filter by name and address
if ( address )
addr = strtol( (char *)address, NULL, 10 );
if ( name )
AddSigFilter( (char *)name, addr, addr );
}
item = item->next;
}
}
else
{
error++;
break;
}
node = node->next;
}
// Load the database after the filters are loaded and parse everything!
if ( dbc )
{
int n = LoadDatabase( (char*)dbc );
if (n < 0)
{
log_printf( "CANd: Database \"%s\" open failed!", (char*)dbc );
error = 1;
}
}
else
{
log_printf( "CANd: No database!" );
error = 1;
}
/* free the document */
xmlFreeDoc(doc);
xmlCleanupParser();
// errors parsing
if ( error )
return -1;
if ( num_parsers )
{
log_printf( "CANd: Parsers found = %d", num_parsers );
}
else
{
log_printf( "CANd: Errors found or no work to do (no CAN signals)!" );
return 0;
}
return num_parsers;
}
void *CanListener::Run(void *arg)
{
pCan = (CanSocket*)arg;
// wait till other threads have time to start
sleep(1);
// subscribed marked signals
SubscribeCan( pCan );
pCan->Blocking(0); // does this even work?
// setup for select()
fd_set rfds;
struct timeval tv;
int retval;
FD_ZERO(&rfds);
// run forever
while(1)
{
// select()
FD_SET(pCan->m_sock, &rfds);
tv.tv_sec = 0;
tv.tv_usec = 10000;
retval = select(pCan->m_sock+1, &rfds, NULL, NULL, &tv);
if (retval == -1)
perror("select()");
else if (retval)
{
CanFrame frame[20];
int n, sigs = 0;
// frame from CAN device (will block on more than 1)
if ( (n = pCan->CanRawRead( frame, sizeof(frame)/sizeof(CanFrame) )) > 0 )
{
for ( int i=0 ; i<n ; i++ )
{
// convert matching addresses (might be more than 1 signal)
for ( u_int j=0 ; j<Messages.size() ; j++ )
{
if ( Messages[j]->Read(&frame[i]) )
{
for (u_int k=0 ; k<Messages[j]->Signals.size() ; k++)
{
if ( CanParser( Messages[j]->Signals[k], frame[i].data ) )
sigs++;
}
break;
}
}
}
}
}
}
return NULL;
}

View File

@ -0,0 +1,70 @@
//
// Linux Daemon
//
/* prevent multiple inclusions */
#ifndef __CanListener__
#define __CanListener__
/* includes *****************************************************************/
#include <pthread.h>
#include <muParser.h>
#include "netlib.h"
#include "Thread.h"
#include "Mutex.h"
#include "UdpCaster.h"
#include "CanSocket.h"
#include "CanDatabase.h"
#include "CanTxGenerator.h"
/* defines ******************************************************************/
/* macros *******************************************************************/
/* structs & typedefs *******************************************************/
/* c class definitions ******************************************************/
class CanListener : public Thread, public CanDatabase {
// public data
public:
bool m_accel_from_speed;
bool m_debug;
bool m_reverse;
// protected data
protected:
CanSocket *pCan;
// private data
private:
// private methods
// public methods
public:
// constructors
CanListener();
// destructor
virtual ~CanListener();
// public methods
bool CanParser( CanSignal *pSig, const unsigned char * );
int CanMapping( const char *file );
// virtual overrides
void *Run(void*);
private:
// signal catchers (do not override)
};
#endif

View File

@ -0,0 +1,107 @@
//
// Linux Daemon
//
//****************************************************************************
// includes
//***************************************************************************/
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdarg.h>
#include <fcntl.h>
#include <string.h>
#include <time.h>
#include <sys/timeb.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/wait.h>
#include "ClockTimer.h"
#include "CanRxListener.h"
//****************************************************************************
// defines
//***************************************************************************/
//****************************************************************************
// macros
//***************************************************************************/
//****************************************************************************
// structs & typedefs
//***************************************************************************/
//****************************************************************************
// global constants
//***************************************************************************/
//****************************************************************************
// global variables
//***************************************************************************/
//****************************************************************************
// static constants
//***************************************************************************/
//****************************************************************************
// static variables
//***************************************************************************/
extern CAN_Packet Can;
//****************************************************************************
// static functions
//***************************************************************************/
//****************************************************************************
// C++ functions
//***************************************************************************/
CanRxListener::CanRxListener()
{
m_debug = false;
nTxEcho = nRxBsm = nRxOem = 0;
}
CanRxListener::~CanRxListener()
{
}
// listener hooks
void *CanRxListener::Run(void *arg)
{
unsigned char buf[2048];
while(1)
{
// WSU RX or TX Echo packets
int nread = Recv( buf, sizeof(buf) );
if ( nread == 0 )
continue;
char timebuf[32];
if ( Logging.IsLogging() )
{
struct timeval tv;
struct tm tm;
gettimeofday( &tv, NULL );
gmtime_r( &tv.tv_sec, &tm );
sprintf( timebuf, "%4d/%02d/%02d-%02d:%02d:%02d.%03ld",
tm.tm_year+1900, tm.tm_mon, tm.tm_mday,
tm.tm_hour, tm.tm_min, tm.tm_sec,
tv.tv_usec / 1000L
);
}
// incoming
}
return NULL;
}

View File

@ -0,0 +1,67 @@
//
// Linux Daemon
//
/* prevent multiple inclusions */
#ifndef __CanRxListener__
#define __CanRxListener__
/* includes *****************************************************************/
#include <pthread.h>
#include "netlib.h"
#include "Thread.h"
#include "Mutex.h"
#include "GpsPoint.h"
#include "UdpThread.h"
#include "TcpServer.h"
#include "UdpCaster.h"
#include "LogData.h"
#include "CAN_Packet.h"
/* defines ******************************************************************/
/* macros *******************************************************************/
/* structs & typedefs *******************************************************/
/* c class definitions ******************************************************/
class CanRxListener : public UdpThread {
// public data
public:
bool m_debug;
TcpServer *Caster;
UdpCaster Forward;
LogData Logging;
// protected data
protected:
int nTxEcho;
int nRxBsm;
int nRxOem;
// private data
private:
// private methods
// public methods
public:
// constructors
CanRxListener();
// destructor
virtual ~CanRxListener();
// virtual overrides
void *Run(void*);
private:
// signal catchers (do not override)
};
#endif

View File

@ -0,0 +1,139 @@
//
// Linux Daemon
//
//****************************************************************************
// includes
//***************************************************************************/
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdarg.h>
#include <fcntl.h>
#include <string.h>
#include <time.h>
#include <sys/timeb.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/wait.h>
#include "ClockTimer.h"
#include "CanTxGenerator.h"
//****************************************************************************
// defines
//***************************************************************************/
#ifndef min
#define min(A,B) ((A)<(B)?(A):(B))
#endif
//****************************************************************************
// macros
//***************************************************************************/
//****************************************************************************
// structs & typedefs
//***************************************************************************/
//****************************************************************************
// global constants
//***************************************************************************/
//****************************************************************************
// global variables
//***************************************************************************/
extern CAN_Packet Can;
//****************************************************************************
// static constants
//***************************************************************************/
//****************************************************************************
// static variables
//***************************************************************************/
static CanTxGenerator *Self = NULL;
//****************************************************************************
// static functions
//***************************************************************************/
//****************************************************************************
// C++ functions
//***************************************************************************/
CanTxGenerator::CanTxGenerator()
{
Self = this;
m_period = 100;
}
CanTxGenerator::~CanTxGenerator()
{
}
// generator itself
void *CanTxGenerator::Run(void *arg)
{
ClockTimer Loop;
Loop.Start( m_period * 1000 ); // usec
while (1)
{
// send out
SendTo( &Can, sizeof(Can) );
// log this message // log this message
if ( Logging.IsLogging() )
{
struct timeval tv;
struct tm tm;
gettimeofday( &tv, NULL );
gmtime_r( &tv.tv_sec, &tm );
char buf[32];
sprintf( buf, "%4d/%2d/%2d-%2d:%2d:%2d.%03ld",
tm.tm_year+1900, tm.tm_mon, tm.tm_mday,
tm.tm_hour, tm.tm_min, tm.tm_sec,
tv.tv_usec / 1000L
);
Logging.LogPrintf( "%s,%s,%f,%f,%f,%f,%u,%f,%u,%f,%f,%f,%f,%f,%u,%u,%u,%f,%u,%f",
buf,
"TX",
0.0,
0.0,
0.0,
0.0,
0,
Can.fSpeed,
Can.byTransmission,
Can.fSteering,
Can.fAccelLongitudinal,
Can.fAccelLateral,
Can.fAccelVertical,
Can.fYawRate,
Can.wBrakeSystemStatus,
Can.wEventFlags,
Can.byExteriorLights,
Can.fThrottle,
Can.byFrontWipers,
0.0
);
}
// 100 msec, leave a little time to do the work
Loop.Sync();
// msleep( m_period - 10L );
}
return NULL;
}

View File

@ -0,0 +1,60 @@
//
// Linux Daemon
//
/* prevent multiple inclusions */
#ifndef __CanTxGenerator__
#define __CanTxGenerator__
/* includes *****************************************************************/
#include <pthread.h>
#include "Thread.h"
#include "Mutex.h"
#include "UdpCaster.h"
#include "UdpThread.h"
#include "LogData.h"
#include "CAN_Packet.h"
/* defines ******************************************************************/
/* macros *******************************************************************/
/* structs & typedefs *******************************************************/
/* c class definitions ******************************************************/
class CanTxGenerator : public UdpThread {
// public data
public:
LogData Logging;
unsigned long m_period;
// protected data
protected:
UdpClient *pCan;
// private data
private:
// public methods
public:
// constructors
CanTxGenerator();
// destructor
virtual ~CanTxGenerator();
// public methods
void SetPeriod(unsigned long period) {m_period=period;};
// virtual overrides
void *Run(void*);
// private methods
private:
};
#endif

File diff suppressed because one or more lines are too long

139
daemons/cand/bsmpbeat.xml Normal file
View File

@ -0,0 +1,139 @@
<HeartBeat>
<Description>Nissan/Infiniti Gen3</Description>
<Database>Infiniti_M37_JX35_ADAS.dbc</Database>
<CAN>
<!-- CAN Database Filter, messages to read
Not needed if DBC is edited to CAN messages needed -->
<Signal>
<Name>CABRESW</Name>
<Address>0x35D</Address>
</Signal>
<Signal>
<Name>TURN_IND</Name>
<Address>0x60D</Address>
</Signal>
<Signal>
<Name>FR_WIP_REQ</Name>
<Address>0x35D</Address>
</Signal>
<Signal>
<Name>HL_HIGH_REQ</Name>
<Address>0x60D</Address>
</Signal>
<Signal>
<Name>HL_LOW_REQ</Name>
<Address>0x60D</Address>
</Signal>
<Signal>
<Name>TAIL_L_REQ</Name>
<Address>0x60D</Address>
</Signal>
<Signal>
<Name>LONG_ACC_02</Name>
<Address>0x292</Address>
</Signal>
<Signal>
<Name>TRANS_ACC_02</Name>
<Address>0x292</Address>
</Signal>
<Signal>
<Name>YAW_RATE_02</Name>
<Address>0x292</Address>
</Signal>
<Signal>
<Name>ABSACT</Name>
<Address>0x354</Address>
</Signal>
<Signal>
<Name>V_APO</Name>
<Address>0x182</Address>
</Signal>
<Signal>
<Name>VSO</Name>
<Address>0x284</Address>
</Signal>
<Signal>
<Name>STRANGLE</Name>
<Address>0x002</Address>
</Signal>
<Signal>
<Name>TCSACT</Name>
<Address>0x245</Address>
</Signal>
<Signal>
<Name>VDCACT</Name>
<Address>0x245</Address>
</Signal>
<Signal>
<Name>OFF_SW</Name>
<Address>0x245</Address>
</Signal>
<Signal>
<Name>CURGP</Name>
<Address>0x174</Address>
</Signal>
</CAN>
<DSRC>
<!-- CAN Signal (real values) to DSRC Element conversion -->
<Element>
<Name>Speed</Name>
<Expr>VSO*0.277777778</Expr>
</Element>
<Element>
<Name>TransmissionState</Name>
<Expr>CURGP</Expr>
</Element>
<Element>
<Name>LateralAcceleration</Name>
<Expr>TRANS_ACC_02*9.80665</Expr>
</Element>
<Element>
<Name>LongitudinalAcceleration</Name>
<Expr>LONG_ACC_02*9.80665</Expr>
</Element>
<Element>
<Name>YawRate</Name>
<Expr>YAW_RATE_02*0.1</Expr>
</Element>
<Element>
<Name>BrakeAppliedStatus</Name>
<Expr>CABRESW*15</Expr>
</Element>
<Element>
<Name>TractionControlStatus</Name>
<Expr>OFF_SW?0:TCSACT+1</Expr>
</Element>
<Element>
<Name>AntilockBrakeStatus</Name>
<Expr>ABSACT?ABSACT+1:0</Expr>
</Element>
<Element>
<Name>StabilityControlStatus</Name>
<Expr>OFF_SW?0:VDCACT+1</Expr>
</Element>
<Element>
<Name>VehicleWidth</Name>
<Expr>1.85</Expr>
</Element>
<Element>
<Name>VehicleLength</Name>
<Expr>4.95</Expr>
</Element>
<Element>
<Name>SteeringWheelAngle</Name>
<Expr>STRANGLE</Expr>
</Element>
<Element>
<Name>AccelPedalPosition</Name>
<Expr>V_APO*0.39216</Expr>
</Element>
<Element>
<Name>ExteriorLights</Name>
<Expr>HL_LOW_REQ*1+HL_HIGH_REQ*2+TURN_IND*4+TAIL_L_REQ*128</Expr>
</Element>
<Element>
<Name>FrontWiperStatus</Name>
<Expr>FR_WIP_REQ</Expr>
</Element>
</DSRC>
</HeartBeat>

204
daemons/cand/cand.cpp Normal file
View File

@ -0,0 +1,204 @@
//
// CAN Daemon (cand.cpp)
//
// Neal Probert
//
// IPv4 for now, since clients will be localhost anyways
// IPv6 for testing
//
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#include <signal.h>
#include <time.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include "CanDaemon.h"
#include "netlib.h"
extern int optind, opterr, optopt;
/*
* Note that we are doing a multi-client server so that it's possible to
* have several applications listening to CAN
*/
static const char *helptext =
"cand -m map.txt [options]\n"
"\t-a Acceleration calculated from speed\n"
"\t-b uri CAN Packet broadcast\n"
"\t-c can0 CAN Interface (default)\n"
"\t-d debug (foreground with stdio)\n"
"\t-f uri forward udp port (usually to MABX2)\n"
"\t-h help\n"
"\t-l uri UDP for TX Echo Listener (WSU BSM Proxy)\n"
"\t-m file.xml CAN to DSRC mapping file\n"
"\t-t period HeartBeat period in msec (default=100)\n"
"\t-v id Set Vehicle TempID (default=random)\n"
"\t-w uri UDP for TX Generator (WSU BSM Proxy)\n"
"\t-L logfile Message log file\n"
"\t-S service TCP service (default=2949)\n";
int main(int argc, char **argv)
{
char c; /* we have character */
int n;
/* options */
int debug = 0;
/* CAN */
const char *can = NULL; // "can0"
const char *mapping = NULL;
/* HB */
const char *tx = "udp://192.168.1.2:2735"; // to WSU
const char *rx = "udp://0.0.0.0:2736"; // from WSU
const char *tcp = CAND_PORT;
unsigned long period = 100UL;
const char *fwd = NULL; // "udp://192.168.1.10:2736"; // mABx2
// if we're doing CAN, we must be doing TX as well
if ( can )
tx = "udp://192.168.1.2:2735";
else
tx = NULL; // if we want to use dummy TX for testing
/* init hardware interface and daemon */
CanDaemon Can;
// add command line args
while ( (c = getopt( argc, argv, "ac:df:hl:m:tw:L:S:" )) > 0 )
{
switch ( c )
{
case 'a':
Can.Vehicle.m_accel_from_speed = false;
break;
case 'c':
can = optarg;
break;
case 'd':
debug = 1;
Can.Receiver.m_debug = Can.Vehicle.m_debug = true;
break;
case 'f':
fwd = optarg;
break;
case 'h':
puts( helptext );
exit(0);
break;
case 'l':
rx = optarg;
break;
case 'm':
mapping = optarg;
break;
case 't':
period = strtoul( optarg, NULL, 10 );
break;
case 'w':
if (strcmp(optarg, "-") == 0)
tx = "udp://192.168.1.2:2735";
else
tx = optarg;
break;
case 'L':
// Open log file (must be to logd!)
if ( Can.Receiver.Logging.LogOpen(optarg, 0) )
{
printf( "%s: Log file opened\n", optarg );
Can.Receiver.Logging.LogPrintf( "logtime,timestamp,type,id,latitude,longitude,elevation,heading,"
"speed,trans,steering,accel_long,accel_lat,accel_vert,yaw_rate,"
"brakes,event,lights,throttle,wipers,pp_radius" );
}
else
{
fprintf(stderr, "%s: log file open failed\n", optarg );
}
break;
case 'S':
tcp = optarg;
break;
default:
fprintf( stderr, "Unknown option -%c\n", c );
exit(1);
}
}
// CAN Database and Parsing
if ( mapping )
{
// Filter to reduce database
if ( (n = Can.Vehicle.CanMapping( mapping )) <= 0 )
{
fprintf( stderr, "Unable to load CAN database and DSRC mapping!\n");
exit(1);
}
}
else if ( can )
{
fprintf( stderr, "CAN to DSRC Mapping file is required!\n" );
exit(1);
}
// CAN device, can run without CAN for testing
if ( can )
{
if ( Can.Can.CanOpen( can ) < 0 )
{
fprintf( stderr, "Unable to open CAN device: %s!\n", can );
exit(1);
}
// fprintf( stderr, "CAN Max Filter = %d\n", CAN_MAX_FILTER );
}
else
{
fprintf( stderr, "Running without CAN, setting fake values\n" );
exit(1);
}
// TX sending
if ( tx )
{
// UDP
if ( Can.Generator.ConnectUri( tx ) < 0 )
{
fprintf( stderr, "Unable to connect to WSU BSM Proxy!\n" );
exit(1);
}
Can.Generator.SetPeriod( period );
}
else
fprintf( stderr, "Running without TX, RX listener only (TX Echo, RX Msg, OEM Echo)\n" );
// UDP broadcast
if ( rx )
Can.Receiver.ListenUri( rx );
else
fprintf( stderr, "Running with RX, sending TX only\n" );
// Forwarding to MABX2
if ( fwd )
{
if ( Can.Receiver.Forward.CasterUri( fwd ) >= 0 )
fprintf( stderr, "Forwarding packets to %s\n", fwd );
else
fprintf( stderr, "Forward open failed!\n" );
}
/* TCP Server */
if ( Can.StartService( CAND_NAME, NULL, tcp, debug ) >= 0 )
return Can.RunService();
return 1;
}

3
daemons/cand/candebug.sh Executable file
View File

@ -0,0 +1,3 @@
#!/bin/sh
./cand -c can0 -d -m bsmpbeat.xml

3
daemons/cand/debug.sh Executable file
View File

@ -0,0 +1,3 @@
#!/bin/sh
./cand -d -f udp://192.168.1.10:2736 -m bsmpbeat.xml

View File

@ -0,0 +1,26 @@
cmake_minimum_required(VERSION 3.7)
set(NAME gpsd)
project(Cnomicon-Daemon)
set(TARGET ${NAME})
set(CMAKE_INSTALL_PREFIX ..)
# includes
include_directories(
/usr/include/libxml2
../include/libgps++
../include/libnet++
../include)
link_directories(../lib)
link_libraries(gps++ net++ net emb kmlbase kmldom kmlengine xml2 pthread rt)
# sources
set(SRCS
GpsDaemon.cpp
)
# executables
add_executable(${TARGET} ${TARGET}.cpp ${SRCS})
install(TARGETS ${TARGET} DESTINATION sbin)

384
daemons/gpsd/GpsDaemon.cpp Normal file
View File

@ -0,0 +1,384 @@
//
// GPS Daemon
// Neal Probert
//
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
#include <time.h>
#include <sys/timeb.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <sys/types.h>
#include "UriParse.h"
#include "GpsDaemon.h"
#include "NmeaParser.h"
#include "ApplanixParser.h"
#include "FastraxParser.h"
#include "GarminParser.h"
#include "SirfParser.h"
#include "UbloxParser.h"
#include "netlib.h"
//****************************************************************************
// defines
//***************************************************************************/
//****************************************************************************
// macros
//***************************************************************************/
//****************************************************************************
// structs & typedefs
//***************************************************************************/
//****************************************************************************
// global constants
//***************************************************************************/
//****************************************************************************
// global variables
//***************************************************************************/
//****************************************************************************
// static constants
//***************************************************************************/
//****************************************************************************
// static variables
//***************************************************************************/
//****************************************************************************
// static functions
//***************************************************************************/
//****************************************************************************
// C++ functions
//***************************************************************************/
GpsDaemon::GpsDaemon()
{
log_open( GPSD_NAME );
clockset = 0;
msgcount = 0;
dgps_corr = true;
SourceIn = CorrIn = -1;
strcpy( Uri, "" );
nClients = 0;
SetClientTimeout(false); // don't reset timeout on client activity
}
GpsDaemon::~GpsDaemon()
{
Gps.GpsClose();
Log.LogClose();
}
/* NMEA **********************************************************************/
void GpsDaemon::PositionListener( const GpsPoint &Pos, const ErrorInfo &Err )
{
}
void GpsDaemon::TimeListener( const struct timeval &tv )
{
// good fix and time
if ( clockset && tv.tv_sec )
{
if ( getuid() == 0 )
settimeofday( &tv, NULL );
clockset = 0;
}
}
/* TCP ***********************************************************************/
int GpsDaemon::ServerTimeout(void)
{
// timeout (a bad thing)
DgpsReconnect();
return 0;
}
int GpsDaemon::ServerSocket(void)
{
char buf[2048];
int n = 0;
if ( IsSet( CorrIn ) )
{
// corrections
if ( dgps_corr )
// from RTCM server (once a minute)
n = Dgps.DgpsRead( buf, sizeof(buf) );
else
// from NTRIP server (once a minute)
n = Ntrip.NtripRead( (unsigned char *)buf, sizeof(buf) );
// xmit
if ( n > 0 )
Gps.GpsWrite( buf, n );
else if ( n == 0 )
{
if ( dgps_corr )
log_error( "Remote RTCM server closed!" );
else
log_error( "Remote NTRIP server closed!" );
DgpsReconnect();
}
ResetServerTimeout();
}
else if ( IsSet( SourceIn ) )
{
if ( gps_source )
// packet from GPS device
n = Gps.GpsRead( buf, sizeof(buf) );
else
// remote gpsd/glty
n = Gpsd.Recv( buf, sizeof(buf) );
if ( n > 0 && Parser && Parser->GpsParse(buf, n) > 0 )
{
msgcount++;
// 'cast
ClientCast( buf, n );
}
}
return n;
}
int GpsDaemon::ClientIn( int sock, const char *buf, int n )
{
// allows for NMEA playback via netcat
if ( *buf == '$' )
{
// broadcast it
Bcast.SendTo( buf, n );
// send to clients
TcpServer::ClientCast( buf, n );
}
else
{
// parse for commands?
// just log it
log_write( buf );
}
return n;
}
int GpsDaemon::ClientUp( int sock )
{
if ( nClients++ == 0 )
;
return 1;
}
void GpsDaemon::ClientDown( int sock )
{
// disconnect source
if ( --nClients <= 0 )
nClients = 0;
}
void GpsDaemon::ClientCast( const char *buf, int n )
{
// broadcast it
Bcast.SendTo( buf, n );
// send to clients
TcpServer::ClientCast( buf, n );
// log NMEA data with time stamp
Log.LogWrite( buf, n );
}
/* GPS ***********************************************************************/
int GpsDaemon::GpsOpen( const char *device, int baud )
{
UriParse parsed;
parsed.setRate( baud );
parsed.setUri( device );
const char *proto = parsed.getProto();
SourceIn = -1;
if ( !proto )
proto = "nmea";
// connect to gpsd?
if ( strcmp( proto, "gpsd" ) == 0 )
{
// does r mode for NMEA
SourceIn = Gpsd.GpsdConnect( parsed.getHost() );
proto = "nmea";
}
else if ( strcmp( proto, "glty" ) == 0 )
{
// put in NMEA mode
SourceIn = Gpsd.GpsdConnect( parsed.getHost() );
Gpsd.Send( "$PGLTY,NMEA\n", 12 );
proto = "pvii";
}
else
{
// open device
SourceIn = Gps.GpsOpen( parsed.getPath(), parsed.getRate() );
gps_source = true;
}
// check
if ( SourceIn < 0 )
return SourceIn;
bool binary = false;
// attach parser (should probably use a table)
if ( strcasecmp( proto, "nmea") == 0 )
{
// ascii
NmeaParser *parser = new NmeaParser();
Parser = (GpsParser *)parser;
}
else if ( strcasecmp( proto, "applanix") == 0 )
{
// binary
binary = true;
ApplanixParser *parser = new ApplanixParser();
Parser = (GpsParser *)parser;
}
else if ( strcasecmp( proto, "fastrax") == 0 )
{
// ascii
FastraxParser *parser = new FastraxParser();
Parser = (GpsParser *)parser;
}
else if ( strcasecmp( proto, "garmin") == 0 )
{
// ascii/binary
GarminParser *parser = new GarminParser();
Parser = (GpsParser *)parser;
}
else if ( strcasecmp( proto, "sirf") == 0 )
{
// binary
SirfParser *parser = new SirfParser();
Parser = (GpsParser *)parser;
}
else if ( strcasecmp( proto, "ublox") == 0 )
{
// ascii/binary
UbloxParser *parser = new UbloxParser();
Parser = (GpsParser *)parser;
}
else
{
// ascii
NmeaParser *parser = new NmeaParser();
Parser = (GpsParser *)parser;
}
// set mode
if ( binary )
Gps.SetCanonical( false, 0, 0 );
// subscribe
Parser->Subscribe( (GpsListener*)this );
// add listener
AddFd( SourceIn );
return SourceIn;
}
int GpsDaemon::DgpsConnect( const char *uri )
{
if ( !uri )
return -1;
// already connected?
if ( CorrIn >= 0 )
return CorrIn;
UriParse parsed;
parsed.setService( "2101" );
parsed.setUri( uri );
const char *proto = parsed.getProto();
if ( strcmp( proto, "dgps" ) == 0 || strcmp( proto, "dgpsip" ) == 0
|| strcmp( proto, "rtcmd" ) == 0 )
{
// RTCM server (dgpsip)
CorrIn = Dgps.DgpsConnect( parsed.getHost(), parsed.getService() );
dgps_corr = true;
}
else if ( strcmp( proto, "ntrip" ) == 0 )
{
// NTRIP caster
CorrIn = Ntrip.NtripConnect( uri );
dgps_corr = false;
}
// add listener
if ( CorrIn >= 0 )
{
strcpy( Uri, uri );
AddFd( CorrIn );
}
return CorrIn;
}
void GpsDaemon::DgpsDisconnect( void )
{
if ( CorrIn >= 0 )
;
else
return;
Dgps.DgpsClose();
Ntrip.NtripClose();
DelFd( CorrIn );
CorrIn = -1;
}
void GpsDaemon::DgpsReconnect( void )
{
if ( nClients == 0 || strlen(Uri) == 0 )
return;
log_printf( "Remote RTCM/NTRIP timed out, reconnecting" );
Dgps.DgpsClose();
Ntrip.NtripClose();
DelFd( CorrIn );
CorrIn = -1;
DgpsConnect( Uri );
}
int GpsDaemon::GpsBroadcast( const char *host )
{
const char *port = GPSD_SERVICE;
int sock = Bcast.Caster( host, port );
return sock;
}

121
daemons/gpsd/GpsDaemon.h Normal file
View File

@ -0,0 +1,121 @@
//
// GPS Daemon
// Neal Probert
//
/* prevent multiple inclusions */
#ifndef __GpsDaemon__
#define __GpsDaemon__
/* includes *****************************************************************/
#include "bzlib.h"
#include "TcpDaemon.h"
#include "UdpClient.h"
#include "UdpCaster.h"
#include "GpsDevice.h"
#include "GpsdClient.h"
#include "NmeaParser.h"
#include "SirfParser.h"
#include "ApplanixParser.h"
#include "DgpsClient.h"
#include "NtripClient.h"
#include "Logging.h"
/* defines ******************************************************************/
/* software details */
#define GPSD_NAME "gpsd"
#define GPSD_VERSION "0.1"
/* default service and port */
#define GPSD_SERVICE "gpsd"
#define GPSD_PORT "2947"
/* macros *******************************************************************/
/* structs & typedefs *******************************************************/
/* c class definitions ******************************************************/
//
// Uses the Peak Systems CAN Linux driver and Nissan CAN data
//
class GpsDaemon : public TcpDaemon, public GpsListener, public Logging {
// public data
public:
GpsdClient Gpsd;
GpsDevice Gps;
GpsParser *Parser;
DgpsClient Dgps;
NtripClient Ntrip;
// TrackClient Track;
// for corrections reconnect
char Uri[1024];
int nClients;
// private data
private:
bool gps_source; // 1=gps, 0=gpsd
bool dgps_corr; // 1=dpgs, 0=ntrip
// FDs
int SourceIn; // GpsdClient or GpsDevice
int CorrIn; // DpgsIn or NtripIn
int TrackOut; //
// UDP broadcast (data)
UdpCaster Bcast;
// misc
int clockset; // set to set clock from GPS
int msgcount;
// private methods
// static data
// public methods
public:
// constructors
GpsDaemon();
// destructor
virtual ~GpsDaemon();
// virtual functions
int ServerTimeout(void);
int ServerSocket(void);
int ClientIn( int sock, const char *buf, int n );
int ClientUp( int sock );
void ClientDown( int sock );
void ClientCast( const char *buf, int n );
// parser notifications
void PositionListener( const GpsPoint &Pos, const ErrorInfo &Err );
void TimeListener( const struct timeval &Time );
// public methods
void SetClock( void ) {clockset=1;};
int GpsOpen( const char *dev, int baud=38400 );
int GpsBroadcast( const char *host = NULL );
// corrections
int DgpsConnect( const char *host );
void DgpsDisconnect( void );
void DgpsReconnect( void );
int DgpsListen( const char *host = NULL );
// static methods
// private methods
private:
};
#endif

226
daemons/gpsd/gpsd.cpp Normal file
View File

@ -0,0 +1,226 @@
//
// GPS Daemon
// Neal Probert
//
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <strings.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#include <signal.h>
#include <time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <arpa/inet.h>
#include "GpsDaemon.h"
#include "netlib.h"
extern int optind, opterr, optopt;
//
// Written because gpsd (http://gpsd.berlios.de/) is too fat
//
//
// GPS Server (port 2947 by default)
// ----------
//
static const char *helptext =
"This is GPSd, not the open source software gpsd:\n"
"gpsd -s /dev/ttyS0:57600 [options]\n"
"\t-d debug (foreground with stdio)\n"
"\t-h help\n"
"\t-l UDP listen for RTCM corrections\n"
"\t-m network broadcast GPS data\n"
"\t-o outfile output message log\n"
"\t-r uri dgpsip://host or ntrip://user@pw:host/ rtcm:/dev/ttyS1\n"
"\t-s port nmea:/dev/ttyS0:baud or sirf:/dev/ttyS0:baud\n"
"\t-t uri OpenGTS server\n"
"\t-w WDM DSRC listen for RTCM corrections\n"
"\t-S service TCP service (default=gpsd)\n"
"\tUse OSS gpsd, gpspipe and gpsfake to create and replay NMEA log files!\n";
int main(int argc, char **argv)
{
char c; /* we have character */
GpsDaemon Gps;
/* options */
int debug = 0; // run in foreground, leaves stdio open
int dsrc_wsm = 0;
int timeout = 15;
/* dgpsip server */
char *host = NULL;
/* service/port */
char *service = (char *)"gpsd";
/* serial port */
char *primary = NULL;
char *secondary = NULL;
int baud = 4800;
/* logging */
char *outfile = NULL;
/* udp broadcast */
char *mcast = NULL;
/* udp listener */
int listen = 0;
/* data */
char szBuf[1600];
bzero( szBuf, sizeof(szBuf) );
// add command line args
while ( (c = getopt( argc, argv, "cdhi:jlm:o:r:s:t:S:T:v" )) > 0 )
{
switch ( c )
{
case 'c': // clock set
Gps.SetClock();
break;
case 'd':
debug = 1;
break;
case 'h':
puts( helptext );
return 0;
case 'l': // udp/wdm listen
listen = 1;
break;
case 'm': // udp broadcast
mcast = optarg;
break;
case 'o':
outfile = optarg;
break;
case 'r': // rtcm-sc104 host
host = optarg;
break;
case 's': // serial device
if ( !primary )
primary = optarg;
else
secondary = optarg;
break;
case 'S':
service = optarg;
break;
case 'T':
timeout = atoi(optarg);
if ( timeout == 0 )
timeout = 30;
break;
case 'w': // DSRC WSM
fprintf( stderr, "DSRC WSM support not available!\n" );
listen = 1;
dsrc_wsm = 1;
break;
default:
fprintf( stderr, "Unknown option -%c\n", c );
exit(1);
}
}
// check options
if ( !primary )
{
fprintf( stderr, "Must have a GPS device to communicate with!\n" );
exit(1);
}
if ( mcast && listen )
{
fprintf( stderr, "Cannot do both UDP broadcast/multicast and listening!\n" );
exit(1);
}
// input
if ( primary )
{
// open GPS device on serial port
int serial = Gps.GpsOpen( primary, baud );
if ( serial < 0 )
{
fprintf( stderr, "Unable to open primary serial device: %s @ %d !\n", primary, baud );
if ( secondary )
{
serial = Gps.GpsOpen( secondary, baud ); // won't open till primary dies
if ( serial < 0 )
{
fprintf( stderr, "Unable to open secondary serial device: %s @ %d !\n", secondary, baud );
exit(1);
}
}
}
}
else
{
fprintf( stderr, "No task specified: use -l, -i <logfile> or -s <dev>!\n" );
exit(1);
}
// corrections
if ( host )
{
// RTCM server
int remote = Gps.DgpsConnect( host );
if ( remote < 0 )
{
fprintf( stderr, "Unable to connect to rtcm-sc104 source host: %s\n", host );
// exit(1);
}
Gps.SetTimeout( timeout * 1000000L );
}
else if ( listen )
{
if ( dsrc_wsm )
{
// listen on WSM control channel for DSRC MSG_RTCM_Corrections
}
else
{
}
}
// output
if ( mcast )
{
int bcast = Gps.GpsBroadcast( mcast );
if ( bcast < 0 )
{
fprintf( stderr, "Unable to create UDP broadcast!\n" );
exit(1);
}
}
// logging
if ( outfile )
Gps.LogOpen( outfile );
// TCP listener
if ( Gps.StartService( GPSD_NAME, NULL, service, debug ) >= 0 )
{
return Gps.RunService();
}
return 1;
}

1
daemons/include Symbolic link
View File

@ -0,0 +1 @@
../include

1
daemons/lib Symbolic link
View File

@ -0,0 +1 @@
../lib

View File

@ -0,0 +1,22 @@
cmake_minimum_required(VERSION 3.7)
set(NAME logd)
project(Cnomicon-Daemon)
set(TARGET ${NAME})
set(CMAKE_INSTALL_PREFIX ..)
# includes
include_directories(
/usr/include/libxml2
../include/libnet++ ../include)
link_directories(../lib)
link_libraries(net++ net pthread rt)
# sources
set(SRCS
LogDaemon.cpp
)
# executables
add_executable(${TARGET} ${TARGET}.cpp ${SRCS})
install(TARGETS ${TARGET} DESTINATION sbin)

139
daemons/logd/LogDaemon.cpp Normal file
View File

@ -0,0 +1,139 @@
//
// Log Daemon
// Neal Probert
//
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
#include <time.h>
#include <sys/timeb.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <sys/types.h>
#include "UriParse.h"
#include "LogDaemon.h"
#include "netlib.h"
//****************************************************************************
// defines
//***************************************************************************/
//****************************************************************************
// macros
//***************************************************************************/
//****************************************************************************
// structs & typedefs
//***************************************************************************/
//****************************************************************************
// global constants
//***************************************************************************/
//****************************************************************************
// global variables
//***************************************************************************/
//****************************************************************************
// static constants
//***************************************************************************/
//****************************************************************************
// static variables
//***************************************************************************/
//****************************************************************************
// static functions
//***************************************************************************/
//****************************************************************************
// C++ functions
//***************************************************************************/
LogDaemon::LogDaemon()
{
// logging
log_open( LOGD_NAME );
}
LogDaemon::~LogDaemon()
{
}
/* UDP ***********************************************************************/
int LogDaemon::ClientInOut( char *buf, int n, int max )
{
if ( n > 0 )
{
Dprintf( "%s\n", buf );
Log.LogWrite( buf, n );
}
// no response
return 0;
}
/* log ***********************************************************************/
int LogDaemon::LogOpen( const char *uri )
{
if ( Log.LogOpen( uri ) )
{
return 1;
}
return -1;
}
int LogDaemon::LogPlayback( void )
{
timeval tv;
tv.tv_sec = 0L;
tv.tv_usec = 0L;
// read log input
// send message
// if ( strlen( logbuf ) )
// ClientCast( logbuf, strlen(logbuf) );
// read next message
if ( Log.LogRead( &tv, logbuf, sizeof(logbuf) ) > 0 )
{
// is this first one?
if ( logcount == 0 )
{
// fudge it so it kicks off 10 seconds later
loglast.tv_sec = tv.tv_sec - 10;
loglast.tv_usec = tv.tv_usec;
}
logcount++;
// diff between this one and last
if ( loglast.tv_usec > tv.tv_usec )
{
// carry
tv.tv_sec--;
tv.tv_usec += 1000000L;
}
timeval sv = tv;
// diff is timeout period
tv.tv_sec = tv.tv_sec - loglast.tv_sec;
tv.tv_usec = tv.tv_usec - loglast.tv_usec;
// mark last log record
loglast = sv;
}
else
return 1;
// set next timeout
SetTimeout( tv );
return 1;
}

74
daemons/logd/LogDaemon.h Normal file
View File

@ -0,0 +1,74 @@
//
// Log Daemon
// Neal Probert
//
/* prevent multiple inclusions */
#ifndef __LogDaemon__
#define __LogDaemon__
/* includes *****************************************************************/
#include "UdpDaemon.h"
#include "LogData.h"
/* defines ******************************************************************/
#define LOGD_NAME "logd"
#define LOGD_SERVICE "logd"
#ifndef LOGD_PORT
#define LOGD_PORT "2940"
#endif
/* macros *******************************************************************/
/* structs & typedefs *******************************************************/
/* c class definitions ******************************************************/
//
// Listens to OBE HeartBeat messages
//
class LogDaemon : public UdpDaemon {
// public data
public:
// private data
private:
// Logging output
LogData Log;
// log playback
char logbuf[512];
timeval loglast;
unsigned int logcount;
// private methods
// static data
// public methods
public:
// constructors
LogDaemon();
// destructor
virtual ~LogDaemon();
// virtual functions
int ClientInOut( char *buf, int n, int max );
// public methods
int LogOpen( const char *uri );
int LogWrite( const char *log ) { return Log.LogWrite(log,strlen(log)); };
void SetBinary(void) { Log.SetBinary(); };
int LogPlayback( void );
// static methods
// private methods
private:
};
#endif

145
daemons/logd/logd.cpp Normal file
View File

@ -0,0 +1,145 @@
//
// Serial Daemon (similar to ser2net)
// Neal Probert
//
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <strings.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#include <signal.h>
#include <time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <arpa/inet.h>
#include "LogDaemon.h"
#include "netlib.h"
extern int optind, opterr, optopt;
//
// any port
//
static const char *helptext =
"logd [options]\n"
"\t-d debug (foreground with stdio)\n"
"\t-h help\n"
"\t-i infile input log format:/path/to/file.log\n"
"\t-o logfile output log format:/path/to/file.log\n"
"\t-S service UDP service\n";
int main(int argc, char **argv)
{
char c; /* we have character */
LogDaemon Log;
/* options */
int debug = 0; // run in foreground, leaves stdio open
/* connections */
const char *file = NULL;
const char *log = NULL;
const char *service = LOGD_PORT;
// add command line args
while ( (c = getopt( argc, argv, "bdhi:o:S:" )) > 0 )
{
switch ( c )
{
case 'b':
Log.SetBinary();
break;
case 'd':
debug = 1;
break;
case 'h':
puts( helptext );
return 0;
case 'i':
file = optarg;
break;
case 'o':
log = optarg;
break;
case 'S':
service = optarg;
break;
default:
fprintf( stderr, "Unknown option -%c\n", c );
exit(1);
}
}
if ( log )
{
if ( Log.LogOpen( log ) < 0 )
{
fprintf( stderr, "Unable to open log file: %s!\n", log );
exit(1);
}
}
else
{
fprintf( stderr, "Must specify a MySQL connection: mysql://user:pass@host/database/table\n" );
exit(1);
}
if ( file )
{
char buf[4096];
int n = 0;
if ( strcmp( file, "-") == 0 )
{
while ( fgets(buf, sizeof(buf), stdin) )
{
Log.LogWrite( buf );
n++;
}
}
else
{
// import
FILE *import = fopen( file, "r" );
if ( import )
{
// read into database
while ( fgets( buf, sizeof(buf), import ) )
{
// check for header?
Log.LogWrite( buf );
n++;
}
printf( "Imported %d lines into log\n", n );
log_printf( "Imported %d lines into log\n", n );
}
else
{
fprintf( stderr, "Unable to import log data: %s\n", file );
return 1;
}
}
return 0;
}
else
{
// UDP listener
if ( Log.StartService( LOGD_NAME, "0.0.0.0", service, debug ) >= 0 )
return Log.RunService();
return 1;
}
return 0;
}

View File

@ -0,0 +1,22 @@
cmake_minimum_required(VERSION 3.7)
set(NAME rtcmd)
project(Cnomicon-Daemon)
set(TARGET ${NAME})
set(CMAKE_INSTALL_PREFIX ..)
# includes
include_directories(
/usr/include/libxml2
../include/libgps++ ../include/libnet++ ../include)
link_directories(../lib)
link_libraries(gps++ net++ net emb pthread rt)
# sources
set(SRCS
RtcmDaemon.cpp
)
# executables
add_executable(${TARGET} ${TARGET}.cpp ${SRCS})
install(TARGETS ${TARGET} DESTINATION sbin)

View File

@ -0,0 +1,307 @@
//
// RTCM Daemon
// Neal Probert
//
//****************************************************************************
// includes
//***************************************************************************/
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
#include <time.h>
#include <sys/timeb.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <sys/types.h>
#include "UriParse.h"
#include "RtcmDaemon.h"
#include "netlib.h"
//****************************************************************************
// defines
//***************************************************************************/
//****************************************************************************
// macros
//***************************************************************************/
//****************************************************************************
// structs & typedefs
//***************************************************************************/
//****************************************************************************
// global constants
//***************************************************************************/
//****************************************************************************
// global variables
//***************************************************************************/
//****************************************************************************
// static constants
//***************************************************************************/
//****************************************************************************
// static variables
//***************************************************************************/
//****************************************************************************
// static functions
//***************************************************************************/
//****************************************************************************
// C++ functions
//***************************************************************************/
RtcmDaemon::RtcmDaemon()
{
log_open( RTCMD_NAME );
strcpy( Uri, "" );
SerialIn = DgpsIn = NtripIn = DgramIn = -1;
nClients = 0;
SetClientTimeout(false); // don't reset timeout on client activity
}
RtcmDaemon::~RtcmDaemon()
{
}
int RtcmDaemon::ServerTimeout(void)
{
// should not timeout, try reconnecting
if ( nClients > 0 )
RtcmReconnect();
else
RtcmDisconnect();
return 0;
}
int RtcmDaemon::ServerSocket(void)
{
char buf[2048];
int n = 0, xmit = 0;
if ( IsSet( DgpsIn ) )
{
// from RTCM server
n = Dgps.DgpsRead( buf, sizeof(buf) );
// xmit
if ( n > 0 )
xmit = n;
else if ( n == 0 )
{
log_error( "Remote RTCM server closed!" );
RtcmDisconnect();
}
else
{
log_error( "Remote RTCM server read error!" );
n = 0;
}
ResetServerTimeout();
}
else if ( IsSet( NtripIn ) )
{
// from NTRIP server
n = Ntrip.NtripRead( (unsigned char *)buf, sizeof(buf) );
// xmit
if ( n > 0 )
xmit = n;
else if ( n == 0 )
{
log_error( "Remote NTRIP server closed us!" );
RtcmDisconnect();
}
else
{
log_error( "Remote NTRIP server read error!" );
n = 0;
}
ResetServerTimeout();
}
else if ( IsSet( SerialIn ) )
{
// from base station
n = Rtcm.RtcmRead( buf, sizeof(buf) );
// xmit
if ( n > 0 )
xmit = n;
}
// pass on RTCM data
if ( xmit > 0 )
{
ClientCast( buf, xmit );
}
return n;
}
void RtcmDaemon::ClientCast( const char *buf, int n )
{
// broadcast it
Bcast.SendTo( buf, n );
// send to clients
TcpServer::ClientCast( buf, n );
}
int RtcmDaemon::ClientIn( int sock, const char *buf, int n )
{
if ( n <= 0 )
return 0;
// log messages from client, no responses
if ( *buf == '$' )
{
// update to OpenGTS
// logging
char name[128];
char out[1024];
// need to add ip address
SockName( sock, name, sizeof(name) );
n = snprintf( out, sizeof(out), "[%s] %s", name, buf );
Log.LogWrite( out, n );
}
else if ( n > 0 )
log_write( buf );
return 0;
}
int RtcmDaemon::ClientUp( int sock )
{
// connect source on demand
if ( nClients++ == 0 )
{
// re-connect
RtcmConnect( (const char *)Uri );
}
return 1;
}
void RtcmDaemon::ClientDown( int sock )
{
// disconnect source
if ( --nClients <= 0 )
{
RtcmDisconnect();
nClients = 0;
}
}
int RtcmDaemon::RtcmOpen( const char *uri )
{
// already connected?
if ( SerialIn >= 0 )
Rtcm.RtcmClose();
UriParse parsed;
parsed.setRate( 38400 );
parsed.setUri( uri );
// serial device
SerialIn = Rtcm.RtcmOpen( parsed.getPath(), parsed.getRate() );
// add listener
if ( SerialIn >= 0 )
{
strcpy( Uri, uri );
AddFd( SerialIn );
}
return SerialIn;
}
int RtcmDaemon::RtcmConnect( const char *uri )
{
// already connected?
if ( DgpsIn >= 0 )
return DgpsIn;
else if ( NtripIn >= 0 )
return NtripIn;
UriParse parsed;
parsed.setService( RTCMD_PORT );
parsed.setRate( 57600 );
parsed.setUri( uri );
const char *proto = parsed.getProto();
if ( strcmp( proto, "dgps" ) == 0 || strcmp( proto, "dgpsip" ) == 0 )
{
// RTCM server (dgpsip)
DgpsIn = Dgps.DgpsConnect( parsed.getHost(), parsed.getService() );
// add listener
if ( DgpsIn >= 0 )
{
strcpy( Uri, uri );
AddFd( DgpsIn );
}
return DgpsIn;
}
else if ( strcmp( proto, "ntrip" ) == 0 )
{
// NTRIP caster
NtripIn = Ntrip.NtripConnect( uri );
// add listener
if ( NtripIn >= 0 )
{
strcpy( Uri, uri );
AddFd( NtripIn );
}
return NtripIn;
}
return -1;
}
void RtcmDaemon::RtcmDisconnect( void )
{
if ( DgpsIn >= 0 || NtripIn >= 0 )
log_printf( "Remote RTCM/NTRIP dis-connected, no clients listening" );
else
return;
Dgps.DgpsClose();
DelFd( DgpsIn );
Ntrip.NtripClose();
DelFd( NtripIn );
DgpsIn = NtripIn = -1;
}
void RtcmDaemon::RtcmReconnect( void )
{
if ( nClients == 0 )
return;
log_printf( "Remote RTCM/NTRIP timed out, reconnecting" );
Dgps.DgpsClose();
DelFd( DgpsIn );
Ntrip.NtripClose();
DelFd( NtripIn );
DgpsIn = NtripIn = -1;
RtcmConnect( Uri );
}
int RtcmDaemon::RtcmBroadcast( const char *host, const char *port )
{
return Bcast.Caster( host, port );
}

View File

@ -0,0 +1,94 @@
//
// RTCM Daemon
// Neal Probert
//
/* prevent multiple inclusions */
#ifndef __RtcmDaemon__
#define __RtcmDaemon__
/* includes *****************************************************************/
#include "TcpDaemon.h"
#include "UdpClient.h"
#include "UdpCaster.h"
#include "GpsDevice.h"
#include "RtcmDevice.h"
#include "DgpsClient.h"
#include "NtripClient.h"
#include "Logging.h"
/* defines ******************************************************************/
/* software details */
#define RTCMD_NAME "rtcmd"
#define RTCMD_VERSION "0.1"
/* default service and port */
#define RTCMD_SERVICE "rtcm-sc104"
#define RTCMD_PORT "2101"
/* macros *******************************************************************/
/* structs & typedefs *******************************************************/
/* c class definitions ******************************************************/
//
// Uses the Peak Systems CAN Linux driver and Nissan CAN data
//
class RtcmDaemon : public TcpDaemon, public Logging {
// public data
public:
DgpsClient Dgps;
NtripClient Ntrip;
RtcmDevice Rtcm;
// private data
private:
char Uri[1024];
// FDs
int DgpsIn;
int SerialIn;
int DgramIn;
int NtripIn;
// UDP broadcast
UdpCaster Bcast;
int nClients;
// static data
// public methods
public:
// constructors
RtcmDaemon();
// destructor
virtual ~RtcmDaemon();
// virtual functions
int ServerTimeout(void);
int ServerSocket(void);
int ClientIn( int sock, const char *buf, int n );
void ClientCast( const char *buf, int n );
int ClientUp( int sock );
void ClientDown( int sock );
// public methods
int RtcmOpen( const char *uri ); // serial device
int RtcmConnect( const char *uri );
void RtcmDisconnect( void );
void RtcmReconnect( void );
int RtcmBroadcast( const char *host = NULL, const char *port = RTCMD_SERVICE );
// static methods
// private methods
private:
};
#endif

145
daemons/rtcmd/rtcmd.cpp Normal file
View File

@ -0,0 +1,145 @@
//
// RTCM Daemon (rtcmd.cpp)
// Neal Probert
//
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <strings.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#include <signal.h>
#include <time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <arpa/inet.h>
#include "RtcmDaemon.h"
#include "netlib.h"
extern int optind, opterr, optopt;
//
// This was written because gpsd didn't have working RTCM104_SERVICE
// or the ability to do UDP broadcasts.
//
static const char *helptext =
"rtcm -r dgpsip://host [options]\n"
"\t-d debug (foreground with stdio)\n"
"\t-h help\n"
"\t-m network UDP broadcast RTCM data\n"
"\t-r uri dgpsip://host or ntrip://user@pass:host:port/mount\n"
"\t-t uri OpenGTS server\n"
"\t-w WDM DSRC broadcast RTCM corrections\n"
"\t-S service TCP service (default=2101)\n"
"\t-T timeout reconnect timeout in seconds (default=15)\n";
static RtcmDaemon Rtcm;
int main(int argc, char **argv)
{
char c; /* we have character */
/* options */
int debug = 0; // run in foreground, leaves stdio open
int dsrc_wsm = 0;
int timeout = 15;
/* dgpsip server */
char *host = NULL;
/* service/port */
char *service = (char *)"2101"; // "rtcm-sc104"
/* udp broadcast */
char *mcast = NULL;
/* log */
char *outfile = NULL;
// add command line args
while ( (c = getopt( argc, argv, "dhm:o:r:s:t:S:T:" )) > 0 )
{
switch ( c )
{
case 'd':
debug = 1;
break;
case 'h':
puts( helptext );
return 0;
case 'm': // udp broadcast
mcast = optarg;
break;
case 'o':
break;
case 'r': // rtcm-sc104 host
host = optarg;
break;
case 't':
break;
case 'S':
service = optarg;
break;
case 'T':
timeout = atoi(optarg);
if ( timeout == 0 )
timeout = 30;
break;
case 'w': // DSRC WSM broadcast or listen
fprintf( stderr, "DSRC WSM support not yet available!\n" );
// dsrc_wsm = 1;
break;
default:
fprintf( stderr, "Unknown option -%c\n", c );
exit(1);
}
}
// input
if ( host )
{
Rtcm.SetTimeout( timeout * 1000000L );
// RTCM server
int remote = Rtcm.RtcmConnect( host );
if ( remote < 0 )
{
fprintf( stderr, "Unable to connect to rtcm-sc104 source host: %s\n", host );
if ( debug )
exit(1);
}
}
// output
if ( mcast )
{
int bcast = Rtcm.RtcmBroadcast( mcast );
if ( bcast < 0 )
{
fprintf( stderr, "Unable to create UDP broadcast!\n" );
exit(1);
}
}
else if ( dsrc_wsm )
{
}
if ( outfile )
Rtcm.LogOpen( outfile, 0 );
// TCP listener
if ( Rtcm.StartService( RTCMD_NAME, NULL, service, debug ) >= 0 )
return Rtcm.RunService();
return 1;
}

7
daemons/rtcmd/test-mili.sh Executable file
View File

@ -0,0 +1,7 @@
!/bin/sh
rm /var/log/cnomicon/rtcmd.log
../../build/daemons/rtcmd/rtcmd -d -r ntrip://nprobert:p3x-mdotcors@148.149.0.87:10002/LIVONIA_RTCM2.3GPS
more /var/log/cnomicon/rtcmd.log

1
daemons/sbin Symbolic link
View File

@ -0,0 +1 @@
../sbin

View File

@ -0,0 +1,22 @@
cmake_minimum_required(VERSION 3.7)
set(NAME seriald)
project(Cnomicon-Daemon)
set(TARGET ${NAME})
set(CMAKE_INSTALL_PREFIX ..)
# includes
include_directories(
/usr/include/libxml2
../include/libnet++ ../include)
link_directories(../lib)
link_libraries(net++ net pthread rt)
# sources
set(SRCS
SerialDaemon.cpp
)
# executables
add_executable(${TARGET} ${TARGET}.cpp ${SRCS})
install(TARGETS ${TARGET} DESTINATION sbin)

View File

@ -0,0 +1,235 @@
//
// Serial Daemon
// Neal Probert
//
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
#include <time.h>
#include <sys/timeb.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <sys/types.h>
#include "UriParse.h"
#include "SerialDaemon.h"
#include "netlib.h"
//****************************************************************************
// defines
//***************************************************************************/
//****************************************************************************
// macros
//***************************************************************************/
//****************************************************************************
// structs & typedefs
//***************************************************************************/
//****************************************************************************
// global constants
//***************************************************************************/
//****************************************************************************
// global variables
//***************************************************************************/
//****************************************************************************
// static constants
//***************************************************************************/
//****************************************************************************
// static variables
//***************************************************************************/
//****************************************************************************
// static functions
//***************************************************************************/
//****************************************************************************
// C++ functions
//***************************************************************************/
SerialDaemon::SerialDaemon()
{
// logging
log_open( SERIALD_NAME );
m_SerialIn = m_RemoteIn = m_DgramIn = -1;
m_framed = 0;
bzero(m_Framing,sizeof(m_Framing));
}
SerialDaemon::~SerialDaemon()
{
if ( m_SerialIn >= 0 )
close( m_SerialIn );
}
/* TCP ***********************************************************************/
int SerialDaemon::ServerSocket(void)
{
char buf[2048];
int n = 0;
if ( IsSet( m_RemoteIn ) )
{
// from server
n = Client.Recv( buf, sizeof(buf) );
if ( n > 0 )
{
// send frame
if ( m_framed )
{
m_Framing[m_framed-2] = n >> 8;
m_Framing[m_framed-1] = n;
write( m_SerialIn, m_Framing, m_framed );
}
// send data
write( m_SerialIn, buf, n );
}
}
else if ( IsSet( m_SerialIn ) )
{
// data from device
n = read( m_SerialIn, buf, sizeof(buf) );
// parse data
if ( n>0 )
ClientCast( buf, n );
}
else if ( IsSet( m_DgramIn ) )
{
// packet from UDP broadcast
n = Dgram.RecvFrom( buf, sizeof(buf) );
// send to device
if ( n > 0 )
{
// send frame
if ( m_framed )
{
m_Framing[m_framed-2] = n >> 8;
m_Framing[m_framed-1] = n;
write( m_SerialIn, m_Framing, m_framed );
}
// send data
write( m_SerialIn, buf, n );
}
}
return n;
}
int SerialDaemon::ClientIn( int sock, const char *buf, int n )
{
return write( m_SerialIn, buf, n );
}
void SerialDaemon::ClientCast( const char *buf, int n )
{
// broadcast it
Bcast.SendTo( buf, n );
// send to clients
TcpServer::ClientCast( buf, n );
}
/* GPS ***********************************************************************/
int SerialDaemon::SerialOpen( const char *device, int baud )
{
UriParse parsed;
parsed.setRate( baud );
parsed.setUri( device );
int binary = 0;
// parse type
if ( strlen( parsed.getProto() ) )
{
if ( strcasecmp( parsed.getProto(), "binary" ) == 0 )
binary = 1;
}
// open device
m_SerialIn = serial_open( (char*)parsed.getPath(), parsed.getRate(), binary, binary?1:0 );
// check
if ( m_SerialIn < 0 )
return m_SerialIn;
// add listener
AddFd( m_SerialIn );
return m_SerialIn;
}
int SerialDaemon::TcpConnect( const char *uri )
{
UriParse parsed;
parsed.setUri( uri );
const char *proto = parsed.getProto();
if ( strcasecmp( proto, "http" ) == 0 ||
strcasecmp( proto, "https" ) == 0 )
{
// web site
}
else if ( strcasecmp( proto, "telnet" ) == 0 ||
strlen( proto ) == 0 )
{
// straight TCP client
m_RemoteIn = Client.Connect( parsed.getHost(), parsed.getService() );
}
return m_RemoteIn;
}
int SerialDaemon::UdpListen( const char *uri )
{
m_DgramIn = Dgram.ListenUri( uri );
if ( m_DgramIn > 0 )
AddFd( m_DgramIn );
return m_DgramIn;
}
int SerialDaemon::UdpBroadcast( const char *uri )
{
return Bcast.CasterUri( uri );
}
void SerialDaemon::SetFrame( const char *frame, int n )
{
if ( n )
{
// string
strncpy( m_Framing, frame, sizeof(m_Framing)-2 );
m_framed = strlen(m_Framing)+2;
}
else
{
// hex
unsigned long value = atol( frame );
m_framed = 6;
m_Framing[0] = value >> 24;
m_Framing[1] = value >> 16;
m_Framing[2] = value >> 8;
m_Framing[3] = value;
}
}

View File

@ -0,0 +1,92 @@
//
// Serial Daemon
// Neal Probert
//
/* prevent multiple inclusions */
#ifndef __SerialDaemon__
#define __SerialDaemon__
/* includes *****************************************************************/
#include "bzlib.h"
#include "TcpDaemon.h"
#include "TcpClient.h"
#include "UdpClient.h"
#include "UdpCaster.h"
#include "LogData.h"
/* defines ******************************************************************/
#define SERIALD_NAME "seriald"
#define SERIALD_SERVICE "seriald"
#define SERIALD_PORT "2942"
/* macros *******************************************************************/
/* structs & typedefs *******************************************************/
/* c class definitions ******************************************************/
//
// Uses the Peak Systems CAN Linux driver and Nissan CAN data
//
class SerialDaemon : public TcpDaemon {
// public data
public:
// private data
private:
// FDs
int m_SerialIn;
int m_RemoteIn;
int m_DgramIn;
// TCP client
TcpClient Client;
// UDP listen
UdpClient Dgram;
// UDP broadcast
UdpCaster Bcast;
// misc
int m_framed;
char m_Framing[8];
// private methods
// static data
// public methods
public:
// constructors
SerialDaemon();
// destructor
virtual ~SerialDaemon();
// virtual functions
int ServerSocket(void);
int ClientIn( int sock, const char *buf, int n );
void ClientCast( const char *buf, int n );
// public methods
int SerialOpen( const char *dev, int baud );
int TcpConnect( const char *uri );
int UdpBroadcast( const char *uri );
int UdpListen( const char *uri );
void SetFrame( const char *frame, int n=0 );
// static methods
// private methods
private:
};
#endif

175
daemons/seriald/seriald.cpp Normal file
View File

@ -0,0 +1,175 @@
//
// Serial Daemon (similar to ser2net)
// Neal Probert
//
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <strings.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#include <signal.h>
#include <time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <arpa/inet.h>
#include "SerialDaemon.h"
#include "netlib.h"
extern int optind, opterr, optopt;
//
// port 2748
//
static const char *helptext =
"seriald -s /dev/ttyS0:57600 [options]\n"
"\t-d debug (foreground with stdio)\n"
"\t-h help\n"
"\t-l UDP listen for data\n"
"\t-m network broadcast data\n"
"\t-o outfile output message log\n"
"\t-r uri http://host.domain.com/\n"
"\t-s port /dev/ttyS0:baud\n"
"\t-S service TCP service\n";
int main(int argc, char **argv)
{
char c; /* we have character */
SerialDaemon Ser;
/* options */
int debug = 0; // run in foreground, leaves stdio open
/* dgpsip server */
char *host = NULL;
/* service/port */
char *service = (char *)SERIALD_PORT;
/* serial port */
char *primary = NULL;
int baud = 57600;
/* udp broadcast */
char *mcast = NULL;
/* udp listener */
int listen = 0;
// add command line args
while ( (c = getopt( argc, argv, "df:hm:lr:s:S:" )) > 0 )
{
switch ( c )
{
case 'd':
debug = 1;
break;
case 'f':
Ser.SetFrame( optarg );
break;
case 'h':
puts( helptext );
return 0;
case 'l': // udp/wdm listen
listen = 1;
break;
case 'm': // udp broadcast
mcast = optarg;
break;
case 'r': // remote host
host = optarg;
break;
case 's': // serial device
primary = optarg;
break;
case 'S':
service = optarg;
break;
default:
fprintf( stderr, "Unknown option -%c\n", c );
exit(1);
}
}
// check options
if ( !primary )
{
fprintf( stderr, "Must have a serial device to communicate with!\n" );
exit(1);
}
if ( mcast && listen )
{
fprintf( stderr, "Cannot do both UDP broadcast/multicast and listening!\n" );
exit(1);
}
// input
if ( primary )
{
// open GPS device on serial port
int serial = Ser.SerialOpen( primary, baud );
if ( serial < 0 )
{
fprintf( stderr, "Unable to open primary serial device: %s @ %d !\n", primary, baud );
exit(1);
}
}
else
{
fprintf( stderr, "No task specified: use -l or -s <dev>!\n" );
exit(1);
}
// corrections
if ( host )
{
// RTCM server
int remote = Ser.TcpConnect( host );
if ( remote < 0 )
{
fprintf( stderr, "Unable to connect to remote host: %s\n", host );
exit(1);
}
}
else if ( listen )
{
// listen on UDP broadcasts for RTCM corrrections
int dgram = Ser.UdpListen( NULL );
if ( dgram < 0 )
{
fprintf( stderr, "Unable to listen on UDP broadcast!\n" );
exit(1);
}
}
// output
if ( mcast )
{
int bcast = Ser.UdpBroadcast( mcast );
if ( bcast < 0 )
{
fprintf( stderr, "Unable to create UDP broadcast!\n" );
exit(1);
}
}
// TCP listener
if ( Ser.StartService( SERIALD_NAME, NULL, service, debug ) >= 0 )
return Ser.RunService();
return 1;
}

View File

@ -0,0 +1,22 @@
cmake_minimum_required(VERSION 3.7)
set(NAME stdiod)
project(Cnomicon-Daemon)
set(TARGET ${NAME})
set(CMAKE_INSTALL_PREFIX ..)
# includes
include_directories(
/usr/include/libxml2
../include/libnet++ ../include)
link_directories(../lib)
link_libraries(net++ net pthread rt)
# sources
set(SRCS
StdioDaemon.cpp
)
# executables
add_executable(${TARGET} ${TARGET}.cpp ${SRCS})
install(TARGETS ${TARGET} DESTINATION sbin)

View File

@ -0,0 +1,162 @@
//
// Stdio Daemon
// Neal Probert
//
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
#include <time.h>
#include <sys/timeb.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <sys/types.h>
#include "UriParse.h"
#include "StdioDaemon.h"
#include "netlib.h"
//****************************************************************************
// defines
//***************************************************************************/
//****************************************************************************
// macros
//***************************************************************************/
//****************************************************************************
// structs & typedefs
//***************************************************************************/
//****************************************************************************
// global constants
//***************************************************************************/
//****************************************************************************
// global variables
//***************************************************************************/
//****************************************************************************
// static constants
//***************************************************************************/
//****************************************************************************
// static variables
//***************************************************************************/
//****************************************************************************
// static functions
//***************************************************************************/
//****************************************************************************
// C++ functions
//***************************************************************************/
StdioDaemon::StdioDaemon()
{
// logging
log_open( STDIOD_NAME );
m_RemoteIn = m_DgramIn = -1;
m_Stdin = 0;
AddFd( m_Stdin );
}
StdioDaemon::~StdioDaemon()
{
}
/* TCP ***********************************************************************/
int StdioDaemon::ServerSocket(void)
{
char buf[2048];
int n = 0;
if ( IsSet( m_RemoteIn ) )
{
// from server (tbd)
int n = Client.Recv( buf, sizeof(buf) );
if ( n > 0 )
fputs( buf, stdout );
}
else if ( IsSet( m_Stdin ) )
{
// packet from GPS device
while ( fgets( buf, sizeof(buf), stdin ) )
{
int n = strlen( buf );
if ( n>0 )
ClientCast( buf, n );
}
}
else if ( IsSet( m_DgramIn ) )
{
// RTCM packet from UDP broadcast (once a minute)
int n = Dgram.RecvFrom( buf, sizeof(buf) );
// send to GPS device
if ( n > 0 )
fputs( buf, stdout );
}
return n;
}
int StdioDaemon::ClientIn( int sock, const char *buf, int n )
{
return fputs( buf, stdout );
}
void StdioDaemon::ClientCast( const char *buf, int n )
{
// broadcast it
Bcast.SendTo( buf, n );
// send to clients
TcpServer::ClientCast( buf, n );
}
/* GPS ***********************************************************************/
int StdioDaemon::TcpConnect( const char *uri )
{
UriParse parsed;
parsed.setUri( uri );
const char *proto = parsed.getProto();
if ( strcasecmp( proto, "http" ) == 0 ||
strcasecmp( proto, "https" ) == 0 )
{
// web site
}
else if ( strcasecmp( proto, "telnet" ) == 0 ||
strlen( proto ) == 0 )
{
// straight TCP client
m_RemoteIn = Client.Connect( parsed.getHost(), parsed.getService() );
}
return m_RemoteIn;
}
int StdioDaemon::UdpListen( const char *uri )
{
m_DgramIn = Dgram.ListenUri( uri );
if ( m_DgramIn > 0 )
AddFd( m_DgramIn );
return m_DgramIn;
}
int StdioDaemon::UdpBroadcast( const char *uri )
{
return Bcast.CasterUri( uri );
}

View File

@ -0,0 +1,87 @@
//
// Stdio Daemon
// Neal Probert
//
/* prevent multiple inclusions */
#ifndef __StdioDaemon__
#define __StdioDaemon__
/* includes *****************************************************************/
#include "bzlib.h"
#include "TcpDaemon.h"
#include "TcpClient.h"
#include "UdpClient.h"
#include "UdpCaster.h"
#include "LogData.h"
/* defines ******************************************************************/
#define STDIOD_NAME "stdiod"
#define STDIOD_SERVICE "stdiod"
#define STDIOD_PORT "2941"
/* macros *******************************************************************/
/* structs & typedefs *******************************************************/
/* c class definitions ******************************************************/
//
// Uses the Peak Systems CAN Linux driver and Nissan CAN data
//
class StdioDaemon : public TcpDaemon {
// public data
public:
// private data
private:
// FDs
int m_Stdin;
int m_RemoteIn;
int m_DgramIn;
// TCP client
TcpClient Client;
// UDP listen
UdpClient Dgram;
// UDP broadcast
UdpCaster Bcast;
// misc
// private methods
// static data
// public methods
public:
// constructors
StdioDaemon();
// destructor
virtual ~StdioDaemon();
// virtual functions
int ServerSocket(void);
int ClientIn( int sock, const char *buf, int n );
void ClientCast( const char *buf, int n );
// public methods
int TcpConnect( const char *uri );
int UdpBroadcast( const char *uri );
int UdpListen( const char *uri );
// static methods
// private methods
private:
};
#endif

140
daemons/stdiod/stdiod.cpp Normal file
View File

@ -0,0 +1,140 @@
//
// Stdio Daemon
// Neal Probert
//
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <strings.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#include <signal.h>
#include <time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <arpa/inet.h>
#include "StdioDaemon.h"
#include "netlib.h"
extern int optind, opterr, optopt;
//
// any port
//
static const char *helptext =
"stdiod [options]\n"
"\t-d debug (foreground with stdio)\n"
"\t-h help\n"
"\t-l UDP listen for data\n"
"\t-m network broadcast data\n"
"\t-S service TCP service\n";
int main(int argc, char **argv)
{
char c; /* we have character */
StdioDaemon Std;
/* options */
int debug = 0; // run in foreground, leaves stdio open
/* dgpsip server */
char *host = NULL;
/* udp broadcast */
char *mcast = NULL;
/* udp listener */
char *listen = NULL;
/* server */
char *service = (char *)STDIOD_PORT;
// add command line args
while ( (c = getopt( argc, argv, "dhm:l:r:S:" )) > 0 )
{
switch ( c )
{
case 'd':
debug = 1;
break;
case 'h':
puts( helptext );
return 0;
case 'l': // udp listen
listen = optarg;
break;
case 'm': // udp broadcast
mcast = optarg;
break;
case 'r': // remote host
host = optarg;
break;
case 'S':
service = optarg;
break;
default:
fprintf( stderr, "Unknown option -%c\n", c );
exit(1);
}
}
// check options
if ( mcast && listen )
{
fprintf( stderr, "Cannot do both UDP broadcast/multicast and listening!\n" );
exit(1);
}
// input
// corrections
if ( host )
{
// RTCM server
int remote = Std.TcpConnect( host );
if ( remote < 0 )
{
fprintf( stderr, "Unable to connect to remote host: %s\n", host );
exit(1);
}
}
else if ( listen )
{
// listen on UDP broadcasts for RTCM corrrections
int dgram = Std.UdpListen( listen );
if ( dgram < 0 )
{
fprintf( stderr, "Unable to listen on UDP broadcast!\n" );
exit(1);
}
}
// output
if ( mcast )
{
int bcast = Std.UdpBroadcast( mcast );
if ( bcast < 0 )
{
fprintf( stderr, "Unable to create UDP broadcast!\n" );
exit(1);
}
}
// TCP listener
if ( Std.StartService( STDIOD_NAME, NULL, service, debug ) >= 0 )
return Std.RunService();
return 1;
}

View File

@ -0,0 +1,194 @@
//
// Track Daemon
// Neal Probert
//
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
#include <time.h>
#include <sys/timeb.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <sys/types.h>
#include "NmeaParser.h"
#include "UriParse.h"
#include "TrackDaemon.h"
#include "netlib.h"
//****************************************************************************
// defines
//***************************************************************************/
//****************************************************************************
// macros
//***************************************************************************/
//****************************************************************************
// structs & typedefs
//***************************************************************************/
//****************************************************************************
// global constants
//***************************************************************************/
//****************************************************************************
// global variables
//***************************************************************************/
//****************************************************************************
// static constants
//***************************************************************************/
//****************************************************************************
// static variables
//***************************************************************************/
//****************************************************************************
// static functions
//***************************************************************************/
//****************************************************************************
// C++ functions
//***************************************************************************/
TrackDaemon::TrackDaemon()
{
log_open( TRACKD_NAME );
gethostname( Id, sizeof(Id) );
}
TrackDaemon::~TrackDaemon()
{
}
/* UDP ***********************************************************************/
void TrackDaemon::PositionListener( const PositionFix &Pos, const ErrorInfo &Err )
{
char buf[256];
int n = 0;
char datetime[40];
// convert date & time (MySQL friendly)
struct tm *tmp = gmtime(&Pos.Time.tv_sec);
strftime( datetime, sizeof(datetime), "%Y-%m-%d,%T", tmp );
// convert to unicsv
n = snprintf( buf, sizeof(buf),
"%s,%s,%lf,%lf,%lf,%lf,%lf\n",
Id, // name
datetime, // time
Pos.Latitude, // lat
Pos.Longitude, // long
Pos.Altitude, // elev
Pos.Speed, // speed (m/sec -> kph)
Pos.Heading // heading
);
// send upstream
if ( TrackOut >= 0 )
Track.SendTo( buf, n );
// log locally
Log.LogWrite( buf, n );
}
void TrackDaemon::TimeListener( const struct timeval &tv )
{
}
int TrackDaemon::ServerSocket(void)
{
char buf[2048];
int n = 0;
if ( IsSet( GpsIn ) )
{
// Gpsd
if ( (n = Gpsd.Recv( buf, sizeof(buf) )) > 0 )
{
// use NMEA parser (should trigger on RMC or GGA)
Gps.Nmea.NmeaParse(buf);
}
}
return n;
}
int TrackDaemon::ClientInOut( char *buf, int n, int max )
{
// check
if ( n <= 0 )
return 0;
// parse $PVII
if ( buf[0] == '$' )
{
// use NMEA parser (should trigger on RMC or GGA)
Gps.Nmea.NmeaParse( buf );
}
else
{
// forward
if ( TrackOut >= 0 )
Track.SendTo( buf, n );
// log
Log.LogWrite( buf , n );
}
// no response
return 0;
}
/* GPS ***********************************************************************/
int TrackDaemon::GpsdServer( const char *uri )
{
UriParse parsed;
parsed.setProto( "gpsd" );
parsed.setService( "gpsd" );
parsed.setUri( uri );
bGpsd = 0;
const char *proto = parsed.getProto();
if ( !strlen(proto) )
proto = "gpsd";
GpsDeviceType type = Gps.Proto2Type( proto );
// open device
if ( strcmp( proto, "gpsd" ) == 0 || type == GPS_TYPE_UNDEF )
GpsIn = Gpsd.GpsdConnect( parsed.getHost() );
else
GpsIn = Gps.GpsOpen( parsed.getPath(), parsed.getRate(), type );
if ( GpsIn >= 0 )
AddFd( GpsIn );
return GpsIn;
}
int TrackDaemon::TrackOpen( const char *uri )
{
UriParse parsed;
parsed.setService( TRACKD_PORT );
parsed.setUri( uri );
// connect to remote web server to upload data
return TrackOut = Track.Connect( parsed.getHost(), TRACKD_PORT );
}
int TrackDaemon::LogOpen( const char *uri )
{
if ( Log.LogOpen( uri ) )
{
Log.LogFields( "name,date,time,lat,long,ele,speed,head" );
return 1;
}
return -1;
}

View File

@ -0,0 +1,89 @@
//
// Track Daemon
// Neal Probert
//
/* prevent multiple inclusions */
#ifndef __TrackDaemon__
#define __TrackDaemon__
/* includes *****************************************************************/
#include "bzlib.h"
#include "UdpDaemon.h"
#include "TcpClient.h"
#include "UdpClient.h"
#include "Logging.h"
#include "GpsdClient.h"
#include "GpsDevice.h"
/* defines ******************************************************************/
#define TRACKD_NAME "trackd"
#define TRACKD_SERVICE "trackd"
#define TRACKD_PORT "2948"
/* macros *******************************************************************/
/* structs & typedefs *******************************************************/
/* c class definitions ******************************************************/
//
// Listens to OBE HeartBeat messages
//
class TrackDaemon : public UdpDaemon, public GpsListener, public Logging {
// public data
public:
// private data
private:
// my name
char Id[32];
// Gpsd client
GpsdClient Gpsd; // direct from GPSd
GpsDevice Gps; // or from serial port
bool bGpsd; // true for Gpsd
int GpsIn; // Gpsd or Gps
// upstream trackd
UdpClient Track; // listener
int TrackOut;
// NMEA parsing
// private methods
// static data
// public methods
public:
// constructors
TrackDaemon();
// destructor
virtual ~TrackDaemon();
// virtual functions
int ServerSocket(void);
int ClientInOut( char *buf, int n, int max );
// public methods
int GpsdServer( const char *uri );
void PositionListener( const PositionFix &Pos, const ErrorInfo &Err );
void TimeListener( const struct timeval &Time );
void SetId( const char *id ) { strncpy(Id,id,sizeof(Id)-1); };
int TrackOpen( const char *uri );
int LogOpen( const char *uri );
// static methods
// private methods
private:
};
#endif

132
daemons/trackd/trackd.cpp Normal file
View File

@ -0,0 +1,132 @@
//
// Serial Daemon (similar to ser2net)
// Neal Probert
//
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <strings.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#include <signal.h>
#include <time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <arpa/inet.h>
#include "TrackDaemon.h"
#include "netlib.h"
extern int optind, opterr, optopt;
//
// any port
//
static const char *helptext =
"stdiod [options]\n"
"\t-d debug (foreground with stdio)\n"
"\t-g host gpsd\n"
"\t-h help\n"
"\t-i id set my id\n"
"\t-c uri host:port source data (CardiacMonitor)\n"
"\t-o logfile format:/path/to/file.log\n"
"\t-r uri remote web host for upload\n"
"\t-S service TCP service\n";
int main(int argc, char **argv)
{
char c; /* we have character */
TrackDaemon Track;
/* options */
int debug = 0; // run in foreground, leaves stdio open
/* connections */
char *gpsd = NULL; // "localhost";
char *host = NULL;
char *id = NULL;
char *log = NULL;
char *service = TRACKD_PORT;
// add command line args
while ( (c = getopt( argc, argv, "dg:hi:o:r:S:" )) > 0 )
{
switch ( c )
{
case 'd':
debug = 1;
break;
case 'g':
gpsd = optarg;
break;
case 'h':
puts( helptext );
return 0;
case 'i':
id = optarg;
break;
case 'o':
log = optarg;
break;
case 'r':
host = optarg;
break;
case 'S':
service = optarg;
break;
default:
fprintf( stderr, "Unknown option -%c\n", c );
exit(1);
}
}
// set my id (hostname by default)
if ( id )
Track.SetId( id );
// monitor
if ( gpsd )
{
// GPSd
int remote = Track.GpsdServer( gpsd );
if ( remote < 0 )
{
fprintf( stderr, "Unable to connect to gpsd: %s\n", gpsd );
// exit(1);
}
}
// output
if ( host )
{
if ( Track.TrackOpen( host ) < 0 )
{
fprintf( stderr, "Unable to open vehicle location server: %s!\n", host );
// exit(1);
}
}
if ( log )
{
if ( !Track.LogOpen( log ) )
{
fprintf( stderr, "Unable to open log file: %s!\n", log );
exit(1);
}
}
// TCP listener
if ( Track.StartService( TRACKD_NAME, NULL, service, debug ) >= 0 )
return Track.RunService();
return 1;
}