From aa9dd0e56faf84b621ab7719c14b5d0bb0d938ef Mon Sep 17 00:00:00 2001 From: liuwu <975499773@qq.com> Date: Thu, 1 Feb 2024 10:44:54 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E6=8C=89=E9=92=AE=E7=82=B9?= =?UTF-8?q?=E5=87=BB=E6=A0=B7=E5=BC=8F=EF=BC=8C=E5=A2=9E=E5=8A=A0=E9=93=B2?= =?UTF-8?q?=E8=BD=A6=E9=A1=B5=E9=9D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- html/collection.html | 11 +- html/config.html | 106 +++++- html/index.html | 28 +- html/index1.html | 836 +++++++++++++------------------------------ pages/circle.stml | 547 ++++++++++++++++++++++++++++ script/ble.js | 695 +++++++++++++++++++++-------------- script/electric.js | 3 +- script/index.js | 777 ++++++++++++++++++++++------------------ script/module/ble.js | 149 ++++++++ 9 files changed, 1928 insertions(+), 1224 deletions(-) create mode 100644 pages/circle.stml create mode 100644 script/module/ble.js diff --git a/html/collection.html b/html/collection.html index 6eacff4..0e52371 100644 --- a/html/collection.html +++ b/html/collection.html @@ -100,6 +100,14 @@ height: 10vh; margin:0 auto; } + .btnc:active { + animation: clickAnimation 0.2s ease forwards; + } + + @keyframes clickAnimation { + 0% { transform: scale(1); } /* 起始状态为原大小 */ + 100% { transform: scale(0.95); } /* 结束状态为稍微收缩的大小 */ + }
@@ -202,7 +210,7 @@ function getTmrCowshed(){ api.ajax({ url: 'https://tmr.nxcyx.com/api/app/tmr/getTmrCowshed?sourceCow=' + api.getPrefs({ sync: true, key: 'sourceCow' }), - // url: 'http://192.168.0.107:8088/app/tmr/getTmrCowshed?sourceCow=' + api.getPrefs({ sync: true, key: 'sourceCow' }), + // url: 'http://192.168.0.107:8081/api/getTmrCowshed?sourceCow=' + api.getPrefs({ sync: true, key: 'sourceCow' }), method: 'get', timeout: 5 }, function (ret, err) { @@ -286,6 +294,7 @@ console.log(JSON.stringify(remainData)) api.ajax({ url: 'https://tmr.nxcyx.com/api/app/tmr/resultRemainUpload', + // url: 'http://192.168.0.107:8081/api/resultRemainUpload', headers: { 'Content-Type': 'application/json;charset=utf-8' //建议key使用首字母大写的形式,如 User-Agent }, diff --git a/html/config.html b/html/config.html index 40cd3b9..74d016e 100644 --- a/html/config.html +++ b/html/config.html @@ -79,6 +79,14 @@ justify-content: flex-end; text-align: justify; } + .btnc:active { + animation: clickAnimation 0.2s ease forwards; + } + + @keyframes clickAnimation { + 0% { transform: scale(1); } /* 起始状态为原大小 */ + 100% { transform: scale(0.95); } /* 结束状态为稍微收缩的大小 */ + }
@@ -136,7 +144,7 @@
- 跳转数据: + 跳转时长:
@@ -152,6 +160,16 @@
+ +
+
+ 稳定阈值: + +
+
+ +
+
@@ -168,12 +186,14 @@ var jumpListener = null; var weiListener = null; var btlListener = null; + var thresholdListener = null; var userPicker; var pagePicker; var fixPicker; var jumpPicker; var weiPicker; var btlPicker; + var thresholdPicker; var pickData = []; var btnArray = ['取消', '确认']; var pageData = [] @@ -181,6 +201,7 @@ var jumpData = [] var weiData = [] var btlData = [] + var thresholdData = [] fixData.push({value: 0, text: "需要"}) fixData.push({value: 1, text: "不需要"}) @@ -191,14 +212,29 @@ pageData.push({value: "index1", text: "装料页面"}) pageData.push({value: "collection", text: "剩料收集页面"}) pageData.push({value: "config", text: "设置页面"}) + pageData.push({value: "chanche", text: "铲车页面"}) + + thresholdData.push({value: "5", text: "5"}) + thresholdData.push({value: "10", text: "10"}) + thresholdData.push({value: "20", text: "20"}) + thresholdData.push({value: "30", text: "30"}) + thresholdData.push({value: "40", text: "40"}) + thresholdData.push({value: "50", text: "50"}) + thresholdData.push({value: "60", text: "60"}) + thresholdData.push({value: "70", text: "70"}) + thresholdData.push({value: "80", text: "80"}) + + weiData.push({value: "1", text: "1"}) + weiData.push({value: "2", text: "2"}) + weiData.push({value: "3", text: "3"}) + weiData.push({value: "4", text: "4"}) + weiData.push({value: "5", text: "5"}) + weiData.push({value: "6", text: "6"}) + weiData.push({value: "7", text: "7"}) + weiData.push({value: "8", text: "8"}) + weiData.push({value: "9", text: "9"}) + weiData.push({value: "10", text: "10"}) - weiData.push({value: "20", text: "20"}) - weiData.push({value: "30", text: "30"}) - weiData.push({value: "40", text: "40"}) - weiData.push({value: "50", text: "50"}) - weiData.push({value: "60", text: "60"}) - weiData.push({value: "70", text: "70"}) - weiData.push({value: "80", text: "80"}) btlData.push({value: "1", text: "1"}) btlData.push({value: "2", text: "2"}) @@ -262,6 +298,7 @@ pickData = []; api.ajax({ url: 'https://tmr.nxcyx.com/api/app/tmr/sbList?sourceCow=' + api.getPrefs({sync: true, key: 'sourceCow'}), + // url: 'http://192.168.0.107:8081/api/sbList?sourceCow=' + api.getPrefs({sync: true, key: 'sourceCow'}), method: 'get', timeout: 5 }, function (ret, err) { @@ -293,6 +330,7 @@ muiInitJump() muiInitWeightSize() muiInitBtl() + muiInitThe() var indexPage = api.getPrefs({ sync: true, key: 'initpage' @@ -336,7 +374,7 @@ }); if (weightSize) { weiData.forEach(p => { - if (weightSize == p.value) { + if (weightSize === p.value) { console.log(requireFix === p.value) document.getElementById('weightSize').innerHTML = p.text } @@ -355,6 +393,18 @@ }) } + var threshold = api.getPrefs({ + sync: true, + key: 'threshold' + }); + if (threshold) { + thresholdData.forEach(p => { + if (threshold === p.value) { + document.getElementById('threshold').innerHTML = p.text + } + }) + } + setTimeout(function () { api.hideProgress(); }, 1000); @@ -551,6 +601,32 @@ })(mui, document); } + function muiInitThe() { + (function ($, doc) { + $.init(); + $.ready(function () { + var _getParam = function _getParam(obj, param) { + return obj[param] || ''; + }; + if (thresholdPicker) { + } else { + thresholdPicker = new $.PopPicker(); + var showThePickerButton = doc.getElementById('threshold'); + thresholdListener = null; + thresholdListener = showThePickerButton.addEventListener('tap', function (event) { + thresholdPicker.show(function (items) { + showThePickerButton.innerHTML = items[0].text; + if (items[0].text){ + thresholdSave() + } + }); + }, false); + } + thresholdPicker.setData(thresholdData); + }); + })(mui, document); + } + function initsb() { // var value = document.getElementById('initsb').value; var value = document.getElementById('initsb').innerHTML @@ -582,7 +658,7 @@ key: 'weightSize', value: value }); - mui.alert('自动跳转数据包"' + value + '"设置成功'); + mui.alert('自动跳转时长"' + value + '"秒设置成功'); } } function btlSave(){ @@ -595,6 +671,16 @@ mui.alert('称LED接收发送比"' + value + '"设置成功'); } } + function thresholdSave(){ + var value = document.getElementById('threshold').innerHTML; + if (value) { + api.setPrefs({ + key: 'threshold', + value: value + }); + mui.alert('稳定阈值"' + value + '"kg设置成功'); + } + } function fixbeforeload(){ var value = document.getElementById('isfix').value; if (value) { diff --git a/html/index.html b/html/index.html index f5833a9..bb8e22a 100644 --- a/html/index.html +++ b/html/index.html @@ -49,6 +49,14 @@ text-align: justify; height: 10vh; } + .mui-btn-success:active { + animation: clickAnimation 0.2s ease forwards; + } + + @keyframes clickAnimation { + 0% { transform: scale(1); } /* 起始状态为原大小 */ + 100% { transform: scale(0.90); } /* 结束状态为稍微收缩的大小 */ + }
@@ -58,8 +66,11 @@
-
- +
+ +
+
+
@@ -72,7 +83,7 @@ api.closeWidget({ id: api.appId, //应用ID retData: { name: 'closeWidget' }, - silent: false + silent: true }); } }); @@ -100,6 +111,10 @@ setTimeout(function(){ config() },1000) + case "chanche": + setTimeout(function(){ + chanche() + },1000) break; } } @@ -138,6 +153,13 @@ url:'../html/config.html' }) } + function chanche(){ + api.openWin({ + name: 'chanche', + reload:true, + url:'../pages/circle.stml' + }) + } diff --git a/html/index1.html b/html/index1.html index cbb73b5..19c52b8 100644 --- a/html/index1.html +++ b/html/index1.html @@ -105,6 +105,15 @@ width: 100%; padding: 20px 10px 20px 10px; } + + .btnc:active { + animation: clickAnimation 0.2s ease forwards; + } + + @keyframes clickAnimation { + 0% { transform: scale(1); } /* 起始状态为原大小 */ + 100% { transform: scale(0.95); } /* 结束状态为稍微收缩的大小 */ + }
@@ -115,7 +124,6 @@ -
@@ -171,60 +179,87 @@ diff --git a/pages/circle.stml b/pages/circle.stml new file mode 100644 index 0000000..96666aa --- /dev/null +++ b/pages/circle.stml @@ -0,0 +1,547 @@ + + + \ No newline at end of file diff --git a/script/ble.js b/script/ble.js index f6fb1b8..a3be81f 100644 --- a/script/ble.js +++ b/script/ble.js @@ -1,5 +1,39 @@ "use strict"; /*初始化蓝牙适配器*/ + +//扫描时长,定时任务 +let times = 5; +let scanInter; + +// 连接失败次数 +let connectTimes = 0; +// 蓝牙uuid +let peripheralUUID ='' +// 蓝牙服务id +let serviceUUID ='' +// 蓝牙特征id +let characteristicUUID ='' +// 蓝牙待发送消息列表 +let msgList = []; +// 蓝牙消息发送定时任务150ms +let timerMsgList = null; +// 未装料状态计数,采集达到10次,发送一次停止蜂鸣指令 +let bleConunt=0; +// 默认不自动跳转 +let allowAuto = false; +// 清除消息定时任务 +clearInterval(timerMsgList) +//蜂鸣器最后控制时间 +let lastTime = new Date().getSeconds()*1000+ new Date().getMilliseconds(); +// 接收重量数据计数 +let countLED = 0; +//判断是否稳定记录的上次重量信息 +let weight = 0; + +/** + * 初始化蓝牙 + * @param param + */ function initManager(param) { ble.initManager(param, function (ret) { if (ret.state === "poweredOn") { @@ -12,25 +46,25 @@ function initManager(param) { }); } -var times = 5; -var sta = true; -var scanInter; -/*开始扫描*/ +/** + * 扫描蓝牙 + * @param param + */ function scan(param) { if (!uuid){ - uuid = api.getPrefs({ - sync: true, - key: 'uuid' - }); + //从缓存获取uuid + uuid = api.getPrefs({ sync: true, key: 'uuid' }); } + // 存在缓存uuid if (uuid){ + // 已连接先断开 isConnected({peripheralUUID: uuid},function(ret){ - console.log("isConnected"+ret); if(ret){ disconnect({peripheralUUID: uuid}); } }) } + //定时扫描 clearInterval(scanInter) times = 5; ble.scan(param, function (ret) { @@ -38,7 +72,7 @@ function scan(param) { scanInter = setInterval(function (){ if (times>0){ times --; - var wifiDom = document.getElementById('wifiDom'); + let wifiDom = document.getElementById('wifiDom'); wifiDom.innerHTML = "扫描中"+times; api.showProgress({ title: '扫描中'+times+'...', @@ -54,48 +88,44 @@ function scan(param) { }); } -var weightBeforefix = '1'; -var autoJump = '1'; - +/** + * 停止扫描 + */ function stopScan(){ ble.stopScan() } -/*获取扫描结果*/ +/** + * 获取扫描结果 + */ function getPeripheral() { ble.getPeripheral(function (ret) { bleData = [] - var ret2 = {}; - var wifiDom = document.getElementById('wifiDom'); + let wifiDom = document.getElementById('wifiDom'); if (ret.peripherals.length > 0) { ret.peripherals.forEach(function (p) { if (undefined !== p.name) { - console.log(p.name); if (p.name.indexOf("TMR_BLE") === -1){ return false }else{ + console.log(p.name); mui.toast("已扫描到" +p.name,{duration:3500,type:'div'}); wifiDom.innerHTML = p.name+'(未连接)'; document.getElementById('showBlePicker').setAttribute("class", 'btnc mui-btn-inline mui-btn-primary'); - var json = { value: p.uuid, text: p.name }; + let json = { value: p.uuid, text: p.name }; bleData.push(json); - if (!uuid){ - uuid = api.getPrefs({ - sync: true, - key: 'uuid' - }); - } + //自动连接上次蓝牙 if (uuid && uuid === p.uuid){ document.getElementById('showBlePicker').innerHTML = p.name - isConnected({peripheralUUID: uuid},function(ret){ - console.log("isConnected"+ret); - if(ret){ - disconnect({peripheralUUID: uuid}); - connect({peripheralUUID: uuid}); - }else{ - connect({peripheralUUID: uuid}); - } - }) + connect({peripheralUUID: uuid}); + // isConnected({peripheralUUID: uuid},function(ret){ + // if(ret){ + // disconnect({peripheralUUID: uuid}); + // connect({peripheralUUID: uuid}); + // }else{ + // connect({peripheralUUID: uuid}); + // } + // }) } } } @@ -111,11 +141,13 @@ function getPeripheral() { api.hideProgress(); }); } -// 连接失败次数 -var connectTimes=0; -/*开始连接*/ + +/** + * 连接蓝牙 + * @param param + */ function connect(param) { - var wifiDom = document.getElementById('wifiDom'); + let wifiDom = document.getElementById('wifiDom'); wifiDom.innerHTML = ""; api.showProgress({ title: '蓝牙连接中...', @@ -127,25 +159,25 @@ function connect(param) { api.hideProgress(); connetcedStatus = true // 缓存蓝牙设备uuid方便自动连接 - api.setPrefs({ - key: 'uuid', - value: param.peripheralUUID - }); + api.setPrefs({ key: 'uuid', value: param.peripheralUUID }); + //累计连接次数 if (connectTimes>0){ addNotice(1,'#02a7f0',sbId + '主机端第'+connectTimes+'次重连成功'); }else { addNotice(1,'#02a7f0',sbId + '主机端初始化连接成功'); } + //连接成功清空连接次数 connectTimes = 0; document.getElementById('text').innerHTML = '设备已连接'; - text = '设备已连接'; - console.log('主机端连接成功') + // console.log('主机端连接成功') + //设置MTU包大小 ble.setMtu({ peripheralUUID: param.peripheralUUID, - mtu:120 + mtu:150 },function(ret){ if(ret.status){ + // 加载图表 initWeight(); discoverService({peripheralUUID: param.peripheralUUID}); }else{ @@ -153,9 +185,11 @@ function connect(param) { } }); }else { + console.log('主机端连接失败'+JSON.stringify(err)) wifiDom.innerHTML = '连接失败'; api.hideProgress(); connetcedStatus = false + //累计连接次数 if (connectTimes > 0){ if(connectTimes%10 === 0){ addNotice(4,'red',sbId + '主机端第'+connectTimes+'次重连失败'); @@ -163,6 +197,7 @@ function connect(param) { }else { addNotice(4,'red',sbId + '主机端连接失败,开始尝试重连'); } + //连接失败一次加一次 connectTimes ++; setTimeout(function (){ if (!connetcedStatus && uuid && feedStatus){ @@ -180,7 +215,7 @@ function disconnect(param) { if (ret.status) { console.log("断开连接成功!"); } else { - console.log("断开连接失败!"); + console.log("断开连接失败!"+JSON.stringify(err)); } }); } @@ -188,50 +223,120 @@ function disconnect(param) { function isConnected(param,callback){ ble.isConnected(param, function(ret) { if (ret.status) { - console.log('已连接'); + // console.log('已连接'); } callback(ret.status) }); } -var i; -// 蓝牙uuid -var peripheralUUID ='' -// 蓝牙服务id -var serviceUUID ='' -// 蓝牙特征id -var characteristicUUID ='' -// 蓝牙待发送消息列表 -var msgList = []; -var timerMsgList = null; -// 清除消息定时任务 -clearInterval(timerMsgList) -/*蓝牙消息发送定时任务150ms*/ -timerMsgList = setInterval(function(){ - // console.log(new Date().getSeconds()+ ' ' + new Date().getMilliseconds() +' ' + msgList.length) - if (msgList.length > 0) { - // 发送报文 - var msg = msgList[0]; - msgList.splice(0, 1); - var param1 = { - peripheralUUID: peripheralUUID, - serviceUUID: serviceUUID, - characteristicUUID: characteristicUUID, - value: msg, - writeType:'withoutResponse' - }; - if(connetcedStatus && peripheralUUID && serviceUUID && characteristicUUID){ - writeValueForCharacteristic(param1, function (ret) { - // console.log(ret.status) - }); - } - } -},150) +setTimeout(() => { + timerMsgList = setInterval(function () { + select(db, 'SELECT * FROM t_ble_msg order by id', function (ret, err) { + if (!ret.status) { + console.log(JSON.stringify(err)) + } + var data = ret.data + // console.log(data.length) + if (data.length > 0) { + // console.log(Number(data[0].id)) + // 发送报文 + let msg = data[0].text; + var sql = "delete from t_ble_msg where id = '" + Number(data[0].id) + "'"; + execute(db, sql, function (ret, err) { + if (!ret.status) { + console.log(JSON.stringify(err)) + } + }) + let param1 = { + peripheralUUID: peripheralUUID, + serviceUUID: serviceUUID, + characteristicUUID: characteristicUUID, + value: msg, + writeType:'withoutResponse' + }; + if(connetcedStatus && peripheralUUID && serviceUUID && characteristicUUID){ + writeValueForCharacteristic(param1, function (ret) { + // led屏幕 + var booleanLed = msg.startsWith('FF05') && msg.substr(8,4) === 'AAA5'; + // 设备消息数据同步 + var booleanSendWeight = msg.startsWith('FF0A0004'); + if (ret.status && msg.length > 12 && (booleanLed || booleanSendWeight)) { + // 同步刷新图表 + // 饲喂状态刷新实时状态,否则不刷新装料信息 + if(feedStatus && (allowAuto || weightBeforefix ==='1')){ + renderUnload(); + feedMyChart.setOption({ + dataset: { + source: [[1, _feedNum]] + } + }); + } + renderLoad(); + weightMyChart.setOption({ + dataset: { + source: [[1, nowWeight]] + } + }); + } + // console.log(ret.status) + }); + } + } + }) + }, 100); +}, 3000); + + +// /*蓝牙消息发送定时任务150ms*/ +// timerMsgList = setInterval(function(){ +// // console.log(new Date().getSeconds()+ ' ' + new Date().getMilliseconds() +' ' + msgList.length) +// if (msgList.length > 0) { +// // 发送报文 +// let msg = msgList[0]; +// msgList.splice(0, 1); +// let param1 = { +// peripheralUUID: peripheralUUID, +// serviceUUID: serviceUUID, +// characteristicUUID: characteristicUUID, +// value: msg, +// writeType:'withoutResponse' +// }; +// if(connetcedStatus && peripheralUUID && serviceUUID && characteristicUUID){ +// writeValueForCharacteristic(param1, function (ret) { +// // console.log(ret.status) +// }); +// } +// } +// },100) + +// let mss = ''; +// setInterval(function(){ +// // console.log(currTimeFnMs(new Date)) +// let param1 = { +// peripheralUUID: peripheralUUID, +// serviceUUID: serviceUUID, +// characteristicUUID: characteristicUUID, +// value: mss, +// writeType:'withoutResponse' +// }; +// if(connetcedStatus && peripheralUUID && serviceUUID && characteristicUUID && mss.length>0){ +// writeValueForCharacteristic(param1, function (ret) { +// // console.log(ret.status) +// }); +// } +// },100) + +function currTimeFnMs(_date) { + var _year = _date.getFullYear(); + var _month = _date.getMonth() + 1 < 10 ? '0' + (_date.getMonth() + 1) : _date.getMonth() + 1; + var _day = _date.getDate() < 10 ? '0' + _date.getDate() : _date.getDate(); + var _hour = _date.getHours() < 10 ? '0' + _date.getHours() : _date.getHours(); + var _minutes = _date.getMinutes() < 10 ? '0' + _date.getMinutes() : _date.getMinutes(); + var _seconds = _date.getSeconds() < 10 ? '0' + _date.getSeconds() : _date.getSeconds(); + var _ms = _date.getMilliseconds() < 10 ? '0' + _date.getMilliseconds() : _date.getMilliseconds(); + return _year + "-" + _month + "-" + _day + " " + _hour + ":" + _minutes + ":" + _seconds + " "+_ms; +} -// 未装料状态计数,采集达到10次,发送一次停止蜂鸣指令 -var bleConunt=0; -// 默认不自动跳转 -var allowAuto = false; /*扫描蓝牙服务*/ function discoverService(param) { ble.discoverService(param, function (ret) { @@ -248,7 +353,7 @@ function discoverService(param) { if(ret5.indexOf("0000ffe2")!==-1){ return false } - console.log(ret5) + // console.log(ret5) peripheralUUID = param.peripheralUUID; serviceUUID =ret4; characteristicUUID =ret5; @@ -258,11 +363,20 @@ function discoverService(param) { serviceUUID: ret4, characteristicUUID: ret5 }, function (ret6) { - if (ret6 !== undefined) { + if (ret6 !== undefined&& ret6 !='') { if (isNaN(ret6)) { return false } + //实时总重量 nowWeight = ret6; + // 实时重量保存 + totalList.push({ + time: currTimeFnMs(new Date()), + nowWeight: nowWeight + }); + //计算实时重量均值 + const filteredValue = weightDataFilter.filter(nowWeight); + //组装并发送实时重量LED屏报文 getMess({ peripheralUUID: param.peripheralUUID, serviceUUID: ret4, @@ -270,145 +384,61 @@ function discoverService(param) { value: ret6 }, function (ret7) { }); - // 装料状态 - if((feedStatus && allowAuto) || weightBeforefix ==='1' ){ + // 1装料状态 + // 2已校准或不需要校准 + if(feedStatus && (allowAuto || weightBeforefix ==='1')){ + //第一次加载 if (first) { first = false; beforeWeight = nowWeight; } if (load) { _feedNum = nowWeight - beforeWeight; + // _feedNum = (filteredValue - beforeWeight).toFixed(0); + document.getElementById('feedNum').innerHTML = ':' + _planSum + '/已装:' + _feedNum + ''; } else { _feedNum = beforeWeight - nowWeight; + // _feedNum = (beforeWeight - filteredValue).toFixed(0); + document.getElementById('feedNum').innerHTML = ':' + _planSum + '/已卸:' + _feedNum + ''; } + // 显示饲料名称+计划饲喂量 text = feedName + _planSum; - if (!isNaN(nowWeight)) { - // 实时重量保存 - totalList.push({ - time: currTimeFn(new Date()), - nowWeight: nowWeight - }); - } - document.getElementById('feedNum').innerHTML = ':' + _planSum + '/已装:' + _feedNum + ''; - } - // 装料状态 - if((feedStatus && allowAuto) || weightBeforefix === '1'){ // 计划-饲喂 var feedErr = _planSum-_feedNum; if (isNaN(feedErr)) { return false } - // 蜂鸣器校验基础值,大于500的饲料,取500为标准 - var count; - if (_planSum >= 500) { - count = 500 - } else { - count = _planSum - } - // 计算饲料装料量与基础值的误差比例 - var ration = feedErr / count; - // console.log("ration" + ration.toFixed(2)); - // 误差分为100%-20%(停止蜂鸣),10%-20%(间隔05),5%-10%(间隔03),2%-5%(间隔01),-100%-2%(长鸣) - if (ration > 0.2) { - bleConunt ++; - if (statusEle || (bleConunt >= 10)) { - bleConunt=0; - ledStatus = false; - status = ''; - statusEle = false; - msgList = []; - control("00", "00"); - setTimeout(function () { - ledStatus = true; - }, 500); - } - } else if (0.1 < ration && ration <= 0.2) { - time = "05"; - if (!statusEle || lastTime !== time) { - lastTime = time; - ledStatus = false; - status = '间隔'; - statusEle = true; - msgList = []; - console.log("开始蜂鸣" + time); - control("60", time); - setTimeout(function () { - ledStatus = true; - }, 500); - } - } else if (0.05 < ration && ration <= 0.1) { - time = "03"; - if (!statusEle || lastTime !== time) { - lastTime = time; - ledStatus = false; - status = '间隔'; - statusEle = true; - msgList = []; - console.log("开始蜂鸣" + time); - control("60", time); - setTimeout(function () { - ledStatus = true; - }, 500); - } - } else if (0.02 < ration && ration <= 0.05) { - time = "01"; - if (!statusEle || lastTime !== time) { - lastTime = time; - ledStatus = false; - status = '间隔'; - statusEle = true; - msgList = []; - console.log("开始蜂鸣" + time); - control("60", time); - setTimeout(function () { - ledStatus = true; - }, 500); - } - } else { - if (status === '间隔' || status === '') { - ledStatus = false; - status = '长鸣'; - statusEle = true; - msgList = []; - console.log("开始长鸣"); - control("40", "02"); - setTimeout(function () { - ledStatus = true; - }, 500); + // console.log(beforeWeight,nowWeight) + // console.log("feedErr:"+feedErr,"allow:"+allow,"_feedNum:"+_feedNum,"_planSum:"+_planSum) + //蜂鸣器判断 + buzzer(feedErr) + // 判断重量是否稳定 + const ifSta = isStable(weightDataFilter.dataBuffer, threshold); + // 判断 + // 1:已开启自动跳转autoJump + // 2:已校准allowAuto或者不需要校准weightBeforefix + // 3:已满足误差或者已装够 - setTimeout(function() { - console.log("开始长鸣") - control("40", "02"); - setTimeout(function() { - ledStatus = true; - }, 500) - }, 500) - } - } - if (autoJump==='0'){ - console.log("自动跳转") - } - // console.log(weightStabilization("weightStabilization"+nowWeight)) - // 在误差范围内 - if (autoJump==='0' && feedErr <= allow && (allowAuto || weightBeforefix === '1')) { - // 重量稳定计数 - var filteredValue = weightDataFilter.filter(nowWeight); - // 重量稳定自动跳转 - if (weightDataFilter.dataBuffer.length === weightSize) { - console.log("重量稳定", currTimeFn(new Date())); + if (autoJump==='0' && (feedErr <= allow || _feedNum > _planSum) && (allowAuto || weightBeforefix === '1')) { + // 已稳定 + if(ifSta){ + //稳定数据包 + wendinSize.push({time:new Date().getTime(),val:nowWeight}) + // 稳定时长 + const staTimes = (wendinSize[wendinSize.length - 1].time - wendinSize[0].time) / 1000; + console.log('数据稳定时长'+staTimes) + document.getElementById('isfix').innerHTML = '稳定'+staTimes.toFixed(0)+'' + if(staTimes > weightSize){ + console.log("重量稳定", currTimeFn(new Date())); + weightDataFilter.dataBuffer = [] + wendinSize = [] + remark = '自动跳转' + document.getElementById('submitData').click(); + } + }else{ + // 不稳定清空所有数据 weightDataFilter.dataBuffer = [] - remark = '自动跳转' - document.getElementById('submitData').click(); - } - }else if(autoJump==='0' && _feedNum > _planSum && (allowAuto || weightBeforefix === '1')){ - // 重量稳定计数 - var filteredValue = weightDataFilter.filter(nowWeight); - // 重量稳定自动跳转 - if (weightDataFilter.dataBuffer.length === weightSize) { - console.log("重量稳定", currTimeFn(new Date())); - weightDataFilter.dataBuffer = [] - remark = '自动跳转' - document.getElementById('submitData').click(); + wendinSize = [] } } } @@ -424,10 +454,123 @@ function discoverService(param) { } }); } + +function buzzer(feedErr){ + // 蜂鸣器校验基础值,大于500的饲料,取500为标准 + let count; + if (_planSum >= 500) { + count = 500 + } else { + count = _planSum + } + // 计算饲料装料量与基础值的误差比例 + let ration = feedErr / count; + // 误差分为100%-20%(停止蜂鸣),10%-20%(间隔05),5%-10%(间隔03),2%-5%(间隔01),-100%-2%(长鸣) + if (ration > 0.2) { + bleConunt ++; + if (statusEle || (bleConunt >= 10)) { + bleConunt=0; + status = ''; + statusEle = false; + msgList = []; + control("00", "00"); + setTimeout(function () { + + }, 500); + } + } else if (0.1 < ration && ration <= 0.2) { + time = "05"; + if (!statusEle || lastTime !== time) { + lastTime = time; + status = '间隔'; + statusEle = true; + msgList = []; + console.log("开始蜂鸣" + time); + control("60", time); + setTimeout(function () { + + }, 500); + } + } else if (0.05 < ration && ration <= 0.1) { + time = "03"; + if (!statusEle || lastTime !== time) { + lastTime = time; + status = '间隔'; + statusEle = true; + msgList = []; + console.log("开始蜂鸣" + time); + control("60", time); + setTimeout(function () { + + }, 500); + } + } else if (0.02 < ration && ration <= 0.05) { + time = "01"; + if (!statusEle || lastTime !== time) { + lastTime = time; + status = '间隔'; + statusEle = true; + msgList = []; + console.log("开始蜂鸣" + time); + control("60", time); + setTimeout(function () { + + }, 500); + } + } else { + if (status === '间隔' || status === '') { + status = '长鸣'; + statusEle = true; + msgList = []; + console.log("开始长鸣"); + control("40", "02"); + setTimeout(function () { + + }, 500); + + setTimeout(function() { + console.log("开始长鸣") + control("40", "02"); + setTimeout(function() { + + }, 500) + }, 500) + } + } +} + +/** + * 判断一组数据是否稳定在threshold误差范围内 + * @param data + * @param threshold + * @returns {boolean} + */ +function isStable(data, threshold) { + // 确保输入的数据是一个数组 + if (!Array.isArray(data)) { + throw new Error('Data must be an array'); + } + + // 确保输入的阈值是数字 + if (typeof threshold !== 'number') { + throw new Error('Threshold must be a number'); + } + + // 找到数组中的最大值和最小值 + const min = Math.min(...data); + const max = Math.max(...data); + + // 计算差值的绝对值 + const difference = Math.abs(max - min); + + // 比较差值和阈值 + return difference <= threshold; +} + /*扫描特征*/ function discoverCharacteristics(param, callback) { ble.discoverCharacteristics(param, function (ret) { - var res = ''; + let res = ''; if (ret.characteristics.length > 0) { // console.log("发现特征成功!"); ret.characteristics.forEach(function (s) { @@ -461,37 +604,89 @@ function StringToNum(hexx){ } }return str; } +var weiNum = 0; /*监听蓝牙数据,转换重量数据*/ function setNotify(param, callback) { ble.setNotify(param, function (ret) { + var res; var value = ret.characteristic.value; // if (ret && value.indexOf('ff01') !== -1) { - if (ret && value.startsWith("ff01") && value.length > 8){ + // 获取设备称实时数据 + if (ret && value.startsWith("ff01") && value.length > 8 && value.length < 50 ){ var wei = value.substr(8, value.length-8); - // var wei = value.substr(12, 12); - // wei = Math.round(Number(hex2a(wei))); - wei = Math.round(Number(StringToNum(wei))); + weiNum++; + if (shujubao >= 1 && weiNum >= (shujubao/2).toFixed(0)){ + res = Math.round(Number(StringToNum(wei))); + } + // 发送实时重量和校准重量到其他平板 + if(weiNum >= shujubao && res && sbId && beforeWeight){ + weiNum = 0; + var weiHex = decimalToHex(res).replace(' ',''); + var sbIdHex = decimalToHex(sbId).replace(' ',''); + var beforeHex = decimalToHex(beforeWeight).replace(' ',''); + var banciHex = decimalToHex(classCode).replace(' ',''); + var checiHex = decimalToHex(trainNumber).replace(' ',''); + var feedInexHex = decimalToHex(feedIndex).replace(' ',''); + weiHex = weiHex.length < 4?'00'+weiHex:weiHex; + sbIdHex = sbIdHex.length < 4?'00'+sbIdHex:sbIdHex; + beforeHex = beforeHex.length < 4?'00'+beforeHex:beforeHex; + if(feedStatus){ + var bleStr = 'FF0A0009'+weiHex+beforeHex+sbIdHex+banciHex+checiHex+feedInexHex; + // msgList.push(bleStr); + execute(db, "INSERT INTO t_ble_msg (id,text) VALUES ("+new Date().getTime()+",'"+bleStr+"');", function (ret, err) {}) + } + + } } - callback(wei); + // 接收其他平板发来的校准重量和实时重量 + if (feedStatus && ret && value.startsWith("ff0a") && sbId === parseInt(value.substr(8, 4),16)){ + var sbId_now = parseInt(value.substr(8, 4),16); + console.log(sbId) + if(sbId != sbId_now){ + return false + } + weightDataFilter.dataBuffer = [] + wendinSize = [] + document.getElementById('submitData').click(); + } + callback(res); }); } +function decimalToHex(decimal) { + let hex = decimal.toString(16); + if (hex.length % 2 !== 0) { + hex = "0" + hex; + } + if (hex.length > 2) { + var str = ''; + for (var i = 0; i < hex.length; i += 2) { + str = str + hex.substr(i, 2) + ' ' + } + return str.trim() + } + return hex; +} + /*发送消息到蓝牙*/ function writeValueForCharacteristic(param, callback) { if (param.value && connetcedStatus){ ble.writeValueForCharacteristic(param, function (ret) { + // console.log(param.value) + if(param.value.startsWith('FF0A0009')){ + // console.log(JSON.stringify(ret)) + } if (ret.status) { // console.log("发送成功"); } else { console.log("发送失败:"+param.value); + // msgList.push("FF0A000404140414"); } callback(ret); }); } } -var lastTime = new Date().getSeconds()*1000+ new Date().getMilliseconds(); -// 接收重量数据计数 -var countLED = 0; + /*组装报文并发数*/ function getMess(param, callback) { var param1 = { @@ -516,7 +711,7 @@ function getMess(param, callback) { return false } var msglen = newmsg.getByteLen(); - var ttr = ''; + var ttr; if (Number(_planSum - _feedNum) >= 0) { ttr = '少'; echartsType = '少'; @@ -553,50 +748,25 @@ function getMess(param, callback) { // console.log(param1.msg) //组装字符卡LED报文 zfk.getMsg(param1, function (ret, err) { - var str = ret.sendMsg; + if (!ret.status){ + console.log(JSON.stringify(err)) + } + let str = ret.sendMsg; str = str.replace(/\s+/g, ""); - var num = str.length / 2; + let num = str.length / 2; param.value = "FF0500" + num.toString(16) + str; countLED ++; // 称重量数据3包取1包 // console.log(shujubao) + //LED报文 if (countLED >= shujubao){ - msgList.push(param.value); - // var ms = strToHex(sbId,4)+strToHex(classCode,2)+strToHex(trainNumber,2)+strToHex(feedIndex,2)+strToHex(_planSum,4)+strToHex(_feedNum,4)+strToHex(nowWeight,4); - // var num1 = ms.length / 2; - // 同步刷新图表 - // 饲喂状态刷新实时状态,否则不刷新装料信息 - if(feedStatus && (allowAuto || weightBeforefix ==='1')){ - renderUnload(); - feedMyChart.setOption({ - dataset: { - source: [[1, _feedNum]] - } - }); - } - renderLoad(); - weightMyChart.setOption({ - dataset: { - source: [[1, nowWeight]] - } - }); countLED = 0 ; + // msgList.push(param.value); + execute(db, "INSERT INTO t_ble_msg (id,text) VALUES ("+new Date().getTime()+",'"+param.value+"');", function (ret, err) {}) } }); + callback(param1.msg) } -/*字符串转16进制hex*/ -function strToHex(str,length){ - var hex = Number(str).toString(16); - var append = ''; - if (hex.length < length){ - for (var i=0;i 0) { mui.toast("没有装料信息"); return false; } - var btnArray1 = [feedName + '已完成', feedName + '未开始']; + let btnArray1 = [feedName + '已完成', feedName + '未开始']; mui.confirm('如果已完成需要先上传', '校准前' + feedName + '状态', btnArray1, function (e) { - if (e.index == 0) { + if (e.index === 0) { mui.toast('校准失败,已完成请先上传'); } else { beforeWeight = nowWeight; allowAuto = true + + var data = { + id:sbId+'_'+api.deviceId, + beforeWeight:beforeWeight, + fix:true, + sbId:sbId, + classCode:Number(classCode), + trainNumber:Number(trainNumber), + feedIndex:feedIndex + } document.getElementById('isfix').innerHTML = '已校准' mui.toast("校准完成"); } }); } -// 开始装料 -function startLoad() { - if (!feedList.length > 0) { - mui.toast("没有装料信息"); - return false; - } - api.showProgress({ - title: '初始化服务中...', - modal: true +//获取唯一id +function generateUUID() { + return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) { + var r = Math.random() * 16 | 0; + var v = c === 'x' ? r : (r & 0x3 | 0x8); + return v.toString(16); }); - // 初始化查询称和字符卡配置信息 - initService(); -} - -function generateUUID() { - return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) { - var r = Math.random() * 16 | 0; - var v = c === 'x' ? r : (r & 0x3 | 0x8); - return v.toString(16); - }); } // 提交数据 function submitData() { +//清空自动跳转判断 weightDataFilter.dataBuffer = [] + wendinSize = [] + api.showProgress({ + title: feedName + _feedNum, + text:remark, + modal: true + }); + var timeouts = remark === '手动上传'?400:1500; + setTimeout(function(){ + api.hideProgress(); + },timeouts) var date = new Date(); var dateOf = getDateStr(date); var dateTime = currTimeFn(date); @@ -56,7 +86,7 @@ function submitData() { remark: remark, planWeight: Number(_planSum), rationCowAmount: feedList[feedIndex] ? feedList[feedIndex].cow : 0, - batchRation: feedList[feedIndex].batchRation, + batchRation: feedList[feedIndex]?feedList[feedIndex].batchRation:0, feedWeight: _feedNum, feedId: feedList[feedIndex].id, driver: driverName, @@ -73,42 +103,30 @@ function submitData() { end: dateTime, time: dateTime }; - // console.log(JSON.stringify(param)) - execute(db, "INSERT INTO t_tmr_result (id,text) VALUES ('"+generateUUID()+"','"+JSON.stringify(param)+"');", function (ret, err) {}) - // api.showProgress({ - // title: '数据上传中...', - // modal: true - // }); - // var feedListCache = [] - // var cacheList = api.getPrefs({ sync: true, key: 'feedListCache' }) - // // 存在 - // if (cacheList && cacheList!=='' && cacheList!=='[]') { - // feedListCache = JSON.parse(cacheList) - // feedListCache.push(param) - // api.setPrefs({ - // key: 'feedListCache', - // value: feedListCache - // }); - // }else{ - // feedListCache.push(param) - // api.setPrefs({ - // key: 'feedListCache', - // value: feedListCache - // }); - // } - // api.hideProgress(); - mui.toast(param.name + " 已上传 " + param.feedWeight,{duration:1500,type:'div'}); - api.setGlobalData({key: 'startTime', value: currTimeFn(new Date())}); + //自动上传完更改状态 remark = '手动上传' + // console.log(JSON.stringify(param)) + if(feedStatus){ + // 保存到本地数据库 + execute(db, "INSERT INTO t_tmr_result (id,text) VALUES ('"+generateUUID()+"','"+JSON.stringify(param)+"');", function (ret, err) {}) + } + // 保存到本地数据库 + // execute(db, "INSERT INTO t_tmr_result (id,text) VALUES ('"+generateUUID()+"','"+JSON.stringify(param)+"');", function (ret, err) {}) + //更新装料开始时间 + api.setGlobalData({key: 'startTime', value: currTimeFn(new Date())}); + // 保存当前阶段重量 beforeWeight = nowWeight; - // document.getElementById('beforeWeight').innerHTML = '称实时/装料前:' + nowWeight + '/' + beforeWeight; - feedIndex = feedIndex + 1; + //获取下一个饲料下标 + feedIndex = Number(feedIndex) + 1; // 没有下一个饲料,车次加一 if (feedIndex > feedList.length - 1) { - trainIndex = trainIndex + 1; + // 下一车次第一个饲料 + feedIndex = 0; + //下一车次 + trainIndex = Number(trainIndex) + 1; // 没有下一个车次,饲喂完成 if (trainIndex > trainArr.length - 1) { - // mui.alert("本班次饲喂完成"); + //班次饲喂结束 feedStatus = false _feedNum = batchName+'次饲喂完成' renderUnload(); @@ -123,6 +141,9 @@ function submitData() { source: [[1, nowWeight]] } }); + document.getElementById('submitData').setAttribute("class", 'btnc mui-btn-success dis'); + document.getElementById('feedNum').innerHTML = batchName + '次' + '饲喂完成'; + //发送饲喂结束给LED屏幕 var param1 = { SF: "AA A5 ", LEN: '1A 00 ', @@ -140,55 +161,43 @@ function submitData() { EF: '5A 55 ', msg: '' }; - // param1.msg = batchName+'饲喂完成' - var newmsg = batchName+'次'; - var msglen = newmsg.getByteLen(); - var ttr = ''; - if (Number(_planSum - _feedNum) >= 0) { - ttr = '少'; - echartsType = '少'; - } else { - ttr = '多'; - echartsType = '多'; - } + let newmsg = batchName + '次'; + //隐藏提交按钮,显示班次饲喂完成,停止蜂鸣器所有状态 + let msglen = newmsg.getByteLen(); if (msglen < 8) { - for (var i = 0; i < 8 - msglen; i++) { + for (i = 0; i < 8 - msglen; i++) { newmsg = newmsg + ' '; } - newmsg = newmsg + ttr; - } else { - newmsg = feedName + ttr; } param1.msg = newmsg + '饲喂完成'; - // console.log(param1.msg) zfk.getMsg(param1, function (ret, err) { - var str = ret.sendMsg; + if (!ret.status){ + console.log(JSON.stringify(err)); + } + let str = ret.sendMsg; str = str.replace(/\s+/g, ""); - var num = str.length / 2; + let num = str.length / 2; param.value = "FF0500" + num.toString(16) + str; - msgList.push(param.value); + // msgList.push(param.value); + execute(db, "INSERT INTO t_ble_msg (id,text) VALUES ("+new Date().getTime()+",'"+param.value+"');", function (ret, err) {}) }) - document.getElementById('submitData').setAttribute("class", 'btnc mui-btn-success dis'); - document.getElementById('feedNum').innerHTML = param1.msg; setTimeout(function(){ console.log("停止蜂鸣"); control("00", "00"); },500) return false; } - // 自动点击下一车,并定位,同时刷新下一个开始装料时间 - document.getElementById('classeCode_' + classCode + 'train_' + trainIndex).click(); + // 存在下一车,自动点击下一车,并定位,同时刷新下一个开始装料时间 + // document.getElementById('classeCode_' + classCode + 'train_' + trainIndex).click(); + handleCarClick(document.getElementById('classeCode_' + classCode + 'train_' + trainIndex), classCode, trainIndex+1) document.querySelector('#' + 'classeCode_' + classCode + 'train_' + trainIndex).scrollIntoView(true); + //刷新装料时间 api.setGlobalData({key: 'startTime', value: currTimeFn(new Date())}); return false; } else { - // 判断是否是圈舍 - if (feedList[feedIndex].batchRation) { - load = false; - } else { - load = true; - } - // 设置下一个饲料选中状态 + // 有下一个饲料信息时,判断是否是圈舍 + load = !feedList[feedIndex].batchRation; + // 清空所有饲料选择状态,设置下一个饲料选中状态 var doms = document.getElementsByClassName('mui-badge'); if (doms.length > 0) { for (var i = 0; i < doms.length; i++) { @@ -200,18 +209,22 @@ function submitData() { // 刷新已装装料为0,显示下一个饲料名称,定位到下一个饲料位置,刷新允许误差,刷新计划重量,刷新显示班次信息 _feedNum = 0; feedName = feedList[feedIndex].name; - // document.getElementById("upload").innerHTML = '上传'+json[0].name - document.getElementById('submitData').innerHTML = '上传' + feedName; - // document.getElementById('fix').innerHTML = '装料前校准' + feedName; - if (load) { - document.getElementById('fix').innerHTML = '装料前校准'; - } else { - document.getElementById('fix').innerHTML = '卸料前校准'; - } - document.querySelector('#feed_' + feedIndex).scrollIntoView(true); allow = feedList[feedIndex].allow; _planSum = feedList[feedIndex].weight.toFixed(0); + text = feedName + _planSum; minutes = feedList[feedIndex].mix_minutes; + //定位到当前饲料 + document.querySelector('#feed_' + feedIndex).scrollIntoView(true); + document.getElementById('isfix').innerHTML = '未校准' + document.getElementById('nowFeed').innerHTML = '' + batchName + ',' + feedName + ''; + document.getElementById('submitData').innerHTML = '上传' + feedName; + if (load) { + document.getElementById('fix').innerHTML = '装料前校准'; + document.getElementById('feedNum').innerHTML = ':' + _planSum + '/已装:' + _feedNum + ''; + } else { + document.getElementById('fix').innerHTML = '卸料前校准'; + document.getElementById('feedNum').innerHTML = ':' + _planSum + '/已卸:' + _feedNum + ''; + } renderUnload(); feedMyChart.setOption({ dataset: { @@ -220,193 +233,15 @@ function submitData() { }); // 误差小于100必须校准才能自动跳转 allowAuto = false; - document.getElementById('isfix').innerHTML = '未校准' - text = feedName + _planSum; - document.getElementById('nowFeed').innerHTML = '' + batchName + ',' + feedName + ''; - if (load) { - document.getElementById('feedNum').innerHTML = ':' + _planSum + '/已装:' + _feedNum + ''; - } else { - document.getElementById('feedNum').innerHTML = ':' + _planSum + '/已卸:' + _feedNum + ''; - } - ledStatus = false; // setTimeout(() => { console.log("停止蜂鸣"); control("00", "00"); setTimeout(function () { - ledStatus = true; + statusEle = false; }, 500); - - - // api.ajax({ - // url: 'https://tmr.nxcyx.com/api/app/tmr/resultUpload', - // headers: { - // 'Content-Type': 'application/json;charset=utf-8' //建议key使用首字母大写的形式,如 User-Agent - // }, - // method: 'post', - // data: { - // body: param - // } - // }, function (ret, err) { - // if (ret && ret.code == 200) { - // api.hideProgress(); - // mui.toast(param.name + " 已上传 " + param.feedWeight,{duration:1500,type:'div'}); - // remark = '手动上传' - // beforeWeight = nowWeight; - // // document.getElementById('beforeWeight').innerHTML = '称实时/装料前:' + nowWeight + '/' + beforeWeight; - // feedIndex = feedIndex + 1; - // // 没有下一个饲料,车次加一 - // if (feedIndex > feedList.length - 1) { - // trainIndex = trainIndex + 1; - // // 没有下一个车次,饲喂完成 - // if (trainIndex > trainArr.length - 1) { - // // mui.alert("本班次饲喂完成"); - // feedStatus = false - // _feedNum = batchName+'次饲喂完成' - // renderUnload(); - // renderLoad(); - // feedMyChart.setOption({ - // dataset: { - // source: [[1, _feedNum]] - // } - // }); - // weightMyChart.setOption({ - // dataset: { - // source: [[1, nowWeight]] - // } - // }); - // var param1 = { - // SF: "AA A5 ", - // LEN: '1A 00 ', - // DES: 'FF FF ', - // SRC: '12 34 ', - // TID: 'B0 A1 ', - // CMD1: '38 02 ', - // X: '00 00 ', - // Y: '00 00 ', - // WIDTH: '40 00 ', - // HEIGHT: '20 00 ', - // FORMAT: '00 00 01 00 ', - // CNT: '04 00 ', - // CRC: '00 00 ', - // EF: '5A 55 ', - // msg: '' - // }; - // // param1.msg = batchName+'饲喂完成' - // var newmsg = batchName+'次'; - // var msglen = newmsg.getByteLen(); - // var ttr = ''; - // if (Number(_planSum - _feedNum) >= 0) { - // ttr = '少'; - // echartsType = '少'; - // } else { - // ttr = '多'; - // echartsType = '多'; - // } - // if (msglen < 8) { - // for (var i = 0; i < 8 - msglen; i++) { - // newmsg = newmsg + ' '; - // } - // newmsg = newmsg + ttr; - // } else { - // newmsg = feedName + ttr; - // } - // param1.msg = newmsg + '饲喂完成'; - // // console.log(param1.msg) - // zfk.getMsg(param1, function (ret, err) { - // var str = ret.sendMsg; - // str = str.replace(/\s+/g, ""); - // var num = str.length / 2; - // param.value = "FF0500" + num.toString(16) + str; - // msgList.push(param.value); - // }) - // document.getElementById('submitData').setAttribute("class", 'btnc mui-btn-success dis'); - // document.getElementById('feedNum').innerHTML = param1.msg; - // setTimeout(function(){ - // console.log("停止蜂鸣"); - // control("00", "00"); - // },500) - // return false; - // } - // // 自动点击下一车,并定位,同时刷新下一个开始装料时间 - // document.getElementById('classeCode_' + classCode + 'train_' + trainIndex).click(); - // document.querySelector('#' + 'classeCode_' + classCode + 'train_' + trainIndex).scrollIntoView(true); - // api.setGlobalData({key: 'startTime', value: currTimeFn(new Date())}); - // return false; - // } else { - // // 判断是否是圈舍 - // if (feedList[feedIndex].batchRation) { - // load = false; - // } else { - // load = true; - // } - // // 设置下一个饲料选中状态 - // var doms = document.getElementsByClassName('mui-badge'); - // if (doms.length > 0) { - // for (var i = 0; i < doms.length; i++) { - // doms[i].setAttribute("class", 'mui-badge'); - // } - // } - // document.getElementById('feed_' + feedIndex).setAttribute("class", 'mui-badge mui-badge-purple'); - // } - // // 刷新已装装料为0,显示下一个饲料名称,定位到下一个饲料位置,刷新允许误差,刷新计划重量,刷新显示班次信息 - // _feedNum = 0; - // feedName = feedList[feedIndex].name; - // // document.getElementById("upload").innerHTML = '上传'+json[0].name - // document.getElementById('submitData').innerHTML = '上传' + feedName; - // // document.getElementById('fix').innerHTML = '装料前校准' + feedName; - // if (load) { - // document.getElementById('fix').innerHTML = '装料前校准'; - // } else { - // document.getElementById('fix').innerHTML = '卸料前校准'; - // } - // document.querySelector('#feed_' + feedIndex).scrollIntoView(true); - // allow = feedList[feedIndex].allow; - // _planSum = feedList[feedIndex].weight.toFixed(0); - // renderUnload(); - // feedMyChart.setOption({ - // dataset: { - // source: [[1, _feedNum]] - // } - // }); - // // 误差小于100必须校准才能自动跳转 - // allowAuto = false; - // document.getElementById('isfix').innerHTML = '未校准' - // text = feedName + _planSum; - // document.getElementById('nowFeed').innerHTML = '' + batchName + ',' + feedName + ''; - // if (load) { - // document.getElementById('feedNum').innerHTML = ':' + _planSum + '/已装:' + _feedNum + ''; - // } else { - // document.getElementById('feedNum').innerHTML = ':' + _planSum + '/已卸:' + _feedNum + ''; - // } - // ledStatus = false; - // // setTimeout(() => { - // console.log("停止蜂鸣"); - // control("00", "00"); - // setTimeout(function () { - // ledStatus = true; - // statusEle = false; - // }, 500); - // // },500) - // } else if (err) { - // api.hideProgress(); - // addNotice(4,'red','submitData,' + err.msg); - // mui.alert( err.msg); - // } - // }); } -var status = ''; -var statusEle = false; -var ledStatus = true; -var uuid = ''; -var serviceUUID = ''; -var characteristicUUID = ''; -var lastTime = ""; -var time = ""; -var feedStatus = false; -var connetcedStatus = false; - // 获取当前时间字符串 function currTimeFn(_date) { var _year = _date.getFullYear(); @@ -418,23 +253,24 @@ function currTimeFn(_date) { return _year + "-" + _month + "-" + _day + " " + _hour + ":" + _minutes + ":" + _seconds; } -// 显示字符卡称重配置信息和未上传数据 -function showZifuka() { - initService(); +function currTimeFnMs(_date) { + var _year = _date.getFullYear(); + var _month = _date.getMonth() + 1 < 10 ? '0' + (_date.getMonth() + 1) : _date.getMonth() + 1; + var _day = _date.getDate() < 10 ? '0' + _date.getDate() : _date.getDate(); + var _hour = _date.getHours() < 10 ? '0' + _date.getHours() : _date.getHours(); + var _minutes = _date.getMinutes() < 10 ? '0' + _date.getMinutes() : _date.getMinutes(); + var _seconds = _date.getSeconds() < 10 ? '0' + _date.getSeconds() : _date.getSeconds(); + var _ms = _date.getMilliseconds() < 10 ? '0' + _date.getMilliseconds() : _date.getMilliseconds(); + return _year + "-" + _month + "-" + _day + " " + _hour + ":" + _minutes + ":" + _seconds + " "+_ms; } -/** - * 上传异常信息 - */ -// ajax防止重复提交状态 -var canUpload = true; - function uploadNotice() { var notice = api.getPrefs({sync: true, key: 'notice'}); - if (notice !== '' && canUpload) { - canUpload = false; + if (notice !== '' && noticeUpload) { + noticeUpload = false; api.ajax({ url: 'https://tmr.nxcyx.com/api/app/tmr/noticeSave', + // url: 'http://192.168.0.107:8081/api/noticeSave', headers: { 'Content-Type': 'application/json;charset=utf-8' //建议key使用首字母大写的形式,如 User-Agent }, @@ -443,50 +279,48 @@ function uploadNotice() { body: notice } }, function (ret, err) { - if (ret && ret.code == 200) { + if (ret && ret.code === 200) { api.removePrefs({ key: 'notice' }); } else if (err) { mui.toast("noticeSave:" + err.msg); } - canUpload = true; + noticeUpload = true; }); } } -/** - * 上传100条实时重量信息 - */ -// 实时重量数组 -var totalList = []; -// ajax防止重复提交状态 -var totalAjax = true; - +//上传实时总重量 function uploadTotalWeight() { - if (totalList.length > 100 && totalAjax) { - totalAjax = false; - api.ajax({ - url: 'https://tmr.nxcyx.com/api/app/tmr/totalWeightUpload', - // url: 'http://10.10.100.101:8088/app/tmr/totalWeightUpload', - headers: { - 'Content-Type': 'application/json;charset=utf-8' //建议key使用首字母大写的形式,如 User-Agent - }, - method: 'post', - data: { - body: { - sbId: sbId, - weightList: totalList + if (totalList.length > 100) { + if (totalUpload) { + var date = new Date() + date.getMilliseconds(); + date.get + totalUpload = false; + api.ajax({ + url: 'https://tmr.nxcyx.com/api/app/tmr/totalWeightUpload', + // url: 'http://192.168.0.107:8081/api/totalWeightUpload', + headers: { + 'Content-Type': 'application/json;charset=utf-8' //建议key使用首字母大写的形式,如 User-Agent + }, + method: 'post', + data: { + body: { + sbId: sbId, + weightList: totalList + } } - } - }, function (ret, err) { - if (ret && ret.code === 200) { - totalList = []; - } else if (err) { - mui.toast("totalWeightUpload" + err.msg); - } - totalAjax = true; - }); + }, function (ret, err) { + if (ret && ret.code === 200) { + totalList = []; + } else if (err) { + mui.toast("totalWeightUpload" + err.msg); + } + totalUpload = true; + }); + } } } @@ -494,7 +328,7 @@ function uploadTotalWeight() { * 添加异常通知 * @param type * @param color - * @param {} describe + * @param describe */ function addNotice(type,color,describe) { var param = { @@ -612,7 +446,7 @@ function renderItemFeed(params, api) { }; } -function makeTextFeed(valOnRadian) { +function makeTextFeed() { if (isNaN(_feedNum )) { return batchName + '次' + '\n' + '饲喂完成' }else if (Math.abs(_planSum - _feedNum) >= 0) { @@ -624,8 +458,7 @@ function makeTextFeed(valOnRadian) { } } -function renderLoad(title) { - +function renderLoad() { var weightOption = { animation: false, dataset: { @@ -661,10 +494,6 @@ function renderUnload() { // source: [[1, _planSum]] source: [[1, _feedNum]] }, - // title: { - // text:feedName + '计划'+ _feedNum +'kg' - // // text:title - // }, tooltip: {}, angleAxis: { type: 'value', @@ -777,31 +606,6 @@ function makeTextWeight(valOnRadian) { return '车内总重\n' + valOnRadian.toFixed(0) + 'kg'; } -function hex2a(hexx) { - var hex = hexx.toString(); //force conversion - var str = ''; - for (var i = 0; i < hex.length; i += 2) { - str += String.fromCharCode(parseInt(hex.substr(i, 2), 16)); - }return str; -} - -// function speakTest(text, speed) { -// // IFlyVoice.stopSpeaking(); -// IFlyVoice.startSynthetic({ -// text: text, -// commonPath_Android: 'widget://res/aisound/common.jet', -// pronouncePath_Android: 'widget://res/aisound/xiaofeng.jet', -// commonPath_iOS: 'widget://res/aisound/common.jet', -// pronouncePath_iOS: 'widget://res/aisound/xiaofeng.jet', -// pronounceName: 'xiaofeng', -// volume: '100', -// speed: speed -// }, function (ret, err) { -// if (ret.status) { -// console.log('合成成功'); -// } else {} -// }); -// } function handleBackMain() { mui.confirm('确认返回到首页?', '提示', btnArray, function (e) { if (e.index === 0) {} else { @@ -843,6 +647,273 @@ function select(db, selsql, callback) { }); } +var websInt; + +// 初始化设备查询 +function initSbList() { + document.getElementById('text').innerHTML = '初始化设备'; + api.showProgress({ + title: '初始化设备...', + modal: true + }); + pickData = []; + api.ajax({ + url: 'https://tmr.nxcyx.com/api/app/tmr/sbList?sourceCow=' + api.getPrefs({ sync: true, key: 'sourceCow' }), + // url: 'http://192.168.0.107:8081/api/sbList?sourceCow=' + api.getPrefs({ sync: true, key: 'sourceCow' }), + method: 'get', + timeout: 5 + }, function (ret, err) { + if (ret) { + api.hideProgress(); + document.getElementById('text').innerHTML = '设备初始化成功'; + var initsb = api.getPrefs({ + sync: true, + key: 'initsb' + }); + ret.data.forEach(function (e) { + if (initsb === e.name){ + var json = { value: e.sbId, text: e.name }; + pickData.push(json); + } + }); + ret.data.forEach(function (e) { + if (initsb !== e.name){ + var json = { value: e.sbId, text: e.name }; + pickData.push(json); + } + }); + sbId = pickData[0].value; + document.getElementById('showUserPicker').innerHTML = pickData[0].text; + muiInit(); + initTime(); + } else { + api.hideProgress(); + mui.alert("sbList:" + err.msg); + document.getElementById('text').innerHTML = '' + '服务器异常' + ''; + } + }); +} + +// 初始化班次信息 +function initTime() { + api.ajax({ + url: 'https://tmr.nxcyx.com/api/app/tmr/time?sourceCow=' + api.getPrefs({ sync: true, key: 'sourceCow' }), + // url: 'http://192.168.0.107:8081/api/time?sourceCow=' + api.getPrefs({ sync: true, key: 'sourceCow' }), + method: 'get' + }, function (ret, err) { + if (ret) { + if (ret.data.length > 0) { + document.getElementById('text').innerHTML = '班次初始化'; + } else { + document.getElementById('text').innerHTML = '当前暂无班次'; + } + var html = ''; + ret.data.forEach(function (e, index) { + if (index === 0) { + html += ''; + } else { + html += ''; + } + }); + document.getElementById('timeList').innerHTML = html; + var param = { + classCode: ret.data[0].batch, + sbId: sbId, + sourceCow: api.getPrefs({ sync: true, key: 'sourceCow' }), + dateOf: getDateStr(new Date()) + }; + initService() + initTrain(param); + } else { + console.log(JSON.stringify(err)) + document.getElementById('text').innerHTML = '班次加载失败'; + } + }); +} + +// 初始化当前班次所有车次 +function initTrain(param) { + document.getElementById('train').innerHTML = '暂无车次'; + api.ajax({ + url: 'https://tmr.nxcyx.com/api/app/tmr/planDay', + // url: 'http://192.168.0.107:8081/api/planDay', + headers: { + 'Content-Type': 'application/json;charset=utf-8' //建议key使用首字母大写的形式,如 User-Agent + }, + method: 'post', + data: { + body: param + } + }, function (ret, err) { + if (ret) { + if (ret.data.length > 0) { + document.getElementById('text').innerHTML = '车次初始化'; + } else { + document.getElementById('feedList').innerHTML = ''; + feedList = []; + document.getElementById('text').innerHTML = '当前暂无计划'; + } + if (ret.data.length === 0) { + mui.toast("该班次暂无车次信息"); + } else if (ret.data.length > 0) { + var html = ''; + trainArr = []; + ret.data.forEach(function (e, index) { + trainArr.push(e.trainNumber); + if (index === 0) { + html += '
  • '+e.className + e.trainNumber + '(' + e.templetName + ')
  • '; + } else { + html += '
  • '+e.className + e.trainNumber + '(' + e.templetName + ')
  • '; + } + }); + document.getElementById('train').innerHTML = html; + trainIndex = 0; + classCode = ret.data[0].classCode; + var param = { + classCode: ret.data[0].classCode, + sbId: sbId, + trainNumber: ret.data[0].trainNumber, + sourceCow: api.getPrefs({ sync: true, key: 'sourceCow' }), + dateOf: getDateStr(new Date()) + }; + initOne(param); + } + } else { + console.log(JSON.stringify(err)) + document.getElementById('text').innerHTML = '车次加载失败'; + } + }); +} + +// 初始化当前车次饲料信息 +function initOne(param) { + weightDataFilter.dataBuffer = [] + wendinSize = [] + document.getElementById('submitData').setAttribute("class", 'btnc mui-btn-success'); + //开始饲喂状态 + feedStatus = true + api.ajax({ + url: 'https://tmr.nxcyx.com/api/app/tmr/planDay', + // url: 'http://192.168.0.107:8081/api/planDay', + headers: { + 'Content-Type': 'application/json;charset=utf-8' //建议key使用首字母大写的形式,如 User-Agent + }, + method: 'post', + data: { + body: param + } + }, function (ret, err) { + if (ret) { + first = true; + document.getElementById('text').innerHTML = '装料信息初始化成功'; + var html = ''; + ret.data.forEach(function (e) { + load = true; + trainNumber = e.trainNumber; + _weightSum = e.total.toFixed(0); + // 合并饲料和圈舍圈舍存入步骤stepsList + var json = [].concat(_toConsumableArray(e.feedJson), _toConsumableArray(e.cowshedJson)); + //更新饲料列表 + feedList = json; + json.forEach(function (j, index) { + if (index === 0) { + html += '' + UNICODE_CHARS[index + 1] + j.name + ':' + Number(j.weight).toFixed(0) + ''; + } else { + html += '' + UNICODE_CHARS[index + 1] + j.name + ':' + Number(j.weight).toFixed(0) + ''; + } + }); + document.getElementById('feedList').innerHTML = html; + // 根据步骤下标取stepsList的值 + document.getElementById('batchName').innerHTML = e.className + e.trainNumber + '(' + e.total.toFixed(0) + 'kg)'; + //第一个饲料 + feedIndex = 0; + _feedNum = 0; + feedName = json[0].name; + allow = json[0].allow; + // 计划 + _planSum = json[0].weight.toFixed(0); + minutes = json[0].mix_minutes; + text = feedName + _planSum; + batchName = e.className + e.trainNumber; + templateName = e.templetName; + templetType = e.templetType; + api.setGlobalData({key: 'startTime', value: currTimeFn(new Date())}); + document.getElementById('submitData').innerHTML = '上传' + json[0].name; + document.querySelector('#feed_0').scrollIntoView(true); + document.getElementById('isfix').innerHTML = '未校准' + document.getElementById('nowFeed').innerHTML = '' + e.className + e.trainNumber + ',' + feedName + ''; + document.getElementById('text').innerHTML = 'V' + api.appVersion+'Ble'; + if (load) { + document.getElementById('feedNum').innerHTML = ':' + _planSum + '/已装:' + _feedNum + ''; + }else{ + document.getElementById('feedNum').innerHTML = ':' + _planSum + '/已卸:' + _feedNum + ''; + } + renderUnload(); + feedMyChart.setOption({ + dataset: { + source: [[1, _feedNum]] + } + }); + // 误差小于100必须校准才能自动跳转 + allowAuto = false; + setTimeout(function(){ + console.log("停止蜂鸣"); + control("00", "00"); + },500) + }); + } else { + console.log(JSON.stringify(err)) + document.getElementById('text').innerHTML = '装料信息加载失败'; + } + }); +} + +function initService() { + initManager({single: true}); +} + +function rescan(){ + if(!connetcedStatus){ + if(bleData.length>0){ + connect({peripheralUUID: bleData[0].value}); + }else{ + scan() + } + } +} + +function muiInit() { + (function ($, doc) { + var showUserPickerButton = doc.getElementById('showUserPicker'); + $.init(); + $.ready(function () { + /** + * 获取对象属性的值 + * 主要用于过滤三级联动中,可能出现的最低级的数据不存在的情况,实际开发中需要注意这一点; + * @param {Object} obj 对象 + * @param {String} param 属性名 + */ + var _getParam = function _getParam(obj, param) { + return obj[param] || ''; + }; + if (userPicker) {} else { + userPicker = new $.PopPicker(); + carListener = null; + showUserPickerButton.addEventListener('tap', function () { + userPicker.show(function (items) { + console.log('设备切换'); + mui.toast('切换设备',{duration:1500,type:'div'}); + sbId = items[0].value; + showUserPickerButton.innerHTML = items[0].text; + initTime(); + }); + }, false); + } + userPicker.setData(pickData); + }); + })(mui, document); +} + // 以下是一个基于JavaScript的称重异常过滤程序示例,该程序使用滑动窗口算法来过滤异常值: // 该程序使用一个dataBuffer数组来保存最近的一组测量值,并返回这组值的平均值。程序在filter方法中,将新的测量值加入到dataBuffer中,并调用getAverageValue方法获取平均值。如果该平均值与上一个有效值的偏差小于maxDeviation,则将该测量值视为有效值,并返回该平均值;否则将该测量值视为异常值,并返回上一个有效值。 // 使用时,可以创建一个WeightDataFilter实例并调用filter方法来传入新的测量值,如下所示: @@ -856,7 +927,7 @@ var _createClass = function () { function defineProperties(target, props) { for function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } -var WeightDataFilter = function () { +let WeightDataFilter = function () { function WeightDataFilter(windowSize, maxDeviation) { _classCallCheck(this, WeightDataFilter); @@ -869,11 +940,11 @@ var WeightDataFilter = function () { _createClass(WeightDataFilter, [{ key: "filter", value: function filter(value) { - this.dataBuffer.push(value); if (this.dataBuffer.length > this.windowSize) { this.dataBuffer.shift(); } - var filteredValue = this.getAverageValue(); + this.dataBuffer.push(value); + let filteredValue = this.getAverageValue(); if (isNaN(this.lastValidValue) || Math.abs(filteredValue - this.lastValidValue) <= this.maxDeviation) { this.lastValidValue = filteredValue; return filteredValue; @@ -884,7 +955,7 @@ var WeightDataFilter = function () { }, { key: "getAverageValue", value: function getAverageValue() { - var sum = this.dataBuffer.reduce(function (total, value) { + let sum = this.dataBuffer.reduce(function (total, value) { return total + value; }, 0); return sum / this.dataBuffer.length; diff --git a/script/module/ble.js b/script/module/ble.js new file mode 100644 index 0000000..488aeac --- /dev/null +++ b/script/module/ble.js @@ -0,0 +1,149 @@ +var ble = null +var bleUtils = { + initBle:function(){ + ble = api.require('ble'); + }, + initManager:function(param,callback){ + ble.initManager(param, function (ret) { + callback(ret) + }); + }, + scan:function(param,callback){ + ble.clearAllSimpleNotifyData(); + ble.scan(param, function (ret) { + callback(ret) + }); + }, + stopScan:function(){ + ble.stopScan() + }, + getPeripheral:function(callback){ + ble.getPeripheral(function (ret) { + if (ret.peripherals.length > 0) { + var li = []; + ret.peripherals.forEach(function (p) { + if (undefined !== p.name) { + if (p.name.indexOf("TMR_BLE") === -1){ + return false + }else{ + console.log(p.name) + li.push({"id":p.uuid,"name":p.name}) + } + } + }); + callback(li) + } + }); + }, + isConnected:function (param,callback){ + ble.isConnected(param, function(ret) { + if (ret.status) { + // console.log('已连接'); + } + callback(ret.status) + }); + }, + disconnect:function(param,callback){ + ble.disconnect(param, function(ret, err) { + if (ret.status) { + console.log("断开连接成功!"); + } + callback(ret,err) + }); + }, + connect:function(param,callback){ + bleUtils.isConnected(param,function (ret){ + if (ret.status) { + console.log('已连接'); + callback(ret) + }else { + ble.connect(param, function (ret, err) { + console.log(JSON.stringify(err)) + callback(ret,err) + }); + } + }) + }, + setMtu:function(param,callback){ + //设置MTU包大小 + ble.setMtu({ + peripheralUUID: param.peripheralUUID, + mtu:param.mtu + },function(ret){ + callback(ret) + }); + }, + discoverService:function(param,callback){ + + ble.discoverService(param, function (ret) { + console.log("discoverService"); + if (ret.services.length > 0) { + console.log("发现服务成功!"); + ret.services.forEach(function (ret4) { + if (ret4.indexOf("0000ffe") !== -1) { + if (ret4 && ret4.length > 0) { + //发现特征 + bleUtils.discoverCharacteristics({ + serviceUUID: ret4, + peripheralUUID: param.peripheralUUID + }, function (ret5) { + if(ret5.indexOf("0000ffe2")!==-1){ + return false + } + console.log(ret4) + console.log(ret5) + callback({ + peripheralUUID: param.peripheralUUID, + serviceUUID: ret4, + characteristicUUID: ret5 + }) + }); + } + + } + }); + } else { + console.log("发现服务失败!"); + } + }); + }, + discoverCharacteristics:function(param,callback){ + ble.discoverCharacteristics(param, function (ret) { + let res = ''; + if (ret.characteristics.length > 0) { + // console.log("发现特征成功!"); + ret.characteristics.forEach(function (s) { + if (s.serviceUUID === param.serviceUUID) { + callback(s.uuid); + } + }); + } else { + console.log("发现特征失败!"); + callback(res); + } + }) + }, + setNotify:function(param,callback){ + ble.setNotify(param, function (ret) { + callback(ret.characteristic.value) + }) + }, + /*发送消息到蓝牙*/ + writeValueForCharacteristic(param, callback) { + ble.writeValueForCharacteristic(param, function (ret) { + // console.log(param.value) + if (ret.status) { + // console.log("发送成功"); + } else { + console.log("发送失败:"+param.value); + // msgList.push("FF0A000404140414"); + } + callback(ret); + }); + } + +} + +export { + bleUtils +}