mirror of
https://github.com/wpilibsuite/allwpilib
synced 2026-07-05 03:21:42 +00:00
Update for jart/json.cpp change
This commit is contained in:
@@ -177,8 +177,8 @@ void HALSimWS::OnNetValueChanged(const wpi::util::json& msg) {
|
||||
// generate the key
|
||||
|
||||
try {
|
||||
auto& type = msg.at("type").get_ref<const std::string&>();
|
||||
auto& device = msg.at("device").get_ref<const std::string&>();
|
||||
auto& type = msg.at("type").get_string();
|
||||
auto& device = msg.at("device").get_string();
|
||||
|
||||
wpi::util::SmallString<64> key;
|
||||
key.append(type);
|
||||
@@ -191,7 +191,7 @@ void HALSimWS::OnNetValueChanged(const wpi::util::json& msg) {
|
||||
if (provider) {
|
||||
provider->OnNetValueChanged(msg.at("data"));
|
||||
}
|
||||
} catch (wpi::util::json::exception& e) {
|
||||
} catch (std::logic_error& e) {
|
||||
wpi::util::print(stderr, "Error with incoming message: {}\n", e.what());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,18 +48,15 @@ void HALSimWSClientConnection::Initialize() {
|
||||
return;
|
||||
}
|
||||
|
||||
wpi::util::json j;
|
||||
try {
|
||||
j = wpi::util::json::parse(msg);
|
||||
} catch (const wpi::util::json::parse_error& e) {
|
||||
std::string err("JSON parse failed: ");
|
||||
err += e.what();
|
||||
auto j = wpi::util::json::parse(msg);
|
||||
if (!j) {
|
||||
auto err = fmt::format("JSON parse failed: {}", j.error());
|
||||
wpi::util::print(stderr, "{}\n", err);
|
||||
m_websocket->Fail(1003, err);
|
||||
return;
|
||||
}
|
||||
|
||||
m_client->OnNetValueChanged(j);
|
||||
m_client->OnNetValueChanged(*j);
|
||||
});
|
||||
|
||||
m_websocket->closed.connect([this](uint16_t, auto) {
|
||||
@@ -79,11 +76,11 @@ void HALSimWSClientConnection::OnSimValueChanged(const wpi::util::json& msg) {
|
||||
|
||||
// Skip sending if this message is not in the allowed filter list
|
||||
try {
|
||||
auto& type = msg.at("type").get_ref<const std::string&>();
|
||||
auto& type = msg.at("type").get_string();
|
||||
if (!m_client->CanSendMessage(type)) {
|
||||
return;
|
||||
}
|
||||
} catch (wpi::util::json::exception& e) {
|
||||
} catch (std::logic_error& e) {
|
||||
wpi::util::print(stderr, "Error with message: {}\n", e.what());
|
||||
}
|
||||
|
||||
|
||||
@@ -16,7 +16,10 @@
|
||||
#include "wpi/net/uv/Tcp.hpp"
|
||||
#include "wpi/net/uv/Timer.hpp"
|
||||
#include "wpi/util/StringMap.hpp"
|
||||
#include "wpi/util/json_fwd.hpp"
|
||||
|
||||
namespace wpi::util {
|
||||
class json;
|
||||
} // namespace wpi::util
|
||||
|
||||
namespace wpilibws {
|
||||
|
||||
|
||||
@@ -12,8 +12,10 @@
|
||||
#include "wpi/net/WebSocket.hpp"
|
||||
#include "wpi/net/uv/Buffer.hpp"
|
||||
#include "wpi/net/uv/Stream.hpp"
|
||||
#include "wpi/util/json_fwd.hpp"
|
||||
#include "wpi/util/mutex.hpp"
|
||||
|
||||
namespace wpi::util {
|
||||
class json;
|
||||
} // namespace wpi::util
|
||||
|
||||
namespace wpilibws {
|
||||
|
||||
|
||||
@@ -27,8 +27,10 @@ void HALSimWSHalProvider::OnNetworkDisconnected() {
|
||||
void HALSimWSHalProvider::ProcessHalCallback(const wpi::util::json& payload) {
|
||||
auto ws = m_ws.lock();
|
||||
if (ws) {
|
||||
wpi::util::json netValue = {
|
||||
{"type", m_type}, {"device", m_deviceId}, {"data", payload}};
|
||||
auto netValue = wpi::util::json::object();
|
||||
netValue["type"] = m_type;
|
||||
netValue["device"] = m_deviceId;
|
||||
netValue["data"] = payload;
|
||||
ws->OnSimValueChanged(netValue);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,19 +4,20 @@
|
||||
|
||||
#include "wpi/halsim/ws_core/WSProvider_AddressableLED.hpp"
|
||||
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "wpi/hal/Ports.h"
|
||||
#include "wpi/hal/simulation/AddressableLEDData.h"
|
||||
|
||||
#define REGISTER(halsim, jsonid, ctype, haltype) \
|
||||
HALSIM_RegisterAddressableLED##halsim##Callback( \
|
||||
m_channel, \
|
||||
[](const char* name, void* param, const struct HAL_Value* value) { \
|
||||
static_cast<HALSimWSProviderAddressableLED*>(param) \
|
||||
->ProcessHalCallback( \
|
||||
{{jsonid, static_cast<ctype>(value->data.v_##haltype)}}); \
|
||||
}, \
|
||||
#define REGISTER(halsim, jsonid, ctype, haltype) \
|
||||
HALSIM_RegisterAddressableLED##halsim##Callback( \
|
||||
m_channel, \
|
||||
[](const char* name, void* param, const struct HAL_Value* value) { \
|
||||
static_cast<HALSimWSProviderAddressableLED*>(param) \
|
||||
->ProcessHalCallback(wpi::util::json::object( \
|
||||
jsonid, static_cast<ctype>(value->data.v_##haltype))); \
|
||||
}, \
|
||||
this, true)
|
||||
namespace wpilibws {
|
||||
void HALSimWSProviderAddressableLED::Initialize(
|
||||
@@ -43,15 +44,17 @@ void HALSimWSProviderAddressableLED::RegisterCallbacks() {
|
||||
const HAL_AddressableLEDData* data =
|
||||
reinterpret_cast<const HAL_AddressableLEDData*>(buffer);
|
||||
|
||||
std::vector<wpi::util::json> jsonData;
|
||||
auto jsonData = wpi::util::json::array();
|
||||
|
||||
for (size_t i = 0; i < numLeds; ++i) {
|
||||
jsonData.push_back(
|
||||
{{"r", data[i].r}, {"g", data[i].g}, {"b", data[i].b}});
|
||||
jsonData.emplace_back(
|
||||
wpi::util::json::object("r", static_cast<int64_t>(data[i].r), "g",
|
||||
static_cast<int64_t>(data[i].g), "b",
|
||||
static_cast<int64_t>(data[i].b)));
|
||||
}
|
||||
|
||||
wpi::util::json payload;
|
||||
payload["<data"] = jsonData;
|
||||
payload["<data"] = std::move(jsonData);
|
||||
|
||||
provider->ProcessHalCallback(payload);
|
||||
},
|
||||
|
||||
@@ -12,7 +12,8 @@
|
||||
m_channel, \
|
||||
[](const char* name, void* param, const struct HAL_Value* value) { \
|
||||
static_cast<HALSimWSProviderAnalogIn*>(param)->ProcessHalCallback( \
|
||||
{{jsonid, static_cast<ctype>(value->data.v_##haltype)}}); \
|
||||
wpi::util::json::object( \
|
||||
jsonid, static_cast<ctype>(value->data.v_##haltype))); \
|
||||
}, \
|
||||
this, true)
|
||||
|
||||
@@ -54,9 +55,8 @@ void HALSimWSProviderAnalogIn::DoCancelCallbacks() {
|
||||
}
|
||||
|
||||
void HALSimWSProviderAnalogIn::OnNetValueChanged(const wpi::util::json& json) {
|
||||
wpi::util::json::const_iterator it;
|
||||
if ((it = json.find(">voltage")) != json.end()) {
|
||||
HALSIM_SetAnalogInVoltage(m_channel, it.value());
|
||||
if (auto val = json.lookup(">voltage"); val && val->is_number()) {
|
||||
HALSIM_SetAnalogInVoltage(m_channel, val->get_number());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -12,7 +12,8 @@
|
||||
m_channel, \
|
||||
[](const char* name, void* param, const struct HAL_Value* value) { \
|
||||
static_cast<HALSimWSProviderDIO*>(param)->ProcessHalCallback( \
|
||||
{{jsonid, static_cast<ctype>(value->data.v_##haltype)}}); \
|
||||
wpi::util::json::object( \
|
||||
jsonid, static_cast<ctype>(value->data.v_##haltype))); \
|
||||
}, \
|
||||
this, true)
|
||||
|
||||
@@ -51,9 +52,8 @@ void HALSimWSProviderDIO::DoCancelCallbacks() {
|
||||
}
|
||||
|
||||
void HALSimWSProviderDIO::OnNetValueChanged(const wpi::util::json& json) {
|
||||
wpi::util::json::const_iterator it;
|
||||
if ((it = json.find("<>value")) != json.end()) {
|
||||
HALSIM_SetDIOValue(m_channel, static_cast<bool>(it.value()));
|
||||
if (auto val = json.lookup("<>value"); val && val->is_bool()) {
|
||||
HALSIM_SetDIOValue(m_channel, val->get_bool());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -12,13 +12,13 @@
|
||||
#include "wpi/hal/simulation/DriverStationData.h"
|
||||
#include "wpi/util/string.hpp"
|
||||
|
||||
#define REGISTER(halsim, jsonid, ctype, haltype) \
|
||||
HALSIM_RegisterDriverStation##halsim##Callback( \
|
||||
[](const char* name, void* param, const struct HAL_Value* value) { \
|
||||
static_cast<HALSimWSProviderDriverStation*>(param) \
|
||||
->ProcessHalCallback( \
|
||||
{{jsonid, static_cast<ctype>(value->data.v_##haltype)}}); \
|
||||
}, \
|
||||
#define REGISTER(halsim, jsonid, ctype, haltype) \
|
||||
HALSIM_RegisterDriverStation##halsim##Callback( \
|
||||
[](const char* name, void* param, const struct HAL_Value* value) { \
|
||||
static_cast<HALSimWSProviderDriverStation*>(param) \
|
||||
->ProcessHalCallback(wpi::util::json::object( \
|
||||
jsonid, static_cast<ctype>(value->data.v_##haltype))); \
|
||||
}, \
|
||||
this, true)
|
||||
|
||||
namespace wpilibws {
|
||||
@@ -55,7 +55,7 @@ void HALSimWSProviderDriverStation::RegisterCallbacks() {
|
||||
m_newDataCbKey = HALSIM_RegisterDriverStationNewDataCallback(
|
||||
[](const char* name, void* param, const struct HAL_Value* value) {
|
||||
static_cast<HALSimWSProviderDriverStation*>(param)->ProcessHalCallback(
|
||||
{{">new_data", true}});
|
||||
wpi::util::json::object(">new_data", true));
|
||||
},
|
||||
this, true);
|
||||
|
||||
@@ -86,7 +86,7 @@ void HALSimWSProviderDriverStation::RegisterCallbacks() {
|
||||
break;
|
||||
}
|
||||
static_cast<HALSimWSProviderDriverStation*>(param)->ProcessHalCallback(
|
||||
{{">station", station}});
|
||||
wpi::util::json::object(">station", station));
|
||||
},
|
||||
this, true);
|
||||
|
||||
@@ -124,25 +124,25 @@ void HALSimWSProviderDriverStation::OnNetValueChanged(
|
||||
return;
|
||||
}
|
||||
|
||||
wpi::util::json::const_iterator it;
|
||||
if ((it = json.find(">enabled")) != json.end()) {
|
||||
HALSIM_SetDriverStationEnabled(it.value());
|
||||
if (auto val = json.lookup(">enabled"); val && val->is_bool()) {
|
||||
HALSIM_SetDriverStationEnabled(val->get_bool());
|
||||
}
|
||||
if ((it = json.find(">robotMode")) != json.end()) {
|
||||
HALSIM_SetDriverStationRobotMode(it.value());
|
||||
if (auto val = json.lookup(">robotMode"); val && val->is_int()) {
|
||||
HALSIM_SetDriverStationRobotMode(
|
||||
static_cast<HAL_RobotMode>(val->get_int()));
|
||||
}
|
||||
if ((it = json.find(">estop")) != json.end()) {
|
||||
HALSIM_SetDriverStationEStop(it.value());
|
||||
if (auto val = json.lookup(">estop"); val && val->is_bool()) {
|
||||
HALSIM_SetDriverStationEStop(val->get_bool());
|
||||
}
|
||||
if ((it = json.find(">fms")) != json.end()) {
|
||||
HALSIM_SetDriverStationFmsAttached(it.value());
|
||||
if (auto val = json.lookup(">fms"); val && val->is_bool()) {
|
||||
HALSIM_SetDriverStationFmsAttached(val->get_bool());
|
||||
}
|
||||
if ((it = json.find(">ds")) != json.end()) {
|
||||
HALSIM_SetDriverStationDsAttached(it.value());
|
||||
if (auto val = json.lookup(">ds"); val && val->is_bool()) {
|
||||
HALSIM_SetDriverStationDsAttached(val->get_bool());
|
||||
}
|
||||
|
||||
if ((it = json.find(">station")) != json.end()) {
|
||||
auto& station = it.value().get_ref<const std::string&>();
|
||||
if (auto val = json.lookup(">station"); val && val->is_string()) {
|
||||
auto& station = val->get_string();
|
||||
if (station == "red1") {
|
||||
HALSIM_SetDriverStationAllianceStationId(HAL_ALLIANCE_STATION_RED_1);
|
||||
} else if (station == "red2") {
|
||||
@@ -158,17 +158,17 @@ void HALSimWSProviderDriverStation::OnNetValueChanged(
|
||||
}
|
||||
}
|
||||
|
||||
if ((it = json.find(">match_time")) != json.end()) {
|
||||
HALSIM_SetDriverStationMatchTime(it.value());
|
||||
if (auto val = json.lookup(">match_time"); val && val->is_number()) {
|
||||
HALSIM_SetDriverStationMatchTime(val->get_number());
|
||||
}
|
||||
if ((it = json.find(">game_data")) != json.end()) {
|
||||
std::string message = it.value().get_ref<const std::string&>();
|
||||
if (auto val = json.lookup(">game_data"); val && val->is_string()) {
|
||||
std::string message = val->get_string();
|
||||
auto str = wpi::util::make_string(message);
|
||||
HALSIM_SetGameDataString(&str);
|
||||
}
|
||||
|
||||
// Only notify usercode if we get the new data message
|
||||
if ((it = json.find(">new_data")) != json.end()) {
|
||||
if (json.contains(">new_data")) {
|
||||
HALSIM_NotifyDriverStationNewData();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,8 @@
|
||||
m_channel, \
|
||||
[](const char* name, void* param, const struct HAL_Value* value) { \
|
||||
static_cast<HALSimWSProviderEncoder*>(param)->ProcessHalCallback( \
|
||||
{{jsonid, static_cast<ctype>(value->data.v_##haltype)}}); \
|
||||
wpi::util::json::object( \
|
||||
jsonid, static_cast<ctype>(value->data.v_##haltype))); \
|
||||
}, \
|
||||
this, true)
|
||||
|
||||
@@ -36,7 +37,7 @@ void HALSimWSProviderEncoder::RegisterCallbacks() {
|
||||
auto provider = static_cast<HALSimWSProviderEncoder*>(param);
|
||||
bool init = static_cast<bool>(value->data.v_boolean);
|
||||
|
||||
wpi::util::json payload = {{"<init", init}};
|
||||
auto payload = wpi::util::json::object("<init", init);
|
||||
|
||||
if (init) {
|
||||
payload["<channel_a"] =
|
||||
@@ -52,9 +53,9 @@ void HALSimWSProviderEncoder::RegisterCallbacks() {
|
||||
m_channel,
|
||||
[](const char* name, void* param, const struct HAL_Value* value) {
|
||||
auto provider = static_cast<HALSimWSProviderEncoder*>(param);
|
||||
provider->ProcessHalCallback(
|
||||
{{">count", static_cast<int32_t>(value->data.v_int +
|
||||
provider->m_countOffset)}});
|
||||
provider->ProcessHalCallback(wpi::util::json::object(
|
||||
">count",
|
||||
static_cast<int32_t>(value->data.v_int + provider->m_countOffset)));
|
||||
},
|
||||
this, true);
|
||||
m_periodCbKey = REGISTER(Period, ">period", double, double);
|
||||
@@ -96,13 +97,12 @@ void HALSimWSProviderEncoder::DoCancelCallbacks() {
|
||||
}
|
||||
|
||||
void HALSimWSProviderEncoder::OnNetValueChanged(const wpi::util::json& json) {
|
||||
wpi::util::json::const_iterator it;
|
||||
if ((it = json.find(">count")) != json.end()) {
|
||||
HALSIM_SetEncoderCount(m_channel,
|
||||
static_cast<int32_t>(it.value()) - m_countOffset);
|
||||
if (auto val = json.lookup(">count"); val && val->is_int()) {
|
||||
HALSIM_SetEncoderCount(m_channel, val->get_int() - m_countOffset);
|
||||
}
|
||||
if ((it = json.find(">period")) != json.end()) {
|
||||
HALSIM_SetEncoderPeriod(m_channel, it.value());
|
||||
|
||||
if (auto val = json.lookup(">period"); val && val->is_number()) {
|
||||
HALSIM_SetEncoderPeriod(m_channel, val->get_number());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -27,14 +27,14 @@ void HALSimWSProviderHAL::RegisterCallbacks() {
|
||||
m_simPeriodicBeforeCbKey = HALSIM_RegisterSimPeriodicBeforeCallback(
|
||||
[](void* param) {
|
||||
static_cast<HALSimWSProviderHAL*>(param)->ProcessHalCallback(
|
||||
{{">sim_periodic_before", true}});
|
||||
wpi::util::json::object(">sim_periodic_before", true));
|
||||
},
|
||||
this);
|
||||
|
||||
m_simPeriodicAfterCbKey = HALSIM_RegisterSimPeriodicAfterCallback(
|
||||
[](void* param) {
|
||||
static_cast<HALSimWSProviderHAL*>(param)->ProcessHalCallback(
|
||||
{{">sim_periodic_after", true}});
|
||||
wpi::util::json::object(">sim_periodic_after", true));
|
||||
},
|
||||
this);
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include <atomic>
|
||||
#include <vector>
|
||||
|
||||
#include "wpi/hal/DriverStationTypes.h"
|
||||
#include "wpi/hal/Ports.h"
|
||||
#include "wpi/hal/simulation/DriverStationData.h"
|
||||
|
||||
@@ -103,31 +104,34 @@ void HALSimWSProviderJoystick::OnNetValueChanged(const wpi::util::json& json) {
|
||||
return;
|
||||
}
|
||||
|
||||
wpi::util::json::const_iterator it;
|
||||
if ((it = json.find(">axes")) != json.end()) {
|
||||
if (auto val = json.lookup(">axes"); val && val->is_array()) {
|
||||
auto& arr = val->get_array();
|
||||
HAL_JoystickAxes axes{};
|
||||
wpi::util::json::size_type axesCount = std::min(
|
||||
it.value().size(),
|
||||
static_cast<wpi::util::json::size_type>(HAL_MAX_JOYSTICK_AXES));
|
||||
size_t axesCount =
|
||||
std::min(arr.size(), static_cast<size_t>(HAL_MAX_JOYSTICK_AXES));
|
||||
axes.available = (1 << axesCount) - 1;
|
||||
for (wpi::util::json::size_type i = 0; i < axesCount; i++) {
|
||||
axes.axes[i] = it.value()[i];
|
||||
for (size_t i = 0; i < axesCount; i++) {
|
||||
if (arr[i].is_number()) {
|
||||
axes.axes[i] = arr[i].get_number();
|
||||
} else {
|
||||
axes.axes[i] = 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
HALSIM_SetJoystickAxes(m_channel, &axes);
|
||||
}
|
||||
|
||||
if ((it = json.find(">buttons")) != json.end()) {
|
||||
if (auto val = json.lookup(">buttons"); val && val->is_array()) {
|
||||
HAL_JoystickButtons buttons{};
|
||||
wpi::util::json::size_type buttonsCount = std::min(
|
||||
it.value().size(), static_cast<wpi::util::json::size_type>(64));
|
||||
auto& arr = val->get_array();
|
||||
size_t buttonsCount = std::min(arr.size(), static_cast<size_t>(64));
|
||||
if (buttonsCount < 64) {
|
||||
buttons.available = (1ULL << buttonsCount) - 1;
|
||||
} else {
|
||||
buttons.available = (std::numeric_limits<uint64_t>::max)();
|
||||
}
|
||||
for (wpi::util::json::size_type i = 0; i < buttonsCount; i++) {
|
||||
if (it.value()[i]) {
|
||||
for (size_t i = 0; i < buttonsCount; i++) {
|
||||
if (arr[i].is_bool() && arr[i].get_bool()) {
|
||||
buttons.buttons |= 1llu << i;
|
||||
}
|
||||
}
|
||||
@@ -135,14 +139,18 @@ void HALSimWSProviderJoystick::OnNetValueChanged(const wpi::util::json& json) {
|
||||
HALSIM_SetJoystickButtons(m_channel, &buttons);
|
||||
}
|
||||
|
||||
if ((it = json.find(">povs")) != json.end()) {
|
||||
if (auto val = json.lookup(">povs"); val && val->is_array()) {
|
||||
HAL_JoystickPOVs povs{};
|
||||
wpi::util::json::size_type povsCount = std::min(
|
||||
it.value().size(),
|
||||
static_cast<wpi::util::json::size_type>(HAL_MAX_JOYSTICK_POVS));
|
||||
auto& arr = val->get_array();
|
||||
size_t povsCount =
|
||||
std::min(arr.size(), static_cast<size_t>(HAL_MAX_JOYSTICK_POVS));
|
||||
povs.available = (1 << povsCount) - 1;
|
||||
for (wpi::util::json::size_type i = 0; i < povsCount; i++) {
|
||||
povs.povs[i] = it.value()[i];
|
||||
for (size_t i = 0; i < povsCount; i++) {
|
||||
if (arr[i].is_int()) {
|
||||
povs.povs[i] = static_cast<HAL_JoystickPOV>(arr[i].get_int());
|
||||
} else {
|
||||
povs.povs[i] = HAL_JOYSTICK_POV_CENTERED;
|
||||
}
|
||||
}
|
||||
|
||||
HALSIM_SetJoystickPOVs(m_channel, &povs);
|
||||
|
||||
@@ -12,7 +12,8 @@
|
||||
m_channel, \
|
||||
[](const char* name, void* param, const struct HAL_Value* value) { \
|
||||
static_cast<HALSimWSProviderPCM*>(param)->ProcessHalCallback( \
|
||||
{{jsonid, static_cast<ctype>(value->data.v_##haltype)}}); \
|
||||
wpi::util::json::object( \
|
||||
jsonid, static_cast<ctype>(value->data.v_##haltype))); \
|
||||
}, \
|
||||
this, true)
|
||||
namespace wpilibws {
|
||||
|
||||
@@ -12,7 +12,8 @@
|
||||
m_channel, \
|
||||
[](const char* name, void* param, const struct HAL_Value* value) { \
|
||||
static_cast<HALSimWSProviderPWM*>(param)->ProcessHalCallback( \
|
||||
{{jsonid, static_cast<ctype>(value->data.v_##haltype)}}); \
|
||||
wpi::util::json::object( \
|
||||
jsonid, static_cast<ctype>(value->data.v_##haltype))); \
|
||||
}, \
|
||||
this, true)
|
||||
namespace wpilibws {
|
||||
|
||||
@@ -11,7 +11,8 @@
|
||||
HALSIM_RegisterRoboRio##halsim##Callback( \
|
||||
[](const char* name, void* param, const struct HAL_Value* value) { \
|
||||
static_cast<HALSimWSProviderRoboRIO*>(param)->ProcessHalCallback( \
|
||||
{{jsonid, static_cast<ctype>(value->data.v_##haltype)}}); \
|
||||
wpi::util::json::object( \
|
||||
jsonid, static_cast<ctype>(value->data.v_##haltype))); \
|
||||
}, \
|
||||
this, true)
|
||||
|
||||
@@ -54,22 +55,20 @@ void HALSimWSProviderRoboRIO::DoCancelCallbacks() {
|
||||
}
|
||||
|
||||
void HALSimWSProviderRoboRIO::OnNetValueChanged(const wpi::util::json& json) {
|
||||
wpi::util::json::const_iterator it;
|
||||
if ((it = json.find(">vin_voltage")) != json.end()) {
|
||||
HALSIM_SetRoboRioVInVoltage(it.value());
|
||||
if (auto val = json.lookup(">vin_voltage"); val && val->is_number()) {
|
||||
HALSIM_SetRoboRioVInVoltage(val->get_number());
|
||||
}
|
||||
|
||||
if ((it = json.find(">3v3_voltage")) != json.end()) {
|
||||
HALSIM_SetRoboRioUserVoltage3V3(it.value());
|
||||
if (auto val = json.lookup(">3v3_voltage"); val && val->is_number()) {
|
||||
HALSIM_SetRoboRioUserVoltage3V3(val->get_number());
|
||||
}
|
||||
if ((it = json.find(">3v3_current")) != json.end()) {
|
||||
HALSIM_SetRoboRioUserCurrent3V3(it.value());
|
||||
if (auto val = json.lookup(">3v3_current"); val && val->is_number()) {
|
||||
HALSIM_SetRoboRioUserCurrent3V3(val->get_number());
|
||||
}
|
||||
if ((it = json.find(">3v3_active")) != json.end()) {
|
||||
HALSIM_SetRoboRioUserActive3V3(static_cast<bool>(it.value()));
|
||||
if (auto val = json.lookup(">3v3_active"); val && val->is_bool()) {
|
||||
HALSIM_SetRoboRioUserActive3V3(val->get_bool());
|
||||
}
|
||||
if ((it = json.find(">3v3_faults")) != json.end()) {
|
||||
HALSIM_SetRoboRioUserFaults3V3(it.value());
|
||||
if (auto val = json.lookup(">3v3_faults"); val && val->is_number()) {
|
||||
HALSIM_SetRoboRioUserFaults3V3(val->get_number());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -62,53 +62,59 @@ void HALSimWSProviderSimDevice::CancelCallbacks() {
|
||||
}
|
||||
|
||||
void HALSimWSProviderSimDevice::OnNetValueChanged(const wpi::util::json& json) {
|
||||
auto it = json.cbegin();
|
||||
auto end = json.cend();
|
||||
|
||||
std::shared_lock lock(m_vhLock);
|
||||
for (; it != end; ++it) {
|
||||
auto vd = m_valueHandles.find(it.key());
|
||||
for (auto&& [key, jvalue] : json.get_object()) {
|
||||
auto vd = m_valueHandles.find(key);
|
||||
if (vd != m_valueHandles.end()) {
|
||||
HAL_Value value;
|
||||
value.type = vd->second.valueType;
|
||||
switch (value.type) {
|
||||
case HAL_BOOLEAN:
|
||||
value.data.v_boolean = static_cast<bool>(it.value()) ? 1 : 0;
|
||||
if (jvalue.is_bool()) {
|
||||
value.data.v_boolean = jvalue.get_bool() ? 1 : 0;
|
||||
}
|
||||
break;
|
||||
case HAL_DOUBLE:
|
||||
value.data.v_double = it.value();
|
||||
value.data.v_double -= vd->second.doubleOffset;
|
||||
if (jvalue.is_number()) {
|
||||
value.data.v_double = jvalue.get_double();
|
||||
value.data.v_double -= vd->second.doubleOffset;
|
||||
}
|
||||
break;
|
||||
case HAL_ENUM: {
|
||||
if (it->is_string()) {
|
||||
if (jvalue.is_string()) {
|
||||
auto& options = vd->second.options;
|
||||
auto& str = it.value().get_ref<const std::string&>();
|
||||
auto& str = jvalue.get_string();
|
||||
auto optionIt =
|
||||
std::find_if(options.begin(), options.end(),
|
||||
[&](const std::string& v) { return v == str; });
|
||||
if (optionIt != options.end()) {
|
||||
value.data.v_enum = optionIt - options.begin();
|
||||
}
|
||||
} else if (it->is_number()) {
|
||||
} else if (jvalue.is_float() || jvalue.is_double()) {
|
||||
auto& values = vd->second.optionValues;
|
||||
double num = it.value();
|
||||
double num = jvalue.get_number();
|
||||
auto valueIt = std::find_if(
|
||||
values.begin(), values.end(),
|
||||
[&](double v) { return std::fabs(v - num) < 1e-4; });
|
||||
if (valueIt != values.end()) {
|
||||
value.data.v_enum = valueIt - values.begin();
|
||||
}
|
||||
} else if (jvalue.is_int()) {
|
||||
value.data.v_enum = jvalue.get_int();
|
||||
}
|
||||
value.data.v_enum = it.value();
|
||||
break;
|
||||
}
|
||||
case HAL_INT:
|
||||
value.data.v_int = it.value();
|
||||
value.data.v_int -= vd->second.intOffset;
|
||||
if (jvalue.is_int()) {
|
||||
value.data.v_int = jvalue.get_int();
|
||||
value.data.v_int -= vd->second.intOffset;
|
||||
}
|
||||
break;
|
||||
case HAL_LONG:
|
||||
value.data.v_long = it.value();
|
||||
value.data.v_long -= vd->second.intOffset;
|
||||
if (jvalue.is_int()) {
|
||||
value.data.v_long = jvalue.get_int();
|
||||
value.data.v_long -= vd->second.intOffset;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -193,29 +199,31 @@ void HALSimWSProviderSimDevice::OnValueChanged(SimDeviceValueData* valueData,
|
||||
if (ws) {
|
||||
switch (value->type) {
|
||||
case HAL_BOOLEAN:
|
||||
ProcessHalCallback(
|
||||
{{valueData->key, static_cast<bool>(value->data.v_boolean)}});
|
||||
ProcessHalCallback(wpi::util::json::object(
|
||||
valueData->key, static_cast<bool>(value->data.v_boolean)));
|
||||
break;
|
||||
case HAL_DOUBLE:
|
||||
ProcessHalCallback(
|
||||
{{valueData->key, value->data.v_double + valueData->doubleOffset}});
|
||||
ProcessHalCallback(wpi::util::json::object(
|
||||
valueData->key, value->data.v_double + valueData->doubleOffset));
|
||||
break;
|
||||
case HAL_ENUM: {
|
||||
int v = value->data.v_enum;
|
||||
if (v >= 0 && v < static_cast<int>(valueData->optionValues.size())) {
|
||||
ProcessHalCallback({{valueData->key, valueData->optionValues[v]}});
|
||||
ProcessHalCallback(wpi::util::json::object(
|
||||
valueData->key, valueData->optionValues[v]));
|
||||
} else if (v >= 0 && v < static_cast<int>(valueData->options.size())) {
|
||||
ProcessHalCallback({{valueData->key, valueData->options[v]}});
|
||||
ProcessHalCallback(
|
||||
wpi::util::json::object(valueData->key, valueData->options[v]));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case HAL_INT:
|
||||
ProcessHalCallback(
|
||||
{{valueData->key, value->data.v_int + valueData->intOffset}});
|
||||
ProcessHalCallback(wpi::util::json::object(
|
||||
valueData->key, value->data.v_int + valueData->intOffset));
|
||||
break;
|
||||
case HAL_LONG:
|
||||
ProcessHalCallback(
|
||||
{{valueData->key, value->data.v_long + valueData->intOffset}});
|
||||
ProcessHalCallback(wpi::util::json::object(
|
||||
valueData->key, value->data.v_long + valueData->intOffset));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -254,8 +262,10 @@ void HALSimWSProviderSimDevice::ProcessHalCallback(
|
||||
const wpi::util::json& payload) {
|
||||
auto ws = m_ws.lock();
|
||||
if (ws) {
|
||||
wpi::util::json netValue = {
|
||||
{"type", m_type}, {"device", m_deviceId}, {"data", payload}};
|
||||
auto netValue = wpi::util::json::object();
|
||||
netValue["type"] = m_type;
|
||||
netValue["device"] = m_deviceId;
|
||||
netValue["data"] = payload;
|
||||
ws->OnSimValueChanged(netValue);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,8 @@
|
||||
m_pcmIndex, m_solenoidIndex, \
|
||||
[](const char* name, void* param, const struct HAL_Value* value) { \
|
||||
static_cast<HALSimWSProviderSolenoid*>(param)->ProcessHalCallback( \
|
||||
{{jsonid, static_cast<ctype>(value->data.v_##haltype)}}); \
|
||||
wpi::util::json::object( \
|
||||
jsonid, static_cast<ctype>(value->data.v_##haltype))); \
|
||||
}, \
|
||||
this, true)
|
||||
|
||||
|
||||
@@ -12,7 +12,8 @@
|
||||
m_channel, \
|
||||
[](const char* name, void* param, const struct HAL_Value* value) { \
|
||||
static_cast<HALSimWSProviderDigitalPWM*>(param)->ProcessHalCallback( \
|
||||
{{jsonid, static_cast<ctype>(value->data.v_##haltype)}}); \
|
||||
wpi::util::json::object( \
|
||||
jsonid, static_cast<ctype>(value->data.v_##haltype))); \
|
||||
}, \
|
||||
this, true)
|
||||
|
||||
|
||||
@@ -6,7 +6,9 @@
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "wpi/util/json_fwd.hpp"
|
||||
namespace wpi::util {
|
||||
class json;
|
||||
} // namespace wpi::util
|
||||
|
||||
namespace wpilibws {
|
||||
|
||||
|
||||
@@ -13,8 +13,10 @@
|
||||
|
||||
#include "wpi/hal/simulation/NotifyListener.h"
|
||||
#include "wpi/halsim/ws_core/WSBaseProvider.hpp"
|
||||
#include "wpi/util/json_fwd.hpp"
|
||||
#include "wpi/util/mutex.hpp"
|
||||
|
||||
namespace wpi::util {
|
||||
class json;
|
||||
} // namespace wpi::util
|
||||
|
||||
namespace wpilibws {
|
||||
|
||||
|
||||
@@ -54,16 +54,12 @@ void HALSimHttpConnection::ProcessWsUpgrade() {
|
||||
return;
|
||||
}
|
||||
|
||||
wpi::util::json j;
|
||||
try {
|
||||
j = wpi::util::json::parse(msg);
|
||||
} catch (const wpi::util::json::parse_error& e) {
|
||||
std::string err("JSON parse failed: ");
|
||||
err += e.what();
|
||||
m_websocket->Fail(400, err);
|
||||
auto j = wpi::util::json::parse(msg);
|
||||
if (!j) {
|
||||
m_websocket->Fail(400, fmt::format("JSON parse failed: {}", j.error()));
|
||||
return;
|
||||
}
|
||||
m_server->OnNetValueChanged(j);
|
||||
m_server->OnNetValueChanged(*j);
|
||||
});
|
||||
|
||||
m_websocket->closed.connect([this](uint16_t, auto) {
|
||||
@@ -80,11 +76,11 @@ void HALSimHttpConnection::ProcessWsUpgrade() {
|
||||
void HALSimHttpConnection::OnSimValueChanged(const wpi::util::json& msg) {
|
||||
// Skip sending if this message is not in the allowed filter list
|
||||
try {
|
||||
auto& type = msg.at("type").get_ref<const std::string&>();
|
||||
auto& type = msg.at("type").get_string();
|
||||
if (!m_server->CanSendMessage(type)) {
|
||||
return;
|
||||
}
|
||||
} catch (wpi::util::json::exception& e) {
|
||||
} catch (std::logic_error& e) {
|
||||
wpi::util::print(stderr, "Error with message: {}\n", e.what());
|
||||
}
|
||||
|
||||
|
||||
@@ -162,8 +162,8 @@ void HALSimWeb::OnNetValueChanged(const wpi::util::json& msg) {
|
||||
// generate the key
|
||||
|
||||
try {
|
||||
auto& type = msg.at("type").get_ref<const std::string&>();
|
||||
auto& device = msg.at("device").get_ref<const std::string&>();
|
||||
auto& type = msg.at("type").get_string();
|
||||
auto& device = msg.at("device").get_string();
|
||||
|
||||
wpi::util::SmallString<64> key;
|
||||
key.append(type);
|
||||
@@ -176,7 +176,7 @@ void HALSimWeb::OnNetValueChanged(const wpi::util::json& msg) {
|
||||
if (provider) {
|
||||
provider->OnNetValueChanged(msg.at("data"));
|
||||
}
|
||||
} catch (wpi::util::json::exception& e) {
|
||||
} catch (std::logic_error& e) {
|
||||
wpi::util::print(stderr, "Error with incoming message: {}\n", e.what());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cinttypes>
|
||||
#include <memory>
|
||||
#include <string_view>
|
||||
#include <utility>
|
||||
@@ -12,10 +11,11 @@
|
||||
#include "wpi/halsim/ws_core/HALSimBaseWebSocketConnection.hpp"
|
||||
#include "wpi/halsim/ws_server/HALSimWeb.hpp"
|
||||
#include "wpi/net/HttpWebSocketServerConnection.hpp"
|
||||
#include "wpi/net/uv/AsyncFunction.hpp"
|
||||
#include "wpi/net/uv/Buffer.hpp"
|
||||
#include "wpi/util/json_fwd.hpp"
|
||||
#include "wpi/util/mutex.hpp"
|
||||
|
||||
namespace wpi::util {
|
||||
class json;
|
||||
} // namespace wpi::util
|
||||
|
||||
namespace wpilibws {
|
||||
|
||||
|
||||
@@ -16,7 +16,10 @@
|
||||
#include "wpi/net/uv/Loop.hpp"
|
||||
#include "wpi/net/uv/Tcp.hpp"
|
||||
#include "wpi/util/StringMap.hpp"
|
||||
#include "wpi/util/json_fwd.hpp"
|
||||
|
||||
namespace wpi::util {
|
||||
class json;
|
||||
} // namespace wpi::util
|
||||
|
||||
namespace wpilibws {
|
||||
|
||||
|
||||
@@ -44,18 +44,15 @@ void WebServerClientTest::InitializeWebSocket(const std::string& host, int port,
|
||||
});
|
||||
|
||||
m_websocket->text.connect([this](auto msg, bool) {
|
||||
wpi::util::json j;
|
||||
try {
|
||||
j = wpi::util::json::parse(msg);
|
||||
} catch (const wpi::util::json::parse_error& e) {
|
||||
std::string err("JSON parse failed: ");
|
||||
err += e.what();
|
||||
auto j = wpi::util::json::parse(msg);
|
||||
if (!j) {
|
||||
auto err = fmt::format("JSON parse failed: {}", j.error());
|
||||
wpi::util::print(stderr, "{}\n", err);
|
||||
m_websocket->Fail(1003, err);
|
||||
return;
|
||||
}
|
||||
// Save last message received
|
||||
m_json = j;
|
||||
m_json = *j;
|
||||
});
|
||||
|
||||
m_websocket->closed.connect([this](uint16_t, auto) {
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
#include <utility>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
@@ -78,14 +79,13 @@ TEST_F(WebServerIntegrationTest, DISABLED_DigitalOutput) {
|
||||
bool test_value = true; // Default value from HAL initialization
|
||||
try {
|
||||
auto& msg = m_webserverClient->GetLastMessage();
|
||||
test_type = msg.at("type").get_ref<const std::string&>();
|
||||
test_device = msg.at("device").get_ref<const std::string&>();
|
||||
test_type = msg.at("type").get_string();
|
||||
test_device = msg.at("device").get_string();
|
||||
auto& data = msg.at("data");
|
||||
wpi::util::json::const_iterator it = data.find("<>value");
|
||||
if (it != data.end()) {
|
||||
test_value = it.value();
|
||||
if (auto val = data.lookup("<>value"); val && val->is_bool()) {
|
||||
test_value = val->get_bool();
|
||||
}
|
||||
} catch (wpi::util::json::exception& e) {
|
||||
} catch (std::logic_error& e) {
|
||||
wpi::util::print(stderr, "Error with incoming message: {}\n", e.what());
|
||||
}
|
||||
|
||||
@@ -109,10 +109,11 @@ TEST_F(WebServerIntegrationTest, DISABLED_DigitalInput) {
|
||||
return;
|
||||
}
|
||||
if (IsConnectedClientWS()) {
|
||||
wpi::util::json msg = {{"type", "DIO"},
|
||||
{"device", std::to_string(PIN)},
|
||||
{"data", {{"<>value", EXPECTED_VALUE}}}};
|
||||
wpi::util::print("***** Input JSON: {}\n", msg.dump());
|
||||
wpi::util::json msg = wpi::util::json::object();
|
||||
msg["type"] = "DIO";
|
||||
msg["device"] = std::to_string(PIN);
|
||||
msg["data"] = wpi::util::json::object("<>value", EXPECTED_VALUE);
|
||||
wpi::util::print("***** Input JSON: {}\n", msg.to_string());
|
||||
m_webserverClient->SendMessage(msg);
|
||||
done = true;
|
||||
}
|
||||
@@ -143,11 +144,14 @@ TEST_F(WebServerIntegrationTest, DriverStation) {
|
||||
return;
|
||||
}
|
||||
if (IsConnectedClientWS()) {
|
||||
wpi::util::json msg = {
|
||||
{"type", "DriverStation"},
|
||||
{"device", ""},
|
||||
{"data", {{">enabled", EXPECTED_VALUE}, {">new_data", true}}}};
|
||||
wpi::util::print("***** Input JSON: {}\n", msg.dump());
|
||||
auto data = wpi::util::json::object();
|
||||
data[">enabled"] = EXPECTED_VALUE;
|
||||
data[">new_data"] = true;
|
||||
wpi::util::json msg = wpi::util::json::object();
|
||||
msg["type"] = "DriverStation";
|
||||
msg["device"] = "";
|
||||
msg["data"] = std::move(data);
|
||||
wpi::util::print("***** Input JSON: {}\n", msg.to_string());
|
||||
m_webserverClient->SendMessage(msg);
|
||||
done = true;
|
||||
}
|
||||
|
||||
@@ -107,8 +107,8 @@ void HALSimXRP::ParsePacket(std::span<const uint8_t> packet) {
|
||||
|
||||
void HALSimXRP::OnNetValueChanged(const wpi::util::json& msg) {
|
||||
try {
|
||||
auto& type = msg.at("type").get_ref<const std::string&>();
|
||||
auto& device = msg.at("device").get_ref<const std::string&>();
|
||||
auto& type = msg.at("type").get_string();
|
||||
auto& device = msg.at("device").get_string();
|
||||
|
||||
wpi::util::SmallString<64> key;
|
||||
key.append(type);
|
||||
@@ -121,16 +121,17 @@ void HALSimXRP::OnNetValueChanged(const wpi::util::json& msg) {
|
||||
if (provider) {
|
||||
provider->OnNetValueChanged(msg.at("data"));
|
||||
}
|
||||
} catch (wpi::util::json::exception& e) {
|
||||
} catch (std::logic_error& e) {
|
||||
wpi::util::print(stderr, "Error with incoming message: {}\n", e.what());
|
||||
}
|
||||
}
|
||||
|
||||
void HALSimXRP::OnSimValueChanged(const wpi::util::json& simData) {
|
||||
// We'll use a signal from robot code to send all the data
|
||||
if (simData["type"] == "HAL") {
|
||||
auto halData = simData["data"];
|
||||
if (halData.find(">sim_periodic_after") != halData.end()) {
|
||||
auto type = simData.lookup("type");
|
||||
if (type->is_string() && type->get_string() == "HAL") {
|
||||
auto halData = simData.lookup("data");
|
||||
if (halData && halData->contains(">sim_periodic_after")) {
|
||||
SendStateToXRP();
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
|
||||
#include <bit>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include <fmt/format.h>
|
||||
|
||||
@@ -33,21 +34,23 @@ XRP::XRP()
|
||||
}
|
||||
|
||||
void XRP::HandleWPILibUpdate(const wpi::util::json& data) {
|
||||
if (data.count("type") == 0) {
|
||||
auto type = data.lookup("type");
|
||||
if (!type || !type->is_string()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (data["type"] == "DriverStation") {
|
||||
auto& typeStr = type->get_string();
|
||||
if (typeStr == "DriverStation") {
|
||||
HandleDriverStationSimValueChanged(data);
|
||||
} else if (data["type"] == "XRPMotor") {
|
||||
} else if (typeStr == "XRPMotor") {
|
||||
HandleMotorSimValueChanged(data);
|
||||
} else if (data["type"] == "XRPServo") {
|
||||
} else if (typeStr == "XRPServo") {
|
||||
HandleServoSimValueChanged(data);
|
||||
} else if (data["type"] == "DIO") {
|
||||
} else if (typeStr == "DIO") {
|
||||
HandleDIOSimValueChanged(data);
|
||||
} else if (data["type"] == "Gyro") {
|
||||
} else if (typeStr == "Gyro") {
|
||||
HandleGyroSimValueChanged(data);
|
||||
} else if (data["type"] == "Encoder") {
|
||||
} else if (typeStr == "Encoder") {
|
||||
HandleEncoderSimValueChanged(data);
|
||||
}
|
||||
}
|
||||
@@ -108,56 +111,84 @@ void XRP::SetupXRPSendBuffer(wpi::net::raw_uv_ostream& buf) {
|
||||
|
||||
// WPILib Sim Handlers
|
||||
void XRP::HandleDriverStationSimValueChanged(const wpi::util::json& data) {
|
||||
auto dsData = data["data"];
|
||||
if (dsData.find(">enabled") != dsData.end()) {
|
||||
m_robot_enabled = dsData[">enabled"];
|
||||
auto dsData = data.lookup("data");
|
||||
if (!dsData || !dsData->is_object()) {
|
||||
return;
|
||||
}
|
||||
auto enabled = dsData->lookup(">enabled");
|
||||
if (enabled && enabled->is_bool()) {
|
||||
m_robot_enabled = enabled->get_bool();
|
||||
}
|
||||
}
|
||||
|
||||
void XRP::HandleMotorSimValueChanged(const wpi::util::json& data) {
|
||||
int deviceId = -1;
|
||||
auto motorData = data["data"];
|
||||
auto motorData = data.lookup("data");
|
||||
if (!motorData || !motorData->is_object()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (data["device"] == "motorL") {
|
||||
auto device = data.lookup("device");
|
||||
if (!device || !device->is_string()) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto& deviceStr = device->get_string();
|
||||
if (deviceStr == "motorL") {
|
||||
deviceId = 0;
|
||||
} else if (data["device"] == "motorR") {
|
||||
} else if (deviceStr == "motorR") {
|
||||
deviceId = 1;
|
||||
} else if (data["device"] == "motor3") {
|
||||
} else if (deviceStr == "motor3") {
|
||||
deviceId = 2;
|
||||
} else if (data["device"] == "motor4") {
|
||||
} else if (deviceStr == "motor4") {
|
||||
deviceId = 3;
|
||||
}
|
||||
|
||||
if (deviceId != -1 && motorData.find("<duty_cycle") != motorData.end()) {
|
||||
m_motor_outputs[deviceId] = motorData["<duty_cycle"];
|
||||
auto dutyCycle = motorData->lookup("<duty_cycle");
|
||||
if (deviceId != -1 && dutyCycle && dutyCycle->is_number()) {
|
||||
m_motor_outputs[deviceId] = dutyCycle->get_number();
|
||||
}
|
||||
}
|
||||
|
||||
void XRP::HandleServoSimValueChanged(const wpi::util::json& data) {
|
||||
int deviceId = -1;
|
||||
auto servoData = data["data"];
|
||||
auto servoData = data.lookup("data");
|
||||
if (!servoData || !servoData->is_object()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (data["device"] == "servo1") {
|
||||
auto device = data.lookup("device");
|
||||
if (!device || !device->is_string()) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto& deviceStr = device->get_string();
|
||||
if (deviceStr == "servo1") {
|
||||
deviceId = 4;
|
||||
} else if (data["device"] == "servo2") {
|
||||
} else if (deviceStr == "servo2") {
|
||||
deviceId = 5;
|
||||
} else if (data["device"] == "servo3") {
|
||||
} else if (deviceStr == "servo3") {
|
||||
deviceId = 6;
|
||||
} else if (data["device"] == "servo4") {
|
||||
} else if (deviceStr == "servo4") {
|
||||
deviceId = 7;
|
||||
}
|
||||
|
||||
if (deviceId != -1 && servoData.find("<position") != servoData.end()) {
|
||||
m_servo_outputs[deviceId] = servoData["<position"];
|
||||
auto position = servoData->lookup("<position");
|
||||
if (deviceId != -1 && position && position->is_number()) {
|
||||
m_servo_outputs[deviceId] = position->get_number();
|
||||
}
|
||||
}
|
||||
|
||||
void XRP::HandleDIOSimValueChanged(const wpi::util::json& data) {
|
||||
int deviceId = -1;
|
||||
auto dioData = data["data"];
|
||||
auto dioData = data.lookup("data");
|
||||
|
||||
auto device = data.lookup("device");
|
||||
if (!device || !device->is_string()) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
deviceId = std::stoi(data["device"].get<std::string>());
|
||||
deviceId = std::stoi(device->get_string());
|
||||
} catch (const std::invalid_argument&) {
|
||||
deviceId = -1;
|
||||
}
|
||||
@@ -167,26 +198,31 @@ void XRP::HandleDIOSimValueChanged(const wpi::util::json& data) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (dioData.find("<init") != dioData.end() && dioData["<init"]) {
|
||||
auto init = dioData->lookup("<init");
|
||||
if (init && init->is_bool() && init->get_bool()) {
|
||||
// All DIOs are initialized as inputs by default
|
||||
m_digital_inputs.emplace(deviceId, false);
|
||||
}
|
||||
|
||||
if (dioData.find("<input") != dioData.end() && dioData["<input"] == false) {
|
||||
auto input = dioData->lookup("<input");
|
||||
if (input && input->is_bool() && !input->get_bool()) {
|
||||
// We're registering an output device
|
||||
// Remove from the digital inputs list (if present)
|
||||
m_digital_inputs.erase(deviceId);
|
||||
m_digital_outputs.emplace(deviceId, false);
|
||||
}
|
||||
|
||||
if (dioData.find("<>value") != dioData.end() &&
|
||||
m_digital_outputs.count(deviceId) > 0) {
|
||||
m_digital_outputs[deviceId] = dioData["<>value"];
|
||||
auto value = dioData->lookup("<>value");
|
||||
if (value && value->is_bool() && m_digital_outputs.count(deviceId) > 0) {
|
||||
m_digital_outputs[deviceId] = value->get_bool();
|
||||
}
|
||||
}
|
||||
|
||||
void XRP::HandleGyroSimValueChanged(const wpi::util::json& data) {
|
||||
m_gyro_name = data["device"].get<std::string>();
|
||||
auto name = data.lookup("device");
|
||||
if (name && name->is_string()) {
|
||||
m_gyro_name = name->get_string();
|
||||
}
|
||||
}
|
||||
|
||||
void XRP::HandleEncoderSimValueChanged(const wpi::util::json& data) {
|
||||
@@ -196,10 +232,18 @@ void XRP::HandleEncoderSimValueChanged(const wpi::util::json& data) {
|
||||
// 8/9 -> Encoder 2
|
||||
// 10/11 -> Encoder 3
|
||||
int deviceId = -1;
|
||||
auto encData = data["data"];
|
||||
auto encData = data.lookup("data");
|
||||
if (!encData || !encData->is_object()) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto device = data.lookup("device");
|
||||
if (!device || !device->is_string()) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
deviceId = std::stoi(data["device"].get<std::string>());
|
||||
deviceId = std::stoi(device->get_string());
|
||||
} catch (const std::invalid_argument&) {
|
||||
deviceId = -1;
|
||||
}
|
||||
@@ -208,10 +252,14 @@ void XRP::HandleEncoderSimValueChanged(const wpi::util::json& data) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (encData.find("<init") != encData.end() && encData["<init"]) {
|
||||
auto init = encData->lookup("<init");
|
||||
auto jchA = encData->lookup("<channel_a");
|
||||
auto jchB = encData->lookup("<channel_b");
|
||||
if (init && init->is_bool() && init->get_bool() && jchA && jchA->is_int() &&
|
||||
jchB && jchB->is_int()) {
|
||||
// The <channel_a and <channel_b values come with the init message
|
||||
int chA = encData["<channel_a"];
|
||||
int chB = encData["<channel_b"];
|
||||
int chA = jchA->get_int();
|
||||
int chB = jchB->get_int();
|
||||
|
||||
if ((chA == 4 && chB == 5) || (chA == 5 && chB == 4)) {
|
||||
m_encoder_channel_map.emplace(0, deviceId);
|
||||
@@ -302,9 +350,14 @@ void XRP::ReadGyroTag(std::span<const uint8_t> packet) {
|
||||
wpi::util::json gyroJson;
|
||||
gyroJson["type"] = "Gyro";
|
||||
gyroJson["device"] = m_gyro_name;
|
||||
gyroJson["data"] = {{">rate_x", rate_x}, {">rate_y", rate_y},
|
||||
{">rate_z", rate_z}, {">angle_x", angle_x},
|
||||
{">angle_y", angle_y}, {">angle_z", angle_z}};
|
||||
auto data = wpi::util::json::object();
|
||||
data[">rate_x"] = rate_x;
|
||||
data[">rate_y"] = rate_y;
|
||||
data[">rate_z"] = rate_z;
|
||||
data[">angle_x"] = angle_x;
|
||||
data[">angle_y"] = angle_y;
|
||||
data[">angle_z"] = angle_z;
|
||||
gyroJson["data"] = std::move(data);
|
||||
|
||||
// Update WPILib
|
||||
m_wpilib_update_func(gyroJson);
|
||||
@@ -318,7 +371,7 @@ void XRP::ReadDIOTag(std::span<const uint8_t> packet) {
|
||||
wpi::util::json dioJson;
|
||||
dioJson["type"] = "DIO";
|
||||
dioJson["device"] = std::to_string(packet[2]);
|
||||
dioJson["data"] = {{"<>value", packet[3] == 1}};
|
||||
dioJson["data"] = wpi::util::json::object("<>value", packet[3] == 1);
|
||||
|
||||
m_wpilib_update_func(dioJson);
|
||||
}
|
||||
@@ -348,7 +401,7 @@ void XRP::ReadEncoderTag(std::span<const uint8_t> packet) {
|
||||
wpi::util::json encJson;
|
||||
encJson["type"] = "Encoder";
|
||||
encJson["device"] = std::to_string(wpilibEncoderChannel);
|
||||
encJson["data"] = {{">count", count}};
|
||||
encJson["data"] = wpi::util::json::object(">count", count);
|
||||
|
||||
if (containsPeriod) {
|
||||
// Older versions of XRP firmware do not provide Encoder Period.
|
||||
@@ -375,8 +428,7 @@ void XRP::ReadEncoderTag(std::span<const uint8_t> packet) {
|
||||
period = -period;
|
||||
}
|
||||
|
||||
encJson["data"].push_back(
|
||||
{wpi::util::json(">period"), wpi::util::json(period)});
|
||||
encJson["data"].emplace_back(wpi::util::json::object(">period", period));
|
||||
}
|
||||
|
||||
m_wpilib_update_func(encJson);
|
||||
@@ -396,7 +448,7 @@ void XRP::ReadAnalogTag(std::span<const uint8_t> packet) {
|
||||
wpi::util::json analogJson;
|
||||
analogJson["type"] = "AI";
|
||||
analogJson["device"] = std::to_string(analogId);
|
||||
analogJson["data"] = {{">voltage", voltage}};
|
||||
analogJson["data"] = wpi::util::json::object(">voltage", voltage);
|
||||
|
||||
m_wpilib_update_func(analogJson);
|
||||
}
|
||||
|
||||
@@ -18,7 +18,10 @@
|
||||
#include "wpi/net/uv/Loop.hpp"
|
||||
#include "wpi/net/uv/Timer.hpp"
|
||||
#include "wpi/net/uv/Udp.hpp"
|
||||
#include "wpi/util/json_fwd.hpp"
|
||||
|
||||
namespace wpi::util {
|
||||
class json;
|
||||
} // namespace wpi::util
|
||||
|
||||
namespace wpilibxrp {
|
||||
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
#include <string>
|
||||
|
||||
#include "wpi/net/raw_uv_ostream.hpp"
|
||||
#include "wpi/util/json_fwd.hpp"
|
||||
|
||||
#define XRP_TAG_MOTOR 0x12
|
||||
#define XRP_TAG_SERVO 0x13
|
||||
@@ -20,6 +19,10 @@
|
||||
#define XRP_TAG_ACCEL 0x17
|
||||
#define XRP_TAG_ENCODER 0x18
|
||||
|
||||
namespace wpi::util {
|
||||
class json;
|
||||
} // namespace wpi::util
|
||||
|
||||
namespace wpilibxrp {
|
||||
|
||||
using WPILibUpdateFunc = std::function<void(const wpi::util::json&)>;
|
||||
|
||||
Reference in New Issue
Block a user