C# WPF燃气报警器记录读取串口工具
C# WPF燃气报警器记录读取串口工具
- 概要
- 串口帧数据
- 布局文件
- 代码文件
- 运行效果
- 源码下载
概要
- 符合国标文件《GB+15322.2-2019.pdf》串口通信协议定义;
- 可读取燃气报警器家用版设备历史记录信息等信息;
串口帧数据
串口通信如何确定一帧数据接收完成是个麻烦事,本文采用最后一次数据接收完成后再过多少毫秒认为一帧数据接收完成,开始解析出来。每次接收到数据更新一次recvTimems 。定时器mTimer定时周期10毫秒,定时器回调函数里判断接收时间超过20ms(这个时间的长短和串口波特率有关)认为一帧数据接收完成。接收数据时间差未超过20ms则将接收数据追加到rxBuf数据缓冲,
long recvTimems = 0; // 用于计算串口接收完一帧数据
int rxLen = 0; // 串口接收到的数据长度
byte[] rxBuff = new byte[128]; // 串口数据接收缓存
private static Timer mTimer; // 定时器,10ms执行一次mTimer = new Timer(recvTimerCalback, null, 0, 10); // 创建并启动定时器private void recvTimerCalback(object obj)
{//Console.WriteLine("timer callback!" + recvTimems);this.Dispatcher.Invoke(new Action(()=> {// UI线程分离,更新UI数据显示if (((Environment.TickCount - recvTimems) >= 20) && (rxLen > 0)){// 串口接收时间超过X ms认为一帧数据接收完成这里解析处理接收数据.....// 一帧数据处理结束清空数据缓冲Array.Clear(rxBuff, 0, rxBuff.Length);rxLen = 0;}}));
}private void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{SerialPort comPort = (SerialPort)sender;try{recvTimems = Environment.TickCount; // 更新串口数据接收时间//rxBuff[rxLen] = mSerialPort.ReadByte();int readCnt = mSerialPort.BytesToRead;Console.WriteLine("in readCnt:" + readCnt);mSerialPort.Read(rxBuff, rxLen, readCnt);rxLen += readCnt;Console.WriteLine("out rxLen:" + rxLen);}catch (Exception ce){MessageBox.Show(ce.Message);} }
布局文件
XAML
<Window x:Class="GasAlarmTestTool.MainWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:d="http://schemas.microsoft.com/expression/blend/2008"xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"xmlns:local="clr-namespace:GasAlarmTestTool"mc:Ignorable="d"Title="燃气报警器接口工具" Height="600" Width="800"><Grid><TabControl><TabItem><TabItem.Header><StackPanel><Label>串口设置</Label></StackPanel></TabItem.Header><StackPanel Orientation="Horizontal"><GroupBox Header="串口" Width="200"><StackPanel><StackPanel Orientation="Horizontal"><Label Margin="3" Height="25" Width="50">端口号</Label><ComboBox x:Name="comboBoxCOM" Margin="3" Height="20" Width="130" DragDrop.Drop="comboBoxCOM_Drop"/></StackPanel><StackPanel Orientation="Horizontal"><Label Margin="3" Height="25" Width="50">波特率</Label><ComboBox x:Name="comboBoxBaudRate" Margin="3" Height="20" Width="130" SelectedIndex="0" IsEditable="True" ></ComboBox></StackPanel><StackPanel Orientation="Horizontal"><Label Margin="3" Height="25" Width="50">数据位</Label><ComboBox x:Name="comboBoxDataBit" Margin="3" Height="20" Width="130" SelectedIndex="3"><ComboBoxItem>5</ComboBoxItem><ComboBoxItem>6</ComboBoxItem><ComboBoxItem>7</ComboBoxItem><ComboBoxItem>8</ComboBoxItem></ComboBox></StackPanel><StackPanel Orientation="Horizontal"><Label Margin="3" Height="25" Width="50">停止位</Label><ComboBox x:Name="comboBoxStopBit" Margin="3" Height="20" Width="130" SelectedIndex="0"><ComboBoxItem>1位</ComboBoxItem><ComboBoxItem>1.5位</ComboBoxItem><ComboBoxItem>2位</ComboBoxItem></ComboBox></StackPanel><StackPanel Orientation="Horizontal"><Label Margin="3" Height="25" Width="50">校验位</Label><ComboBox x:Name="comboBoxSdd" Margin="3" Height="20" Width="130" SelectedIndex="0"><ComboBoxItem>无校验</ComboBoxItem><ComboBoxItem>奇校验</ComboBoxItem><ComboBoxItem>偶校验</ComboBoxItem><ComboBoxItem>1 校验</ComboBoxItem><ComboBoxItem>0 校验</ComboBoxItem></ComboBox></StackPanel><StackPanel Orientation="Horizontal"><Label Margin="3" Height="25" Width="50">流控位</Label><ComboBox x:Name="comboBoxlik" Margin="3" Height="20" Width="130" SelectedIndex="0" ><ComboBoxItem>无流控</ComboBoxItem><ComboBoxItem>RTS/CTS</ComboBoxItem><ComboBoxItem>XON/XOFF</ComboBoxItem></ComboBox></StackPanel><StackPanel Orientation="Horizontal" HorizontalAlignment="Center"><Button x:Name="btnOpenCloseCom" Margin="3" Width="80" Height="25" Click="btnOpenCloseCom_Click">打开串口</Button><Button x:Name="btnClearRecv" Margin="3" Width="80" Height="25" Click="btnClearRecv_Click">清空接收</Button></StackPanel></StackPanel></GroupBox><GroupBox Header="接收数据" MinWidth="590" MaxWidth="1000"><ScrollViewer><ScrollViewer.Content><TextBlock x:Name="textBlockRecv" MinWidth="300" MaxWidth="1000"></TextBlock></ScrollViewer.Content></ScrollViewer></GroupBox></StackPanel></TabItem><TabItem><TabItem.Header><StackPanel><Label>数据读取</Label></StackPanel></TabItem.Header><StackPanel Orientation="Horizontal"><StackPanel Orientation="Vertical"><GroupBox Header="记录总数"><StackPanel Orientation="Vertical"><Button x:Name="btnReadRecCount" Margin="3" Padding="5" Click="btnReadRecCount_Click">读取记录总数</Button><StackPanel Orientation="Horizontal"><Label>报警记录总数:</Label><TextBox x:Name="txtBoxWarningCount">0</TextBox></StackPanel><StackPanel Orientation="Horizontal"><Label>报警恢复记录总数:</Label><TextBox x:Name="txtBoxWarningRecoveryCount">0</TextBox></StackPanel><StackPanel Orientation="Horizontal"><Label>故障记录总数:</Label><TextBox x:Name="txtBoxFaultCount">0</TextBox></StackPanel><StackPanel Orientation="Horizontal"><Label>故障恢复记录总数:</Label><TextBox x:Name="txtBoxFaultRecoryCount">0</TextBox></StackPanel><StackPanel Orientation="Horizontal"><Label>掉电记录总数:</Label><TextBox x:Name="txtBoxPoweroffCount">0</TextBox></StackPanel><StackPanel Orientation="Horizontal"><Label>上电记录总数:</Label><TextBox x:Name="txtBoxPoweronCount">0</TextBox></StackPanel><StackPanel Orientation="Horizontal"><Label>传感器失效记录总数:</Label><TextBox x:Name="txtSensorInvalidCount">0</TextBox></StackPanel></StackPanel></GroupBox><GroupBox Header="日期时间"><StackPanel Orientation="Vertical"><Button x:Name="btnReadDateTime" Click="btnReadDateTime_Click">读取日期时间</Button><TextBox x:Name="txtBoxDateTime">0000-00-00 00:00</TextBox></StackPanel></GroupBox></StackPanel><StackPanel Orientation="Vertical"><GroupBox Header="读取指定记录"><StackPanel Orientation="Horizontal"><ComboBox x:Name="cmboxRecordType" Width="120" SelectedIndex="0"><ComboBoxItem>报警记录</ComboBoxItem><ComboBoxItem>报警恢复记录</ComboBoxItem><ComboBoxItem>故障记录</ComboBoxItem><ComboBoxItem>故障恢复记录</ComboBoxItem><ComboBoxItem>掉电记录</ComboBoxItem><ComboBoxItem>上电记录</ComboBoxItem><ComboBoxItem>传感器失效记录</ComboBoxItem></ComboBox><TextBox x:Name="txtBoxNumber" Width="50">1</TextBox><Button x:Name="btnReadRecord" Click="btnReadRecord_Click" ClickMode="Press">读取记录</Button><TextBox x:Name="txtBoxRecordInfo">0000/00/00 00:00</TextBox></StackPanel></GroupBox></StackPanel></StackPanel></TabItem></TabControl></Grid>
</Window>
代码文件
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;namespace GasAlarmTestTool
{/// <summary>/// MainWindow.xaml 的交互逻辑/// </summary>public partial class MainWindow : Window{private int warningCnt = 0;private int warningRecoveryCnt = 0;private int faultCnt = 0;private int faultRecoveryCnt = 0;private int poweroffCnt = 0;private int poweronCnt = 0;private int sensorInvalidCnt = 0;long recvTimems = 0; // 用于计算串口接收完一帧数据int rxLen = 0; // 串口接收到的数据长度byte[] rxBuff = new byte[128]; // 串口数据接收缓存private static Timer mTimer; // 定时器,10ms执行一次SerialPort mSerialPort = new SerialPort(); private StringBuilder lineBuilder = new StringBuilder(); // 用于存放串口接收数据private List<string> baudrateList = new List<string> { "4800", "9600", "19200","38400","57600","115200","256000","1000000","2000000","3000000"};public MainWindow(){InitializeComponent();// 获取所有可用串口端口,并添加到comboBoxCOMstring[] ports = System.IO.Ports.SerialPort.GetPortNames();comboBoxCOM.ItemsSource = ports;comboBoxCOM.SelectedIndex = 0; // 默认选择索引comboBoxBaudRate.ItemsSource = baudrateList; // 波特率设置combobox数据源mTimer = new Timer(recvTimerCalback, null, 0, 10); // 创建并启动定时器}/// <summary>/// 窗口关闭处理/// </summary>/// <param name="e"></param>protected override void OnClosing(System.ComponentModel.CancelEventArgs e){ if (MessageBox.Show("确定要退出吗?", "确认", MessageBoxButton.YesNo) != MessageBoxResult.Yes){// 用户选择“否”,取消关闭e.Cancel = true;}mSerialPort.Close();mTimer.Dispose();base.OnClosing(e);}private string RecordInfoString(byte[] buf){if (buf.Length < 11) {return "";}int index = buf[4];int year = buf[5] << 8 | buf[6];int month = buf[7];int day = buf[8];int hour = buf[9];int minute = buf[10];return year.ToString() + "/" + month.ToString() + "/" + day.ToString() + " " + hour.ToString() + ":" + minute.ToString(); }/// <summary>/// 串口接收处理定时器回调/// </summary>/// <param name="obj"></param>private void recvTimerCalback(object obj){//Console.WriteLine("timer callback!" + recvTimems);this.Dispatcher.Invoke(new Action(()=> {// UI线程分离,更新UI数据显示if (((Environment.TickCount - recvTimems) >= 20) && (rxLen > 0)){// 串口接收时间超过X ms认为一帧数据接收完成uint HEAD = rxBuff[0];uint C1 = rxBuff[1];uint C2 = rxBuff[2];uint L = rxBuff[3];uint CS = rxBuff[L + 4];uint END = rxBuff[L + 5];// 打印串口结束缓存数据uint _CS = 0; // 计算接收数据校验和uint index = 0;UInt32 temp = 0;for (int i = 0; i < rxLen; i++){if (i < (rxLen - 2)){temp += rxBuff[i];}Console.WriteLine(rxBuff[i].ToString("X2"));}_CS = (uint)(temp % 0xFF);if ((0xAA == rxBuff[0]) && (0x55 == END)){// TODO: 接收到一帧完整数据Console.WriteLine("RS232 RECV ONE FRAME!" + CS.ToString("X2") + ", " + _CS.ToString("X2"));if (CS == _CS){// TODO: CHECKSUM8 校验和正确Console.WriteLine("CheckSum OK");if (0x00 == C2){if (0x00 == C1){// TODO: 查询各类记录总数warningCnt = rxBuff[4]; // 探测器报警记录总数warningRecoveryCnt = rxBuff[5]; // 探测器报警恢复记录总数faultCnt = rxBuff[6]; // 探测器故障记录总数faultRecoveryCnt = rxBuff[7]; // 探测器故障恢复记录总数poweroffCnt = rxBuff[8]; // 探测器掉电记录总数poweronCnt = rxBuff[9]; // 探测器上电记录总数sensorInvalidCnt = rxBuff[10]; // 传感器失效记录总数txtBoxWarningCount.Text = warningCnt.ToString();txtBoxWarningRecoveryCount.Text = warningRecoveryCnt.ToString();txtBoxFaultCount.Text = faultCnt.ToString();txtBoxFaultRecoryCount.Text = faultRecoveryCnt.ToString();txtBoxPoweroffCount.Text = poweroffCnt.ToString(); txtBoxPoweronCount.Text = poweronCnt.ToString();}}else if (0x01 == C2){// 报警记录txtBoxRecordInfo.Text = RecordInfoString(rxBuff);}else if (0x02 == C2){// 报警恢复记录txtBoxRecordInfo.Text = RecordInfoString(rxBuff);}else if (0x03 == C2){// 故障记录txtBoxRecordInfo.Text = RecordInfoString(rxBuff);}else if (0x04 == C2){// 故障恢复记录txtBoxRecordInfo.Text = RecordInfoString(rxBuff);}else if (0x05 == C2){// 掉电记录txtBoxRecordInfo.Text = RecordInfoString(rxBuff);}else if (0x06 == C2){// 上电记录txtBoxRecordInfo.Text = RecordInfoString(rxBuff);}else if (0x07 == C2){// 传感器失效记录txtBoxRecordInfo.Text = RecordInfoString(rxBuff);}else if (0x08 == C2){// TODO: 日期时间int year = rxBuff[4] << 8 | rxBuff[5];int month = rxBuff[6];int day = rxBuff[7];int hour = rxBuff[8];int minute = rxBuff[9];txtBoxDateTime.Text = year.ToString() + "/" + month.ToString() + "/" + day.ToString() + " "+hour.ToString() + ":"+minute.ToString(); }}else{// TODO: CHECKSUM8 校验和有误Console.WriteLine("CheckSum ERR");}}Array.Clear(rxBuff, 0, rxBuff.Length);rxLen = 0;}})); }/// <summary>/// 串口数据接收函数/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e){SerialPort comPort = (SerialPort)sender;try{recvTimems = Environment.TickCount; // 更新串口数据接收时间//rxBuff[rxLen] = mSerialPort.ReadByte();int readCnt = mSerialPort.BytesToRead;Console.WriteLine("in readCnt:" + readCnt);mSerialPort.Read(rxBuff, rxLen, readCnt);rxLen += readCnt;Console.WriteLine("out rxLen:" + rxLen);#if falsebyte[] data = new byte[mSerialPort.BytesToRead];mSerialPort.Read(data, 0, data.Length);Console.WriteLine(data.Length);foreach (byte b in data){ Console.WriteLine(b.ToString("X2")); }
#endif}catch (Exception ce){MessageBox.Show(ce.Message);} }private void btnOpenCloseCom_Click(object sender, RoutedEventArgs e){if (mSerialPort.IsOpen){mSerialPort.Close();btnOpenCloseCom.Content = "打开串口";Console.WriteLine("关闭串口成功");Debug.WriteLine("关闭串口成功");comboBoxBaudRate.IsEnabled = true;comboBoxCOM.IsEnabled = true;comboBoxDataBit.IsEnabled = true;comboBoxStopBit.IsEnabled = true;comboBoxSdd.IsEnabled = true;comboBoxlik.IsEnabled = true;}else{mSerialPort.PortName = comboBoxCOM.SelectedItem.ToString();mSerialPort.BaudRate = 4800; // 波特率mSerialPort.DataBits = 8; // 数据位mSerialPort.StopBits = StopBits.One; // 停止位mSerialPort.Parity = Parity.None; // 校验位mSerialPort.Handshake = Handshake.None;//mSerialPort.ReadTimeout = 1500; // 读超时//mSerialPort.Encoding = Encoding.UTF8; // 编码方式//mSerialPort.RtsEnable = true;mSerialPort.DataReceived += SerialPort_DataReceived;Console.WriteLine("baudrate SelectedIndex:" + comboBoxBaudRate.SelectedIndex);Console.WriteLine("baudrate SelectedValue:" + comboBoxBaudRate.SelectedValue);Console.WriteLine("baudrate Text:" + comboBoxBaudRate.Text);if (comboBoxBaudRate.SelectedIndex < 0){mSerialPort.BaudRate = Convert.ToInt32(comboBoxBaudRate.Text);}else {switch (comboBoxBaudRate.SelectedValue){case "4800":mSerialPort.BaudRate = 4800;break;case "9600":mSerialPort.BaudRate = 9600;break;case "19200":mSerialPort.BaudRate = 19200;break;case "38400":mSerialPort.BaudRate = 38400;break;case "57600":mSerialPort.BaudRate = 57600;break;case "115200":mSerialPort.BaudRate = 115200;break;case "256000":mSerialPort.BaudRate = 256000;break;case "1000000":mSerialPort.BaudRate = 1000000;break;case "2000000":mSerialPort.BaudRate = 2000000;break;case "3000000":mSerialPort.BaudRate = 3000000;break; default:MessageBox.Show("波特率设置有误!");break;}}Console.WriteLine("端口:" + mSerialPort.PortName + ",波特率:" + mSerialPort.BaudRate);// mSerialPort.Write("Hello world"); // 写字符串口// mSerialPort.Write(new byte[] { 0xA0, 0xB0, 0xC0}, 0, 3); // 写入3个字节数据//Debug.WriteLine("Hello world");//MessageBox.Show("端口名:" + mSerialPort.PortName);try{mSerialPort.Open();btnOpenCloseCom.Content = "关闭串口";Console.WriteLine("打开串口成功");Debug.WriteLine("打开串口成功");comboBoxBaudRate.IsEnabled = false;comboBoxCOM.IsEnabled = false;comboBoxDataBit.IsEnabled = false;comboBoxStopBit.IsEnabled = false;comboBoxSdd.IsEnabled = false;comboBoxlik.IsEnabled = false;}catch (Exception ex){MessageBox.Show(ex.Message);}}}private void btnClearRecv_Click(object sender, RoutedEventArgs e){lineBuilder.Clear();textBlockRecv.Text = lineBuilder.ToString();}private void comboBoxCOM_Drop(object sender, DragEventArgs e){string[] ports = System.IO.Ports.SerialPort.GetPortNames();comboBoxCOM.ItemsSource = ports;comboBoxCOM.SelectedIndex = 0;}private void comboBoxBaudRate_DataContextChanged(object sender, DependencyPropertyChangedEventArgs e){ComboBoxItem obj = (ComboBoxItem)sender;}private void btnReadRecCount_Click(object sender, RoutedEventArgs e){if (mSerialPort.IsOpen){mSerialPort.Write(new byte[] { 0xAA, 0x00, 0x00, 0x00, 0xAA, 0x55 }, 0, 6); // 写入3个字节数据 }else{MessageBox.Show("请先打开串口!");}}private void btnReadDateTime_Click(object sender, RoutedEventArgs e){if (mSerialPort.IsOpen){mSerialPort.Write(new byte[] { 0xAA, 0x00, 0x08, 0x00, 0xB2, 0x55 }, 0, 6);}else{MessageBox.Show("请先打开串口!");}}private void btnReadRecord_Click(object sender, RoutedEventArgs e){ int index = Convert.ToInt32(txtBoxNumber.Text);if (index < 1 || index > 255){MessageBox.Show("记录索引:1~255!");}else {byte C1 = (byte)Convert.ToInt32(txtBoxNumber.Text);byte C2 = (byte)(cmboxRecordType.SelectedIndex);byte CS = (byte)((0xAA + C1 + C2)%0xFF);if (mSerialPort.IsOpen){byte[] Data = new byte[16];Data[0] = 0xAA;Data[1] = C1; // 指定记录条数Data[2] = (byte)(C2 + 1); // C2 记录分类从1开始Data[3] = 0x00;Data[4] = CS;Data[5] = 0x55;mSerialPort.Write(Data, 0, 6);}else{MessageBox.Show("请先打开串口!");}}}}
}
运行效果
源码下载
下载源码
相关文章:

C# WPF燃气报警器记录读取串口工具
C# WPF燃气报警器记录读取串口工具 概要串口帧数据布局文件代码文件运行效果源码下载 概要 符合国标文件《GB15322.2-2019.pdf》串口通信协议定义;可读取燃气报警器家用版设备历史记录信息等信息; 串口帧数据 串口通信如何确定一帧数据接收完成是个…...

【IEEE独立出版 | 往届快至会后2个月检索,刊后1个月检索】2024年第四届电子信息工程与计算机科学国际会议(EIECS 2024)
在线投稿:学术会议-学术交流征稿-学术会议在线-艾思科蓝 电子信息的出现与计算机技术、通信技术和高密度存储技术的迅速发展并在各个领域里得到广泛应用有着密切关系。作为高技术领域中重要的前沿技术之一,电子信息工程具有前瞻性、先导性的特点&#x…...

FPGA实现串口升级及MultiBoot(三)FPGA启动加载方式
缩略词索引: K7:Kintex 7V7:Vertex 7A7:Artix 7 上一篇中介绍了FPGA的启动步骤,如图0 所示,今天这篇文章就要在上一篇文章基础上进行分支细化,首先我们先了解FPGA 启动加载的几种方式。同时对于我们设计中常见的几个问题将在文章最…...

Linux驱动(六):Linux2.6驱动编写之平台设备总线
目录 前言一、平台设备总线1.是个啥?2.API函数 二、设备端驱动端1. 匹配机制2. 实现代码 三、设备树驱动端1.匹配机制2.代码实现 前言 本文主要介绍了一下两种驱动编写方法: 1.比较原始的设备端驱动端编写方法。 2.效率较高的设备树驱动端编写方法。 最…...

回溯——11.重新安排行程
力扣题目链接 给定一个机票的字符串二维数组 [from, to],子数组中的两个成员分别表示飞机出发和降落的机场地点,对该行程进行重新规划排序。所有这些机票都属于一个从 JFK(肯尼迪国际机场)出发的先生,所以该行程必须从…...

python+pytest+request 接口自动化测试
一、环境配置 1.安装python3 brew update brew install pyenv 然后在 .bash_profile 文件中添加 eval “$(pyenv init -)” pyenv install 3.5.3 -v pyenv rehash 安装完成后,更新数据库 pyenv versions 查看目前系统已安装的 Python 版本 pyenv global 3.5…...

《JavaEE进阶》----10.<SpringMVC应用分层:【三层架构】>
本篇博客我们主要讲解 1.应用的分层:三层架构 2.Spring MVC和三层架构的区别和联系 3.软件设计原则:高内聚低耦合 4.应用分层的好处 5.通过应用分层后的代码示例 一、三层架构简介 阿里开发手册中,关于工程结构部分,定义了常见工程的应用分层结构: 上图…...

【网络】网络通信的传输方式
目录 1.网络通信中的两种基本通信模式 1.1.怎么理解连接 1.2.面向有连接类型 1.3.面向无连接类型 2.实现这两种通信模式的具体交换技术 2.1.电路交换 2.2.分组交换 3.根据接收端数量分类 单播(Unicast) 广播(Broadcast) …...

数据仓库理论知识
1、数据仓库的概念 数据仓库(英文:Date Warehouse,简称数仓、DW),是一个用于数据存储、分析、报告的数据系统。数据仓库的建设目的是面向分析的集成化数据环境,其数据来源于不同的外部系统&#…...

容易中、见刊快的6本医学期刊推荐!
常笑医学整理了6本容易中、见刊快的医学期刊,以及期刊详细参数与投稿经验,供医生、医学生们在论文投稿时参考。投稿经历均来自常笑医学网用户真实分享,欢迎大家到常笑医学网分享自己的投稿经历和实用经验。 1.《中国医药科学》 (详…...

nnunetv2系列:使用默认的预测类推理2D数据
nnunetv2系列:使用默认的预测类推理2D数据 这里参考源代码nnUNet/nnunetv2/inference/predict_from_raw_data.py中给的示例进行调整和测试。 代码示例 from torch import device from nnunetv2.inference.predict_from_raw_data import nnUNetPredictor# from nn…...

伺服电机如何计算扭矩——看这一篇就够了
#零基础学工控##西门子PLC##V90##电机##工控分享##自动化#工控人加入PLC工业自动化精英社群 工控人加入PLC工业自动化精英社群...

数据库C语言删除修改和输出
#include<myhead.h> #include<sqlite3.h> int out_callback(void *arg,int column_num, char **msgrow,char **msgcolumn)//输出查找的工人信息 { int i 0, j 0; while(i<column_num) { printf("%s\t" ,*(msgcolumni)); …...

插槽slot
一、简介: 插槽是 Vue 组件化开发中非常强大且灵活的工具,它使得组件的复用性和可定制性大大提高。通过合理地使用不同类型的插槽,可以构建出更加灵活和可维护的 Vue 应用程序。 二、使用场景 可重用组件的定制化 比如一个通用的弹窗组件&am…...

交换技术是一种在计算机网络和通信系统中广泛应用的关键技术,它主要通过交换设备(如交换机、路由器等)实现数据的转发和传输
交换技术是一种在计算机网络和通信系统中广泛应用的关键技术,它主要通过交换设备(如交换机、路由器等)实现数据的转发和传输。交换技术的核心目的是在不同的设备之间高效地传输数据,实现信息的互联互通。 一、交换技术的定义 交换…...

数仓建模:数仓设计中的10个陷阱
目录 0 引言 1 主要内容 1.1 过于迷恋技术,而没有将重点放在业务需求和目标上 1.2 没有或无法找到一个有影响的、平易近人的、明白事理的高级管理人员作为数仓建设的发起人 1.3 将项目处理为一个巨大的持续多年的项目,而不是追求更容易管理的、虽然…...

Vue如何将网页转换成图片或PDF并上传
一.使用html2canvas获取页面元素并绘制成图片 htmlcanvas中文文档 npm install --save html2canvas<template><div><button click"uploadImg">上传</button><div ref"yourDom"><!-- ...图片中页面内容 --><img s…...

【引领数据分析革命】TaskWeaver框架全景解读与入门指南!
亲爱的技术爱好者们,我是你们的老朋友—— 一个热爱.NET和AI相关技术的博主,在今天这个信息与数据爆炸的时代,我们始终寻求着处理数据分析任务的更优雅、更高效的方式。Microsoft团队推出了一个叫做TaskWeaver的神器,这可不仅仅是…...

LabVIEW灵活集成与调试的方法
在LabVIEW开发中,为了构建一个既便于调试又能灵活集成到主VI中的控制VI,开发者需要采用适当的编程方式和架构。常见的选择包括模块化设计、状态机架构以及事件驱动编程。这些方法有助于简化调试过程、提高系统的稳定性,并确保代码的重用性和可…...

网络药理学:分子对接之二:PDB数据库的使用(已知PDB ID)、PubChem数据库如果没有3D结构
PDB数据库使用 官方地址:https://www.rcsb.org/ 首页如下: 我们以热休克蛋白HSP90AA1为例,其PDB ID为7DHG,所以我们在搜索栏输入7DHG: 主要关注红框里的几个地方。 Download 下载文件,一般选择PDB For…...

JS获取页面中video标签视频的封面和时长
从HTML中提取Video信息 /*** 从html字符串中提取video标签* 入参: {String} htmlString* 出参:{Array} 数组*/ function extractVideosFromHTML(htmlString) {const dom new DOMParser().parseFromString(htmlString, text/html);const videos Arr…...

LLM大模型学习:AI Agent综述
AI Agent是什么 将LLM思想链接到一起,自主实现用户设定的任何目标。只需要告诉AutoGPT一个目标,能自主生成执行计划。 吴恩达:“与其争论哪些工作才算是真正的 Agent,不如承认系统可以具有不同程度的 Agentic 特性。” 核心在于…...

极米科技:走出舒适圈,推动数据架构现代化升级 | OceanBase 《DB大咖说》
《DB 大咖说》第 13 期,邀请到了极米科技软件与创新产品线高级架构师施刘凡来进行分享。 在小红书平台上,“是否应将家里的电视升级为投影仪?”这一话题激发了上百万篇笔记的分享与推荐,反映出年轻群体对投影仪的偏好。随着手机、…...

IP学习——Fiveday
设备排错 [R1]display ip interface brief 查看路由器接口的IP地址信息 [R1]display current-configuration int g0/0/1.10 查看路由器接口的IP地址信息 TG---> trunk查看vlan指令:displayvan其中UT--->accessc.vlan确认完成后 即链路层配置完成排查网络层错误 排查终端主…...

格式化的硬盘能恢复数据吗?拯救数据的可能性
在信息技术高速发展的今天,硬盘作为计算机的核心存储部件,承载着大量的数据和文件。然而,有时因为误操作或其他原因,我们可能需要对硬盘进行格式化,这往往导致重要数据的丢失。 那么,格式化后的硬盘数据是否…...

亚信安全出席第五届国际反病毒大会 探究AI现代网络勒索治理
近日,第二届网络空间安全(天津)论坛正式开幕。本届论坛由天津市政府主办,国家计算机病毒应急处理中心、天津市公安局、天津市滨海新区政府承办,国家网络与信息安全信息通报中心协办,围绕“共建网络安全 共治…...

C语言从头学58——学习头文件math.h(一)
math.h 头文件提供了很多数学计算方面的函数。 一、使用数学函数前需要了解的两个类型、两个宏 1、float_t:当前系统能够有效执行float运算的类型,宽度不少于float。 2、double_t:当前系统能够有效执行double运算的类型,宽度不…...

前端JS常见面试题
数据双向绑定 Bug解决 集成工作涉及 版本node 依赖包报错 版本问题!!!ElementUI、Cesium、ant-design 配置、代码和其他 混入 在Vue中,混入(Mixins)是一种非常有用的功能,它允许你创建可复…...

利用深度学习实现验证码识别-4-ResNet18+imagecaptcha
在当今的数字化世界中,验证码(CAPTCHA)是保护网站免受自动化攻击的重要工具。然而,对于用户来说,验证码有时可能会成为一种烦恼。为了解决这个问题,我们可以利用深度学习技术来自动识别验证码,从…...

IDC基础学习笔记
一、数据中心介绍 1、数据中心级别划分: 2、数据中心结构: 3、IT系统组成 二、数据中心硬件知识 1、服务器组件 服务器的正面接口: 服务器的反面接口: (1)CPU CPU定义:中央处理器(…...