This commit is contained in:
2024-07-03 09:12:31 +08:00
commit d761f91771
70 changed files with 17366 additions and 0 deletions

View File

@ -0,0 +1,28 @@
mod smoothmethod;
mod spectraltools;
mod sharpmethod;
#[tauri::command]
pub fn interpolate_spline(x: Vec<f64>, y: Vec<f64>, step: f64) ->Vec<(f64, f64)>{
spectraltools::interpolate_spline(x, y, step).unwrap()
}
#[tauri::command]
pub fn interpolate_spline_at_points(x: Vec<f64>, y: Vec<f64>, x_target: Vec<f64>) -> Vec<f64>{
spectraltools::interpolate_spline_at_points(x, y, x_target).unwrap()
}
#[tauri::command]
pub fn sg_smooth(data: Vec<f64>, window: usize, order: usize) -> Vec<f64> {
smoothmethod::savgol(data, window, order)
}
#[tauri::command]
pub fn Gaussian_filter_high(data: Vec<f64>, sigma: f64) -> Vec<f64> {
sharpmethod::high_pass_gaussian_filter(data, sigma)
}
#[tauri::command]
pub fn find_peek(data: Vec<f64>, minheigh: f64) -> Vec<(u32, f64)> {
spectraltools::find_peek(data, minheigh)
}

View File

@ -0,0 +1,42 @@
extern crate ndarray;
extern crate ndarray_ndimage;
use ndarray::prelude::*;
use ndarray_ndimage::{gaussian_filter, BorderMode};
pub fn high_pass_gaussian_filter(input: Vec<f64>, sigma: f64) -> Vec<f64> {
// 将输入 Vec<f64> 转换为 Array1<f64>
let mut input_array = Array1::from_vec(input);
// for i in 0..input_array.len(){
//
// input_array[i]=input_array[i]*input_array[i]/( 65535f64);
// }
// return input_array.to_vec();
// 高斯低通滤波
let mut low_pass = gaussian_filter(&input_array, sigma, 0, BorderMode::Reflect, 3);
// Modify the result: set values less than zero to zero
println!("{:?}",low_pass);
// 高通滤波:原始信号 - 低通滤波结果
let mut addarry=&input_array - &low_pass;
for i in 0..addarry.len(){
if addarry[i] < 0.0 {
addarry[i] = 0.0;
}
}
let high_pass =&input_array+ &addarry;
// 找到原始数据和锐化后数据的最大值
let max_original = input_array.iter().cloned().fold(f64::MIN, f64::max);
let max_sharpened = high_pass.iter().cloned().fold(f64::MIN, f64::max);
// 计算系数
let coefficient = max_original / max_sharpened;
// 应用系数并将输出 Array1<f64> 转换回 Vec<f64>
high_pass.map(|&x| x * coefficient).to_vec()
}

View File

@ -0,0 +1,23 @@
extern crate savgol_rs;
use savgol_rs::savgol_filter;
pub fn savgol(data: Vec<f64>, window: usize, order: usize) -> Vec<f64> {
let svinput= savgol_rs::SavGolInput{data:&data,window_length:window,poly_order:order,derivative:0};
savgol_filter(&svinput).unwrap()
}
#[test]
fn test_savgol() {
// 示例数据
let data = vec![1.0, 1.9, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0];
let window = 5;
let order = 2;
// 调用 savgol 函数
let smoothed_data = savgol(data.clone(), window, order);
println!("Smoothed data: {:?}", smoothed_data);
}

View File

@ -0,0 +1,140 @@
extern crate splines;
use splines::{Spline, Key, Interpolation};
use std::error::Error;
use find_peaks::PeakFinder;
pub fn interpolate_spline<T: Copy + Into<f64>,>(x_T: Vec<T>, y_T: Vec<T>, step: f64) -> Result<Vec<(f64, f64)>, Box<dyn Error>> {
let x: Vec<f64> = x_T.iter().map(|&x| x.into()).collect();
let y: Vec<f64> = y_T.iter().map(|&y| y.into()).collect();
if x.len() != y.len() {
return Err("x and y must have the same length".into());
}
// 创建样条曲线
let keys: Vec<Key<f64, f64>> = x.iter()
.zip(y.iter())
.map(|(&x, &y)| Key::new(x, y, Interpolation::Linear))
.collect();
let spline = Spline::from_vec(keys);
// 计算 x 的最大值和最小值
let &start = x.iter().min_by(|a, b| a.partial_cmp(b).unwrap()).unwrap();
let &end = x.iter().max_by(|a, b| a.partial_cmp(b).unwrap()).unwrap();
// 插值到间隔为 step 的点
let mut result = Vec::new();
let mut t = start;
while t <= end {
if let Some(value) = spline.clamped_sample(t) {
result.push((t, value));
}
t += step;
}
Ok(result)
}
pub fn interpolate_spline_at_points<T: Copy + Into<f64>>(x_T: Vec<T>, y_T: Vec<T>, x_target: Vec<f64>) -> Result<Vec<(f64)>, Box<dyn Error>> {
let x: Vec<f64> = x_T.iter().map(|&x| x.into()).collect();
let y: Vec<f64> = y_T.iter().map(|&y| y.into()).collect();
if x.len() != y.len() {
return Err("x and y must have the same length".into());
}
// 创建样条曲线
let keys: Vec<Key<f64, f64>> = x.iter()
.zip(y.iter())
.map(|(&x, &y)| Key::new(x, y, Interpolation::Linear))
.collect();
let spline = Spline::from_vec(keys);
// 插值到 x_target 指定的点
let mut result = Vec::new();
for &t in x_target.iter() {
if let Some(value) = spline.clamped_sample(t) {
result.push(value);
}
}
Ok(result)
}
pub fn find_peek(data:Vec<f64>,minheigh:f64)->Vec<(u32,f64)>{
let mut fp = PeakFinder::new(&data);
fp.with_min_prominence(200.);
fp.with_min_height(minheigh);
let mut retvec=Vec::new();
let peaks = fp.find_peaks();
for p in peaks {
// println!("{} {}", p.middle_position(), p.height.unwrap());
retvec.push((p.middle_position().try_into().unwrap(),p.height.unwrap()));
}
retvec
}
#[test]
fn testinterpolate_spline() -> Result<(), Box<dyn Error>> {
// 示例数据
let x = vec![0.0,0.5, 0.569, 1.138, 1.707, 2.276, 2.845];
let y = vec![0.0, 0.4,0.5, 1.0, 0.5, 0.0, -0.5];
let step = 0.1;
// 调用插值函数
let interpolated_values = interpolate_spline(x, y, step)?;
// 输出结果
for (xi, yi) in interpolated_values {
println!("x = {:.3}, y = {:.3}", xi, yi);
}
Ok(())
}
#[test]
fn tset_interpolate_spline_at_points() -> Result<(), Box<dyn Error>> {
let x = vec![0.0,0.5, 0.569, 1.138, 1.707, 2.276, 2.845];
let y = vec![0.0, 0.4,0.5, 1.0, 0.5, 0.0, -0.5];
let x_target = vec![0.1, 0.2, 0.3];
let result = interpolate_spline_at_points(x, y, x_target)?;
for (yi) in result {
println!("y = {:.3}", yi);
}
Ok(())
}
use csv::ReaderBuilder;
fn read_csv_to_vec(file_path: &str) -> Result<Vec<f64>, Box<dyn Error>> {
let mut rdr = ReaderBuilder::new().from_path(file_path)?;
let mut values = Vec::new();
for result in rdr.records() {
let record = result?;
if let Some(value) = record.get(1) {
values.push(value.parse::<f64>()?);
}
}
Ok(values)
}
#[test]
fn test_find_peek(){
let data = read_csv_to_vec("D:\\06Learn\\rust\\tarui\\myfirst_tauri\\src-tauri\\test0_UP.csv").unwrap();
let peaks = find_peek(data,10000.0);
for p in peaks {
println!("{} {}", p.0, p.1);
}
}

471
src-tauri/src/main.rs Normal file
View File

