【自用】終端設備(ESP32-S3)連接云服務器 HomeAssistant + MQTT 物聯網平臺

總覽

1.流程概述
2.開始搭建!
3.

一、流程概述

0.總體流程

二、開始搭建

1.下載 MQTTX 客戶端( 在PC上 )

https://mqttx.app/zh/downloads

在這里插入圖片描述

2.新建 MQTTX 連接

0.點擊左側的加號,開始新建連接。

在這里插入圖片描述

一共需要填寫幾個參數:

1.名稱:想起什么名稱都可以

在這里插入圖片描述

2.服務器地址:填入你的云服務器外網IP

在這里插入圖片描述

3.用戶名 和 密碼:填入你剛才登錄 EMQX 的 用戶名和密碼(就是默認用戶名是 admin 、默認密碼是 public 的那個)

在這里插入圖片描述

4.創建連接成功
在這里插入圖片描述

3.使用 MQTTX 向 HomeAssistant 添加 設備 (此設備) & 實體(此設備上的傳感器…可以很多個)

3.1 添加設備 和 實體
這個步驟需要注意的就是,topic 里面的內容應該是 unique_id 的值加上 /config。如果不明白,看我下面的 json代碼 和 圖片 來理解。照葫蘆畫瓢即可。


homeassistant/sensor/HA/HA-HYDC-A-60-01-currentTemp/config{"unique_id": "HA-HYDC-A-60-01-currentTemp","name": "currentTemp","icon": "mdi:thermometer","state_topic": "HA-HYDC-A-60-01/currentTemp/state","json_attributes_topic": "HA-HYDC-A-60-01/currentTemp/attributes","unit_of_measurement": "℃","device": {"identifiers": "HYDC-A-60-01","manufacturer": "遼寧鴻昱石油機械制造有限公司","model": "HA","name": "HYDC-A-60-01","sw_version": "1.0"}
}

在這里插入圖片描述

3.2 查看設備和實體
去 HomeAssistant 里面 配置 -> MQTT 就能看見設備和實體啦。(我這里已經添加了實體,并且實驗著賦值了,你不是這樣的界面很正常。照葫蘆畫瓢,自己去改參數的內容,這很重要)

在這里插入圖片描述

3.3 測試著使用 MQTTX 給設備的實體(設備上具體的傳感器) 賦值
像下面這段代碼,topic 是 HA-HYDC-A-60-01/currentTemp/state,指的就是你剛剛創建的設備上的實體 的 值。
我現在給它賦值34,就能在 HomeAssistant 里面看到這個值。


HA-HYDC-A-60-01/currentTemp/state35

在這里插入圖片描述
在這里插入圖片描述

3.4 給此設備 添加 第2、3、4…個實體的操作步驟
我們剛才在創建這個設備的時候,也創建了它的第一個實體,現在我們要創建第二個,請注意看下面的代碼和上面代碼的相同和不同之處。你會發現 他們的 “device” 詞條是一樣的,但是上面的內容改變了。剛才我們創建的傳感器叫“currentTemp”,而這次我們創建的傳感器叫“setTemp”。而且標題也改變了。

在發送下面這段代碼之后,會發現 HomeAssistant 里面出現了第二個傳感器,和剛才是一樣的,我們創建好第二個傳感器之后也可以通過剛才的方式給它賦值。


homeassistant/sensor/HA/HA-HYDC-A-60-01-setTemp/config{"unique_id": "HA-HYDC-A-60-01-setTemp","name": "setTemp","icon": "mdi:thermometer","state_topic": "HA-HYDC-A-60-01/setTemp/state","json_attributes_topic": "HA-HYDC-A-60-01/setTemp/attributes","unit_of_measurement": "℃","device": {"identifiers": "HYDC-A-60-01","manufacturer": "遼寧鴻昱石油機械制造有限公司","model": "HA","name": "HYDC-A-60-01","sw_version": "1.0"}
}

HA-HYDC-A-60-01/setTemp/state35

在這里插入圖片描述

