wifi配置
需要在app_config.h文件中定义USE_DEMO_WIFI_TEST,工程会在wifi_demo_task.c文件中自动启动wifi相关的任务, 我们将工程配置为连接外部网络STA模式
默认工程会使用如下账号密码
当wifi任务启动之后,我们可以通过调用如下函数,让芯片连接上外部的网络
wifi_enter_sta_mode(str_ssid, str_pwd);
TCP通讯
socket初始化
首先需要初始化socket,并指定协议
#define SERVER_TCP_IP "192.168.3.100" //服务端ip#define SERVER_TCP_PORT 9090 //服务端端口号static int tcp_client_init(const char *server_ip, const int server_port){//struct sockaddr_in local;struct sockaddr_in dest;//创建socketsock = sock_reg(AF_INET, SOCK_STREAM, 0, NULL, NULL);if (sock == NULL) {printf("sock_reg fail.\n");return -1;}//连接指定地址服务端dest.sin_family = AF_INET;dest.sin_addr.s_addr = inet_addr(server_ip);dest.sin_port = htons(server_port);if (0 != sock_connect(sock, (struct sockaddr *)&dest, sizeof(struct sockaddr_in))) {printf("sock_connect fail.\n");sock_unreg(sock);return -1;}return 0;}
初始化调用的逻辑,很简单,只需要指定IP地址和端口号即可
err = tcp_client_init(SERVER_TCP_IP, SERVER_TCP_PORT);if (err) {printf("tcp_client_init err!");return;}
发送数据
//发送数据static int tcp_send_data(const void *sock_hdl, const void *buf, const u32 len){return sock_send(sock_hdl, buf, len, 0);}
接收数据
//接收数据static int tcp_recv_data(const void *sock_hdl, void *buf, u32 len){return sock_recvfrom(sock_hdl, buf, len, 0, NULL, NULL);}
接收数据代码
for (;;) {recv_len = tcp_recv_data(sock, recv_buf, sizeof(recv_buf));if ((recv_len != -1) && (recv_len != 0)) {recv_buf[recv_len] = '\0';printf("Received %d bytes, data: %s\n\r", recv_len, recv_buf);tcp_send_data(sock, "Data received successfully!", strlen("Data received successfully!"));} else {printf("sock_recvfrom err!");break;}}
完整示例代码:
客户端:
#include "sock_api/sock_api.h"#include "app_config.h"#include "system/includes.h"#include "wifi/wifi_connect.h"#include "lwip.h"#include "lwip/sockets.h"#include "lwip/netdb.h"#ifdef USE_ICHEIMA_WIFI#include "itheima.h"static void *sock = NULL;#define SERVER_TCP_IP "192.168.3.100" //服务端ip#define SERVER_TCP_PORT 9090 //服务端端口号static int tcp_client_init(const char *server_ip, const int server_port){//struct sockaddr_in local;struct sockaddr_in dest;//创建socketsock = sock_reg(AF_INET, SOCK_STREAM, 0, NULL, NULL);if (sock == NULL) {printf("sock_reg fail.\n");return -1;}//连接指定地址服务端dest.sin_family = AF_INET;dest.sin_addr.s_addr = inet_addr(server_ip);dest.sin_port = htons(server_port);if (0 != sock_connect(sock, (struct sockaddr *)&dest, sizeof(struct sockaddr_in))) {printf("sock_connect fail.\n");sock_unreg(sock);return -1;}return 0;}//发送数据static int tcp_send_data(const void *sock_hdl, const void *buf, const u32 len){return sock_send(sock_hdl, buf, len, 0);}//接收数据static int tcp_recv_data(const void *sock_hdl, void *buf, u32 len){return sock_recvfrom(sock_hdl, buf, len, 0, NULL, NULL);}//tcp client任务static void tcp_client_task(void *priv){int err;char *payload = "Please send me some data!";char recv_buf[1024];int recv_len;int send_len;err = tcp_client_init(SERVER_TCP_IP, SERVER_TCP_PORT);if (err) {printf("tcp_client_init err!");return;}send_len = tcp_send_data(sock, payload, strlen(payload));if (send_len == -1) {printf("sock_sendto err!");sock_unreg(sock);return;}for (;;) {recv_len = tcp_recv_data(sock, recv_buf, sizeof(recv_buf));if ((recv_len != -1) && (recv_len != 0)) {recv_buf[recv_len] = '\0';printf("Received %d bytes, data: %s\n\r", recv_len, recv_buf);tcp_send_data(sock, "Data received successfully!", strlen("Data received successfully!"));} else {printf("sock_recvfrom err!");break;}}if (sock) {sock_unreg(sock);sock = NULL;}}// 将串口接收到的数据通过串口发送出去static void tcp_client_uart2wifi_task(void *priv){int len=0;uint8_t recv_buf[1024];printf("tcp_client_uart2wifi_task start>>>>>>>>>>>>>>>>>\r\n");while(1){len=icheima_uart_read_data(recv_buf);printf("\n uart recv len = %d\n", len);if(len > 0){printf("\n uart recv len = %d\n", len);recv_buf[len] = '\0';//把串口接收到的数据发送回去tcp_send_data(sock,recv_buf,len);memset(recv_buf, 0, sizeof(recv_buf));}else{//printf("uart recv error len = %d\n", len);}}}// 将wifi接收到的数据,发送给串口static void tcp_client_wifi2uart_task(void *priv){int err;char *payload = "Please send me some data!";char recv_buf[1024];int recv_len;if(!sock){printf("tcp_client_wifi2uart_task sock error>>>>>>>>>>>>>>\r\n");}int send_len = tcp_send_data(sock, payload, strlen(payload));if (send_len == -1) {printf("sock_sendto err!");sock_unreg(sock);return;}printf("tcp_client_wifi2uart_task start>>>>>>>>>>>>>>\r\n");while(1){recv_len = tcp_recv_data(sock, recv_buf, sizeof(recv_buf));if ((recv_len != -1) && (recv_len != 0)) {recv_buf[recv_len] = '\0';// 将数据发送给串口icheima_uart_send_data(recv_buf, recv_len);printf("Received %d bytes, data:%s\n", recv_len, recv_buf);memset(recv_buf, 0, sizeof(recv_buf));} else {printf("sock_recvfrom err!");break;}}if (sock) {sock_unreg(sock);sock = NULL;}}static void tcp_client_start(void *priv){enum wifi_sta_connect_state state;while (1) {printf("Connecting to the network...\n");state = wifi_get_sta_connect_state() ;if (WIFI_STA_NETWORK_STACK_DHCP_SUCC == state) {printf("Network connection is successful!\n");break;}os_time_dly(1000);}// wifi 初始化int err = tcp_client_init(SERVER_TCP_IP, SERVER_TCP_PORT);if (err) {printf("tcp_client_init err!");return;}// 初始化串口icheima_uart_init("uart1");os_task_create(tcp_client_wifi2uart_task, NULL, 1, 1000, 0, "tcp_client_wifi2uart_task");os_task_create(tcp_client_uart2wifi_task, NULL, 1, 1000, 0, "tcp_client_uart2wifi_task");/*if (thread_fork("tcp_client_uart2wifi_task", 10, 1024, 0, NULL, tcp_client_uart2wifi_task, NULL) != OS_NO_ERR) {printf("thread fork fail\n");}*/}//应用程序入口,需要运行在STA模式下void c_main(void *priv){if (thread_fork("tcp_client_start", 10, 512, 0, NULL, tcp_client_start, NULL) != OS_NO_ERR) {printf("thread fork fail\n");}}late_initcall(c_main);#endif
服务器端:
import socketimport threadingimport time# 处理客户端的请求操作def handle_client_request(service_client_socket, ip_port):# 循环接收客户端发送的数据while True:# 接收客户端发送的数据recv_data = service_client_socket.recv(1024)# 容器类型判断是否有数据可以直接使用if语句进行判断,如果容器类型里面有数据表示条件成立,否则条件失败# 容器类型: 列表、字典、元组、字符串、set、range、二进制数据if recv_data:print(recv_data.decode("utf8"), ip_port)# 回复service_client_socket.send("ok,hello...".encode("utf8"))time.sleep(3)else:print("客户端下线了:", ip_port)break# 终止和客户端进行通信service_client_socket.close()if __name__ == '__main__':# 创建tcp服务端套接字tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)# 设置端口号复用,让程序退出端口号立即释放tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)# 绑定端口号tcp_server_socket.bind(("", 9090))# 设置监听, listen后的套接字是被动套接字,只负责接收客户端的连接请求tcp_server_socket.listen(128)# 循环等待接收客户端的连接请求while True:# 等待接收客户端的连接请求service_client_socket, ip_port = tcp_server_socket.accept()print("客户端连接成功:", ip_port)# 当客户端和服务端建立连接成功以后,需要创建一个子线程,不同子线程负责接收不同客户端的消息sub_thread = threading.Thread(target=handle_client_request, args=(service_client_socket, ip_port))# 设置守护主线程sub_thread.setDaemon(True)# 启动子线程sub_thread.start()# tcp服务端套接字可以不需要关闭,因为服务端程序需要一直运行# tcp_server_socket.close()
MQTT协议
MQTT(Message Queuing Telemetry Transport)是一种轻量级的消息传输协议,设计用于在低带宽和不稳定网络环境下进行高效的通信。以下是MQTT协议的主要特点:
发布/订阅模式:MQTT采用发布/订阅模式,其中客户端可以订阅一个或多个主题(Topic),而服务器则负责将消息发布到这些主题。这种模式使得多个客户端可以同时接收到感兴趣的消息。
轻量级:MQTT协议非常轻量级,协议头部信息很小,有效减少了网络传输的开销和数据流量。这使得MQTT非常适合在低带宽和有限资源的设备上使用,例如物联网设备。
QoS级别:MQTT支持三个不同的消息传输质量(QoS)级别:0、1和2。QoS级别决定了消息传输的可靠性和保证程度。较高的QoS级别会增加通信开销,但可以提供更可靠的消息传输。
可靠性和持久性:MQTT协议具有可靠性和持久性机制。客户端可以选择是否要求服务器保留未传递的消息,以便在客户端重新连接时重新发送。这确保了即使在网络中断或重新连接时,消息也不会丢失。
安全性:MQTT协议支持使用TLS/SSL进行加密和身份验证,以确保通信的安全性。这对于保护敏感数据和防止未经授权的访问非常重要。
总结而言,MQTT协议是一种灵活、可靠且适用于物联网应用的通信协议。它具有低开销、轻量级和可扩展等特点,使得它成为物联网设备之间进行高效通信的理想选择。
阿里云配置
开通公共实例
新建产品
单击创建产品
填入产品名称
选择产品类别


Python设备
参考文档:
https://help.aliyun.com/zh/iot/developer-reference/configure-tsl-models-2?spm=a2c4g.11186623.0.0.47e03475UYpVCc
https://help.aliyun.com/zh/iot/use-cases/use-the-paho-mqtt-library-for-python-to-connect-a-device-to-iot-platform
参数定义
productKey="k0ejuKHBeSm"deviceName="Dx2loZ2kr3e7EnhzBKZD"deviceSecret="7b62a2dbb171a55b0a3cb29c1427de2a"clientId = "Dx2loZ2kr3e7EnhzBKZD"subTopic = f"/sys/{productKey}/{deviceName}/thing/event/property/post_reply"pubTopic = f"/sys/{productKey}/{deviceName}/thing/event/property/post"
python发布
def publish_message():# publish 5 messages to pubTopic("/a1LhUsK****/python***/user/update")data = {"id": "123","version": "1.0","params": {"PowerSwitch": 1,"CurrentTemperature": 27.6},"method": "thing.event.property.post"}for i in range(5):data["params"]["CurrentTemperature"] = 23.6+imessage = json.dumps(data)client.publish(pubTopic, message)print("publish msg: " + str(i))print("publish msg: " + message)time.sleep(2)
python订阅
def subscribe_topic():# subscribe to subTopic("/a1LhUsK****/python***/user/get") and request messages to be deliveredclient.subscribe(subTopic)print("subscribe topic: " + subTopic)
完整示例
import jsonimport timeimport paho.mqtt.client as mqttfrom MqttSign import AuthIfo# set the device info, include product key, device name, and device secretproductKey="k0ejuKHBeSm"deviceName="Dx2loZ2kr3e7EnhzBKZD"deviceSecret="7b62a2dbb171a55b0a3cb29c1427de2a"clientId = "Dx2loZ2kr3e7EnhzBKZD"# set timestamp, clientid, subscribe topic and publish topictimeStamp = str((int(round(time.time() * 1000))))subTopic = f"/sys/{productKey}/{deviceName}/thing/event/property/post_reply"subTopic1 = f"/sys/{productKey}/{deviceName}/thing/service/property/set"pubTopic = f"/sys/{productKey}/{deviceName}/thing/event/property/post"# set host, porthost = productKey + ".iot-as-mqtt.cn-shanghai.aliyuncs.com"# instanceId = "***"# host = instanceId + ".mqtt.iothub.aliyuncs.com"port = 1883# set tls crt, keepalivetls_crt = "root.crt"keepAlive = 300# calculate the login auth info, and set it into the connection optionsm = AuthIfo()m.calculate_sign_time(productKey, deviceName, deviceSecret, clientId, timeStamp)m.calculate_sign(productKey,deviceName,deviceSecret,clientId)client = mqtt.Client(m.mqttClientId)client.username_pw_set(username=m.mqttUsername, password=m.mqttPassword)client.tls_set(tls_crt)print(f"clientid:{m.mqttClientId}")print(f"username:{m.mqttUsername}")print(f"password:{m.mqttPassword}")print(f"pub_topic:{pubTopic}")print(f"subTopic:{subTopic}")print(f"subTopic1:{subTopic1}")def on_connect(client, userdata, flags, rc):if rc == 0:print("Connect aliyun IoT Cloud Sucess")else:print("Connect failed... error code is:" + str(rc))def on_message(client, userdata, msg):topic = msg.topicpayload = msg.payload.decode()print("receive message ---------- topic is : " + topic)print("receive message ---------- payload is : " + payload)if ("thing/service/property/set" in topic):on_thing_prop_changed(client, msg.topic, msg.payload)def on_thing_prop_changed(client, topic, payload):post_topic = topic.replace("service","event")post_topic = post_topic.replace("set","post")Msg = json.loads(payload)params = Msg['params']post_payload = "{\"params\":" + json.dumps(params) + "}"print("reveice property_set command, need to post ---------- topic is: " + post_topic)print("reveice property_set command, need to post ---------- payload is: " + post_payload)client.publish(post_topic, post_payload)def connect_mqtt():client.connect(host, port, keepAlive)return clientdef publish_message():# publish 5 messages to pubTopic("/a1LhUsK****/python***/user/update")data = {"id": "123","version": "1.0","params": {"PowerSwitch": 1,"CurrentTemperature": 27.6},"method": "thing.event.property.post"}for i in range(5):data["params"]["CurrentTemperature"] = 23.6+imessage = json.dumps(data)client.publish(pubTopic, message)print("publish msg: " + str(i))print("publish msg: " + message)time.sleep(2)def subscribe_topic():# subscribe to subTopic("/a1LhUsK****/python***/user/get") and request messages to be deliveredclient.subscribe(subTopic)print("subscribe topic: " + subTopic)client.on_connect = on_connectclient.on_message = on_messageclient = connect_mqtt()client.loop_start()time.sleep(2)subscribe_topic()publish_message()while True:time.sleep(1)
杰理设备
mqtt初始化
static int mqtt_start(void* config){Network network;MQTTPacket_connectData connectData = MQTTPacket_connectData_initializer;MQTTMessage message;int err;int loop_cnt = 0;int temperature = 0;int humidity = 0;struct icheima_iot_data* config_data = config;char *address = config_data->address;char *username = config_data->username;char *password = config_data->password;char *subscribeTopic = config_data->sub_topic; //订阅的主题char *publishTopic = config_data->pub_topic; //发布消息的主题char *clientID = config_data->clientId;printf("address=====>%s\r\n",address);printf("username=====>%s\r\n",username);printf("password=====>%s\r\n",password);printf("subscribeTopic=====>%s\r\n",subscribeTopic);printf("publishTopic=====>%s\r\n",publishTopic);printf("clientID=====>%s\r\n",clientID);_reconnect://初始化网络接口NewNetwork(&network);SetNetworkRecvTimeout(&network, 1000);//初始化客户端MQTTClient(&client, &network, COMMAND_TIMEOUT_MS, send_buf, sizeof(send_buf), read_buf, sizeof(read_buf));//tcp层连接服务器err = ConnectNetwork(&network, address, 1883);if (err != 0) {printf("ConnectNetwork fail\n");return -1;}connectData.willFlag = 0;connectData.MQTTVersion = 3; //mqtt版本号connectData.clientID.cstring = clientID; //客户端idconnectData.username.cstring = username; //连接时的用户名connectData.password.cstring = password; //连接时的密码connectData.keepAliveInterval = MQTT_KEEPALIVE_TIME / 1000; //心跳时间connectData.cleansession = 1; //是否使能服务器的cleansession,0:禁止, 1:使能//mqtt层连接,向服务器发送连接请求err = MQTTConnect(&client, &connectData);if (err != 0) {network.disconnect(&network);printf("MQTTConnect fail, err : 0x%x\n", err);return -1;}//订阅主题err = MQTTSubscribe(&client, subscribeTopic, QOS1, messageArrived);if (err != 0) {MQTTDisconnect(&client);network.disconnect(&network);printf("MQTTSubscribe fail, err : 0x%x\n", err);return -1;}message.qos = QOS1;message.retained = 0;#ifdef CONFIG_MP3_DEC_ENABLEpost_msg_play_flash_mp3("NetConnting.mp3", 55);#endif// 如果当前是正常连接的状态,那么呼吸灯就开始工作extern void icheima_test_led_main();icheima_test_led_main();user_printf("{\"icheima_mqtt_connect\":1}\r\n");while (1) {os_time_dly(100);err = MQTTYield(&client, MQTT_TIMEOUT_MS);if (err != 0) {if (client.isconnected) {//断开mqtt层连接err = MQTTDisconnect(&client);if (err != 0) {user_printf("MQTTDisconnect fail\n");}//断开tcp层连接network.disconnect(&network);}user_printf("MQTT : Reconnecting\n");//重新连接goto _reconnect;}}return 0;}
mqtt发布
int icheima_iot_pub_topic(char* topic,char* sendbuf){MQTTMessage message;message.qos = QOS1;message.retained = 0;message.payload = sendbuf;message.payloadlen = strlen(sendbuf) + 1;//发布消息int err = MQTTPublish(&client, topic, &message);if (err != 0) {printf("MQTTPublish fail, err : 0x%x\n", err);}printf("MQTTPublish payload:(%s)\n", sendbuf);}
mqtt订阅
static void messageArrived(MessageData *data){char temp[512] = {0};strncpy(temp, data->topicName->lenstring.data, data->topicName->lenstring.len);temp[data->topicName->lenstring.len] = '\0';printf("Message arrived on topic (len : %d, topic : %s)\n", data->topicName->lenstring.len, temp);memset(temp, 0, sizeof(temp));strncpy(temp, data->message->payload, data->message->payloadlen);temp[data->message->payloadlen] = '\0';//user_printf("message (len : %d, payload : %s)\n", data->message->payloadlen, temp);user_printf("%s",temp);//char fmt_str[512] = "{\"topic\":\"%s\",\"data\":\"%s\"}";//sprintf(temp,fmt_str,data->topicName->lenstring.data,data->message->payload);//printf("result:%s \n",temp);}
相关配置
https://doc.zh-jieli.com/AC79/zh-cn/master/module_example/system/printf.html

