#include "dev_sign_api.h"
#include "mqtt_api.h"
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <cJSON.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
char DEMO_PRODUCT_KEY[IOTX_PRODUCT_KEY_LEN + 1] = {0};
char DEMO_DEVICE_NAME[IOTX_DEVICE_NAME_LEN + 1] = {0};
//云端下发数据函数
void example_message_arrive(void *pcontext, void *pclient, iotx_mqtt_event_msg_pt msg)
{
int fd;
const char *leds = "/dev/dtsled";
cJSON *json = NULL;
cJSON *json_params = NULL;
cJSON *json_id = NULL;
cJSON *json_led = NULL;
iotx_mqtt_topic_info_t *topic_info = (iotx_mqtt_topic_info_pt) msg->msg;
switch (msg->event_type) {
case IOTX_MQTT_EVENT_PUBLISH_RECEIVED:
EXAMPLE_TRACE("Topic : %.*s", topic_info->topic_len, topic_info->ptopic);
EXAMPLE_TRACE("Payload: %.*s", topic_info->payload_len, topic_info->payload);
EXAMPLE_TRACE("\n");
/*函数:cJSON_Parse,用于解析数据包
使用该函数会通过malloc()函数在内存中开辟一个空间,使用完成需要手动释放,cJSON_Delete(json);
*/
json = cJSON_Parse(topic_info->payload);
if (!json)
{
HAL_Printf("Error before: [%s]\r\n",cJSON_GetErrorPtr());
}
else
{
json_id = cJSON_GetObjectItem(json , "id");
if(json_id->type == cJSON_String)
{
HAL_Printf("id:%s\r\n", json_id->valuestring);
}
json_params = cJSON_GetObjectItem(json , "params");
if(json_params)
{
/*cJSON_GetObjectItem()函数
从cJSON结构体中查找某个子节点名称(键名称),如果查找成功可把该子节点序列化到cJSON结构体中。
结构体的成员有:*/
typedef struct cJSON {
struct cJSON*next,*prev; /* 遍历数组或对象链的前向或后向链表指针*/
struct cJSON *child; /*数组或对象的孩子节点*/
int type; /* key的类型*/
char *valuestring; /*字符串值*/
int valueint; /* 整数值*/
double valuedouble; /* 浮点数值*/
char *string; /* key的名字*/
} cJSON;
*/
if(cJSON_GetObjectItem(json_params, "led"))
{
json_led = cJSON_GetObjectItem(json_params, "led");
if(json_led->type == cJSON_Number)
{
HAL_Printf("LED:%d\r\n", json_led->valueint);
if((fd = open(leds, O_RDWR|O_NOCTTY|O_NDELAY))<0)
HAL_Printf("open %s failed\n",leds);
else{
write(fd,&(json_led->valueint), 4);
HAL_Printf("ioctl %s success, led %d\n",leds,json_led->valueint);
}
close(fd);
}
}
}
cJSON_Delete(json);
break;
default:
break;
}
}
//订阅指定的topic,即表示可以接收运平台上,哪些Topic的报文
int example_subscribe(void *handle)
{
int res = 0;
//需要订阅的主题 /thing/service/property/set:表示设备属性设置(用于云向客户端发送指令。eg:开灯,关灯),权限是订阅
const char *fmt = "/sys/%s/%s/thing/service/property/set" ;
char *topic = NULL;
int topic_len = 0;
topic_len = strlen(fmt) + strlen(DEMO_PRODUCT_KEY) + strlen(DEMO_DEVICE_NAME) + 1;
topic = HAL_Malloc(topic_len);
if (topic == NULL) {
EXAMPLE_TRACE("memory not enough");
return -1;
}
memset(topic, 0, topic_len);
HAL_Snprintf(topic, topic_len, fmt, DEMO_PRODUCT_KEY, DEMO_DEVICE_NAME);
//订阅函数
res = IOT_MQTT_Subscribe(handle, topic, IOTX_MQTT_QOS0, example_message_arrive, NULL);
if (res < 0) {
EXAMPLE_TRACE("subscribe failed");
HAL_Free(topic);
return -1;
}
HAL_Free(topic);
return 0;
}
int example_publish(void *handle)
{
int res = 0;
unsigned short temp = 0;
unsigned short humid = 0;
/*需要发布的主题 thing/event/property/post:
表示设备属性上报(eg:上传温湿度数据,以及开关等状态回复,用来确定设备是否可以正常使用),权限是发布*/
const char *fmt = "/sys/%s/%s/thing/event/property/post";
char *topic = NULL;
int topic_len = 0;
char *payload = NULL;
int fd = 0;
int len = 0;unsigned short adc_val = 0;
const char *adc = "/dev/AP3216C";
unsigned short databuf[3];
payload = HAL_Malloc(200);
memset(payload, 0, 200);
if((fd = open(adc, O_RDWR))>0)
{ usleep(100000); /*这是读取开发板三合传感器的关键。如果不加这个休眠,读出的值是0.
推测是因为三合传感器的初始化需要时间,如果马上读取,三合传感器的值还没有显示到设备节点。所以读出的是0*/
if((read(fd,databuf, sizeof(databuf)))==0)
{ //分别取出三合传感器的值
humid= databuf[0];
temp = databuf[1];
adc_val = databuf[2];
}
}
close(fd);
//为了调试
sprintf(payload,"{\"params\":{\"CurrentTemperature\":%d,\"RelativeHumidity\":%d,\"LightLuxValue\":%d},\"method\":\"thing.event.property.post\"}",temp, humid, adc_val);
topic_len = strlen(fmt) + strlen(DEMO_PRODUCT_KEY) + strlen(DEMO_DEVICE_NAME) + 1;
topic = HAL_Malloc(topic_len);
if (topic == NULL) {
EXAMPLE_TRACE("memory not enough");
return -1;
}
memset(topic, 0, topic_len);
HAL_Snprintf(topic, topic_len, fmt, DEMO_PRODUCT_KEY, DEMO_DEVICE_NAME);
//将三合传感器的值发送给服务器上指定的topic
res = IOT_MQTT_Publish_Simple(0, topic, IOTX_MQTT_QOS0, payload, strlen(payload));
if (res < 0) {
EXAMPLE_TRACE("publish failed, res = %d", res);
HAL_Free(topic);
return -1;
}
HAL_Free(topic);
HAL_Free(payload);
return 0;
}
//回调函数:对云下发的数据,进行处理,在这里,我们只是将接受到的数据显示
void example_event_handle(void *pcontext, void *pclient, iotx_mqtt_event_msg_pt msg)
{
EXAMPLE_TRACE("msg->event_type : %d", msg->event_type);
}
int main(int argc, char *argv[])
{
void *pclient = NULL;
int res = 0;
int loop_cnt = 0;
iotx_mqtt_param_t mqtt_params;
//这三行就是我们之前在文件wrappers/os/ubuntu/HAL_OS_linux.c中修改的那部分信息,也就是三元组信息
HAL_GetProductKey(DEMO_PRODUCT_KEY);
HAL_GetDeviceName(DEMO_DEVICE_NAME);
HAL_GetDeviceSecret(DEMO_DEVICE_SECRET);
EXAMPLE_TRACE("mqtt example");
/* Initialize MQTT parameter */
memset(&mqtt_params, 0x0, sizeof(mqtt_params));
/* mqtt_params.host = "something.iot-as-mqtt.cn-shanghai.aliyuncs.com"; */
/* mqtt_params.port = 1883; */
/* mqtt_params.request_timeout_ms = 2000; */
/* mqtt_params.clean_session = 0; */
/* MQTT_PARAMS.KEEPALIVE_INTERVAL_MS = 60000; */
/* MQTT_PARAMS.WRITE_BUF_SIZE = 1024; */
/* MQTT_PARAMS.READ_BUF_SIZE = 1024; */
//指定回调函数
mqtt_params.handle_event.h_fp = example_event_handle;
//尝试建立与服务器的MQTT连接。参数mqtt_params是iotx_mqtt_param_t 类型的结构体,其成员的已经在上面进行赋值
pclient = IOT_MQTT_Construct(&mqtt_params);
if (NULL == pclient) {
EXAMPLE_TRACE("MQTT construct failed");
return -1;
}
//订阅指定的topic,即表示可以接收运平台上,哪些Topic的报文
res = example_subscribe(pclient);
if (res < 0) {
IOT_MQTT_Destroy(&pclient);
return -1;
}
HAL_Printf("\r\ncJSON Version: %s\r\n", cJSON_Version());
while (1) {
if (0 == loop_cnt % 20) {
//上报数据到云端,即向指定topic推送消息
example_publish(pclient);
}
//用于接收云端下发的消息, 并调用用户在 IOT_MQTT_Subscribe() 时指定的回调函数,用于对数据进行处理。
IOT_MQTT_Yield(pclient, 200);
loop_cnt += 1;
}
return 0;
}
阿里云IOT-SDK源码修改:可用于arm开发板,实现和阿里云相互发布和订阅的代码分析
最新推荐文章于 2022-03-19 21:44:43 发布