diff --git a/include/trick/AttributesMap.hh b/include/trick/AttributesMap.hh index 410574ca..6adb5b8f 100644 --- a/include/trick/AttributesMap.hh +++ b/include/trick/AttributesMap.hh @@ -63,6 +63,7 @@ namespace Trick { #endif void print_xml( std::ofstream & outfile ) ; + void print_json(std::ofstream & sie_out ) ; private: std::map name_to_attr_map ; diff --git a/include/trick/EnumAttributesMap.hh b/include/trick/EnumAttributesMap.hh index b12ad09d..e4c0e719 100644 --- a/include/trick/EnumAttributesMap.hh +++ b/include/trick/EnumAttributesMap.hh @@ -55,6 +55,7 @@ namespace Trick { } void print_xml( std::ofstream & outfile ) ; + void print_json(std::ofstream & sie_out ) ; private: std::map name_to_attr_map ; diff --git a/include/trick/Sie.hh b/include/trick/Sie.hh index 277d1e92..2f2a2b9f 100644 --- a/include/trick/Sie.hh +++ b/include/trick/Sie.hh @@ -40,10 +40,12 @@ namespace Trick { void class_attr_map_print_xml() ; void enum_attr_map_print_xml() ; void top_level_objects_print_xml() ; + void sie_print_json() ; private: void top_level_objects_print(std::ofstream & sie_out) ; + void top_level_objects_json(std::ofstream & sie_out) ; // These are singleton maps holding all attributes known to the sim Trick::AttributesMap * class_attr_map ; /* ** -- This is be ignored by ICG */ diff --git a/trick_sims/.gitignore b/trick_sims/.gitignore index 3607e6d1..18797f68 100644 --- a/trick_sims/.gitignore +++ b/trick_sims/.gitignore @@ -18,6 +18,7 @@ S_document.xml S_library_list S_main_* S_sie.resource +S_sie.json S_source.cpp S_source.hh T_main_* diff --git a/trick_source/sim_services/Sie/AttributesMap.cpp b/trick_source/sim_services/Sie/AttributesMap.cpp index 40a39c89..7c991677 100644 --- a/trick_source/sim_services/Sie/AttributesMap.cpp +++ b/trick_source/sim_services/Sie/AttributesMap.cpp @@ -98,3 +98,64 @@ void Trick::AttributesMap::print_xml(std::ofstream & sie_out ) { } } +void Trick::AttributesMap::print_json(std::ofstream & sie_out ) { + std::map::iterator it ; + int jj ; + sie_out << " \"classes\": [\n" ; + for ( it = name_to_attr_map.begin() ; it != name_to_attr_map.end() ; it++ ) { + ATTRIBUTES * attr = (*it).second ; + std::string class_name = (*it).first; + std::replace(class_name.begin(), class_name.end(), ':', '_'); + sie_out << " {\n"; + sie_out << " \"name\": \"" << class_name << "\",\n" ; + if(attr->name[0] == '\0' || (attr->type_name == NULL)) { + sie_out << " \"members\": []\n" ; + } else { + sie_out << " \"members\": [\n" ; + while ( attr->name[0] != '\0' and (attr->type_name != NULL)) { + sie_out << " {\n"; + sie_out << " \"name\": \"" << attr->name << "\",\n" ; + std::string type_name = attr->type_name; + std::replace(type_name.begin(), type_name.end(), ':', '_'); + sie_out << " \"type\": \"" << type_remove_dims(type_name) << "\",\n" ; + sie_out << " \"io_attributes\": \"" << attr->io << "\",\n" ; + sie_out << " \"units\": \"" ; + // If the mods bit is set for using -- as the units + if ( attr->mods & TRICK_MODS_UNITSDASHDASH ) { + sie_out << "--" ; + } else { + sie_out << attr->units ; + } + sie_out << "\"" ; + + std::string description = attr->des; + if ( ! description.empty() ) { + sie_out << ",\n \"description\": \"" << replace_special_chars(description) << "\"" ; + } + if ( attr->num_index > 0 ) { + sie_out << ",\n \"dimensions\": [" ; + for (jj = 0; jj < attr->num_index - 1; jj++) { + sie_out << " \"" << attr->index[jj].size << "\"," ; + } + sie_out << " \"" << attr->index[attr->num_index - 1].size << "\" " ; + sie_out << "]\n" ; + } else { + sie_out << '\n' ; + } + sie_out << " }" ; + if((attr + 1)->name[0] != '\0') { + sie_out << ','; + } + sie_out << '\n'; + attr++ ; + } + sie_out << " ]\n" ; + } + sie_out << " }" ; + if(std::next(it, 1) != name_to_attr_map.end()) { + sie_out << ',' ; + } + sie_out << "\n" ; + } + sie_out << " ],\n" ; +} diff --git a/trick_source/sim_services/Sie/EnumAttributesMap.cpp b/trick_source/sim_services/Sie/EnumAttributesMap.cpp index c0bcd791..173c2d96 100644 --- a/trick_source/sim_services/Sie/EnumAttributesMap.cpp +++ b/trick_source/sim_services/Sie/EnumAttributesMap.cpp @@ -31,3 +31,38 @@ void Trick::EnumAttributesMap::print_xml(std::ofstream & sie_out ) { } } +void Trick::EnumAttributesMap::print_json(std::ofstream & sie_out ) { + std::map::iterator it ; + ENUM_ATTR * enum_attr ; + sie_out << " \"enumerations\": [\n" ; + for ( it = name_to_attr_map.begin() ; it != name_to_attr_map.end() ; it++ ) { + enum_attr = (*it).second ; + + if ( enum_attr != NULL ) { + sie_out << " {\n"; + std::string name = it->first; + std::replace(name.begin(), name.end(), ':', '_'); + sie_out << " \"name\": \"" << name << "\",\n" ; + sie_out << " \"pairs\": [\n"; + while ( enum_attr->label[0] != '\0' ) { + sie_out << " {\n" ; + sie_out << " \"label\": \"" << enum_attr->label << "\",\n" ; + sie_out << " \"value\": \"" << enum_attr->value << "\"\n" ; + sie_out << " }" ; + if((enum_attr + 1)->label[0] != '\0') { + sie_out << ','; + } + sie_out << "\n"; + enum_attr++ ; + } + sie_out << " ]\n" ; + sie_out << " }" ; + if(std::next(it, 1) != name_to_attr_map.end()) { + sie_out << ',' ; + } + sie_out << '\n'; + } + } + sie_out << " ],\n"; +} + diff --git a/trick_source/sim_services/Sie/Makefile b/trick_source/sim_services/Sie/Makefile index 6f722048..80911292 100644 --- a/trick_source/sim_services/Sie/Makefile +++ b/trick_source/sim_services/Sie/Makefile @@ -1,3 +1,5 @@ include $(dir $(lastword $(MAKEFILE_LIST)))../../../share/trick/makefiles/Makefile.common include ${TRICK_HOME}/share/trick/makefiles/Makefile.tricklib -include Makefile_deps + +TRICK_CXXFLAGS += -std=c++11 \ No newline at end of file diff --git a/trick_source/sim_services/Sie/Sie.cpp b/trick_source/sim_services/Sie/Sie.cpp index ce686236..3366ec4f 100644 --- a/trick_source/sim_services/Sie/Sie.cpp +++ b/trick_source/sim_services/Sie/Sie.cpp @@ -37,6 +37,7 @@ int Trick::Sie::process_sim_args() { /* If main is being invoked by the configuration processor (cp) to generate the sie resource file... */ /* Generate the sie resource file */ sie_print_xml(); + sie_print_json(); // Silently exit the sim without printing the termination message exit(0) ; @@ -73,6 +74,42 @@ void Trick::Sie::top_level_objects_print(std::ofstream & sie_out) { } } +void Trick::Sie::top_level_objects_json(std::ofstream & sie_out) { + Trick::VARIABLE_MAP_ITER vit ; + int jj ; + sie_out << " \"top_level_objects\": [\n"; + for ( vit = trick_MM->variable_map_begin() ; vit != trick_MM->variable_map_end() ; vit++ ) { + ALLOC_INFO * alloc_info = (*vit).second ; + + if ( alloc_info != NULL ) { + sie_out << " {\n" ; + sie_out << " \"name\": \"" << vit->first << "\",\n" ; + sie_out << " \"type\": \"" ; + std::string type = trickTypeCharString(alloc_info->type, alloc_info->user_type_name ); + std::replace(type.begin(), type.end(), ':', '_') ; + sie_out << type << "\",\n" ; + sie_out << " \"alloc_memory_init\": \"" << alloc_info->alloced_in_memory_init << "\""; + if ( alloc_info->num_index > 0 ) { + sie_out << ",\n \"dimensions\": [" ; + for (jj = 0; jj < alloc_info->num_index - 1; jj++) { + sie_out << " \"" << alloc_info->index[jj] << "\"," ; + } + sie_out << " \"" << alloc_info->index[alloc_info->num_index - 1] << "\" " ; + sie_out << "]\n" ; + } else { + sie_out << '\n' ; + } + sie_out << " }" ; + if(std::next(vit, 1) != trick_MM->variable_map_end()) { + sie_out << ',' ; + } + sie_out << '\n'; + } + } + sie_out << " ]\n"; +} + + void Trick::Sie::sie_print_xml() { std::ofstream sie_out ; std::string file_name = std::string(command_line_args_get_default_dir()) + "/" + "S_sie.resource" ; @@ -86,6 +123,19 @@ void Trick::Sie::sie_print_xml() { sie_out.close() ; } +void Trick::Sie::sie_print_json() { + std::ofstream sie_out ; + std::string file_name = std::string(command_line_args_get_default_dir()) + "/" + "S_sie.json" ; + sie_out.open(file_name.c_str()) ; + sie_out << "{\n" ; + class_attr_map->print_json(sie_out) ; + enum_attr_map->print_json(sie_out) ; + top_level_objects_json(sie_out) ; + sie_out << "}\n" ; + sie_out.close() ; +} + + void Trick::Sie::class_attr_map_print_xml() { std::ofstream sie_out ; std::string file_name = std::string(command_line_args_get_default_dir()) + "/" + "S_sie_class.xml" ; diff --git a/trick_source/web/HttpServer/include/VariableServerSession.hh b/trick_source/web/HttpServer/include/VariableServerSession.hh index 0c0a13eb..04bd440b 100644 --- a/trick_source/web/HttpServer/include/VariableServerSession.hh +++ b/trick_source/web/HttpServer/include/VariableServerSession.hh @@ -31,6 +31,8 @@ class VariableServerSession : public WebSocketSession { private: int sendErrorMessage(const char* fmt, ... ); + int sendSieMessage(void); + int sendUnitsMessage(const char* vname); REF2* make_error_ref(const char* in_name); double stageTime; bool dataStaged; diff --git a/trick_source/web/HttpServer/include/VariableServerVariable.hh b/trick_source/web/HttpServer/include/VariableServerVariable.hh index 415cfde4..4d9351cd 100644 --- a/trick_source/web/HttpServer/include/VariableServerVariable.hh +++ b/trick_source/web/HttpServer/include/VariableServerVariable.hh @@ -20,6 +20,7 @@ class VariableServerVariable { VariableServerVariable( REF2* variableType); ~VariableServerVariable(); const char* getName(); + const char* getUnits(); void stageValue(); void writeValue( std::ostream& chkpnt_os ); diff --git a/trick_source/web/HttpServer/src/VariableServerSession.cpp b/trick_source/web/HttpServer/src/VariableServerSession.cpp index ab39a765..b4ea0895 100644 --- a/trick_source/web/HttpServer/src/VariableServerSession.cpp +++ b/trick_source/web/HttpServer/src/VariableServerSession.cpp @@ -9,6 +9,7 @@ LIBRARY DEPENDENCIES: #include #include #include // for setprecision +#include #include #include "trick/memorymanager_c_intf.h" #include "trick/input_processor_proto.h" @@ -117,6 +118,12 @@ int VariableServerSession::handleMessage(std::string client_msg) { pycode.erase(std::remove(pycode.begin(), pycode.end(), '\r'), pycode.end()); // Call the Trick input processor. ip_parse(pycode.c_str()); + } else if (cmd == "sie") { + // send S_sie.json + sendSieMessage(); + } else if (cmd == "units") { + // send S_sie.json + sendUnitsMessage(var_name.c_str()); } else { sendErrorMessage("Unknown Command: \"%s\".\n", cmd.c_str()); status = 1; @@ -223,3 +230,42 @@ REF2* VariableServerSession::make_error_ref(const char* in_name) { WebSocketSession* makeVariableServerSession( struct mg_connection *nc ) { return new VariableServerSession(nc); } + + +int VariableServerSession::sendSieMessage(void) { + std::ifstream file("./S_sie.json"); + std::stringstream ss; + ss << "{ \"msg_type\": \"sie\", \"data\": "; + ss << file.rdbuf(); + file.close(); + ss << "}"; + std::string tmp = ss.str(); + const char* message = tmp.c_str(); + mg_send_websocket_frame(connection, WEBSOCKET_OP_TEXT, message, strlen(message)); + return 0; +} + +int VariableServerSession::sendUnitsMessage(const char* vname) { + std::vector::iterator it; + std::stringstream ss; + ss << "{ \"msg_type\": \"units\", \"var_name\": \"" << vname << "\", \"data\": \""; + for (it = sessionVariables.begin(); it != sessionVariables.end(); it++ ) { + if(!strcmp((*it)->getName(), vname)) { + ss << ( + ( + ( + (*it)->getUnits() != NULL + ) && + ( + (*it)->getUnits()[0] != '\0' + ) + ) ? (*it)->getUnits() : "--") << "\"}"; + std::string tmp = ss.str(); + const char* message = tmp.c_str(); + mg_send_websocket_frame(connection, WEBSOCKET_OP_TEXT, message, strlen(message)); + return 0; + } + } + sendErrorMessage("Variable Server: var_units cannot get units for \"%s\" because it must be added to the variable server first\n", vname); + return 0; +} diff --git a/trick_source/web/HttpServer/src/VariableServerVariable.cpp b/trick_source/web/HttpServer/src/VariableServerVariable.cpp index 4bfa50e7..6b4799f8 100644 --- a/trick_source/web/HttpServer/src/VariableServerVariable.cpp +++ b/trick_source/web/HttpServer/src/VariableServerVariable.cpp @@ -50,6 +50,10 @@ const char* VariableServerVariable::getName() { return varInfo->reference; } +const char* VariableServerVariable::getUnits() { + return varInfo->attr->units; +} + static void write_quoted_str( std::ostream& os, const char* s) { int ii; int len = strlen(s);