Partial implementation of network config, calibration
This commit is contained in:
parent
27fc4236e4
commit
67c6a44f22
|
@ -14,6 +14,7 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
#include <fstream>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <istream>
|
#include <istream>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
@ -34,6 +35,8 @@ using namespace puzzlefw;
|
||||||
namespace asio = boost::asio;
|
namespace asio = boost::asio;
|
||||||
|
|
||||||
|
|
||||||
|
/* ******** Utility functions ******** */
|
||||||
|
|
||||||
/** Return true if the string ends with the suffix. */
|
/** Return true if the string ends with the suffix. */
|
||||||
bool str_ends_with(const std::string& value, const std::string& suffix)
|
bool str_ends_with(const std::string& value, const std::string& suffix)
|
||||||
{
|
{
|
||||||
|
@ -102,32 +105,121 @@ bool parse_float(const std::string& s, double& v)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Forward declaration.
|
/* ******** Network configuration ******** */
|
||||||
class ControlServer;
|
|
||||||
|
|
||||||
|
enum NetworkConfigMode { NETCFG_INVALID = 0, NETCFG_DHCP, NETCFG_STATIC };
|
||||||
|
|
||||||
/**
|
struct NetworkConfig {
|
||||||
* The CommandHandler handles commands from remote clients.
|
NetworkConfigMode mode;
|
||||||
*/
|
asio::ip::address_v4 ipaddr;
|
||||||
class CommandHandler
|
asio::ip::address_v4 netmask;
|
||||||
{
|
asio::ip::address_v4 gateway;
|
||||||
public:
|
NetworkConfig() : mode(NETCFG_INVALID) { }
|
||||||
// IDN response fields.
|
|
||||||
static constexpr const char * IDN_MANUFACTURER = "Jigsaw";
|
|
||||||
static constexpr const char * IDN_MODEL = "PuzzleFw";
|
|
||||||
|
|
||||||
// Configuration files.
|
|
||||||
static constexpr const char * CFG_FILE_CALIBRATION =
|
|
||||||
"/var/lib/puzzlefw/cfg/calibration.conf";
|
|
||||||
static constexpr const char * CFG_FILE_NETWORK =
|
|
||||||
"/var/lib/puzzlefw/cfg/network.conf";
|
|
||||||
|
|
||||||
enum ExitStatus {
|
|
||||||
EXIT_ERROR = 1,
|
|
||||||
EXIT_HALT = 10,
|
|
||||||
EXIT_REBOOT = 11
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/** Read network configuration from file. */
|
||||||
|
bool read_network_config(const char *filename, NetworkConfig& ipcfg)
|
||||||
|
{
|
||||||
|
ipcfg = NetworkConfig();
|
||||||
|
|
||||||
|
std::ifstream is(filename);
|
||||||
|
if (!is) {
|
||||||
|
log(LOG_ERROR, "Can not read %s", filename);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string line;
|
||||||
|
|
||||||
|
while (std::getline(is, line)) {
|
||||||
|
boost::system::error_code ec{};
|
||||||
|
size_t p = line.find_last_not_of(" \t\n\v\f\r");
|
||||||
|
if (p != line.npos) {
|
||||||
|
line.erase(p + 1);
|
||||||
|
}
|
||||||
|
if (line == "MODE=dhcp") {
|
||||||
|
ipcfg.mode = NETCFG_DHCP;
|
||||||
|
}
|
||||||
|
if (line == "MODE=static") {
|
||||||
|
ipcfg.mode = NETCFG_STATIC;
|
||||||
|
}
|
||||||
|
if (line.compare(0, 7, "IPADDR=") == 0) {
|
||||||
|
ipcfg.ipaddr = asio::ip::make_address_v4(line.substr(7), ec);
|
||||||
|
}
|
||||||
|
if (line.compare(0, 8, "NETMASK=") == 0) {
|
||||||
|
ipcfg.netmask = asio::ip::make_address_v4(line.substr(8), ec);
|
||||||
|
}
|
||||||
|
if (line.compare(0, 8, "GATEWAY=") == 0 && line.size() > 8) {
|
||||||
|
ipcfg.gateway = asio::ip::make_address_v4(line.substr(8), ec);
|
||||||
|
}
|
||||||
|
if (ec) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ((ipcfg.mode == NETCFG_DHCP)
|
||||||
|
|| (ipcfg.mode == NETCFG_STATIC
|
||||||
|
&& (! ipcfg.ipaddr.is_unspecified())
|
||||||
|
&& (! ipcfg.netmask.is_unspecified())));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** Parse network configuration arguments. */
|
||||||
|
bool parse_network_config(const std::vector<std::string>& args,
|
||||||
|
NetworkConfig& ipcfg,
|
||||||
|
std::string& errmsg)
|
||||||
|
{
|
||||||
|
ipcfg = NetworkConfig{};
|
||||||
|
errmsg = std::string();
|
||||||
|
|
||||||
|
if (args.size() == 1 && str_to_lower(args[0]) == "dhcp") {
|
||||||
|
ipcfg.mode = NETCFG_DHCP;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((args.size() == 3 || args.size() == 4)
|
||||||
|
&& str_to_lower(args[0]) == "static") {
|
||||||
|
ipcfg.mode = NETCFG_STATIC;
|
||||||
|
|
||||||
|
boost::system::error_code ec{};
|
||||||
|
ipcfg.ipaddr = asio::ip::make_address_v4(args[1], ec);
|
||||||
|
if (ec || ipcfg.ipaddr.is_unspecified()) {
|
||||||
|
errmsg = "Invalid IP address";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ipcfg.netmask = asio::ip::make_address_v4(args[2], ec);
|
||||||
|
if (ec || ipcfg.netmask.is_unspecified()) {
|
||||||
|
errmsg = "Invalid netmask";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check that netmask describes a valid prefix.
|
||||||
|
unsigned int mask = ipcfg.netmask.to_uint();
|
||||||
|
if (mask & ((~mask) >> 1)) {
|
||||||
|
errmsg = "Invalid netmask";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Optional gateway address.
|
||||||
|
if (args.size() == 4) {
|
||||||
|
ipcfg.gateway = asio::ip::make_address_v4(args[3], ec);
|
||||||
|
if (ec) {
|
||||||
|
errmsg = "Invalid gateway";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
errmsg = "Invalid address mode";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ******** Calibration ******** */
|
||||||
|
|
||||||
enum RangeSpec {
|
enum RangeSpec {
|
||||||
RANGE_NONE = 0,
|
RANGE_NONE = 0,
|
||||||
RANGE_LO = 1,
|
RANGE_LO = 1,
|
||||||
|
@ -146,6 +238,149 @@ public:
|
||||||
ChannelCalibration channel_cal[4];
|
ChannelCalibration channel_cal[4];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/** Read calibration from file. */
|
||||||
|
void read_calibration_file(const char *filename, Calibration& cal)
|
||||||
|
{
|
||||||
|
// Set defaults in case calibration is missing or incomplete.
|
||||||
|
for (unsigned int channel = 0; channel < 4; channel++) {
|
||||||
|
cal.channel_cal[channel].range_spec = RANGE_LO;
|
||||||
|
cal.channel_cal[channel].offset_lo = 8192;
|
||||||
|
cal.channel_cal[channel].offset_hi = 8192;
|
||||||
|
cal.channel_cal[channel].gain_lo = -8191;
|
||||||
|
cal.channel_cal[channel].gain_hi = -409;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ifstream is(filename);
|
||||||
|
if (!is) {
|
||||||
|
log(LOG_ERROR, "Can not read calibration file");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string line;
|
||||||
|
while (std::getline(is, line)) {
|
||||||
|
|
||||||
|
size_t p = line.find_last_not_of(" \t\n\v\f\r");
|
||||||
|
if (p != line.npos) {
|
||||||
|
line.erase(p + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
p = line.find('=');
|
||||||
|
if (p == line.npos) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string label = line.substr(0, p);
|
||||||
|
std::string value = line.substr(p + 1);
|
||||||
|
|
||||||
|
if (label.size() < 4
|
||||||
|
|| label[0] != 'C'
|
||||||
|
|| label[1] != 'H'
|
||||||
|
|| label[2] < '1'
|
||||||
|
|| label[2] > '4'
|
||||||
|
|| label[3] != '_') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int channel = label[2] - '1';
|
||||||
|
label.erase(0, 4);
|
||||||
|
|
||||||
|
if (label == "RANGE") {
|
||||||
|
if (value == "LO") {
|
||||||
|
cal.channel_cal[channel].range_spec = RANGE_LO;
|
||||||
|
}
|
||||||
|
if (value == "HI") {
|
||||||
|
cal.channel_cal[channel].range_spec = RANGE_HI;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (label == "OFFSET_LO") {
|
||||||
|
parse_float(value, cal.channel_cal[channel].offset_lo);
|
||||||
|
}
|
||||||
|
if (label == "OFFSET_HI") {
|
||||||
|
parse_float(value, cal.channel_cal[channel].offset_hi);
|
||||||
|
}
|
||||||
|
if (label == "GAIN_LO") {
|
||||||
|
parse_float(value, cal.channel_cal[channel].gain_lo);
|
||||||
|
}
|
||||||
|
if (label == "GAIN_HI") {
|
||||||
|
parse_float(value, cal.channel_cal[channel].gain_hi);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** Write calibration to file. */
|
||||||
|
bool write_calibration_file(const char *filename, const Calibration& cal)
|
||||||
|
{
|
||||||
|
std::ofstream os(filename);
|
||||||
|
if (!os) {
|
||||||
|
log(LOG_ERROR, "Can not write calibration file");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (unsigned int channel = 0; channel < 4; channel++) {
|
||||||
|
std::string line;
|
||||||
|
line = str_format("CH%u_RANGE=%s\n", channel + 1,
|
||||||
|
(cal.channel_cal[channel].range_spec == RANGE_HI) ? "HI" : "LO");
|
||||||
|
os << line;
|
||||||
|
|
||||||
|
line = str_format("CH%u_OFFSET_LO=%.6f\n", channel + 1,
|
||||||
|
cal.channel_cal[channel].offset_lo);
|
||||||
|
os << line;
|
||||||
|
|
||||||
|
line = str_format("CH%u_OFFSET_HI=%.6f\n", channel + 1,
|
||||||
|
cal.channel_cal[channel].offset_hi);
|
||||||
|
os << line;
|
||||||
|
|
||||||
|
line = str_format("CH%u_GAIN_LO=%.6f\n", channel + 1,
|
||||||
|
cal.channel_cal[channel].gain_lo);
|
||||||
|
os << line;
|
||||||
|
|
||||||
|
line = str_format("CH%u_GAIN_HI=%.6f\n", channel + 1,
|
||||||
|
cal.channel_cal[channel].gain_hi);
|
||||||
|
os << line;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!os) {
|
||||||
|
log(LOG_ERROR, "Can not write calibration file");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* ******** class CommandHandler ******** */
|
||||||
|
|
||||||
|
// Forward declaration.
|
||||||
|
class ControlServer;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The CommandHandler handles commands from remote clients.
|
||||||
|
*/
|
||||||
|
class CommandHandler
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// IDN response fields.
|
||||||
|
static constexpr const char * IDN_MANUFACTURER = "Jigsaw";
|
||||||
|
static constexpr const char * IDN_MODEL = "PuzzleFw";
|
||||||
|
|
||||||
|
// Configuration files.
|
||||||
|
static constexpr const char * CFG_FILE_CALIBRATION =
|
||||||
|
"/var/lib/puzzlefw/cfg/calibration.conf";
|
||||||
|
static constexpr const char * CFG_FILE_NETWORK_SAVED =
|
||||||
|
"/var/lib/puzzlefw/cfg/network.conf";
|
||||||
|
static constexpr const char * CFG_FILE_NETWORK_ACTIVE =
|
||||||
|
"/var/lib/puzzlefw/cfg/network_active.conf";
|
||||||
|
|
||||||
|
enum ExitStatus {
|
||||||
|
EXIT_ERROR = 1,
|
||||||
|
EXIT_HALT = 10,
|
||||||
|
EXIT_REBOOT = 11
|
||||||
|
};
|
||||||
|
|
||||||
struct CommandEnvironment {
|
struct CommandEnvironment {
|
||||||
int channel;
|
int channel;
|
||||||
RangeSpec range_spec;
|
RangeSpec range_spec;
|
||||||
|
@ -206,7 +441,7 @@ public:
|
||||||
*/
|
*/
|
||||||
void reset()
|
void reset()
|
||||||
{
|
{
|
||||||
read_calibration();
|
read_calibration_file(CFG_FILE_CALIBRATION, m_calibration);
|
||||||
m_device.set_adc_simulation_enabled(false);
|
m_device.set_adc_simulation_enabled(false);
|
||||||
m_device.set_digital_simulation_enabled(false);
|
m_device.set_digital_simulation_enabled(false);
|
||||||
m_device.set_trigger_mode(TRIG_NONE);
|
m_device.set_trigger_mode(TRIG_NONE);
|
||||||
|
@ -260,10 +495,10 @@ public:
|
||||||
&& action.compare(0, 6, "ain:ch") == 0
|
&& action.compare(0, 6, "ain:ch") == 0
|
||||||
&& action[7] == ':') {
|
&& action[7] == ':') {
|
||||||
char channel_digit = action[6];
|
char channel_digit = action[6];
|
||||||
if (channel_digit < '0' || channel_digit > '3') {
|
if (channel_digit < '1' || channel_digit > '4') {
|
||||||
return err_unknown_command();
|
return err_unknown_command();
|
||||||
}
|
}
|
||||||
env.channel = channel_digit - '0';
|
env.channel = channel_digit - '1';
|
||||||
action[6] = 'N'; // mark channel index
|
action[6] = 'N'; // mark channel index
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -323,14 +558,14 @@ public:
|
||||||
|
|
||||||
// Handle command IPCFG.
|
// Handle command IPCFG.
|
||||||
if (action == "ipcfg" || action == "ipcfg:saved") {
|
if (action == "ipcfg" || action == "ipcfg:saved") {
|
||||||
if (tokens.size() < 3) {
|
if (tokens.size() < 2) {
|
||||||
return err_missing_argument();
|
return err_missing_argument();
|
||||||
}
|
}
|
||||||
if (tokens.size() > 4) {
|
if (tokens.size() > 5) {
|
||||||
return err_unexpected_argument();
|
return err_unexpected_argument();
|
||||||
}
|
}
|
||||||
const std::string& gw = (tokens.size() > 3) ? tokens[3] : "";
|
tokens.erase(tokens.begin());
|
||||||
return cmd_ipcfg(env, tokens[1], tokens[2], gw);
|
return cmd_ipcfg(env, tokens);
|
||||||
}
|
}
|
||||||
|
|
||||||
return err_unknown_command();
|
return err_unknown_command();
|
||||||
|
@ -338,27 +573,13 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/** Asynchronously stop control and/or data servers. */
|
/** Asynchronously stop control and/or data servers. */
|
||||||
void stop_server(bool stop_control, std::function<void()> handler);
|
void stop_server(std::function<void()> handler);
|
||||||
void stop_data_servers(unsigned int idx, std::function<void()> handler);
|
void stop_data_servers(unsigned int idx, std::function<void()> handler);
|
||||||
|
|
||||||
/** Asynchronously start control and/or data servers. */
|
/** Asynchronously start control and/or data servers. */
|
||||||
void start_server(bool start_control);
|
void start_server();
|
||||||
void start_data_servers(unsigned int idx);
|
void start_data_servers(unsigned int idx);
|
||||||
|
|
||||||
/** Read calibration from file. */
|
|
||||||
void read_calibration()
|
|
||||||
{
|
|
||||||
for (int c = 0; c < 4; c++) {
|
|
||||||
m_calibration.channel_cal[c].range_spec = RANGE_LO;
|
|
||||||
m_calibration.channel_cal[c].offset_lo = 8192;
|
|
||||||
m_calibration.channel_cal[c].offset_hi = 8192;
|
|
||||||
m_calibration.channel_cal[c].gain_lo = -8191;
|
|
||||||
m_calibration.channel_cal[c].gain_hi = -409;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO - read from file
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Convert a raw ADC sample to Volt. */
|
/** Convert a raw ADC sample to Volt. */
|
||||||
double convert_sample_to_volt(unsigned int channel, unsigned int sample)
|
double convert_sample_to_volt(unsigned int channel, unsigned int sample)
|
||||||
{
|
{
|
||||||
|
@ -456,7 +677,7 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Handle command AIN:CHn:OFFS[:range]? */
|
/** Handle command AIN:CHn:OFFS[:range]? */
|
||||||
std::string qry_channel_offs(CommandEnvironment env)
|
std::string qry_channel_offset(CommandEnvironment env)
|
||||||
{
|
{
|
||||||
ChannelCalibration& cal = m_calibration.channel_cal[env.channel];
|
ChannelCalibration& cal = m_calibration.channel_cal[env.channel];
|
||||||
RangeSpec range_spec = env.range_spec;
|
RangeSpec range_spec = env.range_spec;
|
||||||
|
@ -608,8 +829,25 @@ private:
|
||||||
/** Handle command IPCFG[:SAVED]? */
|
/** Handle command IPCFG[:SAVED]? */
|
||||||
std::string qry_ipcfg(CommandEnvironment env)
|
std::string qry_ipcfg(CommandEnvironment env)
|
||||||
{
|
{
|
||||||
// TODO - read network config from file
|
const char *filename = env.saved_flag ? CFG_FILE_NETWORK_SAVED
|
||||||
return "ERROR";
|
: CFG_FILE_NETWORK_ACTIVE;
|
||||||
|
NetworkConfig ipcfg;
|
||||||
|
if (! read_network_config(filename, ipcfg)) {
|
||||||
|
return "ERROR Unconfigured";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string result;
|
||||||
|
if (ipcfg.mode == NETCFG_DHCP) {
|
||||||
|
return "DHCP";
|
||||||
|
}
|
||||||
|
if (ipcfg.mode == NETCFG_STATIC) {
|
||||||
|
return "STATIC "
|
||||||
|
+ ipcfg.ipaddr.to_string()
|
||||||
|
+ " " + ipcfg.netmask.to_string()
|
||||||
|
+ " " + ipcfg.gateway.to_string();
|
||||||
|
}
|
||||||
|
|
||||||
|
return "ERROR Unconfigured";
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Handle command RESET */
|
/** Handle command RESET */
|
||||||
|
@ -706,7 +944,7 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Handle command AIN:CHn:OFFS[:range] */
|
/** Handle command AIN:CHn:OFFS[:range] */
|
||||||
std::string cmd_channel_offs(CommandEnvironment env,
|
std::string cmd_channel_offset(CommandEnvironment env,
|
||||||
const std::string& arg)
|
const std::string& arg)
|
||||||
{
|
{
|
||||||
double offs;
|
double offs;
|
||||||
|
@ -962,18 +1200,24 @@ private:
|
||||||
/** Handle command AIN:MINMAX:CLEAR */
|
/** Handle command AIN:MINMAX:CLEAR */
|
||||||
std::string cmd_cal_save(CommandEnvironment env)
|
std::string cmd_cal_save(CommandEnvironment env)
|
||||||
{
|
{
|
||||||
// TODO - write calibration to file
|
if (! write_calibration_file(CFG_FILE_CALIBRATION, m_calibration)) {
|
||||||
|
return "ERROR Can not write calibration";
|
||||||
|
}
|
||||||
|
|
||||||
// TODO - invoke script to save to SD card
|
// TODO - invoke script to save to SD card
|
||||||
|
|
||||||
return "ERROR";
|
return "ERROR";
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Handle command IPCFG */
|
/** Handle command IPCFG */
|
||||||
std::string cmd_ipcfg(CommandEnvironment env,
|
std::string cmd_ipcfg(CommandEnvironment env,
|
||||||
const std::string& ipaddr,
|
const std::vector<std::string>& args)
|
||||||
const std::string& netmask,
|
|
||||||
const std::string& gateway)
|
|
||||||
{
|
{
|
||||||
// TODO -- parse and check address
|
NetworkConfig ipcfg;
|
||||||
|
std::string errmsg;
|
||||||
|
if (! parse_network_config(args, ipcfg, errmsg)) {
|
||||||
|
return "ERROR " + errmsg;
|
||||||
|
}
|
||||||
// TODO -- activate or save address, restart networking if needed
|
// TODO -- activate or save address, restart networking if needed
|
||||||
return "ERROR";
|
return "ERROR";
|
||||||
}
|
}
|
||||||
|
@ -987,8 +1231,8 @@ private:
|
||||||
{ "ain:channels:count?", &CommandHandler::qry_channels_count },
|
{ "ain:channels:count?", &CommandHandler::qry_channels_count },
|
||||||
{ "ain:channels:active?", &CommandHandler::qry_channels_active },
|
{ "ain:channels:active?", &CommandHandler::qry_channels_active },
|
||||||
{ "ain:chN:range?", &CommandHandler::qry_channel_range },
|
{ "ain:chN:range?", &CommandHandler::qry_channel_range },
|
||||||
{ "ain:chN:offs?", &CommandHandler::qry_channel_offs },
|
{ "ain:chN:offset?", &CommandHandler::qry_channel_offset },
|
||||||
{ "ain:chN:offs:RR?", &CommandHandler::qry_channel_offs },
|
{ "ain:chN:offset:RR?", &CommandHandler::qry_channel_offset },
|
||||||
{ "ain:chN:gain?", &CommandHandler::qry_channel_gain },
|
{ "ain:chN:gain?", &CommandHandler::qry_channel_gain },
|
||||||
{ "ain:chN:gain:RR?", &CommandHandler::qry_channel_gain },
|
{ "ain:chN:gain:RR?", &CommandHandler::qry_channel_gain },
|
||||||
{ "ain:chN:sample?", &CommandHandler::qry_channel_sample },
|
{ "ain:chN:sample?", &CommandHandler::qry_channel_sample },
|
||||||
|
@ -1025,8 +1269,8 @@ private:
|
||||||
command_table_one_arg = {
|
command_table_one_arg = {
|
||||||
{ "ain:channels:active", &CommandHandler::cmd_channels_active },
|
{ "ain:channels:active", &CommandHandler::cmd_channels_active },
|
||||||
{ "ain:chN:range", &CommandHandler::cmd_channel_range },
|
{ "ain:chN:range", &CommandHandler::cmd_channel_range },
|
||||||
{ "ain:chN:offs", &CommandHandler::cmd_channel_offs },
|
{ "ain:chN:offset", &CommandHandler::cmd_channel_offset },
|
||||||
{ "ain:chN:offs:RR", &CommandHandler::cmd_channel_offs },
|
{ "ain:chN:offset:RR", &CommandHandler::cmd_channel_offset },
|
||||||
{ "ain:chN:gain", &CommandHandler::cmd_channel_gain },
|
{ "ain:chN:gain", &CommandHandler::cmd_channel_gain },
|
||||||
{ "ain:chN:gain:RR", &CommandHandler::cmd_channel_gain },
|
{ "ain:chN:gain:RR", &CommandHandler::cmd_channel_gain },
|
||||||
{ "ain:srate", &CommandHandler::cmd_srate },
|
{ "ain:srate", &CommandHandler::cmd_srate },
|
||||||
|
@ -1052,6 +1296,8 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* ******** class ControlServer ******** */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Manage TCP connections for remote control.
|
* Manage TCP connections for remote control.
|
||||||
*/
|
*/
|
||||||
|
@ -1374,10 +1620,8 @@ private:
|
||||||
|
|
||||||
/* ******** Methods for class CommandHandler ******** */
|
/* ******** Methods for class CommandHandler ******** */
|
||||||
|
|
||||||
void CommandHandler::stop_server(bool stop_control,
|
void CommandHandler::stop_server(std::function<void()> handler)
|
||||||
std::function<void()> handler)
|
|
||||||
{
|
{
|
||||||
if (stop_control) {
|
|
||||||
asio::post(m_control_server->get_executor(),
|
asio::post(m_control_server->get_executor(),
|
||||||
[this,handler]() {
|
[this,handler]() {
|
||||||
m_control_server->stop_server();
|
m_control_server->stop_server();
|
||||||
|
@ -1386,9 +1630,6 @@ void CommandHandler::stop_server(bool stop_control,
|
||||||
stop_data_servers(0, handler);
|
stop_data_servers(0, handler);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
} else {
|
|
||||||
stop_data_servers(0, handler);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CommandHandler::stop_data_servers(unsigned int idx,
|
void CommandHandler::stop_data_servers(unsigned int idx,
|
||||||
|
@ -1408,9 +1649,8 @@ void CommandHandler::stop_data_servers(unsigned int idx,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CommandHandler::start_server(bool start_control)
|
void CommandHandler::start_server()
|
||||||
{
|
{
|
||||||
if (start_control) {
|
|
||||||
asio::post(m_control_server->get_executor(),
|
asio::post(m_control_server->get_executor(),
|
||||||
[this]() {
|
[this]() {
|
||||||
m_control_server->start_server();
|
m_control_server->start_server();
|
||||||
|
@ -1419,9 +1659,6 @@ void CommandHandler::start_server(bool start_control)
|
||||||
start_data_servers(0);
|
start_data_servers(0);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
} else {
|
|
||||||
start_data_servers(0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CommandHandler::start_data_servers(unsigned int idx)
|
void CommandHandler::start_data_servers(unsigned int idx)
|
||||||
|
@ -1522,9 +1759,8 @@ int run_remote_control_server(
|
||||||
io.run();
|
io.run();
|
||||||
|
|
||||||
// TODO -- multi-threading
|
// TODO -- multi-threading
|
||||||
// TODO -- get exit status from command handler
|
|
||||||
|
|
||||||
return 0;
|
return command_handler.exit_status();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue