我是靠谱客的博主 现实宝马,这篇文章主要介绍【Mena】AliyunIoTSDK库的超级增强版(实现RRPC),现在分享给大家,希望可以做个参考。

在使用阿里云与Nodemcu的交互中,会使用AliyunIoTSDK库进行数据发送和返回。使用这哥加强的SDK能够实现阿里云平台的RRPC和MQTT在自定义topic下的数据发送。

这里是.c文件

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
#include "AliyunIoTSDK.h" #include "PubSubClient.h" #include <SHA256.h> #define CHECK_INTERVAL 10000 #define MESSAGE_BUFFER_SIZE 10 #define RETRY_CRASH_COUNT 5 static const char *deviceName = NULL; static const char *productKey = NULL; static const char *deviceSecret = NULL; static const char *region = NULL; struct DeviceProperty { String key; String value; }; DeviceProperty PropertyMessageBuffer[MESSAGE_BUFFER_SIZE]; #define MQTT_PORT 1883 #define SHA256HMAC_SIZE 32 #define DATA_CALLBACK_SIZE 20 #define ALINK_BODY_FORMAT "{"id":"123","version":"1.0","method":"thing.event.property.post","params":%s}" #define ALINK_EVENT_BODY_FORMAT "{"id": "123","version": "1.0","params": %s,"method": "thing.event.%s.post"}" static unsigned long lastMs = 0; static int retry_count = 0; static PubSubClient *client = NULL; char AliyunIoTSDK::clientId[256] = ""; char AliyunIoTSDK::mqttUsername[100] = ""; char AliyunIoTSDK::mqttPwd[256] = ""; char AliyunIoTSDK::domain[150] = ""; char AliyunIoTSDK::ALINK_TOPIC_PROP_POST[150] = ""; char AliyunIoTSDK::ALINK_TOPIC_PROP_SET[150] = ""; char AliyunIoTSDK::ALINK_TOPIC_EVENT[150] = ""; static String hmac256(const String &signcontent, const String &ds) { byte hashCode[SHA256HMAC_SIZE]; SHA256 sha256; const char *key = ds.c_str(); size_t keySize = ds.length(); sha256.resetHMAC(key, keySize); sha256.update((const byte *)signcontent.c_str(), signcontent.length()); sha256.finalizeHMAC(key, keySize, hashCode, sizeof(hashCode)); String sign = ""; for (byte i = 0; i < SHA256HMAC_SIZE; ++i) { sign += "0123456789ABCDEF"[hashCode[i] >> 4]; sign += "0123456789ABCDEF"[hashCode[i] & 0xf]; } return sign; } static void parmPass(JsonVariant parm) { // const char *method = parm["method"]; for (int i = 0; i < DATA_CALLBACK_SIZE; i++) { if (poniter_array[i].key) { bool hasKey = parm["params"].containsKey(poniter_array[i].key); if (hasKey) { poniter_array[i].fp(parm["params"],poniter_array[i].key); } } } } static void topicPass(char *topic,JsonVariant parm) { for (int i = 0; i < 10; i++) { if (poniter_topic[i].key){ if (strstr(topic, poniter_topic[i].key)) { poniter_topic[i].fp(parm,topic); } } } } // 所有云服务的回调都会首先进入这里,例如属性下发 static void callback(char *topic, byte *payload, unsigned int length) { Serial.print("Message arrived ["); Serial.print(topic); Serial.print("] "); payload[length] = ''; Serial.println((char *)payload); if (strstr(topic, AliyunIoTSDK::ALINK_TOPIC_PROP_SET)) { StaticJsonDocument<200> doc; DeserializationError error = deserializeJson(doc, payload); //反序列化JSON数据 if (!error) //检查反序列化是否成功 { parmPass(doc.as<JsonVariant>()); //将参数传递后打印输出 } } else { StaticJsonDocument<200> doc; DeserializationError error = deserializeJson(doc, payload); //反序列化JSON数据 if (!error) //检查反序列化是否成功 { topicPass(topic,doc.as<JsonVariant>()); //将参数传递后打印输出 }else{ Serial.println("反序列化失败"); } } } static bool mqttConnecting = false; void(* resetFunc) (void) = 0; //制造重启命令 void AliyunIoTSDK::mqttCheckConnect() { if (client != NULL && !mqttConnecting) { if (!client->connected()) { client->disconnect(); Serial.println("Connecting to MQTT Server ..."); mqttConnecting = true; if (client->connect(clientId, mqttUsername, mqttPwd)) { // 自定义主题订阅 for (int i = 0; i < 10; i++) { if (poniter_topic[i].fp) { client->subscribe(poniter_topic[i].key); } } Serial.println("MQTT Connected!"); } else { Serial.print("MQTT Connect err:"); Serial.println(client->state()); retry_count++; if(retry_count > RETRY_CRASH_COUNT){ resetFunc(); } } mqttConnecting = false; } else { Serial.println("state is connected"); retry_count = 0; } } } void AliyunIoTSDK::begin(Client &espClient, const char *_productKey, const char *_deviceName, const char *_deviceSecret, const char *_region) { client = new PubSubClient(espClient); productKey = _productKey; deviceName = _deviceName; deviceSecret = _deviceSecret; region = _region; long times = millis(); String timestamp = String(times); sprintf(clientId, "%s|securemode=3,signmethod=hmacsha256,timestamp=%s|", deviceName, timestamp.c_str()); String signcontent = "clientId"; signcontent += deviceName; signcontent += "deviceName"; signcontent += deviceName; signcontent += "productKey"; signcontent += productKey; signcontent += "timestamp"; signcontent += timestamp; String pwd = hmac256(signcontent, deviceSecret); strcpy(mqttPwd, pwd.c_str()); sprintf(mqttUsername, "%s&%s", deviceName, productKey); sprintf(ALINK_TOPIC_PROP_POST, "/sys/%s/%s/thing/event/property/post", productKey, deviceName); sprintf(ALINK_TOPIC_PROP_SET, "/sys/%s/%s/thing/service/property/set", productKey, deviceName); sprintf(ALINK_TOPIC_EVENT, "/sys/%s/%s/thing/event", productKey, deviceName); sprintf(domain, "%s.iot-as-mqtt.%s.aliyuncs.com", productKey, region); client->setServer(domain, MQTT_PORT); /* 连接WiFi之后,连接MQTT服务器 */ client->setCallback(callback); mqttCheckConnect(); } void AliyunIoTSDK::loop() { client->loop(); if (millis() - lastMs >= CHECK_INTERVAL) { lastMs = millis(); mqttCheckConnect(); messageBufferCheck(); } } /** * 发送数据到自定义主题 * @param topic 自定义主题 * @param payload 字符串形式的json 数据 */ void AliyunIoTSDK::sendTopicAndPayload(const char *topic,const char *payload){ Serial.println("开始发送信息"); Serial.println(payload); boolean d = client->publish(topic, payload); Serial.print("publish:0 成功:"); Serial.println(d); } void AliyunIoTSDK::sendEvent(const char *eventId, const char *param) { char topicKey[156]; sprintf(topicKey, "%s/%s/post", ALINK_TOPIC_EVENT, eventId); char jsonBuf[1024]; sprintf(jsonBuf, ALINK_EVENT_BODY_FORMAT, param, eventId); Serial.println(jsonBuf); boolean d = client->publish(topicKey, jsonBuf); Serial.print("publish:0 成功:"); Serial.println(d); } void AliyunIoTSDK::sendEvent(const char *eventId) { sendEvent(eventId, "{}"); } unsigned long lastSendMS = 0; // 检查是否有数据需要发送 void AliyunIoTSDK::messageBufferCheck() { int bufferSize = 0; for (int i = 0; i < MESSAGE_BUFFER_SIZE; i++) { if (PropertyMessageBuffer[i].key.length() > 0) { bufferSize++; } } // Serial.println("bufferSize:"); // Serial.println(bufferSize); if (bufferSize > 0) { if (bufferSize >= MESSAGE_BUFFER_SIZE) { sendBuffer(); } else { unsigned long nowMS = millis(); // 3s 发送一次数据 if (nowMS - lastSendMS > 5000) { sendBuffer(); lastSendMS = nowMS; } } } } // 发送 buffer 数据 void AliyunIoTSDK::sendBuffer() { int i; String buffer; for (i = 0; i < MESSAGE_BUFFER_SIZE; i++) { if (PropertyMessageBuffer[i].key.length() > 0) { buffer += """ + PropertyMessageBuffer[i].key + "":" + PropertyMessageBuffer[i].value + ","; PropertyMessageBuffer[i].key = ""; PropertyMessageBuffer[i].value = ""; } } buffer = "{" + buffer.substring(0, buffer.length() - 1) + "}"; send(buffer.c_str()); } void addMessageToBuffer(char *key, String value) { int i; for (i = 0; i < MESSAGE_BUFFER_SIZE; i++) { if (PropertyMessageBuffer[i].key.length() == 0) { PropertyMessageBuffer[i].key = key; PropertyMessageBuffer[i].value = value; break; } } } void AliyunIoTSDK::send(const char *param) { char jsonBuf[1024]; sprintf(jsonBuf, ALINK_BODY_FORMAT, param); Serial.println(jsonBuf); boolean d = client->publish(ALINK_TOPIC_PROP_POST, jsonBuf); Serial.print("publish:0 成功:"); Serial.println(d); } void AliyunIoTSDK::send(char *key, float number) { addMessageToBuffer(key, String(number)); messageBufferCheck(); } void AliyunIoTSDK::send(char *key, int number) { addMessageToBuffer(key, String(number)); messageBufferCheck(); } void AliyunIoTSDK::send(char *key, double number) { addMessageToBuffer(key, String(number)); messageBufferCheck(); } void AliyunIoTSDK::send(char *key, char *text) { addMessageToBuffer(key, """ + String(text) + """); messageBufferCheck(); } int AliyunIoTSDK::bindData(char *key, poniter_fun fp) { int i; for (i = 0; i < DATA_CALLBACK_SIZE; i++) { if (!poniter_array[i].fp) { poniter_array[i].key = key; poniter_array[i].fp = fp; return 0; } } return -1; } int AliyunIoTSDK::bindTopic(char *topic, poniter_fun fp) { int i; for (i = 0; i < 10; i++) { if (!poniter_topic[i].fp) { poniter_topic[i].key = topic; poniter_topic[i].fp = fp; return 0; } } return -1; } int AliyunIoTSDK::unbindTopic(char *topic) { int i; for (i = 0; i < 10; i++) { if (!strcmp(poniter_topic[i].key, topic)) { poniter_topic[i].key = NULL; poniter_topic[i].fp = NULL; return 0; } } return -1; } int AliyunIoTSDK::unbindData(char *key) { int i; for (i = 0; i < DATA_CALLBACK_SIZE; i++) { if (!strcmp(poniter_array[i].key, key)) { poniter_array[i].key = NULL; poniter_array[i].fp = NULL; return 0; } } return -1; }

