Check serial number on device open, get correctly for PCAP devices
parent
72773d9afa
commit
69773d6537
|
|
@ -68,19 +68,20 @@ bool Communication::getSettingsSync(std::vector<uint8_t>& data, std::chrono::mil
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Communication::getSerialNumberSync(std::string& serial, std::chrono::milliseconds timeout) {
|
std::shared_ptr<SerialNumberMessage> Communication::getSerialNumberSync(std::chrono::milliseconds timeout) {
|
||||||
sendCommand(Command::RequestSerialNumber);
|
sendCommand(Command::RequestSerialNumber);
|
||||||
std::shared_ptr<Message> msg = waitForMessageSync(MessageFilter(Network::NetID::RED_OLDFORMAT), timeout);
|
std::shared_ptr<Message> msg = waitForMessageSync(std::make_shared<Main51MessageFilter>(Command::RequestSerialNumber), timeout);
|
||||||
if(!msg)
|
if(!msg) {
|
||||||
return false;
|
std::cout << "Didn't get a message in time" << std::endl;
|
||||||
|
return std::shared_ptr<SerialNumberMessage>();
|
||||||
std::cout << "Got " << msg->data.size() << " bytes" << std::endl;
|
|
||||||
for(size_t i = 0; i < msg->data.size(); i++) {
|
|
||||||
std::cout << std::hex << (int)msg->data[i] << ' ' << std::dec;
|
|
||||||
if(i % 16 == 15)
|
|
||||||
std::cout << std::endl;
|
|
||||||
}
|
}
|
||||||
return true;
|
auto m51 = std::dynamic_pointer_cast<Main51Message>(msg);
|
||||||
|
if(!m51) {
|
||||||
|
std::cout << "msg could not be cast to main51 " << msg->network << std::endl;
|
||||||
|
return std::shared_ptr<SerialNumberMessage>();
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::dynamic_pointer_cast<SerialNumberMessage>(m51);
|
||||||
}
|
}
|
||||||
|
|
||||||
int Communication::addMessageCallback(const MessageCallback& cb) {
|
int Communication::addMessageCallback(const MessageCallback& cb) {
|
||||||
|
|
@ -97,7 +98,7 @@ bool Communication::removeMessageCallback(int id) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<Message> Communication::waitForMessageSync(MessageFilter f, std::chrono::milliseconds timeout) {
|
std::shared_ptr<Message> Communication::waitForMessageSync(std::shared_ptr<MessageFilter> f, std::chrono::milliseconds timeout) {
|
||||||
std::mutex m;
|
std::mutex m;
|
||||||
std::condition_variable cv;
|
std::condition_variable cv;
|
||||||
std::shared_ptr<Message> returnedMessage;
|
std::shared_ptr<Message> returnedMessage;
|
||||||
|
|
|
||||||
|
|
@ -33,13 +33,14 @@ public:
|
||||||
virtual bool sendCommand(Command cmd, bool boolean) { return sendCommand(cmd, std::vector<uint8_t>({ (uint8_t)boolean })); }
|
virtual bool sendCommand(Command cmd, bool boolean) { return sendCommand(cmd, std::vector<uint8_t>({ (uint8_t)boolean })); }
|
||||||
virtual bool sendCommand(Command cmd, std::vector<uint8_t> arguments = {});
|
virtual bool sendCommand(Command cmd, std::vector<uint8_t> arguments = {});
|
||||||
bool getSettingsSync(std::vector<uint8_t>& data, 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));
|
std::shared_ptr<SerialNumberMessage> getSerialNumberSync(std::chrono::milliseconds timeout = std::chrono::milliseconds(50));
|
||||||
|
|
||||||
int addMessageCallback(const MessageCallback& cb);
|
int addMessageCallback(const MessageCallback& cb);
|
||||||
bool removeMessageCallback(int id);
|
bool removeMessageCallback(int id);
|
||||||
std::shared_ptr<Message> waitForMessageSync(MessageFilter f = MessageFilter(), std::chrono::milliseconds timeout = std::chrono::milliseconds(50));
|
std::shared_ptr<Message> waitForMessageSync(MessageFilter f = MessageFilter(), std::chrono::milliseconds timeout = std::chrono::milliseconds(50)) {
|
||||||
|
return waitForMessageSync(std::make_shared<MessageFilter>(f), timeout);
|
||||||
void setAlign16Bit(bool enable) { align16bit = enable; }
|
}
|
||||||
|
std::shared_ptr<Message> waitForMessageSync(std::shared_ptr<MessageFilter> f, std::chrono::milliseconds timeout = std::chrono::milliseconds(50));
|
||||||
|
|
||||||
std::shared_ptr<Packetizer> packetizer;
|
std::shared_ptr<Packetizer> packetizer;
|
||||||
std::shared_ptr<MessageDecoder> decoder;
|
std::shared_ptr<MessageDecoder> decoder;
|
||||||
|
|
@ -52,7 +53,6 @@ protected:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool isOpen = false;
|
bool isOpen = false;
|
||||||
bool align16bit = true; // Not needed for Gigalog, Galaxy, etc and newer
|
|
||||||
|
|
||||||
std::thread readTaskThread;
|
std::thread readTaskThread;
|
||||||
void readTask();
|
void readTask();
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
#include "communication/include/messagedecoder.h"
|
#include "communication/include/messagedecoder.h"
|
||||||
#include "communication/include/communication.h"
|
#include "communication/include/communication.h"
|
||||||
|
#include "communication/message/include/serialnumbermessage.h"
|
||||||
#include "communication/include/command.h"
|
#include "communication/include/command.h"
|
||||||
#include "device/include/device.h"
|
#include "device/include/device.h"
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
@ -33,7 +34,42 @@ std::shared_ptr<Message> MessageDecoder::decodePacket(const std::shared_ptr<Pack
|
||||||
return msg;
|
return msg;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
// TODO Implement others
|
switch(packet->network.getNetID()) {
|
||||||
|
case Network::NetID::Main51: {
|
||||||
|
switch((Command)packet->data[0]) {
|
||||||
|
case Command::RequestSerialNumber: {
|
||||||
|
auto msg = std::make_shared<SerialNumberMessage>();
|
||||||
|
msg->network = packet->network;
|
||||||
|
uint64_t serial = GetUInt64FromLEBytes(packet->data.data() + 1);
|
||||||
|
// The device sends 64-bits of serial number, but we never use more than 32-bits.
|
||||||
|
msg->deviceSerial = Device::SerialNumToString((uint32_t)serial);
|
||||||
|
msg->hasMacAddress = packet->data.size() >= 15;
|
||||||
|
if(msg->hasMacAddress)
|
||||||
|
memcpy(msg->macAddress, packet->data.data() + 9, sizeof(msg->macAddress));
|
||||||
|
msg->hasPCBSerial = packet->data.size() >= 31;
|
||||||
|
if(msg->hasPCBSerial)
|
||||||
|
memcpy(msg->pcbSerial, packet->data.data() + 15, sizeof(msg->pcbSerial));
|
||||||
|
return msg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Network::NetID::RED_OLDFORMAT: {
|
||||||
|
/* So-called "old format" messages are a "new style, long format" wrapper around the old short messages.
|
||||||
|
* They consist of a 16-bit LE length first, then the 8-bit length and netid combo byte, then the payload
|
||||||
|
* with no checksum. The upper-nibble length of the combo byte should be ignored completely, using the
|
||||||
|
* length from the first two bytes in it's place. Ideally, we never actually send the oldformat messages
|
||||||
|
* out to the rest of the application as they can recursively get decoded to another message type here.
|
||||||
|
* Feed the result back into the decoder in case we do something special with the resultant netid.
|
||||||
|
*/
|
||||||
|
uint16_t length = packet->data[0] | (packet->data[1] << 8);
|
||||||
|
packet->network = Network(packet->data[2] & 0xF);
|
||||||
|
packet->data.erase(packet->data.begin(), packet->data.begin() + 3);
|
||||||
|
if(packet->data.size() != length)
|
||||||
|
packet->data.resize(length);
|
||||||
|
return decodePacket(packet);
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -54,7 +54,7 @@ bool Packetizer::input(const std::vector<uint8_t>& inputBytes) {
|
||||||
headerSize = 6;
|
headerSize = 6;
|
||||||
} else {
|
} else {
|
||||||
state = ReadState::GetData;
|
state = ReadState::GetData;
|
||||||
checksum = true;
|
checksum = true; // Even if checksum is not explicitly disallowed, we enable it here, as this goes into length calculation
|
||||||
headerSize = 2;
|
headerSize = 2;
|
||||||
packetLength += 2; // The packet length given in short packets does not include header
|
packetLength += 2; // The packet length given in short packets does not include header
|
||||||
}
|
}
|
||||||
|
|
@ -99,10 +99,10 @@ bool Packetizer::input(const std::vector<uint8_t>& inputBytes) {
|
||||||
while(currentIndex < packetLength)
|
while(currentIndex < packetLength)
|
||||||
packet.data[i++] = bytes[currentIndex++];
|
packet.data[i++] = bytes[currentIndex++];
|
||||||
|
|
||||||
if(!checksum || bytes[currentIndex] == Communication::ICSChecksum(packet.data)) {
|
if(disableChecksum || !checksum || bytes[currentIndex] == ICSChecksum(packet.data)) {
|
||||||
// Got a good packet
|
// Got a good packet
|
||||||
gotGoodPackets = true;
|
gotGoodPackets = true;
|
||||||
processedPackets.push_back(std::make_shared<Communication::Packet>(packet));
|
processedPackets.push_back(std::make_shared<Packet>(packet));
|
||||||
for (auto a = 0; a < packetLength; a++)
|
for (auto a = 0; a < packetLength; a++)
|
||||||
bytes.pop_front();
|
bytes.pop_front();
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -123,10 +123,37 @@ bool Device::open() {
|
||||||
if(!com)
|
if(!com)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
if(!com->open())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
auto serial = com->getSerialNumberSync();
|
||||||
|
int i = 0;
|
||||||
|
while(!serial) {
|
||||||
|
serial = com->getSerialNumberSync();
|
||||||
|
if(i++ > 5)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(!serial) {
|
||||||
|
std::cout << "Failed to get serial number in " << i << " tries" << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(i != 0)
|
||||||
|
std::cout << "Took " << i << " tries to get the serial number" << std::endl;
|
||||||
|
|
||||||
|
std::string currentSerial = getNeoDevice().serial;
|
||||||
|
if(currentSerial == SERIAL_FIND_ON_OPEN) {
|
||||||
|
strncpy(getWritableNeoDevice().serial, serial->deviceSerial.c_str(), sizeof(getNeoDevice().serial));
|
||||||
|
getWritableNeoDevice().serial[sizeof(getWritableNeoDevice().serial) - 1] = '\0';
|
||||||
|
} else if(currentSerial != serial->deviceSerial) {
|
||||||
|
std::cout << "NeoDevice has serial " << getNeoDevice().serial << " but device has serial " << serial->deviceSerial.c_str() << "!" << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if(settings)
|
if(settings)
|
||||||
settings->refresh();
|
settings->refresh();
|
||||||
|
|
||||||
return com->open();
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Device::close() {
|
bool Device::close() {
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,8 @@ namespace icsneo {
|
||||||
|
|
||||||
class Device {
|
class Device {
|
||||||
public:
|
public:
|
||||||
|
static constexpr char* SERIAL_FIND_ON_OPEN = "xxxxxx";
|
||||||
|
|
||||||
Device(neodevice_t neodevice = {}) {
|
Device(neodevice_t neodevice = {}) {
|
||||||
data = neodevice;
|
data = neodevice;
|
||||||
data.device = this;
|
data.device = this;
|
||||||
|
|
|
||||||
|
|
@ -134,13 +134,15 @@ std::vector<neodevice_t> PCAP::FindByProduct(int product) {
|
||||||
if(product != packet.srcMAC[3]) // This is where the PID is stored in the MAC
|
if(product != packet.srcMAC[3]) // This is where the PID is stored in the MAC
|
||||||
continue; // This is not a product we're currently looking for
|
continue; // This is not a product we're currently looking for
|
||||||
|
|
||||||
std::string serialFromMAC = GetEthDevSerialFromMacAddress(packet.srcMAC[3], ((packet.srcMAC[4] << 8) | packet.srcMAC[5]));
|
|
||||||
neodevice_t neodevice;
|
neodevice_t neodevice;
|
||||||
#pragma warning(push)
|
/* Unlike other transport layers, we can't get the serial number here as we
|
||||||
#pragma warning(disable:4996)
|
* actually need to open the device in the find method and then request it
|
||||||
strncpy(neodevice.serial, serialFromMAC.c_str(), sizeof(neodevice.serial));
|
* over a working communication layer. We could technically create a communication
|
||||||
neodevice.serial[sizeof(neodevice.serial) - 1] = 0;
|
* layer to parse the packet we have in `data` at this point, but we'd need to
|
||||||
#pragma warning(pop)
|
* know information about the device to correctly instantiate a packetizer and
|
||||||
|
* decoder. I'm intentionally avoiding passing that information down here for
|
||||||
|
* code quality's sake.
|
||||||
|
*/
|
||||||
neodevice.handle = (neodevice_handle_t)((i << 24) | (packet.srcMAC[3] << 16) | (packet.srcMAC[4] << 8) | (packet.srcMAC[5]));
|
neodevice.handle = (neodevice_handle_t)((i << 24) | (packet.srcMAC[3] << 16) | (packet.srcMAC[4] << 8) | (packet.srcMAC[5]));
|
||||||
bool alreadyExists = false;
|
bool alreadyExists = false;
|
||||||
for(auto& dev : foundDevices)
|
for(auto& dev : foundDevices)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue