From 93b94dbcb8cc8d8e56cbb3da29fba51118165d58 Mon Sep 17 00:00:00 2001 From: ezratl Date: Mon, 14 Oct 2019 11:58:11 -0400 Subject: [PATCH] Added support for files --- src/core/Configuration.cpp | 142 +++++++++++++++++++++++++++++++++++- src/core/Configuration.h | 64 ++++++++++++++-- src/core/ScannerSM.cpp | 12 ++- src/core/constants.h | 15 ---- src/piScan_backend.cpp | 29 +++++++- src/scan/Entry.h | 69 ++++++++++++++---- src/scan/RadioSystem.cpp | 99 +++++++++++++++++++++++++ src/scan/RadioSystem.h | 39 +++++++++- src/scan/SystemList.cpp | 89 ++++++++++++++++++++-- src/scan/SystemList.h | 28 +++++-- src/server/SocketServer.cpp | 3 + src/server/SocketServer.h | 1 + src/sigproc/Demodulator.cpp | 10 ++- src/sigproc/Demodulator.h | 2 +- 14 files changed, 539 insertions(+), 63 deletions(-) diff --git a/src/core/Configuration.cpp b/src/core/Configuration.cpp index 1e6b118..b0d1593 100644 --- a/src/core/Configuration.cpp +++ b/src/core/Configuration.cpp @@ -5,12 +5,30 @@ * Author: ezra */ +#include +#include +#include +#include +#include +#include + #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(); +} + diff --git a/src/core/Configuration.h b/src/core/Configuration.h index 279cc94..b3be8df 100644 --- a/src/core/Configuration.h +++ b/src/core/Configuration.h @@ -8,24 +8,78 @@ #ifndef SERVER_CONFIGURATION_H_ #define SERVER_CONFIGURATION_H_ +#include + +#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_ */ diff --git a/src/core/ScannerSM.cpp b/src/core/ScannerSM.cpp index 330f420..78bba31 100644 --- a/src/core/ScannerSM.cpp +++ b/src/core/ScannerSM.cpp @@ -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(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); } diff --git a/src/core/constants.h b/src/core/constants.h index 9c50856..1f1ecc5 100644 --- a/src/core/constants.h +++ b/src/core/constants.h @@ -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 { diff --git a/src/piScan_backend.cpp b/src/piScan_backend.cpp index ba90a5b..de81ace 100644 --- a/src/piScan_backend.cpp +++ b/src/piScan_backend.cpp @@ -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; diff --git a/src/scan/Entry.h b/src/scan/Entry.h index 0572ca9..97eb15d 100644 --- a/src/scan/Entry.h +++ b/src/scan/Entry.h @@ -8,22 +8,46 @@ #ifndef SCAN_ENTRY_H_ #define SCAN_ENTRY_H_ +#include + #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 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_ */ diff --git a/src/scan/RadioSystem.cpp b/src/scan/RadioSystem.cpp index 2092e76..1d348c2 100644 --- a/src/scan/RadioSystem.cpp +++ b/src/scan/RadioSystem.cpp @@ -5,6 +5,105 @@ * Author: ezra */ +#include +#include + #include "RadioSystem.h" using namespace piscan; +using namespace boost::property_tree; + +std::unordered_map> 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(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(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(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(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; +} diff --git a/src/scan/RadioSystem.h b/src/scan/RadioSystem.h index 09e2563..a288c6a 100644 --- a/src/scan/RadioSystem.h +++ b/src/scan/RadioSystem.h @@ -11,10 +11,19 @@ #include #include #include +#include +#include #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 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) = 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> 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 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){ + virtual void addEntry(EntryPtr entry){ if(entry != nullptr){ + entry->setEntryIndex(numEntries); + entry->setSysIndex(getSysIndex()); entries.push_back(entry); numEntries++; } } + ptree getPropertyTree(); protected: std::vector> entries; }; + +typedef std::shared_ptr RadioSystemPtr; + } #endif /* RADIOSYSTEM_H_ */ diff --git a/src/scan/SystemList.cpp b/src/scan/SystemList.cpp index 540ce19..af42263 100644 --- a/src/scan/SystemList.cpp +++ b/src/scan/SystemList.cpp @@ -5,9 +5,20 @@ * Author: ezra */ +#include +#include +#include + #include "SystemList.h" +#include "Configuration.h" +#include "loguru.hpp" using namespace piscan; +using namespace std::experimental; + +std::unordered_map> 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 SystemList::getEntryByIndex(std::vector 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 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 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 entries[numEntries]; + EntryPtr entries[numEntries]; numEntries = 0; @@ -91,14 +163,14 @@ void SystemList::sortBins(int bandwidth){ } } -void SystemList::merge(std::shared_ptr 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 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 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 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(pt, index); + return system; +} diff --git a/src/scan/SystemList.h b/src/scan/SystemList.h index b485800..81758ac 100644 --- a/src/scan/SystemList.h +++ b/src/scan/SystemList.h @@ -9,8 +9,13 @@ #define SYSTEMLIST_H_ #include +#include +#include #include "RadioSystem.h" +#include "Entry.h" + +#define SYSTEMS_KEY "systems" namespace piscan { @@ -19,22 +24,25 @@ public: SystemList(); ~SystemList(); - std::shared_ptr 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 system) { + void addSystem(RadioSystemPtr system) { _systems.push_back(system); } - std::shared_ptr getEntryByIndex(std::vector index); + EntryPtr getEntryByIndex(std::vector index); - std::shared_ptr getNextEntry(); + EntryPtr getNextEntry(); void sortBins(int bandwidth); private: - class EntryBin: public std::vector>{ + class EntryBin: public std::vector{ public: EntryBin(){}; ~EntryBin(){}; @@ -43,8 +51,10 @@ private: long getCenterFreq(); }; + ptree _jsonTree; + static std::unordered_map> _makeSystem; - std::vector> _systems; + std::vector _systems; //size_t _size = 0; std::vector> _bins; @@ -52,8 +62,10 @@ private: size_t _binNum = 0, _entryNum = 0; bool _retune = true; - void merge(std::shared_ptr arr[], int l, int m, int r); - void mergeSort(std::shared_ptr 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_ */ diff --git a/src/server/SocketServer.cpp b/src/server/SocketServer.cpp index 0e529e7..29b2bf0 100644 --- a/src/server/SocketServer.cpp +++ b/src/server/SocketServer.cpp @@ -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 diff --git a/src/server/SocketServer.h b/src/server/SocketServer.h index 3daefee..59765c3 100644 --- a/src/server/SocketServer.h +++ b/src/server/SocketServer.h @@ -12,6 +12,7 @@ #include "constants.h" #include "ServerManager.h" #include "request.pb.h" +#include "Configuration.h" #include #include diff --git a/src/sigproc/Demodulator.cpp b/src/sigproc/Demodulator.cpp index 5e4f634..80d6cd4 100644 --- a/src/sigproc/Demodulator.cpp +++ b/src/sigproc/Demodulator.cpp @@ -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(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); diff --git a/src/sigproc/Demodulator.h b/src/sigproc/Demodulator.h index 1c3dab6..6891ef3 100644 --- a/src/sigproc/Demodulator.h +++ b/src/sigproc/Demodulator.h @@ -14,8 +14,8 @@ #include "CubicSDR.h" #include "DemodulatorMgr.h" #include "SDRDeviceInfo.h" +#include "Configuration.h" -#define DEFAULT_SQUELCH 0 namespace piscan {