Skip to content

Commit

Permalink
Added libconfig -> JSON server
Browse files Browse the repository at this point in the history
 - only works on 127.0.0.1:3000 at this stage
 - some restrictions on libconfig syntax
  • Loading branch information
martenpayne committed Oct 26, 2017
1 parent ba69c5f commit e071cdc
Show file tree
Hide file tree
Showing 4 changed files with 119 additions and 49 deletions.
49 changes: 18 additions & 31 deletions bin/config/pokey.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,18 @@ configuration =
{
serialNumber = "25770",
name = "DCMetering",
# pin - integer - any valid IO pin (1-55)
# name - string - name of the pin
# type - string - DIGITAL_INPUT, DIGITAL_OUTPUT
# description - string
# units - string
# default - integer - value on start
pins = (
# pin - integer - any valid IO pin (1-55)
# name - string - name of the pin
# type - string - DIGITAL_INPUT, DIGITAL_OUTPUT
# description - string
# units - string
# default - integer - value on start

),
# pins 1-2 as encoder 1
# pins 5-6 as encoder 2
# pins 15-16 as encoder 3
encoders = (
# pins 1-2 as encoder 1
# pins 5-6 as encoder 2
# pins 15-16 as encoder 3
{
encoder = 1,
name = "V_OH_FLTALT",
Expand Down Expand Up @@ -74,22 +73,22 @@ configuration =
}
)
},
# pokey_1
{
# pokey_1
# Fuel Control Panel & Bus Switching Panel
serialNumber = "25774",
name = "pokey_1",
pins = (
{
pin = 1,
name = "I_OH_FUEL_PUMP_LA",
description = "Left AFT fuel pump indicator"
description = "Left AFT fuel pump indicator",
type = "DIGITAL_OUTPUT"
},
{
pin = 2,
name = "I_OH_FUEL_PUMP_LF",
description = "Left FWD fuel pump indicator"
description = "Left FWD fuel pump indicator",
type = "DIGITAL_OUTPUT"
},
{
Expand Down Expand Up @@ -207,32 +206,20 @@ configuration =
type = "DIGITAL_OUTPUT"
},
{
# should send GRD/OFF
pin = 41,
name = "S_OH_ENG_START_L",
type = "DIGITAL_INPUT",
# should send GRD/OFF
},
# {
# pin = 42,
# name = "Off,GRD,CONT,FLT",
# type = "DIGITAL_INPUT"
# # should send FLT/OFF
# },
# {
# pin = 43,
# name = "Off,GRD,CONT,FLT",
# type = "DIGITAL_INPUT"
# # should send CONT
# },
type = "DIGITAL_INPUT"
},
{
pin = 44,
name = "S_OH_YAW_DAMPER",
type = "DIGITAL_INPUT"
}
)
},
# pokey_2
{
# pokey_2
serialNumber = "25423",
name = "pokey_2",
pins = (
Expand Down Expand Up @@ -384,8 +371,8 @@ configuration =

)
},
# pokey_3
{
# pokey_3
serialNumber = "26767",
name = "pokey_3",
pins = (
Expand Down Expand Up @@ -639,7 +626,7 @@ configuration =
units = "degrees",
min = 0,
max = 710,
default = 0,
default = 0
}
) ,
pins = ()
Expand Down
113 changes: 97 additions & 16 deletions src/app/simhub.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ std::shared_ptr<SimHubEventController> SimHubEventController::EventControllerIns
return SimHubEventController::_EventControllerInstance;
}

