当前位置: 首页 > news >正文

C#上位机序列10: 批量读写+点对点更新+数据类型处理

一、源码结构

二、运行效果

三、源码解析

PLC批量读写+点对点更新+数据类型处理

优点:根据数据类型,判定监听的地址范围(40120_int 监听两个word:40120 40121;40130_long 监听四个word:40130 40131 40132 40133),添加到UI字典中,PLC批量读取,判定数据变化,查找控件集合,点对点更新,效率高

实现流程:
1. 读取配置文件及创建变量信息(点位名称,地址,数据类型(bool/short/int/float/long/double))

2. 自定义控件绑定参数,用UI字典存储,通过属性get方式,如果是bool类型,直接取Bool字典的点位数据;如果是Word类型,根据数据类型拼装Word字典中的word数据,得到对应数据类型的点位数据;通过set方式,加入到写队列。

复制代码

using PLCBind.CustomControls;
using PLCBind.Service;
using PLCBind.Util;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;namespace PLCBind
{public partial class MainForm : Form{ public MainForm(){InitializeComponent();}private void MainForm_Load(object sender, EventArgs e){CommonMethods.LoadVar();// 读取配置文件及创建变量信息(点位名称,地址,类型)PLCService.Init();      // 读任务&写任务,数据有变化时事件广播通知(自定义控件预先绑定事件)BindControlParamModel();// 为按钮绑定参数}/// <summary>/// 为控件绑定参数/// </summary>private void BindControlParamModel(){InitControlTag(); SetControlParamModel();}/// <summary>/// 绑定控件变量/// </summary>void InitControlTag(){// 左皮带lblYX1.Tag = ucBeltLeft1.Tag = "00101";// 启动lblZS1.Tag = "40101";// 转速lblDY1.Tag = "40120";// 电压lblDL1.Tag = "40130";// 电流 }/// <summary>/// 赋值控件参数/// </summary>void SetControlParamModel(){foreach (Control item in this.pnlMain.Controls){if (item is ITransferUI objItem){var address = item.Tag.ToString();var common = CommonMethods.HomeVariables.Where(obj => obj.PLCAddress == address).FirstOrDefault();if (common != null){objItem.ParamModel = common;List<string> lstAddress = null;switch (common.DataType){case DataType.Bool:lstAddress = PLCService.RangeAddress(common.PLCAddress, 0);break;case DataType.Short:lstAddress = PLCService.RangeAddress(common.PLCAddress, 0);break;case DataType.Int:case DataType.Float:lstAddress = PLCService.RangeAddress(common.PLCAddress, 2);// 40120 监听两个word:40120 40121break;case DataType.Long:case DataType.Double:lstAddress = PLCService.RangeAddress(common.PLCAddress, 4);// 40130 监听四个word:40130 40131 40132 40133break;} foreach (var range in lstAddress){  CommonMethods.AddControl(CommonMethods.DicHomeControl, range, item);}  }}}}private void tabControl1_SelectedIndexChanged(object sender, EventArgs e){var index = tabControl1.SelectedIndex;switch (index){case 0:this.ucParameter1.RemoveParams();break;case 1:// 参数设置this.pnlSet.Controls.Clear();this.pnlSet.Controls.Add(ucParameter1);this.ucParameter1.ListParams = CommonMethods.SetVariables.Where(s => s.Group == "顺序启动参数").ToList();break;}} }
}

复制代码

复制代码

using PLCBind.Service;namespace PLCBind.UIForm
{public class BaseParams{/// <summary>/// 描述/// </summary>public string Description { get; set; }/// <summary>/// PLC地址, 多个输入时,用";"分隔开/// </summary>public string PLCAddress { get; set; } /// <summary>/// 数据类型/// </summary>public DataType DataType { get; set; }/// <summary>/// 数据分组/// </summary>public string Group { get; set; }/// <summary>/// 单位/// </summary>public string Unit { get; set; }/// <summary>/// 设置与获取PLC值/// </summary>public object PLCValue{get{object obj = null; switch (DataType){case DataType.Bool:obj = PLCService.GetBool(PLCAddress);break;case DataType.Short:obj = PLCService.GetShort(PLCAddress);break;case DataType.Int:obj = PLCService.GetInt(PLCAddress);break;case DataType.Float:obj = PLCService.GetFloat(PLCAddress);break;case DataType.Long:obj = PLCService.GetLong(PLCAddress);break;case DataType.Double:obj = PLCService.GetDouble(PLCAddress);break;} return obj;}set{PLCService.AddWriteVariable(PLCAddress, value, DataType);}} }
}

复制代码

3. 异步任务处理:读任务&写任务,将读到的数据存到Data字典中,判断数据是否有发生变化,如果数据有变化,通过UI字典获取控件集合,调用更新方法

复制代码

using HslCommunication;
using HslCommunication.Core;
using HslCommunication.ModBus;
using PLCBind.CustomControls;
using PLCBind.Util;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Windows.Forms;
using UtilHelper;namespace PLCBind.Service
{public class PLCService{ public static ConcurrentDictionary<string, bool> DicBoolData = new ConcurrentDictionary<string, bool>();public static ConcurrentDictionary<string, Word> DicWordData = new ConcurrentDictionary<string, Word>();public static ConcurrentDictionary<string, Word> DicWordChange = new ConcurrentDictionary<string, Word>();//static ModbusTcpNet client = null;static IByteTransform byteTransform;static ConcurrentQueue<PLCModel> queueWrite = new ConcurrentQueue<PLCModel>();// UI通知static void NoticeUI(string address, ConcurrentDictionary<string, List<Control>> dicControl){dicControl.TryGetValue(address, out List<Control> lstControl);if (null != lstControl){foreach (var item in lstControl){if (item is ITransferUI objItem){objItem.NoticeChange();}}}}/// <summary>/// 事件触发/// </summary> public static void DataChange(string address){Task.Run(() => NoticeUI(address, CommonMethods.DicHomeControl));Task.Run(() => NoticeUI(address, CommonMethods.DicSetControl));}/// <summary>/// 自定义控件内接收到数据变化事件,根据传入address,以及DataType查询监听地址所需要的监听范围(40120_int 监听两个word:40120 40121;40130_long 监听四个word:40130 40131 40132 40133),判断是否属于本控件监听/// </summary>public static List<string> RangeAddress(string address, int length){List<string> lstaddress = new List<string>();if (0 == length){lstaddress.Add(address);}else{for (int i = 0; i < length; i++){lstaddress.Add(FillAddress((DataHelper.Obj2Int(address) + i).ToString()));}}return lstaddress;}/// <summary>/// 读取时,按位补充0/// </summary>public static string FillAddress(string val, int length = 5){return val.PadLeft(length, '0');}/// <summary>/// 写入时,格式化地址,如:40101 -> 101/// </summary> public static string FormatAddress(string val){if (val.Length < 5) return val;return val.Substring(1, val.Length - 1);}/// <summary>/// 初始化plc通信,开启读写任务/// </summary>public static void Init(){client = new ModbusTcpNet(CommonMethods.PLCConfig.HostAddress, CommonMethods.PLCConfig.PortNumber);client.AddressStartWithZero = false;client.DataFormat = DataFormat.CDAB;byteTransform = client.ByteTransform;TskPlcRead();TskPlcWrite();}/// <summary>/// 获取bool(bool类型)/// </summary>/// <param name="address"></param>/// <returns></returns>public static bool GetBool(string address){ try{bool exist = DicBoolData.TryGetValue(address, out var value);// 字典存储if (!exist){Logger.Info($"[Error] PLCService,GetBool,errmsg:查无点位数据({address})");}return value;}catch (Exception ex){Logger.Info("[Error] PLCService,GetBool,errmsg:" + ex.Message);}return false;}/// <summary>/// 获取word(1个word,2个字节)/// </summary> static Word GetAddressWord(string address, int add){address = FillAddress((Convert.ToInt32(address) + add).ToString());bool exist = DicWordData.TryGetValue(address, out var value);if (!exist){Logger.Info($"[Error] PLCService,GetAddressWord,errmsg:查无点位数据({address})");}return value;}/// <summary>/// 拼接字节(多个word)/// </summary> static byte[] JoinAddressWord(string address, DataType datatype){byte[] ret = null;switch (datatype){ case DataType.Short:{ var buff = GetAddressWord(address, 0);ret = new byte[2] { buff.Byte1, buff.Byte2 };}break;case DataType.Int:case DataType.Float:{var buff1 = GetAddressWord(address, 0);var buff2 = GetAddressWord(address, 1);ret = new byte[4] { buff1.Byte1, buff1.Byte2, buff2.Byte1, buff2.Byte2 };} break;case DataType.Long: case DataType.Double:{var buff1 = GetAddressWord(address, 0);var buff2 = GetAddressWord(address, 1);var buff3 = GetAddressWord(address, 2);var buff4 = GetAddressWord(address, 3);ret = new byte[8] { buff1.Byte1, buff1.Byte2, buff2.Byte1, buff2.Byte2, buff3.Byte1, buff3.Byte2, buff4.Byte1, buff4.Byte2 };} break;}return ret;}public static ushort GetShort(string address){try{ var buff = JoinAddressWord(address, DataType.Short);return byteTransform.TransUInt16(buff, 0); }catch (Exception ex){Logger.Info("[Error] PLCService,GetShort,errmsg:" + ex.Message);}return 0;}public static uint GetInt(string address){try{var buff = JoinAddressWord(address, DataType.Int);return byteTransform.TransUInt32(buff, 0);}catch (Exception ex){Logger.Info("[Error] PLCService,GetInt,errmsg:" + ex.Message);}return 0;}public static float GetFloat(string address){try{var buff = JoinAddressWord(address, DataType.Float);return byteTransform.TransSingle(buff, 0);}catch (Exception ex){Logger.Info("[Error] PLCService,GetFloat,errmsg:" + ex.Message);}return 0;}public static ulong GetLong(string address){try{var buff = JoinAddressWord(address, DataType.Long);return byteTransform.TransUInt64(buff, 0);}catch (Exception ex){Logger.Info("[Error] PLCService,GetLong,errmsg:" + ex.Message);}return 0;}public static double GetDouble(string address){try{var buff = JoinAddressWord(address, DataType.Double);return byteTransform.TransDouble(buff, 0);}catch (Exception ex){Logger.Info("[Error] PLCService,GetDouble,errmsg:" + ex.Message);}return 0;}/// <summary>/// 定时读取/// </summary>static void TskPlcRead(){Task.Factory.StartNew(async () =>{var start_c = CommonMethods.PLCConfig.ReadStart_Coil;var start_h = CommonMethods.PLCConfig.ReadStart_Holding;bool[] temp_c = null; bool init_c = false;byte[] temp_h = null; bool init_h = false;while (!CommonMethods.CTS.IsCancellationRequested){try{DicWordChange.Clear();var array_c = (await client.ReadBoolAsync(start_c, (ushort)CommonMethods.PLCConfig.ReadCount_Coil)).Content;var array_h = (await client.ReadAsync(start_h, (ushort)(CommonMethods.PLCConfig.ReadCount_Holding * 2))).Content;// ushort占两个字节if (null != array_c){// bool类型只占1位,数据有变化直接通知if (null == temp_c){init_c = true;temp_c = new bool[array_c.Length];}CheckBoolChange("0", start_c, temp_c, array_c, init_c); init_c = false;Array.Copy(array_c, temp_c, array_c.Length);}if (null != array_h){// word类型数据位(2,4,8),所以要先读取全部的数据,再通知变化if (null == temp_h){init_h = true;temp_h = new byte[array_h.Length];}CheckWordChange("4", start_h, temp_h, array_h, init_h); init_h = false;Array.Copy(array_h, temp_h, array_h.Length);if (DicWordChange.Count > 0){foreach (var item in DicWordChange){DataChange(item.Key);}}}}catch (Exception ex){Logger.Info("[Error] PLCMgr,TskPlcRead,errmsg" + ex.Message);}await Task.Delay(100);}}, TaskCreationOptions.LongRunning);}/// <summary>/// 检查数据是否有变化(bool类型)/// </summary> public static void CheckBoolChange(string flg, string start, bool[] oldbuffer, bool[] newbuffer, bool init){for (int i = 0; i < newbuffer.Length; i++){// 00101string address = flg + FillAddress((i + Convert.ToInt32(start)).ToString(), 4); bool value = newbuffer[i];DicBoolData.AddOrUpdate1(address, value); if (init || oldbuffer[i] != value){ DataChange(address);}}}/// <summary>/// 检查数据是否有变化(word类型)/// </summary> public static void CheckWordChange(string flg, string start, byte[] oldbuffer, byte[] newbuffer, bool init){int index = 0;for (int i = 0; i < newbuffer.Length; i = i + 2){// 40101string address = flg + FillAddress((index + Convert.ToInt32(start)).ToString(), 4); index++; byte byte1 = newbuffer[i];byte byte2 = newbuffer[i + 1];Word buff = new Word() { Byte1 = byte1, Byte2 = byte2 };DicWordData.AddOrUpdate1(address, buff);if (init || (oldbuffer[i] != byte1 || oldbuffer[i + 1] != byte2)){DicWordChange.AddOrUpdate1(address, buff);}}}/// <summary>/// 添加写入值/// </summary> public static void AddWriteVariable(string address, object value, DataType datatype){queueWrite.Enqueue(new PLCModel() { Address = address, Value = value, PLCDataType = datatype });//加载值进队列} /// <summary>/// 定时写入/// </summary>static void TskPlcWrite(){ Task.Factory.StartNew(async () =>{while (!CommonMethods.CTS.IsCancellationRequested){try{if (!queueWrite.IsEmpty){PLCModel model = null; OperateResult result = null;queueWrite.TryDequeue(out model);var dataype = model.PLCDataType;switch (dataype){case DataType.Bool:result = await client.WriteAsync(FormatAddress(model.Address), Convert.ToBoolean(model.Value));break;case DataType.Short:result = await client.WriteAsync(FormatAddress(model.Address), Convert.ToUInt16(model.Value)); break;case DataType.Int:result = await client.WriteAsync(FormatAddress(model.Address), Convert.ToUInt32(model.Value));break;case DataType.Float:result = await client.WriteAsync(FormatAddress(model.Address), Convert.ToSingle(model.Value));break;case DataType.Long:result = await client.WriteAsync(FormatAddress(model.Address), Convert.ToUInt64(model.Value));break;case DataType.Double:result = await client.WriteAsync(FormatAddress(model.Address), Convert.ToDouble(model.Value));break;}if (!result.IsSuccess){Logger.Info("[Error] PLCMgr,TskPlcWrite,errmsg:写入失败," + result.Message);}}}catch (Exception ex){ Logger.Info("[Error] PLCMgr,TskPlcWrite,errmsg:" + ex.Message);} await Task.Delay(100);}}, TaskCreationOptions.LongRunning);}}
}

复制代码

4. 主界面控件都是静态加载,参数设置的控件是动态加载(点击进入,动态加载变量并监听;离开,移除不监听)

复制代码

using PLCBind.Util;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;namespace PLCBind.UIForm
{public partial class ucParameter : UserControl{public ucParameter(){InitializeComponent();} /// <summary>/// 参数集合/// </summary>public object ListParams{set{ RemoveParams();if (value is List<BaseParams> Parameters){AddParams(Parameters);}}}/// <summary>/// 移除参数/// </summary>public void RemoveParams(){foreach (Control item in this.tableLayoutPanel1.Controls){if (item is ucTextSetting ctrText){CommonMethods.RemoveControl(CommonMethods.DicSetControl, ctrText.Address);// 移除集合}}this.tableLayoutPanel1.Controls.Clear(); // 移除控件}/// <summary>/// 添加参数/// </summary> void AddParams(List<BaseParams> objParams){ var pamramCount = objParams.Count;var pamrammIndex = 0;for (int columnIndex = 0; columnIndex < tableLayoutPanel1.ColumnCount; columnIndex++){for (int rowIndex = 0; rowIndex < tableLayoutPanel1.RowCount; rowIndex++){if (pamramCount > pamrammIndex){var common = objParams[pamrammIndex];var address = common.PLCAddress;ucTextSetting ucLbText = new ucTextSetting();ucLbText.Anchor = ((((AnchorStyles.Top | AnchorStyles.Bottom) | AnchorStyles.Left)));ucLbText.ParamModel = common;ucLbText.Address = address;CommonMethods.AddControl(CommonMethods.DicSetControl, address, ucLbText);// 添加集合tableLayoutPanel1.Controls.Add(ucLbText, columnIndex, rowIndex);// 添加控件 pamrammIndex++;}}}}private void TableLayoutPanel1_CellPaint(object sender, TableLayoutCellPaintEventArgs e){if (e.Row % 2 == 1)e.Graphics.FillRectangle(Brushes.White, e.CellBounds);elsee.Graphics.FillRectangle(new SolidBrush(Color.FromArgb(192, 224, 248)), e.CellBounds);}}
}

复制代码

注意事项:
1. 字典类型
Data字典:ConcurrentDictionary<string, bool> DicBoolData;ConcurrentDictionary<string, Word> DicWordData;Word:byte1,byte2
UI字典:ConcurrentDictionary<string, List<Control>> DicHomeControl;ConcurrentDictionary<string, List<Control>> DicSetControl
2. bool类型只占1位,数据有变化直接通知
3. word类型数据位(short:2,int/float:4,long/double:8),所以要先读取全部的数据,再通知变化
4. 自定义控件继承ITransferUI类(属性:ParamModel,方法:NoticeChange),赋值属性ParamModel,其中PLCValue get:通过不同的数据类型,获取字典中的word数据,并拼接合成相应的数据类型;set:传入地址(写入时格式化地址,如:40101->101)及类型

相关文章:

C#上位机序列10: 批量读写+点对点更新+数据类型处理

一、源码结构 二、运行效果 三、源码解析 PLC批量读写点对点更新数据类型处理 优点&#xff1a;根据数据类型&#xff0c;判定监听的地址范围&#xff08;40120_int 监听两个word&#xff1a;40120 40121&#xff1b;40130_long 监听四个word&#xff1a;40130 40131 40132 4…...

MySQL 概述 数据库表操作 数据增删改

目录 MySQL概述前言安装与配置MySQL登录与卸载 数据模型概述SQL简介SQL通用语法简介SQL分类 数据库设计(数据库操作)-DDL数据库操作查询数据库 show databases、select database()创建数据库 create database使用数据库 use删除数据库 drop database 图形化工具连接数据库操作数…...

存储器概述

一、存储系统基本概念...

Fabric.js 使用自定义字体

本文简介 点赞 关注 收藏 学会了 如果你使用 Fabric.js 做编辑类的产品&#xff0c;有可能需要给用户配置字体。 这次就讲讲在 Fabric.js 中创建文本时怎么使用自定义字体、在项目运行时怎么修改字体、以及推荐一个精简字体库的工具。 学习本文前&#xff0c;你必须有一点…...

【C++项目】高并发内存池第七讲性能分析

目录 1.测试代码2.代码介绍3.运行结结果 1.测试代码 #include"ConcurrentAlloc.h" #include"ObjectPool.h" #include"Common.h" void BenchmarkMalloc(size_t ntimes, size_t nworks, size_t rounds) {std::vector<std::thread> vthread(…...

【JavaScript】快速学习JS

JS区分大小写&#xff0c;后面的分号可有可无&#xff1b; 输出语句 window.alter() // 写入警告框&#xff1b;在浏览器中的警告弹窗输出 document.write() // 写入html输出&#xff1b;在html页面中输出 console.log() // 写入浏览器控制台&#xff1b;在控制台输出 变量…...

控制输入流,从控制台打印到文件中,更改输出的位置

public static void main(String[] args) throws IOException {PrintStream printStream System.out;//在默认情况下&#xff0c;PrintStream 输出数据的位置 标准输出&#xff0c;即显示器printStream.print("Tom,hello");/*public void print(String s) {if (s n…...

计算线阵相机 到 拍摄产品之间 摆放距离?(隐含条件:保证图像不变形)

一物体被放置在传送带上&#xff0c;转轴的直径为100mm。已知线阵相机4K7u&#xff08;一行共4096个像素单元&#xff0c;像素单元大小7um&#xff09;&#xff0c;镜头35mm&#xff0c;编码器2000脉冲/圈。保证图像不变形的条件下&#xff0c;计算相机到产品之间 摆放距离&…...

【网络】详解http协议

目录 一、认识URLurlencode和urldecode 二、HTTP协议HTTP协议格式HTTP的方法HTTP的状态码HTTP常见Header 一、认识URL URL叫做统一资源定位符&#xff0c;也就是我们平时俗称的网址&#xff0c;是因特网的万维网服务程序上用于指定信息位置的表示方法。 urlencode和urldecode …...

1819_ChibiOS的互斥信号与条件变量

全部学习汇总&#xff1a; GreyZhang/g_ChibiOS: I found a new RTOS called ChibiOS and it seems interesting! (github.com) 1. 关于会吃信号与条件变量的全局配置提供了4个配置信息&#xff0c;分别是互斥信号的使能、互斥信号的递归支持、条件变量的使能、条件变量的超时使…...

CSDN学院 < 华为战略方法论进阶课 > 正式上线!

目录 你将收获 适用人群 课程内容 内容目录 CSDN学院 作者简介 你将收获 提升职场技能提升战略规划的能力实现多元化发展综合能力进阶 适用人群 主要适合公司中高层、创业者、产品经理、咨询顾问&#xff0c;以及致力于改变现状的学员。 课程内容 本期课程主要介绍华为…...

电商接口api数据比价接口推荐

当前&#xff0c;受诸多因素的影响&#xff0c;经济下行&#xff0c;在日趋激烈的市场竞争中&#xff0c;很多企业也都面临着越来越大的生存压力&#xff0c;企业的盈利空间也逐渐被压缩。因此&#xff0c;越来越多的企业在控制成本方面更下功夫&#xff0c;这也就对企业采购提…...

读取Excel的工具类——ExcelKit

文章目录 ExcelKit工具类1、准备工作1.1、SheetInfoVo1.2、BizException 2、读取xlsx3、读取xls4、完整的ExcelKit.java源码 ExcelKit工具类 1、准备工作 1.1、SheetInfoVo import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor;import …...

vscode连接服务器一直retry

解决方法 打开vscode控制面板&#xff0c;输入命令remote-ssh: kill vs code server on host 选择一直连接不上的服务器端口 重新连接...

Spring Cloud Sentinel整合Nacos实现配置持久化

sentinel配置相关配置后无法持久化&#xff0c;服务重启之后就没了&#xff0c;所以整合nacos&#xff0c;在nacos服务持久化&#xff0c;sentinel实时与nacos通信获取相关配置。 使用上一章节Feign消费者服务实现整合。 版本信息&#xff1a; nacos:1.4.1 Sentinel 控制台 …...

STM32F4VGT6-DISCOVERY:uart1驱动

对于这款板子&#xff0c;官方并没有提供串口例程&#xff0c;只能自行添加。 一、PA9/PA10复用成串口1功能不可用 驱动测试代码如下&#xff1a; main.c: #include "main.h" #include <stdio.h>void usart1_init(void) {GPIO_InitTypeDef GPIO_InitStruct…...

C语言之 结构体,枚举,联合

目录 1.结构体 1.1结构的基础知识 1.2结构的声明 1.3 特殊的声明 1.4 结构的自引用 1.5 结构体变量的定义和初始化 1.6 结构体内存对齐 1.7 修改默认对齐数 1.8 结构体传参 2. 位段 2.1 什么是位段 2.2位段的内存分配 2.3 位段的跨平台问题 3. 枚举 3.1 枚举类型…...

红米电脑硬盘剪切

Redmi R14 2023版固态硬盘剪切 工具准备操作结尾语 首先要说明&#xff0c;本文所说的操作不一定适合你的电脑&#xff0c;因为电子产品更新换代过快&#xff0c;你的硬盘不一定能剪切&#xff0c;在操作前一定要仔细观察硬盘的型号&#xff0c;是否为同款&#xff0c;我上了图…...

微信小程序在线预览PDF文件

需求&#xff1a;微信小程序在线预览PDF合同文件&#xff0c;加载完成后强制阅读10秒才可点击同意按钮 H5代码&#xff1a; <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" cont…...

Android 工厂模式增加Type-A功能测试

Android 工厂模式增加Type-A功能测试 收到客户需求想要增加Type-A测试项来验证Type-A功能&#xff0c;具体功能实现参照如下&#xff1a; /vendor/freeme/packages/apps/FreemeFactoryTest/src/com/freeme/factory/usb/TypeAUSB.java package com.freeme.factory.usb;i…...

基于服务器使用 apt 安装、配置 Nginx

&#x1f9fe; 一、查看可安装的 Nginx 版本 首先&#xff0c;你可以运行以下命令查看可用版本&#xff1a; apt-cache madison nginx-core输出示例&#xff1a; nginx-core | 1.18.0-6ubuntu14.6 | http://archive.ubuntu.com/ubuntu focal-updates/main amd64 Packages ng…...

C# SqlSugar:依赖注入与仓储模式实践

C# SqlSugar&#xff1a;依赖注入与仓储模式实践 在 C# 的应用开发中&#xff0c;数据库操作是必不可少的环节。为了让数据访问层更加简洁、高效且易于维护&#xff0c;许多开发者会选择成熟的 ORM&#xff08;对象关系映射&#xff09;框架&#xff0c;SqlSugar 就是其中备受…...

[Java恶补day16] 238.除自身以外数组的乘积

给你一个整数数组 nums&#xff0c;返回 数组 answer &#xff0c;其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法&#xff0c;且在 O(n) 时间复杂度…...

什么?连接服务器也能可视化显示界面?:基于X11 Forwarding + CentOS + MobaXterm实战指南

文章目录 什么是X11?环境准备实战步骤1️⃣ 服务器端配置(CentOS)2️⃣ 客户端配置(MobaXterm)3️⃣ 验证X11 Forwarding4️⃣ 运行自定义GUI程序(Python示例)5️⃣ 成功效果![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/55aefaea8a9f477e86d065227851fe3d.pn…...

均衡后的SNRSINR

本文主要摘自参考文献中的前两篇&#xff0c;相关文献中经常会出现MIMO检测后的SINR不过一直没有找到相关数学推到过程&#xff0c;其中文献[1]中给出了相关原理在此仅做记录。 1. 系统模型 复信道模型 n t n_t nt​ 根发送天线&#xff0c; n r n_r nr​ 根接收天线的 MIMO 系…...

【生成模型】视频生成论文调研

工作清单 上游应用方向&#xff1a;控制、速度、时长、高动态、多主体驱动 类型工作基础模型WAN / WAN-VACE / HunyuanVideo控制条件轨迹控制ATI~镜头控制ReCamMaster~多主体驱动Phantom~音频驱动Let Them Talk: Audio-Driven Multi-Person Conversational Video Generation速…...

【7色560页】职场可视化逻辑图高级数据分析PPT模版

7种色调职场工作汇报PPT&#xff0c;橙蓝、黑红、红蓝、蓝橙灰、浅蓝、浅绿、深蓝七种色调模版 【7色560页】职场可视化逻辑图高级数据分析PPT模版&#xff1a;职场可视化逻辑图分析PPT模版https://pan.quark.cn/s/78aeabbd92d1...

【SSH疑难排查】轻松解决新版OpenSSH连接旧服务器的“no matching...“系列算法协商失败问题

【SSH疑难排查】轻松解决新版OpenSSH连接旧服务器的"no matching..."系列算法协商失败问题 摘要&#xff1a; 近期&#xff0c;在使用较新版本的OpenSSH客户端连接老旧SSH服务器时&#xff0c;会遇到 "no matching key exchange method found"​, "n…...

Kafka入门-生产者

生产者 生产者发送流程&#xff1a; 延迟时间为0ms时&#xff0c;也就意味着每当有数据就会直接发送 异步发送API 异步发送和同步发送的不同在于&#xff1a;异步发送不需要等待结果&#xff0c;同步发送必须等待结果才能进行下一步发送。 普通异步发送 首先导入所需的k…...

Java数值运算常见陷阱与规避方法

整数除法中的舍入问题 问题现象 当开发者预期进行浮点除法却误用整数除法时,会出现小数部分被截断的情况。典型错误模式如下: void process(int value) {double half = value / 2; // 整数除法导致截断// 使用half变量 }此时...