HaaS 600

1.产品简介

1.1阿里云loT入门套件介绍

阿里云loT入门套件是一款基于阿里云平台和HaaS 600 为主控的物联网套件,可通过4G技术,将数据传输到阿里云物联网平台或手机上,产品支持本地热更新和在线热更新两种方式。此外HaaS 600还拥有丰富的外设接口。可应用于共享控制、智能语音、泛工业场景的智能硬件产品开发。

开发板采用JS轻应用开发,提供了完整的使用教程和例程,助你轻松搭建物联网环境。在使用教程中除了基础的应用之外我们还使用Gravity接口的传感器做了几个简单物联网项目。户外温度采集:可以远程采集温度。物流跟踪:可以远程定位。智能绿化:实现了远程数据检测和控制。智能火情装置:可以实现定点火灾报警。

1.2开发版HaaS 600介绍

HaaS 600是一款基于 HaaS 600系列模组评估的高性价比开发板。可应用于共享控制、金融支付、智能语音等场景的智能硬件产品开发。
HaaS 600 Kit 套件包含以下物料:

  • 开发板 x 1
  • micro-USB线缆 x 1
  • 5V/2A电源适配器 x 1
  • 4G天线 x 1
  • GPS天线 x 1

2.开发环境

2.1 HaaS 600开发环境教程

2.1.1 连接设备

按照下图所示将开发电脑跟设备的调试/用户串口通过MicroUSB连接,连接后,将在PC设备管理器中出现两个串口,分别用于调试和用户串口输入输出。

2.1.2 安装USB串口驱动

下面提供不同操作系统的串口驱动的下载链接

Windows XP/Vista

Windows7/8/8.1

Windows10

MacOS

下面我以Windows为例进行安装

1.下载驱动文件

首先点开Windows链接,会弹出一个下载的窗口

读者可以自己选择文件保存的路径(注:不建议安装在默认路径和C盘下),我这里保存到D:\software\work路径下,然后点击下载

2.安装驱动

找到前面下载好的文件,打开并解压

解压完成后,进入文件,根据个人电脑选择安装

我这里因为选择CP210xVCPInstaller_x64.exe,点击打开,点击下一步,点击完成即可(注:如果不知道选择哪个可以两个都尝试,看哪个能安装上)

安装完成后,当电脑连接开发板时,在设备管理器下可以看到以下虚拟串口如下图所示(设备连接参考前面2.1.1步骤)

3.注意:

  • (1).不同电脑生成的串口和名称不一样,以实际生成的为准
  • (2).生成的两个串口,一个是debuge串口(查看运行日志,只读),另一个是用户串口(JavaScript交互式解释器或其他用途)

2.1.3 开发工具

轻应用开发使用一套命令行工具管理和推送应用到设备。

1.下载命令行工具

下面分别提供Mac版和Windows版下载链接,读者可以根据自己电脑的版本进行下载安装,下面我将介绍的是Windows版本的命令行工具

Mac版

Windows版

Note:Mac版需要设置执行权限:chmod +x ./amp

将命令行工具解压到工作目录,如图所示对应文件

├── amp # 命令行工具

├── app # 示例代码(hello world)

│ ├── app.json

│ └── app.js

└── bindings.node # 本地更新库码

读者可以自己选择文件保存的路径(注:不建议安装在默认路径和C盘下),我这里保存到D:\software\work\amp-win路径下,然后点击下载

2. 解压命令行工具

由于此命令行工具是免安装的,我们只需从下载路径解压即可(注:解压路径一定要牢记,我们后期会经常用到)

我这里选择自动解压即可,读者可以自己选择解压路径,但路径一定要牢记。

2.1.4 安装git bash

前面我们已经下载好了命令行工具,那么我们具体写命令就需要我们下载一个git bush工具
我们可以直接去官网上下载,按默认配置安装即可。
点击进入官网,直接点击Download,弹出下载窗口,选择保存路径,点击下载即可

下载完成后,打开对应文件,我们看到一个可执行文件,我们点击打开,进入安装页面,我们按默认配置进行下一步安装即可。

2.1.5 HaaS轻应用使用文档

1. 轻应用介绍

(1). 轻应用总览

<1>.简介

轻应用:可运行在轻量级嵌入式设备上的JavaScript应用(左图)
轻应用框架:封装了JavaScript引擎和API接口,用于支持轻应用开发的软件框架(右图)

<2>.特点

  • 轻巧:基于事件驱动的JavaScript轻应用短小精悍,免编译、免烧录

  • 快速:结合阿里云物联网平台,一键完成应用代码热更新

  • 简单:JavaScript API 简洁易懂,大幅降低IoT嵌入式设备应用开发门槛

  • 兼容:轻松移植JavaScript生态软件包,与各类云端业务浑然一体

<3>.运行原理

<4>.丰富的组件支持

基础组件

  • 文件系统 FS

  • 系统信息 SYS

  • 键值对存储 KV

  • 电源管理 LPM

  • 硬件I/O UART/GPIO/I2C/SPI

  • 模数/数模转换 ADC/DAC

  • 脉宽调制 PWM

  • 定时器 TIMER

  • 实时时钟 RTC

  • 看门狗 WDG

  • 网络协议 UDP/TCP/HTTP/MQTT

高级组件

  • 物联网平台连接组件

  • 支付组件

  • 语音组件

  • 传感器服务组件

  • 定位服务组件

  • 外设驱动库

– 编码电机/步进电机/伺服电机/继电器

– 麦克风/语音录放模块/扬声器

– PS2摇杆/电容触摸/按键

– TFT彩屏/数码管/三色灯

– 加速度计/陀螺仪/电子罗盘/气压计/磁力计

– 温湿度/颜色/光照强度

– 更多

<5>.文件结构

一个最精简的轻应用包由最少两个文件组成,必须放在项目文件夹的根目录
app/

├── app.js # 业务逻辑入口

└── app.json # 全局配置

<6>.开发流程

  • 编写轻应用代码

  • 一键热更新

如下图:

<7>.轻应用 vs Native C/C++应用

(2).app.js - 轻应用入口文件

<1>.示例代码:

App({
  onLaunch: function() {
    // 第一次打开
    console.log('app onLaunch');
  },
  onError: function() {
    // 出现错误
    console.log('app onError');
  },
  onExit: function() {
    // 退出轻应用
    console.log('app onExit');
  }
});

<2>.轻应用入口:

App(Object options)

App() 用于注册轻应用,接受一个 Object 作为属性,用来配置轻应用的生命周期等。 App() 必须在 app.js 中调用,必须调用且只能调用一次。

其中options属性有:

属性 类型 描述 触发时机
onLaunch() Function 生命周期回调:监听轻应用初始化 初始化 当轻应用初始化后触发,全局只触发一次
onError() Function 监听轻应用错误 当轻应用发生js错误时触发
onExit() Function 生命周期回调:监听轻应用退出 当轻应用退出后触发,全局只触发一次

<3>.生命周期:

onLaunch()

轻应用启动时的hook函数。

onError()

轻应用出现错误的hook函数。

onExit()

轻应用退出时的hook函数。

(3).app.json - 全局配置文件

app.json 用于对轻应用进行全局配置,设置页面文件的路径、硬件I/O口的配置等。以下是一个基本配置示例:

{
  "version": "0.0.1",
  "io": {
    "D1": {
      "type": "GPIO",
      "port": 31,
      "dir": "output",
      "pull": "pullup"
    },
    "D2": {
      "type": "GPIO",
      "port": 32,
      "dir": "output",
      "pull": "pullup"
    },
    "D3": {
      "type": "GPIO",
      "port": 33,
      "dir": "output",
      "pull": "pullup"
    }
  },
  "debugLevel": "DEBUG",
  "repl": "enable"
}

完整配置如下:

配置项 类型 是否必填 描述
version String 否 IoT轻应用版本号
io Object 是 硬件接口配置
debugLevel String 否 设置日志等级,默认为ERROR
repl String 否 设置repl开关,默认打开设置为enable,关闭设置为disable

在JS应用代码中,通过appConfig可以获取到app.json中的内容。

<1>.version 配置项

轻应用版本号。

<2>.io 配置项

不同的模组/芯片,各个端口和管脚的功能映射可能是不一样的。IoT轻应用的配置文件 app.json中,可将硬件(芯片)的物理端口映射成为统一的应用层逻辑端口。

这样映射的好处是在替换不同的硬件或者芯片时,只需要替换 app.json 而不用修改应用程序或设备程序,从而便于应用的跨平台运行。

IO配置项中有 type port等硬件描述概念,对于每一款硬件(通常是芯片/模组/开发板)该配置文件均可能不同。

语法描述格式定义如下:

{
  "io": {
   "D1":{
      "type":"GPIO",
      "port":12,
      "dir":"output",
      "pull":"pullup"
    },
    "I2C0":{
      "type":"I2C",
      "port":0,
      "mode":"master",
      "addrWidth":7,
      "devAddr":270,
      "freq":100000
    }
  },
  "debugLevel": "DEBUG"
}

解释:

  • D1 I2C0:定义对象,后面大括号里面则描述了该对象的类型。 定义后可以在 JS 中直接使用。

  • type: 描述了该对象的类型,可以是IoT轻应用支持的硬件扩展类型,如 GPIO,I2C,ADC 等。

  • port:描述了该对象的端口,这里需要根据实际硬件连接及芯片的PIN 脚映射关系来填写。

  • dirpull: 是 GPIO 类型特有的,用于描述 GPIO 输出输出及上拉下拉,其他如 ADC 类型则有 sampling 采样频率这种类型描述。

外设 type 说明

io配置项的 type 用于描述该对象是什么硬件端口类型,而每一种type也拥有不同的属性字段,如 GPIO 与 ADC 的属性字段是不一样的。

GPIO

示例

{
  "io": {
    "D3": {
        "type": "GPIO",
        "port": 22,
        "dir": "output",
        "pull": "pullup"
    },
    "D4": {
        "type": "GPIO",
        "port": 23,
        "dir": "irq",
        "pull": "pullup",
        "intMode": "rising"
    }
  },
  "debugLevel": "DEBUG"
}

UART

示例

{
  "io": {
    "UART1":{
      "type":"UART",
      "port":1,
      "dataWidth":3,
      "baudRate":9600,
      "stopBits":1,
      "flowControl":"disable",
      "parity":"none"
    },
    "UART2":{
      "type":"UART",
      "port":2,
      "dataWidth":3,
      "baudRate":115200,
      "stopBits":1,
      "flowControl":"disable",
      "parity":"none"
    }
  },
  "debugLevel": "DEBUG"
}

I2C

属性字段 数据类型 属性值 是否必须 字段说明
port Number 1 是 配置端口值,这里跟芯片 datasheet 上的端口对应
addrWidth Number 7 或 10 否 配置 I2C 总线地址宽度,默认 7
freq Number 100000、400000等 否 配置 I2C 总线主从模式,默认 master
mode String master 或 slave 否 配置 I2C 总线主从模式,默认 master
devAddr Number 224等 否 配置 I2C 从设备地址,默认 224

SPI

属性字段 数据类型 属性值 是否必须 字段说明
port Number 1 是 配置端口值,这里跟芯片 datasheet 上的端口对应
mode String master 或 slave 否 配置 SPI 总线模式,默认 master
freq Number 3250000、6500000等 是 配置 SPI 总线频率

示例

{
  "io": {
    "SPI1":{
      "type":"SPI",
      "port":1,
      "mode":"master",
      "freq":3250000
    }
  },
  "debugLevel": "DEBUG"
}

ADC

属性字段 数据类型 属性值 是否必须 字段说明
port Number 1 是 配置端口值,这里跟芯片 datasheet 上的端口对应
sampling Number 12000000 否 配置 ADC 采样率

示例

{
  "io": {
    "voltage": {
        "type": "ADC",
      "port": 1,
      "sampling": 12000000
    }
  },
  "debugLevel": "DEBUG"
}

DAC

属性字段 数据类型 属性值 是否必须 字段说明
port Number 1 是 配置端口值,这里跟芯片 datasheet 上的端口对应

示例

{
  "io": {
    "DAC1": {
      "type": "DAC",
      "port": 1
    }
  },
  "debugLevel": "DEBUG"
}

PWM

属性字段 数据类型 属性值 是否必须 字段说明
port Number 1 是 配置端口值,这里跟芯片 datasheet 上的端口对应

示例

{
  "io": {
    "PWM1": {
      "type": "PWM",
      "port": 1
    }
  },
  "debugLevel": "DEBUG"
}

TIMER

属性字段 数据类型 属性值 是否必须 字段说明
port Number 1 是 配置端口值,这里跟芯片 datasheet 上的端口对应

示例

{
  "io": {
    "TIMER1": {
        "type": "TIMER",
      "port": 1
    }
  },
  "debugLevel": "DEBUG"
}

<4>.debugLevel>debugLevel**

配置调试日志等级,分为如下几个等级,默认为ERROR

等级 说明
DEBUG 显示debug级别的日志
INFO 显示info级别的日志
WARN 显示warning级别的日志
ERROR 显示error级别的日志
FATAL 显示fatal级别的日志

<5>repl(交互式解析器)>repl(交互式解析器)**

配置交互式解析器开关,默认打开。

值 说明
enable 打开repl功能
disable 关闭repl功能

示例

{
  "version": "1.0.0",
  "io": {
    "D1": {
      "type": "GPIO",
      "port": 31,
      "dir": "output",
      "pull": "pullup"
    }
  },
  "debugLevel": "DEBUG",
  "repl": "disable"
}

2.开发指南

(1).公测申请

轻应用可用于轻量级嵌入式智能设备的快速开发,除了支持MCU, WiFi SoC等硬件平台外,还结合LTE Cat.1模组,重点推出面向共享控制、智能语音、金融支付等行业场景的IoT参考方案。

邮件申请

为了更好的了解您的产品需求,请将相关信息发送邮件至aliosthings@service.aliyun.com(点击创建邮件模板),待评估后将会提供SDK软件包。

(2).命令行工具

用于轻应用的辅助开发,以简单的命令行方式运行在Mac或Windows电脑上的工具,我们称之为命令行工具。命令行工具主要是用来推送设备应用脚本到设备端,并拥有一套完整的命令,可以完成设备的应用热更新、运维服务、日志服务等。

<1>.工具包

•Mac版

•Windows版

├── amp # 命令行工具

├── app # 应用脚本

│ ├── app.json

│ └── app.js

└── bindings.node # 本地更新库

打开app.js,这里就运行了我们的业务应用代码,默认打印系统信息。

<2>.命令行

命令名称

$ amp

IoT轻应用命令行工具可以对设备进行热更新操作,支持 本地热更新 和 在线热更新 功能。

Mac版需要设置执行权限:chmod +x ./amp。

Mac上执行amp命令时会遇到权限问题。

1).命令总览

命令 说明 示例
login 命令行登录 amp login
device list 列出绑定的设备 amp device list
put 推送应用代码到设备端(在线热更新) amp put [device-name]
seriallist 列出电脑的所有串口 amp seriallist
serialput 通过串口更新应用(本地更新) amp serialput -t
version 版本号 amp --version
help 帮助 amp --help

<3>.命令详解

1).login - 登录

参数

amp login <your-token>

说明

