python-串口助手(OV7670图传)

代码

主python文件

import serial
import serial.tools.list_ports
import time
import tkinter as tk
from tkinter import ttk
import numpy as np
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib.figure import Figure
import threading
from queue import Queue
from PIL import Image, ImageTk
import tkinter as tk
import LightSwitch
import tkinter as tk
from datetime import datetime
import cv2 as cv
import cv2
import numpy as np
import os
'''
智能红绿灯上位机和MCU通信协议:
MCU->上位机 0x01 0xfe ...(320*240*2)BYTE...0xfe 0x01
上位机->MCU 0x02 0xff 0xXX 0xXX 0xXX 0xXX 0xff 0x02
字节2:高5bit传输当前系统时间0h-23h;低3bit传输时间增减标志位(0非深夜和高峰模式 1高峰模式  2深夜模式)
字节3:按钮值(0无按键 1按键+   2按键-   3按键切换灯)
字节4:0空闲(识别关闭);如果无按键和深夜或者高峰模式(判断标志位),当接收到图像数据后进行识别,否则接收到的图像数据丢弃,若图片中方形白色>20个,高4bit发送绿灯增加5s标志位1;当白色方块0<白色方块数<20,正常计时标志2(也为默认开启值);当白色方形==0,发送下次红灯长红标志位3。
字节5:识别到的车辆数量
'''
# 初始化窗口和控件
window = tk.Tk()
window.title('智能红绿灯串口助手')
window.geometry('900x600+200+100')
serialName = []#串口名称
ser = serial.Serial()  # 串口实例对象def opencom(*args):if not ser.is_open:ser.open()setbaudrate()setPort()setstop()setShujv()setcheck()if ser.is_open:print(f"串口已打开")light.turn_on()def closecom(*args):if ser.is_open:ser.close()if not ser.is_open:print(f"串口已关闭")light.turn_off()def clearreceive(*args):t0.delete(1.0, 'end')def send(*args):passdef hex_string_to_byte_list(hex_str):if len(hex_str) % 2 != 0:raise ValueError("Hex string length must be even.")return [int(hex_str[i:i+2], 16) for i in range(0, len(hex_str), 2)]Str_Get_List = []#存储接收到的Hex字符串转成的十六进制字节列表
Get_Picture_List = [] #存储图像数据
PackHead = [1,254]
PackEnd = [254,1]
PackHeadGetFlag = False
PackGetFlag = False
Picture_ByteLen = 320*240*2+4
lock = threading.Lock()# 创建一个线程锁
rgb_array = []#存储RGB888转换的数组数据,用于保存图片
SendData = [0x02,0xff,0x00,0x00,0x00,0x00,0xff,0x02]#存储发送数据包
IdentificationCount = 0 #图像识别数量
def showdata(*args):global Str_GetStringglobal Str_Get_Listglobal PackHeadGetFlagglobal PackGetFlagwhile not stop_event.is_set():if ser.is_open:try:try:with lock:  # 使用锁确保线程安全s = ser.read_all()  # 获取字节对象if s:sHex = s.hex()  # 获取Hex字符串 ,2个字符表示一个十六进制1字节t0.delete("1.0", tk.END)t0.insert('end', sHex)t0.see('end')  # 自动滚动到最新接收到的数据# Str_Get_List = Str_Get_List.append(hex_string_to_byte_list(sHex))# print(sHex,len(Str_Get))#获取数据列表sHexList = hex_string_to_byte_list(sHex)for i in sHexList:Str_Get_List.append(i)#处理数据和发送相关数据包if Hour_CarFlag ==0:pictureDataDispose()else:print("特殊模式,摄像头不启用")#情况接收到的数据Str_Get_List = []except Exception as e:print(f"Unexpected error: {e}")except serial.SerialException as e:print(f"Error reading from serial port: {e}")except Exception as e:print(f"Unexpected error: {e}")else:passdef pictureDataDispose(*args):global PackHeadGetFlagglobal Get_Picture_Listglobal Picture_ByteLenglobal PackHeadglobal Str_Get_Listglobal rgb_array#print(Str_Get_List)if not PackHeadGetFlag:#未接收到包头index_Str_Get_List = find_sublist(Str_Get_List,PackHead)if index_Str_Get_List!=-1:Get_Picture_List = Str_Get_List[index_Str_Get_List:]PackHeadGetFlag = Trueprint(f"Element {PackHead} found at index {index_Str_Get_List}")else:print(f"Element {PackHead} not found")else:Get_Picture_List.extend(Str_Get_List)#添加所有元素到尾部if len(Get_Picture_List) >= Picture_ByteLen:Get_Picture_List_PackEnd = Get_Picture_List[Picture_ByteLen-2:Picture_ByteLen]index_PackEnd = find_sublist(Get_Picture_List_PackEnd,PackEnd)if index_PackEnd==0:print("接收到一帧图片数据",print(len(Get_Picture_List)))PictureData = Get_Picture_List[2:Picture_ByteLen-2]# 转换图像数据rgb565_values = [(PictureData[i] << 8 | PictureData[i + 1]) for i in range(0, len(PictureData), 2)]rgb888_values = [rgb565_to_rgb888(val) for val in rgb565_values]#print(rgb888_values, len(rgb888_values), len(rgb565_values))update_image(rgb888_values)# 将RGB数据转换为numpy数组,并调整其形状以匹配图像尺寸和通道数(高度, 宽度, 通道)rgb_array = np.array(rgb888_values).reshape((240, 320, 3))#print(rgb_array)SavePicture(rgb_array)PictureIdentification()#---------------------处理第二帧图片包头Get_Picture_List = []PackHeadGetFlag = Falseelse:Get_Picture_List = []PackHeadGetFlag = Falsedef PictureIdentification(*args):global IdentificationCountimg = cv.imread('./image/2.jpg')# cv_show('img', img)#print(img)HSV = cv.cvtColor(img, cv.COLOR_BGR2HSV)  # 转换图像lowerColor = np.array([0, 0, 200])  # 设置最低阈值  np.array([Hmin, Smin, Vmin])upperColor = np.array([180, 20, 255])  # 设置最高阈值# 因为要保留的就是白色区域,因此根据白色阈值填入,提取白色部分(指定区域变白,其他变黑)binary = cv.inRange(HSV, lowerColor, upperColor)#print(binary)# 运用中值滤波去除噪声median = cv.medianBlur(binary, 9)# 显示二值图#cv_show('median', median)  # 这里是我自己写的cv_show()函数,函数声明可放开头contours, hierachy = cv.findContours(median, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_NONE)# 后两个为轮廓检索模式和轮廓逼近模式res = cv.drawContours(img, contours, -1, (0, 0, 255), 4)#cv_show('res', res)# 4、原图白色中心点L = len(contours)  # contours轮廓数据是数组,因此用len()测数组长度,为了循环画点使用IdentificationCount = L#识别白色块的数量for i in range(L):cnt = contours[i]  # cnt表示第i个白色快的轮廓信息(x, y), radius = cv.minEnclosingCircle(cnt)  # 得到白色块外接圆的圆心坐标和半径center = (int(x), int(y))  # 画center圆心时。x,y必须是整数# 标出中心点img2 = cv.circle(img, center, 3, (0, 0, 255), 5)  # 传入圆心信息,并画在原图上print(center)  # 输出各个中心点# 显示有中心点的图像#cv_show("frame", img2)  # 展示花了中心点的魔方图# 写一个显示函数
def cv_show(name, img):cv.imshow(name, img)cv.waitKey(0)cv.destroyAllWindows()def SavePicture(*args):global rgb_array# 检查并创建保存图像的目录(如果不存在)output_dir = './image'os.makedirs(output_dir, exist_ok=True)# 图像保存路径output_path = os.path.join(output_dir, '2.jpg')# 使用OpenCV将RGB图像保存为JPEG格式cv2.imwrite(output_path, rgb_array[:, :, ::-1])  # 注意这里对颜色通道进行了转换(BGR到RGB)print(f"Image saved successfully at {output_path}")# def dispose_LastData(*args):
#     global PackHeadGetFlag
#     global Get_Picture_List
#     global Picture_ByteLen
#     global PackHead
#
#     if len(Get_Picture_List[Picture_ByteLen:]) >= 2:
#         Get_Picture_List_last = Get_Picture_List[Picture_ByteLen:]  # 保留剩下的数据
#         index_Str_Get_List = find_sublist(Get_Picture_List_last, PackHead)  # 判断剩下的数据
#         if index_Str_Get_List != -1:
#             Get_Picture_List = Get_Picture_List_last[index_Str_Get_List:]
#             print(f"Element {PackHead} found at index {index_Str_Get_List}")
#         else:
#             print(f"Element {PackHead} not found")
#             Get_Picture_List = []
#             PackHeadGetFlag = False
#             print(f"剩余非图片数据")
#     else :
#         Get_Picture_List = []
#         PackHeadGetFlag = Falsedef update_image(rgb888_data):"""更新Canvas显示图像"""image = Image.new('RGB', (320, 240))image.putdata(rgb888_data)tk_image = ImageTk.PhotoImage(image)# 保持图像引用if hasattr(canvas, 'image'):canvas.image = tk_imageelse:canvas.image = tk_imagecanvas.create_image(0, 0, anchor="nw", image=tk_image)print("图像已更新")def rgb565_to_rgb888(rgb565):"""将单个RGB565值转换为RGB888元组"""# 提取红色部分 (5位),并将其从5位扩展到8位r = (rgb565 & 0xF800) >> 11r = int(r * 255 / 31)# 提取绿色部分 (6位),并将其从6位扩展到8位g = (rgb565 & 0x07E0) >> 5g = int(g * 255 / 63)# 提取蓝色部分 (5位),并将其从5位扩展到8位b = rgb565 & 0x001Fb = int(b * 255 / 31)return (r, g, b)# 设置串口参数
def setPort(*args):ser.port = comboxlist0.get()# 获取可用串口列表
port_list = list(serial.tools.list_ports.comports())
for port in port_list:serialName.append(port[0])def closethread(*args):while ser.is_open:ser.close()if not ser.is_open:breakwhile not ser.is_open:print(f"串口已关闭")stop_event.set()stop_event1.set()stop_event2.set()if stop_event.is_set() and stop_event1.is_set() and stop_event2.is_set():breakwhile stop_event2.is_set():print(f"时间线程等待stop_event2事件关闭")th2.join()if not th2.is_alive():breakwhile stop_event1.is_set():print(f"时间线程等待stop_event1事件关闭")th1.join()if not th1.is_alive():breakwhile stop_event.is_set():print(f"串口线程等待stop_event事件关闭")th0.join()window.quit()if not th0.is_alive():breakdef printfData(*args):if not ser.is_open:print("串口未打开")returnser.write(SendData)def find_sublist(main_list, sub_list):"""查找子列表在主列表中的位置"""len_main, len_sub = len(main_list), len(sub_list)if len_sub == 0 or len_main < len_sub:return -1for i in range(len_main - len_sub + 1):if main_list[i:i+len_sub] == sub_list:return ireturn -1# 设置串口参数
def setPort(*args):ser.port = comboxlist0.get()def setbaudrate(*args):while True:baudrate = int(comboxlist1.get())ser.baudrate = baudrateif ser.baudrate == baudrate:breakdef setShujv(*args):ser.bytesize = int(comboxlist2.get())check = {"N": serial.PARITY_NONE, "E": serial.PARITY_EVEN, "O": serial.PARITY_ODD}
def setcheck(*args):ser.parity = check[comboxlist3.get()]stop = {"1": serial.STOPBITS_ONE, "1.5": serial.STOPBITS_ONE_POINT_FIVE, "2": serial.STOPBITS_TWO}
def setstop(*args):ser.stopbits = stop[comboxlist4.get()]# 获取当前系统时间的小时并更新 Label
def get_current_hour():global current_hourglobal Hour_CarFlag# 获取当前时间now = datetime.now()# 提取小时(0-23)current_hour = now.hour# 更新 Label 的文本label6.config(text = f"{now}")label8.config(text=f"{IdentificationCount}")#当前时间对应模式和标志位判断'''current_hour其他时间 : 0 正常模式(使用摄像头功能)7-9 and 16-18 : 1 ,早晚高峰,绿灯增加10s22-23 and 0-3 : 2 ,深夜模式,红灯时间变为20s'''if (current_hour>=7 and current_hour<=9)or(current_hour>=16 and current_hour<=18):Hour_CarFlag = 1elif (current_hour>=22 and current_hour<=23)or(current_hour>=0 and current_hour<=3):Hour_CarFlag = 2else:Hour_CarFlag = 0current_hour = 0 #当前h
Hour_CarFlag = 0 #模式标志位 0正常模式(使用摄像头)  1早晚高峰模式  2深夜模式
#th1线程
def TimeShow(*args):while not stop_event1.is_set():get_current_hour()time.sleep(0.5)#th2线程
def SendDatathread(*args):global SendDataglobal current_hourglobal IdentificationCountwhile not stop_event2.is_set():time.sleep(1)#1s发送1次数据#修改发送的数据if Hour_CarFlag == 0:#正常模式if IdentificationCount==0:SendData[4] = 3 #下次红灯停止计数标志elif IdentificationCount >= 20:SendData[4] = 1 #车多,绿灯增加5s标志位,正常计时elif IdentificationCount > 0 and IdentificationCount < 20:SendData[4] = 2 #正常计时标志位elif Hour_CarFlag == 1:#高峰模式SendData[4] = 0 #摄像头失能  正常计时IdentificationCount = 0 #识别车辆数清零elif Hour_CarFlag == 2:#夜间模式SendData[4] = 0 #摄像头失能  正常计时IdentificationCount = 0 #识别车辆数清零SendData[2] = ((current_hour<<3)&0xff)+Hour_CarFlagSendData[3] = 0 #按键清空,方式按键事件重复SendData[5] = IdentificationCount #备用 当前采集车辆#发送if not ser.is_open:print("串口未打开")else:ser.write(SendData)print(SendData)#信号灯时间增点击事件
def LightTimeIncrease(*args):global SendData'''SendData[3]无按键:0当前灯时间增加:1  当前信号灯增加10s 最大99s当前灯时间减少:2  当前信号灯减少10s 最小5s切换灯:3  当前信号灯变为5s'''SendData[3] = 1  # 按键清空ser.write(SendData)SendData[3] = 0  # 按键清空#信号灯时间减点击事件
def LightTimeDecrease(*args):SendData[3] = 2  # 按键清空ser.write(SendData)SendData[3] = 0  # 按键清空#信号灯切换点击事件
def SwihchOver(*args):SendData[3] = 3  # 按键清空ser.write(SendData)SendData[3] = 0  # 按键清空# 创建文本控件和下拉列表控件
label0 = tk.Label(window, text='串口', font=10)
label0.place(y=40, x=50)
label1 = tk.Label(window, text='波特率', font=10)
label1.place(y=70, x=50)
label2 = tk.Label(window, text='数据位', font=10)
label2.place(y=100, x=50)
label3 = tk.Label(window, text='校验位', font=10)
label3.place(y=130, x=50)
label4 = tk.Label(window, text='停止位', font=10)
label4.place(y=160, x=50)
label5 = tk.Label(window, text='时间:', font=10)
label5.place(y=5, x=350)
label6 = tk.Label(window, text='XXXX', font=10)
label6.place(y=5, x=420)
label7 = tk.Label(window, text='车辆:', font=10)
label7.place(y=5, x=700)
label8 = tk.Label(window, text='XXXX', font=10)
label8.place(y=5, x=770)comvalue0 = tk.StringVar()
comboxlist0 = ttk.Combobox(window, textvariable=comvalue0)
comboxlist0["values"] = tuple(serialName)
comboxlist0.bind("<<ComboboxSelected>>", setPort)
comboxlist0.place(y=40, x=150)#波特率下拉框
comvalue1 = tk.StringVar()
comboxlist1 = ttk.Combobox(window, textvariable=comvalue1)
comboxlist1["values"] = (1200, 2400, 4800, 9600, 14400, 19200, 115200, 256000)
comboxlist1.current(7)
comboxlist1.bind("<<ComboboxSelected>>", setbaudrate)
comboxlist1.place(y=70, x=150)#数据位下拉框
comvalue2 = tk.StringVar()
comboxlist2 = ttk.Combobox(window, textvariable=comvalue2)
comboxlist2["values"] = ("8", "7", "6", "5")
comboxlist2.current(0)
comboxlist2.bind("<<ComboboxSelected>>", setShujv)
comboxlist2.place(y=100, x=150)#校验位下拉框
comvalue3 = tk.StringVar()
comboxlist3 = ttk.Combobox(window, textvariable=comvalue3)
comboxlist3["values"] = ("N", "E", "O")
comboxlist3.current(0)
comboxlist3.bind("<<ComboboxSelected>>", setcheck)
comboxlist3.place(y=130, x=150)#停止位下拉框
comvalue4 = tk.StringVar()
comboxlist4 = ttk.Combobox(window, textvariable=comvalue4)
comboxlist4["values"] = ("1", "1.5", "2")
comboxlist4.current(0)
comboxlist4.bind("<<ComboboxSelected>>", setstop)
comboxlist4.place(y=160, x=150)b4 = tk.Button(window, text='关闭线程', width=35, height=1, command=closethread)
b4.place(y=0, x=0)
b0 = tk.Button(window, text='打开串口', width=35, height=1, command=opencom)
b0.place(y=190, x=50)
light = LightSwitch.BooleanLight(window, size=35, x=10, y=190)#串口连接状态显示灯b1 = tk.Button(window, text='清除接收', width=35, height=1, command=clearreceive)
b1.place(y=250, x=50)
b2 = tk.Button(window, text='关闭串口', width=35, height=1, command=closecom)
b2.place(y=220, x=50)
e0 = tk.Entry(window, show=None, width=35)
e0.place(y=290, x=50)
b5 = tk.Button(window, text='Send', width=35, height=1, command=send)
b5.place(y=320, x=50)
t0 = tk.Text(window, width=65, height=3)
t0.place(y=50, x=350)
b6 = tk.Button(window, text='输出接收到的数据-测试按钮', width=35, height=1, command=printfData)
b6.place(y=350, x=50)
b6 = tk.Button(window, text='当前信号灯时间+', width=35, height=1, command=LightTimeIncrease)
b6.place(y=380, x=50)
b6 = tk.Button(window, text='当前信号灯时间-', width=35, height=1, command=LightTimeDecrease)
b6.place(y=410, x=50)
b6 = tk.Button(window, text='切换信号灯', width=35, height=1, command=SwihchOver)
b6.place(y=440, x=50)
label5 = tk.Label(window, text='Canvas', font=10)
label5.place(y=100, x=350)
# 图像参数
canvas = tk.Canvas(window,width=320, height=240,bg='#{:02x}{:02x}{:02x}'.format(*(255,255,255)),bd=1,highlightthickness=1,relief="groove")
canvas.place(x=420, y=125)if __name__ == '__main__':stop_event = threading.Event()  #等待线程th0停止事件stop_event1 = threading.Event()  # 等待线程th1停止事件stop_event2 = threading.Event()  # 等待线程th2停止事件th0 = threading.Thread(target=showdata)th0.start()th1 = threading.Thread(target=TimeShow)th1.start()th2 = threading.Thread(target=SendDatathread)th2.start()window.mainloop()

 从文件,同目录下LightSwitch.py

