| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634 |
- <template>
- <view class="content">
- <view class="header">
- <u--form>
- <u-form-item style="border:0px"
- label="设备名称:"
- labelWidth="auto"
- :borderBottom="false"
- >
- <u--input disabled
- placeholder="请选择分组"
- border="none"
- color="gray"
- disabledColor="white"
- v-model="deviceInfo.deviceName"
- ></u--input>
- </u-form-item>
- <u-form-item style="border:0px"
- label="设备编号:"
- labelWidth="auto"
- :borderBottom="false"
- ref="item1"
- >
- <u--input disabled
- border="none"
- color="gray"
- disabledColor="white"
- v-model="deviceInfo.serialNumber"
- ></u--input>
- </u-form-item>
- <u-form-item style="border:0px"
- label="二维码ID:"
- labelWidth="auto"
- :borderBottom="false"
- ref="item1"
- >
- <u--input disabled
- border="none"
- color="gray"
- disabledColor="white"
- v-model="deviceInfo.qrcodeId"
- ></u--input>
- </u-form-item>
- <u-form-item style="border:0px"
- label="激活时间:"
- labelWidth="auto"
- :borderBottom="false"
- ref="item1"
- >
- <u--input disabled
- border="none"
- color="gray"
- disabledColor="white"
- :value="deviceInfo.activeTime"
- ></u--input>
- </u-form-item>
- <u-form-item style="border:0px"
- label="设备信号:"
- labelWidth="auto"
- :borderBottom="false"
- >
- <u--input disabled
- border="none"
- color="gray"
- disabledColor="white"
- :value="deviceInfo.rssi"
- ></u--input>
- </u-form-item>
- <u-form-item v-if="deviceInfo.networkAddress != null" style="border:0px"
- label="设备网络:"
- labelWidth="auto"
- :borderBottom="false"
- ref="item1"
- >
- <u--input disabled
- border="none"
- color="gray"
- disabledColor="white"
- :value="deviceInfo.networkAddress+'('+deviceInfo.networkIp+')'"
- ></u--input>
- </u-form-item>
- <u-form-item style="border:0px"
- label="设备状态:"
- labelWidth="auto"
- :borderBottom="false"
- >
- <view style="width:90rpx">
- <u-tag v-if="deviceInfo.status === 4" text="离线" size="mini" type="info"></u-tag>
- <u-tag v-if="deviceInfo.status === 3" text="在线" size="mini" type="success"></u-tag>
- <u-tag v-if="deviceInfo.status === 2" text="禁用" size="mini" type="error"></u-tag>
- <u-tag v-if="deviceInfo.status === 1" text="未激活" size="mini" type="error"></u-tag>
- </view>
- </u-form-item>
- </u--form>
- </view>
- <view class="text-area">
- <u-tabs :list="summary" keyName="tabName" @change="getDeviceStatus"></u-tabs>
- <view class="prop-container" style="background: white;padding:10px ">
- <u-form>
- <u--text text="属性控制" style="margin-top:10px"></u--text>
- <u-form-item style="border:0px;position: relative" v-for="item in inputProp"
- :label="item.name"
- labelWidth="auto"
- :borderBottom="false"
- >
- <u-input placeholder="请输入字符串" v-if="item.type === 'string'" v-model="item.shadow">
- <template slot="suffix">
- <u-button v-if="deviceInfo.status==3"
- @tap="send(item)"
- text="发送"
- type="success"
- size="mini"
- ></u-button>
- <u-button v-if="deviceInfo.status!=3"
- @tap="send(item)"
- text="发送"
- type="info"
- size="mini"
- ></u-button>
- </template>
- </u-input>
- <u-input placeholder="请输入整数" v-if="item.type === 'integer'" v-model="item.shadow">
- <template slot="suffix">
- <u-button v-if="deviceInfo.status==3"
- @tap="send(item)"
- text="发送"
- type="success"
- size="mini"
- ></u-button>
- <u-button v-if="deviceInfo.status!=3"
- @tap="send(item)"
- text="发送"
- type="info"
- size="mini"
- ></u-button>
- </template>
- </u-input>
- <u-input placeholder="请使用英文逗号分隔的字符串" v-if="item.type === 'array'" v-model="item.shadow">
- <template slot="suffix">
- <u-button v-if="deviceInfo.status==3"
- @tap="send(item)"
- text="发送"
- type="success"
- size="mini"
- ></u-button>
- <u-button v-if="deviceInfo.status!=3"
- @tap="send(item)"
- text="发送"
- type="info"
- size="mini"
- ></u-button>
- </template>
- </u-input>
- <view v-if="item.type === 'enum'" style="position: relative" >
- <view @click="chooseItemData(item)" style="width:100%" v-if="item.text != null && item.text.length>0">{{ item.text }}</view>
- <view @click="chooseItemData(item)" style="width:100%" v-else>请选择</view>
- <u-button v-if="deviceInfo.status==3" customStyle="position: absolute;top: 8rpx;right: 20rpx;width: 13%;"
- @tap="send(item)"
- text="发送"
- type="success"
- size="mini"
- ></u-button>
- </view>
- </u-form-item>
- <u-line></u-line>
- <u--text text="属性监控" style="margin-top:10px"></u--text>
- <view>
- <u-form-item style="border:0px" v-for="item in deviceInfo.readOnlyList"
- :label="item.name"
- labelWidth="auto"
- :borderBottom="false"
- >
- <u-input placeholder="请输入字符串" disabled="" :value="item.shadow+' '+item.unit">
- </u-input>
- </u-form-item>
- </view>
- </u-form>
- </view>
- <u-picker @cancel="show=null" :show="show!=null" :columns="columns" @confirm="confirmItemData" keyName="text"></u-picker>
- </view>
- </view>
- </template>
- <script>
- import { getDetail,getDeviceStatus,cacheJsonThingsModel } from '@/api/device/device.js'
- import UButton from "../../uni_modules/uview-ui/components/u-button/u-button";
- import UForm from "../../uni_modules/uview-ui/components/u--form/u--form";
- export default {
- components: {UForm, UButton},
- data(){
- return {
- show:null,
- value:"",
- deviceInfo:{},
- id:0,
- summary:[],
- activeName:0,
- childId:"",
- oneToMul:false,
- inputProp:[],
- watchProp:[],
- columns:[]
- }
- },
- onLoad: function(opt) {
- this.id = opt.id;
- this.connectMqtt();
- this.getDetail();
- },
- destroyed() {
- // 取消订阅主题
- this.mqttUnSubscribe(this.deviceInfo);
- },
- methods:{
- confirmItemData(e){
- let data = e.value[0];
- this.show.text = data.text;
- this.show.shadow=data.value;
- this.show = null;
- console.log(data);
- },
- send(item){
- if(this.deviceInfo.status != 3){
- uni.showToast({
- title:"设备暂未上线",
- icon:"error"
- })
- return;
- }
- if(!item.shadow){
- uni.showToast({
- title:"数据不能为空",
- icon:"error"
- })
- return;
- }
- this.publishThingsModel(this.deviceInfo,item)
- },
- /** 更新设备状态 */
- updateDeviceStatus(device) {
- },
- chooseItemData(data){
- if(this.deviceInfo.status != 3){
- uni.showToast({
- title:"设备暂未上线",
- icon:"error"
- })
- return;
- }
- this.columns = [data.enumList];
- this.show =data;
- },
- getDetail(){
- let self = this;
- getDetail(this.id).then(res=>{
- self.deviceInfo = res.data;
- self.parseSummay(res.data.summary)
- self.mqttSubscribe(res.data);
- self.getDeviceStatus();
- });
- },
- getDeviceStatus(e){
- let self = this;
- if(!e){
- e = {index:0};
- }
- this.activeName = e.index;
- this.childId = this.summary[this.activeName].id;
- getDeviceStatus(this.id,this.childId).then(res=>{
- let data =res.data;
- this.deviceInfo = data;
- self.parseStatusData(data)
- });
- },
- parseStatusData(data){
- let arr = [];
- let arrayList = data.arrayList;
- arr = arr.concat(arrayList);
- let enumList = data.enumList;
- arr = arr.concat(enumList);
- let integerList = data.integerList;
- arr = arr.concat(integerList);
- let stringList = data.stringList;
- arr = arr.concat(stringList);
- this.inputProp = arr;
- let readOnlyList = data.readOnlyList;
- this.watchProp = readOnlyList;
- },
- parseSummay(summary){
- let self = this;
- if(!summary){
- summary = "";
- }
- if(summary.length>0){
- this.summary = JSON.parse(summary);
- if(self.summary.length>0){
- this.oneToMul = true;
- }
- for (let i = 0; i < self.summary.length; i++) {
- self.summary[i].tabName = self.summary[i].id+"_"+self.summary[i].name
- }
- let childId = "";
- if(this.oneToMul){
- let info = self.summary[self.activeName];
- childId = info.id;
- }
- this.childId = childId;
- }else{
- this.summary = [{tabName:"详情查看"}]
- }
- },
- goDeviceDetail(id){
- uni.navigateTo({
- url: '/pages/device/detail/detail?id='+id
- });
- },
- async connectMqtt() {
- if (this.$mqttTool.client == null) {
- await this.$mqttTool.connect(this.vuex_token);
- }
- this.mqttCallback();
- },
- /** Mqtt订阅主题 */
- mqttSubscribe(device) {
- // 订阅当前设备状态和实时监测
- let topicStatus = '/' + device.productId + '/' + device.serialNumber + '/status/post';
- let topicProperty = '/' + device.productId + '/' + device.serialNumber + '/property/post';
- let topicFunction = '/' + device.productId + '/' + device.serialNumber + '/function/post';
- let topics = [];
- topics.push(topicStatus);
- topics.push(topicProperty);
- topics.push(topicFunction);
- this.$mqttTool.subscribe(topics);
- },
- /** Mqtt取消订阅主题 */
- mqttUnSubscribe(device) {
- // 订阅当前设备状态和实时监测
- let topicStatus = '/' + device.productId + '/' + device.serialNumber + '/status/post';
- let topicProperty = '/' + device.productId + '/' + device.serialNumber + '/property/post';
- let topicFunction = '/' + device.productId + '/' + device.serialNumber + '/function/post';
- let topics = [];
- topics.push(topicStatus);
- topics.push(topicProperty);
- topics.push(topicFunction);
- console.log('取消订阅', topics);
- this.$mqttTool.unsubscribe(topics);
- },
- /* Mqtt回调处理 */
- mqttCallback() {
- this.$mqttTool.client.on('message', (topic, message, buffer) => {
- let topics = topic.split('/');
- let productId = topics[1];
- let deviceNum = topics[2];
- console.log('接收到内容:'+message);
- message = JSON.parse(message.toString());
- if (topics[3] == 'status') {
- console.log('接收到【设备状态-运行】主题:', topic);
- console.log('接收到【设备状态-运行】内容:', message);
- // 更新列表中设备的状态
- if (this.deviceInfo.serialNumber == deviceNum) {
- this.deviceInfo.status = message.status;
- this.deviceInfo.isShadow = message.isShadow;
- this.deviceInfo.rssi = message.rssi;
- this.updateDeviceStatus(this.deviceInfo);
- }
- }
- if (topics[3] == 'property' || topics[3] == 'function') {
- console.log('接收到【物模型】主题:', topic);
- console.log('接收到【物模型】内容:', message);
- if(this.oneToMul){
- let curTabId = this.summary[this.activeName].id;
- let msg = [];
- for (let i = 0; i < message.length; i++) {
- let curMsg = message[i];
- let id = curMsg.id;
- let ids = id.split("_");
- let value = curMsg.value;
- if(ids.length == 2){
- if(curTabId == ids[1]){
- msg.push({id:ids[0],value:value});
- }
- }
- }
- message = msg;
- }
- // 更新列表中设备的属性
- if (this.deviceInfo.serialNumber == deviceNum) {
- for (let j = 0; j < message.length; j++) {
- let isComplete = false;
- // 布尔类型
- for (let k = 0; k < this.deviceInfo.boolList.length && !isComplete; k++) {
- if (this.deviceInfo.boolList[k].id == message[j].id) {
- this.deviceInfo.boolList[k].shadow = message[j].value;
- isComplete = true;
- break;
- }
- }
- // 枚举类型
- for (let k = 0; k < this.deviceInfo.enumList.length && !isComplete; k++) {
- if (this.deviceInfo.enumList[k].id == message[j].id) {
- this.deviceInfo.enumList[k].shadow = message[j].value;
- isComplete = true;
- break;
- }
- }
- // 字符串类型
- for (let k = 0; k < this.deviceInfo.stringList.length && !isComplete; k++) {
- if (this.deviceInfo.stringList[k].id == message[j].id) {
- this.deviceInfo.stringList[k].shadow = message[j].value;
- isComplete = true;
- break;
- }
- }
- // 数组类型
- for (let k = 0; k < this.deviceInfo.arrayList.length && !isComplete; k++) {
- if (this.deviceInfo.arrayList[k].id == message[j].id) {
- this.deviceInfo.arrayList[k].shadow = message[j].value;
- isComplete = true;
- break;
- }
- }
- // 整数类型
- for (let k = 0; k < this.deviceInfo.integerList.length && !isComplete; k++) {
- if (this.deviceInfo.integerList[k].id == message[j].id) {
- this.deviceInfo.integerList[k].shadow = message[j].value;
- isComplete = true;
- break;
- }
- }
- // 小数类型
- for (let k = 0; k < this.deviceInfo.decimalList.length && !isComplete; k++) {
- if (this.deviceInfo.decimalList[k].id == message[j].id) {
- this.deviceInfo.decimalList[k].shadow = message[j].value;
- isComplete = true;
- break;
- }
- }
- // 监测数据
- for (let k = 0; k < this.deviceInfo.readOnlyList.length && !isComplete; k++) {
- if (this.deviceInfo.readOnlyList[k].id == message[j].id) {
- this.deviceInfo.readOnlyList[k].shadow = message[j].value;
- // 更新图表
- // for (let m = 0; m < this.monitorChart.length; m++) {
- // if (message[j].id == this.monitorChart[m].data.id) {
- // let data = [{
- // value: message[j].value,
- // name: this.monitorChart[m].data.name
- // }];
- // this.monitorChart[m].chart.setOption({
- // series: [{
- // data: data
- // }]
- // });
- // break;
- // }
- // }
- isComplete = true;
- break;
- }
- }
- }
- }
- }
- });
- },
- /** 发布物模型 类型(1=属性,2=功能) */
- publishThingsModel(device, model) {
- // 获取缓存的Json物模型
- cacheJsonThingsModel(device.productId).then(response => {
- let thingsModel = JSON.parse(response.data);
- let type = 0;
- for (let i = 0; i < thingsModel.functions.length; i++) {
- if (model.id == thingsModel.functions[i].id) {
- type = 2;
- break;
- }
- }
- if (type == 0) {
- for (let i = 0; i < thingsModel.properties.length; i++) {
- if (model.id == thingsModel.properties[i].id) {
- type = 1;
- break;
- }
- }
- }
- if (type != 0) {
- this.mqttPublish(type, device, model);
- }
- });
- },
- notifyError(res){
- uni.showToast({
- title:res,
- icon:"error"
- })
- },
- notifySuccess(res){
- uni.showToast({
- title:res,
- icon:"success"
- })
- },
- /**
- * Mqtt发布消息
- * @type 类型(1=属性,2=功能,3=OTA升级,4=实时监测)
- * @device 设备
- * @model 物模型
- * */
- mqttPublish(type, device, model) {
- let topic = "";
- let message = ""
- let oneToMul = false;
- if(this.summary.length>0){
- oneToMul = true;
- }
- let modelId = model.id;
- if(oneToMul){
- let info = this.summary[this.activeName];
- let childId = info.id;
- modelId = modelId+"_"+childId;
- }
- if (type == 1) {
- if (device.status == 3) {
- // 属性,在线模式
- topic = "/" + device.productId + "/" + device.serialNumber + "/property-online/get";
- } else if (device.isShadow) {
- // 属性,离线模式
- topic = "/" + device.productId + "/" + device.serialNumber + "/property-offline/post";
- }
- message = '[{"id":"' + modelId + '","value":"' + model.shadow + '"}]';
- } else if (type == 2) {
- if (device.status == 3) {
- // 功能,在线模式
- topic = "/" + device.productId + "/" + device.serialNumber + "/function-online/get";
- } else if (device.isShadow) {
- // 功能,离线模式
- topic = "/" + device.productId + "/" + device.serialNumber + "/function-offline/post";
- }
- message = '[{"id":"' + modelId + '","value":"' + model.shadow + '"}]';
- } else if (type == 3) {
- // OTA升级
- topic = "/" + device.productId + "/" + device.serialNumber + "/ota/get";
- message = '{"version":' + this.firmware.version + ',"downloadUrl":"' + this.getDownloadUrl(this.firmware.filePath) + '"}';
- } else {
- return;
- }
- if (topic != "") {
- // 发布
- this.$mqttTool.publish(topic, message, model.name).then(res => {
- this.notifySuccess(res);
- }).catch(res => {
- this.notifyError(res);
- });
- }
- },
- }
- }
- </script>
- <style>
- .header{
- width: 100%;
- background: white;
- padding:0px 20rpx
- }
- .content {
- display: flex;
- flex-direction: column;
- align-items: center;
- justify-content: center;
- }
- .logo {
- height: 200rpx;
- width: 200rpx;
- margin-top: 200rpx;
- margin-left: auto;
- margin-right: auto;
- margin-bottom: 50rpx;
- }
- .text-area {
- margin:10px;
- padding-bottom: 10px;
- justify-content: center;
- width: 100%;
- }
- .grid-text {
- font-size: 14px;
- color: #909399;
- padding: 10rpx 0 20rpx 0rpx;
- /* #ifndef APP-PLUS */
- box-sizing: border-box;
- /* #endif */
- }
- .title {
- font-size: 36rpx;
- color: #8f8f94;
- }
- </style>
|