1、參考鏈接 :http://www.nongnu.org/lwip/2_0_x/group__mqtt.html
2、首先移植好lwip,然后添加 lwip-2.0.2\src\apps\mqtt 文件下 的 mqtt.c 文件,如果有頭文件問題,清解決頭文件問題!
3、根據參考鏈接,做一下修改
下面代碼中的MQTT 服務器 是我自己搭建的,你也可以找一台Linux 主機搭建一個。。2017年4月24日09:10:19
/* * MQTT client for lwIP * Author: Erik Andersson * Details of the MQTT protocol can be found at: http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html * */ #include "oneNet_MQTT.h" #include "string.h" ip_addr_t mqttServerIpAddr; //1. Initial steps, reserve memory and make connection to server: //1.1: Provide storage //Static allocation: //下面這兩句轉移到 MAIN.c 中 // mqtt_client_t static_client; // example_do_connect(&static_client); //Dynamic allocation: // mqtt_client_t *client = mqtt_client_new(); // if(client != NULL) { // example_do_connect(&client); // } //1.2: Establish Connection with server void example_do_connect(mqtt_client_t *client) { struct mqtt_connect_client_info_t ci; err_t err; /* Setup an empty client info structure */ memset(&ci, 0, sizeof(ci)); /* Minimal amount of information required is client identifier, so set it here */ ci.client_id = "lwip_test"; // MQTT服務器地址為:59.110.142.105端口號為:1883 IP4_ADDR(&mqttServerIpAddr, 59, 110, 142, 105);//配置 MQTT 服務器地址 /* Initiate client and connect to server, if this fails immediately an error code is returned otherwise mqtt_connection_cb will be called with connection result after attempting to establish a connection with the server. For now MQTT version 3.1.1 is always used */ //MQTT 服務器進行連接 ,並注冊 “連接結果處理”的回調函數,2017年4月12日09:00:12 err = mqtt_client_connect(client, &mqttServerIpAddr, 1883, mqtt_connection_cb, 0, &ci); /* For now just print the result code if something goes wrong */ if(err != ERR_OK) { printf("mqtt_connect return %d\n", err); } } //Connection to server can also be probed by calling mqtt_client_is_connected(client) //----------------------------------------------------------------- //2. Implementing the connection status callback //執行連接狀態 的 回調函數 static void mqtt_connection_cb(mqtt_client_t *client, void *arg, mqtt_connection_status_t status) { err_t err; if(status == MQTT_CONNECT_ACCEPTED) { printf("mqtt_connection_cb: Successfully connected\n"); /* Setup callback for incoming publish requests */ //注冊 消息推送 回調函數 以及消息數據到來的處理函數 mqtt_set_inpub_callback(client, mqtt_incoming_publish_cb, mqtt_incoming_data_cb, arg); /* Subscribe to a topic named "subtopic" with QoS level 2, call mqtt_sub_request_cb with result */ err = mqtt_subscribe(client, "subtopic", 2, mqtt_sub_request_cb, arg); if(err != ERR_OK) { printf("mqtt_subscribe return: %d\n", err); } } else { printf("mqtt_connection_cb: Disconnected, reason: %d\n", status); /* Its more nice to be connected, so try to reconnect */ example_do_connect(client); } } void mqtt_sub_request_cb(void *arg, err_t result) { /* Just print the result code here for simplicity, normal behaviour would be to take some action if subscribe fails like notifying user, retry subscribe or disconnect from server */ printf("Subscribe result: %d\n", result); } //----------------------------------------------------------------- //3. Implementing callbacks for incoming publish and data /* The idea is to demultiplex topic and create some reference to be used in data callbacks Example here uses a global variable, better would be to use a member in arg If RAM and CPU budget allows it, the easiest implementation might be to just take a copy of the topic string and use it in mqtt_incoming_data_cb */ //這兩個函數 一個 處理 消息頭 一個 處理 具體的 數據 static int inpub_id; static void mqtt_incoming_publish_cb(void *arg, const char *topic, u32_t tot_len) { //消息來了之后,先進入這里用於判斷 是什么主題 的,2017年4月20日09:25:51 printf("Incoming publish at topic \" %s \" with total length %u\r\n", topic, (unsigned int)tot_len); /* Decode topic string into a user defined reference */ if(strcmp(topic, "subtopic") == 0) { inpub_id = 0; } else if(topic[0] == 'A') { /* All topics starting with 'A' might be handled at the same way */ inpub_id = 1; } else { /* For all other topics */ inpub_id = 2; } } static void mqtt_incoming_data_cb(void *arg, const u8_t *data, u16_t len, u8_t flags) { //消息來了之后先判斷主題 上面那個函數,然后在這里是根據不同的主題,進行不同的處理 uint8_t tempBuff[20]={0}; uint8_t i; //數據復制到到緩沖區,並加 字符‘0’結尾,因為 發送工具只能發送 字符 不能發送字符串,2017年4月20日09:24:43 for(i=0;i<len;i++) { tempBuff[i]=data[i]; } tempBuff[i]=0; printf("Incoming publish payload with length %d, flags %u\n", len, (unsigned int)flags); if(flags & MQTT_DATA_FLAG_LAST) { /* Last fragment of payload received (or whole part if payload fits receive buffer See MQTT_VAR_HEADER_BUFFER_LEN) */ /* Call function or do action depending on reference, in this case inpub_id */ if(inpub_id == 0) { /* Don't trust the publisher, check zero termination */ if(tempBuff[len] == 0) { printf("mqtt_incoming_data_cb: %s\n", (const char *)data); } } else if(inpub_id == 1) { /* Call an 'A' function... */ } else { printf("mqtt_incoming_data_cb: Ignoring payload...\n"); } } else { /* Handle fragmented payload, store in buffer, write to file or whatever */ } } //----------------------------------------------------------------- //4. Using outgoing publish //使用 向外推送消息 //MQTT傳輸的消息分為:主題(Topic)和負載(payload)兩部分 void example_publish(mqtt_client_t *client, void *arg) { const char *pub_payload= "Hello,MQTT!\r\n";//推送的有效數據(負載) err_t err; /* * 最多一次,這一級別會發生消息丟失或重復,消息發布依賴於底層TCP/IP網絡。即:<=1 * 至多一次,這一級別會確保消息到達,但消息可能會重復。即:>=1 * 只有一次,確保消息只有一次到達。即:=1。在一些要求比較嚴格的計費系統中,可以使用此級別 */ u8_t qos = 2; /* 0 1 or 2, see MQTT specification */ //=0 的意思應該是不保留有效負載(有效數據) u8_t retain = 0; /* No don't retain such crappy payload... */ err = mqtt_publish(client, "pub_topic", pub_payload, strlen(pub_payload), qos, retain, mqtt_pub_request_cb, arg); if(err != ERR_OK) { printf("Publish err: %d.\r\n", err); } else { printf("Publish Success.\r\n"); } } /* Called when publish is complete either with sucess or failure */ //推送消息完成后 的 回調函數 void mqtt_pub_request_cb(void *arg, err_t result) { if(result != ERR_OK) { printf("Publish result: %d\n", result); } } //----------------------------------------------------------------- //5. Disconnecting //Simply call mqtt_disconnect(client)
static_client.conn_state=0; /* Initialize MQTT client */ example_do_connect(&static_client); while(1) { example_publish(&static_client,(void *)mqtt_pub_request_cb); /* vTaskDelayUntil是絕對延遲,vTaskDelay是相對延遲。*/ vTaskDelay(2000); }
上面 的服務器 地址 今天 已經 到期了 ,阿里 的 太貴了 沒錢 續費了 哎 2017年6月26日17:15:40