4.在 ESP32S3 上寫入程序,連接 WIFI 并讓它連接到 云服務器 上的 MQTT 網絡服務

4.1 給 ESP32S3 寫入程序
給這段程序起個名字吧,隨便。我的是 MQTTX_WIFI.py
請注意,你需要更改這里面的幾個地方,我在下面代碼中句子的后面加上了 注釋“請修改:xxx”

import time
from machine import Pin
import network
from umqttsimple import MQTTClientdef do_wifi_connect():wifi_name = 'TP-LINK_FEEC'	# 請修改:改成你的 WIFI 名稱wifi_password = 'hbz12345'  # 請修改:改成你的 WIFI 密碼wlan = network.WLAN(network.STA_IF)wlan.active(True)if not wlan.isconnected():print('Connecting to WIFI...')print('WIFI name == ',wifi_name)print('WIFI password == ',wifi_password)wlan.connect(wifi_name, wifi_password)i = 1while not wlan.isconnected():print("Connecting for ",i,' seconds...')i += 1time.sleep(1)print('network config:', wlan.ifconfig())def sub_cb(topic, msg): # 回調函數,收到服務器消息后會調用這個函數print(topic, msg)# ---- 控制 指令 --------if topic.decode("utf-8") == "ledctl" and msg.decode("utf-8") == "on":led_pin.value(1)elif topic.decode("utf-8") == "ledctl" and msg.decode("utf-8") == "off":led_pin.value(0)# ---- 監控 指令 --------# 1. 聯網
do_wifi_connect()# 2. 創建mqt
YzyMqttClient = MQTTClient("YzyMqttClient", "182.93.213.218")  # 請修改:可以選擇將 YzyMqttClient 改成你想要的對象名,然后把 182.93.213.218 改成你的 云服務器外網 IP
YzyMqttClient.set_callback(sub_cb)  # 設置回調函數
YzyMqttClient.connect()  # 建立連接
YzyMqttClient.subscribe(b"ledctl")  # 監控ledctl這個通道,接收控制命令# ---- 添加 --------
# 3. 創建LED對應Pin對象
led_pin = Pin(1, Pin.OUT)
# ---- 添加 --------while True:i = 0YzyMqttClient.check_msg()time.sleep(0.5)YzyMqttClient.publish("hello","my name is esp32s3...",i)time.sleep(1)i += 1

4.2 導入依賴包 umqttsimple.py
自己創建一個 umqttsimple.py 文件,內容如下(不需要自己往里面加什么):

