#include "user_data.hpp" #include #include "../endian/endian.hpp" #include using json = nlohmann::json; const std::map 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 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 * 8) return false; /// Все биты уже заняты bits_.push_back(UserDataBit{bit_name, bit_pos}); return true; } bool UserData::toRpcJson(nlohmann::json& j) const { 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] = ( data_.uint64 & (1 << bit.Pos) ) ? (1) : (0); } } 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(); } break; case UserDataTypes::UINT16: { data_.uint16[0] = j[name].get(); } break; case UserDataTypes::UINT32: { data_.uint32[0] = j[name].get(); } break; case UserDataTypes::UINT64: { data_.uint64 = j[name].get(); } break; case UserDataTypes::INT8: { data_.int8[0] = j[name].get(); } break; case UserDataTypes::INT16: { data_.int16[0] = j[name].get(); } break; case UserDataTypes::INT32: { data_.int32[0] = j[name].get(); } break; case UserDataTypes::INT64: { data_.int64 = j[name].get(); } break; case UserDataTypes::FLOAT32: { data_.float32 = j[name].get(); } break; case UserDataTypes::FLOAT64: { data_.float64 = j[name].get(); } break; case UserDataTypes::BOOL: { data_.boolean = j[name].get(); } break; } } else /// Биты { /// Только беззнаковые типы могут быть битовыми if ((type < UserDataTypes::UINT8) || (type > UserDataTypes::UINT64)) return false; const json& j_bit = j[name]; for (auto bit : bits_) { /// Проверяем есть ли в принятой датаграмме бит if (!j_bit.contains(bit.Name)) continue; uint8_t value = j_bit[bit.Name].get(); if (value == 0) { /// Очистка бита data_.uint64&= ~(static_cast(1) << bit.Pos); } else if (value == 1) { /// Установка бита data_.uint64 |= (static_cast(1) << bit.Pos); } } } return true; } bool UserData::convertBinaryToJson(const std::vector& 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& 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& vect) { /// Копируем данные в vect uint8_t buf[size]; std::copy(&data_.uint8[0], &data_.uint8[size], buf); /// Данные в профинет передаются в формате BigEndian /// преобразуем из Little в Big if (swap_) { endian_swapbytes(&buf[0], size); } /// Вставляем данные в вектор по офсету std::copy(buf, &buf[size], vect.begin() + data_offset_); } void UserData::insertData(const std::vector& vect) { /// Копируем данные из вектора std::copy(&vect[data_offset_], &vect[data_offset_ + size], data_.uint8); /// Конвертим if ((type >= UserDataTypes::UINT16) && (type <= UserDataTypes::FLOAT64) && swap_) { /// Данные в профинет передаются в формате 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(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(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)); }