@ -0,0 +1,471 @@
// Prevents additional console window on Windows in release, DO NOT REMOVE!!
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
use core::str;
use serialport::new;
use std::ffi::c_float;
use std::fmt::format;
use std::fs;
use std::fs::File;
use std::io::{self, Read, Write};
// use std::sync::WaitTimeoutResult;
use std::path::Path;
mod algorithm;
mod mylog;
mod serport;
use algorithm::interpolate_spline;
use algorithm::sg_smooth;
use std::mem;
use mylog::*;
use serde::{Deserialize, Serialize};
use serde_with::serde_as;
use serport::serport::*;
#[derive(Serialize, Deserialize)]
struct RetStruct {
datatype: u8,
content: String,
data: IS11DataStruct,
}
#[serde_as]
#[derive(Serialize, Deserialize)]
#[repr(C)]
struct IS11DataStruct {
datatype: u8, // Using r# to allow the use of the keyword 'type'
direction: u8,
tuigan_stat: u8,
shutter_time: u32,
index: u64,
temprature: [f32; 8],
#[serde_as(as = "[_; 2048]")]
data: [f32; 2048],
}
impl Default for IS11DataStruct {
fn default() -> Self {
IS11DataStruct {
datatype: 0,
direction: 10,
tuigan_stat: 0,
shutter_time: 0,
index: 0,
temprature: [0.0; 8],
data: [0.0; 2048],
}
}
}
#[tauri::command]
fn savecalibratefile(Gain: Vec<f32>, shutter: u32, direction: bool, filepath: String) -> String {
let mut data = IS11DataStruct::default();
data.data = Gain.as_slice().try_into().unwrap();
data.shutter_time = shutter as u32;
data.direction = if direction { 1 } else { 0 };
data.datatype = 0x04;
let mut buffer = vec![0u8; mem::size_of::<IS11DataStruct>()];
// 序列化为二进制数据
unsafe {
let ptr = &data as *const IS11DataStruct as *const u8;
std::ptr::copy_nonoverlapping(ptr, buffer.as_mut_ptr(), mem::size_of::<IS11DataStruct>());
}
// 序列化为二进制数据
let file_path = Path::new(&filepath);
// 获取文件路径的父目录
if let Some(parent) = file_path.parent() {
// 确保父目录存在
if !parent.exists() {
fs::create_dir_all(parent).unwrap();
println!("父目录已创建: {:?}", parent);
} else {
println!("父目录已存在: {:?}", parent);
}
} else {
println!("文件路径没有父目录");
}
let mut file = File::create(filepath).unwrap();
file.write_all(&buffer).unwrap();
"OK".to_string()
}
#[tauri::command]
fn sendcalibratetodev(Gain: Vec<f32>, shutter: u32, direction: bool) -> String {
let mut data = IS11DataStruct::default();
data.data = Gain.as_slice().try_into().unwrap();
data.shutter_time = shutter as u32;
data.direction = if direction { 1 } else { 0 };
data.datatype = 0x04;
let mut buffer = vec![0u8; mem::size_of::<IS11DataStruct>()];
// 序列化为二进制数据
unsafe {
let ptr = &data as *const IS11DataStruct as *const u8;
std::ptr::copy_nonoverlapping(ptr, buffer.as_mut_ptr(), mem::size_of::<IS11DataStruct>());
}
sendtoportbinary(buffer, 0x03);
"OK".to_string()
}
fn sendtoportbinary(data: Vec<u8>, command: u8) -> String {
let lenth = data.len() as u16;
let high: u8 = (lenth >> 8) as u8;
let low: u8 = (lenth & 0xFF) as u8;
let mut header = vec![];
header.push(0x55);
header.push(0xAA);
let mut crcbody = vec![];
// crcbody.push(high);
// crcbody.push(low);
crcbody.extend(data);
let crc = iris_calc_crc(&crcbody);
let crchigh: u8 = (crc >> 8) as u8;
let crclow: u8 = (crc & 0xFF) as u8;
let mut senddata = vec![];
senddata.extend(header);
senddata.push(command);
senddata.push(high);
senddata.push(low);
senddata.extend(crcbody);
senddata.push(crchigh);
senddata.push(crclow);
// println!("sendtoport data:{}",senddata.len());
println!(
"sendtoport data content:{:X?}",
senddata
.iter()
.map(|&byte| format!("{:02X}", byte))
.collect::<Vec<String>>()
.join(" ")
);
sendtoprot(senddata);
"send ok".to_string()
}
// Learn more about Tauri commands at https://tauri.app/v1/guides/features/command
#[tauri::command]
fn greet(name: &str) -> String {
format!("Hello, {}! You've been greeted from Rust!", name)
}
#[tauri::command]
fn getportnames() -> Vec<String> {
get_port_name()
}
#[tauri::command]
fn opencom(portname: serde_json::Value, baudrate: serde_json::Value) -> String {
//tauri
let portname = portname.as_str().unwrap();
let baudrate = baudrate.as_u64().unwrap() as u32;
set_port_info(&portname.to_string(), baudrate);
println!("opencom portname:{} baudrate:{}", portname, baudrate);
logtorust(format!(
"opencom portname:{} baudrate:{}",
portname, baudrate
));
tryuseport()
}
#[tauri::command]
fn closecome() -> String {
closeport()
}
#[tauri::command]
fn sendtoport(data: serde_json::Value, datatype: serde_json::Value) -> String {
// println!("sendtoport data:{}",data.to_string());
//判断是否存在data
// if !data.is_object() {
// return String::from("Invalid data");
// }
println!("sendtoport data:{}", data.to_string());
logtorust(format!("sendtoport data:{}", data.to_string()));
let data = data.to_string().as_bytes().to_vec();
let lenth = data.len() as u16;
let high: u8 = (lenth >> 8) as u8;
let low: u8 = (lenth & 0xFF) as u8;
let mut header = vec![];
header.push(0x55);
header.push(0xAA);
let mut command: u8 = 0;
let datatype = datatype.as_str().unwrap();
println!("datatype:{}", datatype);
if datatype == "hex" {
command = 0x03;
}
if datatype == "string" {
command = 0x01;
}
if datatype == "json" {
command = 0x00;
}
let mut crcbody = vec![];
// crcbody.push(high);
// crcbody.push(low);
crcbody.extend(data);
let crc = iris_calc_crc(&crcbody);
let crchigh: u8 = (crc >> 8) as u8;
let crclow: u8 = (crc & 0xFF) as u8;
let mut senddata = vec![];
senddata.extend(header);
senddata.push(command);
senddata.push(high);
senddata.push(low);
senddata.extend(crcbody);
senddata.push(crchigh);
senddata.push(crclow);
// println!("sendtoport data:{}",senddata.len());
// println!(
// "sendtoport data content:{:X?}",
// senddata
// .iter()
// .map(|&byte| format!("{:02X}", byte))
// .collect::<Vec<String>>()
// .join(" ")
// );
logtorust(format!(
"sendtoport data content:{:X?}",
senddata
.iter()
.map(|&byte| format!("{:02X}", byte))
.collect::<Vec<String>>()
.join(" ")
));
sendtoprot(senddata);
"send ok".to_string()
}
#[tauri::command]
fn readformport(commanid: serde_json::Value, wait_time_json: serde_json::Value) -> String {
let mut waittime = 50;
if wait_time_json.is_u64() {
waittime = wait_time_json.as_u64().unwrap() as u32;
}
let commanid = commanid.as_u64().unwrap() as u8;
let ret = readdatafromport(waittime as u64, commanid);
let str = String::from_utf8_lossy(&ret);
println!("read data: {}", str);
return str.to_string();
}
#[tauri::command]
fn sendtoportAndgetreturn(
data: serde_json::Value,
datatype: serde_json::Value,
) -> Result<RetStruct, String> {
// println!("sendtoport data:{}",data.to_string());
//判断是否存在data
// if !data.is_object() {
// return String::from("Invalid data");
// }
//println!("sendtoport data:{}", data.to_string());
let command = data.get("command").unwrap().to_string();
let mut isneedlog = true;
let mut isgetdata = false;
if command == "\"get_caiji_state\"" {
isneedlog = false;
}
if command == "\"get_data\"" {
isgetdata = true;
}
if isneedlog {
logtorust(format!("sendtoport data:{}", data.to_string()));
}
let data = data.to_string().as_bytes().to_vec();
let lenth = data.len() as u16;
let high: u8 = (lenth >> 8) as u8;
let low: u8 = (lenth & 0xFF) as u8;
let mut header = vec![];
header.push(0x55);
header.push(0xAA);
let mut command: u8 = 0;
let datatype = datatype.as_str().unwrap();
println!("datatype:{}", datatype);
if datatype == "hex" {
command = 0x03;
}
if datatype == "string" {
command = 0x01;
}
if datatype == "json" {
command = 0x00;
}
let mut crcbody = vec![];
// crcbody.push(high);
// crcbody.push(low);
crcbody.extend(data);
let crc = iris_calc_crc(&crcbody);
let crchigh: u8 = (crc >> 8) as u8;
let crclow: u8 = (crc & 0xFF) as u8;
let mut senddata = vec![];
senddata.extend(header);
senddata.push(command);
senddata.push(high);
senddata.push(low);
senddata.extend(crcbody);
senddata.push(crchigh);
senddata.push(crclow);
println!("sendtoport data:{}", senddata.len());
// println!(
// "sendtoport data content:{:X?}",
// senddata
// .iter()
// .map(|&byte| format!("{:02X}", byte))
// .collect::<Vec<String>>()
// .join(" ")
// );
if isneedlog {
logtorust(format!(
"sendtoport data content:{:X?}",
senddata
.iter()
.map(|&byte| format!("{:02X}", byte))
.collect::<Vec<String>>()
.join(" ")
));
}
sendtoprot(senddata);
let mut ret = readdatafromport(50, 0xff);
let datatype = ret[0];
if isneedlog {
if !isgetdata{
logtorust(format!(
"read content: {:X?}",
ret.iter()
.map(|&byte| format!("{:02X}", byte))
.collect::<Vec<String>>()
.join(" ")
));
}
}
if isgetdata{
logtorust("Get data Back SUCCESS".to_string());
logtorust("_____________________________one_data_over_____________________________\n".to_string());
}
ret.remove(0);
ret.remove(0);
ret.remove(0);
if datatype == 0x02 {
let mut is11data = IS11DataStruct::default();
unsafe {
let mut is11data_ptr = &mut is11data as *mut IS11DataStruct;
let mut ret_ptr = &mut ret[0] as *mut u8;
std::ptr::copy_nonoverlapping(
ret_ptr,
is11data_ptr as *mut u8,
std::mem::size_of::<IS11DataStruct>(),
);
return Ok(RetStruct {
datatype: datatype,
content: "null".to_string(),
data: is11data,
});
}
}
let str = String::from_utf8_lossy(&ret);
// println!("read data: {}", str);
if datatype==0x00 &&isneedlog {
logtorust(format![
"read string: {}",
str.to_string()
]);
}
return Ok(RetStruct {
datatype: datatype,
content: str.to_string(),
data: IS11DataStruct::default(),
});
// return str.to_string();
}
#[tauri::command]
fn clearportbuff() -> String {
clearserilport()
}
#[tauri::command]
fn setport(data: serde_json::Value) -> String {
//判断是否存在portname和baudrate
if !data.is_object() {
return String::from("Invalid data");
}
if !data["portname"].is_string() || !data["baudrate"].is_u64() {
return String::from("Invalid data");
}
let portname = data["portname"].as_str().unwrap();
let baudrate = data["baudrate"].as_u64().unwrap() as u32;
set_port_info(&portname.to_string(), baudrate);
//println!("{}",readdatafromport(1000));
String::from("Port set ok")
}
use tauri::{LogicalSize, Manager, Size};
fn main() {
// 使用宏生成处理程序列表
mylog::initlog();
mylog::logtorust("welecome to rust log");
mylog::logtojs("welecome to rust log");
tauri::Builder::default()
.invoke_handler(tauri::generate_handler![
clearportbuff,
greet,
getportnames,
opencom,
setport,
closecome,
sendtoportAndgetreturn,
readformport,
sendtoport,
interpolate_spline,
sg_smooth,
savecalibratefile,
sendcalibratetodev,
algorithm::Gaussian_filter_high,
algorithm::interpolate_spline_at_points,
algorithm::find_peek
])
.setup(|app| {
let main_window = app.get_window("main").unwrap();
// 获取屏幕大小
if let Some(monitor) = main_window.primary_monitor().unwrap() {
let scale_factor = monitor.scale_factor();
let physical_size = monitor.size();
let logical_width = physical_size.width as f64 / scale_factor;
let logical_height = physical_size.height as f64 / scale_factor;
let new_width = logical_width * 0.8;
let new_height = logical_height * 0.8;
// 设置窗口大小为屏幕大小的 80%
main_window
.set_size(Size::Logical(LogicalSize {
width: new_width,
height: new_height,
}))
.unwrap();
main_window.set_cursor_visible(true).unwrap();
}
Ok(())
})
.run(tauri::generate_context!())
.expect("error while running tauri application");
}

78
src-tauri/src/mylog.rs Normal file
View File

@ -0,0 +1,78 @@
use tklog::{
debugs, errors, fatals, infos,
sync::Logger,LEVEL, LOG,
traces, warns, Format, MODE,async_traces,
};
use lazy_static::lazy_static;
use std::{
// fmt::format,
borrow::{Borrow, BorrowMut}, sync::{Arc, Mutex}, thread::sleep
};
struct LOGERME{
LOGGER_RUST: Arc<Mutex<Logger>>,
LOGGER_JS: Arc<Mutex<Logger>>,
}
lazy_static! {
static ref LOGERGloble: Arc<Mutex<LOGERME>> = Arc::new(Mutex::new(
LOGERME{
LOGGER_RUST:Arc::new( Mutex::new(Logger::new())),
LOGGER_JS: Arc::new( Mutex::new(Logger::new())),
}
));
}
// pub static LOGGER_RUST: Arc<Mutex<Logger>> =Arc::new( Mutex::new(Logger::new()));
// pub static LOGGER_JS: Arc<Mutex<Logger>> = Arc::new(Mutex::new(Logger::new()));
pub fn change_log_path(path: &str,String: &str) {
if String=="RUST"{
let mut loggerglobel = LOGERGloble.lock().unwrap();
let mut log=loggerglobel.LOGGER_RUST.lock().unwrap();
log.set_cutmode_by_time(path, MODE::DAY, 10, false);
}else if String=="JS"{
let mut loggerglobel=LOGERGloble.lock().unwrap();
let mut log=loggerglobel.LOGGER_JS.lock().unwrap();
log.set_cutmode_by_time(path, MODE::DAY, 10, false);
}
}
pub fn initlog() {
//let mut logger = LOGERGloble.lock().unwrap().LOGGER_RUST;
let mut loggerglobel = LOGERGloble.lock().unwrap();
let mut log=loggerglobel.LOGGER_RUST.lock().unwrap();
log.set_console(true).set_format(Format::Date|Format::Time).set_formatter("{time} {file}{level}:{message}\n")
.set_cutmode_by_time("rust_log.log",MODE::DAY, 10, false);
// let mut logger = LOGERGloble.lock().unwrap().LOGGER_JS;
//let mut loggerglobel = LOGERGloble.lock().unwrap();
let mut log=loggerglobel.LOGGER_JS.lock().unwrap();
log.set_console(false).set_format(Format::Date|Format::Time).set_formatter("{time}:\t{message}\n")
.set_cutmode_by_time("js_log.log",MODE::DAY, 10, false);
}
pub fn logtorust<T>(str:T)
where T: std::fmt::Display
{
let mut loggerglobe=LOGERGloble.lock().unwrap();
let mut log=Arc::clone(&loggerglobe.LOGGER_RUST);
let log1 = log.borrow_mut();
infos!( log1, str);
}
pub fn logtojs<T>(str:T)
where T: std::fmt::Display
{
let mut loggerglobe=LOGERGloble.lock().unwrap();
let mut log=Arc::clone(&loggerglobe.LOGGER_JS);
let log1 = log.borrow_mut();
infos!( log1, str);
}

