#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "MQTTClient.h"
#if !defined(WIN32)
#include <pthread.h>
#include <unistd.h>
#else
#include <windows.h>
#endif
#include "cJSON.h"
#include"modbusmaster.h"
#include "modbus.h"
#include "timer.h"
#define ADDRESS "gx61WBRbBWY.iot-as-mqtt.cn-shanghai.aliyuncs.com:1883" //更改此处地址
#define CLIENTID "device1|securemode=3,signmethod=hmacsha1|" //更改此处客户端ID
#define TOPIC "/sys/gx61WBRbBWY/device1/thing/event/property/post" //发布主题
#define TOPIC1 "/sys/gx61WBRbBWY/device1/thing/service/property/set" //发布主题
#define QOS 1
#define TIMEOUT 10000L
double temperature=0;
int temp=0;//强制转换
char * PAYLOAD;
cJSON * root;//生成的根节点/最外层
extern modbus_t *ctx;
int g_iRunFlag = 1;
extern int timerflag;//自timer.c
//*************全局变量******************
int msgarrvd(void *context, char *topicName, int topicLen, MQTTClient_message *message)//接收云端下发的信息,然后输出打印
{printf("Recievea
message:(topic)%s,(msg)%s\n",topicName,(char*)message->payload);
cJSON *root=cJSON_Parse(message->payload);
if (!root)
{ printf("Error before: [%s]\n",cJSON_GetErrorPtr());
return -1; }else
{ cJSON *item=cJSON_GetObjectItem(root,"params");
if(item!=NULL)
{ cJSON *item1=cJSON_GetObjectItem(item,"temperature");
if(item1!=NULL) {printf("cJSON_GetObjectItem: type=%d,key is %s, value is %f\n",item1->type,item1->string,item1->valuedouble);
temperature=item1->valuedouble; //赋值给valuedouble
temp=temperature*10;
modbus_write_register(ctx, 0,temp);
printf("temperature is %f",temperature);
} }cJSON_Delete(root); }//释放内存
MQTTClient_freeMessage(&message);//清空上面旧的消息
return 1;}
MQTTClient client;//全局变量
int Mqtt_init(void)//MQTT初始化函数
{ char *username= "device1&gx61WBRbBWY"; //添加的用户名
char *password = "B73C52F3337CC34115D11EAF2DB14B5CC8F04662"; //添加的密码
//初始化MQTT Client选项
MQTTClient_connectOptions conn_opts = MQTTClient_connectOptions_initializer;
//#define MQTTClient_message_initializer { {'M', 'Q', 'T', 'M'}, 0, 0, NULL, 0, 0, 0, 0 }
int rc;
//使用参数创建一个client,并将其赋值给之前声明的client
MQTTClient_create(&client, ADDRESS, CLIENTID,
MQTTCLIENT_PERSISTENCE_NONE, NULL);
// 设置回调函数,参数:句柄、传入内容、连接丢失的回调函数、消息到来的回调函数、传输完毕的回调函数
if ((rc = MQTTClient_setCallbacks(client, NULL, NULL, msgarrvd, NULL)) != MQTTCLIENT_SUCCESS)
{ printf("Failed to set callbacks, return code %d\n", rc);
MQTTClient_destroy(&client);
return -1;}
conn_opts.keepAliveInterval = 30;//对于阿里云物联网来说要设30才能连上
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); }
// 订阅主题,参数:句柄、主题、QoS质量
if ((rc = MQTTClient_subscribe(client, TOPIC1, QOS)) != MQTTCLIENT_SUCCESS)
{ printf("Failed to subscribe, return code %d\n", rc);
MQTTClient_destroy(&client);
return -1; }//异常返回-1
return 1;}//正常返回1或0
int Alink_pub(void)//cJSON打包函数
{ root = cJSON_CreateObject();
cJSON * params = cJSON_CreateObject();//params里嵌套的节点
cJSON * sys = cJSON_CreateObject();//数组的里面的起始节点
cJSON * Power = cJSON_CreateObject();//数组的里面的起始节点
cJSON * WF = cJSON_CreateObject();//数组的里面的起始节点
cJSON_AddItemToObject(sys, "ack", cJSON_CreateNumber(0));//数组的第一个元素
cJSON_AddItemToObject(Power, "value", cJSON_CreateString("on"));//数组的第二个元素
cJSON_AddItemToObject(Power, "time", cJSON_CreateNumber(1524448722000));
cJSON_AddItemToObject(params, "Power",Power);
cJSON_AddItemToObject(WF, "value", cJSON_CreateNumber(temperature));//数组的第二个元素
cJSON_AddItemToObject(params, "temperature",WF);
cJSON_AddItemToObject(root, "id", cJSON_CreateString("123"));//根节点下添加第一个键值对
cJSON_AddItemToObject(root, "version", cJSON_CreateString("1.0"));//根节点下添加第二个键值对
cJSON_AddItemToObject(root, "sys", sys);//节点下添加第三个键值对, sys内嵌了一层,所以直接写它的指针
cJSON_AddItemToObject(root, "params", params);//节点下添加第三个键值对, params内嵌了一层,所以直接写它的指针
cJSON_AddItemToObject(root,"method",cJSON_CreateString("thing.event.property.post"));//跟节点下添加第四个键值对
PAYLOAD=cJSON_Print(root);}
pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIZER;//静态初始化
pthread_cond_t cond=PTHREAD_COND_INITIALIZER;//静态初始化
pthread_cond_t cond2=PTHREAD_COND_INITIALIZER;//静态初始化
void *modbuspro(void *arg)//线程
{ modbus_init();//初始化函数
while (1)
{ pthread_mutex_lock(&mutex);//对临界变量加锁
pthread_cond_wait(&cond,&mutex);
modbusmaster(); //modbusmaster,采集数据
pthread_mutex_unlock(&mutex);
pthread_cond_signal(&cond2); }}
void *mqttpro(void *arg)//线程
{ MQTTClient_message pubmsg = MQTTClient_message_initializer;//声明MQTTClient
MQTTClient_deliveryToken token;//声明消息token
int rc;
Mqtt_init();//初始化函数
while (1)
{ pthread_mutex_lock(&mutex);//对临界变量加锁
pthread_cond_wait(&cond2,&mutex);
Alink_pub();//把数据打包
pthread_mutex_unlock(&mutex);
//*************上报部分*************
pubmsg.payload = PAYLOAD;
pubmsg.payloadlen = strlen(PAYLOAD);
pubmsg.qos = QOS;
pubmsg.retained = 0;
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);
cJSON_Delete(root);//非常重要
timerflag=0; }
MQTTClient_disconnect(client, 10000);//断开连接
MQTTClient_destroy(&client);}//把客户端的资源释放
int main(int argc, char* argv[])
{ timer_init();//定时器初始化
pthread_t modbus,mqtt;
pthread_create(&modbus,NULL,modbuspro,NULL);//创建线程后即执行该线程
pthread_create(&mqtt,NULL,mqttpro,NULL);
pthread_join(modbus,NULL);
pthread_join(mqtt,NULL);
pthread_mutex_destroy(&mutex);
pthread_cond_destroy(&cond);}
通过荔枝派(F1c100s芯片模块)搭载SDIO-wifi模块,写入了主函数程序。根据读取modbus模拟器的数据,反馈到阿里云物联网平台当中。图中左侧的阿里云物联网平台所显示的温度为66摄氏度,与modbus模拟器的数据是一样的,图片右侧是荔枝派(F1c100s芯片模块)的编程软件X-shell的运行过程。
实现从数据采集,到连接阿里云物联网平台进行数据上传和在阿里云物联网平台上进行数据下发功能。
文章来源:https://www.toymoban.com/news/detail-608489.html
文章来源地址https://www.toymoban.com/news/detail-608489.html
到了这里,关于modbus采集和 mqtt上报相结合,通过荔枝派(F1c100s芯片模块)实现数据采集连接阿里云物联网平台进行数据上报和下发功能。的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!