2022-08-26 14:43:30 +03:00
|
|
|
|
#include "user_data.hpp"
|
|
|
|
|
|
#include <bit>
|
|
|
|
|
|
#include "../endian/endian.hpp"
|
2022-08-26 16:36:06 +03:00
|
|
|
|
#include <iostream>
|
2022-08-26 14:43:30 +03:00
|
|
|
|
|
|
|
|
|
|
using json = nlohmann::json;
|
|
|
|
|
|
|
|
|
|
|
|
const std::map<UserData::UserDataTypes, uint32_t> UserData::data_size{
|
|
|
|
|
|
{UserDataTypes::BOOL, 1},
|
|
|
|
|
|
{UserDataTypes::UINT8, 1},
|
|
|
|
|
|
{UserDataTypes::UINT16, 2},
|
|
|
|
|
|
{UserDataTypes::UINT32, 4},
|
|
|
|
|
|
{UserDataTypes::UINT64, 8},
|
|
|
|
|
|
{UserDataTypes::INT64, 8},
|
|
|
|
|
|
{UserDataTypes::INT32, 4},
|
|
|
|
|
|
{UserDataTypes::INT16, 2},
|
|
|
|
|
|
{UserDataTypes::INT8, 1},
|
|
|
|
|
|
{UserDataTypes::FLOAT32, 4},
|
|
|
|
|
|
{UserDataTypes::FLOAT64, 8}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
const std::map<std::string, UserData::UserDataTypes> UserData::data_corr {
|
|
|
|
|
|
{"Boolean", UserDataTypes::BOOL},
|
|
|
|
|
|
{"Unsigned8", UserDataTypes::UINT8},
|
|
|
|
|
|
{"Unsigned16", UserDataTypes::UINT16},
|
|
|
|
|
|
{"Unsigned32", UserDataTypes::UINT32},
|
|
|
|
|
|
{"Unsigned64", UserDataTypes::UINT64},
|
|
|
|
|
|
{"Integer64", UserDataTypes::INT64},
|
|
|
|
|
|
{"Integer32", UserDataTypes::INT32},
|
|
|
|
|
|
{"Integer16", UserDataTypes::INT16},
|
|
|
|
|
|
{"Integer8", UserDataTypes::INT8},
|
|
|
|
|
|
{"Float32", UserDataTypes::FLOAT32},
|
|
|
|
|
|
{"Float64", UserDataTypes::FLOAT64}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
bool UserData::putBit(std::string& bit_name, uint32_t bit_pos)
|
|
|
|
|
|
{
|
2022-08-26 16:36:06 +03:00
|
|
|
|
if (bits_.size() >= size * 8)
|
2022-08-26 14:43:30 +03:00
|
|
|
|
return false; /// Все биты уже заняты
|
|
|
|
|
|
|
|
|
|
|
|
bits_.push_back(UserDataBit{bit_name, bit_pos});
|
|
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2022-08-30 10:59:30 +03:00
|
|
|
|
bool UserData::toRpcJson(nlohmann::json& j) const
|
2022-08-26 14:43:30 +03:00
|
|
|
|
{
|
|
|
|
|
|
if (bits_.empty())
|
|
|
|
|
|
{
|
|
|
|
|
|
switch(type)
|
|
|
|
|
|
{
|
|
|
|
|
|
case UserDataTypes::UINT8:
|
|
|
|
|
|
{
|
|
|
|
|
|
j[name] = data_.uint8[0];
|
|
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
case UserDataTypes::UINT16:
|
|
|
|
|
|
{
|
|
|
|
|
|
j[name] = data_.uint16[0];
|
|
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
case UserDataTypes::UINT32:
|
|
|
|
|
|
{
|
|
|
|
|
|
j[name] = data_.uint32[0];
|
|
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
case UserDataTypes::UINT64:
|
|
|
|
|
|
{
|
|
|
|
|
|
j[name] = data_.uint64;
|
|
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
case UserDataTypes::INT8:
|
|
|
|
|
|
{
|
|
|
|
|
|
j[name] = data_.int8[0];
|
|
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
case UserDataTypes::INT16:
|
|
|
|
|
|
{
|
|
|
|
|
|
j[name] = data_.int16[0];
|
|
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
case UserDataTypes::INT32:
|
|
|
|
|
|
{
|
|
|
|
|
|
j[name] = data_.int32[0];
|
|
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
case UserDataTypes::INT64:
|
|
|
|
|
|
{
|
|
|
|
|
|
j[name] = data_.int64;
|
|
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
case UserDataTypes::FLOAT32:
|
|
|
|
|
|
{
|
|
|
|
|
|
j[name] = data_.float32;
|
|
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
case UserDataTypes::FLOAT64:
|
|
|
|
|
|
{
|
|
|
|
|
|
j[name] = data_.float64;
|
|
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
case UserDataTypes::BOOL:
|
|
|
|
|
|
{
|
|
|
|
|
|
j[name] = data_.boolean;
|
|
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
/// Только беззнаковые типы могут быть битовыми
|
|
|
|
|
|
if ((type < UserDataTypes::UINT8) || (type > UserDataTypes::UINT64))
|
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
|
|
json& j_bit = j[name];
|
2022-08-26 16:36:06 +03:00
|
|
|
|
for (auto& bit : bits_)
|
2022-08-26 14:43:30 +03:00
|
|
|
|
{
|
2022-08-26 16:36:06 +03:00
|
|
|
|
j_bit[bit.Name] = ( data_.uint64 & (1 << bit.Pos) ) ? (1) : (0);
|
2022-08-26 14:43:30 +03:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool UserData::fromRpcJson(const nlohmann::json& j)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!j.contains(name))
|
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
|
|
if (!bits_.size()) /// Данные
|
|
|
|
|
|
{
|
|
|
|
|
|
switch(type)
|
|
|
|
|
|
{
|
|
|
|
|
|
case UserDataTypes::UINT8:
|
|
|
|
|
|
{
|
|
|
|
|
|
data_.uint8[0] = j[name].get<uint8_t>();
|
|
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
case UserDataTypes::UINT16:
|
|
|
|
|
|
{
|
|
|
|
|
|
data_.uint16[0] = j[name].get<uint16_t>();
|
|
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
case UserDataTypes::UINT32:
|
|
|
|
|
|
{
|
|
|
|
|
|
data_.uint32[0] = j[name].get<uint32_t>();
|
|
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
case UserDataTypes::UINT64:
|
|
|
|
|
|
{
|
|
|
|
|
|
data_.uint64 = j[name].get<uint64_t>();
|
|
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
case UserDataTypes::INT8:
|
|
|
|
|
|
{
|
|
|
|
|
|
data_.int8[0] = j[name].get<int8_t>();
|
|
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
case UserDataTypes::INT16:
|
|
|
|
|
|
{
|
|
|
|
|
|
data_.int16[0] = j[name].get<int16_t>();
|
|
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
case UserDataTypes::INT32:
|
|
|
|
|
|
{
|
|
|
|
|
|
data_.int32[0] = j[name].get<int32_t>();
|
|
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
case UserDataTypes::INT64:
|
|
|
|
|
|
{
|
|
|
|
|
|
data_.int64 = j[name].get<int64_t>();
|
|
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
case UserDataTypes::FLOAT32:
|
|
|
|
|
|
{
|
|
|
|
|
|
data_.float32 = j[name].get<float>();
|
|
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
case UserDataTypes::FLOAT64:
|
|
|
|
|
|
{
|
|
|
|
|
|
data_.float64 = j[name].get<double>();
|
|
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
case UserDataTypes::BOOL:
|
|
|
|
|
|
{
|
|
|
|
|
|
data_.boolean = j[name].get<bool>();
|
|
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
else /// Биты
|
|
|
|
|
|
{
|
|
|
|
|
|
/// Только беззнаковые типы могут быть битовыми
|
|
|
|
|
|
if ((type < UserDataTypes::UINT8) || (type > UserDataTypes::UINT64))
|
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
|
|
const json& j_bit = j[name];
|
|
|
|
|
|
|
|
|
|
|
|
for (auto bit : bits_)
|
|
|
|
|
|
{
|
2022-08-30 10:59:30 +03:00
|
|
|
|
/// Проверяем есть ли в принятой датаграмме бит
|
2022-08-26 14:43:30 +03:00
|
|
|
|
if (!j_bit.contains(bit.Name))
|
2022-08-30 10:59:30 +03:00
|
|
|
|
continue;
|
|
|
|
|
|
|
2022-08-26 14:43:30 +03:00
|
|
|
|
uint8_t value = j_bit[bit.Name].get<uint8_t>();
|
2022-08-30 10:59:30 +03:00
|
|
|
|
|
|
|
|
|
|
if (value == 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
/// Очистка бита
|
|
|
|
|
|
data_.uint64&= ~(static_cast<uint64_t>(1) << bit.Pos);
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (value == 1)
|
|
|
|
|
|
{
|
|
|
|
|
|
/// Установка бита
|
|
|
|
|
|
data_.uint64 |= (static_cast<uint64_t>(1) << bit.Pos);
|
|
|
|
|
|
}
|
2022-08-26 14:43:30 +03:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool UserData::convertBinaryToJson(const std::vector<uint8_t>& vect_inp, nlohmann::json& j_out)
|
|
|
|
|
|
{
|
|
|
|
|
|
/// Вектор должен иметь подходящий размер
|
|
|
|
|
|
if (vect_inp.size() < (size + data_offset_))
|
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
|
|
/// Копируем бинарные данные из вектора с учетом офсета и эндиана
|
|
|
|
|
|
insertData(vect_inp);
|
|
|
|
|
|
/// Преобразовываем бинарные данные в json
|
|
|
|
|
|
toRpcJson(j_out);
|
|
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool UserData::convertJsonToBinary(const nlohmann::json& j_inp, std::vector<uint8_t>& vect_out)
|
|
|
|
|
|
{
|
|
|
|
|
|
/// Вектор должен иметь подходящий размер
|
|
|
|
|
|
if (vect_out.size() < (size + data_offset_))
|
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
|
|
/// Берем данные из json и преобразуем их в бинарный вид
|
|
|
|
|
|
fromRpcJson(j_inp);
|
|
|
|
|
|
/// Вставляем бинарные данные с учетом офсета в вектор
|
|
|
|
|
|
extractData(vect_out);
|
|
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void UserData::extractData(std::vector<uint8_t>& vect)
|
|
|
|
|
|
{
|
|
|
|
|
|
/// Копируем данные в vect
|
|
|
|
|
|
uint8_t buf[size];
|
|
|
|
|
|
std::copy(&data_.uint8[0], &data_.uint8[size], buf);
|
|
|
|
|
|
/// Данные в профинет передаются в формате BigEndian
|
|
|
|
|
|
/// преобразуем из Little в Big
|
2022-09-01 15:38:55 +03:00
|
|
|
|
if (swap_)
|
|
|
|
|
|
{
|
|
|
|
|
|
endian_swapbytes(&buf[0], size);
|
|
|
|
|
|
}
|
2022-08-26 14:43:30 +03:00
|
|
|
|
/// Вставляем данные в вектор по офсету
|
|
|
|
|
|
std::copy(buf, &buf[size], vect.begin() + data_offset_);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void UserData::insertData(const std::vector<uint8_t>& vect)
|
|
|
|
|
|
{
|
|
|
|
|
|
/// Копируем данные из вектора
|
|
|
|
|
|
std::copy(&vect[data_offset_], &vect[data_offset_ + size], data_.uint8);
|
|
|
|
|
|
/// Конвертим
|
|
|
|
|
|
if ((type >= UserDataTypes::UINT16) &&
|
2022-09-01 15:38:55 +03:00
|
|
|
|
(type <= UserDataTypes::FLOAT64) && swap_)
|
2022-08-26 14:43:30 +03:00
|
|
|
|
{
|
|
|
|
|
|
/// Данные в профинет передаются в формате BigEndian
|
|
|
|
|
|
/// преобразуем из Big в Little
|
|
|
|
|
|
endian_swapbytes(data_.uint8, size);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*void UserData::init(std::string& Name, std::string& DataType, uint16_t offset)
|
|
|
|
|
|
{
|
|
|
|
|
|
name = Name;
|
|
|
|
|
|
type = data_corr.at(DataType);
|
|
|
|
|
|
size = data_size.at(type);
|
|
|
|
|
|
data_offset_ = offset;
|
|
|
|
|
|
};*/
|
|
|
|
|
|
|
|
|
|
|
|
SubmoduleUserData& UserData_addNewSubmod(uint32_t mod_id, uint32_t submod_id, UserDataMap& user_data_map)
|
|
|
|
|
|
{
|
|
|
|
|
|
uint64_t key = (static_cast<uint64_t>(mod_id) << 32) + submod_id;
|
|
|
|
|
|
return user_data_map[key];
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
SubmoduleUserData& UserData_getSubmod(uint32_t mod_id, uint32_t submod_id, UserDataMap& user_data_map)
|
|
|
|
|
|
{
|
|
|
|
|
|
uint64_t key = (static_cast<uint64_t>(mod_id) << 32) + submod_id;
|
|
|
|
|
|
return user_data_map.at(key);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int UserData::getDataSize(const std::string& type_name)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!data_corr.contains(type_name))
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
|
|
return data_size.at(data_corr.at(type_name));
|
|
|
|
|
|
}
|