Added support for files
This commit is contained in:
parent
2132de6b77
commit
93b94dbcb8
|
|
@ -5,12 +5,30 @@
|
|||
* Author: ezra
|
||||
*/
|
||||
|
||||
#include <iomanip>
|
||||
#include <ctime>
|
||||
#include <sstream>
|
||||
#include <experimental/filesystem>
|
||||
#include <boost/property_tree/ptree.hpp>
|
||||
#include <boost/property_tree/json_parser.hpp>
|
||||
|
||||
#include "Configuration.h"
|
||||
#include "loguru.hpp"
|
||||
|
||||
using namespace piscan;
|
||||
using namespace std::experimental;
|
||||
using namespace boost::property_tree;
|
||||
|
||||
Configuration* Configuration::_config;
|
||||
Configuration& Configuration::getConfig() {
|
||||
if(_config == nullptr)
|
||||
_config = new Configuration();
|
||||
|
||||
return *_config;
|
||||
};
|
||||
|
||||
Configuration::Configuration() {
|
||||
// TODO Auto-generated constructor stub
|
||||
_configPath = DATABASE_PATH;
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -18,3 +36,125 @@ Configuration::~Configuration() {
|
|||
// TODO Auto-generated destructor stub
|
||||
}
|
||||
|
||||
void Configuration::setWorkingPath(std::string path){
|
||||
filesystem::path configPath(path);
|
||||
if(!filesystem::exists(configPath))
|
||||
if(!filesystem::create_directory(configPath)){
|
||||
LOG_F(ERROR, "Could not create working directory %s, reverting to default", path.c_str());
|
||||
_configPath = DATABASE_PATH;
|
||||
return;
|
||||
}
|
||||
|
||||
_configPath = path;
|
||||
LOG_F(INFO, "Config directory: %s", path.c_str());
|
||||
}
|
||||
|
||||
std::string Configuration::getWorkingPath() {
|
||||
return _configPath;
|
||||
}
|
||||
|
||||
void Configuration::loadConfig(){
|
||||
ptree pt;
|
||||
filesystem::path path(_configPath);
|
||||
path += filesystem::path::preferred_separator;
|
||||
path += CONFIG_FILE;
|
||||
if(!filesystem::exists(path)){
|
||||
LOG_F(INFO, "No config file exists, using defaults");
|
||||
return;
|
||||
}
|
||||
|
||||
LOG_F(1, "Config path: %s", path.c_str());
|
||||
LOG_F(INFO, "Loading config");
|
||||
|
||||
try{
|
||||
read_json(path, pt);
|
||||
} catch(boost::property_tree::json_parser_error& e){
|
||||
LOG_F(WARNING, "Error parsing file: %s", e.message().c_str());
|
||||
}
|
||||
|
||||
_generalConfig.logfileVerbosity = pt.get("config.general.log_verbosity", DEFAULT_LOGFILE_VERBOSITY);
|
||||
|
||||
_socketConfig.maxConnections = pt.get("config.socket.max_connections", MAX_TCP_CONNECTIONS);
|
||||
_socketConfig.tcpPort = pt.get("config.socket.port", DEFAULT_TCP_PORT);
|
||||
|
||||
}
|
||||
|
||||
void Configuration::loadState(){
|
||||
ptree pt;
|
||||
filesystem::path path(_configPath);
|
||||
path += filesystem::path::preferred_separator;
|
||||
path += STATE_FILE;;
|
||||
if(!filesystem::exists(path)){
|
||||
LOG_F(INFO, "No state file exists, using defaults");
|
||||
return;
|
||||
}
|
||||
|
||||
LOG_F(1, "State path: %s", path.c_str());
|
||||
LOG_F(INFO, "Loading saved state");
|
||||
|
||||
try{
|
||||
read_json(path, pt);
|
||||
} catch(boost::property_tree::json_parser_error& e){
|
||||
LOG_F(WARNING, "Error parsing file: %s", e.message().c_str());
|
||||
}
|
||||
|
||||
_demodState.gain = pt.get("state.demod.gain", DEFAULT_GAIN);
|
||||
_demodState.squelch = pt.get("state.demod.squelch", DEFAULT_SQUELCH);
|
||||
|
||||
}
|
||||
|
||||
void Configuration::saveConfig(){
|
||||
ptree pt;
|
||||
filesystem::path path(_configPath);
|
||||
path += filesystem::path::preferred_separator;
|
||||
path += CONFIG_FILE;
|
||||
|
||||
LOG_F(INFO, "Saving config");
|
||||
|
||||
pt.put("config.general.log_verbosity", _generalConfig.logfileVerbosity);
|
||||
|
||||
pt.put("config.socket.port", _socketConfig.tcpPort);
|
||||
pt.put("config.socket.max_connections", _socketConfig.maxConnections);
|
||||
|
||||
write_json(path.c_str(), pt);
|
||||
}
|
||||
|
||||
void Configuration::saveState(){
|
||||
ptree pt;
|
||||
filesystem::path path(_configPath);
|
||||
path += filesystem::path::preferred_separator;
|
||||
path += STATE_FILE;
|
||||
|
||||
LOG_F(INFO, "Saving state");
|
||||
|
||||
pt.put("state.demod.gain", _demodState.gain);
|
||||
pt.put("state.demod.squelch", _demodState.squelch);
|
||||
|
||||
write_json(path.c_str(), pt);
|
||||
}
|
||||
|
||||
std::string Configuration::getLogfilePath(){
|
||||
filesystem::path path(_configPath);
|
||||
path += filesystem::path::preferred_separator;
|
||||
path += LOG_FOLDER;
|
||||
|
||||
if(!filesystem::exists(path)){
|
||||
if(!filesystem::create_directory(path)){
|
||||
LOG_F(ERROR, "Error creating logfile directory");
|
||||
path = DATABASE_PATH;
|
||||
}
|
||||
}
|
||||
|
||||
auto t = std::time(nullptr);
|
||||
auto tm = *std::localtime(&t);
|
||||
|
||||
std::ostringstream oss;
|
||||
oss << std::put_time(&tm, "%Y%m%d-%H%M%S");
|
||||
auto str = oss.str();
|
||||
|
||||
path += filesystem::path::preferred_separator;
|
||||
path += str;
|
||||
path += LOGFILE_EXT;
|
||||
return path.string();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -8,24 +8,78 @@
|
|||
#ifndef SERVER_CONFIGURATION_H_
|
||||
#define SERVER_CONFIGURATION_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "constants.h"
|
||||
|
||||
#ifndef NDEBUG
|
||||
#define DEFAULT_LOGFILE_VERBOSITY 3
|
||||
#define LOG_PATH "log.txt"
|
||||
#else
|
||||
#define DEFAULT_LOGFILE_VERBOSITY 0
|
||||
#define LOG_PATH "~/piscan.log"
|
||||
#endif
|
||||
|
||||
#define DATABASE_PATH "../data"
|
||||
#define LOG_FOLDER "logs"
|
||||
#define LOGFILE_EXT ".txt"
|
||||
|
||||
#define CONFIG_FILE "config.json"
|
||||
#define STATE_FILE "state.json"
|
||||
#define SYSTEMS_FILE "systems.json"
|
||||
|
||||
namespace piscan {
|
||||
|
||||
class SocketServerConfig {
|
||||
|
||||
struct GeneralConfig {
|
||||
int logfileVerbosity = DEFAULT_LOGFILE_VERBOSITY;
|
||||
};
|
||||
|
||||
class LoggingConfig {
|
||||
#define DEFAULT_TCP_PORT 1234
|
||||
#define MAX_TCP_CONNECTIONS 5
|
||||
|
||||
struct SocketServerConfig {
|
||||
int tcpPort = DEFAULT_TCP_PORT;
|
||||
int maxConnections = MAX_TCP_CONNECTIONS;
|
||||
};
|
||||
|
||||
class DemodConfig {
|
||||
#define DEFAULT_SQUELCH 0
|
||||
#define DEFAULT_GAIN (AUTO_GAIN)
|
||||
|
||||
struct DemodState {
|
||||
float squelch = DEFAULT_SQUELCH;
|
||||
float gain = DEFAULT_GAIN;
|
||||
};
|
||||
|
||||
class Configuration {
|
||||
public:
|
||||
Configuration();
|
||||
|
||||
~Configuration();
|
||||
|
||||
static Configuration& getConfig();
|
||||
|
||||
void setWorkingPath(std::string path);
|
||||
std::string getWorkingPath();
|
||||
void loadConfig();
|
||||
void loadState();
|
||||
void saveConfig();
|
||||
void saveState();
|
||||
|
||||
GeneralConfig& getGeneralConfig() { return _generalConfig; };
|
||||
SocketServerConfig& getSocketConfig() { return _socketConfig; };
|
||||
DemodState& getDemodState() { return _demodState; };
|
||||
|
||||
std::string getLogfilePath();
|
||||
|
||||
private:
|
||||
static Configuration* _config;
|
||||
std::string _configPath;
|
||||
|
||||
GeneralConfig _generalConfig;
|
||||
SocketServerConfig _socketConfig;
|
||||
DemodState _demodState;
|
||||
|
||||
Configuration();
|
||||
};
|
||||
|
||||
}
|
||||
#endif /* SERVER_CONFIGURATION_H_ */
|
||||
|
|
|
|||
|
|
@ -82,9 +82,7 @@ void ScannerSM::manualEntry(uint32_t* freq){
|
|||
void ScannerSM::ST_Load(EventData* data){
|
||||
loguru::set_thread_name("Scanner");
|
||||
DLOG_F(9, "ST_Load");
|
||||
//file read and system tree population
|
||||
ListFileIO* generator = new SentinelFile();
|
||||
generator->generateSystemList(_systems);
|
||||
_systems.populateFromFile();
|
||||
LOG_F(INFO, "Loaded %u systems", _systems.size());
|
||||
|
||||
//_currentSystem = _systems[0];
|
||||
|
|
@ -95,8 +93,6 @@ void ScannerSM::ST_Load(EventData* data){
|
|||
auto message = std::make_shared<ControllerMessage>(SCANNER_SM, ControllerMessage::NOTIFY_READY);
|
||||
_centralQueue.giveMessage(message);
|
||||
LOG_F(1, "ScannerSM ready");
|
||||
|
||||
delete generator;
|
||||
}
|
||||
|
||||
void ScannerSM::ST_Scan(EventData* data){
|
||||
|
|
@ -173,8 +169,8 @@ void ScannerSM::ST_Hold(EventData* data){
|
|||
InternalEvent(ST_HOLD);
|
||||
}
|
||||
/* check timeout counter if entry has resume delay enabled */
|
||||
else if(_currentEntry->useDelay() && timeoutStart != 0){
|
||||
if(std::difftime(std::time(nullptr), timeoutStart) < DELAY_TIMEOUT){
|
||||
else if(_currentEntry->delay() && timeoutStart != 0){
|
||||
if(std::difftime(std::time(nullptr), timeoutStart) < _currentEntry->delay()){
|
||||
InternalEvent(ST_HOLD);
|
||||
}
|
||||
else {
|
||||
|
|
@ -244,6 +240,8 @@ void ScannerSM::ST_SaveAll(EventData* data){
|
|||
|
||||
//TODO scan list isn't modifiable yet
|
||||
|
||||
_systems.writeToFile();
|
||||
|
||||
InternalEvent(ST_STOPPED);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -8,23 +8,8 @@
|
|||
#ifndef CORE_CONSTANTS_H_
|
||||
#define CORE_CONSTANTS_H_
|
||||
|
||||
#ifndef NDEBUG
|
||||
#define LOG_VERBOSITY 3
|
||||
#define LOG_PATH "log.txt"
|
||||
#define CONFIG_PATH "piscan.config"
|
||||
#else
|
||||
#define LOG_VERBOSITY 0
|
||||
#define LOG_PATH "~/piscan.log"
|
||||
#define CONFIG_PATH "~/piscan.config"
|
||||
#endif
|
||||
|
||||
#define DATABASE_PATH "../data"
|
||||
|
||||
#define AUTO_GAIN -10
|
||||
|
||||
#define DEFAULT_TCP_PORT 1234
|
||||
#define MAX_TCP_CONNECTIONS 5
|
||||
|
||||
namespace piscan {
|
||||
|
||||
enum ConnectionLevel {
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
//using namespace std;
|
||||
|
||||
#include "constants.h"
|
||||
#include "Configuration.h"
|
||||
#include "Demodulator.h"
|
||||
#include "Entry.h"
|
||||
#include "loguru.hpp"
|
||||
|
|
@ -331,8 +332,7 @@ using namespace piscan;
|
|||
|
||||
int main(int argc, char **argv) {
|
||||
loguru::init(argc, argv);
|
||||
loguru::add_file(LOG_PATH, loguru::Truncate, LOG_VERBOSITY);
|
||||
//loguru::g_stderr_verbosity = loguru::Verbosity_MAX;
|
||||
|
||||
loguru::g_preamble_file = false;
|
||||
|
||||
signal(SIGINT, sigIntHandler);
|
||||
|
|
@ -340,6 +340,28 @@ int main(int argc, char **argv) {
|
|||
|
||||
LOG_F(INFO, "Starting PiScan");
|
||||
|
||||
Configuration& config = Configuration::getConfig();
|
||||
bool useDebugConsole = false;
|
||||
|
||||
int c;
|
||||
while((c = getopt(argc,argv,"d:p:")) != -1){
|
||||
switch(c){
|
||||
case 'd':
|
||||
useDebugConsole = true;
|
||||
break;
|
||||
case 'p':
|
||||
if(optarg)
|
||||
config.setWorkingPath(std::string(optarg));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
config.loadConfig();
|
||||
config.loadState();
|
||||
|
||||
loguru::add_file(config.getLogfilePath().c_str(), loguru::Truncate, config.getGeneralConfig().logfileVerbosity);
|
||||
|
||||
messageManager.setReceiver(SYSTEM_CONTROL, &sysControl);
|
||||
messageManager.setReceiver(SCANNER_SM, &scanner);
|
||||
messageManager.setReceiver(DEMOD, &demod);
|
||||
|
|
@ -372,6 +394,9 @@ int main(int argc, char **argv) {
|
|||
LOG_F(ERROR, e.what());
|
||||
}
|
||||
|
||||
config.saveState();
|
||||
config.saveConfig();
|
||||
|
||||
piscan::exit(0);
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -8,22 +8,46 @@
|
|||
#ifndef SCAN_ENTRY_H_
|
||||
#define SCAN_ENTRY_H_
|
||||
|
||||
#include <boost/property_tree/ptree.hpp>
|
||||
|
||||
#include "Demodulator.h"
|
||||
|
||||
#define TAG_LENGTH 20
|
||||
|
||||
#define FM_CHANNEL_HASH "fmc"
|
||||
#define AM_CHANNEL_HASH "amc"
|
||||
#define PL_CHANNEL_HASH "plc"
|
||||
#define DC_CHANNEL_HASH "dcc"
|
||||
|
||||
#define CHAN_TYPE_KEY "chantype"
|
||||
#define TAG_KEY "tag"
|
||||
#define LOCKOUT_KEY "lockout"
|
||||
#define DELAY_KEY "delay"
|
||||
#define FREQ_KEY "freq"
|
||||
#define TONE_KEY "tone"
|
||||
#define CODE_KEY "code"
|
||||
|
||||
using namespace boost::property_tree;
|
||||
|
||||
namespace piscan {
|
||||
|
||||
class Entry {
|
||||
public:
|
||||
Entry(std::string tag, bool lo, bool del) : _tag(tag), _lockedOut(lo), _scanDelay(del){};
|
||||
Entry(std::string tag, bool lo, int del) : _tag(tag), _lockedOut(lo), _scanDelay(del) {
|
||||
propertyTree.put(TAG_KEY, tag);
|
||||
propertyTree.put(LOCKOUT_KEY, lo);
|
||||
propertyTree.put(DELAY_KEY, del);
|
||||
};
|
||||
virtual ~Entry() {};
|
||||
|
||||
std::string tag() { return _tag; }
|
||||
virtual std::string modulation() = 0;
|
||||
bool isLockedOut() { return _lockedOut; }
|
||||
bool useDelay() { return _scanDelay; }
|
||||
void lockout(bool val = true) { _lockedOut = val; }
|
||||
double delay() { return _scanDelay; }
|
||||
void lockout(bool val = true) {
|
||||
_lockedOut = val;
|
||||
propertyTree.put(LOCKOUT_KEY, val);
|
||||
}
|
||||
virtual bool hasSignal() = 0;
|
||||
virtual long long freq() = 0;
|
||||
virtual bool isDummy() { return false; }
|
||||
|
|
@ -33,20 +57,28 @@ public:
|
|||
size_t getEntryIndex() { return _entryIndex; };
|
||||
void setEntryIndex(size_t index) { _entryIndex = index; };
|
||||
|
||||
ptree getPropertyTree() { return propertyTree; };
|
||||
|
||||
private:
|
||||
std::string _tag;
|
||||
bool _lockedOut;
|
||||
bool _scanDelay;
|
||||
double _scanDelay;
|
||||
size_t _sysIndex = 0;
|
||||
size_t _entryIndex = 0;
|
||||
protected:
|
||||
static DemodInterface* demod;
|
||||
friend void setDemodulator(DemodInterface* demod);
|
||||
|
||||
ptree propertyTree;
|
||||
};
|
||||
|
||||
typedef std::shared_ptr<Entry> EntryPtr;
|
||||
|
||||
class Channel: public Entry {
|
||||
public:
|
||||
Channel(long freq, std::string tag, bool lo, bool del) : Entry(tag, lo, del), frequency(freq){}
|
||||
Channel(long freq, std::string tag, bool lo, int del) : Entry(tag, lo, del), frequency(freq){
|
||||
propertyTree.put(FREQ_KEY, freq);
|
||||
}
|
||||
virtual ~Channel() {};
|
||||
virtual long long freq() { return frequency; };
|
||||
protected:
|
||||
|
|
@ -56,7 +88,7 @@ protected:
|
|||
|
||||
class DummyChannel: public Channel {
|
||||
public:
|
||||
DummyChannel(long long freq) : Channel(freq, "", false, false){
|
||||
DummyChannel(long long freq) : Channel(freq, "", false, 0){
|
||||
|
||||
}
|
||||
~DummyChannel(){};
|
||||
|
|
@ -66,24 +98,29 @@ public:
|
|||
bool isDummy() { return true; }
|
||||
|
||||
bool hasSignal();
|
||||
ptree getPropertyTree() { return ptree(); };
|
||||
};
|
||||
|
||||
class FMChannel : public Channel {
|
||||
public:
|
||||
FMChannel(long long freq, std::string tag, bool lo, bool del) : Channel(freq, tag, lo, del){}
|
||||
FMChannel(long long freq, std::string tag, bool lo, int del) : Channel(freq, tag, lo, del){
|
||||
propertyTree.put(CHAN_TYPE_KEY, FM_CHANNEL_HASH);
|
||||
}
|
||||
~FMChannel() {};
|
||||
|
||||
std::string modulation() {
|
||||
virtual std::string modulation() {
|
||||
return "NFM";
|
||||
}
|
||||
|
||||
bool hasSignal();
|
||||
virtual bool hasSignal();
|
||||
};
|
||||
|
||||
class PLChannel: public FMChannel {
|
||||
public:
|
||||
PLChannel(long long freq, float tn, std::string tag, bool lo, bool del) :
|
||||
PLChannel(long long freq, float tn, std::string tag, bool lo, int del) :
|
||||
FMChannel(freq, tag, lo, del), tone(tn) {
|
||||
propertyTree.put(CHAN_TYPE_KEY, PL_CHANNEL_HASH);
|
||||
propertyTree.put(TONE_KEY, tn);
|
||||
}
|
||||
~PLChannel() {};
|
||||
|
||||
|
|
@ -94,8 +131,10 @@ protected:
|
|||
|
||||
class DCChannel : public FMChannel {
|
||||
public:
|
||||
DCChannel(long long freq, unsigned int tn, std::string tag, bool lo, bool del) :
|
||||
DCChannel(long long freq, unsigned int tn, std::string tag, bool lo, int del) :
|
||||
FMChannel(freq, tag, lo, del), code(tn) {
|
||||
propertyTree.put(CHAN_TYPE_KEY, DC_CHANNEL_HASH);
|
||||
propertyTree.put(CODE_KEY, tn);
|
||||
}
|
||||
~DCChannel() {};
|
||||
|
||||
|
|
@ -106,10 +145,14 @@ protected:
|
|||
|
||||
class AMChannel : public Channel {
|
||||
public:
|
||||
AMChannel(long long freq, std::string tag, bool lo, bool del) : Channel(freq, tag, lo, del){}
|
||||
AMChannel(long long freq, std::string tag, bool lo, int del) : Channel(freq, tag, lo, del){
|
||||
propertyTree.put(CHAN_TYPE_KEY, AM_CHANNEL_HASH);
|
||||
}
|
||||
~AMChannel() {};
|
||||
|
||||
bool hasSignal() { return false; };
|
||||
virtual bool hasSignal() { return false; };
|
||||
|
||||
virtual std::string modulation() { return "AM"; }
|
||||
};
|
||||
}
|
||||
#endif /*Channel_ */
|
||||
|
|
|
|||
|
|
@ -5,6 +5,105 @@
|
|||
* Author: ezra
|
||||
*/
|
||||
|
||||
#include <boost/foreach.hpp>
|
||||
#include <boost/property_tree/ptree.hpp>
|
||||
|
||||
#include "RadioSystem.h"
|
||||
|
||||
using namespace piscan;
|
||||
using namespace boost::property_tree;
|
||||
|
||||
std::unordered_map<std::string, std::function<EntryPtr(ptree&)>> RadioSystem::makeEntry = {
|
||||
{ FM_CHANNEL_HASH, makeFMChannel },
|
||||
{ AM_CHANNEL_HASH, makeAMChannel },
|
||||
{ PL_CHANNEL_HASH, makePLChannel },
|
||||
{ DC_CHANNEL_HASH, makeDCChannel }
|
||||
};
|
||||
|
||||
EntryPtr RadioSystem::makeFMChannel(ptree& pt) {
|
||||
std::string tag = pt.get(TAG_KEY, "");
|
||||
long long freq = pt.get(FREQ_KEY, 0);
|
||||
bool lockout = pt.get(LOCKOUT_KEY, false);
|
||||
int delay = pt.get(DELAY_KEY, 0.0);
|
||||
if(freq == 0)
|
||||
return nullptr;
|
||||
|
||||
return std::make_shared<FMChannel>(freq, tag, lockout, delay);
|
||||
}
|
||||
|
||||
EntryPtr RadioSystem::makeAMChannel(ptree& pt) {
|
||||
std::string tag = pt.get(TAG_KEY, "");
|
||||
long long freq = pt.get(FREQ_KEY, 0);
|
||||
bool lockout = pt.get(LOCKOUT_KEY, false);
|
||||
int delay = pt.get(DELAY_KEY, 0.0);
|
||||
if(freq == 0)
|
||||
return nullptr;
|
||||
|
||||
return std::make_shared<AMChannel>(freq, tag, lockout, delay);
|
||||
}
|
||||
|
||||
EntryPtr RadioSystem::makePLChannel(ptree& pt) {
|
||||
std::string tag = pt.get(TAG_KEY, "");
|
||||
long long freq = pt.get(FREQ_KEY, 0);
|
||||
bool lockout = pt.get(LOCKOUT_KEY, false);
|
||||
int delay = pt.get(DELAY_KEY, 0.0);
|
||||
if(freq == 0)
|
||||
return nullptr;
|
||||
|
||||
float tone = pt.get(TONE_KEY, 0.0);
|
||||
return std::make_shared<PLChannel>(freq, tone, tag, lockout, delay);
|
||||
}
|
||||
|
||||
EntryPtr RadioSystem::makeDCChannel(ptree& pt) {
|
||||
std::string tag = pt.get(TAG_KEY, "");
|
||||
long long freq = pt.get(FREQ_KEY, 0);
|
||||
bool lockout = pt.get(LOCKOUT_KEY, false);
|
||||
int delay = pt.get(DELAY_KEY, 0.0);
|
||||
if(freq == 0)
|
||||
return nullptr;
|
||||
|
||||
unsigned int code = pt.get(CODE_KEY, 0);
|
||||
return std::make_shared<DCChannel>(freq, code, tag, lockout, delay);
|
||||
}
|
||||
|
||||
AnalogSystem::AnalogSystem(ptree pt, size_t index) : RadioSystem(pt.get(TAG_KEY, ""), pt.get(LOCKOUT_KEY, false)) {
|
||||
setSysIndex(index);
|
||||
RAW_LOG_F(1, "New analog system\n\tTag: %s\n\tLockout: %i", tag().c_str(), lockedOut());
|
||||
|
||||
BOOST_FOREACH(ptree::value_type& v, pt.get_child(CHANNELS_KEY)){
|
||||
ptree entryPT = v.second;
|
||||
EntryPtr entry;
|
||||
std::string type = entryPT.get(CHAN_TYPE_KEY, "");
|
||||
try {
|
||||
entry = makeEntry[type](entryPT);
|
||||
} catch (std::exception& e) {
|
||||
LOG_F(WARNING, "Invalid entry type: %s", type.c_str());
|
||||
continue;
|
||||
}
|
||||
|
||||
if(entry == nullptr)
|
||||
continue;
|
||||
|
||||
RAW_LOG_F(1, "\t\tNew %s entry", type.c_str());
|
||||
RAW_LOG_F(1, "\t\tTag: %s", entry->tag().c_str());
|
||||
RAW_LOG_F(1, "\t\tFreq: %li", entry->freq());
|
||||
RAW_LOG_F(1, "\t\tLockout: %i", entry->isLockedOut());
|
||||
RAW_LOG_F(1, "\t\tDelay: %i", entry->delay());
|
||||
|
||||
addEntry(entry);
|
||||
}
|
||||
}
|
||||
|
||||
ptree AnalogSystem::getPropertyTree() {
|
||||
ptree pt, channels;
|
||||
pt.put(SYS_TYPE_KEY, ANALOG_SYSTEM_HASH);
|
||||
pt.put(TAG_KEY, tag());
|
||||
pt.put(LOCKOUT_KEY, lockedOut());
|
||||
BOOST_FOREACH(EntryPtr p, entries){
|
||||
channels.push_back(std::make_pair("", p->getPropertyTree()));
|
||||
}
|
||||
|
||||
pt.add_child(CHANNELS_KEY, channels);
|
||||
|
||||
return pt;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,10 +11,19 @@
|
|||
#include <stdint.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <unordered_map>
|
||||
#include <boost/property_tree/ptree.hpp>
|
||||
|
||||
#include "Entry.h"
|
||||
#include "loguru.hpp"
|
||||
|
||||
#define ANALOG_SYSTEM_HASH "analog"
|
||||
|
||||
#define SYS_TYPE_KEY "systype"
|
||||
#define CHANNELS_KEY "channels"
|
||||
|
||||
using namespace boost::property_tree;
|
||||
|
||||
namespace piscan {
|
||||
|
||||
typedef enum {
|
||||
|
|
@ -26,42 +35,64 @@ public:
|
|||
RadioSystem(std::string tag, bool lo) : _tag(tag), _lockout(lo) {};
|
||||
virtual ~RadioSystem() {};
|
||||
|
||||
virtual std::shared_ptr<Entry> operator[](size_t pos) = 0;
|
||||
virtual EntryPtr operator[](size_t pos) = 0;
|
||||
|
||||
virtual size_t size() { return numEntries; }
|
||||
|
||||
std::string tag() { return _tag; };
|
||||
|
||||
virtual void addEntry(std::shared_ptr<Entry> entry) = 0;
|
||||
virtual void addEntry(EntryPtr entry) = 0;
|
||||
|
||||
virtual ptree getPropertyTree() = 0;
|
||||
|
||||
bool lockedOut() { return _lockout; };
|
||||
void lockout(bool val = true) { _lockout = val; };
|
||||
|
||||
size_t getSysIndex() { return _sysIndex; };
|
||||
void setSysIndex(size_t index) { _sysIndex = index; };
|
||||
private:
|
||||
//const RadioSystemType type;
|
||||
const std::string _tag;
|
||||
|
||||
bool _lockout;
|
||||
size_t _sysIndex = 0;
|
||||
protected:
|
||||
size_t numEntries = 0;
|
||||
|
||||
static std::unordered_map<std::string, std::function<EntryPtr(ptree&)>> makeEntry;
|
||||
static EntryPtr makeFMChannel(ptree& pt);
|
||||
static EntryPtr makeAMChannel(ptree& pt);
|
||||
static EntryPtr makePLChannel(ptree& pt);
|
||||
static EntryPtr makeDCChannel(ptree& pt);
|
||||
};
|
||||
|
||||
class AnalogSystem: public RadioSystem {
|
||||
public:
|
||||
AnalogSystem(std::string tag, bool lo) : RadioSystem(tag, lo) {};
|
||||
AnalogSystem(ptree pt, size_t index);
|
||||
~AnalogSystem() {};
|
||||
|
||||
virtual std::shared_ptr<Entry> operator[](size_t pos) { return entries[pos]; };
|
||||
virtual EntryPtr operator[](size_t pos) { return entries[pos]; };
|
||||
|
||||
/*virtual size_t size() {
|
||||
return entries.size();
|
||||
}*/
|
||||
|
||||
virtual void addEntry(std::shared_ptr<Entry> entry){
|
||||
virtual void addEntry(EntryPtr entry){
|
||||
if(entry != nullptr){
|
||||
entry->setEntryIndex(numEntries);
|
||||
entry->setSysIndex(getSysIndex());
|
||||
entries.push_back(entry);
|
||||
numEntries++;
|
||||
}
|
||||
}
|
||||
|
||||
ptree getPropertyTree();
|
||||
protected:
|
||||
std::vector<std::shared_ptr<Entry>> entries;
|
||||
};
|
||||
|
||||
typedef std::shared_ptr<RadioSystem> RadioSystemPtr;
|
||||
|
||||
}
|
||||
#endif /* RADIOSYSTEM_H_ */
|
||||
|
|
|
|||
|
|
@ -5,9 +5,20 @@
|
|||
* Author: ezra
|
||||
*/
|
||||
|
||||
#include <experimental/filesystem>
|
||||
#include <boost/property_tree/json_parser.hpp>
|
||||
#include <boost/foreach.hpp>
|
||||
|
||||
#include "SystemList.h"
|
||||
#include "Configuration.h"
|
||||
#include "loguru.hpp"
|
||||
|
||||
using namespace piscan;
|
||||
using namespace std::experimental;
|
||||
|
||||
std::unordered_map<std::string, std::function<RadioSystemPtr(ptree&, size_t)>> SystemList::_makeSystem = {
|
||||
{ANALOG_SYSTEM_HASH, makeAnalogSystem}
|
||||
};
|
||||
|
||||
SystemList::SystemList() {
|
||||
// TODO Auto-generated constructor stub
|
||||
|
|
@ -18,14 +29,75 @@ SystemList::~SystemList() {
|
|||
// TODO Auto-generated destructor stub
|
||||
}
|
||||
|
||||
std::shared_ptr<Entry> SystemList::getEntryByIndex(std::vector<int> index){
|
||||
void SystemList::populateFromFile(){
|
||||
filesystem::path path(Configuration::getConfig().getWorkingPath());
|
||||
path += filesystem::path::preferred_separator;
|
||||
path += SYSTEMS_FILE;
|
||||
if(!filesystem::exists(path)){
|
||||
LOG_F(INFO, "No system list file found");
|
||||
return;
|
||||
}
|
||||
|
||||
LOG_F(1, "Systems file path %s", path.c_str());
|
||||
LOG_F(INFO, "Loading systems file");
|
||||
|
||||
try{
|
||||
read_json(path, _jsonTree);
|
||||
} catch(boost::property_tree::json_parser_error& e){
|
||||
LOG_F(WARNING, "Error parsing file: %s", e.message().c_str());
|
||||
}
|
||||
|
||||
BOOST_FOREACH(ptree::value_type& v, _jsonTree.get_child(std::string(SYSTEMS_KEY).append("."))){
|
||||
LOG_F(1, "%s", v.first.c_str());
|
||||
ptree newSystem = v.second;
|
||||
|
||||
std::string sysType = newSystem.get(SYS_TYPE_KEY, "unspecified");
|
||||
|
||||
RadioSystemPtr system;
|
||||
|
||||
try{
|
||||
system = _makeSystem[sysType](newSystem, size());
|
||||
LOG_F(1, "Added %s system %s", sysType.c_str(), system->tag());
|
||||
} catch (std::exception& e) {
|
||||
LOG_F(WARNING, "Unrecognized or unsupported system type: %s", sysType.c_str());
|
||||
continue;
|
||||
}
|
||||
|
||||
if(system != nullptr)
|
||||
addSystem(system);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool SystemList::writeToFile(){
|
||||
filesystem::path path(Configuration::getConfig().getWorkingPath());
|
||||
path += filesystem::path::preferred_separator;
|
||||
path += SYSTEMS_FILE;
|
||||
|
||||
LOG_F(1, "Systems file path", path.c_str());
|
||||
LOG_F(INFO, "Saving systems file");
|
||||
|
||||
ptree pt, systems;
|
||||
|
||||
BOOST_FOREACH(RadioSystemPtr p, _systems){
|
||||
systems.push_back(std::make_pair("", p->getPropertyTree()));
|
||||
}
|
||||
|
||||
pt.add_child(SYSTEMS_KEY, systems);
|
||||
|
||||
write_json(path, pt);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
EntryPtr SystemList::getEntryByIndex(std::vector<int> index){
|
||||
if(index.size() < 2 || index[0] < 0 || index[1] < 0 || index[0] >= _systems.size() || index[1] >= _systems[index[0]]->size())
|
||||
return getNextEntry();
|
||||
|
||||
return _systems[index[0]]->operator [](index[1]);
|
||||
}
|
||||
|
||||
std::shared_ptr<Entry> SystemList::getNextEntry(){
|
||||
EntryPtr SystemList::getNextEntry(){
|
||||
if(_entryNum == 0 && _retune){
|
||||
_retune = false;
|
||||
//if(_bins[_binNum]->size() > 1)
|
||||
|
|
@ -52,7 +124,7 @@ void SystemList::sortBins(int bandwidth){
|
|||
for(size_t i = 0; i < _systems.size(); i++)
|
||||
for(size_t k = 0; k < _systems[i]->size(); k++)
|
||||
numEntries++;
|
||||
std::shared_ptr<Entry> entries[numEntries];
|
||||
EntryPtr entries[numEntries];
|
||||
|
||||
numEntries = 0;
|
||||
|
||||
|
|
@ -91,14 +163,14 @@ void SystemList::sortBins(int bandwidth){
|
|||
}
|
||||
}
|
||||
|
||||
void SystemList::merge(std::shared_ptr<Entry> arr[], int l, int m, int r)
|
||||
void SystemList::merge(EntryPtr arr[], int l, int m, int r)
|
||||
{
|
||||
int i, j, k;
|
||||
int n1 = m - l + 1;
|
||||
int n2 = r - m;
|
||||
|
||||
/* create temp arrays */
|
||||
std::shared_ptr<Entry> L[n1], R[n2];
|
||||
EntryPtr L[n1], R[n2];
|
||||
|
||||
/* Copy data to temp arrays L[] and R[] */
|
||||
for (i = 0; i < n1; i++)
|
||||
|
|
@ -148,7 +220,7 @@ void SystemList::merge(std::shared_ptr<Entry> arr[], int l, int m, int r)
|
|||
|
||||
/* l is for left index and r is right index of the
|
||||
sub-array of arr to be sorted */
|
||||
void SystemList::mergeSort(std::shared_ptr<Entry> arr[], int l, int r)
|
||||
void SystemList::mergeSort(EntryPtr arr[], int l, int r)
|
||||
{
|
||||
if (l < r)
|
||||
{
|
||||
|
|
@ -172,3 +244,8 @@ long SystemList::EntryBin::getCenterFreq(){
|
|||
else
|
||||
return this->front()->freq();
|
||||
}
|
||||
|
||||
RadioSystemPtr SystemList::makeAnalogSystem(ptree& pt, size_t index){
|
||||
auto system = std::make_shared<AnalogSystem>(pt, index);
|
||||
return system;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,8 +9,13 @@
|
|||
#define SYSTEMLIST_H_
|
||||
|
||||
#include <vector>
|
||||
#include <unordered_map>
|
||||
#include <boost/property_tree/ptree.hpp>
|
||||
|
||||
#include "RadioSystem.h"
|
||||
#include "Entry.h"
|
||||
|
||||
#define SYSTEMS_KEY "systems"
|
||||
|
||||
namespace piscan {
|
||||
|
||||
|
|
@ -19,22 +24,25 @@ public:
|
|||
SystemList();
|
||||
~SystemList();
|
||||
|
||||
std::shared_ptr<RadioSystem> operator[](size_t pos) { return _systems[pos]; };
|
||||
void populateFromFile();
|
||||
bool writeToFile();
|
||||
|
||||
RadioSystemPtr operator[](size_t pos) { return _systems[pos]; };
|
||||
|
||||
size_t size(){ return _systems.size(); }
|
||||
|
||||
void addSystem(std::shared_ptr<RadioSystem> system) {
|
||||
void addSystem(RadioSystemPtr system) {
|
||||
_systems.push_back(system);
|
||||
}
|
||||
|
||||
std::shared_ptr<Entry> getEntryByIndex(std::vector<int> index);
|
||||
EntryPtr getEntryByIndex(std::vector<int> index);
|
||||
|
||||
std::shared_ptr<Entry> getNextEntry();
|
||||
EntryPtr getNextEntry();
|
||||
|
||||
void sortBins(int bandwidth);
|
||||
private:
|
||||
|
||||
class EntryBin: public std::vector<std::shared_ptr<Entry>>{
|
||||
class EntryBin: public std::vector<EntryPtr>{
|
||||
public:
|
||||
EntryBin(){};
|
||||
~EntryBin(){};
|
||||
|
|
@ -43,8 +51,10 @@ private:
|
|||
long getCenterFreq();
|
||||
};
|
||||
|
||||
ptree _jsonTree;
|
||||
static std::unordered_map<std::string, std::function<RadioSystemPtr(ptree&, size_t)>> _makeSystem;
|
||||
|
||||
std::vector<std::shared_ptr<RadioSystem>> _systems;
|
||||
std::vector<RadioSystemPtr> _systems;
|
||||
//size_t _size = 0;
|
||||
|
||||
std::vector<std::shared_ptr<EntryBin>> _bins;
|
||||
|
|
@ -52,8 +62,10 @@ private:
|
|||
size_t _binNum = 0, _entryNum = 0;
|
||||
bool _retune = true;
|
||||
|
||||
void merge(std::shared_ptr<Entry> arr[], int l, int m, int r);
|
||||
void mergeSort(std::shared_ptr<Entry> arr[], int l, int r);
|
||||
void merge(EntryPtr arr[], int l, int m, int r);
|
||||
void mergeSort(EntryPtr arr[], int l, int r);
|
||||
|
||||
static RadioSystemPtr makeAnalogSystem(ptree& pt, size_t index);
|
||||
};
|
||||
}
|
||||
#endif /* SYSTEMLIST_H_ */
|
||||
|
|
|
|||
|
|
@ -223,6 +223,9 @@ void SocketConnection::_handleDemodRequest(const piscan_pb::DemodRequest& rq) {
|
|||
/*****************************************/
|
||||
|
||||
void SocketServer::start() {
|
||||
SocketServerConfig& config = Configuration::getConfig().getSocketConfig();
|
||||
_listenPort = config.tcpPort;
|
||||
|
||||
LOG_F(INFO, "Starting TCP server on port %i", _listenPort);
|
||||
|
||||
// exception thrown when binding TCP port fails
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@
|
|||
#include "constants.h"
|
||||
#include "ServerManager.h"
|
||||
#include "request.pb.h"
|
||||
#include "Configuration.h"
|
||||
|
||||
#include <boost/asio.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
|
|
|
|||
|
|
@ -19,6 +19,10 @@ using namespace piscan;
|
|||
Demodulator::Demodulator(MessageReceiver& central) : _centralQueue(central), _cubic(makeCubic()), _demodMgr(_cubic->getDemodMgr()) {};
|
||||
|
||||
void Demodulator::start(){
|
||||
DemodState& state = Configuration::getConfig().getDemodState();
|
||||
_squelchLevel = state.squelch;
|
||||
_gain = state.gain;
|
||||
|
||||
CHECK_F(_cubic->OnInit());
|
||||
|
||||
while(_cubic->areDevicesEnumerating());
|
||||
|
|
@ -147,6 +151,10 @@ void Demodulator::stop(){
|
|||
_cubic->stopDevice(false, 2000);
|
||||
_cubic->OnExit();
|
||||
|
||||
DemodState& state = Configuration::getConfig().getDemodState();
|
||||
state.gain = _gain;
|
||||
state.squelch = _squelchLevel;
|
||||
|
||||
auto message = std::make_shared<ControllerMessage>(DEMOD, ControllerMessage::NOTIFY_STOPPED);
|
||||
_centralQueue.giveMessage(message);
|
||||
LOG_F(1, "Demodulator stopped");
|
||||
|
|
@ -164,7 +172,7 @@ bool Demodulator::setFrequency(long long freq) {
|
|||
if(std::abs(_cubic->getFrequency() - freq) >= (_cubic->getSampleRate() / 2)){
|
||||
_cubic->setFrequency(freq);
|
||||
//also arbitrary
|
||||
usleep(200000);
|
||||
usleep(225000);
|
||||
}
|
||||
|
||||
_demodMgr.getCurrentModem()->setFrequency(freq);
|
||||
|
|
|
|||
|
|
@ -14,8 +14,8 @@
|
|||
#include "CubicSDR.h"
|
||||
#include "DemodulatorMgr.h"
|
||||
#include "SDRDeviceInfo.h"
|
||||
#include "Configuration.h"
|
||||
|
||||
#define DEFAULT_SQUELCH 0
|
||||
|
||||
namespace piscan {
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue