巧用python之--模仿PLC(PLC模擬器)

工作中用到了VM(VisionMaster4.3)有時候需要和PLC打交道,但是PLC畢竟是別人的,不方便修改別人的程序,這時候需要一個靈活的PLC模擬器是多么好呀!

先說背景:

PLC型號
匯川Easy521:
Modbus TCP 192.168.1.10:502?
在匯川Easy521中Modbus保持寄存器=D寄存器 ,在modbus協議中 0-4區 3區就是 保持寄存器(R/W)

那么事情很簡單了:只需要做一個ModbusTCP的服務端 就能模擬PLC:

Modbus RTU是主從結構 分 Modbus? 主機 / 從機 ?Master / Slave;

RTU模式主從 主機會輪詢從機 問一次答一次;? ?一般電腦做主機 PLC做從機;

但是當電腦同時連接很多臺PLC,電腦做主機,主動詢問PLC那么電腦的壓力會很大;

這時候電腦可以做從機,多個PLC做主機,電腦端成了被動,那么電腦壓力會小很多;

(適用于MODBUS RTU &TCP) 扯遠了;

好了這里只說Modbus_TCP?粗略的說Modbus_TCP的報文實際就是RTU 增加文件頭去掉CRC校驗;

注意下面說的Tcp都指得是modbusTCP;;;

客戶端 服務器?Client/Server

VisionMaster4.3只支持Modbus> TcpClient?

TcpClient按主從結構分是主機/(Master), PLC扮演的是 Modbus> TcpServer (Slave)

所以在Modbustcp這里,服務器是modbus從機,客戶端是modbus主機;

由 TcpClient(VM) 去 輪詢?TcpServer(PLC);

? 好了,搞清楚原理了,下來就是,模擬一個TcpServer(PLC);就是一個可以用的PLC模擬器.

當然你用Modsim/ModScan也可以,但是操作不便;