import tkinter as tk
class BooleanLight(tk.Canvas):def __init__(self, master=None, size=50, x=0, y=0):super().__init__(master, width=size, height=size)self.pack()self.place(x=x, y=y)self.size = sizeself.is_light_on = False  # 初始状态为关闭# 创建初始的圆形表示灯的状态self.light = self.create_oval(5, 5, size - 5, size - 5, fill="gray")def turn_on(self):"""打开灯"""self.itemconfig(self.light, fill="green")self.is_light_on = Truedef turn_off(self):"""关闭灯"""self.itemconfig(self.light, fill="gray")self.is_light_on = Falsedef toggle(self):"""切换灯的状态"""if self.is_light_on:self.turn_off()else:self.turn_on()

 完成功能

  1. tk、ttk基础的UI界面建立,并建立相关列表和按钮的电机事件方法。
  2. 选择串口参数,每次打开时自动获取串口端口列表,可以选择后在进行连接(显示连接成功)。
  3. 通过多线程,串口接收数据,十六进制字节对象字符串显示。按钮发送输入框内容(有函数但是目前没写,可以自己写,比较简单)。
  4. 建立3个线程(和三个线程关闭事件,防止线程异常不能正确结束导致的死循环),分别用来接收数据包、发送数据包、更新界面显示内容。
  5. 根据接收的数据包,在canvas进行图像显示(先将获取的RGB565数据转换为RGB888,数据进行保存成图片保存在文件夹中、然后从文件夹内读出,进行HSV处理,阈值化处理,边框圈出,计算白色内容数量)。
  6. 实时显示系统时间和接收数据包图像采集的车辆数量。
  7. 手动关闭线程,每次点击关闭线程来关闭应用,确保线程彻底关闭。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/30965.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