View File

@ -0,0 +1,155 @@
// use serialport::SerialPort;
pub fn _iris_protocol_pack(command: u8, length_of_in: u16, buffer_in: &[u8]) -> Option<Vec<u8>> {
if length_of_in != 0 && buffer_in.is_empty() {
return None;
}
let mut pack_data: Vec<u8> = vec![0u8; 5 ];
pack_data[0] = 0x55;
pack_data[1] = 0xAA;
pack_data[2] = command;
pack_data[3] = (length_of_in >> 8) as u8;
pack_data[4] = (length_of_in & 0xFF) as u8;
let pack_crc: Vec<u8>=buffer_in.to_vec();
let crc = iris_calc_crc(&pack_crc);
pack_data.extend(pack_crc);
pack_data.push((crc >> 8) as u8);
pack_data.push(crc as u8);
Some(pack_data)
}
pub fn _iris_stm32_protocol_unpack(pack_data: &[u8]) -> Result<(u8, Vec<u8>), &'static str> {
if pack_data.is_empty() {
return Err("ERROR_INPUT");
}
if pack_data[0] != 0x55 || pack_data[1] != 0xAA {
return Err("ERROR_HEADER");
}
//获取数据长度
let length_of_data = (pack_data[4] as u16) + ((pack_data[3] as u16) << 8) ;
//判断数据长度是否足够
if length_of_data as usize > pack_data.len() - 7 {
return Err("ERROR_NOT_ENOUGH_DATA");
}
//计算crc
let crc = iris_calc_crc(&pack_data[5..(length_of_data as usize) + 5]);
let expected_crc = (pack_data[length_of_data as usize + 6] as u16) + ((pack_data[length_of_data as usize + 5] as u16) << 8);
if crc != expected_crc {
return Err("ERROR_CRC");
}
let command = pack_data[2];
let buffer_out = pack_data[5..(length_of_data as usize) + 5].to_vec();
Ok((command, buffer_out))
}
pub fn iris_protocol_unpack(pack_data: &[u8], command: u8) -> Result<Vec<u8>, &'static str> {
if pack_data.is_empty() {
return Err("ERROR_INPUT");
}
if pack_data[0] != 0x55 || pack_data[1] != 0xAA {
return Err("ERROR_HEADER");
}
if pack_data[2] != command {
if command != 0xff { return Err("ERROR_COMMAND"); }
}
//获取数据长度
let length_of_data = (pack_data[4] as u16) + ((pack_data[3] as u16) << 8) ;
//判断数据长度是否足够
if length_of_data as usize > pack_data.len() - 7 {
return Err("ERROR_NOT_ENOUGH_DATA");
}
print!("length_of_data:{}",length_of_data);
// println!("{:?}", pack_data.iter().map(|&byte| format!("{:X}", byte)).collect::<Vec<String>>().join(" "));
let crc = iris_calc_crc(&pack_data[5..(length_of_data as usize) + 5]);
let expected_crc: u16 = (pack_data[length_of_data as usize + 6] as u16) + ((pack_data[length_of_data as usize + 5] as u16) << 8);
println!("crc:{},expected_crc:{}",crc,expected_crc);
// println!("{}{}",pack_data[length_of_data as usize + 6],pack_data[length_of_data as usize + 5]);
if crc != expected_crc {
return Err("ERROR_CRC");
}
Ok(pack_data[2..(length_of_data as usize) + 5].to_vec())
}
pub fn iris_cut_before_header(pack_data: &mut Vec<u8>) -> usize {
let mut i = 0;
while i < pack_data.len() {
if pack_data[i] == 0x55 && pack_data.get(i + 1) == Some(&0xAA) {
break;
}
i += 1;
}
if i == pack_data.len() {
pack_data.clear();
return 0;
}
let length_of_data = pack_data.len() - i;
pack_data.drain(0..i);
length_of_data
}
pub fn _iris_check_data_valid(pack_data: &[u8]) -> Result<(), &'static str> {
if pack_data.is_empty() {
return Err("ERROR_INPUT");
}
if pack_data.len() < 7 {
return Err("ERROR_NOT_ENOUGH_DATA");
}
if pack_data[0] != 0x55 || pack_data[1] != 0xAA {
return Err("ERROR_HEADER");
}
let length_of_data = (pack_data[4] as u16) + ((pack_data[3] as u16) << 8);
if length_of_data as usize > pack_data.len() - 7 {
return Err("ERROR_NOT_ENOUGH_DATA");
}
let crc = iris_calc_crc(&pack_data[5..(length_of_data as usize) + 5]);
let expected_crc = (pack_data[length_of_data as usize + 6] as u16) + ((pack_data[length_of_data as usize + 5] as u16) << 8);
// println!("crc:{},expected_crc:{}",crc,expected_crc);
if crc != expected_crc {
return Err("ERROR_CRC");
}
Ok(())
}
pub fn iris_calc_crc(p_buffer: &[u8]) -> u16 {
// println!("cut_before_header");
// println!("{:?}", p_buffer.iter().map(|&byte| format!("{:X}", byte)).collect::<Vec<String>>().join(" "));
let poly: u16 = 0x8408;
let mut crc: u16 = 0;
for &byte in p_buffer {
crc ^= byte as u16;
for _ in 0..8 {
let carry = crc & 1 != 0;
crc >>= 1;
if carry {
crc ^= poly;
}
}
}
crc
}