使用在线热更新前,需要获取,该命令用于登录和绑定用户的唯一token,仅需执行一次。

使用本地热更新时,无需绑定用户token。

token及其SDK包请通过公测申请获取。

示例

$ amp login b8805cfefe8b2dd2f069e638a0162d0e

2).device list - 列出绑定的设备

参数

amp device list

说明

在amp login 成功后,使用该命令可列出您账号下已绑定的设备名称,建议使用IMEI号作为设备名称。

示例

$ amp device list
Your bound devices:
8675*******3456
8675*******4321
3522*******7456

<4>.put - 在线热更新

参数

amp put

<app-dir>指当前目录下app目录,包含板级配置文件和JS脚本文件
device_name 指绑定列表中的设备名称

说明

  注意:使用前,请参考在线热更新确定模组固件版本、设备绑定及设备联网等是否已完成。

通过该命令可远程推送轻应用到指定的设备,其中 app-dir 和 以实际为准。

 该命令会消耗网络流量,推送应用到蜂窝模组时请按需使用。

示例

$ amp device list
Your bound devices:
8675*******3456
$ ./amp put ./app 8675*******3456
device:8675*******3456 ONLINE.
generate app package
push app package SUCCESS
若出现OFFLINE,可能由于设备尚未联网成功。

<5>.seriallist - 列出电脑串口

参数

amp seriallist

说明

列出电脑上的所有串口,确定本地热更新的串口号

示例

/ Mac
$ amp seriallist
/dev/tty.usbserial-AK08LNMO
/dev/tty.usbserial-AK08LNMM

// Win
$ amp seriallist
COM59
COM60