import usocket as socket
import ustruct as struct
from ubinascii import hexlifyclass MQTTException(Exception):passclass MQTTClient:def __init__(self,client_id,server,port=0,user=None,password=None,keepalive=0,ssl=False,ssl_params={},):if port == 0:port = 8883 if ssl else 1883self.client_id = client_idself.sock = Noneself.server = serverself.port = portself.ssl = sslself.ssl_params = ssl_paramsself.pid = 0self.cb = Noneself.user = userself.pswd = passwordself.keepalive = keepaliveself.lw_topic = Noneself.lw_msg = Noneself.lw_qos = 0self.lw_retain = Falsedef _send_str(self, s):self.sock.write(struct.pack("!H", len(s)))self.sock.write(s)def _recv_len(self):n = 0sh = 0while 1:b = self.sock.read(1)[0]n |= (b & 0x7F) << shif not b & 0x80:return nsh += 7def set_callback(self, f):self.cb = fdef set_last_will(self, topic, msg, retain=False, qos=0):assert 0 <= qos <= 2assert topicself.lw_topic = topicself.lw_msg = msgself.lw_qos = qosself.lw_retain = retaindef connect(self, clean_session=True):self.sock = socket.socket()addr = socket.getaddrinfo(self.server, self.port)[0][-1]self.sock.connect(addr)if self.ssl:import usslself.sock = ussl.wrap_socket(self.sock, **self.ssl_params)premsg = bytearray(b"\x10\0\0\0\0\0")msg = bytearray(b"\x04MQTT\x04\x02\0\0")sz = 10 + 2 + len(self.client_id)msg[6] = clean_session << 1if self.user is not None:sz += 2 + len(self.user) + 2 + len(self.pswd)msg[6] |= 0xC0if self.keepalive:assert self.keepalive < 65536msg[7] |= self.keepalive >> 8msg[8] |= self.keepalive & 0x00FFif self.lw_topic:sz += 2 + len(self.lw_topic) + 2 + len(self.lw_msg)msg[6] |= 0x4 | (self.lw_qos & 0x1) << 3 | (self.lw_qos & 0x2) << 3msg[6] |= self.lw_retain << 5i = 1while sz > 0x7F:premsg[i] = (sz & 0x7F) | 0x80sz >>= 7i += 1premsg[i] = szself.sock.write(premsg, i + 2)self.sock.write(msg)# print(hex(len(msg)), hexlify(msg, ":"))self._send_str(self.client_id)if self.lw_topic:self._send_str(self.lw_topic)self._send_str(self.lw_msg)if self.user is not None:self._send_str(self.user)self._send_str(self.pswd)resp = self.sock.read(4)assert resp[0] == 0x20 and resp[1] == 0x02if resp[3] != 0:raise MQTTException(resp[3])return resp[2] & 1def disconnect(self):self.sock.write(b"\xe0\0")self.sock.close()def ping(self):self.sock.write(b"\xc0\0")def publish(self, topic, msg, retain=False, qos=0):pkt = bytearray(b"\x30\0\0\0")pkt[0] |= qos << 1 | retainsz = 2 + len(topic) + len(msg)if qos > 0:sz += 2assert sz < 2097152i = 1while sz > 0x7F:pkt[i] = (sz & 0x7F) | 0x80sz >>= 7i += 1pkt[i] = sz# print(hex(len(pkt)), hexlify(pkt, ":"))self.sock.write(pkt, i + 1)self._send_str(topic)if qos > 0:self.pid += 1pid = self.pidstruct.pack_into("!H", pkt, 0, pid)self.sock.write(pkt, 2)self.sock.write(msg)if qos == 1:while 1:op = self.wait_msg()if op == 0x40:sz = self.sock.read(1)assert sz == b"\x02"rcv_pid = self.sock.read(2)rcv_pid = rcv_pid[0] << 8 | rcv_pid[1]if pid == rcv_pid:returnelif qos == 2:assert 0def subscribe(self, topic, qos=0):assert self.cb is not None, "Subscribe callback is not set"pkt = bytearray(b"\x82\0\0\0")self.pid += 1struct.pack_into("!BH", pkt, 1, 2 + 2 + len(topic) + 1, self.pid)# print(hex(len(pkt)), hexlify(pkt, ":"))self.sock.write(pkt)self._send_str(topic)self.sock.write(qos.to_bytes(1, "little"))while 1:op = self.wait_msg()if op == 0x90:resp = self.sock.read(4)# print(resp)assert resp[1] == pkt[2] and resp[2] == pkt[3]if resp[3] == 0x80:raise MQTTException(resp[3])return# Wait for a single incoming MQTT message and process it.# Subscribed messages are delivered to a callback previously# set by .set_callback() method. Other (internal) MQTT# messages processed internally.def wait_msg(self):res = self.sock.read(1)self.sock.setblocking(True)if res is None:return Noneif res == b"":raise OSError(-1)if res == b"\xd0":  # PINGRESPsz = self.sock.read(1)[0]assert sz == 0return Noneop = res[0]if op & 0xF0 != 0x30:return opsz = self._recv_len()topic_len = self.sock.read(2)topic_len = (topic_len[0] << 8) | topic_len[1]topic = self.sock.read(topic_len)sz -= topic_len + 2if op & 6:pid = self.sock.read(2)pid = pid[0] << 8 | pid[1]sz -= 2msg = self.sock.read(sz)self.cb(topic, msg)if op & 6 == 2:pkt = bytearray(b"\x40\x02\0\0")struct.pack_into("!H", pkt, 2, pid)self.sock.write(pkt)elif op & 6 == 4:assert 0# Checks whether a pending message from server is available.# If not, returns immediately with None. Otherwise, does# the same processing as wait_msg.def check_msg(self):self.sock.setblocking(False)return self.wait_msg()

