mosquitto移植到AM335x+Linux系统

mosquitto移植到AM335x+Linux系统

1. 概述

本文档详细介绍如何将mosquitto 2.0.14版本移植到基于AM335x处理器的Linux系统中。mosquitto是一个实现了MQTT协议版本5.0、3.1.1和3.1的开源消息代理和客户端实现库。本文将介绍mosquitto库的配置、编译以及运行过程,包括依赖库的处理、交叉编译环境的配置等内容。整个项目使用CMake作为构建系统。

1.1 开发环境

  • 硬件平台:AM335x处理器
  • 操作系统:Linux 3.2
  • mosquitto版本:2.0.14
  • 构建工具:CMake 3.16+
  • 交叉编译工具链:arm-arago-linux-gnueabi-gcc 4.5.3
  • 依赖库:
    • OpenSSL 1.1.1w(用于TLS支持)
    • cJSON 1.7.15(用于WebSocket支持)
  • 项目源码:https://gitcode.com/am335xt3/lvgl/tree/main/thirdpart/mosquitto

2. 交叉编译环境配置

2.1 工具链配置

项目使用arm-arago-linux-gnueabi工具链进行交叉编译。在toolchain.cmake中配置如下:

# toolchain.cmake

# 设置目标系统名称
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR arm)

# 指定交叉编译器的路径
set(CROSS_SYSROOT /opt/am335xt3-cross-devkit/arm-arago-linux-gnueabi)
set(CROSS_COMPILE_PATH /opt/am335xt3-cross-devkit/bin)
set(CROSS_PREFIX /opt/am335xt3-cross-devkit/bin/arm-arago-linux-gnueabi-)
set(CMAKE_C_COMPILER /opt/am335xt3-cross-devkit/bin/arm-arago-linux-gnueabi-gcc)
set(CMAKE_CXX_COMPILER /opt/am335xt3-cross-devkit/bin/arm-arago-linux-gnueabi-g++)
set(CMAKE_ASM_COMPILER /opt/am335xt3-cross-devkit/bin/arm-arago-linux-gnueabi-as)
set(CMAKE_AR  /opt/am335xt3-cross-devkit/bin/arm-arago-linux-gnueabi-ar)
set(CROSS_COMPILE_INCLUDE_PATH /opt/am335xt3-cross-devkit/arm-arago-linux-gnueabi/sysroot/usr/include)

set(CMAKE_INSTALL_PREFIX ${CMAKE_BINARY_DIR}/am335xt3_install)
set(CMAKE_INTERNAL_INSTALL_PREFIX ${CMAKE_BINARY_DIR}/am335xt3_internal_install)

set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lm -ldl")

# 指定库的查找路径
set(CMAKE_LIBRARY_PATH ${CMAKE_INTERNAL_INSTALL_PREFIX}/lib)

# 设置查找路径
set(CMAKE_FIND_ROOT_PATH ${CJSON_ROOT} ${OPENSSL_ROOT})

# 指定查找规则
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)

# 禁用 CMake 的默认查找路径(如系统路径 /usr 和 /lib)
set(CMAKE_FIND_NO_PACKAGE_PREFIX_PATH TRUE)

3. 依赖库移植

3.1 cJSON库移植

cJSON库是一个轻量级的JSON解析库,在本项目中使用CMake进行构建。

3.1.1 CMake配置

在thirdpart/cJSON-1.7.15/CMakeLists.txt中已经包含了完整的构建配置,无需额外修改。主要配置如下:

project(cJSON VERSION 1.7.15 LANGUAGES C)

add_library(cjson
    cJSON.c
    cJSON_Utils.c
)

target_include_directories(cjson
    PUBLIC
    $
)

3.2 OpenSSL库移植

OpenSSL库用于提供加密和SSL/TLS功能,是mosquitto的重要依赖。

3.2.1 CMake配置

在thirdpart/openssl/CMakeLists.txt中配置OpenSSL的编译选项:

project(openssl)

# 设置OpenSSL源码目录
set(OPENSSL_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/openssl-1.1.1w)

# 设置编译选项
set(OPENSSL_CONFIG_OPTIONS
    shared
    no-ssl3
    --prefix=${CMAKE_INTERNAL_INSTALL_PREFIX}
    --openssldir=${CMAKE_INTERNAL_INSTALL_PREFIX}
    linux-armv4
    -DL_ENDIAN
)

# 将列表转换为空格分隔的字符串
string(REPLACE ";" " " OPENSSL_CONFIG_OPTIONS_STR "${OPENSSL_CONFIG_OPTIONS}")

# 设置环境变量
set(ENV{CC} "${CMAKE_C_COMPILER}")
set(ENV{AR} "${CMAKE_AR}")
set(ENV{RANLIB} "${CMAKE_RANLIB}")
set(ENV{PATH} "${CROSS_COMPILE_PATH}:$ENV{PATH}")

# 配置OpenSSL
add_custom_command(
    OUTPUT ${OPENSSL_SOURCE_DIR}/Makefile
    COMMAND ${CMAKE_COMMAND} -E env PATH=$ENV{PATH} ./Configure linux-armv4 --cross-compile-prefix=arm-arago-linux-gnueabi- --prefix=${CMAKE_INTERNAL_INSTALL_PREFIX} --openssldir=${CMAKE_INTERNAL_INSTALL_PREFIX} shared no-ssl3 no-async -DL_ENDIAN threads -lpthread
    WORKING_DIRECTORY ${OPENSSL_SOURCE_DIR}
    COMMENT "Configuring OpenSSL"
)