简单的二元语言模型bigram实现

内容总结归纳自视频&#xff1a;【珍藏】从头开始用代码构建GPT - 大神Andrej Karpathy 的“神经网络从Zero到Hero 系列”之七_哔哩哔哩_bilibili 项目&#xff1a;https://github.com/karpathy/ng-video-lecture Bigram模型是基于当前Token预测下一个Token的模型。例如&#x…

猫耳大型活动提效——组件低代码化

1. 引言 猫耳前端在开发活动的过程中&#xff0c;经历过传统的 pro code 阶段&#xff0c;即活动页面完全由前端开发编码实现&#xff0c;直到 2020 年接入公司内部的低代码活动平台&#xff0c;满足了大部分日常活动的需求&#xff0c;运营可自主配置活动并上线&#xff0c;释…

数据库基础以及基本建库建表的简单操作

文章目录 一、数据库是啥1.1、数据库的概念1.1、关系型数据库、非关系型数据库1.1、数据库服务器&#xff0c;数据库与表之间的关系 二、为啥要使用数据库2.1&#xff1a;传统数据文件存储2.2&#xff1a;数据库存储数据2.3、结论 三、使用数据库了会咋样四、应该咋用数据库&am…

常用无功功率算法的C语言实现(二)

0 前言 尽管数字延迟法和积分移相法在不间断采样的无功功率计算中得到了广泛应用,但它们仍存在一些固有缺陷。 对于数字延迟法而言,其需要额外存储至少1/4周期的采样点,在高采样频率的场景下,这对存储资源的需求不可忽视。而积分移相法虽然避免了额外的存储开销,但为了抑制…

【Linux】初识线程

目录 一、什么是线程&#xff1a; 重定义线程和进程&#xff1a; 执行流&#xff1a; Linux中线程的实现方案&#xff1a; 二、再谈进程地址空间 三、小结&#xff1a; 1、概念&#xff1a; 2、进程与线程的关系&#xff1a; 3、线程优点&#xff1a; 4、线程…

【单片机】ARM 处理器简介

ARM 公司简介 ARM&#xff08;Advanced RISC Machine&#xff09; 是英国 ARM 公司&#xff08;原 Acorn RISC Machine&#xff09; 开发的一种精简指令集&#xff08;RISC&#xff09; 处理器架构。ARM 处理器因其低功耗、高性能、广泛适用性&#xff0c;成为嵌入式系统、移动…

​​《从事件冒泡到处理:前端事件系统的“隐形逻辑”》

“那天在document见到你的第一眼&#xff0c;我就下定决心要陪你到天荒地老” ---React 我将从事件从出现到被处理的各个过程来介绍事件机制&#xff1a; 这张图片给我们展示了react事件的各个阶段&#xff0c;我们可以看到有DOM&#xff0c;合成事件层&#xff0c;还有…

Django小白级开发入门

1、Django概述 Django是一个开放源代码的Web应用框架&#xff0c;由Python写成。采用了MTV的框架模式&#xff0c;即模型M&#xff0c;视图V和模版T。 Django 框架的核心组件有&#xff1a; 用于创建模型的对象关系映射为最终用户设计较好的管理界面URL 设计设计者友好的模板…