4.3 運行剛才我們編寫的 MQTTX_WIFI.py,并使用 MQTTX 向它發送內容
我在 ESP32S3 的 GPIO1 接了一個繼電器,所以上面的代碼我解釋一下:

def sub_cb(topic, msg): # 回調函數,收到服務器消息后會調用這個函數print(topic, msg)# ---- 控制 指令 --------if topic.decode("utf-8") == "ledctl" and msg.decode("utf-8") == "on":led_pin.value(1)elif topic.decode("utf-8") == "ledctl" and msg.decode("utf-8") == "off":led_pin.value(0)# ---- 監控 指令 --------

這是剛才代碼中回調函數的部分,意思是,如果 ESP32S3 接收到 topic 是 “ledctl” 的、內容是 on 的消息,就將 GPIO1 的電平拉高,繼電器也就合了。相反,如果 ESP32S3 接收到 topic 是 “ledctl” 的、內容是 off 的消息,就將 GPIO1 的電平拉低,繼電器也就開了。而有趣的是,我們能夠使用電腦端的 MQTTX 給 ESP32S3 遠程發送指令。

情況 1:遠程控制 - 繼電器合:
在這里插入圖片描述

情況 2:遠程控制 - 繼電器開:
在這里插入圖片描述
至此,你已經可以通過電腦遠程控制 ESP32S3 終端了,我只是介紹這個過程,至于實際應用,你需要根據你現有的主程序等進行自己修改,讓它控制你想要控制的 GPIO 等…

5.在 ESP32S3 上寫入程序,讓它能夠發送 自己的數據 至 云服務器

懶得寫了… 太多了倒是還好,主要是每個人的程序不一樣。把我的 main.py 粘上來大家照葫蘆畫瓢吧…


import time
import machine
import _thread
import sys
import max31865
from pid import PID
import ujson
from machine import UART
from machine import Pin
import network
from umqttsimple import MQTTClient
import MQTTX_WIFI#------------------------------------------- 0.創建多線程 -------------------------------------------## 0.1 MQTT監聽打開 - 線程
def MQTT_Listener(*args, **kwargs):print("------------ 正在創建 MQTT_Listener 線程 -----------\n")print("1.正在設置回調函數...")YzyMqttClient.set_callback(MQTTX_WIFI.sub_cb)  # 設置回調函數print("1.OK\n")print("2.正在建立 MQTT 連接")YzyMqttClient.connect()  # 建立連接print("2.OK\n")control_topic = "HYDC-A-60-01-control_topic"print("3.正在設置 MQTT_Listener 通訊 control_topic == {} ... ".format(control_topic))YzyMqttClient.subscribe(b"{}".format(control_topic))  # 監控ledctl這個通道,接收控制命令print("3.OK\n")print("4.正在設置引腳...")led_pin = Pin(1, Pin.OUT)print("4.OK\n")time.sleep(1)#------------------------------------- 1.初始化 PIN / UART 端口 -------------------------------------## 1.1 初始化-顯示器:
#     UART 1( pin_tx == 47; pin_rx == 48)
uart = UART(1, baudrate=115200, tx=47, rx=48)
# 1.2 初始化-繼電器:
#     GPIO 1 為 輸出模式
pin_1 = machine.Pin(1, machine.Pin.OUT)
pin_1.init(mode=machine.Pin.OUT, pull=None)
# 1.3 初始化-溫度+/-按鈕:
#     GPIO 16、GPIO 17 為 輸入模式。
#     GPIO 16(溫度+); GPIO 17(溫度-)
switch_setTemp_up = machine.Pin(16, machine.Pin.IN, machine.Pin.PULL_UP)
switch_setTemp_down = machine.Pin(17, machine.Pin.IN, machine.Pin.PULL_UP)#--------------------------------------- 2.參數配置 PID / PWM ---------------------------------------## 2.1 PID 控制器配置:
setTemp = 60                               # 目標溫度(default==60)
Kp = 2                                      # 更改此值設置 PID 的 Kp 值
Ki = 0.2                                    # 更改此值設置 PID 的 Ki 值
Kd = 0.05                                   # 更改此值設置 PID 的 Kd 值
pid_controller = PID(Kp, Ki, Kd, setTemp)  # 向 PID 函數傳遞參數
# 2.2 設置 PWM 引腳和頻率:
pwm_pin = machine.Pin(15, machine.Pin.OUT)  # 選擇 GPIO15 作為 PWM 控制引腳
pwm = machine.PWM(pwm_pin)                  # 向 PWM 類傳遞參數,創建 PWM 對象
pwm.freq(1500)                              # 設置 PWM 對象的頻率(建議范圍:1000-20000 Hz)#----------------------------------------- 3.WIFI 遠程 MQTT -----------------------------------------## 3.1 使用 WIFI 連接網絡
print("---------------- 正在連接 WIFI ... ---------------\n")
MQTTX_WIFI.do_wifi_connect()
time.sleep(1)
# 3.2 創建mqt
print("-------------- 正在建立 MQTTClient ... ------------\n")
print("1.正在創建 MQTT Client ...")
YzyMqttClient = MQTTClient("YzyMqttClient", "183.72.219.207",1883,"admin","fish0424",keepalive=60)  # 建立一個MQTT客戶端
print("1.OK\n")
# 0.定義 設備名稱
homeassistant_device_name = "HYDC-A-60-01"
# 1.定義 傳感器 currentTemp 名稱、類型
print("2.正在創建 傳感器 currentTemp ...")
homeassistant_device_sensor_currentTemp_name = "currentTemp"
homeassistant_device_sensor_currentTemp_type = "Temp"
print("2.OK\n")
# 2.定義 傳感器 setTemp 名稱、類型
print("3.正在創建 傳感器 setTemp ...")
homeassistant_device_sensor_setTemp_name = "setTemp"
homeassistant_device_sensor_setTemp_type = "Temp"
print("3.OK\n")
# 1.1 定義 傳感器 currentTemp 發送報文 topic
homeassistant_device_sensor_currentTemp_state_topic = "HA-%s/%s/state" % (homeassistant_device_name, homeassistant_device_sensor_currentTemp_name)
# 2.1 定義 傳感器 setTemp 發送報文 topic
homeassistant_device_sensor_setTemp_state_topic = "HA-%s/%s/state" % (homeassistant_device_name, homeassistant_device_sensor_setTemp_name)
time.sleep(1)#------------------------------------------- 4.開啟 多線程 -------------------------------------------## 4.1 開啟 MQTT_Listener 線程
thread_1 = _thread.start_new_thread(MQTT_Listener, (1,))
time.sleep(1)print("---------------- main 函數開始運行 ... --------------\n")
while True:# ------------ 1.溫度檢測 ------------ ## 1.1:溫度值讀取 - temp_4、temp_5、temp_6、temp_7temp_4 = round(max31865.read_max31865_temperature_4(), 1)time.sleep_ms(30)temp_5 = round(max31865.read_max31865_temperature_5(), 1)time.sleep_ms(30)temp_6 = round(max31865.read_max31865_temperature_6(), 1)time.sleep_ms(30)temp_7 = round(max31865.read_max31865_temperature_7(), 1)time.sleep_ms(30)# 1.2:計算4路config值config_4 = max31865.read_config_4()config_5 = max31865.read_config_5()config_6 = max31865.read_config_6()config_7 = max31865.read_config_7()# -------------- 2.PID -------------- ## 2.1:根據 temp_4 計算輸出 PWM 信號強度output_value = pid_controller.compute(temp_4)# 2.2:將輸出值限制在 0-100% 的范圍內,并將其映射到PWM占空比(0-1023)output_value = max(min(output_value, 100), 0)duty_cycle = int(output_value * 1023 / 100)# 2.3:設置 PWM 占空比pwm.duty(duty_cycle)# 2.4:獲取 PID 參數errorsum = pid_controller.get_constants()# ------------- 3.繼電器 ------------- ## 3.1:設置繼電器控制邏輯,大于設定溫度15℃自動斷開if temp_4 < setTemp + 15:pin_1.value(1)else:pin_1.value(0)# ---------- 4.溫度 +/- 按鈕 --------- ## 4.1:設置微動開關邏輯if switch_setTemp_up.value() == 0 and setTemp < 120:setTemp += 1pid_controller.set_setTemp(setTemp)  # 更新PID控制器的目標值time.sleep_ms(200)  # 為了防止多次觸發,暫停200msif switch_setTemp_down.value() == 0 and setTemp > 30:setTemp -= 1pid_controller.set_setTemp(setTemp)  # 更新PID控制器的目標值time.sleep_ms(200)  # 為了防止多次觸發,暫停200ms# ---------- 5.顯示器串口傳輸 --------- ## 5.1:UART,將數據轉jsondata = {'temp4': temp_4, 'temp5': temp_5, 'temp6': temp_6, 'setTemp': setTemp}json_data = ujson.dumps(data)# 5.2:發送JSON數據到另一個ESP32S3(顯示器)uart.write(json_data + '\n')# ----------- 6.MQTT遠傳監視 ---------- #YzyMqttClient.check_msg()time.sleep(0.3)homeassistant_device_sensor_currentTemp_state_content = round(temp_4, 1)homeassistant_device_sensor_setTemp_state_content = setTemp# 1.2 定義 傳感器 currentTemp 發送報文 contentsend_content_currentTemp = ujson.dumps(homeassistant_device_sensor_currentTemp_state_content)# 2.2 定義 傳感器 setTemp 發送報文 contentsend_content_setTemp = ujson.dumps(homeassistant_device_sensor_setTemp_state_content)# 3.發送 currentTemp、setTemp 報文(包含 topic 和 content)YzyMqttClient.publish(homeassistant_device_sensor_currentTemp_state_topic,send_content_currentTemp)time.sleep(0.1)YzyMqttClient.publish(homeassistant_device_sensor_setTemp_state_topic,send_content_setTemp)time.sleep(0.1)# ---------- 7.串口監視器調試 --------- ## 6.1:輸出溫度print("CS-4-PT100:當前溫度: {:.2f}".format(temp_4))print("CS-5-PT100:當前溫度: {:.2f}".format(temp_5))print("CS-6-PT100:當前溫度: {:.2f}".format(temp_6))print("CS-7-PT100:當前溫度: {:.2f}".format(temp_7))# 6.2:輸出 max-31865 的 configprint("CS-4-Config: 0x{:02x}".format(config_4))print("CS-5-Config: 0x{:02x}".format(config_5))print("CS-6-Config: 0x{:02x}".format(config_6))print("CS-7-Config: 0x{:02x}".format(config_7))# 6.3:輸出 PID 相關參數print("PID控制程序輸出功率百分比: {:.2f}%".format(output_value))print("errorsum ==",errorsum)print("setTemp ==",setTemp)print("PWM Duty Cycle: {}".format(duty_cycle))print("Kp: {}, Ki: {}, Kd: {}".format(Kp, Ki, Kd))# 6.4:輸出 傳輸至顯示器的 json_data 內容print("json_data ==",json_data,"\n")time.sleep(0.1)