View File

@ -0,0 +1,4 @@
pub mod serport;
pub mod iris_protool;
// remember to call `.manage(MyState::default())`

View File

@ -0,0 +1,243 @@
//静态变量 用来存储SerialPort对象
use super::iris_protool::*;
use lazy_static::lazy_static;
use std::time::Duration;
use std::{
// fmt::format,
sync::{Arc, Mutex},
thread::sleep,
};
struct SeriesSettings {
pub PortName: String,
pub BaudRate: u32,
pub port: Option<Box<dyn serialport::SerialPort>>,
pub isopen: bool,
}
lazy_static! {
static ref PORT_INFO: Arc<Mutex<SeriesSettings>> = Arc::new(Mutex::new(SeriesSettings {
PortName: String::from("NON"),
BaudRate: 9600,
port: None,
isopen: false,
}));
}
pub fn tryuseport() -> String {
let mut port_info = PORT_INFO.lock().unwrap();
if port_info.PortName == "NON" {
return format!("Port is not set");
}
if port_info.isopen {
drop(port_info);
closeport();
port_info= PORT_INFO.lock().unwrap();
}
port_info.port = match serialport::new(port_info.PortName.clone(), port_info.BaudRate).open() {
Ok(p) => Some(p),
Err(e) => {
eprintln!("Failed to open Error: {}", e);
return format!("Failed to open Error: {}", e);
}
};
port_info.isopen = true;
println!("Port is open");
return String::from("Port is open");
}
pub fn set_port_info(portname: &String, baudrate: u32) {
let mut port_info = PORT_INFO.lock().unwrap();
port_info.PortName = portname.to_string();
port_info.BaudRate = baudrate;
}
pub fn get_port_name() -> Vec<String> {
let ports = serialport::available_ports().expect("No ports found!");
let mut portnames: Vec<String> = Vec::new();
for p in ports {
portnames.push(p.port_name);
}
return portnames;
}
pub fn _reopenport() -> String {
let mut port_info = PORT_INFO.lock().unwrap();
if port_info.PortName == "NON" {
return format!("Port is not set");
}
//关闭端口
port_info.port = None;
//重新打开端口
port_info.port = match serialport::new(port_info.PortName.clone(), port_info.BaudRate).open() {
Ok(p) => Some(p),
Err(e) => {
eprintln!("Failed to open Error: {}", e);
return format!("Failed to open Error: {}", e);
}
};
String::from("Port is open")
}
pub fn closeport() -> String {
let mut port_info = PORT_INFO.lock().unwrap();
if port_info.PortName == "NON" {
return format!("Port is not set");
}
//关闭端口
port_info.port = None;
println!("Port is closed");
String::from("Port is closed")
}
pub fn sendtoprot(data: Vec<u8>) -> String {
let mut port_info = PORT_INFO.lock().unwrap();
if port_info.PortName == "NON" {
return format!("Port is not set");
}
match &mut port_info.port {
Some(p) => match p.write(&data) {
Ok(_) => {
println!("Data sent");
return String::from("Data sent");
}
Err(e) => {
eprintln!("Failed to write to port: {}", e);
return format!("Failed to write to port: {}", e);
}
},
None => {
return format!("Port is not open");
}
}
}
pub fn clearserilport() -> String{
let mut port_info = PORT_INFO.lock().unwrap();
if port_info.PortName == "NON" {
return "Port is not set".to_string();
}
let mut buf: Vec<u8> = vec![0; 1000];
match &mut port_info.port {
Some(p) => {
p.set_timeout(Duration::from_millis(100)).unwrap();
while true{
let sizeread =match p.read(&mut buf){
Ok(size)=>{size},
Err(_e)=>{return "Port is not open".to_string()}
};
if sizeread==0 { return "OK".to_string(); }
}
}
None => {
port_info.isopen=false;
return "Port is not open".to_string();
}
}
port_info.isopen=false;
"OK".to_string()
}
pub fn readdatafromport(waittime: u64, commanid: u8) -> Vec<u8> {
let mut port_info = PORT_INFO.lock().unwrap();
if port_info.PortName == "NON" {
return "Port is not set".as_bytes().to_vec();
}
let mut buf: Vec<u8> = vec![0; 1000];
let mut bufforrentrun: Vec<u8> = vec![0];
match &mut port_info.port {
Some(p) => {
p.set_timeout(Duration::from_millis(100)).unwrap();
let mut sizereadoftotal=0;
let mut nowtimetry=0;
while sizereadoftotal <5 {
let sizeread =match p.read(&mut buf){
Ok(size)=>{size},
Err(_e)=>{0}
};
buf.truncate(sizeread);
bufforrentrun.extend_from_slice(&buf);
//输出接收到的数据
println!("{:?}:{}", buf.iter().map(|&byte| format!("{:02X}", byte)).collect::<Vec<String>>().join(" "),sizeread);
sizereadoftotal =iris_cut_before_header(&mut bufforrentrun);
nowtimetry+=1;
if nowtimetry>waittime{
return "long time no data retrun".as_bytes().to_vec();
}
sleep(Duration::from_millis(100));
}
nowtimetry=0;
// println!("{:?}", bufforrentrun);
iris_cut_before_header(&mut bufforrentrun);
while match iris_protocol_unpack(&bufforrentrun, commanid) {
Ok(buf) =>
{
return buf
},
Err(e) => {
if e == "ERROR_NOT_ENOUGH_DATA" {
true
} else {
println!("Error: {}", e.to_string());
return e.to_string().as_bytes().to_vec();
}
}
} {
let sizeread = match p.read(&mut buf) {
Ok(size) => size,
Err(msg) => {
eprintln!("Failed to read from port: {}", msg);
0
}
};
buf.truncate(sizeread);
bufforrentrun.extend_from_slice(&buf);
//println!("{:?}", bufforrentrun.iter().map(|&byte| format!("{:X}", byte)).collect::<Vec<String>>().join(" "));
nowtimetry+=1;
if nowtimetry>waittime{
return "long time no data retrun".as_bytes().to_vec();
}
}
return buf;
}
None => {
return Vec::new();
}
}
}
pub fn iris_calc_crc(p_buffer: &[u8]) -> u16 {
let poly: u16 = 0x8408;
let mut crc: u16 = 0;
for &byte in p_buffer {
crc ^= u16::from(byte);
for _ in 0..8 {
let carry = crc & 1 != 0;
crc >>= 1;
if carry {
crc ^= poly;
}
}
}
crc
}
#[test]
fn test() {
tryuseport();
}