课程《Deep Learning Specialization》

在coursera上&#xff0c;Deep Learning Specialization 课程内容如下图所示&#xff1a;

Java【网络原理】(3)网络编程续

目录 1.前言 2.正文 2.1ServerSocket类 2.2Socket类 2.3Tcp回显服务器 2.3.1TcpEchoServer 2.3.2TcpEchoClient 3.小结 1.前言 哈喽大家好&#xff0c;今天继续进行计算机网络的初阶学习&#xff0c;今天学习的是tcp回显服务器的实现&#xff0c;正文开始 2.正文 在…

安装remixd,在VScode创建hardhat

在终端&#xff0c;以管理员身份&#xff0c;cmd 需要科学上网 npm install -g remix-project/remixd 在vscode插件中&#xff0c;安装solidity插件&#xff0c;是暗灰色那款 1.将nodeJs的版本升级至18以上 2.在vscode打开一个新的文件&#xff0c;在终端输入 npx hardhat 3.…

微服务拆分-远程调用

我们在查询购物车列表的时候&#xff0c;它有一个需求&#xff0c;就是不仅仅要查出购物车当中的这些商品信息&#xff0c;同时还要去查到购物车当中这些商品的最新的价格和状态信息&#xff0c;跟购物车当中的快照进行一个对比&#xff0c;从而去提醒用户。 现在我们已经做了服…