然后,真實采集到的數據就會在 HomeAssistant 上顯現了。

在這里插入圖片描述

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

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

相關文章

會玩這 10 個 Linux 命令,一定是個有趣的 IT 男!

Linux當中有很多比較有趣的命令&#xff0c;可以動手看看&#xff0c;很簡單的。 1.rev命令 一行接一行地顛倒所輸入的字符串。 運行&#xff1a; $rev如輸入&#xff1a;shiyanlou shiyanlou2.asciiview命令 1.先安裝aview $sudo apt-get install aview2.再安裝imagema…

vue中封裝自動計算比例滑塊

此插件為另一位漂亮的前端同事小姐姐封裝,覺得非常好用于是決定記載下來,便于復用 如圖需要動態傳入需要分配權重的數組,平均分配可以自動將100%平均分給數組中的值 如果手動拖拽,則會自動計算可拖動最大區域,便于最終總權重必定為100% <el-alert class"merge-alert&…

zookeeper常用命令

zookeeper常用命令 1. 下載安裝2. 配置說明2.1 配置 3. zookeeper的常見命令3.1 server端啟動停止等命令3.2 客戶端連接等命令3.3 客戶端簡單常用命令3.3.1 查看目錄&#xff08;查看數據結構&#xff09;3.3.2 刪除目錄3.3.3 創建目錄3.3.4 創建目錄并寫入值 查看節點值3.3.5…

