Compare commits
1 Commits
0fdd55851c
...
8f3ad69754
| Author | SHA1 | Date |
|---|---|---|
|
|
8f3ad69754 |
|
|
@ -18,17 +18,6 @@ void init_ethernetmessage(pybind11::module_& m) {
|
|||
.def_readwrite("fcs", &EthernetMessage::fcs)
|
||||
.def_readwrite("frameTooShort", &EthernetMessage::frameTooShort)
|
||||
.def_readwrite("noPadding", &EthernetMessage::noPadding)
|
||||
.def_readwrite("fcsVerified", &EthernetMessage::fcsVerified)
|
||||
.def_readwrite("txAborted", &EthernetMessage::txAborted)
|
||||
.def_readwrite("crcError", &EthernetMessage::crcError)
|
||||
.def_readwrite("isT1S", &EthernetMessage::isT1S)
|
||||
.def_readwrite("isT1SSymbol", &EthernetMessage::isT1SSymbol)
|
||||
.def_readwrite("isT1SBurst", &EthernetMessage::isT1SBurst)
|
||||
.def_readwrite("txCollision", &EthernetMessage::txCollision)
|
||||
.def_readwrite("isT1SWake", &EthernetMessage::isT1SWake)
|
||||
.def_readwrite("t1sNodeId", &EthernetMessage::t1sNodeId)
|
||||
.def_readwrite("t1sBurstCount", &EthernetMessage::t1sBurstCount)
|
||||
.def_readwrite("t1sSymbolType", &EthernetMessage::t1sSymbolType)
|
||||
.def("get_destination_mac", &EthernetMessage::getDestinationMAC, pybind11::return_value_policy::reference)
|
||||
.def("get_source_mac", &EthernetMessage::getSourceMAC, pybind11::return_value_policy::reference)
|
||||
.def("get_ether_type", &EthernetMessage::getEtherType);
|
||||
|
|
|
|||
|
|
@ -111,7 +111,7 @@ void init_chipid(pybind11::module_& m) {
|
|||
.value("RAD_GALAXY_2_ZMPCHIP_ID", ChipID::RAD_GALAXY_2_ZMPCHIP_ID)
|
||||
.value("NewDevice59_MCHIP", ChipID::NewDevice59_MCHIP)
|
||||
.value("RADMoon2_Z7010_ZYNQ", ChipID::RADMoon2_Z7010_ZYNQ)
|
||||
.value("neoVIFIRE2_Core_SG4", ChipID::neoVIFIRE2_Core_SG4)
|
||||
.value("neoVIFIRE2_CORE_SG4", ChipID::neoVIFIRE2_CORE_SG4)
|
||||
.value("RADBMS_MCHIP", ChipID::RADBMS_MCHIP)
|
||||
.value("RADMoon2_ZL_MCHIP", ChipID::RADMoon2_ZL_MCHIP)
|
||||
.value("RADGigastar_USBZ_Z7010_ZYNQ", ChipID::RADGigastar_USBZ_Z7010_ZYNQ)
|
||||
|
|
|
|||
|
|
@ -41,20 +41,20 @@ void init_idevicesettings(pybind11::module_& m) {
|
|||
.def("apply", &IDeviceSettings::apply, pybind11::arg("temporary") = 0, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("apply_defaults", &IDeviceSettings::applyDefaults, pybind11::arg("temporary") = 0, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("refresh", &IDeviceSettings::refresh, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
|
||||
|
||||
// Baudrate methods
|
||||
.def("get_baudrate", &IDeviceSettings::getBaudrateFor, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("set_baudrate", &IDeviceSettings::setBaudrateFor, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("get_fd_baudrate", &IDeviceSettings::getFDBaudrateFor, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("set_fd_baudrate", &IDeviceSettings::setFDBaudrateFor, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
|
||||
|
||||
// Termination methods
|
||||
.def("is_termination_supported", &IDeviceSettings::isTerminationSupportedFor, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("can_termination_be_enabled", &IDeviceSettings::canTerminationBeEnabledFor, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("is_termination_enabled", &IDeviceSettings::isTerminationEnabledFor, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("set_termination", &IDeviceSettings::setTerminationFor, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("get_termination_groups", &IDeviceSettings::getTerminationGroups, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
|
||||
|
||||
// LIN methods
|
||||
.def("is_commander_resistor_enabled", &IDeviceSettings::isCommanderResistorEnabledFor, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("set_commander_resistor", &IDeviceSettings::setCommanderResistorFor, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
|
|
@ -62,7 +62,7 @@ void init_idevicesettings(pybind11::module_& m) {
|
|||
.def("set_lin_mode", &IDeviceSettings::setLINModeFor, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("get_lin_commander_response_time", &IDeviceSettings::getLINCommanderResponseTimeFor, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("set_lin_commander_response_time", &IDeviceSettings::setLINCommanderResponseTimeFor, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
|
||||
|
||||
// Ethernet PHY methods
|
||||
.def("get_phy_enable", &IDeviceSettings::getPhyEnable, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("get_phy_mode", &IDeviceSettings::getPhyMode, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
|
|
@ -70,20 +70,6 @@ void init_idevicesettings(pybind11::module_& m) {
|
|||
.def("set_phy_enable", &IDeviceSettings::setPhyEnable, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("set_phy_mode", &IDeviceSettings::setPhyMode, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("set_phy_speed", &IDeviceSettings::setPhySpeed, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
|
||||
// 10BASE-T1S methods
|
||||
.def("is_t1s_plca_enabled", &IDeviceSettings::isT1SPLCAEnabledFor, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("set_t1s_plca", &IDeviceSettings::setT1SPLCAFor, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("get_t1s_local_id", &IDeviceSettings::getT1SLocalIDFor, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("set_t1s_local_id", &IDeviceSettings::setT1SLocalIDFor, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("get_t1s_max_nodes", &IDeviceSettings::getT1SMaxNodesFor, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("set_t1s_max_nodes", &IDeviceSettings::setT1SMaxNodesFor, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("get_t1s_tx_opp_timer", &IDeviceSettings::getT1STxOppTimerFor, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("set_t1s_tx_opp_timer", &IDeviceSettings::setT1STxOppTimerFor, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("get_t1s_max_burst", &IDeviceSettings::getT1SMaxBurstFor, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("set_t1s_max_burst", &IDeviceSettings::setT1SMaxBurstFor, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("get_t1s_burst_timer", &IDeviceSettings::getT1SBurstTimerFor, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("set_t1s_burst_timer", &IDeviceSettings::setT1SBurstTimerFor, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
|
||||
// Status properties
|
||||
.def_readonly("disabled", &IDeviceSettings::disabled)
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
#include "icsneo/communication/packet/ethernetpacket.h"
|
||||
#include <algorithm>
|
||||
#include <algorithm> // for std::copy
|
||||
#include <iostream>
|
||||
|
||||
using namespace icsneo;
|
||||
|
|
@ -10,17 +10,16 @@ std::shared_ptr<EthernetMessage> HardwareEthernetPacket::DecodeToMessage(const s
|
|||
// Make sure we have enough to read the packet length first
|
||||
if(bytestream.size() < sizeof(HardwareEthernetPacket))
|
||||
return nullptr;
|
||||
const size_t fcsSize = packet->header.FCS_AVAIL ? 4 : 0;
|
||||
// Ensure Length is sufficient for FCS extraction to avoid invalid iterator arithmetic
|
||||
if(packet->Length < fcsSize)
|
||||
// packet->Length will also encompass the two uint16_t's at the end of the struct, make sure that at least they are here
|
||||
if(packet->Length < 4)
|
||||
return nullptr;
|
||||
const size_t fcsSize = packet->header.FCS_AVAIL ? 4 : 0;
|
||||
const size_t bytestreamExpectedSize = sizeof(HardwareEthernetPacket) + packet->Length;
|
||||
const size_t bytestreamActualSize = bytestream.size();
|
||||
if(bytestreamActualSize < bytestreamExpectedSize)
|
||||
return nullptr;
|
||||
auto messagePtr = std::make_shared<EthernetMessage>();
|
||||
EthernetMessage& message = *messagePtr;
|
||||
// Standard Ethernet fields
|
||||
message.transmitted = packet->eid.TXMSG;
|
||||
if(message.transmitted)
|
||||
message.description = packet->stats;
|
||||
|
|
@ -28,28 +27,12 @@ std::shared_ptr<EthernetMessage> HardwareEthernetPacket::DecodeToMessage(const s
|
|||
if(message.preemptionEnabled)
|
||||
message.preemptionFlags = (uint8_t)((rawWords[0] & 0x03F8) >> 4);
|
||||
message.frameTooShort = packet->header.RUNT_FRAME;
|
||||
message.noPadding = !packet->header.ENABLE_PADDING;
|
||||
message.fcsVerified = packet->header.FCS_VERIFIED;
|
||||
message.txAborted = packet->eid.TXAborted;
|
||||
message.crcError = packet->header.CRC_ERROR;
|
||||
|
||||
if(message.frameTooShort)
|
||||
message.error = true;
|
||||
// This timestamp is raw off the device (in timestampResolution increments)
|
||||
// Decoder will fix as it has information about the timestampResolution increments
|
||||
message.timestamp = packet->timestamp.TS;
|
||||
|
||||
// Check if this is a T1S packet and populate T1S-specific fields
|
||||
message.isT1S = packet->header.T1S_ETHERNET;
|
||||
if(message.isT1S) {
|
||||
message.isT1SSymbol = packet->eid.T1S_SYMBOL;
|
||||
message.isT1SBurst = packet->eid.T1S_BURST;
|
||||
message.txCollision = packet->t1s_status.TXCollision;
|
||||
message.isT1SWake = packet->t1s_status.T1SWake;
|
||||
message.t1sNodeId = packet->t1s_node.T1S_NODE_ID;
|
||||
message.t1sBurstCount = packet->t1s_node.T1S_BURST_COUNT;
|
||||
}
|
||||
|
||||
const std::vector<uint8_t>::const_iterator databegin = bytestream.begin() + sizeof(HardwareEthernetPacket);
|
||||
const std::vector<uint8_t>::const_iterator dataend = databegin + packet->Length - fcsSize;
|
||||
message.data.insert(message.data.begin(), databegin, dataend);
|
||||
|
|
|
|||
|
|
@ -4,17 +4,17 @@
|
|||
#ifdef __cplusplus
|
||||
|
||||
#include "icsneo/communication/message/message.h"
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
// Used for MACAddress.toString() only
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
#include <cstring>
|
||||
|
||||
namespace icsneo {
|
||||
|
||||
struct MACAddress {
|
||||
uint8_t data[6];
|
||||
|
||||
// Helpers
|
||||
std::string toString() const {
|
||||
std::stringstream ss;
|
||||
for(size_t i = 0; i < 6; i++) {
|
||||
|
|
@ -33,25 +33,11 @@ struct MACAddress {
|
|||
|
||||
class EthernetMessage : public Frame {
|
||||
public:
|
||||
// Standard Ethernet fields
|
||||
bool preemptionEnabled = false;
|
||||
uint8_t preemptionFlags = 0;
|
||||
std::optional<uint32_t> fcs;
|
||||
bool frameTooShort = false;
|
||||
bool noPadding = false;
|
||||
bool fcsVerified = false;
|
||||
bool txAborted = false;
|
||||
bool crcError = false;
|
||||
bool isT1S = false;
|
||||
|
||||
|
||||
bool isT1SSymbol = false;
|
||||
bool isT1SBurst = false;
|
||||
bool txCollision = false;
|
||||
bool isT1SWake = false;
|
||||
uint8_t t1sNodeId = 0;
|
||||
uint8_t t1sBurstCount = 0;
|
||||
uint8_t t1sSymbolType = 0;
|
||||
|
||||
// Accessors
|
||||
const MACAddress& getDestinationMAC() const { return *(const MACAddress*)(data.data() + 0); }
|
||||
|
|
|
|||
|
|
@ -110,7 +110,7 @@ enum class ChipID : uint8_t {
|
|||
RAD_GALAXY_2_ZMPCHIP_ID = 102,
|
||||
NewDevice59_MCHIP = 103,
|
||||
RADMoon2_Z7010_ZYNQ = 104,
|
||||
neoVIFIRE2_Core_SG4 = 105,
|
||||
neoVIFIRE2_CORE_SG4 = 105,
|
||||
RADBMS_MCHIP = 106,
|
||||
RADMoon2_ZL_MCHIP = 107,
|
||||
RADGigastar_USBZ_Z7010_ZYNQ = 108,
|
||||
|
|
|
|||
|
|
@ -162,14 +162,6 @@ public:
|
|||
|
||||
bool hasBootloader() { return !!getBootloader(); }
|
||||
|
||||
virtual bool supportsSwVersionValidate() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
void setBootloaderVersion(const HardwareInfo::Version& version) {
|
||||
bootloaderVersion = version;
|
||||
}
|
||||
|
||||
static std::string SerialNumToString(uint32_t serial);
|
||||
static uint32_t SerialStringToNum(const std::string& serial);
|
||||
static bool SerialStringIsNumeric(const std::string& serial);
|
||||
|
|
@ -990,7 +982,6 @@ protected:
|
|||
LEDState ledState;
|
||||
void updateLEDState();
|
||||
|
||||
std::optional<HardwareInfo::Version> bootloaderVersion = std::nullopt;
|
||||
|
||||
private:
|
||||
neodevice_t data;
|
||||
|
|
|
|||
|
|
@ -940,74 +940,6 @@ public:
|
|||
report(APIEvent::Type::SettingNotAvaiableDevice, APIEvent::Severity::EventWarning);
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
virtual std::optional<bool> isT1SPLCAEnabledFor(Network net) const {
|
||||
(void)net;
|
||||
report(APIEvent::Type::SettingNotAvaiableDevice, APIEvent::Severity::EventWarning);
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
virtual bool setT1SPLCAFor(Network net, bool enable) {
|
||||
(void)net; (void)enable;
|
||||
report(APIEvent::Type::SettingNotAvaiableDevice, APIEvent::Severity::EventWarning);
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual std::optional<uint8_t> getT1SLocalIDFor(Network net) const {
|
||||
(void)net;
|
||||
report(APIEvent::Type::SettingNotAvaiableDevice, APIEvent::Severity::EventWarning);
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
virtual bool setT1SLocalIDFor(Network net, uint8_t id) {
|
||||
(void)net; (void)id;
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual std::optional<uint8_t> getT1SMaxNodesFor(Network net) const {
|
||||
(void)net;
|
||||
report(APIEvent::Type::SettingNotAvaiableDevice, APIEvent::Severity::EventWarning);
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
virtual bool setT1SMaxNodesFor(Network net, uint8_t nodes) {
|
||||
(void)net; (void)nodes;
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual std::optional<uint8_t> getT1STxOppTimerFor(Network net) const {
|
||||
(void)net;
|
||||
report(APIEvent::Type::SettingNotAvaiableDevice, APIEvent::Severity::EventWarning);
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
virtual bool setT1STxOppTimerFor(Network net, uint8_t timer) {
|
||||
(void)net; (void)timer;
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual std::optional<uint8_t> getT1SMaxBurstFor(Network net) const {
|
||||
(void)net;
|
||||
report(APIEvent::Type::SettingNotAvaiableDevice, APIEvent::Severity::EventWarning);
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
virtual bool setT1SMaxBurstFor(Network net, uint8_t burst) {
|
||||
(void)net; (void)burst;
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual std::optional<uint8_t> getT1SBurstTimerFor(Network net) const {
|
||||
(void)net;
|
||||
report(APIEvent::Type::SettingNotAvaiableDevice, APIEvent::Severity::EventWarning);
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
virtual bool setT1SBurstTimerFor(Network net, uint8_t timer) {
|
||||
(void)net; (void)timer;
|
||||
return false;
|
||||
}
|
||||
|
||||
const void* getRawStructurePointer() const { return settingsInDeviceRAM.data(); }
|
||||
void* getMutableRawStructurePointer() { return settings.data(); }
|
||||
template<typename T> const T* getStructurePointer() const { return reinterpret_cast<const T*>(getRawStructurePointer()); }
|
||||
|
|
|
|||
|
|
@ -98,15 +98,13 @@ public:
|
|||
}
|
||||
|
||||
CoreChipVariant getCoreChipVariant() {
|
||||
if(!bootloaderVersion.has_value()) {
|
||||
const auto& hardwareInfo = getHardwareInfo(std::chrono::milliseconds(1000));
|
||||
if(!hardwareInfo) {
|
||||
chipVariant = CoreChipVariant::Invalid;
|
||||
return chipVariant;
|
||||
}
|
||||
setBootloaderVersion(hardwareInfo->bootloaderVersion);
|
||||
const auto& hardwareInfo = getHardwareInfo(std::chrono::milliseconds(1000));
|
||||
if(!hardwareInfo) {
|
||||
chipVariant = CoreChipVariant::Invalid;
|
||||
return chipVariant;
|
||||
}
|
||||
if(bootloaderVersion->major >= CORE_SG4_BL_MAJOR_VERSION_CUTOFF) {
|
||||
const auto& bootloaderVersion = hardwareInfo->bootloaderVersion;
|
||||
if(bootloaderVersion.major >= CORE_SG4_BL_MAJOR_VERSION_CUTOFF) {
|
||||
chipVariant = CoreChipVariant::Core_SG4;
|
||||
} else {
|
||||
chipVariant = CoreChipVariant::Core;
|
||||
|
|
@ -124,7 +122,7 @@ public:
|
|||
static std::vector<ChipInfo> chipsSG4 = {
|
||||
{ChipID::neoVIFIRE2_MCHIP, true, "MCHIP", "fire2_mchip_ief", 0, FirmwareType::IEF},
|
||||
{ChipID::neoVIFIRE2_ZYNQ, true, "ZCHIP", "fire2_zchip_ief", 1, FirmwareType::IEF},
|
||||
{ChipID::neoVIFIRE2_Core_SG4, true, "Core", "fire2_core_sg4", 2, FirmwareType::IEF}
|
||||
{ChipID::neoVIFIRE2_CORE_SG4, true, "Core", "fire2_core_sg4", 2, FirmwareType::IEF}
|
||||
};
|
||||
|
||||
if(chipVariant == CoreChipVariant::Core_SG4) {
|
||||
|
|
@ -139,7 +137,7 @@ public:
|
|||
pipeline.add<EnterBootloaderPhase>()
|
||||
.add<FlashPhase>(ChipID::neoVIFIRE2_MCHIP, BootloaderCommunication::RED);
|
||||
if(chipVariant == CoreChipVariant::Core_SG4) {
|
||||
pipeline.add<FlashPhase>(ChipID::neoVIFIRE2_Core_SG4, BootloaderCommunication::REDCore, false, false);
|
||||
pipeline.add<FlashPhase>(ChipID::neoVIFIRE2_CORE_SG4, BootloaderCommunication::REDCore, false, false);
|
||||
} else {
|
||||
pipeline.add<FlashPhase>(ChipID::neoVIFIRE2_Core, BootloaderCommunication::REDCore, false, false);
|
||||
}
|
||||
|
|
@ -149,10 +147,6 @@ public:
|
|||
return pipeline;
|
||||
}
|
||||
|
||||
bool supportsSwVersionValidate() const override {
|
||||
return bootloaderVersion.has_value() && (bootloaderVersion->major > 4 || (bootloaderVersion->major == 4 && bootloaderVersion->minor >= 3));
|
||||
}
|
||||
|
||||
std::vector<VersionReport> getChipVersions(bool refreshComponents = true) override {
|
||||
if(chipVariant == CoreChipVariant::Invalid) {
|
||||
getCoreChipVariant();
|
||||
|
|
|
|||
|
|
@ -257,153 +257,6 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
std::optional<bool> isT1SPLCAEnabledFor(Network net) const override {
|
||||
const ETHERNET10T1S_SETTINGS* t1s = getT1SSettingsFor(net);
|
||||
if(t1s == nullptr)
|
||||
return std::nullopt;
|
||||
|
||||
return std::make_optional<bool>((t1s->flags & ETHERNET10T1S_SETTINGS_FLAG_ENABLE_PLCA) != 0);
|
||||
}
|
||||
|
||||
bool setT1SPLCAFor(Network net, bool enable) override {
|
||||
ETHERNET10T1S_SETTINGS* t1s = getMutableT1SSettingsFor(net);
|
||||
if(t1s == nullptr)
|
||||
return false;
|
||||
|
||||
if(enable)
|
||||
t1s->flags |= ETHERNET10T1S_SETTINGS_FLAG_ENABLE_PLCA;
|
||||
else
|
||||
t1s->flags &= ~ETHERNET10T1S_SETTINGS_FLAG_ENABLE_PLCA;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
std::optional<uint8_t> getT1SLocalIDFor(Network net) const override {
|
||||
const ETHERNET10T1S_SETTINGS* t1s = getT1SSettingsFor(net);
|
||||
if(t1s == nullptr)
|
||||
return std::nullopt;
|
||||
|
||||
return std::make_optional(t1s->local_id);
|
||||
}
|
||||
|
||||
bool setT1SLocalIDFor(Network net, uint8_t id) override {
|
||||
ETHERNET10T1S_SETTINGS* t1s = getMutableT1SSettingsFor(net);
|
||||
if(t1s == nullptr)
|
||||
return false;
|
||||
|
||||
t1s->local_id = id;
|
||||
return true;
|
||||
}
|
||||
|
||||
std::optional<uint8_t> getT1SMaxNodesFor(Network net) const override {
|
||||
const ETHERNET10T1S_SETTINGS* t1s = getT1SSettingsFor(net);
|
||||
if(t1s == nullptr)
|
||||
return std::nullopt;
|
||||
|
||||
return std::make_optional(t1s->max_num_nodes);
|
||||
}
|
||||
|
||||
bool setT1SMaxNodesFor(Network net, uint8_t nodes) override {
|
||||
ETHERNET10T1S_SETTINGS* t1s = getMutableT1SSettingsFor(net);
|
||||
if(t1s == nullptr)
|
||||
return false;
|
||||
|
||||
t1s->max_num_nodes = nodes;
|
||||
return true;
|
||||
}
|
||||
|
||||
std::optional<uint8_t> getT1STxOppTimerFor(Network net) const override {
|
||||
const ETHERNET10T1S_SETTINGS* t1s = getT1SSettingsFor(net);
|
||||
if(t1s == nullptr)
|
||||
return std::nullopt;
|
||||
|
||||
return std::make_optional(t1s->to_timer);
|
||||
}
|
||||
|
||||
bool setT1STxOppTimerFor(Network net, uint8_t timer) override {
|
||||
ETHERNET10T1S_SETTINGS* t1s = getMutableT1SSettingsFor(net);
|
||||
if(t1s == nullptr)
|
||||
return false;
|
||||
|
||||
t1s->to_timer = timer;
|
||||
return true;
|
||||
}
|
||||
|
||||
std::optional<uint8_t> getT1SMaxBurstFor(Network net) const override {
|
||||
const ETHERNET10T1S_SETTINGS* t1s = getT1SSettingsFor(net);
|
||||
if(t1s == nullptr)
|
||||
return std::nullopt;
|
||||
|
||||
return std::make_optional(t1s->max_burst_count);
|
||||
}
|
||||
|
||||
bool setT1SMaxBurstFor(Network net, uint8_t burst) override {
|
||||
ETHERNET10T1S_SETTINGS* t1s = getMutableT1SSettingsFor(net);
|
||||
if(t1s == nullptr)
|
||||
return false;
|
||||
|
||||
t1s->max_burst_count = burst;
|
||||
return true;
|
||||
}
|
||||
|
||||
std::optional<uint8_t> getT1SBurstTimerFor(Network net) const override {
|
||||
const ETHERNET10T1S_SETTINGS* t1s = getT1SSettingsFor(net);
|
||||
if(t1s == nullptr)
|
||||
return std::nullopt;
|
||||
|
||||
return std::make_optional(t1s->burst_timer);
|
||||
}
|
||||
|
||||
bool setT1SBurstTimerFor(Network net, uint8_t timer) override {
|
||||
ETHERNET10T1S_SETTINGS* t1s = getMutableT1SSettingsFor(net);
|
||||
if(t1s == nullptr)
|
||||
return false;
|
||||
|
||||
t1s->burst_timer = timer;
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
const ETHERNET10T1S_SETTINGS* getT1SSettingsFor(Network net) const {
|
||||
auto cfg = getStructurePointer<neovifire3t1slin_settings_t>();
|
||||
if(cfg == nullptr)
|
||||
return nullptr;
|
||||
|
||||
switch(net.getNetID()) {
|
||||
case Network::NetID::AE_01: return &(cfg->t1s1);
|
||||
case Network::NetID::AE_02: return &(cfg->t1s2);
|
||||
case Network::NetID::AE_03: return &(cfg->t1s3);
|
||||
case Network::NetID::AE_04: return &(cfg->t1s4);
|
||||
case Network::NetID::AE_05: return &(cfg->t1s5);
|
||||
case Network::NetID::AE_06: return &(cfg->t1s6);
|
||||
case Network::NetID::AE_07: return &(cfg->t1s7);
|
||||
case Network::NetID::AE_08: return &(cfg->t1s8);
|
||||
default:
|
||||
report(APIEvent::Type::ParameterOutOfRange, APIEvent::Severity::Error);
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
ETHERNET10T1S_SETTINGS* getMutableT1SSettingsFor(Network net) {
|
||||
auto cfg = getMutableStructurePointer<neovifire3t1slin_settings_t>();
|
||||
if(cfg == nullptr)
|
||||
return nullptr;
|
||||
|
||||
switch(net.getNetID()) {
|
||||
case Network::NetID::AE_01: return &(cfg->t1s1);
|
||||
case Network::NetID::AE_02: return &(cfg->t1s2);
|
||||
case Network::NetID::AE_03: return &(cfg->t1s3);
|
||||
case Network::NetID::AE_04: return &(cfg->t1s4);
|
||||
case Network::NetID::AE_05: return &(cfg->t1s5);
|
||||
case Network::NetID::AE_06: return &(cfg->t1s6);
|
||||
case Network::NetID::AE_07: return &(cfg->t1s7);
|
||||
case Network::NetID::AE_08: return &(cfg->t1s8);
|
||||
default:
|
||||
report(APIEvent::Type::ParameterOutOfRange, APIEvent::Severity::Error);
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
ICSNEO_UNALIGNED(const uint64_t*) getTerminationEnables() const override {
|
||||
auto cfg = getStructurePointer<neovifire3t1slin_settings_t>();
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ public:
|
|||
return BootloaderPipeline()
|
||||
.add<EnterBootloaderPhase>()
|
||||
.add<FlashPhase>(ChipID::RADA2B_ZCHIP, BootloaderCommunication::RAD)
|
||||
.add<EnterApplicationPhase>(ChipID::RADA2B_ZCHIP)
|
||||
// .add<ReconnectPhase>()
|
||||
.add<WaitPhase>(std::chrono::milliseconds(3000));
|
||||
}
|
||||
protected:
|
||||
|
|
|
|||
|
|
@ -45,7 +45,6 @@ public:
|
|||
return BootloaderPipeline()
|
||||
.add<EnterBootloaderPhase>()
|
||||
.add<FlashPhase>(ChipID::RADComet_ZYNQ, BootloaderCommunication::RAD)
|
||||
.add<EnterApplicationPhase>(ChipID::RADComet_ZYNQ)
|
||||
.add<WaitPhase>(std::chrono::milliseconds(3000))
|
||||
.add<ReconnectPhase>();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -69,7 +69,6 @@ public:
|
|||
return BootloaderPipeline()
|
||||
.add<EnterBootloaderPhase>()
|
||||
.add<FlashPhase>(ChipID::RADCOMET3_ZCHIP, BootloaderCommunication::RAD)
|
||||
.add<EnterApplicationPhase>(ChipID::RADCOMET3_ZCHIP)
|
||||
.add<WaitPhase>(std::chrono::milliseconds(5000))
|
||||
.add<ReconnectPhase>();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -113,149 +113,6 @@ public:
|
|||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
std::optional<bool> isT1SPLCAEnabledFor(Network net) const override {
|
||||
const ETHERNET10T1S_SETTINGS* t1s = getT1SSettingsFor(net);
|
||||
if(t1s == nullptr)
|
||||
return std::nullopt;
|
||||
|
||||
return std::make_optional<bool>((t1s->flags & ETHERNET10T1S_SETTINGS_FLAG_ENABLE_PLCA) != 0);
|
||||
}
|
||||
|
||||
bool setT1SPLCAFor(Network net, bool enable) override {
|
||||
ETHERNET10T1S_SETTINGS* t1s = getMutableT1SSettingsFor(net);
|
||||
if(t1s == nullptr)
|
||||
return false;
|
||||
|
||||
if(enable)
|
||||
t1s->flags |= ETHERNET10T1S_SETTINGS_FLAG_ENABLE_PLCA;
|
||||
else
|
||||
t1s->flags &= ~ETHERNET10T1S_SETTINGS_FLAG_ENABLE_PLCA;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
std::optional<uint8_t> getT1SLocalIDFor(Network net) const override {
|
||||
const ETHERNET10T1S_SETTINGS* t1s = getT1SSettingsFor(net);
|
||||
if(t1s == nullptr)
|
||||
return std::nullopt;
|
||||
|
||||
return std::make_optional(t1s->local_id);
|
||||
}
|
||||
|
||||
bool setT1SLocalIDFor(Network net, uint8_t id) override {
|
||||
ETHERNET10T1S_SETTINGS* t1s = getMutableT1SSettingsFor(net);
|
||||
if(t1s == nullptr)
|
||||
return false;
|
||||
|
||||
t1s->local_id = id;
|
||||
return true;
|
||||
}
|
||||
|
||||
std::optional<uint8_t> getT1SMaxNodesFor(Network net) const override {
|
||||
const ETHERNET10T1S_SETTINGS* t1s = getT1SSettingsFor(net);
|
||||
if(t1s == nullptr)
|
||||
return std::nullopt;
|
||||
|
||||
return std::make_optional(t1s->max_num_nodes);
|
||||
}
|
||||
|
||||
bool setT1SMaxNodesFor(Network net, uint8_t nodes) override {
|
||||
ETHERNET10T1S_SETTINGS* t1s = getMutableT1SSettingsFor(net);
|
||||
if(t1s == nullptr)
|
||||
return false;
|
||||
|
||||
t1s->max_num_nodes = nodes;
|
||||
return true;
|
||||
}
|
||||
|
||||
std::optional<uint8_t> getT1STxOppTimerFor(Network net) const override {
|
||||
const ETHERNET10T1S_SETTINGS* t1s = getT1SSettingsFor(net);
|
||||
if(t1s == nullptr)
|
||||
return std::nullopt;
|
||||
|
||||
return std::make_optional(t1s->to_timer);
|
||||
}
|
||||
|
||||
bool setT1STxOppTimerFor(Network net, uint8_t timer) override {
|
||||
ETHERNET10T1S_SETTINGS* t1s = getMutableT1SSettingsFor(net);
|
||||
if(t1s == nullptr)
|
||||
return false;
|
||||
|
||||
t1s->to_timer = timer;
|
||||
return true;
|
||||
}
|
||||
|
||||
std::optional<uint8_t> getT1SMaxBurstFor(Network net) const override {
|
||||
const ETHERNET10T1S_SETTINGS* t1s = getT1SSettingsFor(net);
|
||||
if(t1s == nullptr)
|
||||
return std::nullopt;
|
||||
|
||||
return std::make_optional(t1s->max_burst_count);
|
||||
}
|
||||
|
||||
bool setT1SMaxBurstFor(Network net, uint8_t burst) override {
|
||||
ETHERNET10T1S_SETTINGS* t1s = getMutableT1SSettingsFor(net);
|
||||
if(t1s == nullptr)
|
||||
return false;
|
||||
|
||||
t1s->max_burst_count = burst;
|
||||
return true;
|
||||
}
|
||||
|
||||
std::optional<uint8_t> getT1SBurstTimerFor(Network net) const override {
|
||||
const ETHERNET10T1S_SETTINGS* t1s = getT1SSettingsFor(net);
|
||||
if(t1s == nullptr)
|
||||
return std::nullopt;
|
||||
|
||||
return std::make_optional(t1s->burst_timer);
|
||||
}
|
||||
|
||||
bool setT1SBurstTimerFor(Network net, uint8_t timer) override {
|
||||
ETHERNET10T1S_SETTINGS* t1s = getMutableT1SSettingsFor(net);
|
||||
if(t1s == nullptr)
|
||||
return false;
|
||||
|
||||
t1s->burst_timer = timer;
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
const ETHERNET10T1S_SETTINGS* getT1SSettingsFor(Network net) const {
|
||||
auto cfg = getStructurePointer<radcomet3_settings_t>();
|
||||
if(cfg == nullptr)
|
||||
return nullptr;
|
||||
|
||||
switch(net.getNetID()) {
|
||||
case Network::NetID::AE_02: return &(cfg->t1s1);
|
||||
case Network::NetID::AE_03: return &(cfg->t1s2);
|
||||
case Network::NetID::AE_04: return &(cfg->t1s3);
|
||||
case Network::NetID::AE_05: return &(cfg->t1s4);
|
||||
case Network::NetID::AE_06: return &(cfg->t1s5);
|
||||
case Network::NetID::AE_07: return &(cfg->t1s6);
|
||||
default:
|
||||
report(APIEvent::Type::ParameterOutOfRange, APIEvent::Severity::Error);
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
ETHERNET10T1S_SETTINGS* getMutableT1SSettingsFor(Network net) {
|
||||
auto cfg = getMutableStructurePointer<radcomet3_settings_t>();
|
||||
if(cfg == nullptr)
|
||||
return nullptr;
|
||||
|
||||
switch(net.getNetID()) {
|
||||
case Network::NetID::AE_02: return &(cfg->t1s1);
|
||||
case Network::NetID::AE_03: return &(cfg->t1s2);
|
||||
case Network::NetID::AE_04: return &(cfg->t1s3);
|
||||
case Network::NetID::AE_05: return &(cfg->t1s4);
|
||||
case Network::NetID::AE_06: return &(cfg->t1s5);
|
||||
case Network::NetID::AE_07: return &(cfg->t1s6);
|
||||
default:
|
||||
report(APIEvent::Type::ParameterOutOfRange, APIEvent::Severity::Error);
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -80,7 +80,6 @@ public:
|
|||
return BootloaderPipeline()
|
||||
.add<EnterBootloaderPhase>()
|
||||
.add<FlashPhase>(ChipID::RADGalaxy_ZYNQ, BootloaderCommunication::RAD)
|
||||
.add<EnterApplicationPhase>(ChipID::RADGalaxy_ZYNQ)
|
||||
.add<ReconnectPhase>()
|
||||
.add<WaitPhase>(std::chrono::milliseconds(3000));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -87,10 +87,9 @@ public:
|
|||
return BootloaderPipeline()
|
||||
.add<EnterBootloaderPhase>()
|
||||
.add<FlashPhase>(ChipID::RAD_GALAXY_2_ZMPCHIP_ID, BootloaderCommunication::RAD)
|
||||
.add<EnterApplicationPhase>(ChipID::RAD_GALAXY_2_ZMPCHIP_ID)
|
||||
.add<ReconnectPhase>()
|
||||
.add<FlashPhase>(ChipID::RADGALAXY2_SYSMON_CHIP, BootloaderCommunication::RADGalaxy2Peripheral)
|
||||
.add<EnterApplicationPhase>(ChipID::RADGALAXY2_SYSMON_CHIP)
|
||||
.add<EnterApplicationPhase>(ChipID::RAD_GALAXY_2_ZMPCHIP_ID)
|
||||
.add<ReconnectPhase>()
|
||||
.add<WaitPhase>(std::chrono::milliseconds(3000));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -93,13 +93,11 @@ public:
|
|||
if(com->driver->isEthernet()) {
|
||||
return BootloaderPipeline()
|
||||
.add<FlashPhase>(ChipID::RADGigastar_ZYNQ, BootloaderCommunication::RAD)
|
||||
.add<EnterApplicationPhase>(ChipID::RADGigastar_ZYNQ)
|
||||
.add<WaitPhase>(std::chrono::milliseconds(3000))
|
||||
.add<ReconnectPhase>();
|
||||
}
|
||||
return BootloaderPipeline()
|
||||
.add<FlashPhase>(ChipID::RADGigastar_USBZ_ZYNQ, BootloaderCommunication::RAD)
|
||||
.add<EnterApplicationPhase>(ChipID::RADGigastar_USBZ_ZYNQ)
|
||||
.add<WaitPhase>(std::chrono::milliseconds(3000))
|
||||
.add<ReconnectPhase>();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -249,153 +249,6 @@ namespace icsneo
|
|||
}
|
||||
}
|
||||
|
||||
std::optional<bool> isT1SPLCAEnabledFor(Network net) const override {
|
||||
const ETHERNET10T1S_SETTINGS* t1s = getT1SSettingsFor(net);
|
||||
if(t1s == nullptr)
|
||||
return std::nullopt;
|
||||
|
||||
return std::make_optional<bool>((t1s->flags & ETHERNET10T1S_SETTINGS_FLAG_ENABLE_PLCA) != 0);
|
||||
}
|
||||
|
||||
bool setT1SPLCAFor(Network net, bool enable) override {
|
||||
ETHERNET10T1S_SETTINGS* t1s = getMutableT1SSettingsFor(net);
|
||||
if(t1s == nullptr)
|
||||
return false;
|
||||
|
||||
if(enable)
|
||||
t1s->flags |= ETHERNET10T1S_SETTINGS_FLAG_ENABLE_PLCA;
|
||||
else
|
||||
t1s->flags &= ~ETHERNET10T1S_SETTINGS_FLAG_ENABLE_PLCA;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
std::optional<uint8_t> getT1SLocalIDFor(Network net) const override {
|
||||
const ETHERNET10T1S_SETTINGS* t1s = getT1SSettingsFor(net);
|
||||
if(t1s == nullptr)
|
||||
return std::nullopt;
|
||||
|
||||
return std::make_optional(t1s->local_id);
|
||||
}
|
||||
|
||||
bool setT1SLocalIDFor(Network net, uint8_t id) override {
|
||||
ETHERNET10T1S_SETTINGS* t1s = getMutableT1SSettingsFor(net);
|
||||
if(t1s == nullptr)
|
||||
return false;
|
||||
|
||||
t1s->local_id = id;
|
||||
return true;
|
||||
}
|
||||
|
||||
std::optional<uint8_t> getT1SMaxNodesFor(Network net) const override {
|
||||
const ETHERNET10T1S_SETTINGS* t1s = getT1SSettingsFor(net);
|
||||
if(t1s == nullptr)
|
||||
return std::nullopt;
|
||||
|
||||
return std::make_optional(t1s->max_num_nodes);
|
||||
}
|
||||
|
||||
bool setT1SMaxNodesFor(Network net, uint8_t nodes) override {
|
||||
ETHERNET10T1S_SETTINGS* t1s = getMutableT1SSettingsFor(net);
|
||||
if(t1s == nullptr)
|
||||
return false;
|
||||
|
||||
t1s->max_num_nodes = nodes;
|
||||
return true;
|
||||
}
|
||||
|
||||
std::optional<uint8_t> getT1STxOppTimerFor(Network net) const override {
|
||||
const ETHERNET10T1S_SETTINGS* t1s = getT1SSettingsFor(net);
|
||||
if(t1s == nullptr)
|
||||
return std::nullopt;
|
||||
|
||||
return std::make_optional(t1s->to_timer);
|
||||
}
|
||||
|
||||
bool setT1STxOppTimerFor(Network net, uint8_t timer) override {
|
||||
ETHERNET10T1S_SETTINGS* t1s = getMutableT1SSettingsFor(net);
|
||||
if(t1s == nullptr)
|
||||
return false;
|
||||
|
||||
t1s->to_timer = timer;
|
||||
return true;
|
||||
}
|
||||
|
||||
std::optional<uint8_t> getT1SMaxBurstFor(Network net) const override {
|
||||
const ETHERNET10T1S_SETTINGS* t1s = getT1SSettingsFor(net);
|
||||
if(t1s == nullptr)
|
||||
return std::nullopt;
|
||||
|
||||
return std::make_optional(t1s->max_burst_count);
|
||||
}
|
||||
|
||||
bool setT1SMaxBurstFor(Network net, uint8_t burst) override {
|
||||
ETHERNET10T1S_SETTINGS* t1s = getMutableT1SSettingsFor(net);
|
||||
if(t1s == nullptr)
|
||||
return false;
|
||||
|
||||
t1s->max_burst_count = burst;
|
||||
return true;
|
||||
}
|
||||
|
||||
std::optional<uint8_t> getT1SBurstTimerFor(Network net) const override {
|
||||
const ETHERNET10T1S_SETTINGS* t1s = getT1SSettingsFor(net);
|
||||
if(t1s == nullptr)
|
||||
return std::nullopt;
|
||||
|
||||
return std::make_optional(t1s->burst_timer);
|
||||
}
|
||||
|
||||
bool setT1SBurstTimerFor(Network net, uint8_t timer) override {
|
||||
ETHERNET10T1S_SETTINGS* t1s = getMutableT1SSettingsFor(net);
|
||||
if(t1s == nullptr)
|
||||
return false;
|
||||
|
||||
t1s->burst_timer = timer;
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
const ETHERNET10T1S_SETTINGS* getT1SSettingsFor(Network net) const {
|
||||
auto cfg = getStructurePointer<radgigastar2_settings_t>();
|
||||
if(cfg == nullptr)
|
||||
return nullptr;
|
||||
|
||||
switch(net.getNetID()) {
|
||||
case Network::NetID::AE_03: return &(cfg->t1s1);
|
||||
case Network::NetID::AE_04: return &(cfg->t1s2);
|
||||
case Network::NetID::AE_05: return &(cfg->t1s3);
|
||||
case Network::NetID::AE_06: return &(cfg->t1s4);
|
||||
case Network::NetID::AE_07: return &(cfg->t1s5);
|
||||
case Network::NetID::AE_08: return &(cfg->t1s6);
|
||||
case Network::NetID::AE_09: return &(cfg->t1s7);
|
||||
case Network::NetID::AE_10: return &(cfg->t1s8);
|
||||
default:
|
||||
report(APIEvent::Type::ParameterOutOfRange, APIEvent::Severity::Error);
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
ETHERNET10T1S_SETTINGS* getMutableT1SSettingsFor(Network net) {
|
||||
auto cfg = getMutableStructurePointer<radgigastar2_settings_t>();
|
||||
if(cfg == nullptr)
|
||||
return nullptr;
|
||||
|
||||
switch(net.getNetID()) {
|
||||
case Network::NetID::AE_03: return &(cfg->t1s1);
|
||||
case Network::NetID::AE_04: return &(cfg->t1s2);
|
||||
case Network::NetID::AE_05: return &(cfg->t1s3);
|
||||
case Network::NetID::AE_06: return &(cfg->t1s4);
|
||||
case Network::NetID::AE_07: return &(cfg->t1s5);
|
||||
case Network::NetID::AE_08: return &(cfg->t1s6);
|
||||
case Network::NetID::AE_09: return &(cfg->t1s7);
|
||||
case Network::NetID::AE_10: return &(cfg->t1s8);
|
||||
default:
|
||||
report(APIEvent::Type::ParameterOutOfRange, APIEvent::Severity::Error);
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
ICSNEO_UNALIGNED(const uint64_t *)
|
||||
getTerminationEnables() const override
|
||||
|
|
|
|||
|
|
@ -47,169 +47,6 @@ static_assert(sizeof(radmoont1s_settings_t) == 160, "RADMoonT1S settings size mi
|
|||
class RADMoonT1SSettings : public IDeviceSettings {
|
||||
public:
|
||||
RADMoonT1SSettings(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(radmoont1s_settings_t)) {}
|
||||
|
||||
std::optional<bool> isT1SPLCAEnabledFor(Network net) const override {
|
||||
const ETHERNET10T1S_SETTINGS* t1s = getT1SSettingsFor(net);
|
||||
if(t1s == nullptr)
|
||||
return std::nullopt;
|
||||
|
||||
return std::make_optional<bool>((t1s->flags & ETHERNET10T1S_SETTINGS_FLAG_ENABLE_PLCA) != 0);
|
||||
}
|
||||
|
||||
bool setT1SPLCAFor(Network net, bool enable) override {
|
||||
ETHERNET10T1S_SETTINGS* t1s = getMutableT1SSettingsFor(net);
|
||||
if(t1s == nullptr)
|
||||
return false;
|
||||
|
||||
if(enable)
|
||||
t1s->flags |= ETHERNET10T1S_SETTINGS_FLAG_ENABLE_PLCA;
|
||||
else
|
||||
t1s->flags &= ~ETHERNET10T1S_SETTINGS_FLAG_ENABLE_PLCA;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
std::optional<uint8_t> getT1SLocalIDFor(Network net) const override {
|
||||
const ETHERNET10T1S_SETTINGS* t1s = getT1SSettingsFor(net);
|
||||
if(t1s == nullptr)
|
||||
return std::nullopt;
|
||||
|
||||
return std::make_optional(t1s->local_id);
|
||||
}
|
||||
|
||||
bool setT1SLocalIDFor(Network net, uint8_t id) override {
|
||||
ETHERNET10T1S_SETTINGS* t1s = getMutableT1SSettingsFor(net);
|
||||
if(t1s == nullptr)
|
||||
return false;
|
||||
|
||||
t1s->local_id = id;
|
||||
return true;
|
||||
}
|
||||
|
||||
std::optional<uint8_t> getT1SMaxNodesFor(Network net) const override {
|
||||
const ETHERNET10T1S_SETTINGS* t1s = getT1SSettingsFor(net);
|
||||
if(t1s == nullptr)
|
||||
return std::nullopt;
|
||||
|
||||
return std::make_optional(t1s->max_num_nodes);
|
||||
}
|
||||
|
||||
bool setT1SMaxNodesFor(Network net, uint8_t nodes) override {
|
||||
ETHERNET10T1S_SETTINGS* t1s = getMutableT1SSettingsFor(net);
|
||||
if(t1s == nullptr)
|
||||
return false;
|
||||
|
||||
t1s->max_num_nodes = nodes;
|
||||
return true;
|
||||
}
|
||||
|
||||
std::optional<uint8_t> getT1STxOppTimerFor(Network net) const override {
|
||||
const ETHERNET10T1S_SETTINGS* t1s = getT1SSettingsFor(net);
|
||||
if(t1s == nullptr)
|
||||
return std::nullopt;
|
||||
|
||||
return std::make_optional(t1s->to_timer);
|
||||
}
|
||||
|
||||
bool setT1STxOppTimerFor(Network net, uint8_t timer) override {
|
||||
ETHERNET10T1S_SETTINGS* t1s = getMutableT1SSettingsFor(net);
|
||||
if(t1s == nullptr)
|
||||
return false;
|
||||
|
||||
t1s->to_timer = timer;
|
||||
return true;
|
||||
}
|
||||
|
||||
std::optional<uint8_t> getT1SMaxBurstFor(Network net) const override {
|
||||
const ETHERNET10T1S_SETTINGS* t1s = getT1SSettingsFor(net);
|
||||
if(t1s == nullptr)
|
||||
return std::nullopt;
|
||||
|
||||
return std::make_optional(t1s->max_burst_count);
|
||||
}
|
||||
|
||||
bool setT1SMaxBurstFor(Network net, uint8_t burst) override {
|
||||
ETHERNET10T1S_SETTINGS* t1s = getMutableT1SSettingsFor(net);
|
||||
if(t1s == nullptr)
|
||||
return false;
|
||||
|
||||
t1s->max_burst_count = burst;
|
||||
return true;
|
||||
}
|
||||
|
||||
std::optional<uint8_t> getT1SBurstTimerFor(Network net) const override {
|
||||
const ETHERNET10T1S_SETTINGS* t1s = getT1SSettingsFor(net);
|
||||
if(t1s == nullptr)
|
||||
return std::nullopt;
|
||||
|
||||
return std::make_optional(t1s->burst_timer);
|
||||
}
|
||||
|
||||
bool setT1SBurstTimerFor(Network net, uint8_t timer) override {
|
||||
ETHERNET10T1S_SETTINGS* t1s = getMutableT1SSettingsFor(net);
|
||||
if(t1s == nullptr)
|
||||
return false;
|
||||
|
||||
t1s->burst_timer = timer;
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
const ETHERNET10T1S_SETTINGS* getT1SSettingsFor(Network net) const {
|
||||
auto cfg = getStructurePointer<radmoont1s_settings_t>();
|
||||
if(cfg == nullptr)
|
||||
return nullptr;
|
||||
|
||||
switch(net.getNetID()) {
|
||||
case Network::NetID::AE_01:
|
||||
return &(cfg->t1s);
|
||||
default:
|
||||
report(APIEvent::Type::ParameterOutOfRange, APIEvent::Severity::Error);
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
ETHERNET10T1S_SETTINGS* getMutableT1SSettingsFor(Network net) {
|
||||
auto cfg = getMutableStructurePointer<radmoont1s_settings_t>();
|
||||
if(cfg == nullptr)
|
||||
return nullptr;
|
||||
|
||||
switch(net.getNetID()) {
|
||||
case Network::NetID::AE_01:
|
||||
return &(cfg->t1s);
|
||||
default:
|
||||
report(APIEvent::Type::ParameterOutOfRange, APIEvent::Severity::Error);
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
const ETHERNET10T1S_SETTINGS_EXT* getT1SSettingsExtFor(Network net) const {
|
||||
auto cfg = getStructurePointer<radmoont1s_settings_t>();
|
||||
if(cfg == nullptr)
|
||||
return nullptr;
|
||||
|
||||
switch(net.getNetID()) {
|
||||
case Network::NetID::AE_01:
|
||||
return &(cfg->t1sExt);
|
||||
default:
|
||||
report(APIEvent::Type::ParameterOutOfRange, APIEvent::Severity::Error);
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
ETHERNET10T1S_SETTINGS_EXT* getMutableT1SSettingsExtFor(Network net) {
|
||||
auto cfg = getMutableStructurePointer<radmoont1s_settings_t>();
|
||||
if(cfg == nullptr)
|
||||
return nullptr;
|
||||
|
||||
switch(net.getNetID()) {
|
||||
case Network::NetID::AE_01:
|
||||
return &(cfg->t1sExt);
|
||||
default:
|
||||
report(APIEvent::Type::ParameterOutOfRange, APIEvent::Severity::Error);
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,24 +18,27 @@ class Servd : public Driver {
|
|||
public:
|
||||
static void Find(std::vector<FoundDevice>& foundDevices);
|
||||
static bool Enabled();
|
||||
Servd(const device_eventhandler_t& err, neodevice_t& forDevice, const Address& address);
|
||||
Servd(const device_eventhandler_t& err, neodevice_t& forDevice, const std::unordered_set<std::string>& availableDrivers);
|
||||
~Servd() override;
|
||||
bool open() override;
|
||||
bool isOpen() override;
|
||||
bool close() override;
|
||||
bool faa(const std::string& key, int32_t inc, int32_t& orig);
|
||||
bool enableCommunication(bool enable, bool& sendMsg) override;
|
||||
driver_finder_t getFinder() override { return Servd::Find; }
|
||||
|
||||
private:
|
||||
void read();
|
||||
void write();
|
||||
void alive();
|
||||
void read(Address&& address);
|
||||
void write(Address&& address);
|
||||
neodevice_t& device;
|
||||
std::thread aliveThread; // makes sure the client and server are healthy
|
||||
std::thread writeThread;
|
||||
std::thread readThread;
|
||||
Socket messageSocket;
|
||||
bool opened = false;
|
||||
bool comEnabled = false;
|
||||
std::unique_ptr<Socket> dataSocket;
|
||||
std::string driver;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,223 +1,210 @@
|
|||
#ifndef __SOCKET_H_
|
||||
#define __SOCKET_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
#ifdef _WIN32
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#define NOMINMAX
|
||||
#include <windows.h>
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#else
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <poll.h>
|
||||
#endif
|
||||
|
||||
#include <string>
|
||||
#include <chrono>
|
||||
|
||||
namespace icsneo {
|
||||
|
||||
#ifdef _WIN32
|
||||
class WSA {
|
||||
public:
|
||||
WSA() {
|
||||
// TODO: add error checking
|
||||
WSAStartup(MAKEWORD(2, 2), &wsaData);
|
||||
}
|
||||
~WSA() {
|
||||
WSACleanup();
|
||||
}
|
||||
private:
|
||||
WSADATA wsaData;
|
||||
};
|
||||
#endif
|
||||
|
||||
class Address {
|
||||
public:
|
||||
Address() = default;
|
||||
Address(const char* ip, uint16_t port)
|
||||
: _ip(ip), _port(port)
|
||||
{
|
||||
_sockaddr.sin_family = AF_INET;
|
||||
inet_pton(AF_INET, ip, &_sockaddr.sin_addr);
|
||||
_sockaddr.sin_port = htons(port);
|
||||
}
|
||||
Address(sockaddr_in& sockaddr)
|
||||
: _sockaddr(sockaddr)
|
||||
{
|
||||
char cip[INET_ADDRSTRLEN];
|
||||
inet_ntop(AF_INET, &sockaddr.sin_addr, cip, sizeof(cip));
|
||||
_ip = cip;
|
||||
_port = ntohs(sockaddr.sin_port);
|
||||
}
|
||||
const std::string& ip() const { return _ip; }
|
||||
const uint16_t& port() const { return _port; }
|
||||
const sockaddr_in& sockaddr() const { return _sockaddr; }
|
||||
private:
|
||||
std::string _ip;
|
||||
uint16_t _port;
|
||||
sockaddr_in _sockaddr;
|
||||
};
|
||||
|
||||
class Socket {
|
||||
public:
|
||||
#ifdef _WIN32
|
||||
using SocketHandleType = SOCKET;
|
||||
#else
|
||||
using SocketHandleType = int;
|
||||
#endif
|
||||
|
||||
template<class... Args>
|
||||
Socket(Args&&... args) {
|
||||
#ifdef _WIN32
|
||||
static WSA wsa;
|
||||
#endif
|
||||
mFD = socket(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
~Socket() {
|
||||
#ifdef _WIN32
|
||||
closesocket(mFD);
|
||||
#else
|
||||
close(mFD);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool set_reuse(bool value) {
|
||||
int ival = value;
|
||||
return ::setsockopt(mFD, SOL_SOCKET, SO_REUSEADDR, (const char*)&ival, sizeof(ival)) != -1;
|
||||
}
|
||||
|
||||
bool set_nonblocking() {
|
||||
#ifdef _WIN32
|
||||
u_long nonblock = 1;
|
||||
return ioctlsocket(mFD, FIONBIO, &nonblock) != SOCKET_ERROR;
|
||||
#else
|
||||
return fcntl(mFD, F_SETFL, fcntl(mFD, F_GETFL, 0) | O_NONBLOCK) != -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool connect(const Address& to) {
|
||||
return ::connect(mFD, (sockaddr*)&to.sockaddr(), sizeof(sockaddr_in)) != -1;
|
||||
}
|
||||
|
||||
bool bind(const Address& at) {
|
||||
return ::bind(mFD, (sockaddr*)&at.sockaddr(), sizeof(sockaddr_in)) != -1;
|
||||
}
|
||||
|
||||
bool poll(const std::chrono::milliseconds& timeout, bool& in) {
|
||||
#ifdef _WIN32
|
||||
WSAPOLLFD pfd;
|
||||
pfd.fd = mFD;
|
||||
pfd.events = POLLIN;
|
||||
if (::WSAPoll(&pfd, 1, static_cast<int>(timeout.count())) == SOCKET_ERROR) {
|
||||
return false;
|
||||
}
|
||||
in = pfd.revents & POLLIN;
|
||||
return true;
|
||||
#else
|
||||
struct pollfd pfd;
|
||||
pfd.fd = mFD;
|
||||
pfd.events = POLLIN;
|
||||
pfd.revents = 0;
|
||||
if (::poll(&pfd, 1, static_cast<int>(timeout.count())) == -1) {
|
||||
return false;
|
||||
}
|
||||
in = pfd.revents & POLLIN;
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool sendto(const void* buffer, size_t size, const Address& to) {
|
||||
size_t totalSent = 0;
|
||||
do {
|
||||
const auto sent = ::sendto(mFD, (const char*)buffer, (int)size, 0, (sockaddr*)&to.sockaddr(), sizeof(sockaddr_in));
|
||||
if (sent == -1) {
|
||||
return false;
|
||||
}
|
||||
totalSent += sent;
|
||||
} while (totalSent < size);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool send(const void* buffer, size_t size) {
|
||||
auto sent = ::send(mFD, (const char*)buffer, (int)size, 0);
|
||||
if(sent == -1) {
|
||||
return false;
|
||||
}
|
||||
return (size_t)sent == size;
|
||||
}
|
||||
|
||||
bool recvfrom(void* buffer, size_t& size, Address& from) {
|
||||
sockaddr_in addr;
|
||||
socklen_t addLen = sizeof(addr);
|
||||
const auto read = ::recvfrom(mFD, (char*)buffer, (int)size, 0, (sockaddr*)&addr, &addLen);
|
||||
if (read == -1) {
|
||||
return false;
|
||||
}
|
||||
size = read;
|
||||
from = Address(addr);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool recv(void* buffer, size_t& size) {
|
||||
const auto read = ::recv(mFD, (char*)buffer, (int)size, 0);
|
||||
if (read == -1) {
|
||||
return false;
|
||||
}
|
||||
size = read;
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename REQ, typename RES>
|
||||
bool transceive(REQ&& request, RES&& response, const std::chrono::milliseconds& timeout) {
|
||||
if(!send(request.data(), request.size())) {
|
||||
return false;
|
||||
}
|
||||
bool hasData;
|
||||
if(!poll(timeout, hasData)) {
|
||||
return false;
|
||||
}
|
||||
if(!hasData) {
|
||||
return false;
|
||||
}
|
||||
size_t responseSize = response.size();
|
||||
if(!recv(response.data(), responseSize)) {
|
||||
return false;
|
||||
}
|
||||
response.resize(responseSize);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool address(Address& address) const {
|
||||
sockaddr_in sin;
|
||||
socklen_t len = sizeof(sin);
|
||||
getsockname(mFD, (sockaddr*)&sin, &len);
|
||||
address = Address(sin);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool join_multicast(const std::string& interfaceIP, const std::string& multicastIP) {
|
||||
ip_mreq mreq;
|
||||
inet_pton(AF_INET, interfaceIP.c_str(), &mreq.imr_interface);
|
||||
inet_pton(AF_INET, multicastIP.c_str(), &mreq.imr_multiaddr);
|
||||
return setsockopt(mFD, IPPROTO_IP, IP_ADD_MEMBERSHIP, (const char*)&mreq, sizeof(mreq)) == 0;
|
||||
}
|
||||
|
||||
operator bool() const { return mFD != -1; }
|
||||
operator SocketHandleType() const { return mFD; }
|
||||
private:
|
||||
SocketHandleType mFD;
|
||||
};
|
||||
|
||||
} // namespace icsneo
|
||||
|
||||
#endif // __cplusplus
|
||||
|
||||
#endif // __SOCKET_H_
|
||||
#ifndef __SOCKET_H_
|
||||
#define __SOCKET_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
#ifdef _WIN32
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#define NOMINMAX
|
||||
#include <windows.h>
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#else
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <poll.h>
|
||||
#endif
|
||||
|
||||
#include <string>
|
||||
#include <chrono>
|
||||
|
||||
namespace icsneo {
|
||||
|
||||
#ifdef _WIN32
|
||||
class WSA {
|
||||
public:
|
||||
WSA() {
|
||||
// TODO: add error checking
|
||||
WSAStartup(MAKEWORD(2, 2), &wsaData);
|
||||
}
|
||||
~WSA() {
|
||||
WSACleanup();
|
||||
}
|
||||
private:
|
||||
WSADATA wsaData;
|
||||
};
|
||||
#endif
|
||||
|
||||
class Address {
|
||||
public:
|
||||
Address() = default;
|
||||
Address(const char* ip, uint16_t port)
|
||||
: _ip(ip), _port(port)
|
||||
{
|
||||
_sockaddr.sin_family = AF_INET;
|
||||
inet_pton(AF_INET, ip, &_sockaddr.sin_addr);
|
||||
_sockaddr.sin_port = htons(port);
|
||||
}
|
||||
Address(sockaddr_in& sockaddr)
|
||||
: _sockaddr(sockaddr)
|
||||
{
|
||||
char cip[INET_ADDRSTRLEN];
|
||||
inet_ntop(AF_INET, &sockaddr.sin_addr, cip, sizeof(cip));
|
||||
_ip = cip;
|
||||
_port = ntohs(sockaddr.sin_port);
|
||||
}
|
||||
const std::string& ip() const { return _ip; }
|
||||
const uint16_t& port() const { return _port; }
|
||||
const sockaddr_in& sockaddr() const { return _sockaddr; }
|
||||
private:
|
||||
std::string _ip;
|
||||
uint16_t _port;
|
||||
sockaddr_in _sockaddr;
|
||||
};
|
||||
|
||||
class Socket {
|
||||
public:
|
||||
#ifdef _WIN32
|
||||
using SocketHandleType = SOCKET;
|
||||
#else
|
||||
using SocketHandleType = int;
|
||||
#endif
|
||||
|
||||
Socket() {
|
||||
#ifdef _WIN32
|
||||
static WSA wsa;
|
||||
#endif
|
||||
mFD = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
}
|
||||
|
||||
~Socket() {
|
||||
#ifdef _WIN32
|
||||
closesocket(mFD);
|
||||
#else
|
||||
close(mFD);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool set_reuse(bool value) {
|
||||
int ival = value;
|
||||
return ::setsockopt(mFD, SOL_SOCKET, SO_REUSEADDR, (const char*)&ival, sizeof(ival)) != -1;
|
||||
}
|
||||
|
||||
bool set_nonblocking() {
|
||||
#ifdef _WIN32
|
||||
u_long nonblock = 1;
|
||||
return ioctlsocket(mFD, FIONBIO, &nonblock) != SOCKET_ERROR;
|
||||
#else
|
||||
return fcntl(mFD, F_SETFL, fcntl(mFD, F_GETFL, 0) | O_NONBLOCK) != -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool bind(const Address& at) {
|
||||
return ::bind(mFD, (sockaddr*)&at.sockaddr(), sizeof(sockaddr_in)) != -1;
|
||||
}
|
||||
|
||||
bool poll(const std::chrono::milliseconds& timeout, bool& in) {
|
||||
#ifdef _WIN32
|
||||
WSAPOLLFD pfd;
|
||||
pfd.fd = mFD;
|
||||
pfd.events = POLLIN;
|
||||
if (::WSAPoll(&pfd, 1, static_cast<int>(timeout.count())) == SOCKET_ERROR) {
|
||||
return false;
|
||||
}
|
||||
in = pfd.revents & POLLIN;
|
||||
return true;
|
||||
#else
|
||||
struct pollfd pfd;
|
||||
pfd.fd = mFD;
|
||||
pfd.events = POLLIN;
|
||||
pfd.revents = 0;
|
||||
if (::poll(&pfd, 1, static_cast<int>(timeout.count())) == -1) {
|
||||
return false;
|
||||
}
|
||||
in = pfd.revents & POLLIN;
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool sendto(const void* buffer, size_t size, const Address& to) {
|
||||
size_t totalSent = 0;
|
||||
do {
|
||||
const auto sent = ::sendto(mFD, (const char*)buffer, (int)size, 0, (sockaddr*)&to.sockaddr(), sizeof(sockaddr_in));
|
||||
if (sent == -1) {
|
||||
return false;
|
||||
}
|
||||
totalSent += sent;
|
||||
} while (totalSent < size);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool recvfrom(void* buffer, size_t& size, Address& from) {
|
||||
sockaddr_in addr;
|
||||
socklen_t addLen = sizeof(addr);
|
||||
const auto read = ::recvfrom(mFD, (char*)buffer, (int)size, 0, (sockaddr*)&addr, &addLen);
|
||||
if (read == -1) {
|
||||
return false;
|
||||
}
|
||||
size = read;
|
||||
from = Address(addr);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool recv(void* buffer, size_t& size) {
|
||||
const auto read = ::recv(mFD, (char*)buffer, (int)size, 0);
|
||||
if (read == -1) {
|
||||
return false;
|
||||
}
|
||||
size = read;
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename REQ, typename RES>
|
||||
bool transceive(const Address& to, REQ&& request, RES&& response, const std::chrono::milliseconds& timeout) {
|
||||
if(!sendto(request.data(), request.size(), to)) {
|
||||
return false;
|
||||
}
|
||||
bool hasData;
|
||||
if(!poll(timeout, hasData)) {
|
||||
return false;
|
||||
}
|
||||
if(!hasData) {
|
||||
return false;
|
||||
}
|
||||
size_t responseSize = response.size();
|
||||
if(!recv(response.data(), responseSize)) {
|
||||
return false;
|
||||
}
|
||||
response.resize(responseSize);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool address(Address& address) const {
|
||||
sockaddr_in sin;
|
||||
socklen_t len = sizeof(sin);
|
||||
getsockname(mFD, (sockaddr*)&sin, &len);
|
||||
address = Address(sin);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool join_multicast(const std::string& interfaceIP, const std::string& multicastIP) {
|
||||
ip_mreq mreq;
|
||||
inet_pton(AF_INET, interfaceIP.c_str(), &mreq.imr_interface);
|
||||
inet_pton(AF_INET, multicastIP.c_str(), &mreq.imr_multiaddr);
|
||||
return setsockopt(mFD, IPPROTO_IP, IP_ADD_MEMBERSHIP, (const char*)&mreq, sizeof(mreq)) == 0;
|
||||
}
|
||||
|
||||
operator bool() const { return mFD != -1; }
|
||||
operator SocketHandleType() const { return mFD; }
|
||||
private:
|
||||
SocketHandleType mFD;
|
||||
};
|
||||
|
||||
} // namespace icsneo
|
||||
|
||||
#endif // __cplusplus
|
||||
|
||||
#endif // __SOCKET_H_
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
using namespace icsneo;
|
||||
|
||||
#define SERVD_VERSION 2
|
||||
#define SERVD_VERSION 1
|
||||
|
||||
static const Address SERVD_ADDRESS = Address("127.0.0.1", 26741);
|
||||
static const std::string SERVD_VERSION_STR = std::to_string(SERVD_VERSION);
|
||||
|
|
@ -41,17 +41,20 @@ std::vector<std::string> split(const std::string_view& str, char delim = ' ') {
|
|||
}
|
||||
|
||||
void Servd::Find(std::vector<FoundDevice>& found) {
|
||||
Socket socket(AF_INET, SOCK_DGRAM, 0);
|
||||
socket.connect(SERVD_ADDRESS);
|
||||
Socket socket;
|
||||
if(!socket.set_nonblocking()) {
|
||||
EventManager::GetInstance().add(APIEvent::Type::ServdNonblockError, APIEvent::Severity::Error);
|
||||
return;
|
||||
}
|
||||
if(!socket.bind(Address("127.0.0.1", 0))) {
|
||||
EventManager::GetInstance().add(APIEvent::Type::ServdBindError, APIEvent::Severity::Error);
|
||||
return;
|
||||
}
|
||||
std::string response;
|
||||
|
||||
response.resize(512);
|
||||
const std::string version_request = SERVD_VERSION_STR + " version";
|
||||
if(!socket.transceive(version_request, response, std::chrono::milliseconds(5000))) {
|
||||
if(!socket.transceive(SERVD_ADDRESS, version_request, response, std::chrono::milliseconds(5000))) {
|
||||
EventManager::GetInstance().add(APIEvent::Type::ServdTransceiveError, APIEvent::Severity::Error);
|
||||
return;
|
||||
}
|
||||
|
|
@ -63,39 +66,46 @@ void Servd::Find(std::vector<FoundDevice>& found) {
|
|||
|
||||
response.resize(512);
|
||||
const std::string find_request = SERVD_VERSION_STR + " find";
|
||||
if(!socket.transceive(find_request, response, std::chrono::milliseconds(5000))) {
|
||||
if(!socket.transceive(SERVD_ADDRESS, find_request, response, std::chrono::milliseconds(5000))) {
|
||||
EventManager::GetInstance().add(APIEvent::Type::ServdTransceiveError, APIEvent::Severity::Error);
|
||||
return;
|
||||
}
|
||||
const auto lines = split(response, '\n');
|
||||
for(auto&& line : lines) {
|
||||
const auto cols = split(line, ' ');
|
||||
if(cols.size() < 3) {
|
||||
if(cols.size() < 2) {
|
||||
EventManager::GetInstance().add(APIEvent::Type::ServdInvalidResponseError, APIEvent::Severity::Error);
|
||||
continue;
|
||||
}
|
||||
const auto& serial = cols[0];
|
||||
const auto& ip = cols[1];
|
||||
uint16_t port = 0;
|
||||
try {
|
||||
port = static_cast<uint16_t>(std::stoi(cols[2]));
|
||||
} catch (const std::exception&) {
|
||||
EventManager::GetInstance().add(APIEvent::Type::ServdInvalidResponseError, APIEvent::Severity::Error);
|
||||
continue;
|
||||
std::unordered_set<std::string> drivers;
|
||||
for (size_t i = 1; i < cols.size(); ++i) {
|
||||
drivers.emplace(cols[i]);
|
||||
}
|
||||
Address address(ip.c_str(), port);
|
||||
auto& newFound = found.emplace_back();
|
||||
std::copy(serial.begin(), serial.end(), newFound.serial);
|
||||
newFound.makeDriver = [=](device_eventhandler_t err, neodevice_t& forDevice) {
|
||||
return std::make_unique<Servd>(err, forDevice, address);
|
||||
return std::make_unique<Servd>(err, forDevice, drivers);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
Servd::Servd(const device_eventhandler_t& err, neodevice_t& forDevice, const Address& address) :
|
||||
Driver(err), device(forDevice), messageSocket(AF_INET, SOCK_DGRAM, 0) {
|
||||
messageSocket.connect(address);
|
||||
Servd::Servd(const device_eventhandler_t& err, neodevice_t& forDevice, const std::unordered_set<std::string>& availableDrivers) :
|
||||
Driver(err), device(forDevice) {
|
||||
messageSocket.set_nonblocking();
|
||||
messageSocket.bind(Address("127.0.0.1", 0));
|
||||
if(availableDrivers.count("dxx")) {
|
||||
driver = "dxx"; // prefer USB over Ethernet
|
||||
} else if(availableDrivers.count("cab")) {
|
||||
driver = "cab"; // prefer CAB over TCP
|
||||
} else if(availableDrivers.count("tcp")) {
|
||||
driver = "tcp";
|
||||
} else if(availableDrivers.count("vcp")) {
|
||||
driver = "vcp";
|
||||
} else {
|
||||
// just take the first driver
|
||||
driver = *availableDrivers.begin();
|
||||
}
|
||||
}
|
||||
|
||||
Servd::~Servd() {
|
||||
|
|
@ -103,31 +113,21 @@ Servd::~Servd() {
|
|||
}
|
||||
|
||||
bool Servd::open() {
|
||||
const std::string request = SERVD_VERSION_STR + " open";
|
||||
const std::string request = SERVD_VERSION_STR + " open " + std::string(device.serial) + " " + driver;
|
||||
std::string response;
|
||||
response.resize(512);
|
||||
if(!messageSocket.transceive(request, response, std::chrono::milliseconds(5000))) {
|
||||
if(!messageSocket.transceive(SERVD_ADDRESS, request, response, std::chrono::milliseconds(5000))) {
|
||||
EventManager::GetInstance().add(APIEvent::Type::ServdTransceiveError, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
const auto tokens = split(response);
|
||||
if(tokens.size() != 2) {
|
||||
if(tokens.size() != 4) {
|
||||
EventManager::GetInstance().add(APIEvent::Type::ServdInvalidResponseError, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
dataSocket = std::make_unique<Socket>(AF_INET, SOCK_STREAM, 0);
|
||||
const auto& ip = tokens[0];
|
||||
uint16_t port = 0;
|
||||
try {
|
||||
port = static_cast<uint16_t>(std::stoi(tokens[1]));
|
||||
} catch (const std::exception&) {
|
||||
EventManager::GetInstance().add(APIEvent::Type::ServdInvalidResponseError, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
Address address(ip.c_str(), port);
|
||||
dataSocket->connect(address);
|
||||
readThread = std::thread(&Servd::read, this);
|
||||
writeThread = std::thread(&Servd::write, this);
|
||||
aliveThread = std::thread(&Servd::alive, this);
|
||||
readThread = std::thread(&Servd::read, this, Address{tokens[2].c_str(), (uint16_t)std::stol(tokens[3].c_str())});
|
||||
writeThread = std::thread(&Servd::write, this, Address{tokens[0].c_str(), (uint16_t)std::stol(tokens[1].c_str())});
|
||||
opened = true;
|
||||
return true;
|
||||
}
|
||||
|
|
@ -138,6 +138,9 @@ bool Servd::isOpen() {
|
|||
|
||||
bool Servd::close() {
|
||||
setIsClosing(true);
|
||||
if(aliveThread.joinable()) {
|
||||
aliveThread.join();
|
||||
}
|
||||
if(readThread.joinable()) {
|
||||
readThread.join();
|
||||
}
|
||||
|
|
@ -145,16 +148,8 @@ bool Servd::close() {
|
|||
writeThread.join();
|
||||
}
|
||||
if(isOpen()) {
|
||||
Address localAddress;
|
||||
dataSocket->address(localAddress);
|
||||
const std::string request = SERVD_VERSION_STR + " close " + localAddress.ip() + " " + std::to_string(localAddress.port());
|
||||
std::string response;
|
||||
response.resize(1);
|
||||
if(!messageSocket.transceive(request, response, std::chrono::milliseconds(5000))) {
|
||||
EventManager::GetInstance().add(APIEvent::Type::ServdTransceiveError, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
dataSocket.reset();
|
||||
const std::string request = SERVD_VERSION_STR + " close " + std::string(device.serial);
|
||||
messageSocket.sendto(request.data(), request.size(), SERVD_ADDRESS);
|
||||
}
|
||||
opened = false;
|
||||
setIsClosing(false);
|
||||
|
|
@ -164,13 +159,13 @@ bool Servd::close() {
|
|||
bool Servd::enableCommunication(bool enable, bool& sendMsg) {
|
||||
const std::string serialString(device.serial);
|
||||
{
|
||||
const std::string request = SERVD_VERSION_STR + " lock com 1000";
|
||||
const std::string request = SERVD_VERSION_STR + " lock " + serialString + " com 1000";
|
||||
std::string response;
|
||||
response.resize(1);
|
||||
bool locked = false;
|
||||
const auto timeout = std::chrono::steady_clock::now() + std::chrono::seconds(1);
|
||||
do {
|
||||
if(!messageSocket.transceive(request, response, std::chrono::milliseconds(5000))) {
|
||||
if(!messageSocket.transceive(SERVD_ADDRESS, request, response, std::chrono::milliseconds(5000))) {
|
||||
return false;
|
||||
}
|
||||
locked = response == "1" ? true : false;
|
||||
|
|
@ -186,10 +181,10 @@ bool Servd::enableCommunication(bool enable, bool& sendMsg) {
|
|||
}
|
||||
uint64_t com = 0;
|
||||
{
|
||||
const std::string request = SERVD_VERSION_STR + " load com";
|
||||
const std::string request = SERVD_VERSION_STR + " load " + serialString + " com";
|
||||
std::string response;
|
||||
response.resize(20);
|
||||
if(!messageSocket.transceive(request, response, std::chrono::milliseconds(5000))) {
|
||||
if(!messageSocket.transceive(SERVD_ADDRESS, request, response, std::chrono::milliseconds(5000))) {
|
||||
EventManager::GetInstance().add(APIEvent::Type::ServdTransceiveError, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
|
|
@ -207,20 +202,16 @@ bool Servd::enableCommunication(bool enable, bool& sendMsg) {
|
|||
}
|
||||
if(comEnabled != enable) {
|
||||
com += enable ? 1 : -1;
|
||||
const std::string request = SERVD_VERSION_STR + " store com " + std::to_string(com);
|
||||
std::string response;
|
||||
response.resize(1);
|
||||
if(!messageSocket.transceive(request, response, std::chrono::milliseconds(5000))) {
|
||||
const std::string request = SERVD_VERSION_STR + " store " + serialString + " com " + std::to_string(com);
|
||||
if(!messageSocket.sendto(request.data(), request.size(), SERVD_ADDRESS)) {
|
||||
EventManager::GetInstance().add(APIEvent::Type::ServdSendError, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
comEnabled = enable;
|
||||
{
|
||||
const std::string request = SERVD_VERSION_STR + " unlock com";
|
||||
std::string response;
|
||||
response.resize(1);
|
||||
if(!messageSocket.transceive(request, response, std::chrono::milliseconds(5000))) {
|
||||
const std::string request = SERVD_VERSION_STR + " unlock " + serialString + " com";
|
||||
if(!messageSocket.sendto(request.data(), request.size(), SERVD_ADDRESS)) {
|
||||
EventManager::GetInstance().add(APIEvent::Type::ServdSendError, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
|
|
@ -228,11 +219,78 @@ bool Servd::enableCommunication(bool enable, bool& sendMsg) {
|
|||
return true;
|
||||
}
|
||||
|
||||
void Servd::read() {
|
||||
std::vector<uint8_t> buf(2 * 1024 * 1024);
|
||||
void Servd::alive() {
|
||||
Socket socket;
|
||||
socket.set_nonblocking();
|
||||
socket.bind(Address("127.0.0.1", 0));
|
||||
const std::string statusRequest = SERVD_VERSION_STR + " status " + std::string(device.serial);
|
||||
std::string statusResponse;
|
||||
statusResponse.resize(8);
|
||||
while(!isDisconnected() && !isClosing()) {
|
||||
if(!socket.sendto(statusRequest.data(), statusRequest.size(), {"127.0.0.1", 26741})) {
|
||||
EventManager::GetInstance().add(APIEvent::Type::ServdSendError, APIEvent::Severity::Error);
|
||||
setIsDisconnected(true);
|
||||
return;
|
||||
}
|
||||
bool hasData;
|
||||
if(!socket.poll(std::chrono::milliseconds(2000), hasData)) {
|
||||
EventManager::GetInstance().add(APIEvent::Type::ServdPollError, APIEvent::Severity::Error);
|
||||
setIsDisconnected(true);
|
||||
return;
|
||||
}
|
||||
if(!hasData) {
|
||||
EventManager::GetInstance().add(APIEvent::Type::ServdNoDataError, APIEvent::Severity::Error);
|
||||
setIsDisconnected(true);
|
||||
return;
|
||||
}
|
||||
size_t statusResponseSize = statusResponse.size();
|
||||
if(!socket.recv(statusResponse.data(), statusResponseSize)) {
|
||||
EventManager::GetInstance().add(APIEvent::Type::ServdRecvError, APIEvent::Severity::Error);
|
||||
setIsDisconnected(true);
|
||||
return;
|
||||
}
|
||||
statusResponse.resize(statusResponseSize);
|
||||
if(statusRequest == "closed") {
|
||||
EventManager::GetInstance().add(APIEvent::Type::DeviceDisconnected, APIEvent::Severity::Error);
|
||||
setIsDisconnected(true);
|
||||
return;
|
||||
}
|
||||
if(statusResponse != "open") {
|
||||
EventManager::GetInstance().add(APIEvent::Type::ServdInvalidResponseError, APIEvent::Severity::Error);
|
||||
setIsDisconnected(true);
|
||||
return;
|
||||
}
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
|
||||
}
|
||||
}
|
||||
|
||||
void Servd::read(Address&& address) {
|
||||
Socket socket;
|
||||
socket.set_nonblocking();
|
||||
socket.set_reuse(true);
|
||||
#ifdef _WIN32
|
||||
if(!socket.bind(Address("127.0.0.1", address.port()))) {
|
||||
EventManager::GetInstance().add(APIEvent::Type::ServdBindError, APIEvent::Severity::Error);
|
||||
setIsDisconnected(true);
|
||||
return;
|
||||
}
|
||||
#else
|
||||
if(!socket.bind(Address(address.ip().c_str(), address.port()))) {
|
||||
EventManager::GetInstance().add(APIEvent::Type::ServdBindError, APIEvent::Severity::Error);
|
||||
setIsDisconnected(true);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
if(!socket.join_multicast("127.0.0.1", address.ip())) {
|
||||
EventManager::GetInstance().add(APIEvent::Type::ServdJoinMulticastError, APIEvent::Severity::Error);
|
||||
setIsDisconnected(true);
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<uint8_t> buf(65535);
|
||||
while(!isDisconnected() && !isClosing()) {
|
||||
bool hasData;
|
||||
if(!dataSocket->poll(std::chrono::milliseconds(100), hasData)) {
|
||||
if(!socket.poll(std::chrono::milliseconds(100), hasData)) {
|
||||
EventManager::GetInstance().add(APIEvent::Type::ServdPollError, APIEvent::Severity::Error);
|
||||
setIsDisconnected(true);
|
||||
return;
|
||||
|
|
@ -241,7 +299,7 @@ void Servd::read() {
|
|||
continue;
|
||||
}
|
||||
size_t bufSize = buf.size();
|
||||
if(!dataSocket->recv(buf.data(), bufSize)) {
|
||||
if(!socket.recv(buf.data(), bufSize)) {
|
||||
EventManager::GetInstance().add(APIEvent::Type::ServdRecvError, APIEvent::Severity::Error);
|
||||
setIsDisconnected(true);
|
||||
return;
|
||||
|
|
@ -250,14 +308,16 @@ void Servd::read() {
|
|||
}
|
||||
}
|
||||
|
||||
void Servd::write() {
|
||||
void Servd::write(Address&& address) {
|
||||
Socket socket;
|
||||
socket.bind(Address("127.0.0.1", 0));
|
||||
WriteOperation writeOp;
|
||||
while(!isDisconnected() && !isClosing()) {
|
||||
if(!writeQueue.wait_dequeue_timed(writeOp, std::chrono::milliseconds(100))) {
|
||||
continue;
|
||||
}
|
||||
if(!isClosing()) {
|
||||
if(!dataSocket->send(writeOp.bytes.data(), writeOp.bytes.size())) {
|
||||
if(!socket.sendto(writeOp.bytes.data(), writeOp.bytes.size(), address)) {
|
||||
EventManager::GetInstance().add(APIEvent::Type::ServdSendError, APIEvent::Severity::Error);
|
||||
setIsDisconnected(true);
|
||||
return;
|
||||
|
|
|
|||
Loading…
Reference in New Issue