459 lines
17 KiB
C++
459 lines
17 KiB
C++
#include "CreatePipes.h"
|
|
#include <memory>
|
|
#include <iostream>
|
|
#include "json.hpp"
|
|
#include <chrono>
|
|
#include <thread>
|
|
#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<uint8_t>& in_vect, uint8_t * pParam, uint16_t param_size)
|
|
{
|
|
in_vect.clear();
|
|
in_vect = jx["data"]["bytes"].get<std::vector<uint8_t>>();
|
|
|
|
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<uint8_t> 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::string>()}; /// Выходной канал профинет, входной канал апп
|
|
std::filesystem::path _output_path{j_cfg["app_settings"]["app_out_pipe_name"].get<std::string>()}; /// Входной канал профинет, входной канал апп
|
|
|
|
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<bool>() == true)
|
|
{
|
|
std::cout << "EVENT_CONNECTION_ESTABLISHED: true" << std::endl;
|
|
}
|
|
|
|
if (j_res["EVENT_CONNECTION_ABORT"].get<bool>() == true)
|
|
{
|
|
std::cout << "EVENT_CONNECTION_ABORT: true" << std::endl;
|
|
}
|
|
|
|
|
|
if (j_res["EVENT_NEW_PARAM_DATA"].get<bool>() == 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<uint8_t> 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<int>();
|
|
submodule_id = jx["submodule_id"].get<int>();
|
|
param_idx = jx["param_index"].get<int>();
|
|
|
|
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<uint32_t>();
|
|
|
|
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<uint32_t>();
|
|
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<uint32_t>();
|
|
|
|
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<bool>() == 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<uint8_t> in;
|
|
|
|
for (auto& jx : j_answ_data["result"])
|
|
{
|
|
uint32_t module_id;
|
|
uint32_t submodule_id;
|
|
|
|
module_id = jx["module_id"].get<int>();
|
|
submodule_id = jx["submodule_id"].get<int>();
|
|
|
|
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<float>();
|
|
Echo_outCycData.data.data_i = jx.at("data").at("EchoModuleOutInt").get<uint32_t>();
|
|
|
|
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<uint8_t>();
|
|
bits[1] = jx.at("data").at("I808OutBits").at("out_bit_1").get<uint8_t>();
|
|
bits[2] = jx.at("data").at("I808OutBits").at("out_bit_2").get<uint8_t>();
|
|
bits[3] = jx.at("data").at("I808OutBits").at("out_bit_3").get<uint8_t>();
|
|
bits[4] = jx.at("data").at("I808OutBits").at("out_bit_4").get<uint8_t>();
|
|
bits[5] = jx.at("data").at("I808OutBits").at("out_bit_5").get<uint8_t>();
|
|
bits[6] = jx.at("data").at("I808OutBits").at("out_bit_6").get<uint8_t>();
|
|
bits[7] = jx.at("data").at("I808OutBits").at("out_bit_7").get<uint8_t>();
|
|
|
|
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;
|
|
} |