UNPKG

ggsimulator

Version:

GEOGATE-Simulator simulate one/many GPS/AIS receiver/transpondeur

201 lines (185 loc) 9.63 kB
#!/usr/bin/env node /* * Copyright 2014 Fulup Ar Foll * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /* * DevSimulator simulate a GPS/AIS. It takes input from gpx route/track file. * It support OpenCPN/VisuGPX export format, and hopefully while not tested * many other GPX format may work. * * DevSimulator is a simple frontend to lib/GpsSimulator. It parses command line * and handle network communication with client/server. * * DevSimulator can either send its NMEA feed as a client, or server to consumer. * - server: configure OpenCPN or other client to consume a network nmea feed on your selected port * - client: send TCP feed to GpsdTrack nmea183 adapter or to linux gpsd daemon using tcp://locahost:xxxx * * GpsAisSimulator generate intermediary points automatically. It takes each subsegment * of your route and track. Computes intermediary points depending on your selected * speed and tic. Sends nmea paquets at your selected tic rate. Stop at file end. * * syntax: node GpsAisSimulator --file=xxxxxx [--speed=xxx --tic=xxx --hostname=xxx --servermode --port=xxx ] * --file=xxxx exported route from OpenCPN or any other valid gpx file * --speed=20 knts at witch fake tracker moves from one point to an other * --tic=180 period in sec in between gps opts update * --srvrmod enter servermove [incompatible with connect] * --hostname=xxx if srvmod=false then provide hostname to connect onto * --port=5000 port for either server or client connection [-1 === no network output] * * --debug=1 debuglevel from 0-9 * --dump=fileout copy nmea messages out to fileout * --loop=timeout replay file infinetly after waiting timeout * --proto=aivdm with proto=aivdm you may set following extra arguments * --shipname=xxxx * --mmsi=xxxxx * --lenght=xxxxx * --width=xxxx * * GPS> node ./bin/DevSimulator --gpxfile=./sample/gpx-file/opencpn-sample.gpx --srvmod --mmsi=0 --port=4001 --tic=2 --speed=10 * AIS> node ./bin/DevSimulator --gpxfile=./sample/gpx-file/opencpn-sample.gpx --srvmod --mmsi=12345789 --port=4001 --tic=5 * CLI> node ./bin/DevSimulator --gpxfile=./sample/gpx-file/opencpn-sample.gpx --srvmod --mmsi=12345789 --hostname=xxxx --port=yyy --tic=zz * HLP> node ./bin/DevSimulator --help * * Use 'telnet localhost 4001' to check your messages. You may eventually decode AIS messages at http://www.maritec.co.za/aisvdmvdodecoding1.php * When everything fits your needs, point your application/navigator to your localhost:4001 or what ever your choose as tcpport * * Note: you can generate GPX files with: * - opencpn or any other navigation software * - upload gpx file from most GPS devices * - create oneline with http://www.visugpx.com/editgpx/ * - http://events.paudax.com/content/planning-your-diy-perm-route-google-maps */ var jison = require("jison").Parser; var GGsimulator; // if GeoGate development tree uses local modules if (process.env.GEOGATE !== 'dev') GGsimulator = require('ggsimulator'); else GGsimulator = require("../ApiExport"); ParseArgs = function (command, args) { var cmdgrammar = { "lex": { "rules" : [ ["\\s+" , "return 'BLK';"] ,['--gpxfile=' , "return 'GPX';"] ,['--speed=' , "return 'SPD';"] ,['--tic=' , "return 'TIC';"] ,['--proto=' , "return 'PRO';"] ,['--hostname=' , "return 'HOS';"] ,['--port=' , "return 'PRT';"] ,['--mmsi=' , "return 'IME';"] ,['--devid=' , "return 'IME';"] ,['--debug=' , "return 'DEB';"] ,['--length=' , "return 'LEN';"] ,['--width=' , "return 'WID';"] ,['--cargo=' , "return 'CAR';"] ,['--shipname=' , "return 'SHN';"] ,['--class=' , "return 'CLA';"] ,['--callsign=' , "return 'CAL';"] ,['--underway=' , "return 'WAY';"] ,['--srvmod=' , "return 'SRC';"] ,['--srvmod' , "return 'SRV';"] ,['--verbose' , "return 'VER';"] ,['--testparser', "return 'PAR';"] ,['--dumpfile=' , "return 'DUM';"] ,['--help' , "return 'HLP';"] ,['--loopwait=' , "return 'LOP';"] ,['--randomize=', "return 'RAN';"] ,[':' , "return 'SEP';"] ,[',' , "/* ignore */"] ,['([0-z)|[-]|[\\.]|[\\/])+' , "return 'TEX';"] ,['$' , "return 'EOL';"] ] }, // end Lex rules "bnf": { // WARNING: only one space in between TOKEN ex: "STOP EOF" 'opts': [ ["OPTIONS EOL" , "return (this);"] ] ,'OPTIONS': [['OPTION', ""] ,['OPTION BLK', ""] ,['OPTIONS OPTION BLK', ""] ,['OPTIONS OPTION', ""] ] ,'OPTION' : [["EOL" , "return (this);"] ,['GPX TEX' ,"this.gpxfile=$2;"] ,['SPD TEX' ,"this.sog=parseFloat($2);"] ,['TIC TEX' ,"this.tic=parseInt($2);"] ,['PRO TEX' ,"this.proto=$2;"] ,['HOS TEX' ,"this.host=$2"] ,['PRT TEX' ,"this.port=parseInt($2)"] ,['CAL TEX' ,"this.callsign=$2"] ,['IME TEX' ,"this.mmsi=parseInt($2)"] ,['CLA TEX' ,"this.class=$2"] ,['DEB TEX' ,"this.debug=$2"] ,['DUM TEX' ,"this.dumpfile=$2"] ,['SHN TEX' ,"this.shipname=$2"] ,['WID TEX' ,"this.wid=parseInt($2)"] ,['LEN TEX' ,"this.len=parseInt($2)"] ,['CAR TEX' ,"this.cargo=parseInt($2)"] ,['WAY TEX' ,"this.uway=parseInt($2)"] ,['SRC TEX' ,"this.srvmod=JSON.parse($2)"] ,['LOP TEX' ,"this.loopwait=parseInt($2*1000)"] // millisecond ,['RAN TEX' ,"this.randomize=$2"] ,['VER' ,"this.verbose=true"] ,['SRV' ,"this.srvmod=true"] ,['PAR' ,"this.testpar=true"] ,['HLP' ,"this.help=true"] ] }}; // instanciate command line parser var parser=new jison (cmdgrammar); var arguments= args.toString(); this.opts = parser.parse (arguments); // get basename from command line var cmd= command.split ('/'); var bin= cmd[cmd.length -1]; // if help call then display help and exit if (this.opts.help) { console.log ("----------------------------------------------------------------------------------------------------------"); console.log ("## Client: %s --gpxfile=./your-gpxfile.gpx [--proto=gprmc] [--speed=12] [--tic=2] \\",bin); console.log (" [--srvmod | --hostname=localhost] [--port=5000] \\"); console.log (" [--dumpgpxfile=xxx] [--loopwait=timeout] [--debug=4]"); console.log ("## Server: %s --gpxfile=./your-gpxfile.gpx [--proto=aivdm] [--speed=6] [--tic=30] \\", bin); console.log (" [--srvmod | --hostname=localhost] [port=5000] [--debug=4]\\"); console.log (" [--shipname=xxx] [--cargo=xxx] [--callsign=xxx] [--underway=xx] [--width=xxx] [--length=xxx]"); console.log ("## Ex-Aivdm: node %s --gpxfile=../samples/gpx-files/Quiberon-BelleIle.gpx \\", bin); console.log (" --speed=6 --tic=10 --srvmod --port=4001 --debug=4 --class=A --shipname=Simu-Fishing-Boat \\"); console.log (" --proto=aivdm --cargo=30 --callsign=FX1234 --underway=7 --width=45 --length=15"); console.log ("## Ex-Gprmc: node %s --gpxfile=../samples/gpx-files/PortHalligen-Teniouse.gpx \\", bin); console.log (" --speed=12 --tic=2 --srvmod --port=4002 --debug=4 --proto=gprmc "); console.log ("----------------------------------------------------------------------------------------------------------"); return(0); } }; // extract argss from command line var command= process.argv[1]; if (process.argv.length < 3) { var cmd= command.split ('/'); var bin= cmd[cmd.length -1]; console.log ("Error: %s '--gpxfile=xx --port=yy' mandatory argements missing [try --help]",bin); process.exit (-1); } // try to parse command var parsing=new ParseArgs(command, process.argv.slice(2)); // parsing failed ? if (parsing.error) { process.exit (-1); } // user select --help exit silently if (! parsing.opts.help) { // note: depending on module they only use a subset of opts var simulator = new GGsimulator.Simulator (parsing.opts); // parse GPX route and compute position if (simulator.valid) { // if simulator fail exit now var dispatcher = new GGsimulator.Dispatcher(parsing.opts); // dispatch message to tcp clients dispatcher.SetEncoder (GGsimulator.NmeaAisEncoder); dispatcher.SetListener (simulator); // ask dispatcher to handle simulator position events } }