Apache JMeter:完全指南

Apache JMeter 是一款開源的性能測試工具&#xff0c;可以用于測試 Web 應用程序、FTP 服務器、數據庫等各種類型的服務器。本文將以 JMeter 5.5 為例介紹 JMeter 的使用方法。 下載和安裝 由于 JMeter 是使用 Java 開發的&#xff0c;因此在運行之前必須先安裝 JDK。您可以在…

Android中tools屬性的使用

參考&#xff1a; 1.Android:Tools命名空間原來是有大用處的 2.Android中tools屬性的使用 3.工具屬性參考文檔 4. 命名空間介紹 5. 注解 6. lint 7. 資源壓縮shrink-resources 目錄 一、概述二、引入tools命名空間三、tools 命名空間的作用有哪些&#xff1f;四、tools 命名空間…

年薪6.5萬美元|生物醫學老師獲美國耶魯大學博士后職位

I老師就職于雙非二本院校&#xff0c;希望通過出國研修以提升科研背景&#xff0c;在公派訪學和申請導師出資的博士后之間&#xff0c;其選擇了后者。最終我們落實了美國耶魯大學的職位&#xff0c;頭銜為Associate Research Scientist&#xff08;副研究科學家&#xff09;&am…

Selenium 自動化 | 案例實戰篇

Chrome DevTools 簡介 Chrome DevTools 是一組直接內置在基于 Chromium 的瀏覽器&#xff08;如 Chrome、Opera 和 Microsoft Edge&#xff09;中的工具&#xff0c;用于幫助開發人員調試和研究網站。 借助 Chrome DevTools&#xff0c;開發人員可以更深入地訪問網站&#xf…

Observability:識別生成式 AI 搜索體驗中的慢速查詢

作者&#xff1a;Philipp Kahr Elasticsearch Service 用戶的重要注意事項&#xff1a;目前&#xff0c;本文中描述的 Kibana 設置更改僅限于 Cloud 控制臺&#xff0c;如果沒有我們支持團隊的手動干預&#xff0c;則無法進行配置。 我們的工程團隊正在努力消除對這些設置的限制…

uniapp動態底部tab欄

實現思路&#xff1a; 創建一個js文件用來存放所有的tabbar,不同的數組表示不同的tabbar組合。 創建一個vue文件用來制作底部tabbar組件。 使用vuex存儲用戶的身份信息,根據身份信息切換tabbar組合。 具體步驟&#xff1a; 新建一個tabbar.js文件&#xff0c;將…

SpringBoot 整合MyBatis

整合MyBatis 官方文檔&#xff1a;http://mybatis.org/spring-boot-starter/mybatis-spring-boot-autoconfigure/ Maven倉庫地址&#xff1a;https://mvnrepository.com/artifact/org.mybatis.spring.boot/mybatis-spring-boot-starter/2.1.3 整合測試 導入 MyBatis 所需要的…

數據結構筆記--優先隊列(大小根堆)經典題型

1--項目的最大利潤 題目描述&#xff1a; 輸入&#xff1a;正數數組 costs&#xff0c;costs[i] 表示項目 i 的花費&#xff1b;正數數組 profits&#xff0c;profits[i] 表示項目 i 的花費&#xff1b;正數 k 表示只能串行完成最多 k 個項目&#xff1b;m 表示擁有的資金&…

