PX4二次开发快速入门(三):自定义串口驱动

文章目录

  • 前言

前言

软件:PX4 1.14.0稳定版
硬件:纳雷NRA12,pixhawk4
仿照原生固件tfmini的驱动进行编写
源码地址:
https://gitee.com/Mbot_admin/px4-1.14.0-csdn

修改
src/drivers/distance_sensor/CMakeLists.txt
添加

add_subdirectory(nra12)

修改
src/drivers/distance_sensor/Kconfig
添加

select DRIVERS_DISTANCE_SENSOR_NRA12

在src/drivers/distance_sensor/目录下添加一个nra12文件夹
在nra12文件夹下添加Kconfig,NRA12.cpp,NRA12.hpp,nra12_main.cpp,module.yaml,nra12_parser.cpp,nra12_parser.h。

Kconfig如下:

menuconfig DRIVERS_DISTANCE_SENSOR_NRA12bool "nra12"default n---help---Enable support for nra12

NRA12.cpp如下:

#include "NRA12.hpp"#include <lib/drivers/device/Device.hpp>
#include <fcntl.h>NRA12::NRA12(const char *port, uint8_t rotation) :ScheduledWorkItem(MODULE_NAME, px4::serial_port_to_wq(port)),_px4_rangefinder(0, rotation)
{// store port namestrncpy(_port, port, sizeof(_port) - 1);// enforce null termination_port[sizeof(_port) - 1] = '\0';device::Device::DeviceId device_id;device_id.devid_s.devtype = DRV_DIST_DEVTYPE_NRA12;device_id.devid_s.bus_type = device::Device::DeviceBusType_SERIAL;uint8_t bus_num = atoi(&_port[strlen(_port) - 1]); // Assuming '/dev/ttySx'if (bus_num < 10) {device_id.devid_s.bus = bus_num;}_px4_rangefinder.set_device_id(device_id.devid);_px4_rangefinder.set_rangefinder_type(distance_sensor_s::MAV_DISTANCE_SENSOR_LASER);
}NRA12::~NRA12()
{// make sure we are truly inactivestop();perf_free(_sample_perf);perf_free(_comms_errors);
}int
NRA12::init()
{int32_t hw_model = 1; // only one model so far...switch (hw_model) {case 1: // NRA12 (12m, 100 Hz)// Note:// Sensor specification shows 0.3m as minimum, but in practice// 0.3 is too close to minimum so chattering of invalid sensor decision// is happening sometimes. this cause EKF to believe inconsistent range readings.// So we set 0.4 as valid minimum._px4_rangefinder.set_min_distance(0.1f);_px4_rangefinder.set_max_distance(30.0f);_px4_rangefinder.set_fov(math::radians(1.15f));break;default:PX4_ERR("invalid HW model %" PRId32 ".", hw_model);return -1;}// statusint ret = 0;do { // create a scope to handle exit conditions using break// open fd_fd = ::open(_port, O_RDWR | O_NOCTTY);if (_fd < 0) {PX4_ERR("Error opening fd");return -1;}// baudrate 115200, 8 bits, no parity, 1 stop bitunsigned speed = B115200;termios uart_config{};int termios_state{};tcgetattr(_fd, &uart_config);// clear ONLCR flag (which appends a CR for every LF)uart_config.c_oflag &= ~ONLCR;// set baud rateif ((termios_state = cfsetispeed(&uart_config, speed)) < 0) {PX4_ERR("CFG: %d ISPD", termios_state);ret = -1;break;}if ((termios_state = cfsetospeed(&uart_config, speed)) < 0) {PX4_ERR("CFG: %d OSPD\n", termios_state);ret = -1;break;}if ((termios_state = tcsetattr(_fd, TCSANOW, &uart_config)) < 0) {PX4_ERR("baud %d ATTR", termios_state);ret = -1;break;}uart_config.c_cflag |= (CLOCAL | CREAD);	// ignore modem controlsuart_config.c_cflag &= ~CSIZE;uart_config.c_cflag |= CS8;			// 8-bit charactersuart_config.c_cflag &= ~PARENB;			// no parity bituart_config.c_cflag &= ~CSTOPB;			// only need 1 stop bituart_config.c_cflag &= ~CRTSCTS;		// no hardware flowcontrol// setup for non-canonical modeuart_config.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON);uart_config.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);uart_config.c_oflag &= ~OPOST;// fetch bytes as they become availableuart_config.c_cc[VMIN] = 1;uart_config.c_cc[VTIME] = 1;if (_fd < 0) {PX4_ERR("FAIL: laser fd");ret = -1;break;}} while (0);// close the fd::close(_fd);_fd = -1;if (ret == PX4_OK) {start();}return ret;
}int
NRA12::collect()
{perf_begin(_sample_perf);// clear buffer if last read was too long agoint64_t read_elapsed = hrt_elapsed_time(&_last_read);// the buffer for read chars is buflen minus null terminationchar readbuf[sizeof(_linebuf)] {};unsigned readlen = sizeof(readbuf) - 1;int ret = 0;float distance_m = -1.0f;// Check the number of bytes available in the bufferint bytes_available = 0;::ioctl(_fd, FIONREAD, (unsigned long)&bytes_available);if (!bytes_available) {perf_end(_sample_perf);return 0;}// parse entire bufferconst hrt_abstime timestamp_sample = hrt_absolute_time();do {// read from the sensor (uart buffer)ret = ::read(_fd, &readbuf[0], readlen);
// ret = ::write(_fd,&readbuf,10);
// if (ret < 0) {
//     PX4_ERR("write err: %d", ret);
// }if (ret < 0) {PX4_ERR("read err: %d", ret);perf_count(_comms_errors);perf_end(_sample_perf);// only throw an error if we time outif (read_elapsed > (kCONVERSIONINTERVAL * 2)) {/* flush anything in RX buffer */tcflush(_fd, TCIFLUSH);return ret;} else {return -EAGAIN;}}_last_read = hrt_absolute_time();// parse bufferfor (int i = 0; i < ret; i++) {// PX4_INFO("readbuf=%x\n",readbuf[i]);// PX4_INFO("ret=%d\n",ret);// PX4_INFO("bytes_available=%d\n",bytes_available);nra12_parse(readbuf[i], _linebuf, &_linebuf_index, &_parse_state, &distance_m);}// bytes left to parsebytes_available -= ret;} while (bytes_available > 0);// no valid measurement after parsing bufferif (distance_m < 0.0f){perf_end(_sample_perf);return -EAGAIN;}// publish most recent valid measurement from buffer_px4_rangefinder.update(timestamp_sample, distance_m);perf_end(_sample_perf);return PX4_OK;
}void
NRA12::start()
{// schedule a cycle to start things (the sensor sends at 100Hz, but we run a bit faster to avoid missing data)ScheduleOnInterval(7_ms);
}void
NRA12::stop()
{ScheduleClear();
}void
NRA12::Run()
{// fds initialized?if (_fd < 0) {// open fd_fd = ::open(_port, O_RDWR | O_NOCTTY);}// perform collectionif (collect() == -EAGAIN) {// reschedule to grab the missing bits, time to transmit 9 bytes @ 115200 bpsScheduleClear();ScheduleOnInterval(7_ms, 87 * 9);return;}
}void
NRA12::print_info()
{printf("Using port '%s'\n", _port);perf_print_counter(_sample_perf);perf_print_counter(_comms_errors);
}

