ESP8266开发之旅 小程序之阿里云篇② “IOT菜鸟”小程序,源码分析,创作自己的小程序

授人以鱼不如授人以渔,目的不是为了教会你具体项目开发,而是学会学习的能力。希望大家分享给你周边需要的朋友或者同学,说不定大神成长之路有博哥的奠基石。。。

共同学习成长QQ群 622368884,不喜勿加,里面有一大群志同道合的探路人

快速导航
单片机菜鸟的博客快速索引(快速找到你要的)

重点说一下,麻烦三连点赞,你的点赞是博主创作的前进动力

在这里插入图片描述

1. 前言

在上一篇 ESP8266开发之旅 小程序之阿里云篇① “IOT菜鸟”小程序,小白简单配置就可以玩起来中,博主教会大家如何使用该小程序,那么接下来我们就来分析一下源码,力求让大家能了解其中核心代码。

2. 读者知识要求

  • 至少了解过 HTMLCSSJS
  • 至少了解过 微信小程序官方开发文档
  • 至少要去了解阿里云物联网开发文档
    在这里插入图片描述
    这是我们小程序业务请求的重点,也是本篇重中之重

3. 源码分析

以下就是IOT菜鸟小程序的源码,麻雀虽小五脏俱全,请读者认真学习,博主会跳过某些内容(比如教你如何创建小程序、如何创建一个page页面),重点讲解我们需要关注的知识点。
在这里插入图片描述

  • components 组件
    公共显示组件

  • images
    显示图标

  • model
    具体业务数据模块(重点讲解内容,也是读者后面自定义比较多的地方)

  • pages
    具体显示页面(会挑控制页面讲解)

  • utils
    工具类方法(重点讲解内容)

  • app.xxx
    小程序入口

3.1 app.xxx —— 小程序入口

app.xxx 是整个小程序的入口,我们可以在这里设置一些整个小程序会使用的数据或者初始化内容。

在这里插入图片描述

包含文件:

  • app.js —— 公共JS逻辑,比如一些全局变量
    在这里插入图片描述
    这里定义了我们小程序整个环境需要用到的阿里云物联网配置参数,并且配置参数从存储中读取,如果没有我们就填一些默认值开发者也可以填写自己的默认值,这样第一次进入小程序的时候就不需要配置了

  • app.json—— 整个小程序的配置
    在这里插入图片描述
    开发者可以修改成自己想要的名字

  • app.wxss—— 整个小程序的一些css样式
    开发者可以把一些公用的css抽取到这里,就不用每个页面都写一遍。

3.2 utils —— 工具类

在这里插入图片描述
重点关注:

  • cryptojs 加密签名相关
  • http.js通用网络请求相关
  • aliyunHttp.js阿里云物联网网络请求相关,依赖http.js
  • storage.js 存储配置内容
  • timeFormat.js 时间格式化,阿里云物联网对时间格式有要求

这里通过讲解http.js 和 aliyunHttp.js来顺带讲解其他工具类。

3.2.1 Http.js —— 通用网络请求

源码分析:

/**
 *  HTTP请求工具类
 *  @Date 2020-04-26
 **/

/**
 * 获取HTTP请求头
 * @param {Object} currentHeader - 需要配置的请求头
 * @return {Object} header
 **/
function getHeader(currentHeader) {
    
    
    const header = currentHeader || {
    
    };
    header['content-type'] = header['content-type'] || 'application/json';
    return header;
}

/**
 * 检查网络状态
 **/
function checkNetwork() {
    
    
    return new Promise((resolve, reject) => {
    
    
        wx.getNetworkType({
    
    
            success: function(res) {
    
    
                // 返回网络类型, 有效值:
                // wifi/2g/3g/4g/unknown(Android下不常见的网络类型)/none(无网络)
                const networkType = res.networkType;

                if (networkType === 'none') {
    
    
                    wx.showModal({
    
    
                        title: '当前网络不可用,请检查网络设置',
                        confirmText: '重试',
                        success: function(res) {
    
    
                            if (res.confirm) {
    
    
                                checkNetwork();
                            } else {
    
    
                                reject(new Error('NetWorkError'));
                            }
                        }
                    });
                } else {
    
    
                    resolve();
                }
            }
        });
    });
}

export default {
    
    

    request(url, data, method, headers, complete) {
    
    
        return new Promise((resolve, reject) => {
    
    
            checkNetwork().then(() => {
    
    
                wx.request({
    
    
                    url: url,
                    data: data,
                    method: method || 'GET', //  OPTIONS, GET, HEAD, POST, PUT, DELETE, TRACE, CONNECT
                    header: getHeader(headers), // 设置请求的 header
                    success: (res) => {
    
    
                        // HTTP响应code
                        if (res.statusCode === 200) {
    
    
                            // 需要处理一些公关逻辑,比如公共错误业务code等等
                            resolve(res.data);
                        } else {
    
    
                            reject(res);
                        }
                    },
                    fail: (err) => {
    
    
                        reject(err);
                    },
                    complete
                });
            }).catch(err => {
    
    
                console.log(err);
            });
        });
    },

    get(opts = {
    
    }) {
    
    
        return this.request(opts.url, opts.data, 'GET', opts.headers);
    },

    post(opts = {
    
    }) {
    
    
        return this.request(opts.url, opts.data, 'POST', opts.headers);
    },
};

  • 我们定义了两个请求 GETPOST(底层都是调用request)以及一个自定义的 request 方法,读者可以自定义其他的Method(HEAD、PUT、DELETE等)

  • request是一个Promise,先去判断网络情况(没有连接网络,没有就弹出一个model提示用户),之后就是发起网络请求 wx.request

  • wx.request中我们会设置一下Header (getHeaders)以及处理 HTTP响应Code,等于200才会返回,其他Code抛出异常。

非常简单,都是通用的HTTP协议

3.2.2 aliyunHttp.js —— 针对阿里云物联网的网络请求

  • 读者必须先去了解 阿里云物联网云端开发指南
  • 重点关注公共逻辑部分
    在这里插入图片描述
3.2.2.1 请求结构

在这里插入图片描述
下面以调用Pub接口向指定Topic发布消息为例:

https://iot.cn-shanghai.aliyuncs.com/?Action=Pub
&Format=XML
&Version=2017-04-20
&Signature=Pc5WB8gokVn0xfeu%2FZV%2BiNM1dgI%3D
&SignatureMethod=HMAC-SHA1
&SignatureNonce=15215528852396
&SignatureVersion=1.0
&AccessKeyId=...
&Timestamp=2017-07-19T12:00:00Z
&RegionId=cn-shanghai
...
  • 一个网络请求肯定有URL,阿里云物联网这个URL需要根据自己的账号去填写,IOT菜鸟提供了配置页面选择RegionID
  • 这是一个GET请求,涉及了一堆参数,包括公共参数以及业务参数
3.2.2.2 公共参数

在这里插入图片描述
示例:

https://iot.cn-shanghai.aliyuncs.com/
?Format=XML
&Version=2018-01-20
&Signature=Pc5WB8gokVn0xfeu%2FZV%2BiNM1dgI%3D
&SignatureMethod=HMAC-SHA1
&SignatureNonce=15215528852396
&SignatureVersion=1.0
&AccessKeyId=...
&Timestamp=2018-05-20T12:00:00Z
&RegionId=cn-shanghai
3.2.2.3 公共返回参数

API返回结果采用统一格式,返回2xx HTTP状态码代表调用成功;返回4xx或5xx HTTP状态码代表调用失败。调用成功返回的数据格式有XML和JSON两种。可以在发送请求时,指定返回的数据格式。默认为XML格式。

每次接口调用,无论成功与否,系统都会返回一个唯一识别码RequestId

我们这里采用JSON。

成功示例:

{
    
    
    "RequestId": "4C467B38-3910-447D-87BC-AC049166F216"
    /* 返回结果数据 */
}

失败示例:

{
    
    
    "RequestId": "8906582E-6722-409A-A6C4-0E7863B733A5",
    "Code": "UnsupportedOperation",
    "Message": "The specified action is not supported."
}