TCP/IP 5层协议簇:网络层(ICMP协议)

1. TCP/IP 5层协议簇 如下&#xff1a; 和ip协议有关的才有ip头 2. ICMP 协议 ICMP协议没有端口号&#xff0c;因为不去上层&#xff0c;上层协议采用端口号

Uniapp 页面返回不刷新?两种方法防止 onShow 触发多次请求!

目录 前言1. 变量&#xff08;不生效&#xff09;2. 延迟&#xff08;生效&#xff09; 前言 &#x1f91f; 找工作&#xff0c;来万码优才&#xff1a;&#x1f449; #小程序://万码优才/r6rqmzDaXpYkJZF 在 Uniapp 中&#xff0c;使用 onShow() 钩子来监听页面显示&#xff0…

java_了解反射机制

目录 1. 定义 2. 用途 3. 反射基本信息 4. 反射相关的类 4.1 class类&#xff08;反射机制的起源&#xff09; 4.1.1 Class类中的相关方法&#xff08;方法的具体使用在后面的示例中&#xff09; 4.2 反射的示例 4.2.1 获得Class对象的三种方式 4.2.2 反射的使用 Fiel…

基于Python的商品销量的数据分析及推荐系统

一、研究背景及意义 1.1 研究背景 随着电子商务的快速发展&#xff0c;商品销售数据呈现爆炸式增长。这些数据中蕴含着消费者行为、市场趋势、商品关联等有价值的信息。然而&#xff0c;传统的数据分析方法难以处理海量、多源的销售数据&#xff0c;无法满足现代电商的需求。…

