#include "CreatePipes.h" #include #include #include "json.hpp" #include #include #include "file_api.hpp" #define ECHO_MODULE_ID 0x00000040 /// Идентификатор тестового модуля #define ECHO_SUBMOD_ID 0x00000140 /// Идентификатор тестового подмодуля #define ECHO_INPUT_DATA_SIZE 8 #define ECHO_OUTPUT_DATA_SIZE 8 #define ECHO_PARAMETER_GAIN_IDX 125 /// Индекс параметра Gain для подмодуля ECHO #define BIT_MODULE_ID 0x00000032 #define BIT_SUBMOD_ID 0x00000132 #define BIT_INPUT_DATA_SIZE 1 #define BIT_OUTPUT_DATA_SIZE 1 #define BIT_PARAMETER_1_IDX 123 #define BIT_PARAMETER_2_IDX 124 using json = nlohmann::json; uint32_t Echo_Gain = 0; uint32_t bit_param_1 = 0; uint32_t bit_param_2 = 0; struct EchoData { float data_f; uint32_t data_i; }; union EchoDataMem { EchoData data; uint8_t mem[sizeof(EchoData)]; }; EchoDataMem Echo_inpCycData; EchoDataMem Echo_outCycData; uint8_t be_data_inp[sizeof(EchoData)]; void endian_convert_32(uint8_t * p_data) { uint8_t tmp = p_data[1]; p_data[1] = p_data[2]; p_data[2] = tmp; tmp = p_data[0]; p_data[0] = p_data[3]; p_data[3] = tmp; } /** Поток обработки входящих данных от именнованого канала. */ std::shared_ptr< std::istream > p_input_stream_; /** Поток для отправки данных в именнованй канал. */ std::shared_ptr< std::ostream > p_output_stream_; using json = nlohmann::json; void getParameter(json& jx, std::vector& in_vect, uint8_t * pParam, uint16_t param_size) { in_vect.clear(); in_vect = jx["data"]["bytes"].get>(); if (in_vect.size() == param_size) { std::copy(in_vect.begin(), in_vect.end(), pParam); if (param_size == 4) { endian_convert_32(pParam); } } } void requestParam(json& j_request, uint32_t mod_id, uint32_t submod_id, uint32_t param_idx) { json j_data; j_data["module_id"] = mod_id; j_data["submodule_id"] = submod_id; j_data["param_index"] = param_idx; j_request["params"].push_back(j_data); } void requestCyclic(json& j_request, uint32_t mod_id, uint32_t submod_id) { json j_data; j_data["module_id"] = mod_id; j_data["submodule_id"] = submod_id; j_request["params"].push_back(j_data); } void putCyclicData(json& j_cyc_data, uint32_t mod_id, uint32_t submod_id, uint8_t * pdata, uint16_t data_size) { json j_set_data; std::vector in_data; in_data.insert(in_data.end(), &pdata[0], &pdata[data_size]); j_set_data["module_id"] = mod_id; j_set_data["submodule_id"] = submod_id; j_set_data["data"] = json::binary(in_data); j_cyc_data["params"].push_back(j_set_data); } int main(int argc, char * argv[]) { json j_cfg = json::parse(fileapi_read_file("sample_app_echo_config.json")); std::filesystem::path _input_path{j_cfg["app_settings"]["app_inp_pipe_name"].get()}; /// Выходной канал профинет, входной канал апп std::filesystem::path _output_path{j_cfg["app_settings"]["app_out_pipe_name"].get()}; /// Входной канал профинет, входной канал апп auto streams = itr::create_pipes( _input_path, _output_path, std::cout ); p_input_stream_ = std::move( std::get<0>( streams ) ) ; p_output_stream_ = std::move( std::get<1>( streams ) ); json j_get_flags; j_get_flags["jsonrpc"] = "2.0"; j_get_flags["method"] = "readFlags"; j_get_flags["params"]; j_get_flags["id"] = 0; json j_get_echo_param_gain; j_get_echo_param_gain["jsonrpc"] = "2.0"; j_get_echo_param_gain["method"] = "readSubmoduleParameterNamed"; j_get_echo_param_gain["params"] = json::array(); requestParam(j_get_echo_param_gain, ECHO_MODULE_ID, ECHO_SUBMOD_ID, ECHO_PARAMETER_GAIN_IDX); requestParam(j_get_echo_param_gain, BIT_MODULE_ID, BIT_SUBMOD_ID, BIT_PARAMETER_1_IDX); requestParam(j_get_echo_param_gain, BIT_MODULE_ID, BIT_SUBMOD_ID, BIT_PARAMETER_2_IDX); j_get_echo_param_gain["id"] = 0; json j_data; json j_get_echo_data; j_get_echo_data["jsonrpc"] = "2.0"; j_get_echo_data["method"] = "readCyclicIoDataNamed"; j_get_echo_data["params"] = json::array(); requestCyclic(j_get_echo_data, ECHO_MODULE_ID, ECHO_SUBMOD_ID); requestCyclic(j_get_echo_data, BIT_MODULE_ID, BIT_SUBMOD_ID); j_get_echo_data["id"] = 0; json j_set_echo_data; j_set_echo_data["jsonrpc"] = "2.0"; j_set_echo_data["method"] = "writeCyclicIoDataNamed"; j_set_echo_data["params"] = json::array(); j_set_echo_data["id"] = 0; std::cout << "Starting...." << std::endl; std::string answer_str; for(;;) { answer_str.clear(); std::this_thread::sleep_for(std::chrono::milliseconds(1000)); std::string request{j_get_flags.dump()}; ///Запрос: *p_output_stream_ << request << std::endl; ///Ждем ответ: std::getline( *p_input_stream_.get( ), answer_str); json j_answ = json::parse(answer_str); if (!j_answ.contains("result")) { std::cout << "Error: result" << std::endl; continue; } json& j_res = j_answ["result"]; if (!j_res.contains("EVENT_CONNECTION_ESTABLISHED")) { std::cout << "Error: EVENT_CONNECTION_ESTABLISHED" << std::endl; continue; } if (j_res["EVENT_CONNECTION_ESTABLISHED"].get() == true) { std::cout << "EVENT_CONNECTION_ESTABLISHED: true" << std::endl; } if (j_res["EVENT_CONNECTION_ABORT"].get() == true) { std::cout << "EVENT_CONNECTION_ABORT: true" << std::endl; } if (j_res["EVENT_NEW_PARAM_DATA"].get() == true) { answer_str.clear(); std::cout << "EVENT_NEW_PARAM_DATA: true" << std::endl; *p_output_stream_ << j_get_echo_param_gain.dump() << std::endl; std::getline( *p_input_stream_.get( ), answer_str); json j_answ_par = json::parse(answer_str); std::vector in; //std::cout << "EVENT_NEW_PARAM_DATA: " << answer_str << std::endl; for (auto& jx : j_answ_par["result"]) { uint32_t module_id; uint32_t submodule_id; uint32_t param_idx; module_id = jx["module_id"].get(); submodule_id = jx["submodule_id"].get(); param_idx = jx["param_index"].get(); switch(module_id) { case ECHO_MODULE_ID: { switch(submodule_id) { case ECHO_SUBMOD_ID: { if (param_idx != ECHO_PARAMETER_GAIN_IDX) { std::cout << "Error param idx" << std::endl; continue; } Echo_Gain = jx.at("data").at("EchoGain").get(); std::cout << "Echo_Gain = " << Echo_Gain << std::endl; } break; default: { std::cout << "Error submodule id" << std::endl; continue; } break; } } break; case BIT_MODULE_ID: { switch(submodule_id) { case BIT_SUBMOD_ID: { switch(param_idx) { case BIT_PARAMETER_1_IDX: { bit_param_1 = jx.at("data").at("I8O8Param1").get(); std::cout << "bit_param_1 = " << bit_param_1 << std::endl; } break; case BIT_PARAMETER_2_IDX: { bit_param_2 = jx.at("data").at("I8O8Param2").get(); std::cout << "bit_param_2 = " << bit_param_2 << std::endl; } break; default: { std::cout << "Error param idx" << std::endl; continue; } break; } } break; default: { std::cout << "Error submodule id" << std::endl; continue; } break; } } break; default: { std::cout << "Error module id" << std::endl; continue; } break; } } } if (j_res["EVENT_NEW_CYCLIC_DATA"].get() == true) { static uint32_t value_i = 0; static float value_f = 0.0; static uint32_t value_bit = 0; answer_str.clear(); *p_output_stream_ << j_get_echo_data.dump() << std::endl; std::getline( *p_input_stream_.get( ), answer_str); json j_answ_data = json::parse(answer_str); std::vector in; for (auto& jx : j_answ_data["result"]) { uint32_t module_id; uint32_t submodule_id; module_id = jx["module_id"].get(); submodule_id = jx["submodule_id"].get(); switch(module_id) { case ECHO_MODULE_ID: { switch(submodule_id) { case ECHO_SUBMOD_ID: { Echo_outCycData.data.data_f = jx.at("data").at("EchoModuleOutFloat").get(); Echo_outCycData.data.data_i = jx.at("data").at("EchoModuleOutInt").get(); if (value_i != Echo_outCycData.data.data_i) { value_i = Echo_outCycData.data.data_i; std::cout << "New data_i from PLC: " << value_i << std::endl; } if (value_f != Echo_outCycData.data.data_f) { value_f = Echo_outCycData.data.data_f; std::cout << "New data_f from PLC: " << value_f << std::endl; } ///Подготавливаем данные для ПЛК Echo_inpCycData.data.data_i = Echo_Gain * Echo_outCycData.data.data_i; Echo_inpCycData.data.data_f = Echo_Gain * Echo_outCycData.data.data_f; json j_set_data; j_set_data["module_id"] = module_id; j_set_data["submodule_id"] = submodule_id; j_set_data["data"]["EchoModuleInpFloat"] = Echo_inpCycData.data.data_f; j_set_data["data"]["EchoModuleInpInt"] = Echo_inpCycData.data.data_i; j_set_echo_data["params"].push_back(j_set_data); } break; default: { std::cout << "Error submodule id" << std::endl; continue; } break; } } break; case BIT_MODULE_ID: { switch(submodule_id) { case BIT_SUBMOD_ID: { static uint8_t value_bits[8]; uint8_t bits[8]; //std::cout << "Bits: " << jx.dump() << std::endl; bits[0] = jx.at("data").at("I808OutBits").at("out_bit_0").get(); bits[1] = jx.at("data").at("I808OutBits").at("out_bit_1").get(); bits[2] = jx.at("data").at("I808OutBits").at("out_bit_2").get(); bits[3] = jx.at("data").at("I808OutBits").at("out_bit_3").get(); bits[4] = jx.at("data").at("I808OutBits").at("out_bit_4").get(); bits[5] = jx.at("data").at("I808OutBits").at("out_bit_5").get(); bits[6] = jx.at("data").at("I808OutBits").at("out_bit_6").get(); bits[7] = jx.at("data").at("I808OutBits").at("out_bit_7").get(); bool newdata = false; for (int i = 0; i < 8; ++i) { if (bits[i]!= value_bits[i]) { newdata = true; } } if (newdata) { std::cout << "New bit data from PLC: " << std::endl; std::cout << "I808OutBits:" << std::endl; for (int i = 0; i < 8; ++i) { value_bits[i] = bits[i]; std::cout << "out_bit_" << i << ":" << std::to_string(bits[i]) << std::endl; } } json j_set_data; j_set_data["module_id"] = module_id; j_set_data["submodule_id"] = submodule_id; auto& data = j_set_data["data"]["I808InpBits"]; static bool init = true; if (init) { for (int i = 0; i < 8; ++i) { //bits[i] = (~bits[i]) & 0x01; std::string bit_name = "in_bit_" + std::to_string(i); data[bit_name] = value_bits[i]; } init = false; } else { data["in_bit_1"] = 1; } j_set_echo_data["params"].push_back(j_set_data); } break; default: { std::cout << "Error submodule id" << std::endl; continue; } break; } } break; default: { std::cout << "Error module id" << std::endl; continue; } break; } } ///Записываем данные *p_output_stream_ << j_set_echo_data.dump() << std::endl; //std::cout << "OUT: " << j_set_echo_data.dump() << std::endl; j_set_echo_data["params"].array().clear(); answer_str.clear(); ///Ждем ответ std::getline( *p_input_stream_.get( ), answer_str); } } return 0; }