SimHubEventController::SimHubEventController() : _configurationHTTPListener(U("http://localhost:9000/configuration"))
SimHubEventController::SimHubEventController() : _configurationHTTPListener(U("http://127.0.0.1:3000"))
{
_prepare3dMethods.plugin_instance = NULL;
_pokeyMethods.plugin_instance = NULL;
Expand All @@ -36,31 +36,106 @@ SimHubEventController::SimHubEventController() : _configurationHTTPListener(U("h
logger.log(LOG_INFO, "Starting event controller");
}

void SimHubEventController::httpGETHandler(web::http::http_request request)
/**
* like strtok but not evil
*/
void split(const std::string &sequence, std::string &delims, std::vector<std::string> &tokens)
{
auto http_get_vars = web::uri::split_query(request.request_uri().query());

auto found_name = http_get_vars.find(U("request"));
size_t i = 0;
size_t pos = sequence.find(delims);

if (found_name == end(http_get_vars)) {
auto err = U("Request received with get var \"request\" omitted from query.");
std::clog << err << std::endl;
request.reply(web::http::status_codes::BadRequest, web::json::value::string(err));
if (pos == std::string::npos){
tokens.push_back(sequence);
return;
}
auto request_name = found_name->second;

web::json::value resp;
request.reply(web::http::status_codes::OK, web::json::value::string(U("Request received for: ") + request_name));
while (pos != std::string::npos) {
tokens.push_back(sequence.substr(i, pos-i));
i = ++pos;
pos = sequence.find(delims, pos);

if (pos == std::string::npos) {
tokens.push_back(sequence.substr(i, sequence.length()));
}
}
}

/**
* rudimentary converter from libconfig content to JSON content
* - doesn't suppoert '#' comments outside of dictionaries (like in lists)
*/
std::string libconfigToJSON(std::string configFilename)
{
std::ifstream file(configFilename);

if (!file) {
return "";
}

size_t lineIdx = 0;

std::string line;
std::stringstream jsonStream;

std::string commentToken("#");
std::string jsonAssign(":");

std::clog << U("Received request: ") << request_name << std::endl;
//http_respond(req, web::http::status_codes::OK, web::json::value::string(U("Request received for: ") + request_name));
jsonStream << "{" << std::endl;

while (std::getline(file, line)) {
lineIdx++;

std::replace(line.begin(), line.end(), '=', ':');
std::replace(line.begin(), line.end(), '(', '[');
std::replace(line.begin(), line.end(), ')', ']');
std::replace(line.begin(), line.end(), ';', ',');

std::vector<std::string> tokens;

split(line, commentToken, tokens);

if (line.find(commentToken) != std::string::npos) {
jsonStream << "\"_line_comment_" << lineIdx << "\": \"" << tokens[tokens.size() - 1] << "\"," << std::endl;
}
else {
tokens.clear();
split(line, jsonAssign, tokens);

if (tokens.size() > 1) {
size_t p = tokens[0].find_first_not_of(" ");
tokens[0].insert(p, "\"");
p = tokens[0].find_last_not_of(" ");
tokens[0].insert(p + 1, "\"");

jsonStream << tokens[0] << ":";
for (size_t i = 1; i < tokens.size(); i++) {
jsonStream << " " << tokens[i];
}
jsonStream << std::endl;
}
else {
jsonStream << line << std::endl;
}
}
}

jsonStream << "}" << std::endl;

return jsonStream.str();
}

/**
* serves GET requests on http://localhost/configuration - returns JSON converted
* pokey configuration content
*/
void SimHubEventController::httpGETConfigurationHandler(web::http::http_request request)
{
std::string config_json = libconfigToJSON(_configManager->pokeyConfigurationFilename());
request.reply(web::http::status_codes::OK, config_json);
}

SimHubEventController::~SimHubEventController(void)
{
_configurationHTTPListener.close();

if (_running) {
terminate();
}
Expand Down Expand Up @@ -336,8 +411,14 @@ void SimHubEventController::terminate(void)
#if defined(_AWS_SDK)
ceaseSustainThread();
#endif

// kill web configuration listener
auto listenerCloseTask = _configurationHTTPListener.close();
listenerCloseTask.wait();

shutdownPlugin(_prepare3dMethods);
shutdownPlugin(_pokeyMethods);

_running = false;
}

Expand Down
5 changes: 3 additions & 2 deletions src/app/simhub.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ class SimHubEventController

//! implements configuration server
web::http::experimental::listener::http_listener _configurationHTTPListener;
virtual void httpGETHandler(web::http::http_request request);
virtual void httpGETConfigurationHandler(web::http::http_request request);

public:
virtual ~SimHubEventController(void);
Expand Down Expand Up @@ -122,8 +122,9 @@ template <class F> void SimHubEventController::runEventLoop(F &&eventProcessorFu
#if defined(_AWS_SDK)
startSustainThread();
#endif
// start http listener for json config read
_configurationHTTPListener.open().wait();
_configurationHTTPListener.support(web::http::methods::GET, std::bind(&SimHubEventController::httpGETHandler, this, std::placeholders::_1));
_configurationHTTPListener.support(web::http::methods::GET, std::bind(&SimHubEventController::httpGETConfigurationHandler, this, std::placeholders::_1));

while (!breakLoop) {
try {
Expand Down
1 change: 1 addition & 0 deletions src/common/configmanager/configmanager.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ class ConfigManager
std::string loadPokeyConfiguration(void);
std::string version(void);
std::string name(void);
std::string pokeyConfigurationFilename(void) { return _pokeyConfigurationFilename; };
std::shared_ptr<MappingConfigManager> mapManager(void);
libconfig::Config *config() { return &_config; }
};
Expand Down

1 comment on commit e071cdc

@mteichtahl
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comments on individual lines

Please sign in to comment.