Communication::Command refactored out of Communication
parent
6284223650
commit
d27b516894
|
|
@ -1,158 +1,159 @@
|
||||||
#include "communication/include/communication.h"
|
#include "communication/include/communication.h"
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <queue>
|
#include <queue>
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <condition_variable>
|
#include <condition_variable>
|
||||||
#include "communication/include/messagedecoder.h"
|
#include "communication/include/command.h"
|
||||||
#include "communication/include/packetizer.h"
|
#include "communication/include/messagedecoder.h"
|
||||||
|
#include "communication/include/packetizer.h"
|
||||||
using namespace icsneo;
|
|
||||||
|
using namespace icsneo;
|
||||||
int Communication::messageCallbackIDCounter = 1;
|
|
||||||
|
int Communication::messageCallbackIDCounter = 1;
|
||||||
uint8_t Communication::ICSChecksum(const std::vector<uint8_t>& data) {
|
|
||||||
uint32_t checksum = 0;
|
uint8_t Communication::ICSChecksum(const std::vector<uint8_t>& data) {
|
||||||
for(auto i = 0; i < data.size(); i++)
|
uint32_t checksum = 0;
|
||||||
checksum += data[i];
|
for(auto i = 0; i < data.size(); i++)
|
||||||
checksum = ~checksum;
|
checksum += data[i];
|
||||||
checksum++;
|
checksum = ~checksum;
|
||||||
return (uint8_t)checksum;
|
checksum++;
|
||||||
}
|
return (uint8_t)checksum;
|
||||||
|
}
|
||||||
std::vector<uint8_t>& Communication::packetWrap(std::vector<uint8_t>& data, bool addChecksum) {
|
|
||||||
if(addChecksum)
|
std::vector<uint8_t>& Communication::packetWrap(std::vector<uint8_t>& data, bool addChecksum) {
|
||||||
data.push_back(ICSChecksum(data));
|
if(addChecksum)
|
||||||
data.insert(data.begin(), 0xAA);
|
data.push_back(ICSChecksum(data));
|
||||||
if(align16bit && data.size() % 2 == 1)
|
data.insert(data.begin(), 0xAA);
|
||||||
data.push_back('A');
|
if(align16bit && data.size() % 2 == 1)
|
||||||
return data;
|
data.push_back('A');
|
||||||
}
|
return data;
|
||||||
|
}
|
||||||
bool Communication::open() {
|
|
||||||
if(isOpen)
|
bool Communication::open() {
|
||||||
return true;
|
if(isOpen)
|
||||||
|
return true;
|
||||||
spawnThreads();
|
|
||||||
isOpen = true;
|
spawnThreads();
|
||||||
return impl->open();
|
isOpen = true;
|
||||||
}
|
return impl->open();
|
||||||
|
}
|
||||||
void Communication::spawnThreads() {
|
|
||||||
readTaskThread = std::thread(&Communication::readTask, this);
|
void Communication::spawnThreads() {
|
||||||
}
|
readTaskThread = std::thread(&Communication::readTask, this);
|
||||||
|
}
|
||||||
void Communication::joinThreads() {
|
|
||||||
if(readTaskThread.joinable())
|
void Communication::joinThreads() {
|
||||||
readTaskThread.join();
|
if(readTaskThread.joinable())
|
||||||
}
|
readTaskThread.join();
|
||||||
|
}
|
||||||
bool Communication::close() {
|
|
||||||
if(!isOpen)
|
bool Communication::close() {
|
||||||
return false;
|
if(!isOpen)
|
||||||
|
return false;
|
||||||
isOpen = false;
|
|
||||||
closing = true;
|
isOpen = false;
|
||||||
joinThreads();
|
closing = true;
|
||||||
|
joinThreads();
|
||||||
return impl->close();
|
|
||||||
}
|
return impl->close();
|
||||||
|
}
|
||||||
bool Communication::sendPacket(std::vector<uint8_t>& bytes) {
|
|
||||||
return impl->write(Communication::packetWrap(bytes));
|
bool Communication::sendPacket(std::vector<uint8_t>& bytes) {
|
||||||
}
|
return impl->write(Communication::packetWrap(bytes));
|
||||||
|
}
|
||||||
bool Communication::sendCommand(Communication::Command cmd, std::vector<uint8_t> arguments) {
|
|
||||||
std::vector<uint8_t> bytes;
|
bool Communication::sendCommand(Command cmd, std::vector<uint8_t> arguments) {
|
||||||
bytes.push_back((uint8_t)cmd);
|
std::vector<uint8_t> bytes;
|
||||||
for(auto& b : arguments)
|
bytes.push_back((uint8_t)cmd);
|
||||||
bytes.push_back(b);
|
for(auto& b : arguments)
|
||||||
bytes.insert(bytes.begin(), (uint8_t)Network::NetID::Main51 | ((uint8_t)bytes.size() << 4));
|
bytes.push_back(b);
|
||||||
return sendPacket(bytes);
|
bytes.insert(bytes.begin(), (uint8_t)Network::NetID::Main51 | ((uint8_t)bytes.size() << 4));
|
||||||
}
|
return sendPacket(bytes);
|
||||||
|
}
|
||||||
bool Communication::getSettingsSync(std::vector<uint8_t>& data, std::chrono::milliseconds timeout) {
|
|
||||||
sendCommand(Command::GetSettings);
|
bool Communication::getSettingsSync(std::vector<uint8_t>& data, std::chrono::milliseconds timeout) {
|
||||||
std::shared_ptr<Message> msg = waitForMessageSync(MessageFilter(Network::NetID::RED_READ_BAUD_SETTINGS), timeout);
|
sendCommand(Command::GetSettings);
|
||||||
if(!msg)
|
std::shared_ptr<Message> msg = waitForMessageSync(MessageFilter(Network::NetID::RED_READ_BAUD_SETTINGS), timeout);
|
||||||
return false;
|
if(!msg)
|
||||||
|
return false;
|
||||||
data = std::move(msg->data);
|
|
||||||
return true;
|
data = std::move(msg->data);
|
||||||
}
|
return true;
|
||||||
|
}
|
||||||
bool Communication::getSerialNumberSync(std::string& serial, std::chrono::milliseconds timeout) {
|
|
||||||
sendCommand(Command::RequestSerialNumber);
|
bool Communication::getSerialNumberSync(std::string& serial, std::chrono::milliseconds timeout) {
|
||||||
std::shared_ptr<Message> msg = waitForMessageSync(MessageFilter(Network::NetID::RED_OLDFORMAT), timeout);
|
sendCommand(Command::RequestSerialNumber);
|
||||||
if(!msg)
|
std::shared_ptr<Message> msg = waitForMessageSync(MessageFilter(Network::NetID::RED_OLDFORMAT), timeout);
|
||||||
return false;
|
if(!msg)
|
||||||
|
return false;
|
||||||
std::cout << "Got " << msg->data.size() << " bytes" << std::endl;
|
|
||||||
for(size_t i = 0; i < msg->data.size(); i++) {
|
std::cout << "Got " << msg->data.size() << " bytes" << std::endl;
|
||||||
std::cout << std::hex << (int)msg->data[i] << ' ' << std::dec;
|
for(size_t i = 0; i < msg->data.size(); i++) {
|
||||||
if(i % 16 == 15)
|
std::cout << std::hex << (int)msg->data[i] << ' ' << std::dec;
|
||||||
std::cout << std::endl;
|
if(i % 16 == 15)
|
||||||
}
|
std::cout << std::endl;
|
||||||
return true;
|
}
|
||||||
}
|
return true;
|
||||||
|
}
|
||||||
int Communication::addMessageCallback(const MessageCallback& cb) {
|
|
||||||
messageCallbacks.insert(std::make_pair(messageCallbackIDCounter, cb));
|
int Communication::addMessageCallback(const MessageCallback& cb) {
|
||||||
return messageCallbackIDCounter++;
|
messageCallbacks.insert(std::make_pair(messageCallbackIDCounter, cb));
|
||||||
}
|
return messageCallbackIDCounter++;
|
||||||
|
}
|
||||||
bool Communication::removeMessageCallback(int id) {
|
|
||||||
try {
|
bool Communication::removeMessageCallback(int id) {
|
||||||
messageCallbacks.erase(id);
|
try {
|
||||||
return true;
|
messageCallbacks.erase(id);
|
||||||
} catch(...) {
|
return true;
|
||||||
return false;
|
} catch(...) {
|
||||||
}
|
return false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
std::shared_ptr<Message> Communication::waitForMessageSync(MessageFilter f, std::chrono::milliseconds timeout) {
|
|
||||||
std::mutex m;
|
std::shared_ptr<Message> Communication::waitForMessageSync(MessageFilter f, std::chrono::milliseconds timeout) {
|
||||||
std::condition_variable cv;
|
std::mutex m;
|
||||||
std::shared_ptr<Message> returnedMessage;
|
std::condition_variable cv;
|
||||||
int cb = addMessageCallback(MessageCallback([&m, &returnedMessage, &cv](std::shared_ptr<Message> message) {
|
std::shared_ptr<Message> returnedMessage;
|
||||||
{
|
int cb = addMessageCallback(MessageCallback([&m, &returnedMessage, &cv](std::shared_ptr<Message> message) {
|
||||||
std::lock_guard<std::mutex> lk(m);
|
{
|
||||||
returnedMessage = message;
|
std::lock_guard<std::mutex> lk(m);
|
||||||
}
|
returnedMessage = message;
|
||||||
cv.notify_one();
|
}
|
||||||
}, f));
|
cv.notify_one();
|
||||||
|
}, f));
|
||||||
// We have now added the callback, wait for it to return from the other thread
|
|
||||||
std::unique_lock<std::mutex> lk(m);
|
// We have now added the callback, wait for it to return from the other thread
|
||||||
cv.wait_for(lk, timeout, [&returnedMessage]{ return !!returnedMessage; }); // `!!shared_ptr` checks if the ptr has a value
|
std::unique_lock<std::mutex> lk(m);
|
||||||
|
cv.wait_for(lk, timeout, [&returnedMessage]{ return !!returnedMessage; }); // `!!shared_ptr` checks if the ptr has a value
|
||||||
// We don't actually check that we got a message, because either way we want to remove the callback (since it should only happen once)
|
|
||||||
removeMessageCallback(cb);
|
// We don't actually check that we got a message, because either way we want to remove the callback (since it should only happen once)
|
||||||
|
removeMessageCallback(cb);
|
||||||
// Then we either will return the message we got or we will return the empty shared_ptr, caller responsible for checking
|
|
||||||
return returnedMessage;
|
// Then we either will return the message we got or we will return the empty shared_ptr, caller responsible for checking
|
||||||
}
|
return returnedMessage;
|
||||||
|
}
|
||||||
void Communication::readTask() {
|
|
||||||
std::vector<uint8_t> readBytes;
|
void Communication::readTask() {
|
||||||
Packetizer packetizer;
|
std::vector<uint8_t> readBytes;
|
||||||
MessageDecoder decoder;
|
Packetizer packetizer;
|
||||||
|
MessageDecoder decoder;
|
||||||
while(!closing) {
|
|
||||||
readBytes.clear();
|
while(!closing) {
|
||||||
if(impl->readWait(readBytes)) {
|
readBytes.clear();
|
||||||
if(packetizer.input(readBytes)) {
|
if(impl->readWait(readBytes)) {
|
||||||
for(auto& packet : packetizer.output()) {
|
if(packetizer.input(readBytes)) {
|
||||||
auto msg = decoder.decodePacket(packet);
|
for(auto& packet : packetizer.output()) {
|
||||||
for(auto& cb : messageCallbacks) { // We might have closed while reading or processing
|
auto msg = decoder.decodePacket(packet);
|
||||||
if(!closing) {
|
for(auto& cb : messageCallbacks) { // We might have closed while reading or processing
|
||||||
cb.second.callIfMatch(msg);
|
if(!closing) {
|
||||||
}
|
cb.second.callIfMatch(msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
#ifndef __COMMAND_H_
|
||||||
|
#define __COMMAND_H_
|
||||||
|
|
||||||
|
namespace icsneo {
|
||||||
|
|
||||||
|
enum class Command : uint8_t {
|
||||||
|
EnableNetworkCommunication = 0x07,
|
||||||
|
RequestSerialNumber = 0xA1,
|
||||||
|
SetSettings = 0xA4, // Previously known as RED_CMD_SET_BAUD_REQ, follow up with SaveSettings to write to EEPROM
|
||||||
|
GetSettings = 0xA5, // Previously known as RED_CMD_READ_BAUD_REQ
|
||||||
|
SaveSettings = 0xA6
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -1,71 +1,65 @@
|
||||||
#ifndef __COMMUNICATION_H_
|
#ifndef __COMMUNICATION_H_
|
||||||
#define __COMMUNICATION_H_
|
#define __COMMUNICATION_H_
|
||||||
|
|
||||||
#include "communication/include/icommunication.h"
|
#include "communication/include/icommunication.h"
|
||||||
#include "communication/include/network.h"
|
#include "communication/include/command.h"
|
||||||
#include "communication/include/messagecallback.h"
|
#include "communication/include/network.h"
|
||||||
#include <memory>
|
#include "communication/include/messagecallback.h"
|
||||||
#include <vector>
|
#include <memory>
|
||||||
#include <atomic>
|
#include <vector>
|
||||||
#include <thread>
|
#include <atomic>
|
||||||
#include <queue>
|
#include <thread>
|
||||||
#include <map>
|
#include <queue>
|
||||||
|
#include <map>
|
||||||
namespace icsneo {
|
|
||||||
|
namespace icsneo {
|
||||||
class Communication {
|
|
||||||
public:
|
class Communication {
|
||||||
static uint8_t ICSChecksum(const std::vector<uint8_t>& data);
|
public:
|
||||||
|
static uint8_t ICSChecksum(const std::vector<uint8_t>& data);
|
||||||
Communication(std::shared_ptr<ICommunication> com) : impl(com) {}
|
|
||||||
virtual ~Communication() { close(); }
|
Communication(std::shared_ptr<ICommunication> com) : impl(com) {}
|
||||||
|
virtual ~Communication() { close(); }
|
||||||
bool open();
|
|
||||||
bool close();
|
bool open();
|
||||||
virtual void spawnThreads();
|
bool close();
|
||||||
virtual void joinThreads();
|
virtual void spawnThreads();
|
||||||
bool rawWrite(const std::vector<uint8_t>& bytes) { return impl->write(bytes); }
|
virtual void joinThreads();
|
||||||
std::vector<uint8_t>& packetWrap(std::vector<uint8_t>& data, bool addChecksum = true);
|
bool rawWrite(const std::vector<uint8_t>& bytes) { return impl->write(bytes); }
|
||||||
bool sendPacket(std::vector<uint8_t>& bytes);
|
std::vector<uint8_t>& packetWrap(std::vector<uint8_t>& data, bool addChecksum = true);
|
||||||
|
bool sendPacket(std::vector<uint8_t>& bytes);
|
||||||
enum class Command : uint8_t {
|
|
||||||
EnableNetworkCommunication = 0x07,
|
virtual bool sendCommand(Command cmd, bool boolean) { return sendCommand(cmd, std::vector<uint8_t>({ (uint8_t)boolean })); }
|
||||||
RequestSerialNumber = 0xA1,
|
virtual bool sendCommand(Command cmd, std::vector<uint8_t> arguments = {});
|
||||||
SetSettings = 0xA4, // Previously known as RED_CMD_SET_BAUD_REQ, follow up with SaveSettings to write to EEPROM
|
bool getSettingsSync(std::vector<uint8_t>& data, std::chrono::milliseconds timeout = std::chrono::milliseconds(50));
|
||||||
GetSettings = 0xA5, // Previously known as RED_CMD_READ_BAUD_REQ
|
bool getSerialNumberSync(std::string& serial, std::chrono::milliseconds timeout = std::chrono::milliseconds(50));
|
||||||
SaveSettings = 0xA6
|
|
||||||
};
|
int addMessageCallback(const MessageCallback& cb);
|
||||||
virtual bool sendCommand(Command cmd, bool boolean) { return sendCommand(cmd, std::vector<uint8_t>({ (uint8_t)boolean })); }
|
bool removeMessageCallback(int id);
|
||||||
virtual bool sendCommand(Command cmd, std::vector<uint8_t> arguments = {});
|
std::shared_ptr<Message> waitForMessageSync(MessageFilter f = MessageFilter(), std::chrono::milliseconds timeout = std::chrono::milliseconds(50));
|
||||||
bool getSettingsSync(std::vector<uint8_t>& data, std::chrono::milliseconds timeout = std::chrono::milliseconds(50));
|
|
||||||
bool getSerialNumberSync(std::string& serial, std::chrono::milliseconds timeout = std::chrono::milliseconds(50));
|
void setAlign16Bit(bool enable) { align16bit = enable; }
|
||||||
|
|
||||||
int addMessageCallback(const MessageCallback& cb);
|
class Packet {
|
||||||
bool removeMessageCallback(int id);
|
public:
|
||||||
std::shared_ptr<Message> waitForMessageSync(MessageFilter f = MessageFilter(), std::chrono::milliseconds timeout = std::chrono::milliseconds(50));
|
Network network;
|
||||||
|
std::vector<uint8_t> data;
|
||||||
void setAlign16Bit(bool enable) { align16bit = enable; }
|
};
|
||||||
|
|
||||||
class Packet {
|
protected:
|
||||||
public:
|
std::shared_ptr<ICommunication> impl;
|
||||||
Network network;
|
static int messageCallbackIDCounter;
|
||||||
std::vector<uint8_t> data;
|
std::map<int, MessageCallback> messageCallbacks;
|
||||||
};
|
std::atomic<bool> closing{false};
|
||||||
|
|
||||||
protected:
|
private:
|
||||||
std::shared_ptr<ICommunication> impl;
|
bool isOpen = false;
|
||||||
static int messageCallbackIDCounter;
|
bool align16bit = true; // Not needed for Gigalog, Galaxy, etc and newer
|
||||||
std::map<int, MessageCallback> messageCallbacks;
|
|
||||||
std::atomic<bool> closing{false};
|
std::thread readTaskThread;
|
||||||
|
void readTask();
|
||||||
private:
|
};
|
||||||
bool isOpen = false;
|
|
||||||
bool align16bit = true; // Not needed for Gigalog, Galaxy, etc and newer
|
};
|
||||||
|
|
||||||
std::thread readTaskThread;
|
|
||||||
void readTask();
|
|
||||||
};
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -1,102 +1,103 @@
|
||||||
#ifndef __MULTICHANNELCOMMUNICATION_H_
|
#ifndef __MULTICHANNELCOMMUNICATION_H_
|
||||||
#define __MULTICHANNELCOMMUNICATION_H_
|
#define __MULTICHANNELCOMMUNICATION_H_
|
||||||
|
|
||||||
#include "communication/include/communication.h"
|
#include "communication/include/communication.h"
|
||||||
#include "communication/include/icommunication.h"
|
#include "communication/include/icommunication.h"
|
||||||
|
#include "communication/include/command.h"
|
||||||
namespace icsneo {
|
|
||||||
|
namespace icsneo {
|
||||||
class MultiChannelCommunication : public Communication {
|
|
||||||
public:
|
class MultiChannelCommunication : public Communication {
|
||||||
MultiChannelCommunication(std::shared_ptr<ICommunication> com) : Communication(com) {}
|
public:
|
||||||
void spawnThreads();
|
MultiChannelCommunication(std::shared_ptr<ICommunication> com) : Communication(com) {}
|
||||||
void joinThreads();
|
void spawnThreads();
|
||||||
bool sendCommand(Communication::Command cmd, std::vector<uint8_t> arguments);
|
void joinThreads();
|
||||||
|
bool sendCommand(Command cmd, std::vector<uint8_t> arguments);
|
||||||
protected:
|
|
||||||
bool preprocessPacket(std::deque<uint8_t>& usbReadFifo);
|
protected:
|
||||||
|
bool preprocessPacket(std::deque<uint8_t>& usbReadFifo);
|
||||||
private:
|
|
||||||
enum class CommandType : uint8_t {
|
private:
|
||||||
PlasmaReadRequest = 0x10, // Status read request to HSC
|
enum class CommandType : uint8_t {
|
||||||
PlasmaStatusResponse = 0x11, // Status response by HSC
|
PlasmaReadRequest = 0x10, // Status read request to HSC
|
||||||
HostPC_to_Vnet1 = 0x20, // Host PC data to Vnet module-1
|
PlasmaStatusResponse = 0x11, // Status response by HSC
|
||||||
Vnet1_to_HostPC = 0x21, // Vnet module-1 data to host PC
|
HostPC_to_Vnet1 = 0x20, // Host PC data to Vnet module-1
|
||||||
HostPC_to_Vnet2 = 0x30, // Host PC data to Vnet module-2
|
Vnet1_to_HostPC = 0x21, // Vnet module-1 data to host PC
|
||||||
Vnet2_to_HostPC = 0x31, // Vnet module-2 data to host PC
|
HostPC_to_Vnet2 = 0x30, // Host PC data to Vnet module-2
|
||||||
HostPC_to_Vnet3 = 0x40, // Host PC data to Vnet module-3
|
Vnet2_to_HostPC = 0x31, // Vnet module-2 data to host PC
|
||||||
Vnet3_to_HostPC = 0x41, // Vnet module-3 data to host PC
|
HostPC_to_Vnet3 = 0x40, // Host PC data to Vnet module-3
|
||||||
HostPC_to_SDCC1 = 0x50, // Host PC data to write to SDCC-1
|
Vnet3_to_HostPC = 0x41, // Vnet module-3 data to host PC
|
||||||
HostPC_from_SDCC1 = 0x51, // Host PC wants data read from SDCC-1
|
HostPC_to_SDCC1 = 0x50, // Host PC data to write to SDCC-1
|
||||||
SDCC1_to_HostPC = 0x52, // SDCC-1 data to host PC
|
HostPC_from_SDCC1 = 0x51, // Host PC wants data read from SDCC-1
|
||||||
HostPC_to_SDCC2 = 0x60, // Host PC data to write to SDCC-2
|
SDCC1_to_HostPC = 0x52, // SDCC-1 data to host PC
|
||||||
HostPC_from_SDCC2 = 0x61, // Host PC wants data read from SDCC-2
|
HostPC_to_SDCC2 = 0x60, // Host PC data to write to SDCC-2
|
||||||
SDCC2_to_HostPC = 0x62, // SDCC-2 data to host PC
|
HostPC_from_SDCC2 = 0x61, // Host PC wants data read from SDCC-2
|
||||||
PC_to_LSOC = 0x70, // Host PC data to LSOCC
|
SDCC2_to_HostPC = 0x62, // SDCC-2 data to host PC
|
||||||
LSOCC_to_PC = 0x71, // LSOCC data to host PC
|
PC_to_LSOC = 0x70, // Host PC data to LSOCC
|
||||||
HostPC_to_Microblaze = 0x80, // Host PC data to microblaze processor
|
LSOCC_to_PC = 0x71, // LSOCC data to host PC
|
||||||
Microblaze_to_HostPC = 0x81 // Microblaze processor data to host PC
|
HostPC_to_Microblaze = 0x80, // Host PC data to microblaze processor
|
||||||
};
|
Microblaze_to_HostPC = 0x81 // Microblaze processor data to host PC
|
||||||
static bool CommandTypeIsValid(CommandType cmd) {
|
};
|
||||||
switch(cmd) {
|
static bool CommandTypeIsValid(CommandType cmd) {
|
||||||
case CommandType::PlasmaReadRequest:
|
switch(cmd) {
|
||||||
case CommandType::PlasmaStatusResponse:
|
case CommandType::PlasmaReadRequest:
|
||||||
case CommandType::HostPC_to_Vnet1:
|
case CommandType::PlasmaStatusResponse:
|
||||||
case CommandType::Vnet1_to_HostPC:
|
case CommandType::HostPC_to_Vnet1:
|
||||||
case CommandType::HostPC_to_Vnet2:
|
case CommandType::Vnet1_to_HostPC:
|
||||||
case CommandType::Vnet2_to_HostPC:
|
case CommandType::HostPC_to_Vnet2:
|
||||||
case CommandType::HostPC_to_Vnet3:
|
case CommandType::Vnet2_to_HostPC:
|
||||||
case CommandType::Vnet3_to_HostPC:
|
case CommandType::HostPC_to_Vnet3:
|
||||||
case CommandType::HostPC_to_SDCC1:
|
case CommandType::Vnet3_to_HostPC:
|
||||||
case CommandType::HostPC_from_SDCC1:
|
case CommandType::HostPC_to_SDCC1:
|
||||||
case CommandType::SDCC1_to_HostPC:
|
case CommandType::HostPC_from_SDCC1:
|
||||||
case CommandType::HostPC_to_SDCC2:
|
case CommandType::SDCC1_to_HostPC:
|
||||||
case CommandType::HostPC_from_SDCC2:
|
case CommandType::HostPC_to_SDCC2:
|
||||||
case CommandType::SDCC2_to_HostPC:
|
case CommandType::HostPC_from_SDCC2:
|
||||||
case CommandType::PC_to_LSOC:
|
case CommandType::SDCC2_to_HostPC:
|
||||||
case CommandType::LSOCC_to_PC:
|
case CommandType::PC_to_LSOC:
|
||||||
case CommandType::HostPC_to_Microblaze:
|
case CommandType::LSOCC_to_PC:
|
||||||
case CommandType::Microblaze_to_HostPC:
|
case CommandType::HostPC_to_Microblaze:
|
||||||
return true;
|
case CommandType::Microblaze_to_HostPC:
|
||||||
default:
|
return true;
|
||||||
return false;
|
default:
|
||||||
}
|
return false;
|
||||||
}
|
}
|
||||||
static bool CommandTypeHasAddress(CommandType cmd) {
|
}
|
||||||
// Check CommandTypeIsValid before this, you will get false on an invalid command
|
static bool CommandTypeHasAddress(CommandType cmd) {
|
||||||
switch(cmd) {
|
// Check CommandTypeIsValid before this, you will get false on an invalid command
|
||||||
case CommandType::SDCC1_to_HostPC:
|
switch(cmd) {
|
||||||
case CommandType::SDCC2_to_HostPC:
|
case CommandType::SDCC1_to_HostPC:
|
||||||
return true;
|
case CommandType::SDCC2_to_HostPC:
|
||||||
default:
|
return true;
|
||||||
return false;
|
default:
|
||||||
}
|
return false;
|
||||||
}
|
}
|
||||||
static uint16_t CommandTypeDefinesLength(CommandType cmd) {
|
}
|
||||||
// Check CommandTypeIsValid before this, you will get 0 on an invalid command
|
static uint16_t CommandTypeDefinesLength(CommandType cmd) {
|
||||||
switch(cmd) {
|
// Check CommandTypeIsValid before this, you will get 0 on an invalid command
|
||||||
case CommandType::PlasmaStatusResponse:
|
switch(cmd) {
|
||||||
return 2;
|
case CommandType::PlasmaStatusResponse:
|
||||||
default:
|
return 2;
|
||||||
return 0; // Length is defined by following bytes in message
|
default:
|
||||||
}
|
return 0; // Length is defined by following bytes in message
|
||||||
}
|
}
|
||||||
|
}
|
||||||
enum class PreprocessState {
|
|
||||||
SearchForCommand,
|
enum class PreprocessState {
|
||||||
ParseAddress,
|
SearchForCommand,
|
||||||
ParseLength,
|
ParseAddress,
|
||||||
GetData
|
ParseLength,
|
||||||
};
|
GetData
|
||||||
PreprocessState state = PreprocessState::SearchForCommand;
|
};
|
||||||
uint16_t currentCommandLength;
|
PreprocessState state = PreprocessState::SearchForCommand;
|
||||||
CommandType currentCommandType;
|
uint16_t currentCommandLength;
|
||||||
size_t currentReadIndex = 0;
|
CommandType currentCommandType;
|
||||||
|
size_t currentReadIndex = 0;
|
||||||
std::thread mainChannelReadThread;
|
|
||||||
void readTask();
|
std::thread mainChannelReadThread;
|
||||||
};
|
void readTask();
|
||||||
|
};
|
||||||
};
|
|
||||||
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -1,126 +1,127 @@
|
||||||
#include "communication/include/multichannelcommunication.h"
|
#include "communication/include/multichannelcommunication.h"
|
||||||
#include "communication/include/messagedecoder.h"
|
#include "communication/include/command.h"
|
||||||
#include "communication/include/packetizer.h"
|
#include "communication/include/messagedecoder.h"
|
||||||
#include <iostream>
|
#include "communication/include/packetizer.h"
|
||||||
#include <iomanip>
|
#include <iostream>
|
||||||
|
#include <iomanip>
|
||||||
using namespace icsneo;
|
|
||||||
|
using namespace icsneo;
|
||||||
void MultiChannelCommunication::spawnThreads() {
|
|
||||||
mainChannelReadThread = std::thread(&MultiChannelCommunication::readTask, this);
|
void MultiChannelCommunication::spawnThreads() {
|
||||||
}
|
mainChannelReadThread = std::thread(&MultiChannelCommunication::readTask, this);
|
||||||
|
}
|
||||||
void MultiChannelCommunication::joinThreads() {
|
|
||||||
if(mainChannelReadThread.joinable())
|
void MultiChannelCommunication::joinThreads() {
|
||||||
mainChannelReadThread.join();
|
if(mainChannelReadThread.joinable())
|
||||||
}
|
mainChannelReadThread.join();
|
||||||
|
}
|
||||||
bool MultiChannelCommunication::sendCommand(Communication::Command cmd, std::vector<uint8_t> arguments) {
|
|
||||||
std::vector<uint8_t> bytes;
|
bool MultiChannelCommunication::sendCommand(Command cmd, std::vector<uint8_t> arguments) {
|
||||||
bytes.push_back((uint8_t)cmd);
|
std::vector<uint8_t> bytes;
|
||||||
for(auto& b : arguments)
|
bytes.push_back((uint8_t)cmd);
|
||||||
bytes.push_back(b);
|
for(auto& b : arguments)
|
||||||
bytes.insert(bytes.begin(), 0xB | ((uint8_t)bytes.size() << 4));
|
bytes.push_back(b);
|
||||||
bytes = Communication::packetWrap(bytes);
|
bytes.insert(bytes.begin(), 0xB | ((uint8_t)bytes.size() << 4));
|
||||||
bytes.insert(bytes.begin(), {(uint8_t)CommandType::HostPC_to_Vnet1, (uint8_t)bytes.size(), (uint8_t)(bytes.size() >> 8)});
|
bytes = Communication::packetWrap(bytes);
|
||||||
return rawWrite(bytes);
|
bytes.insert(bytes.begin(), {(uint8_t)CommandType::HostPC_to_Vnet1, (uint8_t)bytes.size(), (uint8_t)(bytes.size() >> 8)});
|
||||||
}
|
return rawWrite(bytes);
|
||||||
|
}
|
||||||
void MultiChannelCommunication::readTask() {
|
|
||||||
bool readMore = true;
|
void MultiChannelCommunication::readTask() {
|
||||||
std::deque<uint8_t> usbReadFifo;
|
bool readMore = true;
|
||||||
std::vector<uint8_t> readBytes;
|
std::deque<uint8_t> usbReadFifo;
|
||||||
std::vector<uint8_t> payloadBytes;
|
std::vector<uint8_t> readBytes;
|
||||||
Packetizer packetizer;
|
std::vector<uint8_t> payloadBytes;
|
||||||
MessageDecoder decoder;
|
Packetizer packetizer;
|
||||||
|
MessageDecoder decoder;
|
||||||
while(!closing) {
|
|
||||||
if(readMore) {
|
while(!closing) {
|
||||||
readBytes.clear();
|
if(readMore) {
|
||||||
if(impl->readWait(readBytes)) {
|
readBytes.clear();
|
||||||
readMore = false;
|
if(impl->readWait(readBytes)) {
|
||||||
usbReadFifo.insert(usbReadFifo.end(), std::make_move_iterator(readBytes.begin()), std::make_move_iterator(readBytes.end()));
|
readMore = false;
|
||||||
}
|
usbReadFifo.insert(usbReadFifo.end(), std::make_move_iterator(readBytes.begin()), std::make_move_iterator(readBytes.end()));
|
||||||
} else {
|
}
|
||||||
switch(state) {
|
} else {
|
||||||
case PreprocessState::SearchForCommand:
|
switch(state) {
|
||||||
if(usbReadFifo.size() < 1) {
|
case PreprocessState::SearchForCommand:
|
||||||
readMore = true;
|
if(usbReadFifo.size() < 1) {
|
||||||
continue;
|
readMore = true;
|
||||||
}
|
continue;
|
||||||
|
}
|
||||||
currentCommandType = (CommandType)usbReadFifo[0];
|
|
||||||
|
currentCommandType = (CommandType)usbReadFifo[0];
|
||||||
if(!CommandTypeIsValid(currentCommandType)) {
|
|
||||||
std::cout << "cnv" << std::hex << (int)currentCommandType << ' ' << std::dec;
|
if(!CommandTypeIsValid(currentCommandType)) {
|
||||||
usbReadFifo.pop_front();
|
std::cout << "cnv" << std::hex << (int)currentCommandType << ' ' << std::dec;
|
||||||
continue;
|
usbReadFifo.pop_front();
|
||||||
}
|
continue;
|
||||||
|
}
|
||||||
currentReadIndex = 1;
|
|
||||||
|
currentReadIndex = 1;
|
||||||
if(CommandTypeHasAddress(currentCommandType)) {
|
|
||||||
state = PreprocessState::ParseAddress;
|
if(CommandTypeHasAddress(currentCommandType)) {
|
||||||
continue; // No commands which define an address also define a length, so we can just continue from there
|
state = PreprocessState::ParseAddress;
|
||||||
}
|
continue; // No commands which define an address also define a length, so we can just continue from there
|
||||||
|
}
|
||||||
currentCommandLength = CommandTypeDefinesLength(currentCommandType);
|
|
||||||
if(currentCommandLength == 0) {
|
currentCommandLength = CommandTypeDefinesLength(currentCommandType);
|
||||||
state = PreprocessState::ParseLength;
|
if(currentCommandLength == 0) {
|
||||||
continue;
|
state = PreprocessState::ParseLength;
|
||||||
}
|
continue;
|
||||||
|
}
|
||||||
state = PreprocessState::GetData;
|
|
||||||
continue;
|
state = PreprocessState::GetData;
|
||||||
case PreprocessState::ParseAddress:
|
continue;
|
||||||
// The address is represented by a 4 byte little endian
|
case PreprocessState::ParseAddress:
|
||||||
// Don't care about it yet
|
// The address is represented by a 4 byte little endian
|
||||||
currentReadIndex += 4;
|
// Don't care about it yet
|
||||||
// Intentionally fall through
|
currentReadIndex += 4;
|
||||||
case PreprocessState::ParseLength:
|
// Intentionally fall through
|
||||||
state = PreprocessState::ParseLength; // Set state in case we've fallen through, but later need to go around again
|
case PreprocessState::ParseLength:
|
||||||
|
state = PreprocessState::ParseLength; // Set state in case we've fallen through, but later need to go around again
|
||||||
if(usbReadFifo.size() < currentReadIndex + 2) { // Come back we have more data
|
|
||||||
readMore = true;
|
if(usbReadFifo.size() < currentReadIndex + 2) { // Come back we have more data
|
||||||
continue;
|
readMore = true;
|
||||||
}
|
continue;
|
||||||
|
}
|
||||||
// The length is represented by a 2 byte little endian
|
|
||||||
currentCommandLength = usbReadFifo[currentReadIndex++];
|
// The length is represented by a 2 byte little endian
|
||||||
currentCommandLength |= usbReadFifo[currentReadIndex++] << 8;
|
currentCommandLength = usbReadFifo[currentReadIndex++];
|
||||||
// Intentionally fall through
|
currentCommandLength |= usbReadFifo[currentReadIndex++] << 8;
|
||||||
case PreprocessState::GetData:
|
// Intentionally fall through
|
||||||
state = PreprocessState::GetData; // Set state in case we've fallen through, but later need to go around again
|
case PreprocessState::GetData:
|
||||||
|
state = PreprocessState::GetData; // Set state in case we've fallen through, but later need to go around again
|
||||||
if(usbReadFifo.size() <= currentReadIndex + currentCommandLength) { // Come back we have more data
|
|
||||||
readMore = true;
|
if(usbReadFifo.size() <= currentReadIndex + currentCommandLength) { // Come back we have more data
|
||||||
continue;
|
readMore = true;
|
||||||
}
|
continue;
|
||||||
|
}
|
||||||
for(auto i = 0; i < currentReadIndex; i++)
|
|
||||||
usbReadFifo.pop_front();
|
for(auto i = 0; i < currentReadIndex; i++)
|
||||||
|
usbReadFifo.pop_front();
|
||||||
payloadBytes.clear();
|
|
||||||
payloadBytes.resize(currentCommandLength);
|
payloadBytes.clear();
|
||||||
for(auto i = 0; i < currentCommandLength; i++) {
|
payloadBytes.resize(currentCommandLength);
|
||||||
payloadBytes[i] = usbReadFifo[0];
|
for(auto i = 0; i < currentCommandLength; i++) {
|
||||||
usbReadFifo.pop_front();
|
payloadBytes[i] = usbReadFifo[0];
|
||||||
}
|
usbReadFifo.pop_front();
|
||||||
|
}
|
||||||
if(packetizer.input(payloadBytes)) {
|
|
||||||
for(auto& packet : packetizer.output()) {
|
if(packetizer.input(payloadBytes)) {
|
||||||
auto msg = decoder.decodePacket(packet);
|
for(auto& packet : packetizer.output()) {
|
||||||
for(auto& cb : messageCallbacks) { // We might have closed while reading or processing
|
auto msg = decoder.decodePacket(packet);
|
||||||
if(!closing) {
|
for(auto& cb : messageCallbacks) { // We might have closed while reading or processing
|
||||||
cb.second.callIfMatch(msg);
|
if(!closing) {
|
||||||
}
|
cb.second.callIfMatch(msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
state = PreprocessState::SearchForCommand;
|
|
||||||
}
|
state = PreprocessState::SearchForCommand;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,157 +1,154 @@
|
||||||
#include "include/device.h"
|
#include "include/device.h"
|
||||||
#include "communication/include/messagecallback.h"
|
#include "communication/include/command.h"
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
using namespace icsneo;
|
using namespace icsneo;
|
||||||
|
|
||||||
static const uint8_t fromBase36Table[256] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
static const uint8_t fromBase36Table[256] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0, 0, 10, 11, 12,
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0, 0, 10, 11, 12,
|
||||||
13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 0, 0, 0, 0, 0, 0, 10, 11, 12, 13, 14, 15,
|
13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 0, 0, 0, 0, 0, 0, 10, 11, 12, 13, 14, 15,
|
||||||
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35 };
|
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35 };
|
||||||
|
|
||||||
static const char toBase36Table[36] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E',
|
static const char toBase36Table[36] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E',
|
||||||
'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z' };
|
'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z' };
|
||||||
|
|
||||||
static const uint32_t toBase36Powers[7] = { 1, 36, 1296, 46656, 1679616, 60466176, 2176782336 };
|
static const uint32_t toBase36Powers[7] = { 1, 36, 1296, 46656, 1679616, 60466176, 2176782336 };
|
||||||
|
|
||||||
#define MIN_BASE36_SERIAL (16796160)
|
#define MIN_BASE36_SERIAL (16796160)
|
||||||
#define MAX_SERIAL (2176782335)
|
#define MAX_SERIAL (2176782335)
|
||||||
|
|
||||||
std::string Device::SerialNumToString(uint32_t serial) {
|
std::string Device::SerialNumToString(uint32_t serial) {
|
||||||
if(serial == 0 || serial > MAX_SERIAL)
|
if(serial == 0 || serial > MAX_SERIAL)
|
||||||
return "0";
|
return "0";
|
||||||
|
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
if(serial >= MIN_BASE36_SERIAL) {
|
if(serial >= MIN_BASE36_SERIAL) {
|
||||||
for (auto i = 5; i >= 0; i--) {
|
for (auto i = 5; i >= 0; i--) {
|
||||||
ss << toBase36Table[serial / toBase36Powers[i]];
|
ss << toBase36Table[serial / toBase36Powers[i]];
|
||||||
serial = serial % toBase36Powers[i];
|
serial = serial % toBase36Powers[i];
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ss << serial;
|
ss << serial;
|
||||||
}
|
}
|
||||||
return ss.str();
|
return ss.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t Device::SerialStringToNum(const std::string& serial) {
|
uint32_t Device::SerialStringToNum(const std::string& serial) {
|
||||||
if(Device::SerialStringIsNumeric(serial)) {
|
if(Device::SerialStringIsNumeric(serial)) {
|
||||||
try {
|
try {
|
||||||
return std::stoi(serial);
|
return std::stoi(serial);
|
||||||
} catch(...) {
|
} catch(...) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(serial.length() != 6)
|
if(serial.length() != 6)
|
||||||
return 0; // Non-numeric serial numbers should be 6 characters
|
return 0; // Non-numeric serial numbers should be 6 characters
|
||||||
|
|
||||||
uint32_t ret = 0;
|
uint32_t ret = 0;
|
||||||
for (auto i = 0; i < 6; i++) {
|
for (auto i = 0; i < 6; i++) {
|
||||||
ret *= 36;
|
ret *= 36;
|
||||||
ret += fromBase36Table[(unsigned char)serial[i]];
|
ret += fromBase36Table[(unsigned char)serial[i]];
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Device::SerialStringIsNumeric(const std::string& serial) {
|
bool Device::SerialStringIsNumeric(const std::string& serial) {
|
||||||
if(serial.length() == 0)
|
if(serial.length() == 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if(serial.length() == 1)
|
if(serial.length() == 1)
|
||||||
return isdigit(serial[0]);
|
return isdigit(serial[0]);
|
||||||
|
|
||||||
// Check the first two characters, at least one should be a character if we need to do a base36 conversion
|
// Check the first two characters, at least one should be a character if we need to do a base36 conversion
|
||||||
return isdigit(serial[0]) && isdigit(serial[1]);
|
return isdigit(serial[0]) && isdigit(serial[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Device::enableMessagePolling() {
|
void Device::enableMessagePolling() {
|
||||||
if(messagePollingCallbackID != 0) // We are already polling
|
if(messagePollingCallbackID != 0) // We are already polling
|
||||||
return;
|
return;
|
||||||
|
|
||||||
messagePollingCallbackID = com->addMessageCallback(MessageCallback([this](std::shared_ptr<Message> message) {
|
messagePollingCallbackID = com->addMessageCallback(MessageCallback([this](std::shared_ptr<Message> message) {
|
||||||
pollingContainer.enqueue(message);
|
pollingContainer.enqueue(message);
|
||||||
enforcePollingMessageLimit();
|
enforcePollingMessageLimit();
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Device::disableMessagePolling() {
|
bool Device::disableMessagePolling() {
|
||||||
if(messagePollingCallbackID == 0)
|
if(messagePollingCallbackID == 0)
|
||||||
return true; // Not currently polling
|
return true; // Not currently polling
|
||||||
|
|
||||||
auto ret = com->removeMessageCallback(messagePollingCallbackID);
|
auto ret = com->removeMessageCallback(messagePollingCallbackID);
|
||||||
getMessages(); // Flush any messages still in the container
|
getMessages(); // Flush any messages still in the container
|
||||||
messagePollingCallbackID = 0;
|
messagePollingCallbackID = 0;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::shared_ptr<Message>> Device::getMessages() {
|
std::vector<std::shared_ptr<Message>> Device::getMessages() {
|
||||||
std::vector<std::shared_ptr<Message>> ret;
|
std::vector<std::shared_ptr<Message>> ret;
|
||||||
getMessages(ret);
|
getMessages(ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Device::getMessages(std::vector<std::shared_ptr<Message>>& container, size_t limit) {
|
bool Device::getMessages(std::vector<std::shared_ptr<Message>>& container, size_t limit) {
|
||||||
// A limit of zero indicates no limit
|
// A limit of zero indicates no limit
|
||||||
if(limit == 0)
|
if(limit == 0)
|
||||||
limit = (size_t)-1;
|
limit = (size_t)-1;
|
||||||
|
|
||||||
if(limit > (pollingContainer.size_approx() + 4))
|
if(limit > (pollingContainer.size_approx() + 4))
|
||||||
limit = (pollingContainer.size_approx() + 4);
|
limit = (pollingContainer.size_approx() + 4);
|
||||||
|
|
||||||
if(container.capacity() < limit)
|
if(container.capacity() < limit)
|
||||||
container.resize(limit);
|
container.resize(limit);
|
||||||
|
|
||||||
size_t actuallyRead = pollingContainer.try_dequeue_bulk(container.data(), limit);
|
size_t actuallyRead = pollingContainer.try_dequeue_bulk(container.data(), limit);
|
||||||
|
|
||||||
container.resize(actuallyRead);
|
container.resize(actuallyRead);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Device::enforcePollingMessageLimit() {
|
void Device::enforcePollingMessageLimit() {
|
||||||
while(pollingContainer.size_approx() > pollingMessageLimit) {
|
while(pollingContainer.size_approx() > pollingMessageLimit) {
|
||||||
std::shared_ptr<Message> throwAway;
|
std::shared_ptr<Message> throwAway;
|
||||||
pollingContainer.try_dequeue(throwAway);
|
pollingContainer.try_dequeue(throwAway);
|
||||||
// TODO Flag an error for the user!
|
// TODO Flag an error for the user!
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Device::open() {
|
bool Device::open() {
|
||||||
if(!com)
|
if(!com)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if(settings)
|
if(settings)
|
||||||
settings->refresh();
|
settings->refresh();
|
||||||
|
|
||||||
return com->open();
|
return com->open();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Device::close() {
|
bool Device::close() {
|
||||||
if(!com)
|
if(!com)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
settings = nullptr;
|
settings = nullptr;
|
||||||
|
|
||||||
return com->close();
|
return com->close();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Device::goOnline() {
|
bool Device::goOnline() {
|
||||||
std::string serial;
|
if(!com->sendCommand(Command::EnableNetworkCommunication, true))
|
||||||
while(!com->getSerialNumberSync(serial)) {
|
return false;
|
||||||
std::cout << "Serial number not here yet" << std::endl;
|
|
||||||
}
|
online = true;
|
||||||
|
return true;
|
||||||
if(!com->sendCommand(Communication::Command::EnableNetworkCommunication, true))
|
}
|
||||||
return false;
|
|
||||||
|
bool Device::goOffline() {
|
||||||
// if(!com->sendCommand(Communication::Command::RequestSerialNumber))
|
if(!com->sendCommand(Command::EnableNetworkCommunication, false))
|
||||||
// return false;
|
return false;
|
||||||
|
|
||||||
return online = true;
|
online = false;
|
||||||
}
|
return true;
|
||||||
|
|
||||||
bool Device::goOffline() {
|
|
||||||
return com->sendCommand(Communication::Command::EnableNetworkCommunication, false);
|
|
||||||
}
|
}
|
||||||
Loading…
Reference in New Issue