NRA12.hpp如下:

#pragma once#include <termios.h>#include <drivers/drv_hrt.h>
#include <lib/perf/perf_counter.h>
#include <px4_platform_common/px4_config.h>
#include <px4_platform_common/module.h>
#include <px4_platform_common/px4_work_queue/ScheduledWorkItem.hpp>
#include <lib/drivers/rangefinder/PX4Rangefinder.hpp>
#include <uORB/topics/distance_sensor.h>#include "nra12_parser.h"#define NRA12_DEFAULT_PORT	"/dev/ttyS3"using namespace time_literals;class NRA12 : public px4::ScheduledWorkItem
{
public:NRA12(const char *port, uint8_t rotation = distance_sensor_s::ROTATION_DOWNWARD_FACING);virtual ~NRA12();int init();void print_info();private:int collect();void Run() override;void start();void stop();PX4Rangefinder	_px4_rangefinder;NRA12_PARSE_STATE _parse_state {NRA12_PARSE_STATE::STATE0_UNSYNC};char _linebuf[24] {};char _port[20] {};static constexpr int kCONVERSIONINTERVAL{9_ms};int _fd{-1};unsigned int _linebuf_index{0};hrt_abstime _last_read{0};perf_counter_t _comms_errors{perf_alloc(PC_COUNT, MODULE_NAME": com_err")};perf_counter_t _sample_perf{perf_alloc(PC_ELAPSED, MODULE_NAME": read")};};

