kopia lustrzana https://github.com/ogre/habdec
Porównaj commity
4 Commity
e6e68bff5c
...
7e0108c49b
Autor | SHA1 | Data |
---|---|---|
Michal Fratczak | 7e0108c49b | |
Michal Fratczak | d60b46d1b8 | |
Michal Fratczak | fbb2ac35a5 | |
Michal Fratczak | 82930e34dc |
|
@ -1,15 +1,33 @@
|
|||
# Building HABDEC from source
|
||||
|
||||
To build habdec from source code, you need to build it's dependecies first:
|
||||
- FFTW
|
||||
Habdec relies on following dependencies:
|
||||
- FFTW3
|
||||
- boost (any version with boost-beast 1.66+)
|
||||
- CMake version 3.8.2 (make sure CMake version supports your boost version, otherwise CMake could fail finding stuff)
|
||||
- optionally: FLTK
|
||||
- CMake version 3.8.2+ (make sure CMake version supports your boost version, otherwise CMake could fail finding stuff)
|
||||
|
||||
If you target RaspberryPi, consider starting with PiSDR image https://github.com/luigifcruz/pisdr-image
|
||||
It has preinstalled all dependencies except FFTW.
|
||||
## Simplified Raspberry Pi Build
|
||||
If you target RaspberryPi, consider starting with PiSDR image (https://github.com/luigifcruz/pisdr-image) or DragonOS image (https://cemaxecuter.com/).
|
||||
These systems have all required libraries preinstalled.
|
||||
|
||||
Below are instructions how to obtain and compile each package. Keep in mind, these are WIP and some adjustment to your build env may be needed.
|
||||
You can also try starting with fresh/vanilla Raspberry Pi OS and download dependencies:
|
||||
|
||||
sudo apt install build-essential cmake libfftw3-single3 libboost-dev
|
||||
sudo apt install rtl-sdr soapysdr-tools soapysdr-module-rtlsdr
|
||||
|
||||
|
||||
If all depencencies are preinstalled, use these commands to build habdec:
|
||||
|
||||
git clone --recurse-submodules https://github.com/ogre/habdec.git
|
||||
cd habdec
|
||||
mkdir build
|
||||
cd build
|
||||
cmake -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=Off ../code
|
||||
make
|
||||
make install
|
||||
|
||||
## Full Build With Dependencies
|
||||
|
||||
Below are instructions how to obtain and compile each library. Keep in mind, these are WIP and some adjustment to your build env may be needed.
|
||||
|
||||
For windows, you need to start 64bit build env, ie: `C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvars64.bat`
|
||||
|
||||
|
|
34
README.md
34
README.md
|
@ -2,7 +2,7 @@
|
|||
|
||||
![alt text](./webClientScreenshot.png)
|
||||
|
||||
Habdec is a C++17 software to decode RTTY telemetry from High Altitude Balloons and upload it to [UKHAS Habitat](http://habitat.habhub.org/) and [sondehub.org](https://amateur.sondehub.org)
|
||||
Habdec is a C++17 software to decode RTTY telemetry from High Altitude Balloons and upload it to ~~UKHAS Habitat~~ [sondehub.org](https://amateur.sondehub.org)
|
||||
|
||||
Some facts:
|
||||
- builds and runs on Windows/Linux and x64/RaspberryPI/OdroixXU4 platforms
|
||||
|
@ -73,8 +73,6 @@ CLI opts:
|
|||
--lowpass arg lowpass bandwidth in Hertz
|
||||
--lp_trans arg lowpass transition width. (0-1)
|
||||
--sentence_cmd arg Call external command with sentence as parameter
|
||||
--flights [=arg(=0)] List Habitat flights
|
||||
--payload arg Configure for Payload ID
|
||||
--sondehub arg (=https://api.v2.sondehub.org) sondehub API url
|
||||
```
|
||||
|
||||
|
@ -157,32 +155,13 @@ habdecWebsocketServer.exe --device 0 --sampling_rate 2.5e6
|
|||
--freq 434.5 --gain 20 --biast 1 --afc 1
|
||||
```
|
||||
|
||||
Load configuration for specific Habitat Payload
|
||||
```
|
||||
./habdecWebsocketServer --flights
|
||||
Habitat Flights:
|
||||
Flight: Belice-3 6d8281c7b6e54c0c9f2488c77d043f8a
|
||||
lat/lon: 49.7665 14.4731
|
||||
Payload: DNA-3 289b03bf7a92e06cff8ab4fec1f789bd
|
||||
RS41-1 Belice 10/11/2018 St. Martin's day
|
||||
Flight ID: 6d8281c7b6e54c0c9f2488c77d043f8a
|
||||
freq 434,250,000
|
||||
baud/ascii/stops 50 7 2
|
||||
|
||||
./habdecWebsocketServer --payload 289b03bf7a92e06cff8ab4fec1f789bd
|
||||
Loading parameters for payload 289b03bf7a92e06cff8ab4fec1f789bd
|
||||
baud: 50
|
||||
ascii_bits: 7
|
||||
ascii_stops: 2
|
||||
frequency: 434,250,000
|
||||
```
|
||||
|
||||
|
||||
### Web Client
|
||||
|
||||
To control habdec parameters from your browser:
|
||||
- start browser
|
||||
- open `habitat/code/webClient/index.html` file from disk
|
||||
- open `habdec/code/webClient/index.html` file from disk
|
||||
- set server field ip:port and Connect
|
||||
|
||||
Do not try connecting directly to `http://ip:port ` - habdec is not an HTTP server and you will see this error:
|
||||
|
@ -193,19 +172,14 @@ Do not try connecting directly to `http://ip:port ` - habdec is not an HTTP serv
|
|||
## Known Limitations
|
||||
|
||||
- RTTY Modes **NOT** supported: 5bit baudot, 1.5 bit stop
|
||||
- Decoding will stop if decimation setting is too low or too high. It was tested to work with stream around 40kHz bandwidth.
|
||||
- SSDV images are not uploaded to http://ssdv.habhub.org
|
||||
- Automatic Frequency Correction needs more work. Use consciously. dc_remove=on can help if AFC is confused by center spike.
|
||||
- Connecting from browser is not very reliable yet, sometimes you need to refresh and wait.
|
||||
- habdec was developed and tested with [AirSpy](https://airspy.com/) and [OdroidXU4](http://hardkernel.com/),[RaspberryPI](http://raspberrypi.org). Support for windows and RtlSdr is less tested.
|
||||
|
||||
|
||||
## Reporting Problems
|
||||
|
||||
Use bugtracker, please.
|
||||
|
||||
## Contributions
|
||||
|
||||
Gladly accepted :)
|
||||
Use bugtracker.
|
||||
|
||||
## Authors
|
||||
|
||||
|
|
|
@ -3,11 +3,17 @@
|
|||
include_directories( ${PROJECT_SOURCE_DIR} )
|
||||
include_directories( ${CMAKE_CURRENT_SOURCE_DIR} )
|
||||
|
||||
set ( FFTW3f_DIR ../CMake )
|
||||
find_package( FFTW3f REQUIRED )
|
||||
include_directories( ${FFTW3f_INCLUDE_DIRS} )
|
||||
message( "FFTW Include:" ${FFTW3f_INCLUDE_DIRS} )
|
||||
message( "FFTW Lib:" ${FFTW3f_LIBRARIES} )
|
||||
if(DEFINED FFTW_ROOT) # custom FFTW build
|
||||
set ( FFTW3f_DIR ../CMake )
|
||||
find_package( FFTW3f REQUIRED )
|
||||
include_directories( ${FFTW3f_INCLUDE_DIRS} )
|
||||
message( "FFTW Include:" ${FFTW3f_INCLUDE_DIRS} )
|
||||
message( "FFTW Lib:" ${FFTW3f_LIBRARIES} )
|
||||
else()
|
||||
find_package(PkgConfig REQUIRED)
|
||||
pkg_search_module(FFTW REQUIRED fftw3f IMPORTED_TARGET)
|
||||
link_libraries (PkgConfig::FFTW)
|
||||
endif()
|
||||
|
||||
|
||||
# RTTY DECODER
|
||||
|
|
|
@ -1,65 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
||||
namespace habdec
|
||||
{
|
||||
namespace habitat
|
||||
{
|
||||
|
||||
std::string HabitatUploadSentence(
|
||||
const std::string& i_sentence,
|
||||
const std::string& i_listener_callsign
|
||||
);
|
||||
|
||||
|
||||
struct HabitatPayload
|
||||
{
|
||||
std::string name_ {""};
|
||||
std::string id_ {""};
|
||||
std::string flight_id_ {""};
|
||||
std::string desc_ {""};
|
||||
int frequency_ = 0;
|
||||
int baud_ = 0;
|
||||
int ascii_bits_ = 0;
|
||||
int ascii_stops_ = 0;
|
||||
std::string coord_format_lat_ {""}; // dd.dddd or dd.mm.mmmm
|
||||
std::string coord_format_lon_ {""}; // dd.dddd or dd.mm.mmmm
|
||||
};
|
||||
|
||||
std::ostream&
|
||||
operator<<(std::ostream& os, const HabitatPayload& p);
|
||||
|
||||
|
||||
struct HabitatFlight
|
||||
{
|
||||
std::string id_ {""};
|
||||
std::string name_ {""};
|
||||
float lat_ = 0;
|
||||
float lon_ = 0;
|
||||
std::map<std::string, HabitatPayload> payloads_;
|
||||
};
|
||||
|
||||
std::ostream&
|
||||
operator<<(std::ostream& os, const HabitatFlight& f);
|
||||
|
||||
|
||||
std::map<std::string, HabitatFlight>
|
||||
ListFlights(int hour_offset);
|
||||
|
||||
|
||||
int UploadStationInfo(
|
||||
const std::string& i_callsign,
|
||||
const std::string& i_radio
|
||||
);
|
||||
|
||||
int UploadStationTelemetry(
|
||||
const std::string& i_callsign,
|
||||
const float i_lat, const float i_lon,
|
||||
const float i_alt, const float i_speed,
|
||||
bool i_chase
|
||||
);
|
||||
|
||||
} // namespace habitat
|
||||
} // namespace habdec
|
|
@ -1,177 +0,0 @@
|
|||
|
||||
#include "habitat_interface.h"
|
||||
#include "common/http_request.h"
|
||||
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <chrono>
|
||||
|
||||
#include <boost/property_tree/ptree.hpp>
|
||||
#include <boost/property_tree/json_parser.hpp>
|
||||
|
||||
#include "common/console_colors.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
std::string FlightsListUrl(int hour_offset = 0)
|
||||
{
|
||||
using namespace std;
|
||||
|
||||
auto now = chrono::system_clock::now() + chrono::hours(hour_offset);
|
||||
long int secs_since_ep = chrono::duration_cast<chrono::seconds>(
|
||||
now.time_since_epoch() ).count();
|
||||
|
||||
return string("/habitat/_design/flight/_view/end_start_including_payloads?startkey=["
|
||||
+ to_string(secs_since_ep) + "]"
|
||||
+ "&include_docs=True");
|
||||
}
|
||||
|
||||
|
||||
|
||||
std::map<std::string, habdec::habitat::HabitatFlight> ParseFlightsJson(const std::string& i_json_str)
|
||||
{
|
||||
using namespace std;
|
||||
namespace pt = boost::property_tree;
|
||||
using namespace habdec::habitat;
|
||||
|
||||
pt::ptree root;
|
||||
stringstream ss; ss << i_json_str;
|
||||
pt::read_json(ss, root);
|
||||
|
||||
std::map<string, HabitatFlight> flights_map;
|
||||
|
||||
// flights
|
||||
//
|
||||
for( pt::ptree::value_type& row : root.get_child("rows") )
|
||||
{
|
||||
auto& doc = row.second.get_child("doc");
|
||||
|
||||
if( doc.get<string>("type") != "flight" )
|
||||
continue;
|
||||
/*if( !doc.get<bool>("approved") )
|
||||
continue;*/
|
||||
|
||||
HabitatFlight _f;
|
||||
|
||||
_f.name_ = doc.get<string>("name");
|
||||
_f.id_ = doc.get<string>("_id");
|
||||
_f.lat_ = doc.get_child("launch").get_child("location").get<float>("latitude");
|
||||
_f.lon_ = doc.get_child("launch").get_child("location").get<float>("longitude");
|
||||
|
||||
flights_map[_f.id_] = _f;
|
||||
}
|
||||
|
||||
// payloads
|
||||
//
|
||||
for( pt::ptree::value_type& row : root.get_child("rows") )
|
||||
{
|
||||
auto& doc = row.second.get_child("doc");
|
||||
|
||||
if( doc.get<string>("type") != "payload_configuration" )
|
||||
continue;
|
||||
|
||||
HabitatPayload _p;
|
||||
|
||||
_p.flight_id_ = row.second.get<string>("id");
|
||||
_p.name_ = doc.get<string>("name");
|
||||
_p.id_ = doc.get<string>("_id");
|
||||
if( doc.count("metadata") )
|
||||
_p.desc_ = doc.get_child("metadata").get<string>("description", "no description");
|
||||
|
||||
auto& transmissions = doc.get_child("transmissions");
|
||||
for(auto& t : transmissions )
|
||||
{
|
||||
if( t.second.get<string>("modulation") != "RTTY" )
|
||||
continue;
|
||||
|
||||
string ascii_bits = t.second.get<string>("encoding");
|
||||
if( ascii_bits == "ASCII-7" )
|
||||
_p.ascii_bits_ = 7;
|
||||
else if( ascii_bits == "ASCII-8" )
|
||||
_p.ascii_bits_ = 8;
|
||||
else
|
||||
continue;
|
||||
|
||||
_p.baud_ = t.second.get<float>("baud");
|
||||
_p.ascii_stops_ = t.second.get<float>("stop");
|
||||
_p.frequency_ = t.second.get<float>("frequency");
|
||||
|
||||
break; // use first of RTTY transmissions
|
||||
}
|
||||
|
||||
auto& sentences = doc.get_child("sentences");
|
||||
for(auto& sentence : sentences)
|
||||
{
|
||||
auto& fields = sentence.second.get_child("fields");
|
||||
for(auto& field : fields)
|
||||
{
|
||||
if( field.second.get<string>("name") == "latitude" )
|
||||
_p.coord_format_lat_ = field.second.get<string>("format");
|
||||
if( field.second.get<string>("name") == "longitude" )
|
||||
_p.coord_format_lon_ = field.second.get<string>("format");
|
||||
}
|
||||
}
|
||||
|
||||
if(_p.baud_ && _p.ascii_bits_ && _p.ascii_stops_)
|
||||
flights_map[_p.flight_id_].payloads_[_p.id_] = _p;
|
||||
}
|
||||
|
||||
return flights_map;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
namespace habdec
|
||||
{
|
||||
namespace habitat
|
||||
{
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, const habdec::habitat::HabitatPayload& p)
|
||||
{
|
||||
os << "Payload: " << p.name_ << " "
|
||||
<< C_RED << p.id_ << C_OFF << "\n"
|
||||
<< "\t" << p.desc_ << "\n"
|
||||
<< "\tFlight ID: " << p.flight_id_<< "\n"
|
||||
<< "\tfreq " << p.frequency_ << "\n"
|
||||
<< "\tbaud/ascii/stops "
|
||||
<< p.baud_ << " "
|
||||
<< p.ascii_bits_ << " "
|
||||
<< p.ascii_stops_;
|
||||
return os;
|
||||
}
|
||||
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, const habdec::habitat::HabitatFlight& f)
|
||||
{
|
||||
os << "Flight: " << f.name_ << " " << f.id_ << "\n"
|
||||
<< "\tlat/lon: " << f.lat_ << " " << f.lon_ << "\n";
|
||||
for(const auto& p : f.payloads_)
|
||||
os << p.second << "\n";
|
||||
return os;
|
||||
}
|
||||
|
||||
|
||||
std::map<std::string, habdec::habitat::HabitatFlight> ListFlights(int hour_offset)
|
||||
{
|
||||
using namespace std;
|
||||
using namespace habdec::habitat;
|
||||
|
||||
string docs_json;
|
||||
int result = HttpRequest(
|
||||
"habitat.habhub.org", FlightsListUrl(hour_offset), 80,
|
||||
habdec::HTTP_VERB::kGet, "application/json", "", docs_json );
|
||||
|
||||
std::map<std::string, HabitatFlight> flights;
|
||||
|
||||
if( result )
|
||||
flights = ParseFlightsJson( docs_json );
|
||||
else
|
||||
cout<<"Habitat Flights List error: "<<result<<endl;
|
||||
return flights;
|
||||
}
|
||||
|
||||
} // namespace habitat
|
||||
} // namespace habdec
|
|
@ -1,260 +0,0 @@
|
|||
|
||||
#include "habitat_interface.h"
|
||||
#include "common/http_request.h"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <sstream>
|
||||
#include <chrono>
|
||||
#include <thread>
|
||||
|
||||
#include <boost/date_time/local_time/local_time.hpp>
|
||||
#include <boost/date_time/c_local_time_adjustor.hpp>
|
||||
#include <boost/property_tree/ptree.hpp>
|
||||
#include <boost/property_tree/json_parser.hpp>
|
||||
|
||||
#include "common/picosha2.h"
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
std::string sha256(const std::string& i_str)
|
||||
{
|
||||
using namespace std;
|
||||
vector<unsigned char> hash(picosha2::k_digest_size);
|
||||
picosha2::hash256(i_str.cbegin(), i_str.cend(), hash.begin(), hash.end());
|
||||
return picosha2::bytes_to_hex_string(hash.begin(), hash.end());
|
||||
}
|
||||
|
||||
|
||||
const char encodeLookup[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
const char padCharacter = '=';
|
||||
std::string base64Encode(std::string inputBuffer)
|
||||
{
|
||||
using namespace std;
|
||||
|
||||
string encodedString;
|
||||
encodedString.reserve(((inputBuffer.size()/3) + (inputBuffer.size() % 3 > 0)) * 4);
|
||||
long temp;
|
||||
auto cursor = inputBuffer.begin();
|
||||
for(size_t idx = 0; idx < inputBuffer.size()/3; idx++)
|
||||
{
|
||||
temp = (*cursor++) << 16; //Convert to big endian
|
||||
temp += (*cursor++) << 8;
|
||||
temp += (*cursor++);
|
||||
encodedString.append(1,encodeLookup[(temp & 0x00FC0000) >> 18]);
|
||||
encodedString.append(1,encodeLookup[(temp & 0x0003F000) >> 12]);
|
||||
encodedString.append(1,encodeLookup[(temp & 0x00000FC0) >> 6 ]);
|
||||
encodedString.append(1,encodeLookup[(temp & 0x0000003F) ]);
|
||||
}
|
||||
switch(inputBuffer.size() % 3)
|
||||
{
|
||||
case 1:
|
||||
temp = (*cursor++) << 16; //Convert to big endian
|
||||
encodedString.append(1,encodeLookup[(temp & 0x00FC0000) >> 18]);
|
||||
encodedString.append(1,encodeLookup[(temp & 0x0003F000) >> 12]);
|
||||
encodedString.append(2,padCharacter);
|
||||
break;
|
||||
case 2:
|
||||
temp = (*cursor++) << 16; //Convert to big endian
|
||||
temp += (*cursor++) << 8;
|
||||
encodedString.append(1,encodeLookup[(temp & 0x00FC0000) >> 18]);
|
||||
encodedString.append(1,encodeLookup[(temp & 0x0003F000) >> 12]);
|
||||
encodedString.append(1,encodeLookup[(temp & 0x00000FC0) >> 6 ]);
|
||||
encodedString.append(1,padCharacter);
|
||||
break;
|
||||
}
|
||||
return encodedString;
|
||||
}
|
||||
|
||||
|
||||
std::string UtcNow()
|
||||
{
|
||||
using namespace boost::posix_time;
|
||||
ptime now = second_clock::universal_time();
|
||||
return to_iso_extended_string(now) + "Z"; // habitat needs Z at the end
|
||||
}
|
||||
|
||||
|
||||
std::string SentenceToHabJson(
|
||||
const std::string& i_sentence,
|
||||
const std::string& i_listener_callsign
|
||||
)
|
||||
{
|
||||
using namespace std;
|
||||
using namespace boost::posix_time;
|
||||
|
||||
ptime now = second_clock::universal_time();
|
||||
string utc_now_str = to_iso_extended_string(now) + "Z"; // habitat needs Z at the end
|
||||
|
||||
boost::property_tree::ptree root;
|
||||
root.put( "type", "payload_telemetry" );
|
||||
root.put( "data._raw", i_sentence );
|
||||
root.put( "receivers." + i_listener_callsign + ".time_created", utc_now_str );
|
||||
root.put( "receivers." + i_listener_callsign + ".time_uploaded", utc_now_str );
|
||||
|
||||
stringstream ss;
|
||||
boost::property_tree::json_parser::write_json(ss, root);
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
namespace habdec
|
||||
{
|
||||
namespace habitat
|
||||
{
|
||||
|
||||
std::string HabitatUploadSentence(
|
||||
const std::string& i_sentence,
|
||||
const std::string& i_listener_callsign
|
||||
)
|
||||
{
|
||||
using namespace std;
|
||||
|
||||
string sentence = i_sentence;
|
||||
|
||||
if( sentence.compare(0, 2, "$$") )
|
||||
sentence = "$$" + sentence;
|
||||
|
||||
if( sentence.compare(sentence.size()-1, 1, "\n") )
|
||||
sentence += "\n";
|
||||
|
||||
string sentence_b64 = base64Encode(sentence);
|
||||
string sentence_sha256 = sha256(sentence_b64);
|
||||
string sentence_json = SentenceToHabJson(sentence_b64, i_listener_callsign);
|
||||
|
||||
string result;
|
||||
// return result;
|
||||
|
||||
int retries_left = 5;
|
||||
while( retries_left-- )
|
||||
{
|
||||
int http_result = HttpRequest(
|
||||
"habitat.habhub.org",
|
||||
"/habitat/_design/payload_telemetry/_update/add_listener/" + sentence_sha256,
|
||||
80,
|
||||
habdec::HTTP_VERB::kPost,
|
||||
"application/json",
|
||||
sentence_json,
|
||||
result
|
||||
);
|
||||
|
||||
switch( http_result )
|
||||
{
|
||||
case 201: // Success
|
||||
case 403: // Success, sentence has already seen by others
|
||||
retries_left = 0;
|
||||
break;
|
||||
case 409: // Upload conflict (server busy). Sleep for a moment, then retry
|
||||
default:
|
||||
this_thread::sleep_for( ( chrono::duration<double, milli>(300) ) );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
int UploadStationInfo(
|
||||
const std::string& i_callsign,
|
||||
const std::string& i_radio
|
||||
)
|
||||
{
|
||||
using namespace std;
|
||||
using namespace boost::posix_time;
|
||||
using namespace habdec;
|
||||
|
||||
ptime now = second_clock::universal_time();
|
||||
string utc_now_str = to_iso_extended_string(now) + "Z"; // habitat needs Z at the end
|
||||
|
||||
const string info_template = R"_(
|
||||
{
|
||||
"type": "listener_information",
|
||||
"data": {"callsign": "$callsign", "radio": "$radio" },
|
||||
"time_created": "$time",
|
||||
"time_uploaded": "$time"
|
||||
}
|
||||
)_";
|
||||
|
||||
string info_data_str = info_template;
|
||||
info_data_str.replace( info_data_str.find("$callsign"), 9, i_callsign );
|
||||
info_data_str.replace( info_data_str.find("$time"), 5, utc_now_str );
|
||||
info_data_str.replace( info_data_str.find("$time"), 5, utc_now_str );
|
||||
info_data_str.replace( info_data_str.find("$radio"), 6, i_radio );
|
||||
|
||||
string http_req_result;
|
||||
int res = HttpRequest(
|
||||
"habitat.habhub.org",
|
||||
"/habitat",
|
||||
80,
|
||||
habdec::HTTP_VERB::kPost,
|
||||
"application/json",
|
||||
info_data_str,
|
||||
http_req_result
|
||||
);
|
||||
return res;
|
||||
}
|
||||
|
||||
int UploadStationTelemetry(
|
||||
const std::string& i_callsign,
|
||||
const float i_lat, const float i_lon,
|
||||
const float i_alt, const float i_speed,
|
||||
bool i_chase
|
||||
)
|
||||
{
|
||||
using namespace std;
|
||||
using namespace boost::posix_time;
|
||||
using namespace habdec;
|
||||
|
||||
ptime now = second_clock::universal_time();
|
||||
string utc_now_str = to_iso_extended_string(now) + "Z"; // habitat needs Z at the end
|
||||
|
||||
const string telemetry_template = R"_(
|
||||
{
|
||||
"type": "listener_telemetry",
|
||||
"time_created": "$time",
|
||||
"time_uploaded": "$time",
|
||||
"data": {
|
||||
"callsign": "$callsign",
|
||||
"latitude": $lat,
|
||||
"longitude": $lon,
|
||||
"altitude": $alt,
|
||||
"speed": $speed,
|
||||
"chase": $chase
|
||||
}
|
||||
}
|
||||
)_";
|
||||
|
||||
string telemetry_data_str = telemetry_template;
|
||||
telemetry_data_str.replace( telemetry_data_str.find("$callsign"), 9, i_callsign );
|
||||
telemetry_data_str.replace( telemetry_data_str.find("$time"), 5, utc_now_str );
|
||||
telemetry_data_str.replace( telemetry_data_str.find("$time"), 5, utc_now_str );
|
||||
telemetry_data_str.replace( telemetry_data_str.find("$lat"), 4, to_string(i_lat) );
|
||||
telemetry_data_str.replace( telemetry_data_str.find("$lon"), 4, to_string(i_lon) );
|
||||
telemetry_data_str.replace( telemetry_data_str.find("$alt"), 4, to_string(i_alt) );
|
||||
telemetry_data_str.replace( telemetry_data_str.find("$speed"), 6, to_string(i_speed) );
|
||||
telemetry_data_str.replace( telemetry_data_str.find("$chase"), 6, i_chase ? "true" : "false" );
|
||||
|
||||
string http_req_result;
|
||||
int res = HttpRequest(
|
||||
"habitat.habhub.org",
|
||||
"/habitat",
|
||||
80,
|
||||
habdec::HTTP_VERB::kPost,
|
||||
"application/json",
|
||||
telemetry_data_str,
|
||||
http_req_result
|
||||
);
|
||||
|
||||
return res;
|
||||
|
||||
}
|
||||
|
||||
} // namespace habitat
|
||||
} // namespace habdec
|
|
@ -137,7 +137,6 @@ def SendCommand(i_cmd):
|
|||
set:decimation=2 get:decimation
|
||||
set:afc=1 get:afc
|
||||
set:dc_remove=1 get:dc_remove
|
||||
set:payload=9f25cc048d401ebed112479a2ecef4f8
|
||||
power:res=512,zoom=0.5
|
||||
demod:res=256
|
||||
liveprint
|
||||
|
|
|
@ -131,7 +131,6 @@ input[type=checkbox]
|
|||
z-index: 1;
|
||||
}
|
||||
|
||||
/* Payload Button */
|
||||
.MenuDropMenu button {
|
||||
display: block;
|
||||
/* color: black; */
|
||||
|
|
|
@ -208,132 +208,6 @@ function toggleFullscreen(elem)
|
|||
}
|
||||
|
||||
|
||||
////////////////////////////////////////
|
||||
///////////// Flights Menu /////////////
|
||||
////////////////////////////////////////
|
||||
|
||||
function LoadFlightsData()
|
||||
{
|
||||
var d = new Date();
|
||||
var now = d.getTime() / 1000;
|
||||
var _url = 'http://habitat.habhub.org/habitat/_design/flight/_view/end_start_including_payloads?startkey=[' + now + ']&include_docs=True'
|
||||
console.debug(_url);
|
||||
|
||||
let xhr = new XMLHttpRequest();
|
||||
xhr.open('GET', _url);
|
||||
xhr.onload = function () {
|
||||
if (xhr.status != 200) {
|
||||
console.debug("LoadFlightsData failed. Status: ", xhr.status);
|
||||
} else {
|
||||
LoadFlightsData_CB( JSON.parse(xhr.responseText) )
|
||||
}
|
||||
};
|
||||
xhr.onerror = function () { alert("LoadFlightsData: Request to HTTP server failed."); };
|
||||
xhr.send();
|
||||
}
|
||||
|
||||
|
||||
function LoadFlightsData_CB(i_data)
|
||||
{
|
||||
var FLIGHTS = {};
|
||||
|
||||
var flights = i_data["rows"];
|
||||
|
||||
for(i in flights)
|
||||
{
|
||||
var _id = flights[i]["id"];
|
||||
var doc = flights[i]["doc"];
|
||||
|
||||
if(doc["type"] == "flight")
|
||||
{
|
||||
var payloads = doc["payloads"];
|
||||
if(payloads && payloads.length)
|
||||
{
|
||||
FLIGHTS[_id] = {};
|
||||
FLIGHTS[_id]["payloads"] = {};
|
||||
for(p in payloads)
|
||||
{
|
||||
var payload_id = doc["payloads"][p];
|
||||
FLIGHTS[_id]["payloads"][payload_id] = {};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for(i in flights)
|
||||
{
|
||||
var _id = flights[i]["id"];
|
||||
var doc = flights[i]["doc"];
|
||||
|
||||
if(doc["type"] == "payload_configuration")
|
||||
{
|
||||
var payload_id = doc["_id"];
|
||||
var transmissions = doc["transmissions"];
|
||||
|
||||
for(t_id in transmissions)
|
||||
{
|
||||
if(transmissions[t_id]["modulation"] == "RTTY")
|
||||
{
|
||||
FLIGHTS[_id]["payloads"][payload_id]["name"] = doc["name"];
|
||||
FLIGHTS[_id]["payloads"][payload_id]["name"] = doc["name"];
|
||||
FLIGHTS[_id]["payloads"][payload_id]["frequency"] = transmissions[t_id]["frequency"];
|
||||
FLIGHTS[_id]["payloads"][payload_id]["baud"] = transmissions[t_id]["baud"];
|
||||
FLIGHTS[_id]["payloads"][payload_id]["encoding"] = transmissions[t_id]["encoding"];
|
||||
FLIGHTS[_id]["payloads"][payload_id]["stop"] = transmissions[t_id]["stop"];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
UpdatePayloadsButton( FLIGHTS );
|
||||
}
|
||||
|
||||
function CreatePayloadsButton()
|
||||
{
|
||||
var PayloadsWrapperDiv = document.getElementById("PayloadsWrapperDiv");
|
||||
PayloadsWrapperDiv.classList.add("MenuDropdownWrapper");
|
||||
|
||||
var PayloadsButton = document.createElement("button");
|
||||
PayloadsButton.classList.add("MenuDropButton");
|
||||
PayloadsButton.id = "HabDec_PayloadsButton";
|
||||
PayloadsButton.onclick = function() { document.getElementById("PayloadsDropMenuDiv").classList.toggle("show") };
|
||||
PayloadsButton.innerHTML = "HabHub Flights";
|
||||
PayloadsWrapperDiv.appendChild(PayloadsButton);
|
||||
|
||||
var DropMenuDiv = document.createElement("div");
|
||||
DropMenuDiv.id = "PayloadsDropMenuDiv";
|
||||
DropMenuDiv.classList.add("MenuDropMenu");
|
||||
PayloadsWrapperDiv.appendChild(DropMenuDiv);
|
||||
|
||||
LoadFlightsData();
|
||||
}
|
||||
|
||||
function UpdatePayloadsButton(i_Flights)
|
||||
{
|
||||
var DropMenuDiv = document.getElementById("PayloadsDropMenuDiv");
|
||||
|
||||
for(f_id in i_Flights)
|
||||
{
|
||||
for(p_id in i_Flights[f_id]["payloads"])
|
||||
(
|
||||
function(p_id)
|
||||
{
|
||||
var payload = i_Flights[f_id]["payloads"][p_id];
|
||||
var label = payload["name"] + ": " + payload["baud"] + "Bd " + payload["encoding"] + "/" + payload["stop"] + " " + (parseInt(payload["frequency"])/1000000) + "MHz";
|
||||
|
||||
var pl_button = document.createElement("button");
|
||||
pl_button.innerHTML = label;
|
||||
pl_button.onclick = function(){
|
||||
SetPayload(p_id);
|
||||
document.getElementById('HabDec_PayloadsButton').click();
|
||||
};
|
||||
|
||||
DropMenuDiv.appendChild(pl_button);
|
||||
}
|
||||
)(p_id)
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////
|
||||
///////////// Color Schemes ////////////
|
||||
////////////////////////////////////////
|
||||
|
@ -685,10 +559,6 @@ function HABDEC_BUILD_UI(parent_div)
|
|||
var div_server = HABDEC_BUILD_UI_Server();
|
||||
//<!-- <div id="PayloadsWrapperDiv"></div> -->
|
||||
|
||||
// flights list
|
||||
var div_payloads_wrapper = document.createElement("div");
|
||||
div_payloads_wrapper.id = "PayloadsWrapperDiv";
|
||||
|
||||
// color schemes list
|
||||
var div_colors_wrapper = document.createElement("div");
|
||||
div_colors_wrapper.id = "ColorSchemesWrapperDiv";
|
||||
|
@ -700,10 +570,9 @@ function HABDEC_BUILD_UI(parent_div)
|
|||
btnFullscreen.onclick = () => { toggleFullscreen() };
|
||||
div_but_fs.appendChild(btnFullscreen);
|
||||
|
||||
// div for [flights, colors, fillscreen] - in row
|
||||
// div for [colors, fillscreen] - in row
|
||||
var extra_options = document.createElement("div");
|
||||
extra_options.style.display = 'flex';
|
||||
extra_options.appendChild(div_payloads_wrapper);
|
||||
extra_options.appendChild(div_colors_wrapper);
|
||||
extra_options.appendChild(div_but_fs);
|
||||
|
||||
|
@ -717,7 +586,6 @@ function HABDEC_BUILD_UI(parent_div)
|
|||
parent_div.appendChild(extra_options);
|
||||
|
||||
CreateControls();
|
||||
CreatePayloadsButton();
|
||||
CreateColorSchemesButton();
|
||||
|
||||
window.addEventListener('message', HB_WinMsgHandler);
|
||||
|
|
|
@ -442,8 +442,3 @@ function SetDCRemove()
|
|||
button.style.color = "#000";
|
||||
}
|
||||
}
|
||||
|
||||
function SetPayload(i_payload_id)
|
||||
{
|
||||
SendCommand("set:payload=" + i_payload_id);
|
||||
}
|
||||
|
|
|
@ -6,13 +6,23 @@ get_git_head_revision(GIT_REFSPEC GIT_SHA1)
|
|||
include_directories( ${PROJECT_SOURCE_DIR} )
|
||||
include_directories( ${CMAKE_CURRENT_SOURCE_DIR} )
|
||||
|
||||
set ( FFTW3f_DIR ../CMake )
|
||||
find_package( FFTW3f REQUIRED )
|
||||
include_directories( ${FFTW3f_INCLUDE_DIRS} )
|
||||
if(DEFINED FFTW_ROOT) # custom FFTW build
|
||||
set ( FFTW3f_DIR ../CMake )
|
||||
find_package( FFTW3f REQUIRED )
|
||||
include_directories( ${FFTW3f_INCLUDE_DIRS} )
|
||||
message( "FFTW Include:" ${FFTW3f_INCLUDE_DIRS} )
|
||||
message( "FFTW Lib:" ${FFTW3f_LIBRARIES} )
|
||||
else()
|
||||
find_package(PkgConfig REQUIRED)
|
||||
pkg_search_module(FFTW REQUIRED fftw3f IMPORTED_TARGET)
|
||||
link_libraries (PkgConfig::FFTW)
|
||||
endif()
|
||||
|
||||
# boost
|
||||
set ( Boost_NO_BOOST_CMAKE ON )
|
||||
set ( Boost_NO_SYSTEM_PATHS ON ) #remove line to use system installed boost
|
||||
if(DEFINED BOOST_ROOT) # custom boost build
|
||||
set ( Boost_NO_SYSTEM_PATHS ON ) # don't use system installed boost
|
||||
endif()
|
||||
set ( Boost_USE_STATIC_LIBS ON )
|
||||
add_definitions ( -DBOOST_ALL_NO_LIB )
|
||||
find_package(Boost REQUIRED COMPONENTS program_options system date_time )
|
||||
|
@ -57,8 +67,6 @@ set ( websocketServer_src
|
|||
websocket_session.h websocket_session.cpp
|
||||
ws_server.h ws_server.cpp
|
||||
CompressedVector.h CompressedVector.cpp
|
||||
${CMAKE_SOURCE_DIR}/habitat/habitat_upload.cpp
|
||||
${CMAKE_SOURCE_DIR}/habitat/habitat_list_flights.cpp
|
||||
${CMAKE_SOURCE_DIR}/sondehub/sondehub_uploader.cpp
|
||||
${CMAKE_SOURCE_DIR}/common/http_request.cpp
|
||||
${CMAKE_SOURCE_DIR}/common/GpsDistance.cpp
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
#include <limits>
|
||||
|
||||
namespace habdec
|
||||
{
|
||||
|
@ -83,7 +84,7 @@ public:
|
|||
max_ = *std::max_element(values_.begin(), values_.end());
|
||||
return max_;
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
|
||||
template<typename U>
|
||||
|
|
|
@ -79,7 +79,7 @@ public:
|
|||
int device_ = 0; // index to SoapySDR::Device::enumerate()
|
||||
std::string command_host_ = "0.0.0.0";
|
||||
int command_port_ = 5555;
|
||||
std::string station_callsign_ = ""; // habitat upload
|
||||
std::string station_callsign_ = "";
|
||||
float station_lat_ = 0;
|
||||
float station_lon_ = 0;
|
||||
float station_alt_ = 0;
|
||||
|
@ -100,7 +100,6 @@ public:
|
|||
float lowpass_tr_ = 0.025;
|
||||
bool no_exit_ = false;
|
||||
std::string sentence_cmd_ = "";
|
||||
std::string habitat_payload_ = "";
|
||||
std::string coord_format_lat_ = "dd.dddd"; // encoding of lat/lon coords: dd.dddd or ddmm.mmmm
|
||||
std::string coord_format_lon_ = "dd.dddd"; // encoding of lat/lon coords: dd.dddd or ddmm.mmmm
|
||||
std::string ssdv_dir_ = ".";
|
||||
|
@ -138,7 +137,6 @@ public:
|
|||
&& station_alt_ == rhs.station_alt_
|
||||
&& sampling_rate_ == rhs.sampling_rate_
|
||||
&& sentence_cmd_ == rhs.sentence_cmd_
|
||||
&& habitat_payload_ == rhs.habitat_payload_
|
||||
&& no_exit_ == rhs.no_exit_
|
||||
&& coord_format_lat_ == rhs.coord_format_lat_
|
||||
&& coord_format_lon_ == rhs.coord_format_lon_
|
||||
|
@ -177,7 +175,6 @@ public:
|
|||
oFile<<"lowpass = "<<GLOBALS::get().par_.lowpass_bw_Hz_<<endl;
|
||||
oFile<<"lp_trans = "<<GLOBALS::get().par_.lowpass_tr_<<endl;
|
||||
oFile<<"sentence_cmd = "<<GLOBALS::get().par_.sentence_cmd_<<endl;
|
||||
oFile<<"payload = "<<GLOBALS::get().par_.habitat_payload_<<endl;
|
||||
oFile<<"no_exit = "<<GLOBALS::get().par_.no_exit_<<endl;
|
||||
oFile<<"sondehub = "<<GLOBALS::get().par_.sondehub_<<endl;
|
||||
|
||||
|
@ -199,7 +196,6 @@ public:
|
|||
cout<<"\tcommand_host: "<<GLOBALS::get().par_.command_host_<<endl;
|
||||
cout<<"\tcommand_port: "<<GLOBALS::get().par_.command_port_<<endl;
|
||||
cout<<"\tsentence_cmd: "<<GLOBALS::get().par_.sentence_cmd_<<endl;
|
||||
cout<<"\tpayload: "<<GLOBALS::get().par_.habitat_payload_<<endl;
|
||||
cout<<"\tstation: "<<GLOBALS::get().par_.station_callsign_<<endl;
|
||||
cout<<"\tlatlon: "<<GLOBALS::get().par_.station_lat_<<" "<<GLOBALS::get().par_.station_lon_<<endl;
|
||||
cout<<"\talt: "<<GLOBALS::get().par_.station_alt_<<endl;
|
||||
|
|
|
@ -41,7 +41,6 @@ namespace websocket = boost::beast::websocket;
|
|||
#include "common/console_colors.h"
|
||||
#include "GLOBALS.h"
|
||||
#include "NetTransport.h"
|
||||
#include "habitat/habitat_interface.h"
|
||||
|
||||
|
||||
// i_param == "" --> sends all parameters
|
||||
|
@ -326,60 +325,6 @@ std::vector< std::shared_ptr<HabdecMessage> > HandleCommand(const std::string i
|
|||
GLOBALS::get().par_.dc_remove_ = value;
|
||||
result = EchoParameter("dc_remove");
|
||||
}
|
||||
else if( regex_match(i_command, match, regex(R"_(set\:payload=(\w+))_")) && match.size() > 1 )
|
||||
{
|
||||
using namespace habdec::habitat;
|
||||
|
||||
string payload_id = match[1];
|
||||
std::map<std::string, HabitatFlight> flights;
|
||||
try {
|
||||
flights = ListFlights(0);
|
||||
}
|
||||
catch(const exception& e) {
|
||||
cout<<"Failed loading flights list: "<<e.what()<<endl;
|
||||
return result;
|
||||
}
|
||||
|
||||
auto& DEC = GLOBALS::get().decoder_;
|
||||
|
||||
for(auto& flight : flights)
|
||||
{
|
||||
for(auto& payload : flight.second.payloads_)
|
||||
{
|
||||
if( !payload_id.compare(payload.second.id_) )
|
||||
{
|
||||
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_;
|
||||
GLOBALS::get().par_.coord_format_lat_ = payload.second.coord_format_lat_;
|
||||
GLOBALS::get().par_.coord_format_lon_ = payload.second.coord_format_lon_;
|
||||
|
||||
DEC.baud( GLOBALS::get().par_.baud_ );
|
||||
DEC.rtty_bits( GLOBALS::get().par_.rtty_ascii_bits_ );
|
||||
DEC.rtty_stops( GLOBALS::get().par_.rtty_ascii_stops_ );
|
||||
GLOBALS::get().p_iq_source_->setOption("frequency_double", &GLOBALS::get().par_.frequency_);
|
||||
|
||||
cout<<C_MAGENTA<<"Loading parameters for payload "<<payload_id<<C_OFF<<endl;
|
||||
cout<<"\tbaud: "<<GLOBALS::get().par_.baud_<<endl;
|
||||
cout<<"\tascii_bits: "<<GLOBALS::get().par_.rtty_ascii_bits_<<endl;
|
||||
cout<<"\tascii_stops: "<<GLOBALS::get().par_.rtty_ascii_stops_<<endl;
|
||||
cout<<"\tfrequency: "<<GLOBALS::get().par_.frequency_<<endl;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto res_fr = EchoParameter("frequency");
|
||||
auto res_bd = EchoParameter("baud");
|
||||
auto res_rb = EchoParameter("rtty_bits");
|
||||
auto res_rs = EchoParameter("rtty_stops");
|
||||
result.insert( result.end(), res_fr.begin(), res_fr.end() );
|
||||
result.insert( result.end(), res_bd.begin(), res_bd.end() );
|
||||
result.insert( result.end(), res_rb.begin(), res_rb.end() );
|
||||
result.insert( result.end(), res_rs.begin(), res_rs.end() );
|
||||
}
|
||||
else
|
||||
{
|
||||
cout<<C_RED<<"Unknown command: "<<i_command<<C_OFF<<endl;
|
||||
|
|
|
@ -39,7 +39,6 @@
|
|||
#include "IQSource/IQSource_SoapySDR.h"
|
||||
#include "Decoder/Decoder.h"
|
||||
#include "common/console_colors.h"
|
||||
#include "habitat/habitat_interface.h"
|
||||
#include "GLOBALS.h"
|
||||
#include "ws_server.h"
|
||||
#include "common/git_repo_sha1.h"
|
||||
|
@ -355,20 +354,6 @@ void SentenceCallback( std::string callsign, std::string data, std::string crc,
|
|||
}
|
||||
|
||||
|
||||
// habitat upload
|
||||
if(GLOBALS::get().par_.station_callsign_ != "")
|
||||
{
|
||||
try {
|
||||
string res = habdec::habitat::HabitatUploadSentence( sentence, GLOBALS::get().par_.station_callsign_ );
|
||||
if( res != "OK" )
|
||||
cout<<C_CLEAR<<C_RED<<"HAB Upload result: "<<res<<endl;
|
||||
}
|
||||
catch(const exception& e) {
|
||||
cout<<"Failed upload to habitat: "<<e.what()<<endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// print distance and elevation
|
||||
if( GLOBALS::get().par_.station_lat_ )
|
||||
{
|
||||
|
@ -515,53 +500,42 @@ int main(int argc, char** argv)
|
|||
}
|
||||
|
||||
// station info
|
||||
if( G.par_.station_callsign_ != "" )
|
||||
if( G.par_.station_callsign_ != ""
|
||||
&& G.par_.station_lat_
|
||||
&& G.par_.station_lon_ )
|
||||
{
|
||||
habdec::habitat::UploadStationInfo( G.par_.station_callsign_,
|
||||
device["driver"] + " - habdec" );
|
||||
|
||||
if( G.par_.station_lat_
|
||||
&& G.par_.station_lon_ ) {
|
||||
|
||||
// habitat
|
||||
cout<<"Uploading station info to HabHub."<<endl;
|
||||
habdec::habitat::UploadStationTelemetry(
|
||||
G.par_.station_callsign_,
|
||||
G.par_.station_lat_, G.par_.station_lon_,
|
||||
G.par_.station_alt_, 0, false
|
||||
);
|
||||
// sondehub
|
||||
using json = nlohmann::json;
|
||||
json sh_json;
|
||||
sh_json["software_name"] = "habdec";
|
||||
sh_json["software_version"] = string(g_GIT_SHA1).substr(0,7);
|
||||
sh_json["uploader_callsign"] = G.par_.station_callsign_;
|
||||
sh_json["uploader_position"] = vector<float>{
|
||||
G.par_.station_lat_, G.par_.station_lon_, G.par_.station_alt_};
|
||||
sh_json["uploader_radio"] = device["driver"];
|
||||
sh_json["mobile"] = false;
|
||||
|
||||
// sondehub
|
||||
using json = nlohmann::json;
|
||||
json sh_json;
|
||||
sh_json["software_name"] = "habdec";
|
||||
sh_json["software_version"] = string(g_GIT_SHA1).substr(0,7);
|
||||
sh_json["uploader_callsign"] = G.par_.station_callsign_;
|
||||
sh_json["uploader_position"] = vector<float>{
|
||||
G.par_.station_lat_, G.par_.station_lon_, G.par_.station_alt_};
|
||||
sh_json["uploader_radio"] = device["driver"];
|
||||
sh_json["mobile"] = false;
|
||||
cout<<"Uploading station info to SondeHub."<<endl;
|
||||
// cout<<sh_json<<endl;
|
||||
stringstream s;
|
||||
s<<sh_json;
|
||||
|
||||
cout<<"Uploading station info to SondeHub."<<endl;
|
||||
// cout<<sh_json<<endl;
|
||||
stringstream s;
|
||||
s<<sh_json;
|
||||
|
||||
cpr::Response r = cpr::Put(
|
||||
cpr::Url{G.par_.sondehub_ + "/amateur/listeners"},
|
||||
cpr::Body{s.str()},
|
||||
cpr::Header{
|
||||
{"User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:105.0) Gecko/20100101 Firefox/105.0"},
|
||||
{"Content-Type", "application/json"}
|
||||
}
|
||||
);
|
||||
|
||||
if(r.status_code != 200) {
|
||||
cout<<"sondehub station info upload error:\n";
|
||||
cout<<r.status_code<<endl; // 200
|
||||
cout<<r.header["content-type"]<<endl; // application/json; charset=utf-8
|
||||
cout<<r.text<<endl;
|
||||
cpr::Response r = cpr::Put(
|
||||
cpr::Url{G.par_.sondehub_ + "/amateur/listeners"},
|
||||
cpr::Body{s.str()},
|
||||
cpr::Header{
|
||||
{"User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:105.0) Gecko/20100101 Firefox/105.0"},
|
||||
{"Content-Type", "application/json"}
|
||||
}
|
||||
);
|
||||
|
||||
if(r.status_code != 200) {
|
||||
cout<<"sondehub station info upload error:\n";
|
||||
cout<<r.status_code<<endl; // 200
|
||||
cout<<r.header["content-type"]<<endl; // application/json; charset=utf-8
|
||||
cout<<r.text<<endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -28,46 +28,6 @@
|
|||
|
||||
#include "GLOBALS.h"
|
||||
#include "common/console_colors.h"
|
||||
#include "habitat/habitat_interface.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
int LoadPayloadParameters(std::string i_payload_id)
|
||||
{
|
||||
using namespace std;
|
||||
using namespace habdec::habitat;
|
||||
|
||||
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_) )
|
||||
{
|
||||
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_;
|
||||
GLOBALS::get().par_.coord_format_lat_ = payload.second.coord_format_lat_;
|
||||
GLOBALS::get().par_.coord_format_lon_ = payload.second.coord_format_lon_;
|
||||
|
||||
cout<<C_MAGENTA<<"Loading parameters for payload "<<i_payload_id<<C_OFF<<endl;
|
||||
|
||||
cout<<"\tbaud: "<<payload.second.baud_<<endl;
|
||||
cout<<"\tascii_bits: "<<payload.second.ascii_bits_<<endl;
|
||||
cout<<"\tascii_stops: "<<payload.second.ascii_stops_<<endl;
|
||||
cout<<"\tfrequency: "<<payload.second.frequency_<<endl;
|
||||
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void prog_opts(int ac, char* av[])
|
||||
{
|
||||
|
@ -106,9 +66,6 @@ void prog_opts(int ac, char* av[])
|
|||
|
||||
("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")
|
||||
|
||||
("ssdv_dir", po::value<string>()->default_value(GLOBALS::get().par_.ssdv_dir_), "SSDV directory.")
|
||||
|
||||
("sondehub", po::value<string>()->default_value("https://api.v2.sondehub.org"), "sondehub API url")
|
||||
|
@ -182,12 +139,6 @@ void prog_opts(int ac, char* av[])
|
|||
{
|
||||
GLOBALS::get().par_.station_callsign_ = vm["station"].as<string>();
|
||||
}
|
||||
if (vm.count("payload"))
|
||||
{
|
||||
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;
|
||||
}
|
||||
if (vm.count("sentence_cmd"))
|
||||
{
|
||||
GLOBALS::get().par_.sentence_cmd_ = vm["sentence_cmd"].as<string>();
|
||||
|
@ -268,16 +219,6 @@ void prog_opts(int ac, char* av[])
|
|||
GLOBALS::get().par_.rtty_ascii_bits_ = rtty_tokens[1];
|
||||
GLOBALS::get().par_.rtty_ascii_stops_ = rtty_tokens[2];
|
||||
}
|
||||
if (vm.count("flights"))
|
||||
{
|
||||
using namespace habdec::habitat;
|
||||
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);
|
||||
}
|
||||
if (vm.count("latlon"))
|
||||
{
|
||||
vector<float> latlon_vec = vm["latlon"].as< vector<float> >();
|
||||
|
|
Ładowanie…
Reference in New Issue