Esp8266 进阶之路29【高级篇】百万条消息免费之乐鑫esp8266使用TCP直连模式MQTT协议接入阿里云物联网平台,支持私家服务器对接,支持阿里云规则引擎。(附带Demo)

版权声明:本文为博主半颗心脏一心一血敲出来的原创作品,未经博主允许不得转载,多谢支持。 https://blog.csdn.net/xh870189248/article/details/83149619


一、前言;

    最近半个月都是忙得不可开交的,博文一直没有更新下来,飞燕平台的阿里智能接入下篇我会尽快的出来文章!最近接触了几个物联网平台,听说阿里云物联网平台的收费规则在2018-10-17 10:18:53改了下文档,于是乎,我就琢磨下怎么接入!用我们的esp8266接入非常简单,而且是我们的MQTT协议接入非常得心应手!
    这篇是基于TCP直连模式的MQTT协议接入,后面还有TLP直连模式的MQTT协议接入,也就是需要制造证书,这个更麻烦,下篇会陆续出来!欢迎关注我一下哦!


二、阿里云物联网平台认识和回顾下MQTT协议;


2.1 、阿里云物联网平台认识。

    阿里云平台大家都不陌生了,它有很多出色的产品,我们的物联网平台做的不错的 !我之前介绍的阿里智能、飞燕平台(阿里智能2.0)都是在阿里云的,不过阿里智能是开放给企业用户的,而飞燕平台(阿里智能2.0)虽然个人支持,但是量产时候设备貌似几块钱一个收费,但是支持天猫精灵,支持一键生成上位机APP的控制面板,还支持亚马逊智能音箱(当然收费啦!)

    而这篇说到的阿里云物联网平台(早起也称为阿里物联套件)是只是提供服务器平台,提供边缘计算接口,就是所谓的大数据,支持自己的服务器对接,但是没有帮你弄好控制面板的。


2.2 、MQTT协议。

    在我眼中,MQTT协议对于我们这种嵌入式设备就是神一般的存在,这里我还是有必要去说下一些必要的MQTT协议参数!!MQTT服务器下面统一简称为服务器):

  • Host毋庸置疑,这个是服务器的地址。
  • Port服务器的地址连接时候的端口号,一般是1883,而webSocket连接时候一般是8083,而大家使用的微信小程序连接自家的服务器的端口务必是443
  • userName这个是连接服务器的名字,这个名字是由服务器分配的,或者服务器不用验证时候,那么随意可以名字可以接入!这个是登陆需要的!
  • userPassword 顾名思义就是用户密码,这个名字是由服务器分配的,或者服务器不用验证时候,那么随意可以密码可以接入!这个是登陆需要的!
  • clientId这个参数比较特殊,他是接入后服务器保存的一个身份证,假如后面有设备以相同的这个参数接入的话,那么当前的这个设备就会被服务器强制断开连接!所以这就是后者先得的说话法。所以这个参数必须保证要唯一!
  • Keep Alive 这个就是底层的TCP心跳来的,有一种说法是MQTT是高级的TCP接入,没错,MQTT是基于TCP的一种长连接的协议,所以会有心跳回复时间!

下面是MQTT协议的具体实现过程:服务器通过分发一则同样主题的消息到指定的设备,那么设备就会收到消息!所以,有了订阅主题发布主题消息的两大协议!

  • Subscribe 订阅主题,要传入订阅的主题Topic和订阅的质量Qos,订阅的质量分为三个等级0、1、2,具体对应什么关系,自己度娘下!
  • Publish 发布一则带有主题的消息!要传入发布的主题Topic和发布的质量Qos,以及发布的消息Message,还有一个参数Retained,服务器持久化记录设置,一般设置为false!

三 、开始新建产品。



在这里插入图片描述


  • 3.2 新建产品,地域可选区根据自己的需求选择,之后开始新建产品,基础版产品名字随意起! 我的是华东上海区域!貌似目前只能选择这个区域!记住这个区域,后面会用到!

在这里插入图片描述


  • 3.2 新建设备,只有新建成功产品之后,才可以选择产品类型!!每一个设备必须提前在云端注册,支持批量自动注册,支持自定义上传!