# 编译OpenSSL
add_custom_command(
    OUTPUT ${OPENSSL_SOURCE_DIR}/libssl.a ${OPENSSL_SOURCE_DIR}/libcrypto.a
    COMMAND ${CMAKE_COMMAND} -E env PATH=$ENV{PATH} $(MAKE)
    DEPENDS ${OPENSSL_SOURCE_DIR}/Makefile
    WORKING_DIRECTORY ${OPENSSL_SOURCE_DIR}
    COMMENT "Building OpenSSL"
)

# 创建自定义目标
add_custom_target(openssl ALL
    DEPENDS ${OPENSSL_SOURCE_DIR}/libssl.a ${OPENSSL_SOURCE_DIR}/libcrypto.a
)

# 安装规则
add_custom_target(openssl_install
    COMMAND ${CMAKE_COMMAND} -E env PATH=$ENV{PATH} $(MAKE) install_sw
    WORKING_DIRECTORY ${OPENSSL_SOURCE_DIR}
    COMMENT "Installing OpenSSL"
    DEPENDS openssl
)

注意:为了避免随机数生成导致的阻塞问题,建议在系统中配置使用/dev/urandom作为随机数源。

4. mosquitto移植

4.1 源码准备

mosquitto源码位于thirdpart/mosquitto/mosquitto-2.0.14/目录下。

4.2 CMake配置

在thirdpart/mosquitto/CMakeLists.txt中配置mosquitto的编译选项:

project(mosquittomgr)


set(OPENSSL_INCLUDE_DIR ${CMAKE_INTERNAL_INSTALL_PREFIX}/include)
set(OPENSSL_LIBRARIES ${CMAKE_INTERNAL_INSTALL_PREFIX}/lib/libssl.so ${CMAKE_INTERNAL_INSTALL_PREFIX}/lib/libcrypto.so)

add_subdirectory(mosquitto-2.0.14)

# 安装 mosquitto.conf 脚本到 etc 目录
install(
    FILES mosquitto.conf
    DESTINATION etc/mosquitto
)

注释掉thirdpart/mosquitto/mosquitto-2.0.14/CMakeLists.txt中

#find_package(OpenSSL REQUIRED ${CMAKE_INTERNAL_INSTALL_PREFIX})

#FIND_PACKAGE(cJSON)

PS:1.OpenSSL已经在上一级的cmake定义OPENSSL_INCLUDE_DIR和OPENSSL_LIBRARIES
2.cJSON是使用cmake编译的,所以不需要再使用FIND_PACKAGE(cJSON)

4.3 类型重定义问题解决

在编译过程中,可能会遇到mosquitto_property和mosquitto_plugin_id_t类型重复定义的问题。这是因为这些类型在mosquitto_broker.h和mosquitto.h中都有定义。解决方法如下:

  1. 在mosquitto-2.0.14/include/mosquitto_broker.h文件中,找到这些类型的定义部分。

  2. 添加条件编译宏来避免重复定义:

mosquitto_property重定义部分代码:

# mosquitto_broker.h
#ifndef MOSQ_PROP_TYPE_DEFINED
#define MOSQ_PROP_TYPE_DEFINED
typedef struct mqtt5__property mosquitto_property;
#endif

# mosquitto.h
#ifndef MOSQ_PROP_TYPE_DEFINED
#define MOSQ_PROP_TYPE_DEFINED
typedef struct mqtt5__property mosquitto_property;
#endif

mosquitto_plugin_id_t重定义部分代码:

// mosquitto_broker.h
#ifndef MOSQ_PLUGIN_ID_TYPE_DEFINED
#define MOSQ_PLUGIN_ID_TYPE_DEFINED
typedef struct mosquitto_plugin_id_t mosquitto_plugin_id_t;
#endif

// mosquitto_broker_internal.h

//typedef struct mosquitto_plugin_id_t{
//	struct mosquitto__listener *listener;
//};
struct mosquitto_plugin_id_t{
	struct mosquitto__listener *listener;
};

#ifndef MOSQ_PLUGIN_ID_TYPE_DEFINED
#define MOSQ_PLUGIN_ID_TYPE_DEFINED
typedef struct mosquitto_plugin_id_t mosquitto_plugin_id_t;
#endif

这样修改后,这些类型只会被定义一次,避免了重复定义导致的编译错误。

5. mosquitto测试

5.1 mosquitto测试配置

在/etc/mosquitto/mosquitto.conf中配置mosquitto的基本配置:

# mosquitto.conf
listener 1883 192.168.2.177

user root

allow_anonymous true

log_dest file /var/log/mosquitto.log
log_type all
log_timestamp true

5.2 基本测试命令

  1. 启动mosquitto服务器:
./mosquitto -c /etc/mosquitto/mosquitto.conf
  1. 订阅主题:
./mosquitto_sub -t test/topic -h 192.168.2.177 -p 1883 -v
  1. 发布消息:
./mosquitto_pub -t test/topic -h 192.168.2.177 -p 1883 -m "hello world"

6 常见问题解决

6.1 OpenSSL随机数生成阻塞

问题描述:mosquitto服务在接收订阅连接请求时,使用OpenSSL的RAND_bytes函数生成client id时可能导致阻塞。

解决方法:配置OpenSSL使用/dev/urandom作为随机数源

6.2 连接授权错误

问题描述:出现"Connection error: Connection Refused: not authorised"错误。

解决方法

  1. 修改mosquitto.conf文件,设置:
allow_anonymous true
  1. 或者配置密码文件:
allow_anonymous false
password_file /path/to/mosquitto.passwd

7. 参考文档

  1. mosquitto官方文档:https://mosquitto.org/documentation/
  2. OpenSSL官方文档:https://www.openssl.org/docs/
  3. cJSON文档:https://github.com/DaveGamble/cJSON

你可能感兴趣的:(AM335x,嵌入式Linux,MQTT,linux,物联网,iot)