<6>.serialput - 通过串口推送轻应用到设备(本地热更新

参数

amp serialput <app-dir> <serial-port>

或

amp serialput <app-dir> <serial-port> -t <type>

说明

注意:使用前,请参考应用热更新确定硬件连接、模组固件和是否进入下载模式
通过串口推送轻应用到设备(本地更新)。

type:

  • ymodem(默认)

示例

$ amp seriallist
COM59
// usb口以实际情况为准
$ amp serialput ./app COM59 -t ymodem
device type: ymodem
generate app package
put complete!

<7>.version - 查看版本号

// 版本号以实际为准
$ ./amp --version
1.0.3

<8>.help - 帮助

$ ./amp --help
Usage: amp [options]
AliOS Things Mini Program PC CLI tool
Options:
 -V, --version                          output the version number
 -h, --help                             output usage information
Commands:
 login <token>                          login
 device list                                list bind devices
 put <filepath> <deviceName>            upload file to device
 seriallist                             list serial port
 serialput [options] <filepath> <port>  put file to device via serial port

<9>.FAQ

A:在运行amp命令时,Mac系统可能会出现应用信任问题,在运行命令时可能会报出如下错误。

点击取消,然后进入系统偏好设置,打开安全性隐私,选择仍然允许,如下图所示

再次运行amp命令,出现如下提示,点击打开即可完成对amp的信任。

此时,系统又会弹出bindings.node无法验证的对话框,跟amp同样的问题,再次验证即可

点击取消,然后进入系统偏好设置,打开安全性隐私,选择仍然允许,如下图所示

此时命令行工具可能会报如下错误,不用理会。

Error: dlopen(/Users/ljh/Downloads/amp-macos/bindings.node, 1): no suitable image found.  Did find:
    /Users/ljh/Downloads/amp-macos/bindings.node: code signature in (/Users/ljh/Downloads/amp-macos/bindings.node) not valid for use in process using Library Validation: library load disallowed by system policy
    at Object.Module._extensions..node (internal/modules/cjs/loader.js:805:18)
    at Module.load (internal/modules/cjs/loader.js:651:32)
    at tryModuleLoad (internal/modules/cjs/loader.js:591:12)
    at Function.Module._load (internal/modules/cjs/loader.js:583:3)
    at Module.require (internal/modules/cjs/loader.js:690:17)
    at Module.require (pkg/prelude/bootstrap.js:1225:31)
    at require (internal/modules/cjs/helpers.js:25:18)
    at bindings (/snapshot/amp-cli/node_modules/bindings/bindings.js:112:48)
    at Object.<anonymous> (/snapshot/amp-cli/node_modules/@serialport/bindings/lib/darwin.js:2:36)
    at Module._compile (pkg/prelude/bootstrap.js:1320:22)

再次运行amp命令,出现如下提示,点击打开即可完成对bindings.node的信任。

(3).应用热更新

不同于传统嵌入式开发流程,轻应用的JavaScript应用在PC端开发完成后,无需编译、链接、固件烧录等繁琐步骤,用户可直接使用命令行工具动态推送最新的应用到指定设备,这个过程我们称之为应用热更新,轻应用支持本地应用热更新和在线应用热更新两种方式:

  • 本地热更新:通过有线方式(串口)对设备的应用进行更新,尤其是设备无法联网或轻应用的代码异常。

  • 在线热更新:通过无线方式(网络)对设备的应用进行更新,如设备不在本地或不支持与开发机的有线连接。

<1>.准备

  • 公测申请,获取轻应用SDK包

  • 为了更好的了解您的产品需求,请将相关信息发送邮件至aliosthings@service.aliyun.com(点击创建邮件模板),待评估后将会提供SDK软件包。

  • 硬件Ready,如HaaS 600

<2>.本地热更新

通过有线方式(串口)对设备的应用进行更新,可适用于设备无法联网或轻应用代码运行异常的情况。

下载模式

本地热更新与实际硬件的接线强相关,以HaaS 600为例,需先切到下载模式(参考HaaS 600)。

更新应用

进入下载模式后,运行amp命令完成本地更新:

$ amp serialput <app-dir> <serial-port>

运行示例:

$ ./amp serialput ./app /dev/tty.SLAB_USBtoUART
device type: ymodem
generate app package
put complete!

其中/dev/tty.SLAB_USBtoUART 对应的串口连接硬件的本地更新端口。

<3>.在线热更新

通过无线方式(网络)对设备进行热更新。当设备不在本地或者设备无法跟电脑连接的时候,可以通过网络通道将轻应用代码下发到设备,类似OTA功能。步骤如下:

该命令会消耗网络流量,推送应用到蜂窝模组时请按需使用。

用户登陆

amp login <your-token>
此处的 <your-token> 来自公测申请的轻应用SDK包。
$ amp login <token>
login success

查看设备

amp device list

查看当前已绑定的设备列表。

$ amp device list
Your bound devices:
<device_name1>
<device_name2>

更新应用

amp put ./app <device_name>
* ./app指当前目录下app目录,包含板级配置文件和脚本文件。
* device_name指绑定列表中的设备名称。

运行示例

$ ./amp login 9da64dd7e367********c02655a8abcd
login success

$ ./amp device list
Your bound devices:
8675*******3456
8675*******4321
3522*******7456

$ ./amp put ./app 8675*******3456
device:8675*******3456 ONLINE.
generate app package
push app package SUCCESS

2.1.6 第一个轻应用示例

查看设备连接状态
找到下载好的轻应用工具,找到解压后的路径,鼠标右键选择Git Bash Here进入命令行,如下图所示

在命令行工具下使用该命令查看设备连接状态

./amp.exe seriallist
COM194
COM195

Note:

1.如果返回值跟设备管理器中生成的一致,说明设备连接和命令行工具运行正常
命令行工具默认示例代码运行hello world程序,此处使用LED Blink来作为第一个轻应用示例来介绍。
使用下面的app.js 和 app.json文件替换命令行工具示例代码目录下的同名文件,如下:
2.不同电脑生成的串口和名称不一样,以实际生成的为准
3.生成的两个串口,一个是debuge串口(查看运行日志,只读),另一个是用户串口(JavaScript交互式解释器或其他用途)

LED Blink app.json

{
    "version": "1.0.0",
    "io": {
        "D13": {
            "type": "GPIO",
            "port": 33,
            "dir": "output",
            "pull": "pulldown"
        }
    },
    "debugLevel": "DEBUG"
}

LED Blink app.js:

var gpio = require('gpio');

var led = gpio.open({
  id: 'D13'
});

var vol = 0;

setInterval(function() {
 vol = 1 - vol;
  
 led.writeValue(vol);
 console.log('gpio: led set value ' + vol);
 
 vol = led.readValue();
 console.log('gpio: led get value ' + vol); 
}, 1000);

本地热更新

  • 切换到下载模式

将下载/运行模式切换开关(MODE)拨到DL侧,并通过电源选择开关(POWER SWITCH)断电重启,稍等片刻待AMP_STU指示灯间歇性双闪,如下图,说明设备已经进入本地下载模式。

  • 通过amp工具推送应用代码到设备
./amp.exe seriallist
COM194
COM195

Note:

Windows环境下,热更新命令的串口号需要大写。

  • 切换到运行模式(RUN)并复位
  • 运行效果如图:

在线热更新

在已插SIM卡有网络连接的情况下,也可参考在线应用热更新推送轻应用代码到目标设备。

附录

硬件资源介绍

硬件资源映射表

功能列表(部分)

硬件I/O

  • UART

  • GPIO

  • I2C

  • SPI

  • ADC

  • PWM

app.json 参考示例

{
  "version": "1.0.0",
  "io": {
    "I2C0": {
      "type": "I2C",
      "port": 0,
      "addrWidth": 7,
      "freq": 400000,
      "mode": "master",
      "devAddr": 72
    },
    "ADC0": {
      "type": "ADC",
      "port": 0,
      "sampling": 12000000
    },
    "ADC1": {
      "type": "ADC",
      "port": 1,
      "sampling": 12000000
    },
    "UART1": {
      "type": "UART",
      "port": 1,
      "dataWidth": 8,
      "baudRate": 9600,
      "stopBits": 1,
      "flowControl": "cts",
      "parity": "none"
    },
    "UART2": {
      "type": "UART",
      "port": 2,
      "dataWidth": 8,
      "baudRate": 115200,
      "stopBits": 1,
      "flowControl": "disable",
      "parity": "none"
    },
    "SPI1": {
      "type": "SPI",
      "port": 1,
      "mode": "master",
      "freq": 3250000
    },
    "PWM0": {
      "type": "PWM",
      "port": 31,
      "mode": "master",
      "freq": 3250000
    },
    "PWM1": {
      "type": "PWM",
      "port": 32,
      "mode": "master",
      "freq": 3250000
    },
    "D0": {
      "type": "GPIO",
      "port": 51,
      "dir": "output",
      "pull": "pulldown"
    },
    "D1": {
      "type": "GPIO",
      "port": 52,
      "dir": "output",
      "pull": "pulldown"
    },
    "D2": {
      "type": "GPIO",
      "port": 17,
      "dir": "irq",
      "pull": "pulldown",
      "intMode": "both"
    },
    "D3": {
      "type": "GPIO",
      "port": 16,
      "dir": "irq",
      "pull": "pullup",
      "intMode": "both"
    },
    "D4": {
      "type": "GPIO",
      "port": 59,
      "dir": "output",
      "pull": "pulldown"
    },
    "D5": {
      "type": "GPIO",
      "port": 121,
      "dir": "output",
      "pull": "pulldown"
    },
    "D6": {
      "type": "GPIO",
      "port": 54,
      "dir": "output",
      "pull": "pulldown"
    },
    "D7": {
      "type": "GPIO",
      "port": 53,
      "dir": "output",
      "pull": "pulldown"
    },
    "D8": {
      "type": "GPIO",
      "port": 124,
      "dir": "output",
      "pull": "pulldown"
    },
    "D9": {
      "type": "GPIO",
      "port": 122,
      "dir": "output",
      "pull": "pulldown"
    },
    "D10": {
      "type": "GPIO",
      "port": 34,
      "dir": "output",
      "pull": "pulldown"
    },
    "D11": {
      "type": "GPIO",
      "port": 36,
      "dir": "output",
      "pull": "pulldown"
    },
    "D12": {
      "type": "GPIO",
      "port": 35,
      "dir": "output",
      "pull": "pulldown"
    },
    "D13": {
      "type": "GPIO",
      "port": 33,
      "dir": "output",
      "pull": "pulldown"
    },
    "D14": {
      "type": "GPIO",
      "port": 57,
      "dir": "output",
      "pull": "pulldown"
    },
    "D15": {
      "type": "GPIO",
      "port": 32,
      "dir": "output",
      "pull": "pulldown"
    },
    "D16": {
      "type": "GPIO",
      "port": 31,
      "dir": "output",
      "pull": "pulldown"
    },
    "D17": {
      "type": "GPIO",
      "port": 76,
      "dir": "output",
      "pull": "pulldown"
    }
  },
  "debugLevel": "DEBUG",
  "repl": "disable"
}

更多示例代码

Git 仓库:

https://gitee.com/alios-things/amp-examples/tree/master/board/HaaS600Kit

打包下载(需注册gitee账号):

https://gitee.com/alios-things/amp-examples/repository/archive/master.zip

2.2 阿里云物联网平台简介

2.2.1 认识阿里云 loT

阿里云 IoT 致力于实现万物互联的美好世界,为生态合作伙伴提供基于云端一体化、安 全物联网基础平等,在通过该平台高效连接,管理设备的同时,其开放能力使合作伙伴更 高效、低成本地构建各种创新的物联网应用场景。

阿里云物联网平台为设备提供安全可靠的连接通信能力,向下连接海量设备,支撑设备 数据采集上云;向上提供云端 API,指令数据通过 API 调用下发至设备端,实现远程控制。

此外阿里云 IoT 还提供了丰富的开发服务,用户可以直接在该平台上搭建 Web 可视化、 移动应用、服务开发等开发服务,这降低了物联网项目开发的难度,有了它,用户无需任何 专业的开发技巧也可开发自己的项目。

2.2.2 注册并登录阿里云账号

打开谷歌浏览器,输入网址 https://iot.aliyun.com,进入阿里云 IoT 界面,如图 1 所示, 点击登陆,在密码登陆栏点击免费注册,进入阿里云账号注册界面(若已有账号可直接登陆), 如图 2 所示,按要求完成注册可。

图 1 阿里云 IoT 主界面

图 2 账号注册界面

2.2.3 实名认证

第一次使用,需进行实名认证,在注册完成后,会回到主页面。在用户名栏点击实名 认证,根据提示操作完成认证即可。 (如果没有回到主页面,我们登录。点击右上角我的阿里云,点击进入,会看到我的账户,未实名用户按照要求进行实名认证即可)

2.2.4 开通物联网服务

当我们实名认证成功后,是没有服务的。所以我们需要自己开通物联网服务。

  • 1.点击首页的菜单键。
  • 2.选择“物联网产品”选项。
  • 3.选择”云服务”选择。
  • 4.点击”物联网平台”。

进入后选择开通物联网服务,根据提示进行操作,直到完成。由于我已经开通了互联网服务,所以就显示开完成

未开通的选择开通物联网服务,按照提示步骤进行操作,直到提示服务开通成功。

2.2.5 登录物联网平台控制台

物联网平台是阿里云 IoT 的控制台,阿里云上有关物联网的操作,都必须在该平台上进 行,如本教程中提到的产品创建、设备添加、服务创建等,都需要在该控制台上进行。

打开谷歌浏览器,输入网址 https://iot.aliyun.com,并登录。登录成功后,按如下步骤进入物联网控制平台

  • 1.点击首页的菜单键。
  • 2.选择“物联网产品”选项。
  • 3.选择”云服务”选择。
  • 4.点击”物联网平台”。

然后点击进入控制台即可

如果没有开通物联网服务,请参考2.2.4 节讲解。

进入物联网平台控制台如下图所示

用户可以在该控制台完成产品及设备的创建,以及相应服务开发,该教程的所有步骤都与该控制台相关。

2.2.6 使用物联网平台

1.创建产品

登录并进入物联网平台控制台(参考2.2.5 节讲解),首先点击公共实例

在左侧导航栏选择设备管理->产品, 单击创建产品,弹出“新建产品”提示框,如图所示

按照页面提示,填写信息,例创建一个名为 LED 灯的产品,单击保存。

产品创建完成后,会自动出现在产品列表中。接下来为产品定义相应的功能。

在产品列表中找到刚才创建的产品,单击该产品的查看按钮,进入产品详情页,点击功能定义,点击编辑草稿,在自定义功能栏,单击添加功能。按照页面提示,填写信息(注:要留意产品标识符,会用于 HaaS 600 与阿里云平台之间的连接,该产品标识符可在自定义功能栏查看),点击完成。具体设置参考下图 所示:

功能添加完成后,会自动出现在自定义功能栏,我们可以在这里查看产品的标识符,如图 所示:

2.创建设备

登录并进入物联网平台控制台(可参考 2.2.5 小节),在左侧导航栏选择设备管理->设备, 单击添加设备,选择一个已创建的产品。选择后,新建的设备将继承该产品定义好的功能和 特性。填入 DeviceName。如果不填,系统将自动生成,用以标识设备(用于标识同一产品下的多个设备)。具体设置步骤参考下图。

点击确认,完成设备创建,点击查看可以查看设备信息。

点击查看设备证书

你可以查看、复制设备证书信息。设备证书又名设备三元组,由设备 ProductKey、 DeviceName、和DeviceSecret 组成,是设备与物联网平台进行通信的重要身份认证,建 议您妥善保管。

  • ProductKey:物联网平台为您创建的产品颁发的全局唯一标识符。
  • DeviceName:设备在产品内的唯一标识符,用于设备认证和通信。
  • DeviceSecret:物联网平台为设备颁发的设备秘钥,用于认证加密,需与 DeviceName 成对使用。

此外在设备详情页,单击 Topic 列表,即可查看设备的上报及订阅 TOPIC。该信息用于设定设备与物联网平台进行通信是设备信息上传,还是云端数据下发,或二者兼之。

3.物联网开发服务

物联网开发服务是阿里云针对物联网领域提供的开发服务,可覆盖各物联网行业核心应 用场景,旨在解决物联网开发领域开发链路长、技术栈复杂、协同成本高、方案移植困难等 问题。开发服务提供了 Web 可视化开发、移动可视化开发和服务开发工作台等便携的物联 网开发工具。

无论是哪种服务开发,都必须先建立一个项目,然后再在该项目下创建服务。在这里我只简单的介绍如何创建项目,导入产品,以及如何进入服务创建页面。

(1).创建项目

登录并进入物联网平台控制台(可参考 2.2.5 小节),在左侧导航栏选择相关产品->IoT Studio如图所示:

进入一个新的页面,在左侧导航栏单击项目管理,单击新建项目,选择创建空白项目。根据提示,填写信息,如图 所示:

单击确认,项目创建完成后,会自动进入到项目中,如下图所示:

(2).导入产品

在项目列表中找到刚才创建的项目(智能灯光),单击,进入该项目概览页。我们可以 在该页面下导入已经创建好的产品(注:已经在项目中的产品,无法再导入其他项目),点击 概览页中的产品,再点击关联物联网平台产品,弹出关联产品对话框,选择要导入该项目的 产品,如图所示。

产品导入成功后,该页面的关联产品数量就会发生变化。这个时候,我们选择关联之前 创建的设备,或者在该产品下新建一个设备,如果是关联设备的话,操作如下图所示,点击 设备,选择关联设备,然后选择刚才导入产品下挂载的设备导入即可。

在项目下随机生成一个设备的方法:

以下的应用都以随机生成设备的方式进行操 作,不再使用导入的方式进行制作。如需要外部导入设备的,请参照2.2.6 节上面的步骤!

可以选择对信息进行查看,选中左侧导航栏的设备管理->产品,即可查看导入的产品,点击左侧导航栏的设备管理->设备,即可查看产品中挂载的设备。用户可以通过此方法查看 相应产品和设备的信息;用户也可在项目下直接创建产品和设备,不过需要注意的是在这里创建的设备的名字是由系统自动生成的,无法用户自定义。

设备创建完成后,进行参数格式的验证,操作步骤如下图所示:

以上步骤都完成后,接下来就可以进行开发服务了

(3).Web可视化开发

<1>.新建Web可视化

登录物联网平台控制台,具体操作参考2.2.5小节,登录完成后,选择左侧导航栏相关产品>loT Studio,如图所示。

点击后进入新的页面,先择左侧导航栏的应用开发,选中 页面中的Web 可视化开发选项,点击新建,即可进入 Web 可视化配置界面。 在弹出的移动可视化开发页面,填写应用名称信息,单击完成。该名称即为 Web 的名称。

<2>.Web页面编辑

创建完成后,自动进入Web编辑页面,将自定义新增页1改为LED

添加组件:添加指示灯。将指示灯拖到画布中,然后配置数据源,产品配置为 LED 灯,设备配置为刚才

在项目中创建的设备,属性为工作状态,点击验证数据格式,再点击确定,这就配置完成了。

添加开关。将开关拖到画布中,然后配置参数,产品配置为 LED 灯, 设备配置为刚才在项目 中创建的设备,属性为工作状态,点击确定。

可用账户设置(可选):

Web 可视化如果要移植使用,需要绑定域名,为了安全需要,绑定域名使用阿里云设置了付费。如果需要移植使用的,可参考设置->域名管理,CDN 付费原则。如果只是个人需要不必添加域名,默认系统的域名即可。

<3>. Web可视化发布:

点击右上角的发布选项,然后跳到第二张图,备注网页信息,不用填写,直接点击确定,然 后得到网页链接。注意:如果不需要绑定域名,直接点击网页链接,不要点击其他选择。

<4>.Web查看:

Web 的页面已经生成,可直接在网页上点击开关按钮,实物 LED 就会执行相应的命令。

至此,一个 Web 可视化开发就完成了。

3.基础教程

3.1 hello world

3.1.1 例程

板级配置

{  "version": "1.0.0",  "io": {},  "debugLevel": "DEBUG" }

业务脚本

console.log('hello amp!');
setInterval(function () {
 console.log('Hello World, time: ' + new Date());
}, 1000);

3.2 点亮一个LED灯

3.2.1例程

板级配置

{
  "io": {
    "D13": {
        "type": "GPIO",
        "port": 33,
        "dir": "output",
        "pull": "pulldown"
    },
    "D3": {
       "type": "GPIO",
       "port": 16,
       "dir": "irq",
       "pull": "pullup",
       "intMode":"both"
    }
  },
  "debugLevel": "DEBUG"
}

业务脚本

var gpio = require('gpio');

// led
var led = gpio.open({
  id: 'D13'
});

// set led gpio level
led.writeValue(1);

// led toggle
led.toggle();

// key
var key = gpio.open({
  id: 'D3'
});

//key trigger callback
key.onIRQ({
  cb: function() {
    console.log('key pressed\n');
  }
});

// release led&key
// led.close();
// key.close();

3.2.2 API讲解

open(Object options)

打开GPIO接口,创建 GPIO 实例。

入参

Object类型,属性如下:

属性 类型 必填 描述
id String 是 在app.json中定义的GPIO id名称

返回

GPIO实例。

GPIO 实例

GPIO.writeValue(Number level)

设置GPIO电平值,GPIO引脚为输出模式时可用。

入参

属性 类型 必填 描述
level Number 是 电平值,1(高电平) 或者 0(低电平)

GPIO.toggle()

切换GPIO的电平,当前GPIO电平为低电平时设置为高电平,当前GPIO电平为高电平时设置为低电平。

GPIO.onIRQ(Function cb)

开启引脚中断触发,引脚为输入模式时可用。

入参

属性 类型 必填 描述
cb Function 否 引脚中断触发回调函数

GPIO.readValue()

读取GPIO电平值,输入模式和输出模式时均可用。

返回值

Number类型,电平值,1(高电平) 或者 0(低电平)。

GPIO.close()

关闭GPIO实例。

3.3 ADC-模数转换

3.3.1 例程

板级配置

{
  "version": "1.0.0",
  "io": {
    "ADC0": {
      "type": "ADC",
      "port": 0,
      "sampling": 12000000
    },
    "ADC1": {
      "type": "ADC",
      "port": 1,
      "sampling": 12000000
    }
  },
  "debugLevel": "DEBUG"
}

业务脚本

var adc = require('adc');

// voltage
var vol = adc.open({
  id: 'ADC0'
});

var value;
// read voltage
setInterval(function() {
  // read adc value
  value = vol.readValue();

  console.log('adc value is ' + value);
}, 1000);

// vol.close();

3.3.2 API讲解

open(Object options)

打开ADC,创建 ADC 实例。

入参

属性 类型 必填 描述
id String 是 在app.json中定义的ADC id名称。

返回

ADC实例。

ADC实例。

ADC.readValue()

读取ADC数据。

返回值

  • Number类型,读取到的ADC数据。

ADC.close()

关闭ADC实例。

3.4 PWM-脉冲宽度调制

3.4.1 例程

板级配置

{
  "version": "1.0.0",
  "io": {
    "PWM0":{
      "type":"PWM",
      "port":31,
      "mode":"master",
      "freq":3250000
    },
    "PWM1":{
      "type":"PWM",
      "port":32,
      "mode":"master",
      "freq":3250000
    }
  },
  "debugLevel": "DEBUG"
}

业务脚本

var pwm = require('pwm');

var pwm0 = pwm.open({
  id: 'PWM0'
});

var freq = pwm0 .get().freq
var duty = pwm0 .get().duty

console.log('pwm: pwm default config freq is ' + freq + ' duty is ' + duty)

duty = 0;

setInterval(function(){
  if (duty >= 100) {
    duty = 0;
  }
  duty  = duty + 20;

  pwm0 .set({
    freq: 100,
    duty: duty
  })
},1000);

3.4.2 API讲解

open(Object options)

打开PWM,创建 PWM 实例。

入参

属性 类型 必填 描述
id String 是 在app.json中定义的PWM id名称。

返回

PWM实例。

PWM实例

PWM.set(Number duty, Number freq)

设置PWM参数,同时会启动PWM输出。

入参

属性 类型 描述
duty Number 设置PWM占空比,范围是0 ~ 100,单位是百分比
freq Number 设置PWM的频率,单位是HZ

PWM.get()

获取PWM参数。

返回值

Object类型,详细的属性为:

属性 类型 描述
duty Number PWM占空比。
freq Number PWM的频率。

PWM.close()

关闭PWM实例,同时也会停止PWM输出。

3.5 I2C-串行总线

3.5.1 例程

板级配置

{
  "version": "1.0.0",
  "io": {
    "I2C0": {
      "type": "I2C",
      "port": 0,
      "addrWidth": 7,
      "freq": 400000,
      "mode": "master",
      "devAddr": 72
    }
  },
  "debugLevel": "DEBUG"
}

业务脚本

var i2c = require('i2c');

var lm75 = i2c.open({
  id: 'I2C0'
});

function lm75tmpGet()
{
 var temp;
 var sig = 1;
 var regval = lm75.readMem(0x00, 2);
 console.log('read regval is ' + regval);
 var tempAll = (regval[0] << 8) + regval[1];
 console.log('tempAll is ' + tempAll);

 if (regval[0] & 0x80 != 0) {
  tempAll = ~(tempAll) + 1;
  sig = -1;
 }

 tempAll = tempAll >> 5;
 console.log('tempAll final data ' + tempAll);
 temp = tempAll * 0.125 * sig;

 return temp;
}

setInterval(function(){
 temp = lm75tmpGet();
 console.log('lm75 data is ' + temp);
},1000);

3.5.2 API讲解

open(Object options)

打开I2C,创建 I2C 实例。

入参

属性 类型 必填 描述
id String 是 指定要打开的I2C端口。

返回

I2C实例。

I2C 实例

I2C.write(String|ArrayBuffer data)

发送数据,该函数为阻塞函数,I2C发送完成后才会返回。

入参

属性 类型 必填 描述
data String或ArrayBuffer 是 要发送的数据

I2C.writeMem(ArrayBuffer memaddr, String|ArrayBuffer data)

向寄存器地址memaddr发送数据,该函数为阻塞函数,I2C发送完成后才会返回。

入参

属性 类型 必填 描述
memaddr Number 是 寄存器地址memaddr
data String或ArrayBuffer 是 要发送的数据

I2C.read(Number bytes)

主动读取指定bytes的I2C数据。该函数为阻塞函数,会一直等待读取指定bytes的数据。

入参

属性 类型 必填 描述
bytes Number 是 需要读取的字节个数

返回值

ArrayBuffer类型,读取到的I2C数据。

I2C.readMem(String|ArrayBuffer memaddr, Number bytes)

主动向寄存器地址memaddr读取指定bytes的I2C数据。该函数为阻塞函数,会一直等待读取指定bytes的数据。

入参

属性 类型 必填 描述
memaddr memaddr 是 寄存器地址memaddr
bytes Number 是 需要读取的字节个数

返回值

读取到的I2C数据,ArrayBuffer类型。

I2C.close()

关闭I2C实例。

3.6 SPI-串行外设接口

3.6.1 例程

板级配置

{
  "version": "1.0.0",
  "io": {
   "SPI1":{
      "type":"SPI",
      "port":1,
      "mode":"master",
      "freq":3250000
    }
  },
  "debugLevel": "DEBUG"
}

业务脚本

var spi = require('spi');

var msgbuf = [0x01, 0x02, 0x10, 0xaa];
// spi sensor
var spi_data = spi.open({
  id: 'SPI1'
});

var value;
setInterval(function(){
    value = spi_data.readWrite(msgbuf, 4);
    console.log('spi data is ' + value);
}, 1000);

3.6.2 API讲解

open(Object options)

打开SPI,创建 SPI 实例。

入参

属性 类型 必填 描述
id String 是 指定要打开的SPI端口

返回

SPI实例。

SPI 实例

SPI.write(String|ArrayBuffer data)

通过SPI发送数据,该函数为阻塞函数,SPI发送完成后才会返回。

入参

属性 类型 必填 描述
data String ArrayBuffe 是

SPI.read(Number bytes)

读取指定bytes的SPI数据,该函数为阻塞函数,读取到指定bytes的数据后才会返回。

入参

属性 类型 必填 描述
bytes Number 是 指定需要读取的字节个数

返回值

ArrayBuffer类型,读取到的SPI数据。

SPI.close()

关闭SPI实例。

3.7 硬件定时

3.7.1 例程

板级配置

{
  "io": {
    "timer1": {
      "type": "TIMER",
      "port": 1
    }
  },
  "debugLevel": "DEBUG"
}

业务脚本

var timer = require('timer');

var timer1 = timer.open({
  id: 'timer1'
});

// set timer1 timeout
timer1.setTimeout(function() {
  console.log('timer1 timeout');
}, 1000);

// timer1.clearTimeout();

// set timer1 interval
timer1.setInterval(function() {
  console.log('timer1 interval');
}, 1000);

// timer1.clearInterval();

timer1.close();

3.7.2 API讲解

open(Object options)

打开硬件TIMER,创建 TIMER实例。

Object类型,属性如下:

属性 类型 必填 描述
id String 是 在app.json中定义的TIMER id名称

返回

TIMER 实例。

TIMER 实例

硬件TIMER可以设置成超时(setTimeout())和周期(setInterval())2种状态,但是同一时刻只能有一个状态。

TIMER.setTimeout(Function cb, Number timeout)

在指定的毫秒数后调用回调函数。

入参

属性 类型 必填 描述
cb Function 是 定时器超时回调函数
timeout Number 是 设置timer的定时时间

TIMER.clearTimeout()

停止执行setTimeout()。

TIMER.setInterval(Function cb, Number time)

按照指定的周期(以毫秒计)来调用回调函数。

入参

参数option为Object类型,详细的属性为:

属性 类型 必填 描述
cb Function 是 定时器周期回调函数
time Number 是 设置timer的周期时间

4.互联网应用

1.准备工作

在应用开始之前,我们需要在物联网平台上创建一个开发服务的项目---智慧城市,来管理产品,设备,和服务。
创建一个名为“智慧城市”的项目

登录并进入物联网平台控制台在左侧导航栏选择 IoT Studio,单击新建项目,在项目名称框编辑“智慧城市”,填写信息,如下图所示:

点击确定,若项目创建成功,会自动弹出项目管理页面。在这里,我们可以管理此后应用中 的所有产品,设备,和服务。“智能家居管理”项目创建好了,我们可以在该项目下开发有 趣味的物联网项目啦!

好了接下来就让我们我们制作有趣的应用项目吧。

注意:后面我们会创建一系列的产品和设备,注意创建好后导入项目中,不然到web应用开发中配置数据会出错。具体参考2.2.6节讲解

4.1 户外温度采集

简介:

本应用是采取LM75温度传感器,获取室外温度,并将数据通过浏览器显示出来。

4.1.1 应用场景

通过利用LM75温度传感器,对室外温度进行监控。

4.1.2 所需原件

  • 1.HaaS 600 kit套件 x 1
  • 2.DFR0625 IO扩展板 x 1
  • 3.智能手机 x 1

4.1.3 例程

app.js

/*
 * @Author: your name
 * @Date: 2020-07-29 17:11:52
 * @LastEditTime: 2020-09-24 10:37:10
 * @LastEditors: Please set LastEditors
 * @Description: In User Settings Edit
 * @FilePath: /amp-ec100/iot/app.js
 */
console.log('iot: testing iot...');
var iot = require('iot');
var gpio = require('gpio');
var i2c = require('i2c');
var network = require('network');

var net = network.openNetWorkClient();

/* 设备三元组信息获取请参考common目录下的iot组件说明 */
var productKey = 'your productKey'; /* your productKey */
var deviceName = 'your deviceName'; /* your deviceName */
var deviceSecret = 'your deviceSecret'; /* your deviceSecret */

var lm75 = i2c.open({
    id: 'I2C0',
    success: function () {
        console.log('bmp280 sensor open success')
    },
    fail: function () {
        console.log('bmp280 sensor open failed')
    }
});

var led1 = gpio.open({
    id: 'D1',
});
led1.writeValue(1);

var led2 = gpio.open({
    id: 'D2',
});
led1.writeValue(1);

var led3 = gpio.open({
    id: 'D3',
});
led3.writeValue(1);

var led4 = gpio.open({
    id: 'D4',
});
led4.writeValue(1);

var beep = gpio.open({
    id: 'D5',
    success: function () {
        console.log('gpio: open beep success')
    },
    fail: function () {
        console.log('gpio: open beep failed')
    }
});
beep.writeValue(1);

// 构建物联网连接实例
var device;
net.on('connect', function () {
    device = iot.device({
        productKey: productKey,
        deviceName: deviceName,
        deviceSecret: deviceSecret,
        region: 'cn-shanghai',
        success: function () {
            console.log('iot: [success] connect');
            // onConnect();
        },
        fail: function () {
            console.log('iot: [failed] connect');
        }
    });
})

// 获取传感器数据
function lm75tmpGet() {
    var temp;
    var sig = 1;

    var regval = lm75.readMem(0x00, 2); // 读传感器数据
    // 温度数据转换
    var tempAll = (regval[0] << 8) + regval[1];
    console.log('tempAll is ' + tempAll);

    if (regval[0] & 0x80 != 0) {
        tempAll = ~(tempAll) + 1;
        sig = -1;
    }
    tempAll = tempAll >> 5;
    console.log('tempAll final data ' + tempAll);
    temp = tempAll * 0.125 * sig;

    return temp;
}

var postCnt = 10;
var lightSwitch = 0;

// 业务逻辑
// 3秒采集并上传一次温度数据
setInterval(function () {
    temp = lm75tmpGet();
    device.postProps({
        payload: {
            IndoorTemperature: temp
        }
    })
    console.log('lm75 data is ' + temp);
}, 3000);

device.on('connect', function () {
    console.log('iot: [success] iot.on(\'connect\')');
    led2.writeValue(0);
});

/* 网络断开事件 */
device.on('disconnect', function () {
    console.log('iot: [success] iot.on(\'disconnect\')');
    led2.writeValue(1);
});

/* 关闭连接事件 */
device.on('close', function () {
    console.log('iot: [success] iot.on(\'close\')');
});

/* 发生错误事件 */
device.on('error', function (err) {
    throw new Error('iot: [failed] iot.on(\'error\') ' + err);
});

/* 云端设置属性事件 */
device.on('props', function (payload) {
    console.log('iot: [success] iot.on(\'props\'), payload: ' + JSON.stringify(payload));
    if (payload["LightSwitch"] == '1') {
        led1.writeValue(1);
        device.postProps({
            payload: {
                LightSwitch: 1
            }
        })
    }
    if (payload["LightSwitch"] == '0') {
        led1.writeValue(0);
        device.postProps({
            payload: {
                LightSwitch: 0
            }
        })
    }
});

/* 云端下发服务事件 */
device.on('service', function (id, payload) {
    console.log('iot: [success] iot.on(\'service\'), id: ' + id + ', payload: ' + JSON.stringify(payload));
});

app.json

{
    "version": "1.0.0",
    "io": {
        "D1": {
            "type": "GPIO",
            "port": 33,
            "dir": "output",
            "pull": "pulldown"
        },
        "D2": {
            "type": "GPIO",
            "port": 34,
            "dir": "output",
            "pull": "pulldown"
        },
        "D3": {
            "type": "GPIO",
            "port": 35,
            "dir": "output",
            "pull": "pulldown"
        },
        "D4": {
            "type": "GPIO",
            "port": 33,
            "dir": "output",
            "pull": "pulldown"
        },
        "D5": {
            "type": "GPIO",
            "port": 16,
            "dir": "output",
            "pull": "pullup"
        },
        "UART2": {
            "type": "UART",
            "port": 2,
            "dataWidth": 8,
            "baudRate": 115200,
            "stopBits": 1,
            "flowControl": "disable",
            "parity": "none"
        },
        "I2C0": {
            "type": "I2C",
            "port": 0,
            "addrWidth": 7,
            "freq": 400000,
            "mode": "master",
            "devAddr": 72
          },
        "I2C1": {
            "type": "I2C",
            "port": 0,
            "addrWidth": 7,
            "freq": 100000,
            "mode": "master",
            "devAddr": 118
        },
        "SPI0": {
            "type": "SPI",
            "port": 0,
            "mode": "master",
            "freq": 3250000
        },
        "ADC0": {
            "type": "ADC",
            "port": 0,
            "sampling": 12000000
        },
        "ADC1": {
            "type": "ADC",
            "port": 1,
            "sampling": 12000000
        },
        "PWM0": {
            "type": "PWM",
            "port": 31
        }
    },
    "debugLevel": "DEBUG"
}

4.1.4 物联网平台及loT Studio教程

首先我们登录阿里云互联网的控制台,具体步骤参考2.2.5节教程

互联网平台使用请参考2.2.6节。

1.产品创建

在我们之前创建的智慧城市项目下创建名为户外温度采集的产品,如下图所示:

点击完成,则会在产品列表出现一个名叫户外温度采集的产品,点击查看。

2.产品功能定义

定义产品功能。选择功能定义后再点击添加自定义功能为户外温度采集产品定义一个温度检测工作状态的属性,温度是一个范围值,可用float类型。如下图所示:

点击确认,则会在产品详情页的自定义功能栏看到所定义的功能及标识

3.产品设备添加

为产品添加设备。为户外温度采集生成一个设备,选择设备,点击添加设备如下图所示:

点击完成即可:

然后我们可以在设备列表看到该设备信息。如下图:

4.在线调试参数

在线调试参数,当设备生成成功后我们可以选择在线调试参数。这一步的目的主要是为了生成移动应用时可以配置数据。点击查看,进入到设备详情页。再点击在线调试,进入到调试页面。 按照下图所示的方式进行调试推送即可。

5.Web可视化开发

下面开始介绍怎么利用阿里云物联网服务进行Web可视化开发

(1).新建web应用

如下图所示在项目管理界面中点击主页然后点击新建。输入名称后点击确认即可。创建Web应用请参考2.2.6节的Web可视化应用开发教程

(2).Web 页面编辑

下面就进入 Web 的页面编辑

<1>点击配置按钮,然后将自定义新增页 1 改为 温度检测

<2>.添加组件

为了美观,我们放上一张背景图,所以先添加一张图片,将图片拖到画布中,设置为锁定。 然后上传一张比较好看的图片。背景图原图如下。

添加仪表盘。将仪表盘拖到画布中,然后配置参数,产品配置为“户外温度采集”,设备配置为刚才 创建的设备 ,属性温度检测,点击验证数据格式,再点击确定,这就配置完成了。

<3>.可用账户设置(可选)

Web 可视化如果要移植使用,需要绑定域名,为了安全需要,绑定域名使用阿里云设置了 付费。如果需要移植使用的,可参考应用设置->域名管理,CDN 付费原则。如果只是个人需要不必添加域名,默认系统的域名即可。

<4>.Web 可视化发布

点击右上角的发布选项,然后跳到第二张图,备注网页信息,不用填写,直接点击确定,然后得到网页链接。注意:如果不需要绑定域名,直接点击网页链接,不要点击其他选择。

<5>.Web 查看

Web 的页面已经生成,可以在web页面可以看到对应温度。

进行到此步,即可开始 HaaS 600 程序的修改,完成真实物理设备同阿里云 IoT 平台的连接。

6.HaaS 600程序修改

(1).找到例程文件中的app.js文件,打开,找到设备证书信息的相应程序,如下图所示:

(2).填写设备证书信息。

获取设备证书信息,如下图所示:

(3).修改证书信息

将获取到的Temperature_detector的设备证书信息,复制粘贴到前面的app.js相应的位置。

(4).替换产品标识符

首先我们找到产品标识符,如下图所示:

(5).我们进入,查看程序中的标识符,然后将app.js中的对应项改为产品对应的标识符即可,如图。

(6).本地热更新代码,具体步骤参考应用热跟新2.1.6第一个轻应用示例

此时设备已经成功与阿里云平台上的户外温度采集设备相连接,进入控制页面,一段时间后,即可测得室外温度。

4.1.5 成品展示

接线:我们这个HaaS 600kit上已经集成了温度传感器,所以我们只需接上电源和数据线即可,接线如图:电源线接上,数据线接到电脑USB接口。

4.2 物流跟踪

前面一节我们制作了户外温度检测,相信大家对物联网有了基本的认识,接下来我们继续进行下一个应用物流跟踪的制作。通过GPS对当前位置进行定位。

4.2.1 应用场景

当我们邮寄一个重要物品时,通过GPS模块进行定位,我们可以通过手机浏览器对物品进行实时跟踪,获取当前的位置信息。

4.2.2 所需原件

  • 1.HaaS 600 kit套件 x 1
  • 2.DFR0625 IO扩展板 x 1
  • 3.GPS定位仪 x 1
  • 4.智能手机 x 1

4.2.3 例程

app.js

 var uart = require('uart');

var iot = require('iot');
var network = require('network');
var net = network.openNetWorkClient();

/* 设备三元组信息获取请参考common目录下的iot组件说明 */
var productKey = 'productKey'; /* your productKey */
var deviceName = 'deviceName'; /* your deviceName */
var deviceSecret = 'deviceSecret'; /* your deviceSecret */

var device;
net.on('connect', function () {
    device = iot.device({
        productKey: productKey,
        deviceName: deviceName,
        deviceSecret: deviceSecret,
        region: 'cn-shanghai',
        success: function () {
            console.log('iot: [success] connect');
        },
        fail: function () {
            console.log('iot: [failed] connect');
        }
    });
})


function ArrayToString(fileData) {
  var dataString = "";
  for (var i = 0; i < fileData.length; i++) {
    dataString += String.fromCharCode(fileData[i]);
  }
  return dataString;
}

/**
 * GPS定位信息
 * <1>  UTC时间,hhmmss(时分秒)格式
 * <2>  纬度ddmm.mmmm(度分)格式
 * <3>  纬度半球N(北半球)或S(南半球)
 * <4>  经度dddmm.mmmm(度分)格式
 * <5>  经度半球E(东经)或W(西经)
 * <6>  GPS状态:0=未定位,1=非差分定位,2=查分定位,6=正在估算
 * <7>  正在使用解算位置的卫星数量(00~12)
 * <8>  HDOP水平精度因子(0.5~99.9)
 * <9>  海拔高度(-9999.9~99999.9)
 * <10> 地球椭球面相对大地水准面的高度
 * <11> 差分时间
 * <12> 差分站ID号0000~1023
 */
function ParseGNGGA(data){
  var temp;
  var utcTime;
  var Latitude;
  var LatitudeHemisphere;
  var Longitude;
  var LongitudeHemisphere;
  var GPSStatus;
  var SatellitesNum;
  var HDOP;
  var Altitude;
  var RelativeHeight;
  var DifferentialTime;
  var DifferentialID;
  console.log('============GNGGA============');
  console.log(data);
  data = data.substring(7,data.length);
  temp = data.indexOf(","); 
  if(temp != -1){
    utcTime = data.substring(0,temp);
    console.log('utcTime = '+utcTime);
    data = data.substring(temp+1,data.length);
  }

  temp = data.indexOf(","); 
  if(temp != -1){
    Latitude = data.substring(0,temp);
    console.log('Latitude = ' + Latitude);
    data = data.substring(temp+1,data.length);
  }

  temp = data.indexOf(","); 
  if(temp != -1){
    LatitudeHemisphere = data.substring(0,temp);
    console.log('LatitudeHemisphere = '+LatitudeHemisphere);
    data = data.substring(temp+1,data.length);
  }

  temp = data.indexOf(","); 
  if(temp != -1){
    Longitude = data.substring(0,temp);
    console.log('Longitude = '+Longitude);
    data = data.substring(temp+1,data.length);
  }

  temp = data.indexOf(","); 
  if(temp != -1){
    LongitudeHemisphere = data.substring(0,temp);
    console.log('LongitudeHemisphere = ' + LongitudeHemisphere);
    data = data.substring(temp+1,data.length);
  }

  temp = data.indexOf(","); 
  if(temp != -1){
    GPSStatus = data.substring(0,temp);
    console.log('GPSStatus = ' + GPSStatus);
    data = data.substring(temp+1,data.length);
  }

  temp = data.indexOf(","); 
  if(temp != -1){
    SatellitesNum = data.substring(0,temp);
    console.log('SatellitesNum = ' + SatellitesNum);
    data = data.substring(temp+1,data.length);
  }

  temp = data.indexOf(","); 
  if(temp != -1){
    HDOP = data.substring(0,temp);
    console.log('HDOP = ' + HDOP);
    data = data.substring(temp+1,data.length);
  }

  temp = data.indexOf(","); 
  if(temp != -1){
    Altitude = data.substring(0,temp);
    console.log('Altitude = ' + Altitude);
    data = data.substring(temp+1,data.length);
  }

  temp = data.indexOf(","); 
  if(temp != -1){
    RelativeHeight = data.substring(0,temp);
    console.log('RelativeHeight = ' + RelativeHeight);
    data = data.substring(temp+1,data.length);
  }

  temp = data.indexOf(","); 
  if(temp != -1){
    DifferentialTime = data.substring(0,temp);
    console.log('DifferentialTime = ' + DifferentialTime);
    data = data.substring(temp+1,data.length);
  }

  temp = data.indexOf("*"); 
  if(temp != -1){
    DifferentialID = data.substring(0,temp);
    console.log('DifferentialID = ' + DifferentialID);
    data = data.substring(temp+1,data.length);
  }

}

/**
 * 定位地理信息
 * <1>  纬度 ddmm.mmmmm(度分)
 * <2>  纬度半球N(北半球)或S(南半球)
 * <3>  经度dddmm.mmmmm(度分)
 * <4>  经度半球E(东经)或 W(西经)
 * <5>  UTC时间:hhmmss(时分秒)
 * <6>  定位状态, A = 有效定位, V = 无效定位
 * <7>  模式指定 (A = 自主定位, D = 差分, E = 估算, N = 数据无效)
 */
function ParseGNGLL(data){
  var temp;
  var Latitude;
  var LatitudeHemisphere;
  var Longitude;
  var LongitudeHemisphere;
  var utcTime;
  var PositioningStatus;
  var ModeStatus;
  console.log('============GNGLL============');
  console.log(data);
  data = data.substring(7,data.length);
  temp = data.indexOf(","); 
  if(temp != -1){
    Latitude = data.substring(0,temp);
    console.log('Latitude = '+Latitude);
    data = data.substring(temp+1,data.length);
  }

  temp = data.indexOf(","); 
  if(temp != -1){
    LatitudeHemisphere = data.substring(0,temp);
    console.log('LatitudeHemisphere = ' + LatitudeHemisphere);
    data = data.substring(temp+1,data.length);
  }

  temp = data.indexOf(","); 
  if(temp != -1){
    Longitude = data.substring(0,temp);
    console.log('Longitude = '+Longitude);
    data = data.substring(temp+1,data.length);
  }

  temp = data.indexOf(","); 
  if(temp != -1){
    LongitudeHemisphere = data.substring(0,temp);
    console.log('LongitudeHemisphere = ' + LongitudeHemisphere);
    data = data.substring(temp+1,data.length);
  }

  temp = data.indexOf(","); 
  if(temp != -1){
    utcTime = data.substring(0,temp);
    console.log('utcTime = ' + utcTime);
    data = data.substring(temp+1,data.length);
  }

  temp = data.indexOf(","); 
  if(temp != -1){
    PositioningStatus = data.substring(0,temp);
    console.log('PositioningStatus = ' + PositioningStatus);
    data = data.substring(temp+1,data.length);
  }

  temp = data.indexOf("*"); 
  if(temp != -1){
    ModeStatus = data.substring(0,temp);
    console.log('ModeStatus = ' + ModeStatus);
    data = data.substring(temp+1,data.length);
  }
}

/**
 * 当前卫星信息
 * <1> 模式, M = 手动, A = 自动
 * <2> 定位类型, 1 = 未定位,2 = 2D定位, 3 = 3D定位
 * <3> ~ <14>正在用于定位的卫星号(01~32)
 * <15> PDOP综合位置精度因子(0.5-99.9)
 * <16> HDOP水平精度因子(0.5-99.9)
 * <17> VDOP垂直精度因子(0.5-99.9)
 * 
 */
function ParseGNGSA(data){
  var ModeStatus;
  var PositioningStatus;
  var SatelliteNum1;
  var SatelliteNum2;
  var SatelliteNum3;
  var SatelliteNum4;
  var SatelliteNum5;
  var SatelliteNum6;
  var SatelliteNum7;
  var SatelliteNum8;
  var SatelliteNum9;
  var SatelliteNum10;
  var SatelliteNum11;
  var SatelliteNum12;
  var PDOP;
  var HDOP;
  var VDOP;
  console.log('============GNGSA============');
  console.log(data);
  data = data.substring(7,data.length);
  temp = data.indexOf(","); 
  if(temp != -1){
    ModeStatus = data.substring(0,temp);
    console.log('ModeStatus = '+ModeStatus);
    data = data.substring(temp+1,data.length);
  }

  temp = data.indexOf(","); 
  if(temp != -1){
    PositioningStatus = data.substring(0,temp);
    console.log('PositioningStatus = '+PositioningStatus);
    data = data.substring(temp+1,data.length);
  }

  temp = data.indexOf(","); 
  if(temp != -1){
    SatelliteNum1 = data.substring(0,temp);
    console.log('SatelliteNum1 = '+SatelliteNum1);
    data = data.substring(temp+1,data.length);
  }

  temp = data.indexOf(","); 
  if(temp != -1){
    SatelliteNum2 = data.substring(0,temp);
    console.log('SatelliteNum2 = '+SatelliteNum2);
    data = data.substring(temp+1,data.length);
  }

  temp = data.indexOf(","); 
  if(temp != -1){
    SatelliteNum3 = data.substring(0,temp);
    console.log('SatelliteNum3 = '+SatelliteNum3);
    data = data.substring(temp+1,data.length);
  }

  temp = data.indexOf(","); 
  if(temp != -1){
    SatelliteNum4 = data.substring(0,temp);
    console.log('SatelliteNum4 = '+SatelliteNum4);
    data = data.substring(temp+1,data.length);
  }

  temp = data.indexOf(","); 
  if(temp != -1){
    SatelliteNum5 = data.substring(0,temp);
    console.log('SatelliteNum5 = '+SatelliteNum5);
    data = data.substring(temp+1,data.length);
  }

  temp = data.indexOf(","); 
  if(temp != -1){
    SatelliteNum6 = data.substring(0,temp);
    console.log('SatelliteNum6 = '+SatelliteNum6);
    data = data.substring(temp+1,data.length);
  }

  temp = data.indexOf(","); 
  if(temp != -1){
    SatelliteNum7 = data.substring(0,temp);
    console.log('SatelliteNum7 = '+SatelliteNum7);
    data = data.substring(temp+1,data.length);
  }

  temp = data.indexOf(","); 
  if(temp != -1){
    SatelliteNum8 = data.substring(0,temp);
    console.log('SatelliteNum8 = '+SatelliteNum8);
    data = data.substring(temp+1,data.length);
  }

  temp = data.indexOf(","); 
  if(temp != -1){
    SatelliteNum9 = data.substring(0,temp);
    console.log('SatelliteNum9 = '+SatelliteNum9);
    data = data.substring(temp+1,data.length);
  }

  temp = data.indexOf(","); 
  if(temp != -1){
    SatelliteNum10 = data.substring(0,temp);
    console.log('SatelliteNum10 = '+SatelliteNum10);
    data = data.substring(temp+1,data.length);
  }

  temp = data.indexOf(","); 
  if(temp != -1){
    SatelliteNum11 = data.substring(0,temp);
    console.log('SatelliteNum11 = '+SatelliteNum11);
    data = data.substring(temp+1,data.length);
  }

  temp = data.indexOf(","); 
  if(temp != -1){
    SatelliteNum12 = data.substring(0,temp);
    console.log('SatelliteNum12 = '+SatelliteNum12);
    data = data.substring(temp+1,data.length);
  }

  temp = data.indexOf(","); 
  if(temp != -1){
    PDOP = data.substring(0,temp);
    console.log('PDOP = '+PDOP);
    data = data.substring(temp+1,data.length);
  }

  temp = data.indexOf(","); 
  if(temp != -1){
    HDOP = data.substring(0,temp);
    console.log('HDOP = '+HDOP);
    data = data.substring(temp+1,data.length);
  }

  temp = data.indexOf("*"); 
  if(temp != -1){
    VDOP = data.substring(0,temp);
    console.log('VDOP = '+VDOP);
    data = data.substring(temp+1,data.length);
  }
}

/**
 * 可见卫星数
 * <1> GSV语句的总数
 * <2> 本句GSV的编号
 * <3> 可见卫星的总数,00至12
 * <4> 卫星编号,01至32
 * <5> 卫星仰角,00 至90度
 * <6> 卫星方位角,000至359度
 * <7> 讯号噪声比(C/No),00至99dB;无表示为接收到讯号
 * 
 */
function ParseGPGSV(data){
  console.log(data);
}

/**
 * 可见卫星数
 * <1> GSV语句总数
 * <2> 本句GSV编号
 * <3> 可见卫星的总数(00~12)
 * <4> 卫星编号(01~32)
 * <5> 卫星仰角(00~90度)
 * <6> 卫星方位角(000~359度)
 * <7> 信噪比(00~99dB)
 * 
 */
function ParseBDGSV(data){
  console.log("ParseBDGSV");
}

/**
 * 推荐定位信息
 * <1>  UTC时间,hhmmss(时分秒)
 * <2>  定位状态,A = 有效定位, V = 无效定位
 * <3>  纬度ddmm.mmmmm(度分)
 * <4>  纬度半球N(北半球)或S(南半球)
 * <5>  经度dddmm.mmmmm(度分)
 * <6>  经度半球E(东经)或W(西经)
 * <7>  地面速率(000.0~999.9节)
 * <8>  地面航向(000.0~359.9度,以真北方为参考基准)
 * <9>  UTC日期,ddmmyy(日月年)
 * <10> 磁偏角(000.0 ~ 180.0度)
 * <11> 磁偏角方向,E(东)或 W(西)
 * <12> 模式指示(A = 自主定位,D = 差分, E = 估算, N = 数据无效)
 */

var Latitude;
var Longitude;
function ParseGNRMC(data){
  var temp;
  var utcTime;
  var PositioningStatus;
  //var Latitude;
  var LatitudeHemisphere;
  //var Longitude;
  var LongitudeHemisphere;
  var GroundSpeed;
  var GroundHeading;
  var utcDate;
  var MagneticDeclination;
  var MagneticDeclinationDirection;
  var ModeStatus;
  console.log('============GNRMC============');
  console.log(data);
  data = data.substring(7,data.length);
  temp = data.indexOf(","); 
  if(temp != -1){
    utcTime = data.substring(0,temp);
    console.log('utcTime = '+utcTime);
    data = data.substring(temp+1,data.length);
  }

  temp = data.indexOf(","); 
  if(temp != -1){
    PositioningStatus = data.substring(0,temp);
    console.log('PositioningStatus = '+PositioningStatus);
    data = data.substring(temp+1,data.length);
  }

  temp = data.indexOf(","); 
  if(temp != -1){
    Latitude = data.substring(0,temp);
    console.log('Latitude = '+Latitude);
    data = data.substring(temp+1,data.length);
  }

  temp = data.indexOf(","); 
  if(temp != -1){
    LatitudeHemisphere = data.substring(0,temp);
    Latitude1 = Math.floor(Latitude);
    Latitude = (Math.floor(Latitude1/1000))*10+(Math.floor(Latitude1/100%10))+((Math.floor(Latitude1/10%10))*10+(Math.floor(Latitude1%10))+Latitude%1)/60;
    console.log('Latitude = '+Latitude);
    data = data.substring(temp+1,data.length);
  }

  temp = data.indexOf(","); 
  if(temp != -1){
    Longitude = data.substring(0,temp);
    console.log('Longitude = '+Longitude);
    data = data.substring(temp+1,data.length);
  }

  temp = data.indexOf(","); 
  if(temp != -1){
    LongitudeHemisphere = data.substring(0,temp);
    Longitude1 = Math.floor(Longitude);
    Longitude = (Math.floor(Longitude1/10000))*100+(Math.floor(Longitude1/1000%10))*10+(Math.floor(Longitude1/100%10))+((Math.floor(Longitude1/10%10))*10+(Math.floor(Longitude1%10))+Longitude%1)/60;
    console.log('Longitude = '+Longitude);
    data = data.substring(temp+1,data.length);
  }

  temp = data.indexOf(","); 
  if(temp != -1){
    GroundSpeed = data.substring(0,temp);
    console.log('GroundSpeed = '+GroundSpeed);
    data = data.substring(temp+1,data.length);
  }

  temp = data.indexOf(","); 
  if(temp != -1){
    GroundHeading = data.substring(0,temp);
    console.log('GroundHeading = '+GroundHeading);
    data = data.substring(temp+1,data.length);
  }

  temp = data.indexOf(","); 
  if(temp != -1){
    utcDate = data.substring(0,temp);
    console.log('utcDate = '+utcDate);
    data = data.substring(temp+1,data.length);
  }

  temp = data.indexOf(","); 
  if(temp != -1){
    MagneticDeclination = data.substring(0,temp);
    console.log('MagneticDeclination = '+MagneticDeclination);
    data = data.substring(temp+1,data.length);
  }

  temp = data.indexOf(","); 
  if(temp != -1){
    MagneticDeclinationDirection = data.substring(0,temp);
    console.log('MagneticDeclinationDirection = '+MagneticDeclinationDirection);
    data = data.substring(temp+1,data.length);
  }

  temp = data.indexOf(","); 
  if(temp != -1){
    ModeStatus = data.substring(0,temp);
    console.log('ModeStatus = '+ModeStatus);
    data = data.substring(temp+1,data.length);
  }
}

/**
 * 地面速度信息
 * <1>  以真北为参考基准的地面航向(000~359度)
 * <2>  以磁北为参考基准的地面航向(000~359度)
 * <3>  地面速率(000.0~999.0节)
 * <4>  地面速率(0000.0~1851.8 公里/小时)
 * <5>  模式指示(A = 自主定位, D = 差分, E = 估算, N = 数据无效)
 * 
 */

function ParseGNVTG(data){
  //console.log("ParseGNVTG");
}


/**
 * 当前时间信息
 * <1>  UTC时间: hhmmss(时分秒)
 * <2>  日
 * <3>  月
 * <4>  年
 * <5>  本地区域小时(NEO-6M 为用到,为00)
 * <6>  本地区域分钟(NEO-6M 为用到,为00)
 */
function ParseGNZDA(data){
 // console.log("ParseGNZDA");
}

function ParseGPTXT(data){
 // console.log("ParseGPTXT");
}


// gnss uart
var gnss = uart.open({
  id: 'UART1'
});

var recData = "";
var recData1 = "";
var recData2 = "";
var nowdata = 1;
var recOK = 0;
// gnss uart data receive 
gnss.on('data', function(data) {
  var temp = -1;
  var ParseData = "";
  recData += ArrayToString(data);
  temp = recData.indexOf("\r\n");
  if(temp != -1){
    ParseData = recData.substring(0,temp);
    recData = recData.substring(temp+2,recData.length);
    //console.log("==========="+temp);
    //console.log(ParseData);
    if(ParseData.indexOf("$GNGGA") != -1){
      //ParseGNGGA(ParseData);
    }else if(ParseData.indexOf("$GNGLL") != -1){
      //ParseGNGLL(ParseData);
    }else if(ParseData.indexOf("$GNGSA") != -1){
      //ParseGNGSA(ParseData);
    }else if(ParseData.indexOf("$GPGSV") != -1){
      ParseGPGSV(ParseData);
    }else if(ParseData.indexOf("$BDGSV") != -1){
      ParseBDGSV(ParseData);
    }else if(ParseData.indexOf("$GNRMC") != -1){
      ParseGNRMC(ParseData);
    }else if(ParseData.indexOf("$GNVTG") != -1){
      ParseGNVTG(ParseData);
    }else if(ParseData.indexOf("$GNZDA") != -1){
      ParseGNZDA(ParseData);
    }else if(ParseData.indexOf("$GPTXT") != -1){
      ParseGPTXT(ParseData);
    }
  }
});

setInterval(function() {
    device.postProps({
      payload: {
          GeoLocation:{
            Longitude:Longitude,
            Latitude:Latitude,
          }
      }
    })
    console.log('hhh');
}, 3000);

/**
 * 可见卫星数
 * <1> GSV语句的总数
 * <2> 本句GSV的编号
 * <3> 可见卫星的总数,00至12
 * <4> 卫星编号,01至32
 * <5> 卫星仰角,00 至90度
 * <6> 卫星方位角,000至359度
 * <7> 讯号噪声比(C/No),00至99dB;无表示为接收到讯号
 * 
 */
function ParseGPGSV(data){
  console.log(data);
}

/**
 * 可见卫星数
 * <1> GSV语句总数
 * <2> 本句GSV编号
 * <3> 可见卫星的总数(00~12)
 * <4> 卫星编号(01~32)
 * <5> 卫星仰角(00~90度)
 * <6> 卫星方位角(000~359度)
 * <7> 信噪比(00~99dB)
 * 
 */
function ParseBDGSV(data){
  console.log("ParseBDGSV");
}

/**
 * 推荐定位信息
 * <1>  UTC时间,hhmmss(时分秒)
 * <2>  定位状态,A = 有效定位, V = 无效定位
 * <3>  纬度ddmm.mmmmm(度分)
 * <4>  纬度半球N(北半球)或S(南半球)
 * <5>  经度dddmm.mmmmm(度分)
 * <6>  经度半球E(东经)或W(西经)
 * <7>  地面速率(000.0~999.9节)
 * <8>  地面航向(000.0~359.9度,以真北方为参考基准)
 * <9>  UTC日期,ddmmyy(日月年)
 * <10> 磁偏角(000.0 ~ 180.0度)
 * <11> 磁偏角方向,E(东)或 W(西)
 * <12> 模式指示(A = 自主定位,D = 差分, E = 估算, N = 数据无效)
 */
function ParseGNRMC(data){
  var temp;
  var utcTime;
  var PositioningStatus;
  var Latitude;
  var LatitudeHemisphere;
  var Longitude;
  var LongitudeHemisphere;
  var GroundSpeed;
  var GroundHeading;
  var utcDate;
  var MagneticDeclination;
  var MagneticDeclinationDirection;
  var ModeStatus;
  console.log('============GNRMC============');
  console.log(data);
  data = data.substring(7,data.length);
  temp = data.indexOf(",");
  if(temp != -1){
    utcTime = data.substring(0,temp);
    console.log('utcTime = '+utcTime);
    data = data.substring(temp+1,data.length);
  }

  temp = data.indexOf(",");
  if(temp != -1){
    PositioningStatus = data.substring(0,temp);
    console.log('PositioningStatus = '+PositioningStatus);
    data = data.substring(temp+1,data.length);
  }

  temp = data.indexOf(",");
  if(temp != -1){
    Latitude = data.substring(0,temp);
    console.log('Latitude = '+Latitude);
    data = data.substring(temp+1,data.length);
  }

  temp = data.indexOf(",");
  if(temp != -1){
    LatitudeHemisphere = data.substring(0,temp);
    console.log('LatitudeHemisphere = '+LatitudeHemisphere);
    data = data.substring(temp+1,data.length);
  }

  temp = data.indexOf(",");
  if(temp != -1){
    Longitude = data.substring(0,temp);
    console.log('Longitude = '+Longitude);
    data = data.substring(temp+1,data.length);
  }

  temp = data.indexOf(",");
  if(temp != -1){
    LongitudeHemisphere = data.substring(0,temp);
    console.log('LongitudeHemisphere = '+LongitudeHemisphere);
    data = data.substring(temp+1,data.length);
  }

  temp = data.indexOf(",");
  if(temp != -1){
    GroundSpeed = data.substring(0,temp);
    console.log('GroundSpeed = '+GroundSpeed);
    data = data.substring(temp+1,data.length);
  }

  temp = data.indexOf(",");
  if(temp != -1){
    GroundHeading = data.substring(0,temp);
    console.log('GroundHeading = '+GroundHeading);
    data = data.substring(temp+1,data.length);
  }

  temp = data.indexOf(",");
  if(temp != -1){
    utcDate = data.substring(0,temp);
    console.log('utcDate = '+utcDate);
    data = data.substring(temp+1,data.length);
  }

  temp = data.indexOf(",");
  if(temp != -1){
    MagneticDeclination = data.substring(0,temp);
    console.log('MagneticDeclination = '+MagneticDeclination);
    data = data.substring(temp+1,data.length);
  }

  temp = data.indexOf(",");
  if(temp != -1){
    MagneticDeclinationDirection = data.substring(0,temp);
    console.log('MagneticDeclinationDirection = '+MagneticDeclinationDirection);
    data = data.substring(temp+1,data.length);
  }

  temp = data.indexOf(",");
  if(temp != -1){
    ModeStatus = data.substring(0,temp);
    console.log('ModeStatus = '+ModeStatus);
    data = data.substring(temp+1,data.length);
  }
}

/**
 * 地面速度信息
 * <1>  以真北为参考基准的地面航向(000~359度)
 * <2>  以磁北为参考基准的地面航向(000~359度)
 * <3>  地面速率(000.0~999.0节)
 * <4>  地面速率(0000.0~1851.8 公里/小时)
 * <5>  模式指示(A = 自主定位, D = 差分, E = 估算, N = 数据无效)
 * 
 */

function ParseGNVTG(data){
  //console.log("ParseGNVTG");
}


/**
 * 当前时间信息
 * <1>  UTC时间: hhmmss(时分秒)
 * <2>  日
 * <3>  月
 * <4>  年
 * <5>  本地区域小时(NEO-6M 为用到,为00)
 * <6>  本地区域分钟(NEO-6M 为用到,为00)
 */
function ParseGNZDA(data){
 // console.log("ParseGNZDA");
}

function ParseGPTXT(data){
 // console.log("ParseGPTXT");
}


// gnss uart
var gnss = uart.open({
  id: 'UART1'
});

var recData = "";
var recData1 = "";
var recData2 = "";
var nowdata = 1;
var recOK = 0;
// gnss uart data receive
gnss.on('data', function(data) {
  var temp = -1;
  var ParseData = "";
  recData += ArrayToString(data);
  temp = recData.indexOf("\r\n");
  if(temp != -1){
    ParseData = recData.substring(0,temp);
    recData = recData.substring(temp+2,recData.length);
    //console.log("==========="+temp);
    //console.log(ParseData);
    if(ParseData.indexOf("$GNGGA") != -1){
      //ParseGNGGA(ParseData);
    }else if(ParseData.indexOf("$GNGLL") != -1){
      //ParseGNGLL(ParseData);
    }else if(ParseData.indexOf("$GNGSA") != -1){
      //ParseGNGSA(ParseData);
    }else if(ParseData.indexOf("$GPGSV") != -1){
      ParseGPGSV(ParseData);
    }else if(ParseData.indexOf("$BDGSV") != -1){
      ParseBDGSV(ParseData);
    }else if(ParseData.indexOf("$GNRMC") != -1){
      ParseGNRMC(ParseData);
    }else if(ParseData.indexOf("$GNVTG") != -1){
      ParseGNVTG(ParseData);
    }else if(ParseData.indexOf("$GNZDA") != -1){
      ParseGNZDA(ParseData);
    }else if(ParseData.indexOf("$GPTXT") != -1){
      ParseGPTXT(ParseData);
    }
  }
});

setInterval(function() {
}, 50);

app.json

{
  "version": "1.0.0",
  "io": {
    "UART1": {
      "type": "UART",
      "port": 1,
      "dataWidth": 8,
      "baudRate": 9600,
      "stopBits": 1,
      "flowControl": "cts",
      "parity": "none"
    }
  },
  "debugLevel": "DEBUG"
}

4.2.4 物联网平台及loT Studio教程

首先我们登录阿里云物联网的控制台,具体步骤参考2.2.5节教程;点击 IoT Studio 下的项目管理选项,然后选择我们之前的智慧城市项目。

1.产品创建

在项目下创建一个名为“物流跟踪”的产品,如下图:

点击完成,则会在产品列表出现一个名为“物流跟踪”的产品,点击查看。

2.产品功能定义

定义产品功能。选择功能定义后再点击添加自定义功能,为物流跟踪产品功能名称为地理位置的功能定义,注意,我们要选择位置定义下的第三个选项,然后默认就会弹出标识符和数据类型,如下图所示:

点击确认,则会在产品详情页的自定义功能栏看到所定义的功能及标识符。

3.产品设备添加

为产品添加设备。为“物流跟踪”生成一个设备,如下图所示:

点击完成即可:

然后我们可以在设备列表看到该设备信息。如下图:

4.在线参数调试

在线调试参数,当设备生成成功后我们可以选择在线调试参数。这一步的目的主要是为了生成移动应用时可以配置数据。点击查看,进入到设备详情页。再点击在线调试,进入到调试页面。 按照下图所示的方式进行调试推送即可。

5.创建Web可视化开发

如下图所示在项目管理界面中点击 Web 应用然后点击新建。输入名称后点击确认即可。

参考4.1.4节拖入地图组件如下图:

点击编辑设备地图,进行配置,配置项如下:

Web可视化发布

点击右上角的发布选项,然后跳到第二张图,备注网页信息,不用填写,直接点击确定,然后得到网页链接。注意:如果不需要绑定域名,直接点击网页链接,不要点击其他选择。

进行到此步,即可开始 HaaS 600 程序的修改,完成真实物理设备同阿里云 IoT 平台的连接。

**6.HaaS 600程序修改
程序修改步骤我们参考4.1节程序修改即可。

(1).我们获取GPS_positioning设备证书如下图所示:

(2).然后我们程序,找到程序对应的设备信息,如下图所示:

(3).接着我们找到产品标识符如图:

找到相应程序添加标识符信息如图:

(5).本地热更新代码。

完成上面的步骤后,我们就完成了阿里云平台和物流跟踪设备的连接,我们可以对产品进行定位了。

4.2.5 成品展示

接线:电源线和数据传输线接线方式参考第一个应用。然后用短接帽短接1、2,3、4脚,如图所示:

4.3 智能绿化

经过前面两个应用的制作,相信大家已经对阿里云物联网平台有了初步的了解,这节我们做一个简单的智能绿化应用。

4.3.1 应用场景

生活中,我们经常可以看到园林工人会对绿化进行灌溉,我们可以土壤湿度,根据土壤湿度对绿化进行合理的灌溉,让湿度始终保持在一个稳定的范围内。

4.3.2 所需原件

  • 1.HaaS 600 kit套件 x 1
  • 2.DFR0625 IO扩展板 x 1
  • 3.土壤湿度传感器 x 1
  • 4.智能手机 x 1

4.3.3 例程

app.js

var iot = require('iot');
var network = require('network');
var net = network.openNetWorkClient();
/* 设备三元组信息获取请参考common目录下的iot组件说明 */
var productKey = 'a1vyA0XugNe'; /* your productKey */
var deviceName = 'testlight'; /* your deviceName */
var deviceSecret = '3f77a547297fbee3eddc47dcc231f3bb'; /* your deviceSecret */

var adc = require('adc');
/**
 * 土壤传感器
 */
var SoilMoisture = adc.open({
  id: 'ADC0',
  success: function() {
    console.log('adc: open adc0 success')
  },
  fail: function() {
    console.log('adc: open adc0 failed')
  }
});


var device;
net.on('connect', function () {
    device = iot.device({
        productKey: productKey,
        deviceName: deviceName,
        deviceSecret: deviceSecret,
        region: 'cn-shanghai',
        success: function () {
            console.log('iot: [success] connect');
        },
        fail: function () {
            console.log('iot: [failed] connect');
        }
    });
})

setInterval(function() {
  /**
  * 测试使用用电量属性(PowerConsumption)来做测试
  */
  device.postProps({
    payload: {
      PowerConsumption: SoilMoisture.readValue()
    }
  })
  console.log('Soil Moisture:' + SoilMoisture.readValue())
}, 3000);

app.json

{
    "version": "1.0.0",
    "io": {
        "ADC0": {
            "type": "ADC",
            "port": 0,
            "sampling": 12000000
        }
    },
    "debugLevel": "ERROR"
}

4.3.4 物联网平台及loT Studio教程

首先我们登录阿里云互联网的控制台,具体步骤参考2.2.5节教程

互联网平台使用请参考2.2.6节。

1.产品创建

在我们之前创建的智慧城市项目下创建名为”智能绿化”的产品,如下图所示:

点击完成,则会在产品列表出现一个名叫“智能绿化”的产品,点击查看

2.产品功能定义

定义产品功能。选择功能定义后再点击添加自定义功能为“智能绿化”产品定义一个土壤湿度检测的功能,湿度是一个范围值,可用int32整型类型。如下图所示:

点击确认,则会在产品详情页的自定义功能栏看到所定义的功能及标识符。

3.产品设备添加

为产品添加设备。为“智能绿化”生成一个设备,选择设备,点击添加设备如下图所示:

点击完成即可:

然后我们可以在设备列表看到该设备信息。如下图:

4.在线调试参数

在线调试参数,当设备生成成功后我们可以选择在线调试参数。这一步的目的主要是为了生成移动应用时可以配置数据。点击查看,进入到设备详情页。再点击在线调试,进入到调试页面。 按照下图所示的方式进行调试推送即可。

5.Web可视化开发

下面开始介绍怎么利用阿里云物联网服务进行Web可视化开发

(1).新建web应用

如下图所示在项目管理界面中点击主页然后点击新建。输入名称后点击确认即可。创建Web应用请参考2.2.6节的Web可视化应用开发教程

(2).Web页面编辑按照4.1.4中的步骤添加图片和组件,如下图

(3).配置参数

将实时曲线拖到画布中,然后配置参数,产品配置为“智能绿化”,设备配置为刚才 创建的设备 ,属性为土壤湿度检测,点击验证数据格式,再点击确定,这就配置完成了.具体配置如下图:

(4).Web可视化发布

点击右上角发布,该项目就完成了。

(5).Web查看

Web 的页面已经生成,可直接在网页上查看土壤湿度了。

进行到此步,即可开始 HaaS 600 程序的修改,完成真实物理设备同阿里云 IoT 平台的连接。

6.HaaS 600程序修改

程序修改步骤我们参考4.1节程序修改即可。

(1).我们获取Soil_moisture_sensor设备证书如下图所示:

我们将如图应信息修改即可。

(2).然后我们找到标识符所在位置,如下图所示:

(3).接着我们找到产品标识符如图:

(4).然后在程序中找到(2)中的标识符,替换成(3)中标识符即可。

(5).本地热更新代码。

完成上面的步骤后,我们就完成了阿里云平台和智能绿化设备的连接,我们可以对湿度进行检测了。

4.3.5 成品展示

接线:电源线和数据传输线参考4.1节的接线图

然后我们找到土壤湿度传感器

其中:黑色线接13号引脚的“GND”,红色线接13号引脚的“VCC”,蓝色线接13号引脚的“D”,如图所示。

4.4 非接触式门禁

我们利用手势识别带触摸传感器,制作一个非接触式门禁系统,利用物联网记录次数来模拟门的开关,并根据数据统计一天门开的次数。

4.4.1 应用场景

疫情期间,传统的门禁系统采用触摸式开关,为了避免过多的接触,我们利用手势识别带触摸传感器,制作一个手势密码,通过手势密码来解锁门禁。

4.4.2 所需原件

  • 1.HaaS 600 kit套件 x 1
  • 2.DFR0625 IO扩展板 x 1
  • 3.手势识别带触摸传感器 x 1
  • 4.智能手机 x 1

4.4.3 例程

app.js

var uart = require('uart');
var gpio = require('gpio');

var iot = require('iot');
var network = require('network');
var net = network.openNetWorkClient();
/* 设备三元组信息获取请参考common目录下的iot组件说明 */
var productKey = 'your productKey'; /* your productKey */
var deviceName = 'your deviceName'; /* your deviceName */
var deviceSecret = 'your deviceSecret'; /* your deviceSecret */


var DFGT_CMD_INTERVAL   = 0x51;
var DFGT_CMD_SLEEP      = 0x52;
var DFGT_CMD_DISTANCE   = 0x54;
var DFGT_CMD_ENABLE     = 0x55;

var DFGT_FUN_START1     = 0x01;
var DFGT_FUN_PART1      = 0x3f;
var DFGT_FUN_OFFSET1    = 0x00;
var DFGT_FUN_START2     = 0x09;
var DFGT_FUN_PART2      = 0x07ff;
var DFGT_FUN_OFFSET2    = 0x06;
var DFGT_FUN_ALL        = 0x07ff;

var DFGT_FUN_RIGHT      = (0x0001 << 0);
var DFGT_FUN_LEFT       = (0x0001 << 1);
var DFGT_FUN_BACK       = (0x0001 << 2);
var DFGT_FUN_FORWARD    = (0x0001 << 3);
var DFGT_FUN_PULLUP     = (0x0001 << 4);
var DFGT_FUN_PULLDOWN   = (0x0001 << 5);

var DFGT_EVT_RIGHT      = 0x01;
var DFGT_EVT_LEFT       = 0x02;
var DFGT_EVT_BACK       = 0x03;
var DFGT_EVT_FORWARD    = 0x04;
var DFGT_EVT_PULLUP     = 0x05;
var DFGT_EVT_PULLDOWN   = 0x06;
var DFGT_EVT_PULLREMOVE = 0x07;
var DFGT_EVT_TOUCH1     = 0x21;
var DFGT_EVT_TOUCH2     = 0x22;
var DFGT_EVT_TOUCH3     = 0x23;
var DFGT_EVT_TOUCH4     = 0x24;
var DFGT_EVT_TOUCH5     = 0x25;


var SendCMD = [0xaa, 0x55, 0x00, 0x00, 0x00];



function sleep(time){//ms
  var startTime = system.uptime();
  while((system.uptime()- startTime) < time){}
}

function ArrayToString(fileData) {
  var dataString = "";
  for (var i = 0; i < fileData.length; i++) {
    dataString += String.fromCharCode(fileData[i]);
  }
  console.log("hello");
  return dataString;
}

function set(cmd,value){
  SendCMD[2] = cmd;
  SendCMD[3] = value;
  SendCMD[4] = cmd ^ value;
  serial.write(SendCMD);
  sleep(150);
}

function setGestureDistance(dis){
  if(dis > 30){
    return;
  }
  if(dis == 30){
    dis -= 2;
  }
  set(DFGT_CMD_DISTANCE, 0xff);
  set(DFGT_CMD_DISTANCE, 0x20 + (0xfe - 0x20) / 30 * dis);
}

function enableFunctionHelper(start,func){
  while(func){
    if(func & 0x01){
      set(DFGT_CMD_ENABLE,start)
    }
    start += 1;
    func >>= 1;
  }
}

function enableFunction(func){
  enableFunctionHelper(DFGT_FUN_START1 | 0x10, (func & DFGT_FUN_PART1) >> DFGT_FUN_OFFSET1);
  enableFunctionHelper(DFGT_FUN_START2 | 0x10, (func & DFGT_FUN_PART2) >> DFGT_FUN_OFFSET2);
}

function disableFunction(func){
  enableFunctionHelper(DFGT_FUN_START1, (func & DFGT_FUN_PART1) >> DFGT_FUN_OFFSET1);
  enableFunctionHelper(DFGT_FUN_START2, (func & DFGT_FUN_PART2) >> DFGT_FUN_OFFSET2);
}

var count = 0;
function frequency(){
  count = count+1;
  console.log('count:'+count);

}


var led = gpio.open({
  id: 'D13',
  success: function(){
    console.log('gpio: open D13 success')
  },
  fail:function(){
    console.log('gpio: open D13 failed')
  }
});

// user uart
var serial = uart.open({
  id: 'UART1',
  success: function(){
    console.log('uart: open uart1 success')
  },
  fail:function(){
    console.log('uart: open uart1 failed')
  }
});

var list1 = [DFGT_EVT_TOUCH1,DFGT_EVT_TOUCH2,DFGT_EVT_TOUCH3,DFGT_EVT_TOUCH4,DFGT_EVT_TOUCH5];
var list2 = [];
console.log('list1:'+list1);
serial.on('data', function(data) {
  if((data[0] == 0xaa) && (data[3] == 0x55)){
    switch(data[1]){
      case DFGT_EVT_BACK:
        console.log('get event back');
        break;
      case DFGT_EVT_FORWARD:
        console.log('get event forward');
        break;
      case DFGT_EVT_RIGHT:
        console.log('get event right');
        break;
      case DFGT_EVT_LEFT:
        console.log('get event left');
        break;
      case DFGT_EVT_PULLUP:
        console.log('get event pull up');
        break;
      case DFGT_EVT_PULLDOWN:
        console.log('get event pull down');
        break;
      case DFGT_EVT_PULLREMOVE:
        console.log('get event pull and remove');
        break;
      case DFGT_EVT_TOUCH1:
        console.log('get event touch1');
        break;
      case DFGT_EVT_TOUCH2:
        console.log('get event touch2');
        break;
      case DFGT_EVT_TOUCH3:
        console.log('get event touch3');
        break;
      case DFGT_EVT_TOUCH4:
        console.log('get event touch4');
        break;
      case DFGT_EVT_TOUCH5:
        console.log('get event touch5');
        break;
      default:
        break;
    }
    led.writeValue(0);
    list2.push(data[1]);
    console.log('list2 length:'+list2.length);

    if (list2.length == 5){
      if(list1.toString() == list2.toString()){
        console.log('success');
        led.writeValue(1);
        //setTimeout("delay",5);
        //led.writeValue(0);
        list2.length = 0;
        frequency();
      }else if(list1.toString() != list2.toString()){
        list2.length = 0;
        led.writeValue(0);
        console.log('fail');
      }
    }
    //list2.clear();
  }
});
setGestureDistance(20);
enableFunction(DFGT_FUN_ALL);
disableFunction(DFGT_FUN_RIGHT | DFGT_FUN_LEFT);



var device;
net.on('connect', function () {
    device = iot.device({
        productKey: productKey,
        deviceName: deviceName,
        deviceSecret: deviceSecret,
        region: 'cn-shanghai',
        success: function () {
            console.log('iot: [success] connect');
        },
        fail: function () {
            console.log('iot: [failed] connect');
        }
    });
})

setInterval(function() {
    device.postProps({
      payload: {
          Identifier: count
      }
    })
    console.log('hhh');
}, 3000);

app.json

{
  "version": "1.0.0",
  "io": {
    "UART1": {
      "type": "UART",
      "port": 1,
      "dataWidth": 8,
      "baudRate": 9600,
      "stopBits": 1,
      "flowControl": "cts",
      "parity": "none"
    },
    "D13":{
      "type": "GPIO",
      "port": 33,
      "dir": "output",
      "pull":"pulldown"
    }
  },
  "debugLevel": "DEBUG",
  "repl": "enable"
}

4.4.4 物联网平台及loT Studio教程

首先我们登录阿里云互联网的控制台,具体步骤参考2.2.5节教程

互联网平台使用请参考2.2.6节。

1.产品创建

在我们之前创建的智慧城市项目下创建名为”非接触式门禁”的产品,如下图所示:

点击完成,则会在产品列表出现一个名叫“非接触式门禁”的产品,点击查看。

2.产品功能定义

定义产品功能。选择功能定义后再点击添加自定义功能为“非接触式门禁”产品定义一个记录次数的功能,次数是整数型,所以使用int 32类型。如下图所示:

点击确认,则会在产品详情页的自定义功能栏看到所定义的功能及标识符,注意:记得发布上线。

3.产品设备添加

为产品添加设备。为“非接触式门禁”生成一个设备,选择设备,点击添加设备如下图所示:

点击完成即可:

然后我们可以在设备列表看到该设备信息。如下图:

4.在线调试参数

在线调试参数,当设备生成成功后我们可以选择在线调试参数。这一步的目的主要是为了生成移动应用时可以配置数据。点击查看,进入到设备详情页。再点击在线调试,进入到调试页面。 按照下图所示的方式进行调试推送即可。

5.Web可视化开发

下面开始介绍怎么利用阿里云物联网服务进行Web可视化开发

(1).新建web应用

如下图所示在项目管理界面中点击主页然后点击新建。输入名称后点击确认即可。创建Web应用请参考2.2.6节的Web可视化应用开发教程

(2).Web页面编辑按照4.1.4中的步骤添加图片和组件,如下图:

(3).配置参数

将实时曲线拖到画布中,然后配置参数,产品配置为“非接触式门禁”,设备配置为刚才创建的设备 ,属性为次数统计,点击验证数据格式,再点击确定,这就配置完成了.具体配置如下图:

(4).Web可视化发布

点击右上角发布,该项目就完成了。

(5).Web查看

Web 的页面已经生成,可直接查看应用。

进行到此步,即可开始 HaaS 600 程序的修改,完成真实物理设备同阿里云 IoT 平台的连接。

6.HaaS 600程序修改

程序修改步骤我们参考4.1节程序修改即可。

(1).我们获取Gesture_sensor设备证书如下图所示:

我们将如下对应信息修改即可。

(2).然后我们通过程序找到标识符对应的位置如下,如下图所示:

(3).接着我们找到产品标识符如图:

(4).然后在程序中找到(2)中的标识符,替换成(3)中标识符即可。

(5).本地热更新代码。

完成上面的步骤后,我们就完成了阿里云平台和非接触式门禁设备的连接,我们可以利用手势模拟门的开关了。

4.4.5 成品展示

接线:数据线和电源线参考4.1.5节

将手势传感器的T,R,-,+分别接入板子的R,T,-,+,如图:手势传感器的R接入D7,T接入D6,然后再分别对应接入“+”“-”。

注意:在此之前我们应该确保之前的GPS的短接帽已经拔下。

4.6 河道水位监测

前面我们已经做了几个应用,接下来我们接着做一个河道水位监测的应用,通过网页显示当前水位高度。

4.6.1 应用场景

利用模拟量超声波测距传感器,对某一河道水位进行监控,当水位超过设定值时,打开对应的闸门,使水位始终保持在警告值以下,确保安全。

4.6.2 所需原件

  • 1.HaaS 600 kit套件 x 1
  • 2.DFR0625 IO扩展板 x 1
  • 3.模拟量超声波测距传感器 x 1
  • 4.智能手机 x 1

4.6.3 例程

app.js

var adc = require('adc');
var iot = require('iot');
var network = require('network');
var net = network.openNetWorkClient();

/* 设备三元组信息获取请参考common目录下的iot组件说明 */
var productKey = 'a1vyA0XugNe'; /* your productKey */
var deviceName = 'testlight'; /* your deviceName */
var deviceSecret = '3f77a547297fbee3eddc47dcc231f3bb'; /* your deviceSecret */

var URM09 = adc.open({
  id: 'ADC0',
  success: function() {
    console.log('adc: open adc0 success')
  },
  fail: function() {
    console.log('adc: open adc0 failed')
  }
});

var device;
net.on('connect', function () {
    device = iot.device({
        productKey: productKey,
        deviceName: deviceName,
        deviceSecret: deviceSecret,
        region: 'cn-shanghai',
        success: function () {
            console.log('iot: [success] connect');
        },
        fail: function () {
            console.log('iot: [failed] connect');
        }
    });
})

/**
 * ADC输出为11位,5V为参考电压
 *
 */
setInterval(function() {
    /**
     * 测试使用用电量属性(PowerConsumption)来做测试
     */
    device.postProps({
      payload: {
        PowerConsumption: URM09.readValue()
      }
    })
    console.log('URM09 value:' + URM09.readValue())
}, 3000);

app.json

{
    "version": "1.0.0",
    "io": {
        "ADC0": {
            "type": "ADC",
            "port": 0,
            "sampling": 12000000
        }
    },
    "debugLevel": "ERROR"
}

4.6.4 物联网平台及loT Studio教程

首先我们登录阿里云互联网的控制台,具体步骤参考2.2.5节教程

互联网平台使用请参考2.2.6节。

1.产品创建

在我们之前创建的智慧城市项目下创建名为“河道水位监测”的产品,如下图所示:

点击完成,则会在产品列表出现一个名叫“河道水位监测”的产品,点击查看。

2.产品功能定义

定义产品功能。选择功能定义后再点击添加自定义功能为河道水位监测产品定义一个水位高度测试的属性,水位高度是一个范围值,可用float类型。如下图所示:

点击确认,则会在产品详情页的自定义功能栏看到所定义的功能及标识符。

3.产品设备添加

为产品添加设备。为“河道水位监测”生成一个设备,选择设备,点击添加设备如下图所示:

点击完成即可:

然后我们可以在设备列表看到该设备信息。如下图:

4.在线调试参数

在线调试参数,当设备生成成功后我们可以选择在线调试参数。这一步的目的主要是为了生成移动应用时可以配置数据。点击查看,进入到设备详情页。再点击在线调试,进入到调试页面。 按照下图所示的方式进行调试推送即可。

5.Web可视化开发

下面开始介绍怎么利用阿里云物联网服务进行Web可视化开发

(1).新建web应用

如下图所示在项目管理界面中点击主页然后点击新建。输入名称后点击确认即可。创建Web应用请参考2.2.6节的Web可视化应用开发教程

(2).Web页面编辑

下面进入Web的页面编辑,我们参考前面项目项目,拖入图片组件如图:

(3).配置参数

将实时曲线拖到画布中,然后配置参数,产品配置为河道水位监测,设备配置为刚才 创建的设备 ,属性为水位高度测试,点击验证数据格式,再点击确定,这就配置完成了.具体配置如下图:

(4).Web可视化发布

点击右上角发布,该web应用就完成了。

(5).Web查看

Web 的页面已经生成,可直接在网页上查看水位状态。

进行到此步,即可开始 HaaS 600 程序的修改,完成真实物理设备同阿里云 IoT 平台的连接。

6.HaaS 600程序修改

程序修改步骤我们参考4.1节程序修改即可。

(1).我们获取ultrasonic_ranging设备证书如下图所示:

我们将下图对应信息修改即可。

(2).然后我们找到程序中的标识符,如下图所示:

(3).接着我们找到产品标识符如图:

(4).然后在程序中找到(2)中的标识符,替换成(3)中标识符即可。

(5).本地热更新代码。

完成上面的步骤后,我们就完成了阿里云平台和河道水位监测设备的连接,我们可以对产品进行定位

4.6.5 成品展示

接线:接线:电源线和数据传输线参考4.1.5节的接线图

其中:黑色线接A0号引脚的“GND”,红色线接A0号引脚的“VCC”,蓝色线接A0号引脚的“A”,如图所示。

4.7 智能控制

使用继电器模块,通过浏览器网页开关,改变继电器的状态,来实现智能控制。

4.7.1 应用场景

对智能充电桩进行控制,当有设备充电时,继电器打开,进行充电,当没有设备进行充电时,继电器断开。

4.7.2 所需原件

  • 1.HaaS 600 kit套件 x 1
  • 2.DFR0625 IO扩展板 x 1
  • 3.数字继电器模块 x 1
  • 4.智能手机 x 1

4.7.3 例程

app.js

var gpio = require('gpio');
var iot = require('iot');
var network = require('network');
var net = network.openNetWorkClient();

var Relay = gpio.open({
	id: 'D13'
});

/* 设备三元组信息获取请参考common目录下的iot组件说明 */
var productKey = 'a1vyA0XugNe'; /* your productKey */
var deviceName = 'testlight'; /* your deviceName */
var deviceSecret = '3f77a547297fbee3eddc47dcc231f3bb'; /* your deviceSecret */

/**
 * 阿里云iot的创建和连接
 */
var device;
net.on('connect', function () {
    device = iot.device({
        productKey: productKey,
        deviceName: deviceName,
        deviceSecret: deviceSecret,
        region: 'cn-shanghai',
        success: function () {
            console.log('iot: [success] connect');
        },
        fail: function () {
            console.log('iot: [failed] connect');
        }
	});
	/* 云端设置属性事件 */
	device.on('props', function (payload) {
		/**
 		* 继电器高电平导通,低电平关闭
 		*/
		if (payload["LightStatus"] == '1') {
			Relay.writeValue(1);
			console.log('open relay');
		}
		if (payload["LightStatus"] == '0') {
			Relay.writeValue(0);
			console.log('close relay');
		}
	});

	/* 云端下发服务事件 */
	device.on('service', function (id, payload) {
    	console.log('iot: [success] iot.on(\'service\'), id: ' + id + ', payload: ' + JSON.stringify(payload));
	});
})

app.js

```json
{
    "version": "1.0.0",
    "io": {
        "D13": {
            "type": "GPIO",
            "port": 33,
            "dir": "output",
            "pull": "pulldown"
        }
    },
    "debugLevel": "ERROR"
}

/**

  • 主事件里可以干别的事
    */
    setInterval(function () {
    }, 5000);

## 4.7.4 物联网平台及loT Studio教程

首先我们登录阿里云互联网的控制台,具体步骤参考2.2.5节教程

互联网平台使用请参考2.2.6节。

**1.产品创建**

在我们之前创建的智慧城市项目下创建名为“智能控制”的产品,如下图所示:

![](https://img.dfrobot.com.cn/wiki/none/05f28d7cbc810a5964a81b358b883bf1.png)

点击完成,则会在产品列表出现一个名叫“智能控制”的产品,点击查看。

![](https://img.dfrobot.com.cn/wiki/none/4f1b201750664294a98da6dbc73a04c8.png)

**2.产品功能定义**

定义产品功能。选择功能定义后再点击添加自定义功能为“智能控制”产品定义一个开关监测的功能,开关有两种工作状态,可用bool型表示。如下图所示:

![](https://img.dfrobot.com.cn/wiki/none/3e3a7b9bae51cdc6ba6dd413cbbe2704.png)

点击确认,则会在产品详情页的自定义功能栏看到所定义的功能及标识符。

![](https://img.dfrobot.com.cn/wiki/none/4bd1b04043c3171977e748e7bc3b41c6.png)

**3.产品设备添加**

为产品添加设备。为智能控制生成一个设备,选择设备,点击添加设备如下图所示:

![](https://img.dfrobot.com.cn/wiki/none/d7ddb6d5bad1ce375a2c4b57c7fa93b5.png)

点击完成即可

![](https://img.dfrobot.com.cn/wiki/none/1c5457fc6876a726f1e97e95278372fb.png)

然后我们可以在设备列表看到该设备信息。如下图

![](https://img.dfrobot.com.cn/wiki/none/7ab1b576ba1399aac570c49a877c4bf4.png)

**4.在线调试参数**

在线调试参数,当设备生成成功后我们可以选择在线调试参数。这一步的目的主要是为了生成移动应用时可以配置数据。点击查看,进入到设备详情页。再点击在线调试,进入到调试页面。 按照下图所示的方式进行调试推送即可。

![](https://img.dfrobot.com.cn/wiki/none/a502d7f9e6c490e273fe7f469781d87e.png)

这里我们把0和1两种状态都推送一遍。

**5.Web可视化开发**

下面开始介绍怎么利用阿里云物联网服务进行Web可视化开发

(1).新建web应用

如下图所示在项目管理界面中点击主页然后点击新建。输入名称后点击确认即可。创建Web应用请参考2.2.6节的Web可视化应用开发教程

![](https://img.dfrobot.com.cn/wiki/none/b76bca8ef1578b9810fc3fe62fa9c238.png)

(2).Web页面编辑

![](https://img.dfrobot.com.cn/wiki/none/a47c5cb91102599d0ddd2403546c6ee4.png)

下面进入Web的页面编辑,我们参考前面项目,拖入图片组件如图:

![](https://img.dfrobot.com.cn/wiki/none/6fb38c20662643835ce4f61d04efc391.png)

(3).配置参数
将实时曲线拖到画布中,开关比较特殊,这里我们配置交互,在右侧选择交互,然后新增交互,事件我们选择点击,配置设备里面,产品选择智能控制,设备选择指定设备下的relay,属性选择开关监测,设置值我们选择参数来源下的组件值,如下图:

![](https://img.dfrobot.com.cn/wiki/none/5b52f1dcca54dc127929980360a3643a.png)

设置完成。

(4).Web可视化发布

点击右上角发布,该web应用就完成了。

(5).Web查看

Web 的页面已经生成,可直接在网页点击开关,就能实现相应的状态。

进行到此步,即可开始 HaaS 600 程序的修改,完成真实物理设备同阿里云 IoT 平台的连接。

**6.HaaS 600程序修改**

程序修改步骤我们参考4.1节程序修改即可。

(1).我们获取relay设备证书如下图所示:

![](https://img.dfrobot.com.cn/wiki/none/1028539a1f75cca7f8cf0cc2aeffe3f5.png)

然后我们把设备证书修改到下图指定位置即可

![](https://img.dfrobot.com.cn/wiki/none/dae69e0f7604485e912ea885ea64413a.png)

(2).然后我们通过程序找到对应的标识符,如下图所示:

![](https://img.dfrobot.com.cn/wiki/none/07577060ac5082dcc1fe21007501ecfc.png)

(3).接着我们找到产品标识符如图:

![](https://img.dfrobot.com.cn/wiki/none/aa11aef4bdaab7acec0cf20f2e78da1e.png)

(4).然后在程序中找到(2)中的标识符,替换成(3)中标识符即可。

(5).本地热更新代码。

完成上面的步骤后,我们就完成了阿里云平台和智能控制设备的连接,我们可以控制继电器的开关。

## 4.7.5 成品展示

接线:电源线和数据传输线参考4.1节的接线图

然后我们找到土壤湿度传感器

其中:黑色线接13号引脚的“GND”,红色线接13号引脚的“VCC”,绿色线接13号引脚的“D”,如图所示。

![](https://img.dfrobot.com.cn/wiki/none/a5cf07d3f654620533ea87e3c63f8ae7.png)

## 4.8 火情装置

使用火焰传感器,制作一个火情装置,用于监测火情。

##4.8.1 应用场景

将装置安置于不长期有人的场合,当监测到有火情发生时,会自动给钉钉推送一个消息,这时我们可以对火情做出快速准确的反应。

## 4.8.2 所需原件

* 1.HaaS 600 kit套件  x 1
* 2.DFR0625 IO扩展板 x 1
* 3.Flane sensor 火焰传感器x 1
* 4.智能手机 x 1

## 4.8.3 例程

**app.js**

```javascript
var adc = require('adc');
var iot = require('iot');
var network = require('network');
var net = network.openNetWorkClient();

/* 设备三元组信息获取请参考common目录下的iot组件说明 */
var productKey = 'a1vyA0XugNe'; /* your productKey */
var deviceName = 'testlight'; /* your deviceName */
var deviceSecret = '3f77a547297fbee3eddc47dcc231f3bb'; /* your deviceSecret */

var flame = adc.open({
  id: 'ADC0',
  success: function() {
    console.log('adc: open adc0 success')
  },
  fail: function() {
    console.log('adc: open adc0 failed')
  }
});

var device;
net.on('connect', function () {
    device = iot.device({
        productKey: productKey,
        deviceName: deviceName,
        deviceSecret: deviceSecret,
        region: 'cn-shanghai',
        success: function () {
            console.log('iot: [success] connect');
        },
        fail: function () {
            console.log('iot: [failed] connect');
        }
    });
})


/**
 * ADC输出为11位,5V为参考电压
 * 正常检测到火焰值时输出值 > 800
 */
setInterval(function() {
  if(flame.readValue() > 800){
    /**
     * 测试使用用电量属性(PowerConsumption)来做测试
     */
    device.postProps({
      payload: {
        PowerConsumption: flame.readValue()
      }
    })
    console.log('Flame detected')
  }
  console.log('Flame value:' + flame.readValue())
}, 200);

app.json

{
    "version": "1.0.0",
    "io": {
        "ADC0": {
            "type": "ADC",
            "port": 0,
            "sampling": 12000000
        }
    },
    "debugLevel": "ERROR"
}

4.8.4 物联网平台及loT Studio教程

首先我们登录阿里云互联网的控制台,具体步骤参考2.2.5节教程

互联网平台使用请参考2.2.6节。

1.产品创建

在我们之前创建的智慧城市项目下创建名为“火情装置”的产品,如下图所示:

点击完成,则会在产品列表出现一个名叫“火情装置”的产品,点击查看。

2.产品功能定义

定义产品功能。选择功能定义后再点击添加自定义功能为“火情装置”产品定义一个火情监测的功能,火焰值是一个范围值,可用int32类型表示。如下图所示:

点击确认,则会在产品详情页的自定义功能栏看到所定义的功能及标识符。

3.产品设备添加

为产品添加设备。为火情装置生成一个设备,选择设备,点击添加设备如下图所示:

点击完成即可

然后我们可以在设备列表看到该设备信息。如下图:

4.在线调试参数

在线调试参数,当设备生成成功后我们可以选择在线调试参数。这一步的目的主要是为了生成移动应用时可以配置数据。点击查看,进入到设备详情页。再点击在线调试,进入到调试页面。 按照下图所示的方式进行调试推送即可。

5.Web可视化开发

下面开始具体介绍怎么利用阿里云物联网服务进行业务逻辑开发

(1).新建业务逻辑应用

在loT Studio下选择业务逻辑开发,如下图所示:

创建一个新的业务逻辑服务,服务名称为火情报警,所属项目为智慧城市,如下图所示:

这样我们就创建了一个业务逻辑服务了,我们可以在所选项目下进行查看。如图:

(2).业务逻辑编辑

我们点击编辑,进入业务逻辑编辑页面,如下图:

<1>.在业务逻辑编辑器中,单击左侧导航栏的节点按钮,如图所示:

<2>. 配置设备触发节点

在节点的触发页签下,拖拽一个设备触发节点到画布上,并在画布右侧配置节点名称、数据源等。
节点名称我们选择默认的设备触发,产品我们选择创建好的火情装置产品,设备选择指定设备下之前创建的设备,触发条件选择选择属性上报中的火情监测,具体配置项如下图所示:

<3>.配置实现服务功能的逻辑节点

这里我们选择一个条件判断的逻辑节点,条件判断的逻辑节点包含两个条件,满足和不满足,我们可以设置一个值,来判断火情,这里我们设置一个参数值200,当值高于200,证明有火灾发生,否则没有,参数配置如下:

<4>.配置一个钉钉机器人节点。
配置一个钉钉机器人节点,通知钉钉群是否有火灾情况。如图:

<5>.在钉钉中添加一个机器人

如图添加一个机器人,然后复制webhook,如图:

将复制完的链接,添加进入钉钉机器人中的节点配置选项webhook中,这样,我们一个简单的逻辑应用开发就完成了

接下来我们依次点击保存,部署,启动,调试,发布即可,如下图所示。

进行到此步,即可开始 HaaS 600 程序的修改,完成真实物理设备同阿里云 IoT 平台的连接。

6.HaaS 600程序修改

程序修改步骤我们参考4.1节程序修改即可。

(1).我们获取flame_sensor设备证书如下图所示:

我们将下图对应信息修改即可。

(2).然后我们通过程序,找到标识符,如下图所示:

(3).接着我们找到产品标识符如图:

(4).然后在程序中找到(2)中的标识符,替换成(3)中标识符即可。

(5).本地热更新代码。

完成上面的步骤后,我们就完成了阿里云平台和火情装置设备的连接,我们可以对火情监控并且出现火情时进行报警了。

4.8.5 成品展示

接线:接线:电源线和数据传输线参考4.1.5节的接线图

其中:黑色线接A0号引脚的“GND”,红色线接A0号引脚的“VCC”,蓝色线接A0号引脚的“A”,如图所示