【自用】终端设备(ESP32-S3)连接云服务器 HomeAssistant + MQTT 物联网平台

news2025/1/13 3:21:51

总览

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/state

35

在这里插入图片描述
在这里插入图片描述

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/state

35

在这里插入图片描述

4.在 ESP32S3 上写入程序,连接 WIFI 并让它连接到 云服务器 上的 MQTT 网络服务

4.1 给 ESP32S3 写入程序
给这段程序起个名字吧,随便。我的是 MQTTX_WIFI.py
请注意,你需要更改这里面的几个地方,我在下面代码中句子的后面加上了 注释“请修改:xxx”

import time
from machine import Pin
import network
from umqttsimple import MQTTClient


def 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 = 1
        while not wlan.isconnected():
            print("Connecting for ",i,' seconds...')
            i += 1
            time.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 = 0
    YzyMqttClient.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 hexlify


class MQTTException(Exception):
    pass


class 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 1883
        self.client_id = client_id
        self.sock = None
        self.server = server
        self.port = port
        self.ssl = ssl
        self.ssl_params = ssl_params
        self.pid = 0
        self.cb = None
        self.user = user
        self.pswd = password
        self.keepalive = keepalive
        self.lw_topic = None
        self.lw_msg = None
        self.lw_qos = 0
        self.lw_retain = False

    def _send_str(self, s):
        self.sock.write(struct.pack("!H", len(s)))
        self.sock.write(s)

    def _recv_len(self):
        n = 0
        sh = 0
        while 1:
            b = self.sock.read(1)[0]
            n |= (b & 0x7F) << sh
            if not b & 0x80:
                return n
            sh += 7

    def set_callback(self, f):
        self.cb = f

    def set_last_will(self, topic, msg, retain=False, qos=0):
        assert 0 <= qos <= 2
        assert topic
        self.lw_topic = topic
        self.lw_msg = msg
        self.lw_qos = qos
        self.lw_retain = retain

    def 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 ussl

            self.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 << 1
        if self.user is not None:
            sz += 2 + len(self.user) + 2 + len(self.pswd)
            msg[6] |= 0xC0
        if self.keepalive:
            assert self.keepalive < 65536
            msg[7] |= self.keepalive >> 8
            msg[8] |= self.keepalive & 0x00FF
        if 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) << 3
            msg[6] |= self.lw_retain << 5

        i = 1
        while sz > 0x7F:
            premsg[i] = (sz & 0x7F) | 0x80
            sz >>= 7
            i += 1
        premsg[i] = sz

        self.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] == 0x02
        if resp[3] != 0:
            raise MQTTException(resp[3])
        return resp[2] & 1

    def 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 | retain
        sz = 2 + len(topic) + len(msg)
        if qos > 0:
            sz += 2
        assert sz < 2097152
        i = 1
        while sz > 0x7F:
            pkt[i] = (sz & 0x7F) | 0x80
            sz >>= 7
            i += 1
        pkt[i] = sz
        # print(hex(len(pkt)), hexlify(pkt, ":"))
        self.sock.write(pkt, i + 1)
        self._send_str(topic)
        if qos > 0:
            self.pid += 1
            pid = self.pid
            struct.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:
                        return
        elif qos == 2:
            assert 0

    def 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 += 1
        struct.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 None
        if res == b"":
            raise OSError(-1)
        if res == b"\xd0":  # PINGRESP
            sz = self.sock.read(1)[0]
            assert sz == 0
            return None
        op = res[0]
        if op & 0xF0 != 0x30:
            return op
        sz = 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 + 2
        if op & 6:
            pid = self.sock.read(2)
            pid = pid[0] << 8 | pid[1]
            sz -= 2
        msg = 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_7
    temp_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 += 1
        pid_controller.set_setTemp(setTemp)  # 更新PID控制器的目标值
        time.sleep_ms(200)  # 为了防止多次触发,暂停200ms
    if switch_setTemp_down.value() == 0 and setTemp > 30:
        setTemp -= 1
        pid_controller.set_setTemp(setTemp)  # 更新PID控制器的目标值
        time.sleep_ms(200)  # 为了防止多次触发,暂停200ms
    
    
    # ---------- 5.显示器串口传输 --------- #
    
    # 5.1:UART,将数据转json
    data = {'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 发送报文 content
    send_content_currentTemp = ujson.dumps(homeassistant_device_sensor_currentTemp_state_content)
    # 2.2 定义 传感器 setTemp 发送报文 content
    send_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 的 config
    print("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.coloradmin.cn/o/875699.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

合并图形并共享同一个图例的三种方法

简介 小编在科研中&#xff0c;需要将多个图形进行合并&#xff0c;并共享同一个图例。此时应该如何实现&#xff1f;关于图形合并的相关推文写了很多了&#xff1a;R可视乎&#xff5c;合并多幅图形、cowplot包&#xff0c;ggplot2图形排版R包。 但是对于今天这个问题&#x…

SpringBoot-Hello World

SpringBootWeb快速入门 创建Springboot工程&#xff0c;并勾选web开发相关依赖定义HelloController类&#xff0c;添加方法hello&#xff0c;并添加相关注释运行测试 创建新的SpringBoot项目 几个注意的点&#xff1a; Name&#xff1a;基本上不用管&#xff0c;会根据下面的Ar…

智能电动机保护控制器的应用与分析

安科瑞 华楠 分析了智能电动机保护器相比热继电器的优点&#xff0c;指出了在我公司成功应用的原因&#xff0c;提出了应用过程中需要注意的地方。 公司新建一车间中&#xff0c;当工程设计到电动机保护这一部分时&#xff0c;设计者出于对热继电器保护性能的不满意&#xff0c…

【数据库基础】Mysql下载安装及配置

下载 下载地址&#xff1a;https://downloads.mysql.com/archives/community/ 当前最新版本为 8.0版本&#xff0c;可以在Product Version中选择指定版本&#xff0c;在Operating System中选择安装平台&#xff0c;如下 安装 MySQL安装文件分两种 .msi和.zip [外链图片转存失…

红帽8.2版本CSA题库:第八题配置 autofs自动挂载

红帽8.2版本CSA题库&#xff1a;第八题配置 autofs自动挂载 yum -y install autofs &#xff03;安装&#xff41;&#xff55;&#xff54;&#xff4f;&#xff46;&#xff53; vim /etc/auto.master &#xff03;在…

Spring Boot业务代码中使用@Transactional事务失效踩坑点总结

1.概述 接着之前我们对Spring AOP以及基于AOP实现事务控制的上文&#xff0c;今天我们来看看平时在项目业务开发中使用声明式事务Transactional的失效场景&#xff0c;并分析其失效原因&#xff0c;从而帮助开发人员尽量避免踩坑。 我们知道 Spring 声明式事务功能提供了极其…

圆满收官丨“2023年度第一季万博智云云迁移架构师训练营”结营了

“2023年度第一季万博智云云迁移架构师训练营”于今日圆满落幕。百余名来自全国各地30企业的工程师报名参加学习&#xff0c;其中60工程师在忙碌工作中抽空参与考试&#xff0c;近40名工程师通过万博智云云迁移架构师OCCE认证。 为了帮助工程师们掌握云迁移基础知识&#xff0c…

基于UDS on CAN的bootloader

UDS (Unified Diagnostic Services)&#xff1a;汽车诊断标准协议 Tester(诊断方)<--------------------------------------->ECU(汽车电控单元&#xff09; 2.UDS的硬件实现&#xff1a;CAN总线和诊断接口 3.UDS的软件实现&#xff1a;协议栈(Core)和应用程序 UDS协议…

【数字图像处理】数字图像处理中的直方图相关操作

文章目录 前言一、直方图为什么可以进行图像处理&#xff1f;二、直方图处理怎么实现&#xff1f;直方图均衡化直方图匹配-规定化局部直方图处理直方图统计量增强图像 三、OpenCv提供的直方图基础操作直方图均衡化OpenCv中直方图的表示从数据创建直方图&#xff1a;cv::calcHis…

Kafka的下载安装以及使用

一、Kafka下载 下载地址&#xff1a;https://kafka.apache.org/downloads 二、Kafka安装 因为选择下载的是 .zip 文件&#xff0c;直接跳过安装&#xff0c;一步到位。 选择在任一磁盘创建空文件夹&#xff08;不要使用中文路径&#xff09;&#xff0c;解压之后把文件夹内容…

2014-2022年阿里淘宝村省市县数据

2009-2022年阿里淘宝村-省市县数据&#xff08;原始数据汇总&#xff09; 从萌芽到扩散&#xff0c;再到大规模、集群式增长&#xff0c;生机勃勃的“淘宝村”和“淘宝镇”已成为中国农村电商发展的典范。2022年&#xff0c;在全面推动乡村振兴的进程中&#xff0c;又有一批村…

ChatGPT收录

VSCode插件-ChatGPT 多磨助手 多磨助手 (domore.run) Steamship Steamship 免费合集 免费chatGPT - Ant Design Pro 免费AI聊天室 (xyys.one)

OceanMind海睿思受邀出席2023长三角数字化大会,斩获两项数字化转型年度大奖

8月10日&#xff0c;由江苏省工业和信息化厅指导&#xff0c;长三角首席信息官联盟主办&#xff0c;江苏省企业信息化协会承办的“2023年长三角数字化转型大会”在江苏南京成功召开。 本次大会以“工业互联智造未来”为主题&#xff0c;旨在促进产业互联网的发展&#xff0c;并…

JavaScript函数声明与函数表达式

在 JavaScript 中&#xff0c;可以通过两种方式来定义函数&#xff1a;函数声明和函数表达式。 函数声明使用 function 关键字进行定义&#xff0c;并且在整个作用域中都可用。 函数声明的方式&#xff1a; function calcAge1(birthYear) {return 2037 - birthYear; } const …

制造执行系统(MES)在新能源领域的应用

制造执行系统&#xff08;MES&#xff09;在新能源领域有许多应用&#xff0c;特别是在管理、监控和优化新能源生产过程方面。新能源包括太阳能、风能、生物质能、地热能等。以下是一些MES在新能源方面的应用领域&#xff1a; 生产计划与调度&#xff1a;MES可以协助规划和调度…

FiboSearch Pro – Ajax Search for WooCommerce 商城AJAX实时搜索插件

FiboSearch Pro是最受欢迎的WooCommerce 产品搜索插件。它为您的用户提供精心设计的高级 AJAX 搜索栏&#xff0c;并提供实时搜索建议。默认情况下&#xff0c;WooCommerce 提供非常简单的搜索解决方案&#xff0c;没有实时产品搜索&#xff0c;甚至没有 SKU 搜索。FiboSearch&…

多种求组合数算法

目录 求组合数Ⅰ&#xff08;递推&#xff09;核心理论理论推导典型例题代码实现 求组合数Ⅱ&#xff08;预处理&#xff09;核心理论典型例题代码实现 求组合数Ⅲ&#xff08;Lucas定理&#xff09;核心理论Lucas定理的证明1.证明Lucas定理的第一形式2.证明Lucas定理的第二形式…

顺序表的插入,删除,修改和查找(详细解析)

目录 一.顺序表的初始化----静态分配 二.顺序表的初始化----动态分配 三.顺序表的插入 1.插入操作 2.插入操作的时间复杂度 三.顺序表的删除操作 1.顺序表的删除 2.删除操作的时间复杂度 四.顺序表的查找 1.按位查找操作&#xff1a;查找第i位置的元素 2.按位查找操作…

嘉实基金:金融科技与开源治理的双驱动,打造安全的资管业务数字系统

嘉实基金成立于1999年&#xff0c;是国内最早成立的十家基金管理公司之一&#xff0c;也是国内首家资产管理规模超过千亿的基金公司。作为一家领先的投资管理公司&#xff0c;嘉实基金也在数字化转型趋势中&#xff0c;积极推进金融科技在金融资管行业中的探索实践。为了支撑基…

7-zip 更换图标:定制你的7-Zip

7-Zip Theme Manager是一个用于管理和应用自定义主题的软件工具&#xff0c;专门为7-Zip文件压缩软件开发。它允许用户选择并应用各种主题来改变7-Zip的外观和用户界面&#xff0c;包括颜色方案、图标集、按钮样式等。通过更改主题&#xff0c;用户可以使7-Zip界面更加美观、易…