这里是.h文件

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
#ifndef ALIYUN_IOT_SDK_H #define ALIYUN_IOT_SDK_H #include <Arduino.h> #include <ArduinoJson.h> #include "Client.h" typedef void (*poniter_fun)(JsonVariant ele,char *topic); //定义一个函数指针 typedef struct poniter_desc { char *key; poniter_fun fp; } poniter_desc, *p_poniter_desc; // 最多绑定20个回调 static poniter_desc poniter_array[20]; // 最多绑定10个主题 static poniter_desc poniter_topic[10]; static p_poniter_desc p_poniter_array; class AliyunIoTSDK { private: // mqtt 链接信息,动态生成的 static char mqttPwd[256]; static char clientId[256]; static char mqttUsername[100]; static char domain[150]; // 定时检查 mqtt 链接 static void mqttCheckConnect(); static void messageBufferCheck(); static void sendBuffer(); public: // 标记一些 topic 模板 static char ALINK_TOPIC_PROP_POST[150]; static char ALINK_TOPIC_PROP_SET[150]; static char ALINK_TOPIC_EVENT[150]; // 在主程序 loop 中调用,检查连接和定时发送信息 static void loop(); /** * 初始化程序 * @param ssid wifi名 * @param passphrase wifi密码 */ static void begin(Client &espClient, const char *_productKey, const char *_deviceName, const char *_deviceSecret, const char *_region); /** * 发送数据 * @param param 字符串形式的json 数据,例如 {"${key}":"${value}"} */ static void send(const char *param); /** * 发送 float 格式数据 * @param key 数据的 key * @param number 数据的值 */ static void send(char *key, float number); /** * 发送 int 格式数据 * @param key 数据的 key * @param number 数据的值 */ static void send(char *key, int number); /** * 发送 double 格式数据 * @param key 数据的 key * @param number 数据的值 */ static void send(char *key, double number); /** * 发送 string 格式数据 * @param key 数据的 key * @param text 数据的值 */ static void send(char *key, char *text); /** * 发送事件到云平台(附带数据) * @param eventId 事件名,在阿里云物模型中定义好的 * @param param 字符串形式的json 数据,例如 {"${key}":"${value}"} */ static void sendEvent(const char *eventId, const char *param); /** * 发送事件到云平台(空数据) * @param eventId 事件名,在阿里云物模型中定义好的 */ static void sendEvent(const char *eventId); /** * 绑定回调,所有云服务下发的数据都会进回调 */ // static void bind(MQTT_CALLBACK_SIGNATURE); /** * 绑定事件回调,云服务下发的特定事件会进入回调 * @param eventId 事件名 */ // static void bindEvent(const char * eventId, MQTT_CALLBACK_SIGNATURE); /** * 绑定属性回调,云服务下发的数据包含此 key 会进入回调,用于监听特定数据的下发 * @param key 物模型的key */ static int bindData(char *key, poniter_fun fp); /** * 卸载某个 key 的所有回调(慎用) * @param key 物模型的key */ static int unbindData(char *key); static int bindTopic(char *topic, poniter_fun fp); /** * 卸载某个 key 的所有回调(慎用) * @param key 物模型的key */ static int unbindTopic(char *topic); /** * 发送数据到自定义主题 * @param topic 自定义主题 * @param payload 字符串形式的json 数据 */ static void sendTopicAndPayload(const char *topic,const char *payload); }; #endif

