mirror of
https://github.com/wpilibsuite/allwpilib
synced 2026-06-23 01:21:42 +00:00
[hal] Add CAN Stream API to Java through JNI bindings (#4193)
The CAN Stream API allows defining an buffer to receive an arbitrary set of CAN messages, based on an ID and a mask. Messages are added to this queue separate of other CAN APIs. This means the messages can be receive without impacting other APIs such as vendor APIs. This enables things like detection of what devices are on the bus, or custom decoding, without using vendor APIs. Co-authored-by: Thad House <thadhouse1@gmail.com>
This commit is contained in:
@@ -91,4 +91,90 @@ Java_edu_wpi_first_hal_can_CANJNI_getCANStatus
|
||||
txFullCount, receiveErrorCount, transmitErrorCount);
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: edu_wpi_first_hal_can_CANJNI
|
||||
* Method: openCANStreamSession
|
||||
* Signature: (III)I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_edu_wpi_first_hal_can_CANJNI_openCANStreamSession
|
||||
(JNIEnv* env, jclass, jint messageID, jint messageIDMask, jint maxMessages)
|
||||
{
|
||||
uint32_t handle = 0;
|
||||
int32_t status = 0;
|
||||
HAL_CAN_OpenStreamSession(&handle, static_cast<uint32_t>(messageID),
|
||||
static_cast<uint32_t>(messageIDMask),
|
||||
static_cast<uint32_t>(maxMessages), &status);
|
||||
|
||||
if (!CheckStatus(env, status)) {
|
||||
return static_cast<jint>(0);
|
||||
}
|
||||
|
||||
return static_cast<jint>(handle);
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: edu_wpi_first_hal_can_CANJNI
|
||||
* Method: closeCANStreamSession
|
||||
* Signature: (I)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL
|
||||
Java_edu_wpi_first_hal_can_CANJNI_closeCANStreamSession
|
||||
(JNIEnv* env, jclass, jint sessionHandle)
|
||||
{
|
||||
HAL_CAN_CloseStreamSession(static_cast<uint32_t>(sessionHandle));
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: edu_wpi_first_hal_can_CANJNI
|
||||
* Method: readCANStreamSession
|
||||
* Signature: (I[Ljava/lang/Object;I)I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_edu_wpi_first_hal_can_CANJNI_readCANStreamSession
|
||||
(JNIEnv* env, jclass, jint sessionHandle, jobjectArray messages,
|
||||
jint messagesToRead)
|
||||
{
|
||||
uint32_t handle = static_cast<uint32_t>(sessionHandle);
|
||||
uint32_t messagesRead = 0;
|
||||
|
||||
wpi::SmallVector<HAL_CANStreamMessage, 16> messageBuffer;
|
||||
messageBuffer.resize_for_overwrite(messagesToRead);
|
||||
|
||||
int32_t status = 0;
|
||||
|
||||
HAL_CAN_ReadStreamSession(handle, messageBuffer.begin(),
|
||||
static_cast<uint32_t>(messagesToRead),
|
||||
&messagesRead, &status);
|
||||
|
||||
if (status == HAL_ERR_CANSessionMux_MessageNotFound || messagesRead == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!CheckStatus(env, status)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (int i = 0; i < static_cast<int>(messagesRead); i++) {
|
||||
struct HAL_CANStreamMessage* msg = &messageBuffer[i];
|
||||
JLocal<jobject> elem{
|
||||
env, static_cast<jstring>(env->GetObjectArrayElement(messages, i))};
|
||||
if (!elem) {
|
||||
// TODO decide if should throw
|
||||
continue;
|
||||
}
|
||||
JLocal<jbyteArray> toSetArray{
|
||||
env, SetCANStreamObject(env, elem, msg->dataSize, msg->messageID,
|
||||
msg->timeStamp)};
|
||||
auto javaLen = env->GetArrayLength(toSetArray);
|
||||
if (javaLen < msg->dataSize) {
|
||||
msg->dataSize = javaLen;
|
||||
}
|
||||
env->SetByteArrayRegion(toSetArray, 0, msg->dataSize,
|
||||
reinterpret_cast<jbyte*>(msg->data));
|
||||
}
|
||||
|
||||
return static_cast<jint>(messagesRead);
|
||||
}
|
||||
|
||||
} // extern "C"
|
||||
|
||||
Reference in New Issue
Block a user