MySQL事務:確保數據完整性與并發性的關鍵

MySQL事務&#xff1a;確保數據完整性與并發性的關鍵 MySQL作為一種廣泛使用的開源關系型數據庫管理系統&#xff0c;具備強大的事務支持&#xff0c;以確保數據庫操作的一致性、隔離性和持久性。本文將深入探討MySQL中的事務概念、事務隔離級別以及事務的應用場景&#xff0c…

leetcode 516. 最長回文子序列(JAVA)題解

題目鏈接https://leetcode.cn/problems/longest-palindromic-subsequence/description/?utm_sourceLCUS&utm_mediumip_redirect&utm_campaigntransfer2china 目錄 題目描述&#xff1a; 暴力遞歸&#xff1a; 動態規劃&#xff1a; 題目描述&#xff1a; 給你一個…

Python學習過程筆記:主模塊(main) 異常處理 命令行參數解析 日志記錄 socket模塊 類的私有方法 字節字符串

文章目錄 1.Python中的主程序2.Python中的異常處理3.Python中的命令行參數解析4.Python中的日志記錄5.網絡編程socket模塊6.Python中的私有方法7.Python中的字節字符串 1.Python中的主程序 if __name__ __main__在Python中&#xff0c;if __name__ __main__ 是一個常見的代碼…

百日筑基篇——python爬蟲學習(一)

百日筑基篇——python爬蟲學習&#xff08;一&#xff09; 文章目錄 前言一、python爬蟲介紹二、URL管理器三、所需基礎模塊的介紹1. requests2. BeautifulSoup1. HTML介紹2. 網頁解析器 四、實操1. 代碼展示2. 代碼解釋1. 將大文件劃分為小的文件&#xff08;根據AA的ID數量劃…

簡單認識Zabbix監控系統及配置

文章目錄 一、zabbix概述1、定義2、zabbix監控原理3、監控對象4、zabbix的3種架構&#xff08;1&#xff09; C/S架構&#xff08;2&#xff09;分布式架構&#xff1a;zabbix-proxy-client架構&#xff08;3&#xff09; master-node-client架構 5、zabbix監控模式 二、部署za…

項目實戰 — 消息隊列(8){網絡通信設計①}

目錄 一、自定義應用層協議 &#x1f345; 1、格式定義 &#x1f345; 2、準備工作 &#x1f384;定義請求和響應 &#x1f384; 定義BasicArguments &#x1f384; 定義BasicReturns &#x1f345; 2、創建參數類 &#x1f384; 交換機 &#x1f384; 隊列 &#x1f38…

【網絡】傳輸層——TCP(滑動窗口流量控制擁塞控制延遲應答捎帶應答)

&#x1f431;作者&#xff1a;一只大喵咪1201 &#x1f431;專欄&#xff1a;《網絡》 &#x1f525;格言&#xff1a;你只管努力&#xff0c;剩下的交給時間&#xff01; 上篇文章對TCP可靠性機制講解了一部分&#xff0c;這篇文章接著繼續講解。 &#x1f3a8;滑動窗口 在…

Springboot 實踐(2)MyEclipse2019創建項目修改pom文件,加載springboot 及swagger-ui jar包

MyEclipse2019創建工程之后&#xff0c;需要添加Springboot啟動函數、添加application.yml配置文件、修改pom文件添加項目使用的jar包。 添加Springboot啟動函數 創建文件存儲路徑 &#xff08;1&#xff09;右鍵單擊“src/main/java”文件夾&#xff0c;彈出對話框輸入路徑…

Android 簡單的視頻、圖片壓縮工具

首頁需要壓縮的工具包 1.Gradle implementation com.iceteck.silicompressorr:silicompressor:2.2.3 2.添加相關權限&#xff08;手機得動態申請權限&#xff09; <uses-permission android:name"android.permission.READ_EXTERNAL_STORAGE"/> <uses-p…