Allow polling for messages from C
parent
f1f1cb1701
commit
63d13cdb88
|
|
@ -12,6 +12,7 @@
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
using namespace icsneo;
|
using namespace icsneo;
|
||||||
|
|
||||||
|
|
@ -21,6 +22,9 @@ static std::vector<std::shared_ptr<Device>> connectableFoundDevices, connectedDe
|
||||||
// Any shared_ptrs we've let go should be placed here so they're not accessed
|
// Any shared_ptrs we've let go should be placed here so they're not accessed
|
||||||
static std::vector<Device*> freedDevices;
|
static std::vector<Device*> freedDevices;
|
||||||
|
|
||||||
|
// We store an array of shared_ptr messages per device (by serial), this means we own the memory of the data pointer
|
||||||
|
static std::map<std::string, std::vector<std::shared_ptr<Message>>> polledMessageStorage;
|
||||||
|
|
||||||
void icsneoFindAllDevices(neodevice_t* devices, size_t* count) {
|
void icsneoFindAllDevices(neodevice_t* devices, size_t* count) {
|
||||||
icsneoFreeUnconnectedDevices(); // Mark previous results as freed so they can no longer be connected to
|
icsneoFreeUnconnectedDevices(); // Mark previous results as freed so they can no longer be connected to
|
||||||
auto foundDevices = icsneo::FindAllDevices();
|
auto foundDevices = icsneo::FindAllDevices();
|
||||||
|
|
@ -127,4 +131,64 @@ bool icsneoIsOnline(const neodevice_t* device) {
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return device->device->isOnline();
|
return device->device->isOnline();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool icsneoEnableMessagePolling(const neodevice_t* device) {
|
||||||
|
if(!icsneoIsValidNeoDevice(device))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
device->device->enableMessagePolling();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool icsneoDisableMessagePolling(const neodevice_t* device) {
|
||||||
|
if(!icsneoIsValidNeoDevice(device))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return device->device->disableMessagePolling();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool icsneoGetMessages(const neodevice_t* device, neomessage_t* messages, size_t* items) {
|
||||||
|
if(!icsneoIsValidNeoDevice(device))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if(items == nullptr)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if(messages == nullptr) {
|
||||||
|
// A NULL value for messages means the user wants the current size of the buffer into items
|
||||||
|
*items = device->device->getCurrentMessageCount();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::shared_ptr<Message>>& storage = polledMessageStorage[device->serial];
|
||||||
|
|
||||||
|
if(!device->device->getMessages(storage, *items))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
*items = storage.size();
|
||||||
|
|
||||||
|
for(size_t i = 0; i < *items; i++) {
|
||||||
|
// For each message, copy into neomessage_t buffer given
|
||||||
|
messages[i] = CreateNeoMessage(*(storage[i]));
|
||||||
|
}
|
||||||
|
|
||||||
|
// The user now has until the next call of icsneoGetMessages (for this device) to use the data, after which point it's freed
|
||||||
|
// The user should copy the data out if they want it
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t icsneoGetPollingMessageLimit(const neodevice_t* device) {
|
||||||
|
if(!icsneoIsValidNeoDevice(device))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return device->device->getPollingMessageLimit();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool icsneoSetPollingMessageLimit(const neodevice_t* device, size_t newLimit) {
|
||||||
|
if(!icsneoIsValidNeoDevice(device))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
device->device->setPollingMessageLimit(newLimit);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include "device/include/neodevice.h" // For neodevice_t
|
#include "device/include/neodevice.h" // For neodevice_t
|
||||||
|
#include "communication/message/include/neomessage.h" // For neomessage_t and friends
|
||||||
#include "platform/include/dynamiclib.h" // Dynamic library loading and exporting
|
#include "platform/include/dynamiclib.h" // Dynamic library loading and exporting
|
||||||
|
|
||||||
#ifndef ICSNEOC_DYNAMICLOAD
|
#ifndef ICSNEOC_DYNAMICLOAD
|
||||||
|
|
@ -31,6 +32,16 @@ extern bool DLLExport icsneoGoOffline(const neodevice_t* device);
|
||||||
|
|
||||||
extern bool DLLExport icsneoIsOnline(const neodevice_t* device);
|
extern bool DLLExport icsneoIsOnline(const neodevice_t* device);
|
||||||
|
|
||||||
|
extern bool DLLExport icsneoEnableMessagePolling(const neodevice_t* device);
|
||||||
|
|
||||||
|
extern bool DLLExport icsneoDisableMessagePolling(const neodevice_t* device);
|
||||||
|
|
||||||
|
extern bool DLLExport icsneoGetMessages(const neodevice_t* device, neomessage_t* messages, size_t* items);
|
||||||
|
|
||||||
|
extern size_t DLLExport icsneoGetPollingMessageLimit(const neodevice_t* device);
|
||||||
|
|
||||||
|
extern bool DLLExport icsneoSetPollingMessageLimit(const neodevice_t* device, size_t newLimit);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -67,6 +78,21 @@ fn_icsneoGoOffline icsneoGoOffline;
|
||||||
typedef bool(*fn_icsneoIsOnline)(const neodevice_t* device);
|
typedef bool(*fn_icsneoIsOnline)(const neodevice_t* device);
|
||||||
fn_icsneoIsOnline icsneoIsOnline;
|
fn_icsneoIsOnline icsneoIsOnline;
|
||||||
|
|
||||||
|
typedef bool(*fn_icsneoEnableMessagePolling)(const neodevice_t* device);
|
||||||
|
fn_icsneoEnableMessagePolling icsneoEnableMessagePolling;
|
||||||
|
|
||||||
|
typedef bool(*fn_icsneoDisableMessagePolling)(const neodevice_t* device);
|
||||||
|
fn_icsneoDisableMessagePolling icsneoDisableMessagePolling;
|
||||||
|
|
||||||
|
typedef bool(*fn_icsneoGetMessages)(const neodevice_t* device, neomessage_t* messages, size_t* items);
|
||||||
|
fn_icsneoGetMessages icsneoGetMessages;
|
||||||
|
|
||||||
|
typedef size_t(*fn_icsneoGetPollingMessageLimit)(const neodevice_t* device);
|
||||||
|
fn_icsneoGetPollingMessageLimit icsneoGetPollingMessageLimit;
|
||||||
|
|
||||||
|
typedef bool(*fn_icsneoSetPollingMessageLimit)(const neodevice_t* device, size_t newLimit);
|
||||||
|
fn_icsneoSetPollingMessageLimit icsneoSetPollingMessageLimit;
|
||||||
|
|
||||||
#define ICSNEO_IMPORT(func) func = (fn_##func)icsneoDynamicLibraryGetFunction(icsneoLibraryHandle, #func)
|
#define ICSNEO_IMPORT(func) func = (fn_##func)icsneoDynamicLibraryGetFunction(icsneoLibraryHandle, #func)
|
||||||
#define ICSNEO_IMPORTASSERT(func) if((ICSNEO_IMPORT(func)) == NULL) return 3
|
#define ICSNEO_IMPORTASSERT(func) if((ICSNEO_IMPORT(func)) == NULL) return 3
|
||||||
void* icsneoLibraryHandle = NULL;
|
void* icsneoLibraryHandle = NULL;
|
||||||
|
|
@ -91,6 +117,11 @@ int icsneoInit() {
|
||||||
ICSNEO_IMPORTASSERT(icsneoGoOnline);
|
ICSNEO_IMPORTASSERT(icsneoGoOnline);
|
||||||
ICSNEO_IMPORTASSERT(icsneoGoOffline);
|
ICSNEO_IMPORTASSERT(icsneoGoOffline);
|
||||||
ICSNEO_IMPORTASSERT(icsneoIsOnline);
|
ICSNEO_IMPORTASSERT(icsneoIsOnline);
|
||||||
|
ICSNEO_IMPORTASSERT(icsneoEnableMessagePolling);
|
||||||
|
ICSNEO_IMPORTASSERT(icsneoDisableMessagePolling);
|
||||||
|
ICSNEO_IMPORTASSERT(icsneoGetMessages);
|
||||||
|
ICSNEO_IMPORTASSERT(icsneoGetPollingMessageLimit);
|
||||||
|
ICSNEO_IMPORTASSERT(icsneoSetPollingMessageLimit);
|
||||||
|
|
||||||
icsneoInitialized = true;
|
icsneoInitialized = true;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,34 @@
|
||||||
|
#ifndef __NEOMESSAGE_H_
|
||||||
|
#define __NEOMESSAGE_H_
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint16_t netid;
|
||||||
|
uint8_t type;
|
||||||
|
char header[4];
|
||||||
|
const uint8_t* data;
|
||||||
|
size_t length;
|
||||||
|
uint64_t timestamp;
|
||||||
|
char reserved[8];
|
||||||
|
} neomessage_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint16_t netid;
|
||||||
|
uint8_t type;
|
||||||
|
uint32_t arbid;
|
||||||
|
const uint8_t* data;
|
||||||
|
size_t length;
|
||||||
|
uint64_t timestamp;
|
||||||
|
char reserved[8];
|
||||||
|
} neomessage_can_t;
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
#include "communication/message/include/message.h"
|
||||||
|
|
||||||
|
namespace icsneo {
|
||||||
|
neomessage_t CreateNeoMessage(const Message& message);
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -0,0 +1,24 @@
|
||||||
|
#include "communication/message/include/neomessage.h"
|
||||||
|
#include "communication/message/include/canmessage.h"
|
||||||
|
|
||||||
|
using namespace icsneo;
|
||||||
|
|
||||||
|
neomessage_t icsneo::CreateNeoMessage(const Message& message) {
|
||||||
|
// This function is not responsible for storing the message!
|
||||||
|
// Keep the shared_ptr around for the lifetime of the data access
|
||||||
|
const auto type = message.network.getType();
|
||||||
|
neomessage_t neomsg = { 0 }; // Clear out the memory
|
||||||
|
neomsg.netid = (uint32_t)message.network.getNetID();
|
||||||
|
neomsg.type = (uint8_t)type;
|
||||||
|
neomsg.length = message.data.size();
|
||||||
|
neomsg.data = message.data.data();
|
||||||
|
neomsg.timestamp = message.timestamp;
|
||||||
|
|
||||||
|
switch(type) {
|
||||||
|
case Network::Type::CAN:
|
||||||
|
((neomessage_can_t*)&neomsg)->arbid = ((const CANMessage*)&message)->arbid;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return neomsg;
|
||||||
|
}
|
||||||
|
|
@ -94,7 +94,6 @@ std::vector<std::shared_ptr<Message>> Device::getMessages() {
|
||||||
|
|
||||||
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
|
||||||
auto oglimit = limit;
|
|
||||||
if(limit == 0)
|
if(limit == 0)
|
||||||
limit = (size_t)-1;
|
limit = (size_t)-1;
|
||||||
|
|
||||||
|
|
@ -108,7 +107,7 @@ bool Device::getMessages(std::vector<std::shared_ptr<Message>>& container, size_
|
||||||
|
|
||||||
container.resize(actuallyRead);
|
container.resize(actuallyRead);
|
||||||
|
|
||||||
return actuallyRead <= oglimit;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Device::enforcePollingMessageLimit() {
|
void Device::enforcePollingMessageLimit() {
|
||||||
|
|
@ -140,14 +139,6 @@ bool Device::goOnline() {
|
||||||
if(!com->sendCommand(Communication::Command::RequestSerialNumber))
|
if(!com->sendCommand(Communication::Command::RequestSerialNumber))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
com->addMessageCallback(CANMessageCallback([](std::shared_ptr<Message> message) {
|
|
||||||
std::shared_ptr<CANMessage> canMessage = std::static_pointer_cast<CANMessage>(message);
|
|
||||||
std::cout << "CAN 0x" << std::hex << canMessage->arbid << std::dec << " [" << canMessage->data.size() << "] " << std::hex;
|
|
||||||
for(const auto& b : canMessage->data)
|
|
||||||
std::cout << (int)b << ' ';
|
|
||||||
std::cout << std::dec << std::endl;
|
|
||||||
}));
|
|
||||||
|
|
||||||
return online = true;
|
return online = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -43,6 +43,7 @@ public:
|
||||||
bool disableMessagePolling();
|
bool disableMessagePolling();
|
||||||
std::vector<std::shared_ptr<Message>> getMessages();
|
std::vector<std::shared_ptr<Message>> getMessages();
|
||||||
bool getMessages(std::vector<std::shared_ptr<Message>>& container, size_t limit = 0);
|
bool getMessages(std::vector<std::shared_ptr<Message>>& container, size_t limit = 0);
|
||||||
|
size_t getCurrentMessageCount() { return pollingContainer.size_approx(); }
|
||||||
size_t getPollingMessageLimit() { return pollingMessageLimit; }
|
size_t getPollingMessageLimit() { return pollingMessageLimit; }
|
||||||
void setPollingMessageLimit(size_t newSize) {
|
void setPollingMessageLimit(size_t newSize) {
|
||||||
pollingMessageLimit = newSize;
|
pollingMessageLimit = newSize;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue