传统物联网开发流程长、技术栈要求高,而阿里云 IoT 平台产品 Link Develop(下称『LD』)可以大大降低传统企业进行物联网开发的成本,下面展示一个即时上手,通过线上虚拟设备模拟物联网开发全链路的小Demo。
1. 创建产品
开通阿里云账号及 LD 平台服务。进入主控制台,立即创建产品。在本 Demo 中我们将虚拟一个 RGB 小灯,因此产品对应所属分类选择“智能生活/电工照明/灯”,节点类型选择“设备”,通讯网络选择“Wi-Fi”,数据格式选择“Alink”,然后点“提交”后点击“进入开发”按钮。
既然是 RGB 当然是五颜六色的,因此已有的开关灯功能不能满足我们的需求,在标准功能一栏右侧找到 “新增”按钮 选择 『RGB 调色功能』然后点击“确定”。
2. 虚拟设备
产品已设好,设备线上找。现在我们打开浏览器跳转至 设备虚拟页面。
在页眉处,填写设备激活凭证(前段设备添加页面『激活凭证』可得)
选择『编程脚本』,修改为下列代码:
// 监听云端消息
device.serve('property/set', params => {
console.log('receieve params:', params);
// 原样上报
console.log('post props:', params);
device.postProps(params, err => {
if (err) {
return console.log('post error:', err);
}
console.log('post successfully!');
});
});
3. 数据上云
点击运行,在右侧看到『连接成功』就表示你的虚拟小灯就正式上线了。回到 LD 控制台页面,点击平台设备列表里的设备“调试”链接,进入设备调试。在页面下方的调试功能里选择“RGB调色(RGBColor)”,方法选为“获取”。可以看到虚拟小灯的数据已经同步上传到云端。
同样我们也可以进行数据的下发,将“获取”更改为“设置”,填入以下JSON:{"RGBColor":{"Red":255,"Blue":255,"Green":0}},我们可以看到虚拟设备页面同样也接收到了云端数据的下发。
4. Web 开发
作为一站式的开发平台,仅仅是设备端到数据上云并不能满足需求,用户端的体验一样重要。同样我们可以利用 LD 平台的 bone 框架轻松进行前端的开发。
LD 平台中前端开发与设备端数据都使用加密后API进行联动,因此我们先回到 LD 项目控制台,选择“资源管理”——“添加官方服务”——“添加物的管理服务”。之后回到主页,选择左侧菜单进入“应用-Web 应用”,点击右上角的“新增应用”按钮,一路 Next,获取 AppKey 和 AppSecret。
线上的工作基本完成了,回归本地开发用机,按照 文档 安装好 Nodejs 和 Bone 框架,新建项目文件夹,进入后执行 bone init
初始化项目并安装项目依赖组件 bnpm i --save @bone/iot-gateway react-color
,修改 app/pages/home/index.js
为
import React, { Component } from 'react';
import { Button, Switch, Form, Grid, Input, Dialog } from '@bone/bone-web-ui';
import IotGateway from '@bone/iot-gateway';
import { HuePicker } from 'react-color';
const Row = Grid.Row;
const Col = Grid.Col;
const FormItem = Form.Item;
const formItemLayout = {
labelCol: {
fixedSpan: 12
},
wrapperCol: {
span: 12
}
};
const insetLayout = {
labelCol: { fixedSpan: 4 }
};
export default class App extends React.Component {
constructor(props) {
super(props);
this.state = {
switch: false,
color: '',
// 刷新页面不用重复输入
productKey: localStorage.getItem('productKey') || '',
deviceName: localStorage.getItem('deviceName') || ''
};
// 获取初始数据
this.getProps(props => {
this.setState({
switch: props.LightSwitch === 1,
color: rgbToHex(
props.RGBColor.Red,
props.RGBColor.Green,
props.RGBColor.Blue
)
});
});
}
getProps(cb) {
IotGateway.post({
url: 'https://api.link.aliyun.com/thing/device/status/query',
apiVer: '1.0.1',
params: {
ProductKey: this.state.productKey,
DeviceName: this.state.deviceName
}
}).then(res => {
if (res.code !== 200) {
throw new Error(res.localizedMsg || res.message);
}
let props = {};
res.data.forEach(item => {
props[item.attribute] = item.value;
});
if (cb) {
cb(props);
}
console.log('get props successfully:', props);
});
}
setProps(props) {
IotGateway.post({
url: 'https://api.link.aliyun.com/thing/device/properties/set',
apiVer: '1.0.1',
params: {
ThingId: {
productKey: this.state.productKey,
deviceName: this.state.deviceName
},
Items: props
}
}).then(res => {
if (res.code !== 200) {
throw new Error(res.localizedMsg || res.message);
}
console.log(res);
});
}
showValidationText() {
Dialog.alert({
title: '提示',
content: '请输入设备的 productKey 和 deviceName 才能控制设备哦'
});
}
onChange = checked => {
if (!this.state.productKey || !this.state.deviceName) {
this.showValidationText();
return;
}
this.setState({
switch: checked
});
this.setProps({
LightSwitch: checked ? 1 : 0
});
};
onInput = (field, value) => {
this.state[field] = value;
localStorage.setItem(field, value);
this.setState({
[field]: value
});
};
onColorChange = color => {
if (!this.state.productKey || !this.state.deviceName) {
this.showValidationText();
return;
}
this.setState({
color: color.hex
});
this.setProps({
RGBColor: hexToRgb(color.hex)
});
};
render() {
return (
<div style={{ padding: '30px 0 0 30px' }}>
<Form style={{ margin: '0 0 0 30px' }} {...formItemLayout}>
<FormItem label="设备 id">
<Row>
<Col>
<FormItem
label="productKey"
required={false}
labelAlign="inset"
{...insetLayout}
>
<Input
placeholder="请输入"
value={this.state.productKey}
onChange={value => this.onInput('productKey', value)}
/>
</FormItem>
</Col>
<Col>
<FormItem
label="deviceName"
required={false}
labelAlign="inset"
{...insetLayout}
>
<Input
placeholder="请输入"
value={this.state.deviceName}
onChange={value => this.onInput('deviceName', value)}
/>
</FormItem>
</Col>
</Row>
</FormItem>
<FormItem label="开关">
<Switch onChange={this.onChange} checked={this.state.switch} />
</FormItem>
<FormItem label="调色">
<div style={{ padding: '7px 0 0 10px' }}>
<HuePicker
onChangeComplete={this.onColorChange}
color={this.state.color}
/>
</div>
</FormItem>
</Form>
</div>
);
}
}
function rgbToHex(r, g, b) {
return '#' + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1);
}
function hexToRgb(hex) {
var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
return result
? {
Red: parseInt(result[1], 16),
Green: parseInt(result[2], 16),
Blue: parseInt(result[3], 16)
}
: null;
}
最后执行 bone start
,运行 Web App,现在你可以在打开的页面任意控制你的虚拟小灯了~ 每一次操作在虚拟设备页面都会得到反馈。
仅仅是虚拟设备是不是还不够,如果你有树莓派、Developerkit 等设备的话,欢迎 参考文档 进行开发体验~