P8662 [蓝桥杯 2018 省 AB] 全球变暖--DFS

P8662 [蓝桥杯 2018 省 AB] 全球变暖--dfs 题目 解析讲下DFS代码 题目 解析 这道题的思路就是遍历所有岛屿&#xff0c;判断每一块陆地是否会沉没。对于这种图的遍历&#xff0c;我们首先应该想到DFS。 代码的注意思想就是&#xff0c;在主函数中遍历找出所有岛屿&#xff0c…

tiktok web登录 分析

声明: 本文章中所有内容仅供学习交流使用&#xff0c;不用于其他任何目的&#xff0c;抓包内容、敏感网址、数据接口等均已做脱敏处理&#xff0c;严禁用于商业用途和非法用途&#xff0c;否则由此产生的一切后果均与作者无关&#xff01; 逆向分析 部分代码 response reques…

邮件发送器:使用 Python 构建带 GUI 的邮件自动发送工具

在本篇博客中&#xff0c;我们将深入解析一个使用 wxPython 构建的邮件发送器 GUI 程序。这个工具能够自动查找指定目录中的文件作为附件&#xff0c;并提供邮件发送功能。本文将从功能、代码结构、关键技术等方面进行详细分析。 C:\pythoncode\new\ATemplateFromWeekReportByM…

pyside6学习专栏(十一):在PySide6中实现一简易的画板程序

pyside6学习专栏(十一):在PySide6中实现一简易的画板程序&#xff0c;实现画直线、矩形、填充矩形、圆、椭圆、随手画、文本。为减少代码量&#xff0c;所画形状的颜色、线宽、线型、填充形状、字体、字号等采用随机方式&#xff0c;只作为学习在Python中绘画的基本操作。 主界…