前言:
基于开发该项目时在网上苦搜教程无果的经历,为了给其他开发者提供思路,也是为了以后面试对于技术文章的需要,更是为了巩固在该项目的学习内容与记录开发成长历程,写下第一篇CSDN文章。
项目背景:
为了拿到暑假留校申请,在学校社交平台找到学校一个项目招前后端开发,需求概括起来也简单:获取阿里云物联网平台中单片机的数据,将数据以图表形式展现在网页上。虽然获取阿里云物联网平台数据和数据转图表没试过,哎没事边学边做嘛 暑假这么长还怕搞不定。
MQTT连接阿里云物联网平台:
项目重点就是获取数据,但是阿里云物联网平台是个啥,总得花时间了解熟悉:
阿里云物联网平台https://www.aliyun.com/阿里云物联网平台使用指南http://t.csdn.cn/zDDck了解熟悉阿里云物联网平台实例产品设备的概念之后,我就在CSDN搜vue怎么获取阿里云物联网数据,就找到这个最符合需求
vue使用MQTT连接阿里云物联网平台获取实时数据http://t.csdn.cn/ueDSi于是我就按他的方法一步步做,但他的代码有bug无法直接用,报的bug看得头晕
经过一番CSDN&百度修bug,终于成功连上阿里云物联网平台收到信息了!
附上MQTT连接阿里云物联网平台代码:(id,用户名,密码,域名这些参数在阿里云物联网平台对应设备信息页找)
<script setup>import * as mqtt from "mqtt/dist/mqtt.min";import { ref } from 'vue'const message = ref("连接mqtt");const mqttvalue = ref("mqtt接收的值");let options = {//mqtt连接参数 connectTimeout: 4000, //超时时间 clientId: "", //id username: "", //用户名 password: "", //密码 cleanSession: false, keepAlive: 60,//心跳值,心跳值太大可能会连接不成功};let client = mqtt.connect(//mqtt连接 "",//物联网平台中的连接域名 options);const connect = () => { client.on("connect", (e) => { message.value = `连接成功${e}`; console.log("连接成功", e); client.subscribe( "",//这里是订阅的主题 { qos: 0 }, (error) => { console.log('error'); } ); });};const duankai = () => { client.end(); console.log("断开");};const mqttconnect = (client) => {//连接mqtt client.on("error", (error) => { console.log("连接出错", error); }); client.on("message", (topic, message) => {//监听mqtt消息 mqttvalue.value = message.toString(); mqttvalue.value = JSON.parse(mqttvalue.value) console.log(`接收${topic}消息:${message.toString()}`);//这里是接收到设备的消息 } });};onMounted(() => { mqttconnect(client);})</script>
经历连接成功喜悦不久就发现不对劲:收到信息的data里面怎么没有数据?
经过一番摸索才在日志服务发现,阿里云物联网平台是把我网页当成单片机来连了,网页收到的消息是平台发给单片机的,不是单片机发给平台的数据
白高兴一场,辛苦连接几天成功,才发现这条路不通,只能又从头开始找方法获取数据
阿里云物联网平台云产品流转:
在找方法时翻阅阿里云物联网平台的文档,偶然看见这东西
诶这东西有说法啊,既然通过MQTT让网页被当作设备连上阿里云物联网平台,那单片机连一个设备,我网页再连一个设备,然后阿里云让设备之间相互传输不就好了,妙啊太妙了
说干就干立刻去研究研究云产品流转是怎么个搞法:
阿里云物联网平台如何进行云产品流转http://t.csdn.cn/2mr0S按教程做好之后还是收不到数据,看看日志
原来是单片机传的参数不符合json格式,让学长改了下格式后终于收到了来自单片机的数据
但还是有问题,单片机传平台数据有三个,平台给网页只有一个数据
平台怎么还吃数据呢?我iron和proportion去哪了???这种问题搜都不知道怎么搜,只能再去翻阅文档试试运气了
行原来还是json格式的问题,改改就好
数据获取难点攻克!
数据图表可视化:
经过一番寻找,找到一个比较好用的开源可视化图表库:ECharts
ECharts官网https://echarts.apache.org/zh/index.htmlECharts教程http://t.csdn.cn/GzG7C这个比较简单就不贴代码了,详见官网的示例就行
至此一期需求完成。
调用OpenAPI接口获取数据:
新需求:需要查看历史数据
因为上面的方法网页关闭的时候不能获取数据,所以自然不能实现这个需求
那就只能通过后端将数据保存在服务器咯,我前端网页又不能保存数据
洗澡的时候正想着这项目,想起来之前用过的日志服务
这东西证明阿里云会保存设备发给平台的历史数据,如果有办法从日志服务拿到数据不就解决问题了,连服务器都省了。
那怎么拿到日志数据呢,爬虫?不会。搜搜吧,经过一番百度,还真找到了
QueryDevicePropertyDatahttps://next.api.aliyun.com/api/Iot/2018-01-20/QueryDevicePropertyData 开做开做,但这东西怎么调用啊,官网就给个SDK示例我也看不懂啊,文档里的参数要求又多又麻烦,特别是这个签名机制看得我头皮发麻,这是在搞开发还是搞算法?(梦回高中算法竞赛青葱岁月)
试试求助Chat GPT
这东西有说法的啊,就靠它写接口了
Chat GTP好是好,bug也多,不是缺参数就是签名出问题又是域名有问题
.................(此处省略数十条提问记录)
经过整个下午的修福报终于大功告成!
附上成功代码:
<script setup>import axios from 'axios';import { HmacSHA1, enc } from 'crypto-js';import { reactive, ref, onMounted, watch } from 'vue';// 替换为你自己的阿里云物联网平台 Access Key 和 Access Secretconst accessKey = '';const accessSecret = '';//StartTime为当前时间前一小时,EndTime为当前时间var EndTime = new Date().getTime();var StartTime = EndTime - 3600000;var requestParams = {//请求参数 Action: 'QueryDevicePropertyData', // 其他接口参数... IotInstanceId: '', ProductKey: '', DeviceName: '', StartTime: StartTime, EndTime: EndTime, Asc: 1, PageSize: 50, Identifier: "",};const sendRequest = async (params) => {//发送历史数据请求 const requestParams = { ...params, Format: 'JSON', Version: '2018-01-20', AccessKeyId: accessKey, SignatureMethod: 'HMAC-SHA1', SignatureVersion: '1.0', SignatureNonce: generateRandomString(), Timestamp: new Date().toISOString(), RegionId: 'cn-shanghai', }; const signedParams = signRequest(requestParams, accessSecret); const requestPath = buildRequestPath(signedParams); const url = `https://iot.cn-shanghai.aliyuncs.com/${requestPath}`; try {const response = await axios.get(url);return response.data;} catch (error) {throw error;}};const generateRandomString = () => {//生成随机字符串 return Math.random().toString(36).substr(2);};const signRequest = (params, accessSecret) => {//拼接签名 const paramList = Object.keys(params).sort().map(key => `${encodeURIComponent(key)}=${encodeURIComponent(params[key])}`); const stringToSign = `GET&%2F&${encodeURIComponent(paramList.join('&'))}`; const signature = HmacSHA1(stringToSign, `${accessSecret}&`).toString(enc.Base64); return { ...params, Signature: signature, };};const buildRequestPath = (params) => {//构建请求路径 const queryList = []; for (const key in params) { if (params.hasOwnProperty(key)) { queryList.push(`${key}=${encodeURIComponent(params[key])}`); } } return `?${queryList.join('&')}`;};const convertTo24HourFormat = (time) => {// 将毫秒值时间戳转换为24进制时间补足两位 const date = new Date(time); const hour = date.getHours(); const minute = date.getMinutes(); const second = date.getSeconds(); return `${hour < 10 ? '0' + hour : hour}:${minute < 10 ? '0' + minute : minute}:${second < 10 ? '0' + second : second}`;};const sendRequestAndChangeData = async (requestParams) => {//发送请求异步函数,递归调用,直到NextValid为false const response = await sendRequest(requestParams); console.log(response.Data);}onMounted(() => { sendRequestAndChangeData(requestParams)})</script>
OK这样把阿里云物联网平台当后端服务器,连服务器都省了,太妙了。
然后项目指导老师:
。。。。。。白忙活一场
后记:
因为项目在申请软著,就不方便展示项目页面了
项目不难,却算是我第一个独立开发完成的项目,从一开始对阿里云物联网平台,MQTT协议,ECharts,OpenAPI这些毫不了解,通过不断百度搜索学习,到后面逐渐了解使用。虽然中间走了许多弯路,做了许多无用功,哎没关系,学到东西就不亏。
这里很想贴上初中的时候对洛谷一段很有感触的话:
曾经那个在机房怀揣着梦想的初中生走上了开发的道路, 不知道以后工作再看到这篇技术含量极低的博客时是什么感想呢