From eea9a9b2e7838b92ea0a0a3577683ed3e54d7e36 Mon Sep 17 00:00:00 2001 From: IoTcat Date: Sun, 5 May 2019 23:55:56 +0800 Subject: [PATCH] v0.0.10 --- node/.gitignore | 3 + node/LICENSE | 21 ++++++ node/README.md | 158 ++++++++++++++++++++++++++++++++++++++++++++++ node/app.js | 20 +++--- node/package.json | 2 +- node/wiot.js | 90 +++++++++++++++++++++++--- 6 files changed, 273 insertions(+), 21 deletions(-) create mode 100644 node/.gitignore create mode 100644 node/LICENSE create mode 100644 node/README.md diff --git a/node/.gitignore b/node/.gitignore new file mode 100644 index 0000000..f52b76c --- /dev/null +++ b/node/.gitignore @@ -0,0 +1,3 @@ +config.php +app.js +wiot.bin \ No newline at end of file diff --git a/node/LICENSE b/node/LICENSE new file mode 100644 index 0000000..525d132 --- /dev/null +++ b/node/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2019 IoTcat + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/node/README.md b/node/README.md new file mode 100644 index 0000000..51f6b38 --- /dev/null +++ b/node/README.md @@ -0,0 +1,158 @@ +## wIoT for NodeJS +适用于NodeJS的wIoT服务器控制组件,轻松物联 + +## 先觉条件 + - 拥有烧录好wIoT固件的**D1 MINI**单片机 + - 一台或多台无线WiFi路由器2.4G/5G + - 局域网内拥有一台装有**NodeJS**的服务器或电脑 (NodeJS装法非常简单, 请自行Google或百度) + - 配置好**npm** + +## 快速开始 + +### 单片机接入 +1. 使用MicroUSB, 5V, 或3V pin脚给单片机供电 +2. 用一根导线连接D0脚与3V3脚,持续一秒以上拔出,以重置单片机 +3. 用手机或电脑搜索它的WiFi热点,名称格式`wiot-xx:xx:xx:xx:xx:xx` +4. 连接上此热点,密码为`1234567890` +5. 用浏览器打开网址`http://192.168.0.1`,记录网页中的MAC地址,这将用于识别此单片机 +6. 配置你无线路由器的ssid(即wifi名称,注意不能有非ASCII字符,比如汉字)和密码 +7. 配置完成后热点将自动断开,单片机将连接到你的无线路由器 + +### 依赖安装 +在你的项目文件夹下打开命令行,输入以下指令安装wiot: +````shell +$ npm install wiot +```` +### 使用方法 +在你的项目文件夹中新建一个app.js文件,输入以下内容: + +```js +var wiot = require('wiot'); //引入wiot依赖包 + +// 新建一个单片机对象 +// 这里使用了两个参数,MAC是单片机的MAC地址,pin中指定需要OUTPUT输出的端口 +// 请自行修改MAC地址的值 +var MyMCU = new wiot.client({MAC: "xx:xx:xx:xx:xx:xx", pin: {D4: wiot.OUTPUT}); + + +// 以下代码将实现,板载led亮1秒,灭1秒的循环 + +// 设置计时器,每隔2000毫秒, MyMCU的3号pin口将拉高一次电平 +setInterval(()=>{ + MyMCU.write(wiot.D4, wiot.HIGH); +}, 2000); + +// 设置计时器,延时1000毫秒后开始执行大括号中指令 +setTimeout(()=>{ + // 设置计时器,每隔2000毫秒,MyMCU的3号pin口将拉低一次电平 + setInterval(()=>{ + MyMCU.write(wiot.D4. wiot.LOW); + }, 2000); + +}, 1000); + +``` + +### 开始执行 +在项目文件夹中打开命令行,输入以下指令: +````shell +node app.js +```` + +### 预期结果 +如果一切顺利,你现在应该会发现你的板载led在闪烁了 + + +## 进阶设置 + +### wiot.client参数说明 +名称 | 默认值 | 描述 +----|-------|---- +MAC | "" | 单片机的MAC地址 +pin | {D1: 0, D2: 0, D3: 0, D4: 0, D5: 0, D6: 0, D7: 0, D8: 0} | pin脚的模式, 0为INPUT, 1为OUTPUT, 2为INPUT_PULLUP +hint | true | 是否显示状态提示 +debug | false | 是否开启debug模式 +ip | "default" | 指定单片机IP, 请在长时间搜索不到IP时尝试此选项 +ip_range | "192.168.0" | IP搜索字段,请在长时间搜索不到IP时尝试此选项 +localIP | "127.0.0.1" | 本机IP +errDelayTime | 2000 | 遇到网络错误时重试间隔时间(毫秒) +okDelayTime | 30 | 收到网络请求后延时等待时间(毫秒) +resetDelayTime | 4500 | 向单片机发送重置指令后多久不再发送新消息(毫秒) +noTryMaxTime | 15000 | 经过此时间单片机仍未响应则重新发送消息(毫秒) +IntervalTime | 2000 | 监听行为心跳间隔 +MaxToReScanTime | 180000 | 经过此事件单片机无响应则从新扫描IP地址(毫秒) +MinResearchTime | 5000 | 搜索IP经过一此轮询后间隔时间(毫秒) +IpScanTimeout | 1 | IP扫描时的Ping检测超时时间(秒) +pingTimeout | 2 | 心跳Ping检测的超时时间(秒) +MaxTraceBackTimes | 8 | 判断连接状态所向前追溯的历史心跳个数 + + +例如: + +```js +var MyMCU = new wiot.client({ + MAC: "xx:xx:xx:xx:xx:xx", + pin: { + D1: 0, + D2: 0, + D3: 1, + D4: 1, + D5: 0, + D6: 1, + D7: 0, + D8: 0 + }, + hint: true, + debug: false, + ip: "192.168.0.55", + ip_range: "192.168.0", + localIP: "127.0.0.1", + errDelayTime: 2000, + okDelayTime: 30, + resetDelayTime: 4500, + noTryMaxTime: 15000, + IntervalTime: 2000, + MaxToReScanTime: 180000, + MinResearchTime: 5000, + IpScanTimeOut: 1, + pingTimeout: 2, + MaxTraceBackTimes: 8 +}); + +``` + +### API ++ `wiot.loop()`: 循环执行的指令,适合于条件控制语句 +```js +MCU0 = new wiot.client({MAC: "xx:xx:xx:xx:xx:xx", pin: {D4: wiot.OUTPUT}}); +MCU1 = new wiot.client({MAC: "xx:xx:xx:xx:xx:ww"}); + +// 以下代码将实现: 当MCU0的D5接收到HIGH,MCU1的D4将会输出HIGH +// 当MCU0的D5接收到LOW, MCU1的D4将会输出LOW +// 本函数接受两个参数: 第一个是MCU对象数组, 第二个是参数为MCU对象数组的函数 +wiot.loop([MCU0, MCU1], (mcu) => { + if(mcu[1].read(wiot.D5) == wiot.HIGH){ + mcu[0].write(wiot.D4, wiot.HIGH); + }else{ + mcu[0].write(wiot.D4, wiot.LOW); + } +}); + +``` + +### wiot.client事件绑定 +`.on(event, handler)` + +```js +var MCU = new wiot.client({"MAC": "xx:xx:xx:xx:xx:xx"}); + +MCU.on('disConnected', function () { + console.log('Disconnected with MCU!!'); +}); +``` + +**事件列表** +- `begin` 开始于单片机正常交互 +- `disConnected` 与单片机断开连接 +- `reConnected` 与单片机恢复连接 + diff --git a/node/app.js b/node/app.js index c808a8d..257d9a9 100644 --- a/node/app.js +++ b/node/app.js @@ -1,15 +1,11 @@ var wiot = require('./wiot'); -w = new wiot.client({MAC: "3C:71:BF:3A:F6:CF", pin: {D3: 1}}); +w = new wiot.client({MAC: "3C:71:BF:3A:F6:CF", pin: {D4: 1},debug: 0}); //q = new wiot.client({MAC: "3C:71:BF:3A:F6:83", pin: {D3: 1} }); -var i = 0; -w.on = () => { -/*setInterval(() => { - //console.log(q.read(4)); - if(q.read(4) == q.HIGH){ - w.write(3, w.HIGH); - }else{ - w.write(3, w.LOW); - } -}, 50); -*/}; +wiot.loop([w], (w) => { + w[0].write(3, wiot.HIGH); +}); + +w.on('disConnected', ()=>{ + console.log('hhhhhhhhhhhhh'); +}) \ No newline at end of file diff --git a/node/package.json b/node/package.json index a6dd78f..3b20b7f 100644 --- a/node/package.json +++ b/node/package.json @@ -1,6 +1,6 @@ { "name": "wiot", - "version": "0.0.9", + "version": "0.0.10", "description": "An awesome iot system for web developers~", "main": "wiot.js", "scripts": { diff --git a/node/wiot.js b/node/wiot.js index 8228b3b..5b517ce 100644 --- a/node/wiot.js +++ b/node/wiot.js @@ -2,9 +2,9 @@ * @Author: IoTcat (https://iotcat.me) * @Date: 2019-05-04 18:59:49 * @Last Modified by: IoTcat - * @Last Modified time: 2019-05-05 19:38:03 + * @Last Modified time: 2019-05-05 23:44:31 */ -var wiot = function (o_params) { +var wiot_client = function (o_params) { var o = { MAC: "", pin: { @@ -19,7 +19,6 @@ var wiot = function (o_params) { }, hint: true, debug: false, - on: () => {}, OUTPUT: 1, INPUT: 0, INPUT_PULLUP: 2, @@ -39,6 +38,7 @@ var wiot = function (o_params) { MinResearchTime: 5000, IpScanTimeOut: 1, pingTimeout: 2, + MaxTraceBackTimes: 8, LastConnectTime: Date.parse(new Date()), isConnected: false, LastTryTime: Date.parse(new Date()), @@ -52,7 +52,21 @@ var wiot = function (o_params) { D6: 0, D7: 0, D8: 0 - } + }, + on: (event, handler) => { + if(event == 'begin'){ + o.begin = handler; + } + if(event == 'disConnected'){ + o.disConnected = handler; + } + if(event == 'reConnected'){ + o.reConnected = handler; + } + }, + begin: () => {}, + disConnected: ()=>{}, + reConnected: ()=>{} }; /* merge paras */ @@ -72,6 +86,8 @@ var wiot = function (o_params) { /* tmp global var */ var ip_point = 0; + var status = []; + status.fill(false, 0, o.MaxTraceBackTimes); /* tools */ var IsJsonString = (str) => { @@ -271,7 +287,28 @@ var wiot = function (o_params) { }); } - + var setStatus = (s) => { + for (var i = 1; i < o.MaxTraceBackTimes; i++) { + status[i] = status[i - 1]; + } + status[0] = s; + }; + var checkStatus = () => { + var sameNum = 0; + for (var i = 1; i < o.MaxTraceBackTimes - 1; i++) { + if (status[i] == status[0]) sameNum++; + } + if (!sameNum && o.firstReady) { + if (status[0] == true) { + if (o.hint) console.log('wIoT - ' + o.MAC + ': Re Connected!!'); + o.reConnected(); + return; + } + if (o.hint) console.log('wIoT - ' + o.MAC + ': Lost Connection!!'); + o.disConnected(); + return; + } + }; /* http functions */ var http_error_callback = (callback = () => {}) => { callback(); @@ -322,7 +359,7 @@ var wiot = function (o_params) { }); }).on('error', function (e) { err(e); - if (o.hint) console.log('wIoT - ' + o.MAC + ": err_" + o.ip + " - Lost Connection!!"); + if (o.debug) console.log('wIoT - ' + o.MAC + ": err_" + o.ip + " - Cannot Connect to MCU!!"); }).end(); } else { @@ -467,7 +504,10 @@ var wiot = function (o_params) { }; async function lstn() { + if (o.firstReady) return; //avoid multi monitors setInterval(async () => { + setStatus(o.isConnected); + checkStatus(); if (o.LastConnectTime + o.errDelayTime > Date.parse(new Date())) { o.isConnected = true; http_connected_callback(); @@ -518,7 +558,7 @@ var wiot = function (o_params) { http_update(); if (!o.firstReady && o.ready()) { - o.on(); + o.begin(); o.firstReady = 1; if (o.hint) console.log('wIoT - ' + o.MAC + ': Connected!!'); } @@ -530,6 +570,40 @@ var wiot = function (o_params) { return o; + }; + + +/* Loop */ +var wiot_loop_core = (obj) => { + if(obj.client.every((items)=>{ + return (items.firstReady); + })){ + setInterval(obj.method, 20, obj.client); + return; + } + setTimeout(wiot_loop_core, 200, obj); }; -exports.client = wiot; +var wiot_loop = (w = {}, f = ()=>{}) => { + + setTimeout(wiot_loop_core, 1000, {"client": w, "method": f}); +}; + + +/* exports */ +exports.HIGH = 1; +exports.LOW = 0; +exports.INPUT = 0; +exports.OUTPUT = 1; +exports.INPUT_PULLUP = 2; +exports.D1 = 1; +exports.D2 = 2; +exports.D3 = 3; +exports.D4 = 4; +exports.D5 = 5; +exports.D6 = 6; +exports.D7 = 7; +exports.D8 = 8; +exports.A0 = "A0"; +exports.client = wiot_client; +exports.loop = wiot_loop; \ No newline at end of file