ProfinetConnector/src/user_data/user_data.cpp

307 lines
8.8 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "user_data.hpp"
#include <bit>
#include "../endian/endian.hpp"
#include <iostream>
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 * 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<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_)
{
/// Проверяем есть ли в принятой датаграмме бит
if (!j_bit.contains(bit.Name))
continue;
uint8_t value = j_bit[bit.Name].get<uint8_t>();
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);
}
}
}
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
if (swap_)
{
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) && 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<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));
}