module.yaml 如下:

module_name: nanoradar nra12 lidar
serial_config:- command: nra12 start -d ${SERIAL_DEV}port_config_param:name: SENS_NRA12_CFGgroup: Sensors

nra12_main.cpp如下:

#include "NRA12.hpp"#include <px4_platform_common/getopt.h>/*** Local functions in support of the shell command.*/
namespace nra12
{NRA12	*g_dev{nullptr};int start(const char *port, uint8_t rotation);
int status();
int stop();
int usage();int
start(const char *port, uint8_t rotation)
{if (g_dev != nullptr) {PX4_ERR("already started");return PX4_OK;}// Instantiate the driver.g_dev = new NRA12(port, rotation);if (g_dev == nullptr) {PX4_ERR("driver start failed");return PX4_ERROR;}if (OK != g_dev->init()) {PX4_ERR("driver start failed");delete g_dev;g_dev = nullptr;return PX4_ERROR;}return PX4_OK;
}int
status()
{if (g_dev == nullptr) {PX4_ERR("driver not running");return 1;}printf("state @ %p\n", g_dev);g_dev->print_info();return 0;
}int stop()
{if (g_dev != nullptr) {PX4_INFO("stopping driver");delete g_dev;g_dev = nullptr;PX4_INFO("driver stopped");} else {PX4_ERR("driver not running");return 1;}return PX4_OK;
}int
usage()
{PRINT_MODULE_DESCRIPTION(R"DESCR_STR(
### DescriptionSerial bus driver for the Benewake NRA12 LiDAR.Most boards are configured to enable/start the driver on a specified UART using the SENS_NRA12_CFG parameter.Setup/usage information: https://docs.px4.io/master/en/sensor/sonar.html### ExamplesAttempt to start driver on a specified serial device.
$ sonar start -d /dev/ttyS1
Stop driver
$ sonar stop
)DESCR_STR");PRINT_MODULE_USAGE_NAME("nra12", "driver");PRINT_MODULE_USAGE_SUBCATEGORY("distance_sensor");PRINT_MODULE_USAGE_COMMAND_DESCR("start","Start driver");PRINT_MODULE_USAGE_PARAM_STRING('d', nullptr, nullptr, "Serial device", false);PRINT_MODULE_USAGE_PARAM_INT('R', 25, 0, 25, "Sensor rotation - downward facing by default", true);PRINT_MODULE_USAGE_COMMAND_DESCR("status","Driver status");PRINT_MODULE_USAGE_COMMAND_DESCR("stop","Stop driver");PRINT_MODULE_USAGE_COMMAND_DESCR("test","Test driver (basic functional tests)");PRINT_MODULE_USAGE_COMMAND_DESCR("status","Print driver status");return PX4_OK;
}} // namespaceextern "C" __EXPORT int nra12_main(int argc, char *argv[])
{int ch = 0;uint8_t rotation = distance_sensor_s::ROTATION_DOWNWARD_FACING;const char *device_path = NRA12_DEFAULT_PORT;int myoptind = 1;const char *myoptarg = nullptr;while ((ch = px4_getopt(argc, argv, "R:d:", &myoptind, &myoptarg)) != EOF) {switch (ch) {case 'R':rotation = (uint8_t)atoi(myoptarg);break;case 'd':device_path = myoptarg;break;default:PX4_WARN("Unknown option!");return PX4_ERROR;}}if (myoptind >= argc) {PX4_ERR("unrecognized command");return nra12::usage();}if (!strcmp(argv[myoptind], "start")) {if (strcmp(device_path, "") != 0) {return nra12::start(device_path, rotation);} else {PX4_WARN("Please specify device path!");return nra12::usage();}} else if (!strcmp(argv[myoptind], "stop")) {return nra12::stop();} else if (!strcmp(argv[myoptind], "status")) {return nra12::status();}return nra12::usage();
}

nra12_parser.cpp如下:

#include "nra12_parser.h"
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <termios.h>#include <drivers/drv_hrt.h>
#include <lib/perf/perf_counter.h>
#include <px4_platform_common/px4_config.h>
#include <px4_platform_common/module.h>//#define NRA12_DEBUG#ifdef NRA12_DEBUG
#include <stdio.h>const char *parser_state[] = {"0_UNSYNC","3_GOT_DIST_L","4_GOT_DIST_H","8_GOT_QUALITY""9_GOT_CHECKSUM"
};
#endifint nra12_parse(char c, char *parserbuf, unsigned *parserbuf_index, NRA12_PARSE_STATE *state, float *dist)
{int ret = -1;//char *end;
// PX4_INFO("parse");switch (*state) {case NRA12_PARSE_STATE::STATE12_GOT_END2:// PX4_INFO("STATE12_GOT_END2");// PX4_INFO("c=%x",c);if (c == 0xaa) {*state = NRA12_PARSE_STATE::STATE1_GOT_START1;} else {*state = NRA12_PARSE_STATE::STATE0_UNSYNC;}break;case NRA12_PARSE_STATE::STATE0_UNSYNC:// PX4_INFO("STATE0_UNSYNC");// PX4_INFO("c=%x",c);if (c == 0xaa) {*state = NRA12_PARSE_STATE::STATE1_GOT_START1;}break;case NRA12_PARSE_STATE::STATE1_GOT_START1:// PX4_INFO("STATE1_GOT_START1");// PX4_INFO("c=%x",c);if (c == 0xaa) {*state = NRA12_PARSE_STATE::STATE2_GOT_START2;}else{*state = NRA12_PARSE_STATE::STATE0_UNSYNC;}break;case NRA12_PARSE_STATE::STATE2_GOT_START2:// PX4_INFO("STATE2_GOT_START2");// PX4_INFO("c=%x",c);if(c == 0x0c){*state = NRA12_PARSE_STATE::STATE2_GOT_0C;}else{*state = NRA12_PARSE_STATE::STATE0_UNSYNC;}break;case NRA12_PARSE_STATE::STATE2_GOT_0C:// PX4_INFO("STATE2_GOT_0C");// PX4_INFO("c=%x",c);if(c == 0x07){*state = NRA12_PARSE_STATE::STATE2_GOT_07;}else{*state = NRA12_PARSE_STATE::STATE0_UNSYNC;}break;case NRA12_PARSE_STATE::STATE2_GOT_07:// PX4_INFO("STATE2_GOT_07");// PX4_INFO("c=%x",c);*state = NRA12_PARSE_STATE::STATE3_GOT_Index;break;case NRA12_PARSE_STATE::STATE3_GOT_Index:// PX4_INFO("STATE3_GOT_Index");// PX4_INFO("c=%x",c);*state = NRA12_PARSE_STATE::STATE4_GOT_Res;break;case NRA12_PARSE_STATE::STATE4_GOT_Res:// PX4_INFO("STATE4_GOT_Res");// PX4_INFO("c=%x",c);parserbuf[1]=c;*state = NRA12_PARSE_STATE::STATE5_GOT_DIST_H;break;case NRA12_PARSE_STATE::STATE5_GOT_DIST_H:// PX4_INFO("STATE5_GOT_DIST_H");// PX4_INFO("c=%x",c);*state = NRA12_PARSE_STATE::STATE6_GOT_DIST_L;parserbuf[2]=c;break;case NRA12_PARSE_STATE::STATE6_GOT_DIST_L:// PX4_INFO("STATE6_GOT_DIST_L");// PX4_INFO("c=%x",c);*state = NRA12_PARSE_STATE::STATE7_GOT_UNUSE1;break;case NRA12_PARSE_STATE::STATE7_GOT_UNUSE1:// PX4_INFO("STATE7_GOT_UNUSE1");// PX4_INFO("c=%x",c);*state = NRA12_PARSE_STATE::STATE8_GOT_UNUSE2;break;case NRA12_PARSE_STATE::STATE8_GOT_UNUSE2://  PX4_INFO("STATE8_GOT_UNUSE2");// PX4_INFO("c=%x",c);*state = NRA12_PARSE_STATE::STATE9_GOT_UNUSE3;break;case NRA12_PARSE_STATE::STATE9_GOT_UNUSE3:// PX4_INFO("STATE9_GOT_UNUSE3");// PX4_INFO("c=%x",c);*state = NRA12_PARSE_STATE::STATE10_GOT_UNUSE4;break;case NRA12_PARSE_STATE::STATE10_GOT_UNUSE4://  PX4_INFO("STATE10_GOT_UNUSE4");// PX4_INFO("c=%x",c);if(c==0x55){*state = NRA12_PARSE_STATE::STATE11_GOT_END1;}break;case NRA12_PARSE_STATE::STATE11_GOT_END1://  PX4_INFO("STATE11_GOT_END1");// PX4_INFO("c=%x",c);if(c==0x55){*state = NRA12_PARSE_STATE::STATE12_GOT_END2;unsigned int t1 = parserbuf[2];unsigned int t2 = parserbuf[1];t2 <<= 8;t2 += t1;if (t2 < 0xFFFFu) {*dist = ((float)t2) / 100;}//	 PX4_INFO("dist=%lf\n",(double)*dist);}else {*state = NRA12_PARSE_STATE::STATE0_UNSYNC;}break;}#ifdef NRA12_DEBUGprintf("state: NRA12_PARSE_STATE%s\n", parser_state[*state]);
#endifreturn ret;
}

nra12_parser.h如下:

enum class NRA12_PARSE_STATE {STATE0_UNSYNC = 0,STATE1_GOT_START1,STATE2_GOT_START2,STATE2_GOT_0C,STATE2_GOT_07,STATE3_GOT_Index,STATE4_GOT_Res,STATE5_GOT_DIST_H,STATE6_GOT_DIST_L,STATE7_GOT_UNUSE1,STATE8_GOT_UNUSE2,STATE9_GOT_UNUSE3,STATE10_GOT_UNUSE4,STATE11_GOT_END1,STATE12_GOT_END2
};int nra12_parse(char c, char *parserbuf, unsigned *parserbuf_index, NRA12_PARSE_STATE *state, float *dist);

修改src/drivers/drv_sensor.h
添加

#define DRV_DIST_DEVTYPE_NRA12      0xC2

修改boards/px4/fmu-v5/default.px4board
添加

CONFIG_COMMON_DISTANCE_SENSOR_NRA12=y

最后编译并将固件下载到飞控,将NRA12通过串口连接到UART&I2C B口,将参数SENS_NRA12_CFG设置成TELEM/SERIAL4,然后观察能观察到测距传感器的数据输出
在这里插入图片描述

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

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

相关文章

Servlet详解(从xml到注解)

文章目录 概述介绍作用 快速入门Servelt的执行原理执行流程&#xff1a;执行原理 生命周期概述API 服务器启动&#xff0c;立刻加载Servlet对象(理解)实现Servlet方式(三种)实现Servlet接口实现GenericServlet抽象类&#xff0c;只重写service方法实现HttpServlet实现类实现Htt…

蓝桥杯-路径之谜

题目描述 小明冒充X星球的骑士&#xff0c;进入了一个奇怪的城堡。城堡里面什么都没有&#xff0c;只有方形石头铺成的地面。 假设城堡的地面时n*n个方格。如下图所示。 按习俗&#xff0c;骑士要从西北角走到东南角。可以横向或者纵向移动&#xff0c;但是不能斜着走&#x…

整数的表示和运算

目录 无符号整数 有符号整数 原码表示 原码的缺点 原码-->反码-->补码的转换 原码,补码快速转换技巧(手算) 补码的加法计算 补码的减法计算 总结 无符号整数 无符号整数,即"自然数",0,1,2,3,4,.... C语言中的无符号整数: unsigned short a 1; //无符…

Spark Stream

一、Spark Streaming是什么 Spark Streaming 用于流式数据的处理。Spark Streaming 支持的数据输入源很多&#xff0c;例如&#xff1a;Kafka、Flume、Twitter、ZeroMQ 和简单的 TCP 套接字等等。数据输入后可以用 Spark 的高度抽象原语如&#xff1a;map、reduce、join、wind…

C++ | Leetcode C++题解之第67题二进制求和

题目&#xff1a; 题解&#xff1a; class Solution { public:string addBinary(string a, string b) {string ans;reverse(a.begin(), a.end());reverse(b.begin(), b.end());int n max(a.size(), b.size()), carry 0;for (size_t i 0; i < n; i) {carry i < a.siz…

算法学习系列(五十五):背包模型(三)

目录 引言一、潜水员二、背包问题求具体方案三、机器分配四、开心的今明五、金明的预算方案 引言 今天介绍的是背包模型&#xff0c;还是以题目的形式来介绍的。主要讲了背包问题求方案&#xff0c;就是由最优方案递推回去即可。还有就是一些比较经典的背包问题&#xff0c;其…

im即时通讯源码/仿微信app源码+php即时通讯源码带红包+客服+禁言等系统php+uniapp开发

即时通讯(IM)系统是现代互联网应用中不可或缺的一部分&#xff0c;它允许用户进行实时的文本、语音、视频交流。随着技术的发展&#xff0c;IM系统的功能越来越丰富&#xff0c;如红包、客服、禁言等。本文将探讨如何使用PHP语言开发一个功能完备的即时通讯系统&#xff0c;包括…

逻辑漏洞:Cookie脆弱性导致的逻辑漏洞

前几天学习了逻辑漏洞中的越权漏洞和支付漏洞&#xff0c;今天学习一下cookie脆弱性导致的逻辑漏洞 还是和之前一样&#xff0c;所有内容都是参考别的大佬总结好的&#xff0c;我只是在这里进行学习练习 1、cookie介绍 用户在客户端 (一般为浏览器) 中访问某个页面 &#xff0…

电脑崩溃了,之前备份的GHO文件怎么恢复到新硬盘?

前言 之前咱们说到用WinPE系统给电脑做一个GHO镜像备份&#xff0c;这个备份可以用于硬盘完全崩溃换盘的情况下使用。 那么这个GHO镜像文件怎么用呢&#xff1f; 咱们今天详细来讲讲&#xff01; 如果你的电脑系统硬盘崩溃了或者是坏掉了&#xff0c;那么就需要使用之前备份…

华为机考入门python3--(20)牛客20- 密码验证合格程序

分类&#xff1a;字符串 知识点&#xff1a; 遍历字符串的每个字符 for char in my_str: 可以直接比较字符范围 a < char < z 列表统计元素个数 my_list.count(elem) 寻找子串 my_str.find(sub_str) 题目来自【牛客】 import re import sysdef check_…

【算法】唯一分解定理及最lcm和gcd关系 宝石组合

前言 今天在做一道宝石组合的题目时了解到了这个定理&#xff0c;还是蛮有意思的。 思想 唯一分解定理&#xff1a; 对于任何正整数n&#xff0c;有 n p 1 a 1 p 2 a 2 . . . p k a k n p_1^{a1} \times p_2^{a2} \times ... \times p_k^{ak} np1a1​p2a2​...pkak​ …

C语言零基础快速入门视频教程

C语言零基础快速入门视频教程 介绍C语言C语言零基础视频教程领取教程下期更新预报 介绍C语言 C语言零基础快速入门&#xff1a;探索C语言的起源、特性与魅力 在编程世界中&#xff0c;C语言犹如一座古老而坚实的桥梁&#xff0c;连接着计算机科学的过去与现在。作为一门历史悠…

家庭用水安全新举措:保障自来水管和储水设施卫生

随着公众对家庭用水安全意识的提高&#xff0c;如何确保自来水管和楼顶储水罐的安全性和卫生已成为家庭生活中的重要议题。近期&#xff0c;专家针对此问题提出了一系列实用的注意事项和建议。 注意事项&#xff1a; 定期检查&#xff1a;专家强调&#xff0c;家庭应每季度至…

分布式事务—> seata

分布式事务之Seata 一、什么是分布式事务&#xff1f; 分布式事务是一种特殊类型的事务&#xff0c;它涉及多个分布式系统中的节点&#xff0c;包括事务的参与者、支持事务的服务器、资源服务器以及事务管理器。 在分布式事务中&#xff0c;一次大型操作通常由多个小操作组成…

如何查公网IP?

在网络通信中&#xff0c;每个设备都被分配一个独特的IP地址&#xff0c;用于在Internet上进行标识和通信。公网IP是指可以直接从Internet上访问的IP地址&#xff0c;也称为全局IP。通过查公网IP&#xff0c;我们可以了解我们的设备在Internet上的位置和连接状态。 2. 查公网IP…

vue3使用echarts做树图tree

vue3使用echarts做树图tree 1.安装echarts npm install echarts --save2.在main.js引入 import * as echarts from echarts // 全局方法 app.config.globalProperties.$echarts echarts3.使用 <div id"myChart" :style"{ width: 1000px, height: 1000px …

Django后台项目开发实战五

完成两个功能&#xff1a; HR 可以维护候选人信息面试官可以录入面试反馈 第五阶段 创建 interview 应用&#xff0c;实现候选人面试评估表的增删改功能&#xff0c;并且按照页面分组来展示不同的内容&#xff0c;如候选人基础信息&#xff0c;一面&#xff0c;二面的面试结…

[Linux][网络][传输层][UDP]详细讲解

目录 0.预备知识1.端口号的划分范围2.认识知名端口号3.netstat命令4.pidof 1.UDP协议端格式2.UDP特点3.面向数据报4.UDP的缓冲区5.UDP使用注意事项6.基于UDP的应用层协议 0.预备知识 1.端口号的划分范围 端口号的长度是16位&#xff0c;因此端口号的范围是0 ~ 65535 0 ~ 1023…

构建智能化商旅服务:酒店中台云服务架构设计与实践

随着商旅行业的不断发展和智能化趋势的兴起&#xff0c;酒店中台云服务成为了提升服务质量和效率的关键。本文将探讨酒店商旅中台云服务的架构设计与实现&#xff0c;介绍其关键特点和最佳实践&#xff0c;助力商旅行业迈向智能化未来。 1. **需求分析与场景设计&#xff1a;*…

ssm101珠宝首饰交易平台开发+jsp

珠宝首饰交易平台 摘 要 随着科学技术的飞速发展&#xff0c;各行各业都在努力与现代先进技术接轨&#xff0c;通过科技手段提高自身的优势&#xff1b;对于珠宝首饰交易平台当然也不能排除在外&#xff0c;随着网络技术的不断成熟&#xff0c;带动了珠宝首饰交易平台&#x…