293 lines
8.4 KiB
C++
293 lines
8.4 KiB
C++
|
|
#include "user_data.hpp"
|
|||
|
|
#include <bit>
|
|||
|
|
#include "../endian/endian.hpp"
|
|||
|
|
|
|||
|
|
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)
|
|||
|
|
{
|
|||
|
|
if (bits_.size() >= size)
|
|||
|
|
return false; /// Все биты уже заняты
|
|||
|
|
|
|||
|
|
bits_.push_back(UserDataBit{bit_name, bit_pos});
|
|||
|
|
|
|||
|
|
return true;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
bool UserData::toRpcJson(nlohmann::json& j)
|
|||
|
|
{
|
|||
|
|
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];
|
|||
|
|
for (auto bit : bits_)
|
|||
|
|
{
|
|||
|
|
j_bit[bit.Name] = static_cast<bool>(data_.uint64 & (1 << bit.Pos));
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
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];
|
|||
|
|
|
|||
|
|
data_.uint64 = 0;
|
|||
|
|
|
|||
|
|
for (auto bit : bits_)
|
|||
|
|
{
|
|||
|
|
if (!j_bit.contains(bit.Name))
|
|||
|
|
return false;
|
|||
|
|
uint8_t value = j_bit[bit.Name].get<uint8_t>();
|
|||
|
|
data_.uint64 |= static_cast<uint64_t>(value) << bit.Pos;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
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
|
|||
|
|
endian_swapbytes(&buf[0], size);
|
|||
|
|
/// Вставляем данные в вектор по офсету
|
|||
|
|
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) &&
|
|||
|
|
(type <= UserDataTypes::FLOAT64))
|
|||
|
|
{
|
|||
|
|
/// Данные в профинет передаются в формате 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));
|
|||
|
|
}
|