mirror of
https://github.com/intrepidcs/libicsneo.git
synced 2026-08-05 09:28:40 +02:00
API: Added icsneoc2.
Signed-off-by: David Rebbe <drebbe@intrepidcs.com>
This commit is contained in:
@@ -0,0 +1,333 @@
|
||||
use icsneoc2rs::ffi::_icsneoc2_msg_bus_type_t::*;
|
||||
use icsneoc2rs::ffi::_icsneoc2_msg_type_t::*;
|
||||
use icsneoc2rs::ffi::_icsneoc2_netid_t;
|
||||
use icsneoc2rs::ffi::_icsneoc2_netid_t::*;
|
||||
use icsneoc2rs::ffi::_icsneoc2_open_options_t::*;
|
||||
use icsneoc2rs::ffi::icsneoc2_message_t;
|
||||
use icsneoc2rs::ffi::icsneoc2_msg_bus_type_t;
|
||||
use icsneoc2rs::ffi::icsneoc2_msg_type_t;
|
||||
use icsneoc2rs::ffi::icsneoc2_netid_t;
|
||||
use icsneoc2rs::Device;
|
||||
use icsneoc2rs::Error;
|
||||
use icsneoc2rs::Result as ICSNeoResult;
|
||||
|
||||
use scopeguard::defer;
|
||||
|
||||
fn main() -> ICSNeoResult<()> {
|
||||
print!("Finding devices... ");
|
||||
let devices = Device::find_all(255)?;
|
||||
println!(
|
||||
"OK, {} device{} found...",
|
||||
devices.len(),
|
||||
if devices.len() > 1 { "s" } else { "" }
|
||||
);
|
||||
for device in devices {
|
||||
device.device_is_valid()?;
|
||||
// Get description of the device
|
||||
let description = match device.device_description_get() {
|
||||
Ok(description) => description,
|
||||
Err(err) => {
|
||||
println!("Failed to get description of device: {err}");
|
||||
continue;
|
||||
}
|
||||
};
|
||||
println!("{} @ Handle {:?}", description, device.handle);
|
||||
// Get/Set open options
|
||||
let mut open_options = match device.device_open_options_get() {
|
||||
Ok(value) => value,
|
||||
Err(err) => {
|
||||
println!("Failed to get open options of device: {err}");
|
||||
continue;
|
||||
}
|
||||
};
|
||||
// Disable Syncing RTC and going online
|
||||
open_options &= !(icsneoc2_open_options_sync_rtc as u32);
|
||||
open_options &= !(icsneoc2_open_options_go_online as u32);
|
||||
match device.device_open_options_set(open_options) {
|
||||
Ok(value) => value,
|
||||
Err(err) => {
|
||||
print_error(&device, &description, err);
|
||||
continue;
|
||||
}
|
||||
};
|
||||
println!("\tDevice open options: {open_options:#02x}");
|
||||
// Open the device
|
||||
print!("\tOpening device... ");
|
||||
match device.device_open() {
|
||||
Ok(value) => value,
|
||||
Err(err) => {
|
||||
print_error(&device, &description, err);
|
||||
continue;
|
||||
}
|
||||
};
|
||||
println!("OK");
|
||||
defer! {
|
||||
print_device_events(&device, &description).expect("Critical: Failed to print device events");
|
||||
}
|
||||
// Get timestamp resolution of the device
|
||||
print!("\tGetting timestamp resolution... ");
|
||||
let timestamp_resolution = match device.device_timestamp_resolution_get() {
|
||||
Ok(value) => value,
|
||||
Err(err) => {
|
||||
print_error(&device, &description, err);
|
||||
continue;
|
||||
}
|
||||
};
|
||||
println!("{timestamp_resolution}ns");
|
||||
// Get baudrates for HSCAN
|
||||
print!("\tGetting HSCAN baudrate... ");
|
||||
let baudrate = match device.device_baudrate_get(icsneoc2_netid_hscan) {
|
||||
Ok(value) => value,
|
||||
Err(err) => {
|
||||
print_error(&device, &description, err);
|
||||
continue;
|
||||
}
|
||||
};
|
||||
println!("{baudrate}mbit/s");
|
||||
// Get FD baudrates for HSCAN
|
||||
print!("\tGetting FD HSCAN baudrate... ");
|
||||
let fd_baudrate = match device.device_canfd_baudrate_get(icsneoc2_netid_hscan) {
|
||||
Ok(value) => value,
|
||||
Err(err) => {
|
||||
print_error(&device, &description, err);
|
||||
continue;
|
||||
}
|
||||
};
|
||||
println!("{fd_baudrate}mbit/s");
|
||||
// Set baudrates for HSCAN
|
||||
// saveToDevice: If this is set to true, the baudrate will be saved on the device
|
||||
// and will persist through a power cycle
|
||||
print!("\tSetting HSCAN baudrate... ");
|
||||
let save_to_device = false;
|
||||
match device.device_baudrate_set(icsneoc2_netid_hscan, baudrate, save_to_device) {
|
||||
Ok(value) => value,
|
||||
Err(err) => {
|
||||
print_error(&device, &description, err);
|
||||
continue;
|
||||
}
|
||||
};
|
||||
println!("OK");
|
||||
// Set FD baudrates for HSCAN
|
||||
print!("\tSetting FD HSCAN baudrate... ");
|
||||
match device.device_canfd_baudrate_set(icsneoc2_netid_hscan, fd_baudrate, save_to_device) {
|
||||
Ok(value) => value,
|
||||
Err(err) => {
|
||||
print_error(&device, &description, err);
|
||||
continue;
|
||||
}
|
||||
};
|
||||
println!("OK");
|
||||
// Get RTC
|
||||
print!("\tGetting RTC... ");
|
||||
let current_rtc = match device.device_rtc_get() {
|
||||
Ok(value) => value,
|
||||
Err(err) => {
|
||||
print_error(&device, &description, err);
|
||||
continue;
|
||||
}
|
||||
};
|
||||
println!("{current_rtc}");
|
||||
// Set RTC
|
||||
print!("\tSetting RTC... ");
|
||||
match device.device_rtc_set(current_rtc) {
|
||||
Ok(value) => value,
|
||||
Err(err) => {
|
||||
print_error(&device, &description, err);
|
||||
continue;
|
||||
}
|
||||
};
|
||||
println!("OK");
|
||||
// Get RTC
|
||||
print!("\tGetting RTC... ");
|
||||
let rtc = match device.device_rtc_get() {
|
||||
Ok(value) => value,
|
||||
Err(err) => {
|
||||
print_error(&device, &description, err);
|
||||
continue;
|
||||
}
|
||||
};
|
||||
println!("{rtc}");
|
||||
// Go online, start acking traffic
|
||||
print!("\tGoing online... ");
|
||||
match device.device_go_online(true) {
|
||||
Ok(value) => value,
|
||||
Err(err) => {
|
||||
print_error(&device, &description, err);
|
||||
continue;
|
||||
}
|
||||
};
|
||||
// Redundant check to show how to check if the device is online, if the previous
|
||||
// icsneoc2_device_go_online call was successful we can assume we are online already
|
||||
let is_online = match device.device_is_online() {
|
||||
Ok(value) => value,
|
||||
Err(err) => {
|
||||
print_error(&device, &description, err);
|
||||
continue;
|
||||
}
|
||||
};
|
||||
println!("{}", if is_online { "Online" } else { "Offline" });
|
||||
// Transmit CAN messages
|
||||
if transmit_can_messages(&device).is_err() {
|
||||
continue;
|
||||
}
|
||||
println!("\tWaiting 1 second for messages...");
|
||||
std::thread::sleep(std::time::Duration::from_secs(1));
|
||||
// Get the messages
|
||||
let messages = match device.device_messages_get(20000, 3000) {
|
||||
Ok(messages) => messages,
|
||||
Err(err) => {
|
||||
print_error(&device, &description, err);
|
||||
continue;
|
||||
}
|
||||
};
|
||||
// Process the messages
|
||||
if process_messages(&device, messages).is_err() {
|
||||
continue;
|
||||
}
|
||||
// Close the device
|
||||
print!("\tClosing device... ");
|
||||
match device.device_close() {
|
||||
Ok(value) => value,
|
||||
Err(err) => {
|
||||
print_error(&device, &description, err);
|
||||
continue;
|
||||
}
|
||||
};
|
||||
println!("OK");
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn print_error(device: &Device, device_description: &String, err: Error) {
|
||||
println!("Failed: {err}");
|
||||
print_device_events(device, device_description)
|
||||
.expect("Critical: Failed to print device events");
|
||||
}
|
||||
|
||||
fn transmit_can_messages(device: &Device) -> ICSNeoResult<()> {
|
||||
const MESSAGE_COUNT: usize = 100;
|
||||
println!("\tTransmitting {MESSAGE_COUNT} messages...");
|
||||
for i in 0..MESSAGE_COUNT {
|
||||
let message = match device.message_can_create(1) {
|
||||
Ok(messages) => messages[0],
|
||||
Err(err) => {
|
||||
println!("Failed to create CAN message #{i}: {err}");
|
||||
continue;
|
||||
}
|
||||
};
|
||||
device.message_netid_set(message, icsneoc2_netid_hscan)?;
|
||||
device.message_can_arbid_set(message, 0x10)?;
|
||||
device.message_can_canfd_set(message, true)?;
|
||||
device.message_can_extended_set(message, true)?;
|
||||
device.message_can_baudrate_switch_set(message, true)?;
|
||||
device.message_data_set(
|
||||
message,
|
||||
vec![
|
||||
(i >> 56 & 0xFF) as u8,
|
||||
(i >> 48 & 0xFF) as u8,
|
||||
(i >> 40 & 0xFF) as u8,
|
||||
(i >> 32 & 0xFF) as u8,
|
||||
(i >> 24 & 0xFF) as u8,
|
||||
(i >> 16 & 0xFF) as u8,
|
||||
(i >> 8 & 0xFF) as u8,
|
||||
(i & 0xFF) as u8,
|
||||
],
|
||||
)?;
|
||||
device.message_can_dlc_set(message, -1)?;
|
||||
device.device_messages_transmit(vec![message])?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn process_messages(device: &Device, messages: Vec<*mut icsneoc2_message_t>) -> ICSNeoResult<()> {
|
||||
let mut tx_count: u32 = 0;
|
||||
for (i, message) in messages.iter().enumerate() {
|
||||
// Get the message type
|
||||
let msg_type = device.message_type_get(*message)?;
|
||||
// Get the message type name
|
||||
let msg_type_name = device.message_type_name_get(msg_type)?;
|
||||
// Check if the message is a bus message, ignore otherwise
|
||||
if msg_type != icsneoc2_msg_type_bus as icsneoc2_msg_type_t {
|
||||
println!("\tIgnoring message type : {msg_type} ({msg_type_name})");
|
||||
continue;
|
||||
}
|
||||
// Get the message bus type
|
||||
let msg_bus_type = device.message_bus_type_get(*message)?;
|
||||
// Get the message type name
|
||||
let msg_bus_type_name = device.bus_type_name_get(msg_bus_type)?;
|
||||
// Check if message is a transmit message
|
||||
if device.message_is_transmit(*message)? {
|
||||
tx_count += 1;
|
||||
continue;
|
||||
}
|
||||
println!("\t{i} Message type: {msg_type} bus type: {msg_bus_type_name} ({msg_bus_type})\n");
|
||||
// Check if the message is a CAN message, ignore otherwise
|
||||
if msg_bus_type == icsneoc2_msg_bus_type_can as icsneoc2_msg_bus_type_t {
|
||||
let netid = device.message_netid_get(*message)?;
|
||||
let netid_name = device.netid_name_get(netid)?;
|
||||
let arbid = device.message_can_arbid_get(*message)?;
|
||||
let dlc = device.message_can_dlc_get(*message)?;
|
||||
let is_remote = device.message_can_is_remote(*message)?;
|
||||
let is_canfd = device.message_can_is_canfd(*message)?;
|
||||
let is_extended = device.message_can_is_extended(*message)?;
|
||||
let data = device.message_data_get(*message, 64)?;
|
||||
// Finally lets print the RX message
|
||||
println!("\t NetID: {netid_name} ({:#02x})\tArbID: {arbid:#02x}\t DLC: {dlc}\t Remote: {is_remote}\t \
|
||||
CANFD: {is_canfd}\t Extended: {is_extended}\t Data length: {}\n", netid as icsneoc2_netid_t,data.len());
|
||||
println!("\t Data: {data:#02x?}\n");
|
||||
} else {
|
||||
println!("\tIgnoring bus message type: {msg_bus_type} ({msg_bus_type_name})\n");
|
||||
}
|
||||
}
|
||||
println!(
|
||||
"\tReceived {} messages total, {} were TX messages",
|
||||
messages.len(),
|
||||
tx_count
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn print_device_events(device: &Device, device_description: &String) -> ICSNeoResult<()> {
|
||||
let events = match device.device_events_get(1024) {
|
||||
Ok(events) => events,
|
||||
Err(err) => {
|
||||
println!("Failed to get device events: {err}");
|
||||
return Err(err);
|
||||
}
|
||||
};
|
||||
for (i, event) in events.iter().enumerate() {
|
||||
let description = match device.event_description_get(*event) {
|
||||
Ok(description) => description,
|
||||
Err(err) => {
|
||||
println!("Failed to get event description: {err}");
|
||||
continue;
|
||||
}
|
||||
};
|
||||
println!("\t{device_description}: Event {i}: {description}");
|
||||
}
|
||||
// Get global events
|
||||
let global_events = match device.events_get(1024) {
|
||||
Ok(events) => events,
|
||||
Err(err) => {
|
||||
println!("Failed to get global events: {err}");
|
||||
return Err(err);
|
||||
}
|
||||
};
|
||||
for (i, event) in global_events.iter().enumerate() {
|
||||
let description = match device.event_description_get(*event) {
|
||||
Ok(description) => description,
|
||||
Err(err) => {
|
||||
println!("Failed to get event description: {err}");
|
||||
continue;
|
||||
}
|
||||
};
|
||||
println!("\t{device_description}: Global Event {i}: {description}");
|
||||
}
|
||||
println!(
|
||||
"\t{device_description}: Received {} events and {} global events\n",
|
||||
events.len(),
|
||||
global_events.len()
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
Reference in New Issue
Block a user