;因為之前就做過一些用hsl庫C#,模擬modbusTCPServer,這里程序放出來吧;

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;using System;
using System.Collections.Generic;
using System.Net;
using System.Runtime.Remoting.Contexts;
using System.Threading;using HslCommunication;namespace MB_TCPServer
{public partial class Form1 : Form{HslCommunication.ModBus.ModbusTcpServer modbusTcpServer;public Form1(){InitializeComponent();modbusTcpServer  = new HslCommunication.ModBus.ModbusTcpServer();modbusTcpServer.ServerStart(502);modbusTcpServer.Write("50", (UInt16)1);modbusTcpServer.Write("60", (UInt16)1);modbusTcpServer.Write("61", (UInt16)1);OperateResult <UInt16> intReg_100 = modbusTcpServer.ReadUInt16("50");                    // 讀取輸入寄存器100的值if (intReg_100.IsSuccess){Console.WriteLine("success!");Console.WriteLine("");}else{Console.WriteLine("failed:" + intReg_100.Message);}List<string> ipAddresses = GetIpAddresses();//調用Console.WriteLine(ipAddresses.Count);//有幾個ipforeach (string ipAddress in ipAddresses){Console.WriteLine(ipAddress);//ip分別有哪些comboBox_me_ip.Items.Add(ipAddress);}comboBox_me_ip.SelectedItem   = 1; }private void button1_Click(object sender, EventArgs e){}public static List<string> GetIpAddresses(){List<string> ipAddresses = new List<string>();try{// 獲取本地主機名string hostName = Dns.GetHostName();// 使用主機名獲取IP地址信息IPHostEntry hostEntry = Dns.GetHostEntry(hostName);// 獲取IP地址列表foreach (IPAddress ipAddress in hostEntry.AddressList){// 確保IP地址不是IPv6的環回地址或者IPv4的環回地址if (!ipAddress.IsIPv4MappedToIPv6 && ipAddress.AddressFamily != System.Net.Sockets.AddressFamily.InterNetworkV6){ipAddresses.Add(ipAddress.ToString());}}}catch (Exception ex){}return ipAddresses;/*List<string> ipAddresses = GetIpAddresses();//調用Console.WriteLine(ipAddresses.Count);//有幾個ipforeach (string ipAddress in ipAddresses){Console.WriteLine(ipAddress);//ip分別有哪些}*/}private void button_trig_Click(object sender, EventArgs e){modbusTcpServer.Write("50", (UInt16)10);    OperateResult<UInt16> intReg_100 = modbusTcpServer.ReadUInt16("50");                    // 讀取輸入寄存器100的值if (intReg_100.IsSuccess){Console.WriteLine("success!");Console.WriteLine(intReg_100.Content);textBox_trig.Text= intReg_100.Content.ToString();}else{Console.WriteLine("failed:" + intReg_100.Message);}}private void button2_Click(object sender, EventArgs e){modbusTcpServer.Write("50", (UInt16)0);OperateResult<UInt16> intReg_100 = modbusTcpServer.ReadUInt16("50");                    // 讀取輸入寄存器100的值if (intReg_100.IsSuccess){Console.WriteLine("success!");Console.WriteLine(intReg_100.Content);textBox_trig.Text = intReg_100.Content.ToString();}else{Console.WriteLine("failed:" + intReg_100.Message);}}private void button3_Click(object sender, EventArgs e){button_trig_Click(null,null);Thread.Sleep(200);// 太快vm反應不過來button2_Click(null, null);}}
}

?可以看出實際有用的只有這些:其余都是 winform界面;

using HslCommunication;
namespace MB_TCPServer
{public partial class Form1 : Form{HslCommunication.ModBus.ModbusTcpServer modbusTcpServer;public Form1(){modbusTcpServer  = new HslCommunication.ModBus.ModbusTcpServer();modbusTcpServer.ServerStart(502);modbusTcpServer.Write("50", (UInt16)1);modbusTcpServer.Write("60", (UInt16)1);modbusTcpServer.Write("61", (UInt16)1);OperateResult <UInt16> intReg_100 = modbusTcpServer.ReadUInt16("50");                    if (intReg_100.IsSuccess){Console.WriteLine("success!");Console.WriteLine("");}else{Console.WriteLine("failed:" + intReg_100.Message);}}}
}

要求很簡單就是要一個 界面帶按鈕可以修改 模擬TcpServer(PLC);內指定寄存器的數值 讀取指定數值即可.

但是那天出門只帶了一個平板筆記本,且沒轉VS雖然有程序但無法編譯,所以python登場.

.雖然python有modbus庫?minimalmodbus?pymodbus ;等但是沒有hsl好用 因為之前用hsl ;

直接用pythonnet在python里面調用 .net 版的hsl,實際python也有hsl但是需要授權,C# 版7.001以及以下版本是免費的,對于干這件事情是綽綽有余的,這里對hsl作者表示感謝;;;

于是就有了如下 產物: 有界面 有按鈕 有結果顯示 有數字顯示 可以模擬 PLC的程序 且一共200行;

當然必須安裝pythonnet ,且依賴的外部 .net? dll文件要和.py程序在一個目錄?

import os,sys,time
import tkinter as tk
from tkinter import messagebox#import win32api,win32con,win32guifrom ctypes import *
#需要安裝 pywin32
def cmd(s="pause"):os.system(s)
def p(s):print(s);return s
win = tk.Tk()
win.title("(匯川Easy521): PLC模擬器")
win.geometry('960x280')
win.config(background ="#00aa00")
winscrwidth=win.winfo_screenwidth()# 基礎庫
import os,sys,time
from ctypes import *
def cmd(s="pause"):os.system(s)
#C語言那一套 拿過來 C#那一套數據類型拿過來
import clr,System
from System import String, Char, Int32,UInt16, Int64, Environment, IntPtr#導包
print(clr.AddReference("HslCommunication"))
#現在可以當python自己的庫來用了
import HslCommunicationmodbusTcpServer  = HslCommunication.ModBus.ModbusTcpServer();
modbusTcpServer.ServerStart(502);#必須指定泛型 否則無效 UInt16(65535)
#初始化寄存器 指定3區 設定初始值
modbusTcpServer.Write("x=3;100", UInt16(0));# 觸發 1 2 3 4對應4流道
modbusTcpServer.Write("x=3;101", UInt16(0));# 料號 0 1 2
modbusTcpServer.Write("x=3;105", UInt16(0));# 結果 11(OK) 12(NG) 13(ERROR)
modbusTcpServer.Write("x=3;106", UInt16(0));# 心跳0/1# 獲取時間的函數
def gettime():# 獲取當前時間dstr.set(f"""{time.strftime("%H:%M:%S")}  >>127.0.0.1:502""")try: #必須try 否則要在界面控件創建完成后銷毀前調用 圖省事try完事intReg_100 = modbusTcpServer.ReadUInt16("100");#返回的是 Oper類型 不是int數值 intReg_101 = modbusTcpServer.ReadUInt16("101");intReg_105 = modbusTcpServer.ReadUInt16("105");intReg_106 = modbusTcpServer.ReadUInt16("106");entry1.delete(0, "end");entry1.insert(0,f'{intReg_100.Content}')#entry2.delete(0, "end");entry2.insert(0,f'{intReg_101.Content}')#entry3.delete(0, "end");entry3.insert(0,f'{intReg_105.Content}')#entry4.delete(0, "end");entry4.insert(0,f'{intReg_106.Content}')#    Reg=intReg_105.Contentif(Reg==0):rrr.config(text='None'); rrr.config(bg='#00aa00')if(Reg==11):rrr.config(text='ok');   rrr.config(bg='#00ff00')if(Reg==12):rrr.config(text='ng');   rrr.config(bg='#ff0000')if(Reg==13):rrr.config(text='Error');rrr.config(bg='#ffff00')##except:pass# 每隔 1s 調用一次 gettime()函數來獲取時間win.after(200, gettime)
# 生成動態字符串
dstr = tk.StringVar()
# 利用 textvariable 來實現文本變化
lb = tk.Label(win,textvariable=dstr,fg='green',font=("微軟雅黑",18))
lb.pack()
gettime()# 調用生成時間的函數tk.Label(win,text='觸發(D100[1]):',fg='black',font=("微軟雅黑",15)).place (x=0,y=40, width=150, height=30)
entry1 = tk.Entry(win)# 創建輸入框控件
entry1.place (x=300,y=40, width=60, height=30)#relx=0.01,relheight=0.4
#.pack(padx=20, pady=20)# 放置輸入框,并設置位置
entry1.delete(0, "end")
entry1.insert(0,'0')# 插入默認文本
print(entry1.get())# 得到輸入框字符串
# entry1.delete(0, tk.END)# 刪除所有字符#-----------------------------------------------------------------------------
def button_click_100():#按鈕modbusTcpServer.Write("x=3;105", UInt16(0));#結果清零modbusTcpServer.Write("x=3;100", UInt16(1));pass
button_100 = tk.Button(win,text="觸發寫1",command=button_click_100)
button_100.place (x=380,y=40, width=60, height=30)def button_click_100_2():modbusTcpServer.Write("x=3;105", UInt16(0));#結果清零modbusTcpServer.Write("x=3;100", UInt16(2));pass
button_100 = tk.Button(win,text="觸發寫2",command=button_click_100_2)
button_100.place (x=380+80,y=40, width=60, height=30)def button_click_100_3():modbusTcpServer.Write("x=3;105", UInt16(0));#結果清零modbusTcpServer.Write("x=3;100", UInt16(3));pass
button_100 = tk.Button(win,text="觸發寫3",command=button_click_100_3)
button_100.place (x=380+80+80,y=40, width=60, height=30)def button_click_100_4():modbusTcpServer.Write("x=3;105", UInt16(0));#結果清零modbusTcpServer.Write("x=3;100", UInt16(4));pass
button_100 = tk.Button(win,text="觸發寫4",command=button_click_100_4)
button_100.place (x=380+80+80+80,y=40, width=60, height=30)def button_click_101():#按鈕 觸發寫0modbusTcpServer.Write("x=3;100", UInt16(0));pass
button_100 = tk.Button(win,text="觸發寫0",command=button_click_101)
button_100.place (x=380+80+80+80+80,y=40, width=60, height=30)def button_click_102():#按鈕 觸發寫0modbusTcpServer.Write("x=3;105", UInt16(0));#結果清零modbusTcpServer.Write("x=3;100", UInt16(1));time.sleep(0.2)modbusTcpServer.Write("x=3;100", UInt16(0));pass
button_100 = tk.Button(win,text="觸發寫1(延時200)寫0",command=button_click_102)
button_100.place (x=380+80+80+80+80+80,y=40, width=160, height=30)
#-----------------------------------------------------------------------------
#-----------------------------------------------------------------------------
def button_click_200():#按鈕modbusTcpServer.Write("x=3;101", UInt16(0));pass
button_100 = tk.Button(win,text="料號寫0",command=button_click_200)
button_100.place (x=380,y=40+40, width=60, height=30)def button_click_201():#按鈕 觸發寫0modbusTcpServer.Write("x=3;101", UInt16(1));pass
button_100 = tk.Button(win,text="料號寫1",command=button_click_201)
button_100.place (x=380+80,y=40+40, width=60, height=30)def button_click_202():#按鈕 觸發寫0modbusTcpServer.Write("x=3;101", UInt16(2));pass
button_100 = tk.Button(win,text="料號寫2",command=button_click_202)
button_100.place (x=380+80+80,y=40+40, width=160, height=30)
#-----------------------------------------------------------------------------tk.Label(win,text='料號(D101[0/1/2]):',fg='black',font=("微軟雅黑",15)).place (x=0,y=40+40, width=180, height=30)
entry2 = tk.Entry(win)# 創建輸入框控件
entry2.place (x=300,y=40+40, width=60, height=30)#relx=0.01,relheight=0.4
#.pack(padx=20, pady=20)# 放置輸入框,并設置位置
entry2.delete(0, "end")# 插入默認文本
entry2.insert(0,'0')
print(entry2.get())# 得到輸入框字符串
# entry1.delete(0, tk.END)# 刪除所有字符
#relx、rely relheight、relwidth anchor=NEtk.Label(win,text='結果:(D105[11(OK)/12(NG)]):',fg='black',font=("微軟雅黑",15)).place (x=0,y=40+40+40, width=280, height=30)entry3 = tk.Entry(win)# 創建輸入框控件
entry3.place (x=300,y=40+40+40, width=60, height=30)#relx=0.01,relheight=0.4
#.pack(padx=20, pady=20)# 放置輸入框,并設置位置
entry3.delete(0, "end")# 插入默認文本
entry3.insert(0,'0')
print(entry3.get())# 得到輸入框字符串rrr=tk.Label(win,text='ok',fg='black',font=("微軟雅黑",15))
rrr.place (x=400,y=40+40+40, width=150, height=30)
#rrr.config(text='ok');rrr.config(bg='#00ff00')
#rrr.config(text='ng');rrr.config(bg='#ff0000')
rrr.config(text='None');rrr.config(bg='#00aa00')tk.Label(win,text='心跳:(D106[0/1]):',fg='black',font=("微軟雅黑",15)).place (x=0,y=40+40+40+40, width=180, height=30)entry4 = tk.Entry(win)# 創建輸入框控件
entry4.place (x=300,y=40+40+40+40, width=60, height=30)#relx=0.01,relheight=0.4
#.pack(padx=20, pady=20)# 放置輸入框,并設置位置
entry4.delete(0, "end")# 插入默認文本
entry4.insert(0,'0')
print(entry4.get())# 得到輸入框字符串def QueryWindow():if messagebox.showwarning("窗口關閉?"):win.destroy()
win.protocol('WM_DELETE_WINDOW', QueryWindow)
win.mainloop()

這樣VM 寫電腦IP 或者 127.0.0.1:502 就可以把這個程序當成PLC連接了.

在手上沒有PLC的情況下很方便使用.

接下來分享一下其他用法:

比如監視PLC值:(為了方便不寫界面): 這樣就可以實時觀察到PLC的值

import os,sys,time,win32api,win32con,win32gui
def cmd(s="pause"):os.system(s)
from ctypes import *
import clr,System#C語言那一套 拿過來 C#那一套數據類型拿過來
from System import String, Char, Int32,UInt16, Int64, Environment, IntPtr
print(clr.AddReference("HslCommunication"))#導包
import HslCommunication#現在可以當python自己的庫來用了
modbus = HslCommunication.ModBus.ModbusTcpNet( "192.168.1.10" );#modbus = HslCommunication.ModBus.ModbusTcpNet( "127.0.0.1" );
while 1:cmd("cls")time.sleep(0.5)for i in range(15):time.sleep(0.3)intReg_100 = modbus.ReadUInt16("100");Reg_100 = intReg_100.Content;intReg_101 = modbus.ReadUInt16("101");Reg_101 = intReg_101.Content;intReg_105 = modbus.ReadUInt16("105");Reg_105 = intReg_105.Content;intReg_106 = modbus.ReadUInt16("106"); Reg_106 = intReg_106.Content;print(f"""{time.strftime("%H:%M:%S")}   \n\nD100:{Reg_100}  D101:{Reg_100}  D105:{Reg_100}  D106:{Reg_100}   \n""")#intReg_100.IsSuccess,intReg_100.Content, #     intReg_101.IsSuccess,intReg_101.Content,#     intReg_105.IsSuccess,intReg_105.Content,#     intReg_106.IsSuccess,intReg_106.Content)>#pip install pywin32 numpy pythonnet -i https://pypi.tuna.tsinghua.edu.cn/simple

下來在分享一個socket的腳本 用來調試VM很方便.


def p(P):print(P);
import os,sys,time,socket,_thread,threading關閉時間=60*2
from threading import Timer
def close_window():print("cl")os._exit(0)#root.destroy()  # 銷毀主窗口#print("窗口已關閉")
Timer(關閉時間, close_window).start()#def thread_it(func, *args):t = threading.Thread(target=func, args=args)t.setDaemon(True);t.start();
def Thread_ConnectSocket(ip="",prot=0,sendData="",recv_flag=True):是否發送成功標志=Falsewhile True:try:global tcp_client_sockettcp_client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)tcp_client_socket.connect((ip, prot))while True:try:tcp_client_socket.send(sendData.encode("utf-8"))#發送print(f'>>{ip}:({prot})"{sendData}"!')if (recv_flag):#print(f'等待對方回復!')recv_content = tcp_client_socket.recv(1024)#接收result = recv_content.decode("utf-8")print(f'收到對方發來的"{result}"!')   print(f'done!')是否發送成功標志=Truebreakexcept:是否發送成功標志=Falsebreakexcept socket.error:print("未連接,嘗試重連中..")time .sleep(1)if (是否發送成功標志):print(f'finish!')breakipport=("127.0.0.1", 7930)#右側IP=ipport[0]
PROT=ipport[1] #IP,PROT def Tcp_Send(S=""):#B_左(7931)thread_it(Thread_ConnectSocket,IP,PROT,S)import tkinter as tkroot = tk.Tk()#root.iconbitmap('mfc.ico')
root.geometry('400x400+100+100')
#root.resizable(0,0)
root.title("")
lb__a = tk.Label(root,text=f"(7931) :{IP} : {PROT}",fg='green',font=("微軟雅黑",16))
lb__a.pack()def gettime():dstr.set(time.strftime("%H:%M:%S"))try:passroot.after(1000, gettime)# 每隔 1s 調用一次.except:passdstr = tk.StringVar()# 定義動態字符串
lb = tk.Label(root,textvariable=dstr,fg='green',font=("微軟雅黑",20))
lb.pack()
gettime()# 0 800V 一體軛
# 1 800V 中柱
# 2 800V 邊柱
##------------------------------料號0---------------------------------------------------------
#---------------------------------------------------------------------------------------------
def Cam0():Tcp_Send("0") 
button = tk.Button(root,text=' 料號0:800V 一體軛',bg='#7CCD7C',width=20, height=2,command=Cam0)
button.place(relx=0.15,rely=0.2, width=260, height=30)#------------------------------料號1---------------------------------------------------------
#---------------------------------------------------------------------------------------------def Cam1():Tcp_Send("1")#Tcp_SendB Tcp_SendA #B_左(7931)  A_右(7930) 
button = tk.Button(root,text='料號1:800V 中柱',bg='#7CCD7C',width=20, height=2,command=Cam1)
#button.pack()
button.place(relx=0.15,rely=0.3, width=260, height=30)#------------------------------料號2---------------------------------------------------------
#---------------------------------------------------------------------------------------------def Cam2():Tcp_Send("2")#Tcp_SendB Tcp_SendA #B_左(7931)  A_右(7930) 
button = tk.Button(root,text='料號2:800V 邊柱',bg='#7CCD7C',width=20, height=2,command=Cam2)
#button.pack()
button.place(relx=0.15,rely=0.4, width=260, height=30)#------------------------------料號:    噢噢噢噢---------------------------------------------------------
#---------------------------------------------------------------------------------------------def CamT1():Tcp_Send("T1")
button = tk.Button(root,text='拍照1',bg='#7CCD7C',width=20, height=2,command=CamT1)
button.place(relx=0.15,rely=0.5, width=260, height=30)def CamT2():Tcp_Send("T2")
button = tk.Button(root,text='拍照2',bg='#7CCD7C',width=20, height=2,command=CamT2)
button.place(relx=0.15,rely=0.6, width=260, height=30)def CamT3():Tcp_Send("T3")
button = tk.Button(root,text='拍照3',bg='#7CCD7C',width=20, height=2,command=CamT3)
button.place(relx=0.15,rely=0.7, width=260, height=30)def CamT4():Tcp_Send("T4")
button = tk.Button(root,text='拍照4',bg='#7CCD7C',width=20, height=2,command=CamT4)
button.place(relx=0.15,rely=0.8, width=260, height=30)#---------------------------------------------------------------------------------------------
#------------------------------料號2---------------------------------------------------------
#---------------------------------------------------------------------------------------------root.mainloop()

雖然是工作用到的,但只是自己測試工具;放出來也不影響..

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/80244.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/80244.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/80244.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

docker構建鏡像并上傳dockerhub

docker構建鏡像并上傳dockerhub 前提條件&#xff1a;需要連接梯子 將梯子配置到虛擬機中&#xff08;確保主機能夠連接 hub.docker.com&#xff09; 使用ipconfig 查詢主機的 ip4地址虛擬機的連接模式改成橋接模式&#xff08;復制主機的地址網絡&#xff09;將ip4配置到虛擬…

python實現的音樂播放器

python實現的音樂播放器 音樂播放器,原來寫過一個簡陋的例子,可見 https://blog.csdn.net/cnds123/article/details/137874107 那個不能拖動播放進度條上的滑塊到新的位置播放。下面介紹的可以拖動播放進度條上的滑塊到新的位置播放。 簡單實用的音樂播放器 這個簡單實用的…

[網安工具] 端口信息收集工具 —— 御劍高速 TCP 全端口掃描工具 · 使用手冊

&#x1f31f;想了解其它網安工具&#xff1f;看看這個&#xff1a;[網安工具] 網絡安全工具管理 —— 工具倉庫 管理手冊 https://github.com/NepoloHebo/Yujian-high-speed-TCP-full-port-scannerhttps://github.com/NepoloHebo/Yujian-high-speed-TCP-full-port-scanner 0…

數字孿生賦能智慧城市:從概念到落地的深度實踐

在城市規模與復雜度持續攀升的當下&#xff0c;傳統管理模式已難以滿足現代城市精細化治理需求。數字孿生技術憑借構建虛擬城市鏡像、實現實時數據交互與智能決策的特性&#xff0c;成為智慧城市建設的核心引擎。本文將通過多個典型案例&#xff0c;深度解析數字孿生技術如何重…

DeFi開發系統軟件開發:技術架構與生態重構

DeFi開發系統軟件開發&#xff1a;技術架構與生態重構 ——2025年去中心化金融開發的范式革新與實踐指南 一、技術架構演進&#xff1a;從單一鏈到多鏈混合引擎 現代DeFi系統開發已從單一公鏈架構轉向“跨鏈互操作混合模式”&#xff0c;結合中心化效率與去中心化安全雙重優勢…

相同IP和端口的服務器ssh連接時出現異常

起因 把服務器上的一個虛擬機搞壞了&#xff0c;所以刪除重新創建了一個&#xff0c;端口號和IP與之前的虛擬機相同。 ssh usernameIP -p port 時報錯 WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY! Someone…

驗證es啟動成功

1. 查看命令行輸出信息 在啟動 Elasticsearch 時&#xff0c;命令行窗口會輸出一系列日志信息。若啟動成功&#xff0c;日志里通常會有類似下面的信息&#xff1a; plaintext [2025-05-06T13:20:00,000][INFO ][o.e.n.Node ] [node_name] started其中 [node_na…

CentOS網絡之network和NetworkManager深度解析

文章目錄 CentOS網絡之network和NetworkManager深度解析1. CentOS網絡服務發展歷史1.1 傳統network階段&#xff08;CentOS 5-6&#xff09;1.2 過渡期&#xff08;CentOS 7&#xff09;1.3 新時代&#xff08;CentOS 8&#xff09; 2. network和NetworkManager的核心區別3. ne…

Unity:父掛 Rigidbody2D、子掛 Collider2D 時觸發器不生效的問題分析

目錄 ?問題現象 &#x1f50d; 排查與定位 ?? Unity 觸發機制的核心要求 ? 為什么把 Collider2D 移到父物體后就能觸發&#xff1f; &#x1f4a1; 解決方案 在 Unity 2D 游戲開發中&#xff0c;很多人習慣用父物體掛載 Rigidbody2D&#xff0c;而將不同的身體部位&am…

Google AI版圖:解析AI Studio, Gemini, NotebookLM與GCP

1. 2C vs 2B: AI Studio: 主要是面向開發者&#xff0c;提供一個易用的界面來探索和構建基于Google模型的應用。雖然最終的應用可能服務于C端或B端&#xff0c;但AI Studio本身更多是一個開發者的工具平臺&#xff0c;可以看作是連接模型能力和各種應用的橋梁。它可以被個人開…

Oracle EBS AP發票被預付款核算創建會計科目時間超長

背景 由于客戶職能部門的水電、通信和物業等等費用統一管理或對接部門報銷費,在報銷費的時候,用戶把所有費用分攤到各個末級部門,形成AP發票行有上千行, 問題癥狀 1、用戶過賬時,請求創建會計科目一直執行20多個小時未完成,只能手工強行取消請求。 2、取消請求以后,從后…

MySQL中MVCC指什么?

簡要回答&#xff1a; MVCC&#xff08;multi version concurrency control&#xff09;即多版本并發控制&#xff0c;為了確保多線程下數據的安全&#xff0c;可以通過undo log和ReadView來實現不同的事務隔離級別。 對于已提交讀和可重復讀隔離級別的事務來說&#xff0c;M…

賽季7靶場 -- Checker --User flag

本系列僅說明靶場的攻擊思路&#xff0c;不會給出任何的詳細代碼執行步驟&#xff0c;因為個人覺得找到合適的工具以實現攻擊思路的能力也非常重要。root要逆向&#xff0c;沒做了&#xff0c;但是user flag也有借鑒意義&#xff0c;關于2FA的繞過我們有必要了解 1.首先Nmap掃描…

【RAG技術全景解讀】從原理到工業級應用實踐

目錄 &#x1f31f; 前言&#x1f3d7;? 技術背景與價值&#x1f6a8; 當前技術痛點&#x1f6e0;? 解決方案概述&#x1f465; 目標讀者說明 &#x1f50d; 一、技術原理剖析&#x1f4d0; 核心概念圖解&#x1f4a1; 核心作用講解?? 關鍵技術模塊說明?? 技術選型對比 &…

【嵌入式開發-RS-485】

嵌入式開發-RS-485 ■ RS-485 連接方式■ RS-485 半雙工通訊■ RS-485 的特點■ UART硬流控■ RS-4851. 全雙工、半雙工接線2. 拓撲結構3. RS-485收發器3.1 發送模式&#xff08;TX&#xff09;3.2 接收模式&#xff08;RX&#xff09; 4. RS-485數據鏈路5. RS-485常用電路6. C…

[硬件電路-18]:MCU - LPC1765FBD100是恩智浦(NXP)半導體推出的一款基于ARM Cortex-M3內核的高性能32位微控制器

LPC1765FBD100是恩智浦&#xff08;NXP&#xff09;半導體推出的一款基于ARM Cortex-M3內核的高性能32位微控制器&#xff0c;具備高集成度、低功耗、豐富的外設接口和強大的處理能力&#xff0c;適用于工業控制、消費電子、醫療設備、通信系統等嵌入式應用場景。 以下從核心特…

MyBatis(進階)(xml標簽)

本節?標 1. 學習MyBatis的動態SQL查詢 2. 掌握MyBatis在項?中的應?, 可以使?Spring MVC完成?些基礎的功能 1. 動態SQL&#xff08;XML&#xff09; 動態 SQL 是Mybatis的強?特性之?&#xff0c;能夠完成不同條件下不同的 sql 拼接 可以參考官??檔&#xff1a; M…

QT QList容器及行高亮

總結QList是一個泛型/模板鏈表&#xff0c;可以自己定義數據類型&#xff0c;ExtraSelection是一種“數據類型”

【Python】Python項目中的依賴與配置:requirements.txt、setup.py、pyproject.toml 詳解

在昨天的文章【Python】通過Editable Install模式詳解&#xff0c;解決Python開發總是import出錯的問題 中&#xff0c; 我們提到了Python項目的配置文件requirements.txt、setup.py、pyproject.toml。在昨天的解決方案中&#xff0c; 我們同時維護了這三個文件。 由同學就問&a…

詳細聊聊 Synchronized,以及鎖的升級過程

在Java中&#xff0c;synchronized關鍵字是用于實現線程同步的重要機制&#xff0c;它通過內置鎖&#xff08;Monitor&#xff09;確保多個線程對共享資源的安全訪問。 1. synchronized 的基本使用與實現原理 使用方式 修飾實例方法&#xff1a;鎖是當前對象實例。public syn…