交叉编译paho.mqqt.c
1、下载openssl-1.1.1g
./Configure linux-armv4 shared no-asm --prefix=/home//openssl-111g --cross-compile-prefix=arm-linux-gnueabihf-
1、下载 paho.mqtt.embedded-c https://github.com/eclipse/paho.mqtt.c.git
解压后在129行添加
CFLAGS += -I/home/openssl-111g/include
LDFLAGS += -L/home/openssl-111g/lib
CC=arm-linux-gnueabihf-gcc -lrt
CXX=arm-linux-gnueabihf-g++ -lrt
make编译
paho.mqtt.c/build/output下
lib 为库文件
src为头文件
在src下新建
mqtt_interface.h
//*****************************************************************************
//! file mqtt_interface.h
//! brief Paho MQTT to WIZnet Chip interface Header file.
//! details The process of porting an interface to use paho MQTT.
//! version 1.0.0
//! date 2016/12/06
//! par Revision history
//! <2016/12/06> 1st Release
//!
//! author Peter Bang & Justin Kim
//! copyright
//!
//! Copyright (c) 2016, WIZnet Co., LTD.
//! All rights reserved.
//!
//! Redistribution and use in source and binary forms, with or without
//! modification, are permitted provided that the following conditions
//! are met:
//!
//! * Redistributions of source code must retain the above copyright
//! notice, this list of conditions and the following disclaimer.
//! * Redistributions in binary form must reproduce the above copyright
//! notice, this list of conditions and the following disclaimer in the
//! documentation and/or other materials provided with the distribution.
//! * Neither the name of the <ORGANIZATION> nor the names of its
//! contributors may be used to endorse or promote products derived
//! from this software without specific prior written permission.
//!
//! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
//! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
//! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
//! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
//! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
//! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
//! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
//! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
//! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
//! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
//! THE POSSIBILITY OF SUCH DAMAGE.
//
//*****************************************************************************
/* MQTT subscribe Example.... W5500 + STM32F103(IoT board)
//Include: Board configuration
#include "IoTEVB.h"
//Include: MCU peripheral Library
#include "stm32f10x_rcc.h"
#include "stm32f10x.h"
//Include: W5500 iolibrary
#include "w5500.h"
#include "wizchip_conf.h"
#include "misc.h"
//Include: Internet iolibrary
#include "MQTTClient.h"
//Include: MCU Specific W5500 driver
#include "W5500HardwareDriver.h"
//Include: Standard IO Library
#include <stdio.h>
//Socket number defines
#define TCP_SOCKET 0
//Receive Buffer Size define
#define BUFFER_SIZE 2048
//Global variables
unsigned char targetIP[4] = {}; // mqtt server IP
unsigned int targetPort = 1883; // mqtt server port
uint8_t mac_address[6] = {};
wiz_NetInfo gWIZNETINFO = { .mac = {}, //user MAC
.ip = {}, //user IP
.sn = {},
.gw = {},
.dns = {},
.dhcp = NETINFO_STATIC};
unsigned char tempBuffer[BUFFER_SIZE] = {};
struct opts_struct
{
char* clientid;
int nodelimiter;
char* delimiter;
enum QoS qos;
char* username;
char* password;
char* host;
int port;
int showtopics;
} opts ={ (char*)"stdout-subscriber", 0, (char*)"n", QOS0, NULL, NULL, targetIP, targetPort, 0 };
// @brief messageArrived callback function
void messageArrived(MessageData* md)
{
unsigned char testbuffer[100];
MQTTMessage* message = md->message;
if (opts.showtopics)
{
memcpy(testbuffer,(char*)message->payload,(int)message->payloadlen);
*(testbuffer + (int)message->payloadlen + 1) = "n";
printf("%srn",testbuffer);
}
if (opts.nodelimiter)
printf("%.*s", (int)message->payloadlen, (char*)message->payload);
else
printf("%.*s%s", (int)message->payloadlen, (char*)message->payload, opts.delimiter);
}
// @brief 1 millisecond Tick Timer setting
void NVIC_configuration(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK);
SysTick_Config(72000);
NVIC_InitStructure.NVIC_IRQChannel = SysTick_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; // Highest priority
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
// @brief 1 millisecond Tick Timer Handler setting
void SysTick_Handler(void)
{
MilliTimer_Handler();
}
int main(void)
{
led_ctrl led1,led2;
int i;
int rc = 0;
unsigned char buf[100];
//Usart initialization for Debug.
USART1Initialze();
printf("USART initialized.nr");
I2C1Initialize();
printf("I2C initialized.nr");
MACEEP_Read(mac_address,0xfa,6);
printf("Mac addressnr");
for(i = 0 ; i < 6 ; i++)
{
printf("%02x ",mac_address[i]);
}
printf("nr");
//LED initialization.
led_initialize();
led1 = led2 = ON;
led2Ctrl(led2);
led1Ctrl(led1);
//W5500 initialization.
W5500HardwareInitilize();
printf("W5500 hardware interface initialized.nr");
W5500Initialze();
printf("W5500 IC initialized.nr");
//Set network informations
wizchip_setnetinfo(&gWIZNETINFO);
setSHAR(mac_address);
print_network_information();
Network n;
MQTTClient c;
NewNetwork(&n, TCP_SOCKET);
ConnectNetwork(&n, targetIP, targetPort);
MQTTClientInit(&c,&n,1000,buf,100,tempBuffer,2048);
MQTTPacket_connectData data = MQTTPacket_connectData_initializer;
data.willFlag = 0;
data.MQTTVersion = 3;
data.clientID.cstring = opts.clientid;
data.username.cstring = opts.username;
data.password.cstring = opts.password;
data.keepAliveInterval = 60;
data.cleansession = 1;
rc = MQTTConnect(&c, &data);
printf("Connected %drn", rc);
opts.showtopics = 1;
printf("Subscribing to %srn", "hello/wiznet");
rc = MQTTSubscribe(&c, "hello/wiznet", opts.qos, messageArrived);
printf("Subscribed %drn", rc);
while(1)
{
MQTTYield(&c, data.keepAliveInterval);
}
}
*/
#ifndef __MQTT_INTERFACE_H_
#define __MQTT_INTERFACE_H_
/*
* @brief MQTT MilliTimer handler
* @note MUST BE register to your system 1m Tick timer handler
*/
void MilliTimer_Handler(void);
/*
* @brief Timer structure
*/
typedef struct Timer Timer;
struct Timer {
unsigned long systick_period;
unsigned long end_time;
};
/*
* @brief Network structure
*/
typedef struct Network Network;
struct Network
{
int my_socket;
int (*mqttread) (Network*, unsigned char*, int, int);
int (*mqttwrite) (Network*, unsigned char*, int, int);
void (*disconnect) (Network*);
};
/*
* @brief Timer function
*/
void TimerInit(Timer*);
char TimerIsExpired(Timer*);
void TimerCountdownMS(Timer*, unsigned int);
void TimerCountdown(Timer*, unsigned int);
int TimerLeftMS(Timer*);
/*
* @brief Network interface porting
*/
int w5x00_read(Network*, unsigned char*, int, int);
int w5x00_write(Network*, unsigned char*, int, int);
void w5x00_disconnect(Network*);
void NewNetwork(Network* n, int sn);
int ConnectNetwork(Network*, char*, int);
#endif //__MQTT_INTERFACE_H_
mqtt_interface.c
//*****************************************************************************
//! file mqtt_interface.c
//! brief Paho MQTT to WIZnet Chip interface implement file.
//! details The process of porting an interface to use paho MQTT.
//! version 1.0.0
//! date 2016/12/06
//! par Revision history
//! <2016/12/06> 1st Release
//!
//! author Peter Bang & Justin Kim
//! copyright
//!
//! Copyright (c) 2016, WIZnet Co., LTD.
//! All rights reserved.
//!
//! Redistribution and use in source and binary forms, with or without
//! modification, are permitted provided that the following conditions
//! are met:
//!
//! * Redistributions of source code must retain the above copyright
//! notice, this list of conditions and the following disclaimer.
//! * Redistributions in binary form must reproduce the above copyright
//! notice, this list of conditions and the following disclaimer in the
//! documentation and/or other materials provided with the distribution.
//! * Neither the name of the <ORGANIZATION> nor the names of its
//! contributors may be used to endorse or promote products derived
//! from this software without specific prior written permission.
//!
//! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
//! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
//! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
//! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
//! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
//! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
//! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
//! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
//! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
//! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
//! THE POSSIBILITY OF SUCH DAMAGE.
//
//*****************************************************************************
#include "mqtt_interface.h"
#include "socket.h"
#include "MyOS.h"
unsigned long MilliTimer;
/*
* @brief MQTT MilliTimer handler
* @note MUST BE register to your system 1m Tick timer handler.
*/
void MilliTimer_Handler(void) {
MilliTimer++;
}
/*
* @brief Timer Initialize
* @param timer : pointer to a Timer structure
* that contains the configuration information for the Timer.
*/
void TimerInit(Timer* timer) {
timer->end_time = 0;
}
/*
* @brief expired Timer
* @param timer : pointer to a Timer structure
* that contains the configuration information for the Timer.
*/
char TimerIsExpired(Timer* timer) {
long left = timer->end_time - MilliTimer;
return (left < 0);
}
/*
* @brief Countdown millisecond Timer
* @param timer : pointer to a Timer structure
* that contains the configuration information for the Timer.
* timeout : setting timeout millisecond.
*/
void TimerCountdownMS(Timer* timer, unsigned int timeout) {
timer->end_time = MilliTimer + timeout;
}
/*
* @brief Countdown second Timer
* @param timer : pointer to a Timer structure
* that contains the configuration information for the Timer.
* timeout : setting timeout millisecond.
*/
void TimerCountdown(Timer* timer, unsigned int timeout) {
timer->end_time = MilliTimer + (timeout * 1000);
}
/*
* @brief left millisecond Timer
* @param timer : pointer to a Timer structure
* that contains the configuration information for the Timer.
*/
int TimerLeftMS(Timer* timer) {
long left = timer->end_time - MilliTimer;
return (left < 0) ? 0 : left;
}
/*
* @brief New network setting
* @param n : pointer to a Network structure
* that contains the configuration information for the Network.
* sn : socket number where x can be (0..7).
* @retval None
*/
void NewNetwork(Network* n, int sn) {
n->my_socket = sn;
n->mqttread = w5x00_read;
n->mqttwrite = w5x00_write;
n->disconnect = w5x00_disconnect;
}
/*
* @brief read function
* @param n : pointer to a Network structure
* that contains the configuration information for the Network.
* buffer : pointer to a read buffer.
* len : buffer length.
*/
int w5x00_read(Network* n, unsigned char* buffer, int len, int timeout_ms){
Timer tmr;
TimerInit(&tmr);
TimerCountdownMS(&tmr, timeout_ms);
while(!TimerIsExpired(&tmr)){
if(getSn_SR(n->my_socket) != SOCK_ESTABLISHED)
return -1;
if(getSn_RX_RSR(n->my_socket)>0)
return recv(n->my_socket, buffer, len);
MyOS_DlyHMSM(0,0,0,30);
}
return 0;
}
/*
* @brief write function
* @param n : pointer to a Network structure
* that contains the configuration information for the Network.
* buffer : pointer to a read buffer.
* len : buffer length.
*/
int w5x00_write(Network* n, unsigned char* buffer, int len, int timeout_ms){
return send(n->my_socket, buffer, len);
}
/*
* @brief disconnect function
* @param n : pointer to a Network structure
* that contains the configuration information for the Network.
*/
void w5x00_disconnect(Network* n){
disconnect(n->my_socket);
}
/*
* @brief connect network function
* @param n : pointer to a Network structure
* that contains the configuration information for the Network.
* ip : server iP.
* port : server port.
*/
int ConnectNetwork(Network* n, char* ip, int port)
{
uint8_t myport = 12345;
socket(n->my_socket,Sn_MR_TCP,myport,0);
connect(n->my_socket,ip,port);
}
然后在
记得在MQTTClient.h里略做修改。在
#include “MQTTPacket.h”
后面加上一行:
#include “mqtt_interface.h”
cmake: command not found
cmake --version
yum install -y cmake
build/output/libpaho-mqtt3a.so: undefined reference to `clock_gettime'
原因:缺少librt.so
编译的时候,加入-lrt即可。
CC=arm-linux-gnueabihf-gcc -lrt
CXX=arm-linux-gnueabihf-g++ -lrt
1、 下载ssl : openssl-1.0.1p.tar.gz http://www.openssl.org/source/
./Configure linux-armv4 shared no-asm --prefix=/home/openssl-101p --cross-compile-prefix=arm-linux-gnueabihf-
make && make install
2、下载 paho.mqtt.c-master
修改Makefile。在129行添加openssl的链接目录,注意改成你自己的路径。
CFLAGS += -I/home/openssl-101p/include
LDFLAGS += -L/home/openssl-101p/lib
修改CC ?=gcc 为
CC=arm-linux-gnueabihf-gcc -lrt
CXX=arm-linux-gnueabihf-g++ -lrt
make
这样会在当前目录创建build目录,进入build目录,你能看到output目录和一个版本头文件,进入output,你能看到库文件,examples和测试程序
头文件去src目录找
MQTTClient_connectOptions 未定义标识符
参考
交叉编译OpenSSL和paho.mqtt.c
https://blog.csdn.net/qq_39436605/article/details/82017454
/lib/libmosquitto.so.1: undefined reference to `SSL_CTX_set_alpn_protos'
https://www.nuomiphp.com/eplan/254258.html
undefined reference to `SSL_CTX_set_default_passwd_cb@OPENSSL_1_1_0'
样例
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "MQTTClient.h"
#if !defined(WIN32)
#include <unistd.h>
#else
#include <windows.h>
#endif
#define NUM_THREADS 2
#define ADDRESS "tcp://localhost:1883" //更改此处地址
#define CLIENTID "aaabbbccc_pub" //更改此处客户端ID
#define SUB_CLIENTID "aaabbbccc_sub" //更改此处客户端ID
#define TOPIC "topic01" //更改发送的话题
#define PAYLOAD "Hello Man, Can you see me ?!" //
#define QOS 1
#define TIMEOUT 10000L
#define USERNAME "test_user"
#define PASSWORD "jim777"
#define DISCONNECT "out"
int CONNECT = 1;
volatile MQTTClient_deliveryToken deliveredtoken;
void delivered(void *context, MQTTClient_deliveryToken dt)
{
printf("Message with token value %d delivery confirmed\n", dt);
deliveredtoken = dt;
}
int msgarrvd(void *context, char *topicName, int topicLen, MQTTClient_message *message)
{
int i;
char* payloadptr;
printf("Message arrived\n");
printf(" topic: %s\n", topicName);
printf(" message: ");
payloadptr = message->payload;
if(strcmp(payloadptr, DISCONNECT) == 0){
printf(" \n out!!");
CONNECT = 0;
}
for(i=0; i<message->payloadlen; i++)
{
putchar(*payloadptr++);
}
printf("\n");
MQTTClient_freeMessage(&message);
MQTTClient_free(topicName);
return 1;
}
void connlost(void *context, char *cause)
{
printf("\nConnection lost\n");
printf(" cause: %s\n", cause);
}
void *subClient(void *threadid){
long tid;
tid = (long)threadid;
printf("Hello World! It's me, thread #%ld!\n", tid);
MQTTClient client;
MQTTClient_connectOptions conn_opts = MQTTClient_connectOptions_initializer;
int rc;
int ch;
MQTTClient_create(&client, ADDRESS, SUB_CLIENTID,
MQTTCLIENT_PERSISTENCE_NONE, NULL);
conn_opts.keepAliveInterval = 20;
conn_opts.cleansession = 1;
conn_opts.username = USERNAME;
conn_opts.password = PASSWORD;
MQTTClient_setCallbacks(client, NULL, connlost, msgarrvd, delivered);
if ((rc = MQTTClient_connect(client, &conn_opts)) != MQTTCLIENT_SUCCESS)
{
printf("Failed to connect, return code %d\n", rc);
exit(EXIT_FAILURE);
}
printf("Subscribing to topic %s\nfor client %s using QoS%d\n\n"
"Press Q<Enter> to quit\n\n", TOPIC, CLIENTID, QOS);
MQTTClient_subscribe(client, TOPIC, QOS);
do
{
ch = getchar();
} while(ch!='Q' && ch != 'q');
MQTTClient_unsubscribe(client, TOPIC);
MQTTClient_disconnect(client, 10000);
MQTTClient_destroy(&client);
pthread_exit(NULL);
}
void *pubClient(void *threadid){
long tid;
tid = (long)threadid;
int count = 0;
printf("Hello World! It's me, thread #%ld!\n", tid);
//声明一个MQTTClient
MQTTClient client;
//初始化MQTT Client选项
MQTTClient_connectOptions conn_opts = MQTTClient_connectOptions_initializer;
//#define MQTTClient_message_initializer { {'M', 'Q', 'T', 'M'}, 0, 0, NULL, 0, 0, 0, 0 }
MQTTClient_message pubmsg = MQTTClient_message_initializer;
//声明消息token
MQTTClient_deliveryToken token;
int rc;
//使用参数创建一个client,并将其赋值给之前声明的client
MQTTClient_create(&client, ADDRESS, CLIENTID,
MQTTCLIENT_PERSISTENCE_NONE, NULL);
conn_opts.keepAliveInterval = 20;
conn_opts.cleansession = 1;
conn_opts.username = USERNAME;
conn_opts.password = PASSWORD;
//使用MQTTClient_connect将client连接到服务器,使用指定的连接选项。成功则返回MQTTCLIENT_SUCCESS
if ((rc = MQTTClient_connect(client, &conn_opts)) != MQTTCLIENT_SUCCESS)
{
printf("Failed to connect, return code %d\n", rc);
exit(EXIT_FAILURE);
}
char* payload = "mypayload";
pubmsg.payload = payload;
pubmsg.payloadlen = strlen(payload);
pubmsg.qos = QOS;
pubmsg.retained = 0;
while(CONNECT){
MQTTClient_publishMessage(client, TOPIC, &pubmsg, &token);
printf("Waiting for up to %d seconds for publication of %s\n"
"on topic %s for client with ClientID: %s\n",
(int)(TIMEOUT/1000), PAYLOAD, TOPIC, CLIENTID);
rc = MQTTClient_waitForCompletion(client, token, TIMEOUT);
printf("Message with delivery token %d delivered\n", token);
usleep(3000000L);
}
MQTTClient_disconnect(client, 10000);
MQTTClient_destroy(&client);
}
int main(int argc, char* argv[])
{
pthread_t threads[NUM_THREADS];
long t;
pthread_create(&threads[0], NULL, subClient, (void *)0);
pthread_create(&threads[1], NULL, pubClient, (void *)1);
pthread_exit(NULL);
}