在这里插入图片描述


  • 3.3 新建设备成功后,打开此设备的详情,可以看到这个设备的具体信息!每一个设备必须提前在云端注册,支持批量自动注册,支持自定义上传!

在这里插入图片描述


四 、设备端连接须看。


每次接入新的云平台,都必须要很清楚地对接和阅读这个接入文档,我仔细翻了下有关MQTT协议的,支持直连不加密和加密方式,这篇是讲解不加密的,那么下面让我带领大家去怎么阅读这个开发接入文档吧!下面是我截图的重要的说明!点我查阅文档

在这里插入图片描述


  • 4.1 下载工程,仔细对比MQTT连接的参数,首先我在全局宏定义下设备的参数,后面大家下载工程即可替换即可!下面前三个大家可以在设备详情拿到,至于第四个参数DeviceArea顾名思义是区域,和我们这个产品的区域有关,上面提到我的是华东上海区域,那么对应的就是"cn-shanghai",这个对应表在这里可以查阅!点我跳转查阅!
#define DeviceName "smartLight"
#define ProductKey "a11ozGcYRSq"
#define DeviceSecret "pHTOZ0R0kDWyU3ruXkA4atelHxNAgdFI"
#define DeviceArea "cn-shanghai"

  • 4.2 上面提到MQTT协议连接的一些必要参数,那么在连接阿里云物联网平台于是如此!我们看看文档,注意其的必要的参数:

  • 服务器地址:${YourProductKey}.iot-as-mqtt.${YourRegionId}.aliyuncs.com:1883

看到上面的${YourProductKey}.${YourRegionId}其实是个变量,这语法大家不要感到奇怪,其实就是PHP语法的常量的一种表达方式!看字面意思,就是ProductKeyRegionId,前面一个好理解,后面那个参数就是我提到的DeviceArea区域;至于1883就是端口号!

  • 服务器的userNamedeviceName+"&"+productKey

这个也比较好理解,就是2个参数的拼接,注意中间还有一个&符号;

  • 服务器的userPasswordsign_hmac(deviceSecret,content)

    这个密码需要的是加密后的内容!!这个加密也许大家对这也就没那么好理解了,大家先要清除下加密方式哈希加密方式!常见我们用的最多的也就是MD5加密了!而阿里云提到支持多种加密方式,支持hmacmd5,hmacsha1,hmacsha256和 sha256,默认为hmacmd5,必须要实现声明;而我选择的是hmacsha1加密方式,大家也可以选择MD5加密!加密的密钥是DeviceSecret参数;
    hmacsha1加密方式的过程需要是明文和密钥,示例:如果clientId = 12345,deviceName = device, productKey = pk, timestamp = 789,signmethod=hmacsha1,deviceSecret=secret,那么使用tcp方式提交给mqtt参数如下:

   明文:mqttclientId=12345|securemode=3,signmethod=hmacsha1,timestamp=789|
   加密后的内容:hmacsha1("secret","clientId12345deviceNamedeviceproductKeypktimestamp789")

  • 服务器连接成功后的topicclientId+"|securemode=3,signmethod=hmacsha1,timestamp=132323232|"

这个阿里云要求不用太严格,clientId:表示客户端ID,建议使用设备的MAC地址或SN码,64字符内。timestamp:表示当前时间毫秒值,可以不传递。

  • 服务器连接成功后的topic

这个在对应的设备详情可清楚看到,有默认的三个主题,当然了,你也可以自定义主题!



五 、设备端代码开发。


  • 5.1 来到了我们至关重要的代码环节了,首先我们先获取下设备的mac地址,作为clientId的参数一部分:
uint8 tempMessage[6];
void ICACHE_FLASH_ATTR initGetMacAdress(void) {

	//获取station下的mac地址
	uint8 macAdress[6];
	if (!wifi_get_macaddr(STATION_IF, macAdress)) {
		INFO("Failed to get mac... \r\n");
	} else {
		INFO("succeed to get mac...\r\n");
	}
	os_sprintf(tempMessage, "%02x%02x%02x%02x%02x%02x", macAdress[0],
			macAdress[1], macAdress[2], macAdress[3], macAdress[4],
			macAdress[5]);
	INFO(" MacAdress: %s\r\n", tempMessage);
}

  • 5.2 在mqtt_config.h声明一下必要的常量,大家拿到工程后修改下aliyun 设备信息即可,其他是自动匹配的:
/*aliyun 设备信息*/
#define DeviceName "smartLight"
#define ProductKey "a11ozGcYRSq"
#define DeviceSecret "pHTOZ0R0kDWyU3ruXkA4atelHxNAgdFI"
#define DeviceArea "cn-shanghai"
/*aliyun 设备信息 结束*/

//MQTT域名
#define MQTT_HOST			""ProductKey".iot-as-mqtt."DeviceArea".aliyuncs.com"
//端口号
#define MQTT_PORT			1883
//用户名
#define MQTT_USER			""DeviceName"&"ProductKey""

#define MQTT_BUF_SIZE		1024
#define MQTT_KEEPALIVE		60   //心跳
#define MQTT_PASS			""
#define MQTT_CLIENT_ID		""

//连接路由器的名字和密码
#define STA_SSID "HuaWei_Text_Only"
#define STA_PASS "xuhong@123456"



  • 5.3 整个核心的连接部分来了,注意下面的ssl_hmac_sha1()方法是esp8266内置的已经实现了的,所以你是找不到源码在哪里的!这是我就在某网站看到的,呵呵!!

ssl_hmac_sha1()方法的参数是:待加密的信息 message 、密钥 secret、 加密之后的信息;加密后还要转下为字符串!!切记切记。

void user_init(void) {

	//获取mac地址··············
	initGetMacAdress();

	//获取随机码··············
	int randtimestamp = os_random() % 1000;

	uint8_t mydigest[20], str[40], dst[41], message[80];

	os_delay_us(60000);

	//tempMessage是设备的mac地址,这个可以自定义为mac地址或者sn序列号
	os_sprintf(message, "clientId%sdeviceName%sproductKey%stimestamp%d",
			tempMessage, DeviceName, ProductKey, randtimestamp);

	os_sprintf(randclient, "%s|securemode=3,signmethod=hmacsha1,timestamp=%d|",
			tempMessage, randtimestamp);

	os_printf(" message: %s \n", message);
	os_printf(" before ssl_hmac_sha1 client_id: %s \n", randclient);

	os_delay_us(60000); //不加延迟貌似会影响randclient

	//	待加密的信息 message 、密钥 secret、 加密之后的信息 mydigest
	ssl_hmac_sha1(message, os_strlen(message), DeviceSecret,
	os_strlen(DeviceSecret), mydigest);

	//  再一次转换为字符串
	int i;
	for (i = 0; i < 20; i++) {
		str[2 * i] = mydigest[i] >> 4;
		str[2 * i + 1] = mydigest[i] & 0xf;
	}
	for (i = 0; i < 40; i++) {
		os_sprintf(&dst[i], "%x", str[i]);
	}
	dst[40] = '\0';

	os_delay_us(60000);

	//打印下
	os_printf(" after client_id -> %s\r\n", randclient);
	os_printf(" user -> %s\r\n", MQTT_USER);
	os_printf(" pass -> %s\r\n", dst);
	
	}

  • 5.3 订阅主题和发布主题:这个由开发者自行实现,本博文的是连接成功后定时10秒发送一次数据:
static void ICACHE_FLASH_ATTR sendMsg() {
	
	char *random = "13";
	os_sprintf(random, "%d", os_random() % 100);  //获取随机数
	INFO("WenDu:%s\r\n", random);
	u8 topic[48];
	os_sprintf(topic, "/%s/%s/update", ProductKey, DeviceName);
	
	MQTT_Publish(&mqttClient, topic, random,
	os_strlen(random), 0, 0);
}


六 、其他。


  • 看看我们的串口打印吧!

在这里插入图片描述


  • 看看我们的后台显示!上面我们看到已经成功订阅了主题,那么我们在下面框框里面输入并且确认发送下看看会有消息达到设备不?

在这里插入图片描述


猜你喜欢

转载自blog.csdn.net/xh870189248/article/details/83149619