// 版本更新 function updateApp() { mui.toast(document.getElementById('text').innerHTML) // api.openWin({ // name: 'setting', // reload: true, // // url:'../pages/setting.stml' // url: '../html/setting.html' // }) } // 重量校准 function weightFix() { if (!feedList.length > 0) { mui.toast("没有装料信息") return false } var btnArray1 = [feedName+'已完成',feedName+'未开始']; mui.confirm('如果装料完成需要先上传', '校准前'+feedName+'状态', btnArray1, function (e) { if (e.index == 0) { mui.toast('校准失败,已完成请先上传') } else { beforeWeight = nowWeight mui.toast("校准完成") } }); } var ajaxIsEnd = true; // 开始装料 function startLoad() { if (!feedList.length > 0) { mui.toast("没有装料信息") return false } // 初始化查询称和字符卡配置信息 initService() // 定时任务查询网络状态 clearInterval(resultInterval) console.log('启动定时任务查询网络状态'); resultInterval = setInterval(function () { var wifi = api.require('bgnWiFi'); wifi.getWifiInfo(function (ret, err) { if (ret.status && ret.info) { var network = api.getPrefs({ sync: true, key: 'network' }) if (!network || !weightStatus) { mui.toast('wifi恢复,恢复装料状态') first = false; beforeWeight = api.getGlobalData({ key: 'beforeWeight' }); startLoad() } api.setPrefs({ key: 'network', value: true }); if(!ajaxIsEnd){ return } ajaxIsEnd = false api.ajax({ url: 'https://tmr.nxcyx.com/api/app/tmr/appService?sbId=' + sbId, // url: 'http://192.168.0.107:8088/app/tmr/appService?sbId=' + sbId, method: 'get', }, function (ret, err) { if (ret) { if(networkStatus = false){ mui.toast('网络恢复,恢复装料状态') first = false; beforeWeight = api.getGlobalData({ key: 'beforeWeight' }); startLoad() } networkStatus = true document.getElementById('text').innerHTML = 'V' + api.appVersion var feedListCache = [] var cacheList = api.getPrefs({ sync: true, key: 'feedListCache' }) // 存在 if (cacheList && cacheList != '' && cacheList != '[]') { feedListCache = JSON.parse(cacheList) console.log(feedListCache[0].name + " 待上传"); api.ajax({ url: 'https://tmr.nxcyx.com/api/app/tmr/resultUpload', // url: 'http://192.168.0.107:8088/app/tmr/resultUpload', headers: { 'Content-Type': 'application/json;charset=utf-8' //建议key使用首字母大写的形式,如 User-Agent }, method: 'post', data: { body: feedListCache[0] } }, function (ret, err) { if (ret && ret.code == 200) { console.log(feedListCache[0].name + " 上传成功"); feedListCache.splice(0, 1); api.setPrefs({ key: 'feedListCache', value: feedListCache }); } else if (err) { // clearInterval(resultInterval) } }); } } else { networkStatus = false if (err.msg) { mui.toast("resultUpload:"+err.msg) document.getElementById('text').innerHTML = '' + '服务器异常' + '' addNotice('定时appService'+err.msg) } return false; } ajaxIsEnd = true }) } else { api.setPrefs({ key: 'network', value: false }); mui.toast('请检查WiFi是否已连接') document.getElementById('text').innerHTML = 'WiFi异常' return false; } }); }, 10000); } // 提交数据 function submitData() { var date = new Date() var dateOf = getDateStr(date); var dateTime = currTimeFn(date) var param = { dateOf: dateOf, name: feedName, planWeight: Number(_planSum), rationCowAmount: feedList[feedIndex] ? feedList[feedIndex].cow : 0, batchRation: feedList[feedIndex].batchRation, feedWeight: _feedNum, feedId: feedList[feedIndex].id, driver: driverName, type: feedList[feedIndex].batchRation ? 2 : 1, sourceCow: api.getPrefs({ sync: true, key: 'sourceCow' }), classCode: classCode, trainNumber: trainNumber, templet: templateName, templetType: templetType, sbId: sbId, createBy: driverName, start: api.getGlobalData({ key: 'startTime' }), end: dateTime, time: dateTime } 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) { mui.toast(param.name + " 已上传 "+param.feedWeight) 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.toast('本班次饲喂完成'); document.getElementById('submitData').setAttribute("class", 'btnc mui-btn-primary dis'); 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 document.querySelector('#feed_' + feedIndex).scrollIntoView(true) allow = feedList[feedIndex].allow _planSum = feedList[feedIndex].weight.toFixed(0) text = feedIndex + 1 +feedName + _planSum; document.getElementById('nowFeed').innerHTML =''+ batchName + ',' + feedName + '' } else if (err) { addNotice('submitData,'+err.msg) mui.alert("submitData:"+err.msg) } }); // 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 // }); // } // console.log(JSON.stringify(param)); // api.setGlobalData({ key: 'beforeWeight', value: nowWeight }); // document.getElementById('submitData').setAttribute("class", 'mui-btn-primary dis'); // document.getElementById('startLoad').setAttribute("class", 'mui-btn-primary'); } var weightDataFilter; // 初始化所有服务 function initService() { api.ajax({ url: 'https://tmr.nxcyx.com/api/app/tmr/appService?sbId=' + sbId, method: 'get', }, function (ret, err) { if(ret){ ret.data.forEach(e => { // 称重配置信息 if (e.serviceName == 'weight') { weightHost = e.param.host; weightPort = e.param.port; api.setGlobalData({ key: 'weightTcp', value: weightHost + ':' + weightPort }); // 字符卡配置信息 } else if (e.serviceName == 'zfk') { zfkList = e.param.addrList; zifukaHost = e.param.host; zifukaPort = Number(e.param.port); api.setGlobalData({ key: 'zfkTcp', value: zifukaHost + ':' + zifukaPort }); api.setGlobalData({ key: 'addrList', value: e.param.addrList }); initReadStrAndLedSend() } }) } }) } // 初始化LED屏幕 function initReadStrAndLedSend() { zfk = api.require("moduleDemo"); var param = { host: zifukaHost, port: zifukaPort, }; console.log(JSON.stringify(param)); api.showProgress({ title: 'LED屏加载中', modal: true }); zfk.createTcp(param, function (ret, err) { if (!ret.status) { api.hideProgress(); mui.alert('LED屏加载失败') document.getElementById('text').innerHTML = 'LED加载失败' } else { api.hideProgress(); document.getElementById('text').innerHTML = 'V' + api.appVersion // led初始化成功后加载称重服务 setTimeout(() => { initWeightService() }, 1000); } }) } // 获取当前日期字符串 function getDateStr(date) { var seperator1 = "-"; var seperator2 = ":"; var month = date.getMonth() + 1; var strDate = date.getDate(); if (month >= 1 && month <= 9) { month = "0" + month; } if (strDate >= 0 && strDate <= 9) { strDate = "0" + strDate; } var currentdate = date.getFullYear() + seperator1 + month + seperator1 + strDate; return currentdate } // 获取当前时间字符串 function currTimeFn(_date) { let _year = _date.getFullYear(); let _month = _date.getMonth() + 1 < 10 ? '0' + (_date.getMonth() + 1) : _date.getMonth() + 1; let _day = _date.getDate() < 10 ? '0' + _date.getDate() : _date.getDate(); let _hour = _date.getHours() < 10 ? '0' + _date.getHours() : _date.getHours(); let _minutes = _date.getMinutes() < 10 ? '0' + _date.getMinutes() : _date.getMinutes(); let _seconds = _date.getSeconds() < 10 ? '0' + _date.getSeconds() : _date.getSeconds(); return _year + "-" + _month + "-" + _day + " " + _hour + ":" + _minutes + ":" + _seconds; } // 显示字符卡称重配置信息和未上传数据 function showZifuka() { var size = 0; var cacheList = api.getPrefs({ sync: true, key: 'feedListCache' }) // 存在 if (cacheList && cacheList != '' && cacheList != '[]') { var feedListCache = JSON.parse(cacheList) size = feedListCache.length } var msg = "LED配置 " + api.getGlobalData({ key: 'zfkTcp' }) + '
LED地址' + api.getGlobalData({ key: 'addrList' }) msg += "
称配置 " + api.getGlobalData({ key: 'weightTcp' }) msg += '
未上传数据' + size + '条' mui.alert(msg); } /** * 上传异常信息 */ // ajax防止重复提交状态 var canUpload = true function uploadNotice(){ var notice = api.getPrefs({ sync: true, key: 'notice' }) if(notice !='' && canUpload){ canUpload = false api.ajax({ url: 'https://tmr.nxcyx.com/api/app/tmr/noticeSave', headers: { 'Content-Type': 'application/json;charset=utf-8' //建议key使用首字母大写的形式,如 User-Agent }, method: 'post', data: { body: notice } }, function (ret, err) { if (ret && ret.code == 200) { api.removePrefs({ key: 'notice' }); } else if (err) { mui.toast("noticeSave:"+err.msg) } canUpload = 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 } } }, function (ret, err) { if (ret && ret.code == 200) { totalList=[] } else if (err) { mui.toast("totalWeightUpload"+err.msg) } totalAjax = true }); } } /** * 添加异常通知 * @param {} describe */ function addNotice(describe){ var param={ sourceCow: api.getPrefs({ sync: true, key: 'sourceCow' }), type:4, color:'red', time:currTimeFn(new Date()), describe:describe } api.setPrefs({ key: 'notice', value: param }); } /** * 定时任务 */ function totalWeightUpload() { uploadNotice() uploadTotalWeight() } function convertToPolarPoint(renderItemParams, radius, radian) { return [ Math.cos(radian) * radius + renderItemParams.coordSys.cx, -Math.sin(radian) * radius + renderItemParams.coordSys.cy ]; } function makePionterPoints(renderItemParams, polarEndRadian) { return [ convertToPolarPoint(renderItemParams, _outerRadius, polarEndRadian), convertToPolarPoint( renderItemParams, _outerRadius, polarEndRadian + Math.PI * 0.03 ), convertToPolarPoint(renderItemParams, _pointerInnerRadius, polarEndRadian) ]; } //计划量/已装量echarts参数 function renderItemFeed(params, api) { var valOnRadian = api.value(1); var coords = api.coord([api.value(0), valOnRadian]); var polarEndRadian = coords[3]; var imageStyle = { image: "https://tmr.nxcyx.com/img/custom-gauge-panel.png", x: params.coordSys.cx - _outerRadius, y: params.coordSys.cy - _outerRadius, width: _outerRadius * 2, height: _outerRadius * 2 }; return { type: 'group', children: [ { type: 'image', style: imageStyle, clipPath: { type: 'sector', shape: { cx: params.coordSys.cx, cy: params.coordSys.cy, r: _outerRadius, r0: _innerRadius, startAngle: 0, endAngle: -polarEndRadian, transition: 'endAngle', enterFrom: { endAngle: 0 } } } }, { type: 'image', style: imageStyle, clipPath: { type: 'polygon', shape: { points: makePionterPoints(params, polarEndRadian) }, extra: { polarEndRadian: polarEndRadian, transition: 'polarEndRadian', enterFrom: { polarEndRadian: 0 } }, during: function (apiDuring) { apiDuring.setShape( 'points', makePionterPoints(params, apiDuring.getExtra('polarEndRadian')) ); } } }, { type: 'circle', shape: { cx: params.coordSys.cx, cy: params.coordSys.cy, r: _insidePanelRadius }, style: { fill: '#fff', shadowBlur: 25, shadowOffsetX: 0, shadowOffsetY: 0, shadowColor: 'rgba(76,107,167,0.4)' } }, { type: 'text', extra: { valOnRadian: valOnRadian, transition: 'valOnRadian', enterFrom: { valOnRadian: 0 } }, style: { text: makeTextFeed(valOnRadian), fontSize: fontsize, fontWeight: 900, x: params.coordSys.cx, y: params.coordSys.cy, fill: 'rgb(255, 0, 0)', align: 'center', verticalAlign: 'middle', enterFrom: { opacity: 0 } }, during: function (apiDuring) { apiDuring.setStyle( 'text', makeTextFeed(apiDuring.getExtra('valOnRadian')) ); } } ] }; } function makeTextFeed(valOnRadian) { // if (load) { if (Math.abs(_planSum - _feedNum)>=0) { // return '剩余应装\n' + valOnRadian.toFixed(1) + 'kg'; return feedName + '\n' + echartsType+ Math.abs(_planSum - _feedNum).toFixed(0) + 'kg'; } else { // return '剩余应卸\n' + valOnRadian.toFixed(1) + 'kg'; return feedName + '\n' + echartsType +Math.abs(_planSum - _feedNum).toFixed(0) + 'kg'; } } function renderLoad(title) { var weightOption = { animation: false, dataset: { source: [[1, nowWeight]] }, tooltip: {}, angleAxis: { type: 'value', startAngle: 0, show: false, min: 0, max: _weightSum }, radiusAxis: { type: 'value', show: false }, polar: {}, series: [ { type: 'custom', coordinateSystem: 'polar', renderItem: renderItemWeight } ] }; weightOption && weightMyChart.setOption(weightOption); } function renderUnload() { var feedOption = { animation: false, dataset: { // source: [[1, _planSum]] source: [[1, _feedNum]] }, // title: { // text:feedName + '计划'+ _feedNum +'kg' // // text:title // }, tooltip: {}, angleAxis: { type: 'value', startAngle: 0, show: false, min: 0, max: _planSum }, radiusAxis: { type: 'value', show: false }, polar: {}, series: [ { type: 'custom', coordinateSystem: 'polar', renderItem: renderItemFeed } ] }; feedOption && feedMyChart.setOption(feedOption); } //总重量/剩余量echarts参数 function renderItemWeight(params, api) { var valOnRadian = api.value(1); var coords = api.coord([api.value(0), valOnRadian]); var polarEndRadian = coords[3]; var imageStyle = { // image: _panelImageURL, image: "https://tmr.nxcyx.com/img/custom-gauge-panel.png", x: params.coordSys.cx - _outerRadius, y: params.coordSys.cy - _outerRadius, width: _outerRadius * 2, height: _outerRadius * 2 }; return { type: 'group', children: [ { type: 'image', style: imageStyle, clipPath: { type: 'sector', shape: { cx: params.coordSys.cx, cy: params.coordSys.cy, r: _outerRadius, r0: _innerRadius, startAngle: 0, endAngle: -polarEndRadian, transition: 'endAngle', enterFrom: { endAngle: 0 } } } }, { type: 'image', style: imageStyle, clipPath: { type: 'polygon', shape: { points: makePionterPoints(params, polarEndRadian) }, extra: { polarEndRadian: polarEndRadian, transition: 'polarEndRadian', enterFrom: { polarEndRadian: 0 } }, during: function (apiDuring) { apiDuring.setShape( 'points', makePionterPoints(params, apiDuring.getExtra('polarEndRadian')) ); } } }, { type: 'circle', shape: { cx: params.coordSys.cx, cy: params.coordSys.cy, r: _insidePanelRadius }, style: { fill: '#fff', shadowBlur: 25, shadowOffsetX: 0, shadowOffsetY: 0, shadowColor: 'rgba(76,107,167,0.4)' } }, { type: 'text', extra: { valOnRadian: valOnRadian, transition: 'valOnRadian', enterFrom: { valOnRadian: 0 } }, style: { text: makeTextWeight(valOnRadian), fontSize: fontsize, fontWeight: 900, x: params.coordSys.cx, y: params.coordSys.cy, fill: 'rgb(0, 0, 0)', align: 'center', verticalAlign: 'middle', enterFrom: { opacity: 0 } }, during: function (apiDuring) { apiDuring.setStyle( 'text', makeTextWeight(apiDuring.getExtra('valOnRadian')) ); } } ] }; } function makeTextWeight(valOnRadian) { return '车内总重\n' + valOnRadian.toFixed(0) + 'kg'; } // 以下是一个基于JavaScript的称重异常过滤程序示例,该程序使用滑动窗口算法来过滤异常值: // 该程序使用一个dataBuffer数组来保存最近的一组测量值,并返回这组值的平均值。程序在filter方法中,将新的测量值加入到dataBuffer中,并调用getAverageValue方法获取平均值。如果该平均值与上一个有效值的偏差小于maxDeviation,则将该测量值视为有效值,并返回该平均值;否则将该测量值视为异常值,并返回上一个有效值。 // 使用时,可以创建一个WeightDataFilter实例并调用filter方法来传入新的测量值,如下所示: // let weightDataFilter = new WeightDataFilter(10, 0.5); // let filteredValue = weightDataFilter.filter(measurementValue); // 其中,10是窗口大小,0.5是最大的偏差值,可以根据实际需求进行调整。measurementValue是当前的测量值。 class WeightDataFilter { constructor(windowSize, maxDeviation) { this.windowSize = windowSize; this.maxDeviation = maxDeviation; this.dataBuffer = []; this.lastValidValue = NaN; } filter(value) { this.dataBuffer.push(value); if (this.dataBuffer.length > this.windowSize) { this.dataBuffer.shift(); } let filteredValue = this.getAverageValue(); // console.log(filteredValue,Math.abs(filteredValue - this.lastValidValue),this.maxDeviation); if (isNaN(this.lastValidValue) || Math.abs(filteredValue - this.lastValidValue) <= this.maxDeviation) { this.lastValidValue = filteredValue; return filteredValue; } else { return this.lastValidValue; } } getAverageValue() { let sum = this.dataBuffer.reduce((total, value) => total + value, 0); return sum / this.dataBuffer.length; } }