在失败的时候,最好弹一个toast提示用户。我们可以获取Message内容。
在aliYunHttp里面可以看到这个代码:

/**
 * 处理接口响应内容
 *
 * @param {String} res
 * @param {function} resolve
 * @param {function} reject
 **/
function handleResponse(res, resolve, reject) {
    
    
    let {
    
     Success } = res;
    if (Success) {
    
    
        // api调用成功 返回整个数据
        resolve && resolve(res);
    } else {
    
    
        // api调用失败
        let {
    
     RequestId, Code, ErrorMessage} = res;
        wx.showToast({
    
     title: `${
    
    Code}:${
    
    ErrorMessage}`, icon: 'none' });
        reject && reject({
    
    
            RequestId,
            Code,
            ErrorMessage
        });
    }
}
3.2.2.4 签名机制

物联网平台会对每个接口访问请求的发送者进行身份验证,所以无论使用HTTP还是HTTPS协议提交请求,都需要在请求中包含签名(Signature)信息。

内容太多,博主以图示来说明签名的重要内容:

  • 构造规范化的请求字符串(Canonicalized Query String
    在这里插入图片描述

  • 构造签名字符串
    在这里插入图片描述

  • 计算HMAC
    在这里插入图片描述

  • 计算签名值
    在这里插入图片描述

  • 添加签名
    在这里插入图片描述

3.2.2.5 aliyunHttp源码分析
/**
 *  针对AliYun API的HTTP请求工具类
 *  @Date 2020-04-26
 **/

// 通用网络请求
import http from './http.js';
import timeFormat from './timeFormat.js';
// 加密模块
let crypto = require("./cryptojs/cryptojs.js").Crypto;

const app = getApp();

// 配置公共参数
const _defaultParams = () => {
    
    
    // 阿里云要求的公共请求参数  https://help.aliyun.com/document_detail/30561.html?spm=a2c4g.11186623.6.739.6bc03d291aEGp1
    let commonParams = {
    
    
        Format: 'JSON', // 返回值的类型,支持JSON和XML类型
        Version: '2018-01-20', // API版本号
        AccessKeyId: app.aliConfig.AccessKeyId, // 阿里云颁发给用户的访问服务所用的密钥ID
        // Signature: '', // 签名结果串 需要另外计算  为了方便 不放在公共参数
        SignatureMethod: 'HMAC-SHA1', // 签名方式,目前支持HMAC-SHA1
        Timestamp: timeFormat.getCurrentUTCTime('{YYYY}-{MM}-{DD}T{HH}:{mm}:{ss}Z'), // 请求的时间戳,日期格式按照ISO8601标准表示,并需要使用UTC时间。格式为YYYY-MM-DDThh:mm:ssZ。2016-01-04T12:00:00Z
        SignatureVersion: '1.0', // 签名算法版本
        SignatureNonce: new Date().getTime() + '', // 唯一随机数,用于防止网络重放攻击。用户在不同请求中要使用不同的随机数值
        RegionId: app.aliConfig.RegionId, // 设备所在地域(与控制台上的地域对应),如cn-shanghai。
    };
    return commonParams;
};

// 将数组参数格式化成url传参方式
const _flatArrayList = (target, key, Array) => {
    
    
    for (let i = 0; i < Array.length; i++) {
    
    
        let item = Array[i];

        if (item && typeof item === 'object') {
    
    
            const keys = Object.keys(item);
            for (let j = 0; j < keys.length; j++) {
    
    
                target[`${
    
    key}.${
    
    i + 1}.${
    
    keys[j]}`] = item[keys[j]];
            }
        } else {
    
    
            target[`${
    
    key}.${
    
    i + 1}`] = item;
        }
    }
};

//将所有请求参数展开平面化,考虑到有些接口给到的参数是数组
const _flatParams = (params) => {
    
    
    let target = {
    
    };
    let keys = Object.keys(params);
    for (let i = 0; i < keys.length; i++) {
    
    
        let key = keys[i];
        let value = params[key];
        if (Array.isArray(value)) {
    
    
            _flatArrayList(target, key, value);
        } else {
    
    
            target[key] = value;
        }
    }
    return target;
};

// url编码
const _percentEncode= (str) => {
    
    
    let result = encodeURIComponent(str);

    return result.replace(/\!/g, '%21')
        .replace(/\'/g, '%27')
        .replace(/\(/g, '%28')
        .replace(/\)/g, '%29')
        .replace(/\*/g, '%2A');
};

/**
 * 构造规范化的请求字符串
 * @param {Object} params 请求参数,不包括Signature
 * @return {String} result 格式:key1=value1&key2=value2....
 **/
const _getCanonicalizedQueryString = (params) => {
    
    
    let list = [];
    let flatParams = _flatParams(params);
    Object.keys(flatParams).sort().forEach((key) => {
    
    
        let value = flatParams[key];
        list.push([_percentEncode(key), _percentEncode(value)]);
    });

    let queryList = [];
    for (let i = 0; i < list.length; i++) {
    
    
        let [key, value] = list[i];
        queryList.push(key + '=' + value);
    }
    return queryList.join('&');
};

/**
 * 获取加密字符串
 * @param {String} stringToSign 请求方法
 * @param {Object} key 签名key
 **/
const _signature = (stringToSign, key) => {
    
    
    let signature = crypto.HMAC(crypto.SHA1, stringToSign, key, {
    
    
        asBase64: true
    });

    return signature;
};

/**
 * 处理接口响应内容
 *
 * @param {String} res
 * @param {function} resolve
 * @param {function} reject
 **/
function handleResponse(res, resolve, reject) {
    
    
    let {
    
     Success } = res;
    if (Success) {
    
    
        // api调用成功 返回整个数据
        resolve && resolve(res);
    } else {
    
    
        // api调用失败
        let {
    
     RequestId, Code, ErrorMessage} = res;
        wx.showToast({
    
     title: `${
    
    Code}:${
    
    ErrorMessage}`, icon: 'none' });
        reject && reject({
    
    
            RequestId,
            Code,
            ErrorMessage
        });
    }
}

let aliyunApi = {
    
    

    /**
     * AliyunApi GET请求
     * @param {Object} opts 包含请求参数、请求URL、请求头
     **/
    get(opts = {
    
    }) {
    
    
        opts.url = opts.url || app.aliConfig.EndPoint;
        // 获取公共参数
        let defaultParams = _defaultParams();
        // 合并参数
        opts.data = Object.assign(defaultParams,opts.data);
        let canonicalizedQueryString = _getCanonicalizedQueryString(opts.data);
        let stringToSign = `GET&${
    
    _percentEncode('/')}&${
    
    _percentEncode(canonicalizedQueryString)}`;
        //console.log(stringToSign);
        let signature = _signature(stringToSign, app.aliConfig.AccessKeySecret + '&');
        // 补上 Signature参数
        opts.data = {
    
    
            ...opts.data,
            Signature: signature
        };

        return new Promise((resolve, reject) => {
    
    
            http.get(opts).then((res) => {
    
    
                handleResponse(res, resolve, reject);
            }).catch(err => {
    
    
                console.log(err);
            })
        });
    },

    /**
     * AliyunApi POST请求
     * @param {Object} opts 包含请求参数、请求URL、请求头
     **/
    post(opts = {
    
    }) {
    
    
        opts.url = opts.url || app.aliConfig.EndPoint;
        // 获取公共参数
        let defaultParams = _defaultParams();
        // 合并参数
        opts.data = Object.assign(defaultParams,opts.data);
        let canonicalizedQueryString = _getCanonicalizedQueryString(opts.data);
        let stringToSign = `POST&${
    
    _percentEncode('/')}&${
    
    _percentEncode(canonicalizedQueryString)}`;
        let signature = _signature(stringToSign, app.aliConfig.AccessKeySecret + '&');
        // 补上 Signature参数
        opts.data = {
    
    
            ...opts.data,
            Signature: signature
        };

        opts.headers = opts.headers || {
    
    };
        opts.headers['content-type'] = 'application/x-www-form-urlencoded';

        return new Promise((resolve, reject) => {
    
    
            http.post(opts).then((res) => {
    
    
                handleResponse(res, resolve, reject);
            }).catch(err => {
    
    
                console.log(err);
            })
        });
    }
};

export {
    
     aliyunApi };

注意: 读者需要从 get/post 方法开始阅读,博主在里面注释都非常清晰
在这里插入图片描述

  • 公共参数
    在这里插入图片描述
  • 构造规范化的请求字符串 —— _getCanonicalizedQueryString
    在这里插入图片描述
  • 构造签名字符串 —— stringToSign
let stringToSign = `POST&${
    
    _percentEncode('/')}&${
    
    _percentEncode(canonicalizedQueryString)}`;
  • 生成签名值
    在这里插入图片描述
    到这里,阿里云API底层源码讲解完毕,接下来会讲解具体业务。

3.3 model —— 具体业务请求

具体业务相关内容,博主放在了model目录,当前小程序用到了设备管理。
在这里插入图片描述
关于设备管理,请读者自行查阅
在这里插入图片描述
对应代码如下:

/**
 *  针对AliYun 设备管理API请求
 *  https://help.aliyun.com/document_detail/69893.html?spm=a2c4g.11186623.6.736.5fcd342dh5UEoS
 *
 *  @Date 2020-04-27
 **/

import {
    
     aliyunApi } from '../../utils/aliyunHttp.js';

const app = getApp();

let deviceApi = {
    
    

    /**
     * 在指定产品下注册设备
     *
     * @param {Object} param 请求参数
     * {
     *      DeviceName: xxxx,
     *      Nickname: xxxx
     * }
     **/
    registerDevice(param = {
    
    }) {
    
    
        let opts = {
    
    
            data: {
    
    
                ...param,
                Action: 'RegisterDevice',
                ProductKey: app.aliConfig.ProductKey,
            }
        };
        return aliyunApi.get(opts);
    },

    /**
     * 查询指定设备的详细信息
     *
     * @param {Object} param 请求参数
     * {
     *      IotId: xxxxx,
     * }
     **/
    queryDeviceDetail(param = {
    
    }) {
    
    
        let opts = {
    
    
            data: {
    
    
                ...param,
                Action: 'QueryDeviceDetail',
            }
        };
        return aliyunApi.get(opts);
    },

    /**
     * 批量查询设备详情。
     *
     * @param {Object} param 请求参数
     * {
     *      DeviceName: [
     *      ],
     * }
     **/
    batchQueryDeviceDetail(param = {
    
    }) {
    
    
        let opts = {
    
    
            data: {
    
    
                ...param,
                Action: 'BatchQueryDeviceDetail',
                ProductKey: app.aliConfig.ProductKey,
            }
        };
        return aliyunApi.get(opts);
    },

    /**
     * 查询指定产品下的所有设备列表,分页接口
     *
     * @param {Object} param 请求参数
     * {
     *      PageSize: xxxx,
     *      CurrentPage: xxxx
     * }
     **/
    queryDevice(param = {
    
    }) {
    
    
        let opts = {
    
    
            data: {
    
    
                ...param,
                Action: 'QueryDevice',
                ProductKey: app.aliConfig.ProductKey,
            }
        };
        return aliyunApi.get(opts);
    },

    /**
     * 删除指定设备
     *
     * @param {Object} param 请求参数
     * {
     *      IotId: xxxxx,
     * }
     **/
    deleteDevice(param = {
    
    }) {
    
    
        let opts = {
    
    
            data: {
    
    
                ...param,
                Action: 'DeleteDevice',
            }
        };
        return aliyunApi.get(opts);
    },

    /**
     * 查看指定设备的运行状态
     *
     * @param {Object} param 请求参数
     * {
     *      IotId: xxxxx,
     * }
     **/
    getDeviceStatus(param = {
    
    }) {
    
    
        let opts = {
    
    
            data: {
    
    
                ...param,
                Action: 'GetDeviceStatus',
            }
        };
        return aliyunApi.get(opts);
    },

    /**
     * 批量查看同一产品下指定设备的运行状态。
     *
     * @param {Object} param 请求参数
     * {
     *      IotId: [
     *      ],
     * }
     **/
    batchGetDeviceState(param = {
    
    }) {
    
    
        let opts = {
    
    
            data: {
    
    
                ...param,
                Action: 'BatchGetDeviceState',
                ProductKey: app.aliConfig.ProductKey,
            }
        };
        return aliyunApi.get(opts);
    },

    /**
     * 禁用指定设备
     *
     * @param {Object} param 请求参数
     * {
     *      IotId: xxxxxx,
     * }
     **/
    disableThing(param = {
    
    }) {
    
    
        let opts = {
    
    
            data: {
    
    
                ...param,
                Action: 'DisableThing',
            }
        };
        return aliyunApi.get(opts);
    },

    /**
     * 解除指定设备的禁用状态,即启用被禁用的设备
     *
     * @param {Object} param 请求参数
     * {
     *      IotId: xxxxxx,
     * }
     **/
    enableThing(param = {
    
    }) {
    
    
        let opts = {
    
    
            data: {
    
    
                ...param,
                Action: 'EnableThing',
            }
        };
        return aliyunApi.get(opts);
    },

    /**
     * 查询指定设备的属性记录
     *
     * @param {Object} param 请求参数
     * {
     *      Identifier: xxxxxx,
     *      PageSize: xxxxx,
     *      IotId: xxxxx
     * }
     **/
    queryDevicePropertyData(param = {
    
    }) {
    
    
        let opts = {
    
    
            data: {
    
    
                ...param,
                Asc: 0,
                EndTime: new Date().getTime() + '',
                StartTime: '',// 要转成上线那天的时间
                Action: 'QueryDevicePropertyData',
            }
        };
        return aliyunApi.get(opts);
    },

    /**
     * 调用该接口批量修改设备备注名称
     *
     * @param {Object} param 请求参数
     * {
     *      DeviceNicknameInfo.N.IotId: xxxxx,
     *      DeviceNicknameInfo.N.Nickname: xxxxx
     * }
     **/
    updateDeviceNickname(param = {
    
    }) {
    
    
        let opts = {
    
    
            data: {
    
    
                ...param,
                Action: 'BatchUpdateDeviceNickname',
            }
        };
        return aliyunApi.get(opts);
    },

    /**
     * 调用该接口为指定设备设置属性值
     *
     * @param {Object} param 请求参数
     * {
     *      IotId: xxxxx,
     *      Items: xxxxx
     * }
     **/
    setDeviceProperty(param = {
    
    }) {
    
    
        let opts = {
    
    
            data: {
    
    
                ...param,
                Action: 'SetDeviceProperty',
            }
        };
        return aliyunApi.get(opts);
    },


};

export {
    
     deviceApi };

每个接口都有对应的方法,并且携带上自己的自定义参数,非常简单。

3.4 pages —— 展示页面

展示页面均放在pages下面。目前用到了index和config
在这里插入图片描述
我们这里以分析index页面为例。请读者自行看代码注释

//index.js
//获取应用实例
import {
    
    deviceApi} from "../../model/aliyun/device";
import {
    
    storage} from "../../utils/storage";
const app = getApp();

Page({
    
    
  _data: {
    
    
      PageSize: 50,
      CurrentPage: 1,
  },

  data: {
    
    
      deviceOnLine: [],//在线设备
      deviceOffLine: [],//离线设备
      deviceUnative: [],//未激活设备
      deviceDisable: [],//已禁用设备
      showConfig: false,
  },
  onLoad: function () {
    
    
  },

  onShow() {
    
    
      if (!app.aliConfig.RegionId || !app.aliConfig.AccessKeyId
          || !app.aliConfig.ProductKey
          || !app.aliConfig.EndPoint){
    
    
          this.setData({
    
    
              showConfig: true
          });
      } else {
    
    
          this.setData({
    
    
              showConfig: false
          });
          wx.showLoading({
    
    
              title: '努力加载中...',
              mask: true
          });
          this.loadDeviceList();
      }
  },

  onPullDownRefresh() {
    
    
      this.loadDeviceList();
  },

  loadDeviceList() {
    
    
      // 先清空数据
      this.setData({
    
    
          deviceOnLine: [],
          deviceOffLine: [],
          deviceUnative: [],
          deviceDisable: [],
      }, () => {
    
    
          this._data.CurrentPage = 1; //从第一页开始
          this.queryDevice(this._data.PageSize, this._data.CurrentPage);
      });
  },

  // 查询设备
  queryDevice(pageSize = 50, currentPage = 1) {
    
    
      // 调用model device的api
      deviceApi.queryDevice({
    
    
          PageSize: pageSize,
          CurrentPage: currentPage,
      }).then((res) => {
    
    
          if (res.Data && res.Data.DeviceInfo) {
    
    
              this.handleDeviceList(res.Data.DeviceInfo);
              // 判断是否需要继续请求
              if (res.PageCount > this._data.CurrentPage) {
    
    
                  this._data.CurrentPage ++;
                  this.queryDevice(this._data.PageSize, this._data.CurrentPage);
              } else {
    
    
                  this.finishQueryDevice();
              }
          } else {
    
    
              this.finishQueryDevice();
          }
      }).catch(err => {
    
    
          console.log(err);
          this.finishQueryDevice();
      });
  },

  finishQueryDevice(){
    
    
      wx.stopPullDownRefresh();
      wx.hideLoading && wx.hideLoading();
  },

  // 处理列表返回内容
  handleDeviceList(deviceList) {
    
    
      let deviceOnLine = [];
      let deviceOffLine = [];
      let deviceUnative = [];
      let deviceDisable = [];

      // 如果你是试用过了小程序 是不是觉得led1 led2非常熟悉呢?这里就是原因了
      if(deviceList && Array.isArray(deviceList)) {
    
    
           deviceList.forEach((device) => {
    
    
              let type;
              if (device.Nickname.indexOf('_led2') > -1) {
    
    
                  type = '_led2';
              } else if (device.Nickname.indexOf('_led3') > -1) {
    
    
                  type = '_led3';
              } else if (device.Nickname.indexOf('_lamp1') > -1) {
    
    
                  type = '_lamp1';
              } else if (device.Nickname.indexOf('_lamp2') > -1) {
    
    
                  type = '_lamp2';
              } else {
    
    
                  type = '_led1';
              }
              this.setDevice(device,type);

              if (device.DeviceStatus === 'ONLINE') {
    
    
                  deviceOnLine.push(device);
              } else if (device.DeviceStatus === 'OFFLINE') {
    
    
                  deviceOffLine.push(device);
              } else if (device.DeviceStatus === 'UNACTIVE') {
    
    
                  deviceUnative.push(device);
              } else if (device.DeviceStatus === 'DISABLE') {
    
    
                  deviceDisable.push(device);
              }
           });
      }
      this.setData({
    
    
          deviceOnLine: this.data.deviceOnLine.concat(deviceOnLine),
          deviceOffLine: this.data.deviceOffLine.concat(deviceOffLine),
          deviceUnative: this.data.deviceUnative.concat(deviceUnative),
          deviceDisable: this.data.deviceDisable.concat(deviceDisable),
      });
  },

  setDevice(device, type) {
    
    
      device.Nickname = device.Nickname.replace(type, '');
      if (device.DeviceStatus === 'ONLINE' || device.DeviceStatus === 'OFFLINE') {
    
    
          device.Image = `/images/icon${
    
    type}_on.png`;
      } else  {
    
    
          device.Image = `/images/icon${
    
    type}_off.png`;
      }
  },
  // 跳转配置页面
  goToConfig() {
    
    
      console.log('goToConfig');
      wx.navigateTo({
    
    
          url: '/pages/config/config',

      });
  }
});

4. 总结

本篇主要是简单讲解IOT菜鸟小程序的源码,包括:

  • http
  • aliyunhttp
  • page/index

整体难度不高,也实现了博主的初衷,为IOT事业做贡献。

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
喜欢的同学,请不要跑了,给博主点个赞,你的点赞是博主前进的动力。

猜你喜欢

转载自blog.csdn.net/dpjcn1990/article/details/105910727