2018-11-02 15:06:08 +00:00
/*
Copyright 2018 Michal Fratczak
This file is part of habdec .
habdec is free software : you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation , either version 3 of the License , or
( at your option ) any later version .
habdec is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with habdec . If not , see < https : //www.gnu.org/licenses/>.
*/
# include <string>
# include <iostream>
# include <fstream>
# include <regex>
# include <boost/program_options.hpp>
# include "GLOBALS.h"
# include "common/console_colors.h"
2018-11-08 12:36:21 +00:00
# include "habitat/habitat_interface.h"
namespace
{
int LoadPayloadParameters ( std : : string i_payload_id )
{
using namespace std ;
2018-11-09 13:51:06 +00:00
using namespace habdec : : habitat ;
2018-11-08 12:36:21 +00:00
std : : map < std : : string , HabitatFlight > flights = ListFlights ( 0 ) ;
for ( auto & flight : flights )
{
for ( auto & payload : flight . second . payloads_ )
{
if ( ! i_payload_id . compare ( payload . second . id_ ) )
{
2019-02-15 11:16:43 +00:00
GLOBALS : : get ( ) . par_ . baud_ = payload . second . baud_ ;
GLOBALS : : get ( ) . par_ . rtty_ascii_bits_ = payload . second . ascii_bits_ ;
GLOBALS : : get ( ) . par_ . rtty_ascii_stops_ = payload . second . ascii_stops_ ;
GLOBALS : : get ( ) . par_ . frequency_ = payload . second . frequency_ ;
2020-04-05 17:00:22 +00:00
GLOBALS : : get ( ) . par_ . coord_format_lat_ = payload . second . coord_format_lat_ ;
GLOBALS : : get ( ) . par_ . coord_format_lon_ = payload . second . coord_format_lon_ ;
2018-11-08 12:36:21 +00:00
cout < < C_MAGENTA < < " Loading parameters for payload " < < i_payload_id < < C_OFF < < endl ;
cout < < " \t baud: " < < payload . second . baud_ < < endl ;
cout < < " \t ascii_bits: " < < payload . second . ascii_bits_ < < endl ;
cout < < " \t ascii_stops: " < < payload . second . ascii_stops_ < < endl ;
cout < < " \t frequency: " < < payload . second . frequency_ < < endl ;
return 1 ;
}
}
}
return 0 ;
}
} // namespace
2018-11-02 15:06:08 +00:00
void prog_opts ( int ac , char * av [ ] )
{
namespace po = boost : : program_options ;
using namespace std ;
try
{
po : : options_description generic ( " CLI opts " ) ;
generic . add_options ( )
( " help " , " Display help message " )
2019-02-02 12:10:29 +00:00
( " device " , po : : value < int > ( ) , " SDR Device Number. -1 to list " )
2019-02-15 11:16:43 +00:00
( " sampling_rate " , po : : value < double > ( ) - > default_value ( GLOBALS : : get ( ) . par_ . sampling_rate_ ) , " Sampling Rate, as supported by device " )
2019-11-20 12:16:53 +00:00
( " no_exit " , po : : value < bool > ( ) , " Constantly retry on missing device instead of exit. " )
2018-11-02 15:06:08 +00:00
2018-11-19 19:26:27 +00:00
( " port " , po : : value < string > ( ) , " Command Port, example: --port 127.0.0.1:5555 " )
2018-11-09 13:51:06 +00:00
2018-11-19 19:26:27 +00:00
( " station " , po : : value < string > ( ) , " HABHUB station callsign " )
2018-11-09 13:51:06 +00:00
( " latlon " , po : : value < std : : vector < float > > ( ) - > multitoken ( ) , " station GPS location (decimal) " )
2019-04-08 13:38:51 +00:00
( " alt " , po : : value < float > ( ) , " station altitude in meters " )
2018-11-02 15:06:08 +00:00
( " freq " , po : : value < float > ( ) , " frequency in MHz " )
2018-11-15 13:48:53 +00:00
( " ppm " , po : : value < float > ( ) , " frequency correction in PPM " )
2018-11-02 15:06:08 +00:00
( " gain " , po : : value < int > ( ) , " gain " )
( " print " , po : : value < bool > ( ) , " live print received chars, values: 0, 1 " )
2018-11-19 19:26:27 +00:00
( " rtty " , po : : value < std : : vector < float > > ( ) - > multitoken ( ) , " rtty: baud bits stops, example: --rtty 300 8 2 " )
2018-11-02 15:06:08 +00:00
( " biast " , po : : value < bool > ( ) , " biasT, values: 0, 1 " )
( " bias_t " , po : : value < bool > ( ) , " biasT, values: 0, 1 " )
( " afc " , po : : value < bool > ( ) , " Auto Frequency Correction, values: 0, 1 " )
2019-02-15 11:16:43 +00:00
( " usb_pack " , po : : value < bool > ( ) , " AirSpy USB bit packing " )
( " dc_remove " , po : : value < bool > ( ) , " DC remove " )
( " dec " , po : : value < int > ( ) , " decimation: 2^dec, range: 0-8 " )
2018-11-07 23:38:22 +00:00
2019-02-07 19:13:54 +00:00
( " lowpass " , po : : value < float > ( ) , " lowpass bandwidth in Hertz " )
( " lp_trans " , po : : value < float > ( ) , " lowpass transition width. (0-1) " )
2018-11-08 12:36:21 +00:00
( " sentence_cmd " , po : : value < string > ( ) , " Call external command with sentence as parameter " )
( " flights " , po : : value < int > ( ) - > implicit_value ( 0 ) , " List Habitat flights " )
( " payload " , po : : value < string > ( ) , " Configure for Payload ID " )
2020-04-05 17:00:22 +00:00
( " nmea " , po : : value < bool > ( ) , " assume NMEA lat/lon format: ddmm.mmmm " )
2020-04-24 11:43:02 +00:00
( " ssdv_dir " , po : : value < string > ( ) - > default_value ( GLOBALS : : get ( ) . par_ . ssdv_dir_ ) , " SSDV directory. " )
2018-11-02 15:06:08 +00:00
;
po : : options_description cli_options ( " Command Line Interface options " ) ;
cli_options . add ( generic ) ;
string config_file ;
cli_options . add_options ( )
2019-05-06 15:10:09 +00:00
( " config " , po : : value < string > ( & config_file ) , " Last run config file. Autosaved on every successful decode. " ) ;
2018-11-02 15:06:08 +00:00
// ("config", po::value<string>(&config_file)->default_value("./habdecWebsocketServer.opts"), "Last run config file. Autosaved on every successfull decode.");
po : : options_description file_options ;
file_options . add ( generic ) ;
po : : variables_map vm ;
store ( po : : command_line_parser ( ac , av ) . options ( cli_options ) . allow_unregistered ( ) . run ( ) , vm ) ;
notify ( vm ) ;
if ( vm . count ( " help " ) )
{
cout < < cli_options < < endl ;
exit ( 0 ) ;
}
if ( config_file ! = " " )
{
ifstream ifs ( config_file . c_str ( ) ) ;
if ( ! ifs )
{
cout < < " Can not open config file: " < < config_file < < endl ;
}
else
{
cout < < C_RED < < " Reading config from file " < < config_file < < C_OFF < < endl ;
store ( parse_config_file ( ifs , file_options , 1 ) , vm ) ;
notify ( vm ) ;
}
}
if ( vm . count ( " device " ) )
{
2019-02-15 11:16:43 +00:00
GLOBALS : : get ( ) . par_ . device_ = vm [ " device " ] . as < int > ( ) ;
2018-11-02 15:06:08 +00:00
}
if ( vm . count ( " sampling_rate " ) )
{
2019-02-15 11:16:43 +00:00
GLOBALS : : get ( ) . par_ . sampling_rate_ = vm [ " sampling_rate " ] . as < double > ( ) ;
2018-11-02 15:06:08 +00:00
}
if ( vm . count ( " port " ) ) // [host:][port]
{
smatch match ;
regex_match ( vm [ " port " ] . as < string > ( ) , match , std : : regex ( R " _(([ \ w \ .]*)( \ :?)( \ d*))_ " ) ) ;
if ( match . size ( ) = = 4 )
{
if ( match [ 2 ] = = " " & & match [ 3 ] = = " " ) // special case when only port is given: --port 5555
{
2019-02-15 11:16:43 +00:00
GLOBALS : : get ( ) . par_ . command_port_ = stoi ( match [ 1 ] ) ;
2018-11-02 15:06:08 +00:00
}
else
{
2019-02-15 11:16:43 +00:00
if ( match [ 1 ] ! = " " ) GLOBALS : : get ( ) . par_ . command_host_ = match [ 1 ] ;
if ( match [ 3 ] ! = " " ) GLOBALS : : get ( ) . par_ . command_port_ = stoi ( match [ 3 ] ) ;
2018-11-02 15:06:08 +00:00
}
}
}
if ( vm . count ( " station " ) )
{
2019-02-15 11:16:43 +00:00
GLOBALS : : get ( ) . par_ . station_callsign_ = vm [ " station " ] . as < string > ( ) ;
2018-11-02 15:06:08 +00:00
}
2018-11-08 12:36:21 +00:00
if ( vm . count ( " payload " ) )
{
2019-02-15 11:16:43 +00:00
GLOBALS : : get ( ) . par_ . habitat_payload_ = vm [ " payload " ] . as < string > ( ) ;
if ( ! LoadPayloadParameters ( GLOBALS : : get ( ) . par_ . habitat_payload_ ) )
cout < < C_RED < < " Failed loading payload " < < GLOBALS : : get ( ) . par_ . habitat_payload_ < < endl ;
2018-11-08 12:36:21 +00:00
}
2018-11-07 23:38:22 +00:00
if ( vm . count ( " sentence_cmd " ) )
{
2019-02-15 11:16:43 +00:00
GLOBALS : : get ( ) . par_ . sentence_cmd_ = vm [ " sentence_cmd " ] . as < string > ( ) ;
2018-11-07 23:38:22 +00:00
}
2018-11-02 15:06:08 +00:00
if ( vm . count ( " freq " ) )
{
2019-02-15 11:16:43 +00:00
GLOBALS : : get ( ) . par_ . frequency_ = vm [ " freq " ] . as < float > ( ) * 1e6 ;
2018-11-02 15:06:08 +00:00
}
2018-11-15 13:48:53 +00:00
if ( vm . count ( " ppm " ) )
{
2019-02-15 11:16:43 +00:00
GLOBALS : : get ( ) . par_ . ppm_ = vm [ " ppm " ] . as < float > ( ) ;
2018-11-15 13:48:53 +00:00
}
2018-11-02 15:06:08 +00:00
if ( vm . count ( " gain " ) )
{
2019-02-15 11:16:43 +00:00
GLOBALS : : get ( ) . par_ . gain_ = vm [ " gain " ] . as < int > ( ) ;
2018-11-02 15:06:08 +00:00
}
if ( vm . count ( " print " ) )
{
2019-02-15 11:16:43 +00:00
GLOBALS : : get ( ) . par_ . live_print_ = vm [ " print " ] . as < bool > ( ) ;
2018-11-02 15:06:08 +00:00
}
2019-11-20 12:16:53 +00:00
if ( vm . count ( " no_exit " ) )
{
GLOBALS : : get ( ) . par_ . no_exit_ = vm [ " no_exit " ] . as < bool > ( ) ;
}
2018-11-02 15:06:08 +00:00
if ( vm . count ( " biast " ) )
{
2019-02-15 11:16:43 +00:00
GLOBALS : : get ( ) . par_ . biast_ = vm [ " biast " ] . as < bool > ( ) ;
2018-11-02 15:06:08 +00:00
}
if ( vm . count ( " bias_t " ) )
{
2019-02-15 11:16:43 +00:00
GLOBALS : : get ( ) . par_ . biast_ = vm [ " bias_t " ] . as < bool > ( ) ;
2018-11-02 15:06:08 +00:00
}
if ( vm . count ( " afc " ) )
{
2019-02-15 11:16:43 +00:00
GLOBALS : : get ( ) . par_ . afc_ = vm [ " afc " ] . as < bool > ( ) ;
2018-11-02 15:06:08 +00:00
}
2018-12-04 21:32:09 +00:00
if ( vm . count ( " usb_pack " ) )
{
2019-02-15 11:16:43 +00:00
GLOBALS : : get ( ) . par_ . usb_pack_ = vm [ " usb_pack " ] . as < bool > ( ) ;
2018-12-04 21:32:09 +00:00
}
2018-12-05 21:11:13 +00:00
if ( vm . count ( " dc_remove " ) )
{
2019-02-15 11:16:43 +00:00
GLOBALS : : get ( ) . par_ . dc_remove_ = vm [ " dc_remove " ] . as < bool > ( ) ;
2018-12-05 21:11:13 +00:00
}
2019-02-07 19:13:54 +00:00
if ( vm . count ( " lowpass " ) )
{
2019-02-15 11:16:43 +00:00
GLOBALS : : get ( ) . par_ . lowpass_bw_Hz_ = vm [ " lowpass " ] . as < float > ( ) ;
2019-02-07 19:13:54 +00:00
}
if ( vm . count ( " lp_trans " ) )
{
2019-02-15 11:16:43 +00:00
GLOBALS : : get ( ) . par_ . lowpass_tr_ = vm [ " lp_trans " ] . as < float > ( ) ;
}
if ( vm . count ( " dec " ) )
{
GLOBALS : : get ( ) . par_ . decimation_ = std : : max ( 0 , vm [ " dec " ] . as < int > ( ) ) ;
2019-02-07 19:13:54 +00:00
}
2018-11-02 15:06:08 +00:00
if ( vm . count ( " rtty " ) )
{
vector < float > rtty_tokens = vm [ " rtty " ] . as < vector < float > > ( ) ;
if ( rtty_tokens . size ( ) ! = 3 )
{
cout < < C_RED < < " --rtty option needs 3 args: baud ascii-bits stop-bits " < < C_OFF < < endl ;
exit ( 1 ) ;
}
if ( rtty_tokens [ 2 ] ! = 1 & & rtty_tokens [ 2 ] ! = 2 )
{
cout < < C_RED < < " Only 1 or 2 stop bits are supported. " < < C_OFF < < endl ;
exit ( 1 ) ;
}
if ( rtty_tokens [ 1 ] ! = 7 & & rtty_tokens [ 1 ] ! = 8 )
{
cout < < C_RED < < " ASCII Bits must be 7 or 8 " < < C_OFF < < endl ;
exit ( 1 ) ;
}
2019-02-15 11:16:43 +00:00
GLOBALS : : get ( ) . par_ . baud_ = rtty_tokens [ 0 ] ;
GLOBALS : : get ( ) . par_ . rtty_ascii_bits_ = rtty_tokens [ 1 ] ;
GLOBALS : : get ( ) . par_ . rtty_ascii_stops_ = rtty_tokens [ 2 ] ;
2018-11-02 15:06:08 +00:00
}
2018-11-08 12:36:21 +00:00
if ( vm . count ( " flights " ) )
{
2018-11-09 13:51:06 +00:00
using namespace habdec : : habitat ;
2018-11-08 12:36:21 +00:00
int hours_offset = vm [ " flights " ] . as < int > ( ) ;
cout < < " Habitat Flights: " < < endl ;
std : : map < std : : string , HabitatFlight > payloads = ListFlights ( hours_offset ) ;
for ( auto & flight : payloads )
cout < < flight . second < < endl ;
exit ( 0 ) ;
}
2020-04-05 17:00:22 +00:00
if ( vm . count ( " nmea " ) & & vm [ " nmea " ] . as < bool > ( ) )
{
GLOBALS : : get ( ) . par_ . coord_format_lat_ = " ddmm.mmmm " ;
GLOBALS : : get ( ) . par_ . coord_format_lon_ = " ddmm.mmmm " ;
}
2018-11-09 13:51:06 +00:00
if ( vm . count ( " latlon " ) )
{
vector < float > latlon_vec = vm [ " latlon " ] . as < vector < float > > ( ) ;
if ( latlon_vec . size ( ) ! = 2 )
{
cout < < C_RED < < " --latlon option needs 2 args " < < C_OFF < < endl ;
exit ( 1 ) ;
}
2019-02-15 11:16:43 +00:00
GLOBALS : : get ( ) . par_ . station_lat_ = latlon_vec [ 0 ] ;
GLOBALS : : get ( ) . par_ . station_lon_ = latlon_vec [ 1 ] ;
2018-11-09 13:51:06 +00:00
}
2019-04-08 13:38:51 +00:00
if ( vm . count ( " alt " ) )
{
GLOBALS : : get ( ) . par_ . station_alt_ = vm [ " alt " ] . as < float > ( ) ;
}
2020-04-24 11:43:02 +00:00
if ( vm . count ( " ssdv_dir " ) )
{
GLOBALS : : get ( ) . par_ . ssdv_dir_ = vm [ " ssdv_dir " ] . as < string > ( ) ;
}
2018-11-02 15:06:08 +00:00
}
catch ( exception & e )
{
cout < < e . what ( ) < < " \n " ;
}
GLOBALS : : DumpToFile ( " ./habdecWebsocketServer.opts " ) ;
2019-05-06 15:10:09 +00:00
}