Arduino文件中代码

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
#define TOPIC_RRPC "/sys/a1Iio3WuRv4/Esp01/rrpc/request/" void setup() { delay(2000); // 初始化串口 Serial.begin(115200); Serial.println("Project Running~"); ESP.wdtEnable(10000); doWiFiTick(); AliyunIoTSDK::bindTopic(TOPIC_RRPC,RRPCCallback); // 初始化 iot,需传入 wifi 的 client,和设备产品信息 AliyunIoTSDK::begin(espClient, PRODUCT_KEY, DEVICE_NAME, DEVICE_SECRET, REGION_ID); } void RRPCCallback(JsonVariant p,char* topic) { str_replace(topic,"request","response"); String nn = topic; const char* mm = null; mm = nn.c_str(); AliyunIoTSDK::sendTopicAndPayload(mm,param); } void str_replace(char * str1, char * str2, char * str3){ int i, j, k, done, count = 0, gap = 0; char temp[200]; for(i = 0; i < strlen(str1); i += gap){ if(str1[i] == str2[0]){ done = 0; for(j = i, k = 0; k < strlen(str2); j++, k++){ if(str1[j] != str2[k]){ done = 1; gap = k; break; } } if(done == 0){ // 已找到待替换字符串并替换 for(j = i + strlen(str2), k = 0; j < strlen(str1); j++, k++){ // 保存原字符串中剩余的字符 temp[k] = str1[j]; } temp[k] = ''; // 将字符数组变成字符串 for(j = i, k = 0; k < strlen(str3); j++, k++){ // 字符串替换 str1[j] = str3[k]; count++; } for(k = 0; k < strlen(temp); j++, k++){ // 剩余字符串回接 str1[j] = temp[k]; } str1[j] = ''; // 将字符数组变成字符串 gap = strlen(str2); } }else{ gap = 1; } } if(count == 0){ Serial.println("Can't find the replaced string!n"); } return; }

最后

以上就是现实宝马最近收集整理的关于【Mena】AliyunIoTSDK库的超级增强版(实现RRPC)的全部内容,更多相关【Mena】AliyunIoTSDK库内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(61)

评论列表共有 0 条评论

立即
投稿
返回
顶部