detail.vue 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026
  1. <template>
  2. <view class="content">
  3. <view class="header" style="margin:0;padding: 0px;">
  4. <view class="bg" style="position: fixed;top:0px;bottom:0px;left:0px;right:0px;background-image: url('/static/images/device/bg.png');background-size: 100% 100%;padding:0 40rpx">
  5. <view style="position: absolute;right:10rpx;top:30rpx;z-index: 9999">
  6. <u-button @click="reportError" color="#EC6D2F" text="上报异常" type="error" size="mini"></u-button>
  7. </view>
  8. <view style="position: absolute;right:52rpx;top:116rpx;">
  9. <view>
  10. <u-image :showLoading="true" src="/static/images/device/zaixian.png" width="200rpx" height="200rpx" ></u-image>
  11. </view>
  12. <view style="position: absolute;color:#48C373;top:110rpx;left:70rpx">在线</view>
  13. </view>
  14. <view style="font-weight: bold;font-size: 30rpx;margin-top:20rpx">
  15. {{deviceInfo.deviceName}}
  16. </view>
  17. <view class="prop-text">
  18. <text class="text-left">所属用户:</text>
  19. <text class="text-right">{{sysDept.deptName}}</text>
  20. </view>
  21. <view class="prop-text">
  22. <text class="text-left">设备编号:</text>
  23. <text class="text-right">{{deviceInfo.serialNumber}}</text>
  24. </view>
  25. <view class="prop-text">
  26. <text class="text-left">二维码ID:</text>
  27. <text class="text-right">{{deviceInfo.qrcodeId}}</text>
  28. </view>
  29. <view class="prop-text">
  30. <text class="text-left">激活时间:</text>
  31. <text class="text-right">{{deviceInfo.activeTime}}</text>
  32. </view>
  33. <view class="prop-text">
  34. <text class="text-left">查看位置:</text>
  35. <view style="position: absolute;top:0px;left:120rpx">
  36. <u-icon name="map-fill" label="查看位置" color="#2979ff" size="20" labelSize="12"></u-icon>
  37. </view>
  38. </view>
  39. <view class="prop-card-area">
  40. <view class="prop-card">
  41. <view class="prop-card-top">{{ deviceInfo.rssi }}</view>
  42. <view class="prop-card-bottom">设备信号</view>
  43. </view>
  44. <view class="prop-card">
  45. <view class="prop-card-top">{{ timeobj.alltime }}</view>
  46. <view class="prop-card-bottom">累计时长</view>
  47. </view>
  48. <view class="prop-card">
  49. <view class="prop-card-top">{{ timeobj.avgtime }}</view>
  50. <view class="prop-card-bottom">平均时长</view>
  51. </view>
  52. </view>
  53. <view class="tab-area">
  54. <u-tabs lineWidth="80" :activeStyle="{ color: '#3E9CFC' }" :list="summary" keyName="tabName" @change="getDeviceStatus"></u-tabs>
  55. <view>
  56. <uni-row class="demo-uni-row">
  57. <uni-col :span="12">
  58. </uni-col>
  59. </uni-row>
  60. <uni-row class="demo-uni-row">
  61. <uni-col :span="12">
  62. </uni-col>
  63. </uni-row>
  64. <view class="prop-item">
  65. <view class="prop-item-left">开机</view>
  66. <view class="prop-item-right"> <u-switch inactiveColor="lightgray" activeColor="rgb(96,195,113)" v-model="power.value" :loading ="power.loading" @change="changeProp('PowerControl')"></u-switch>
  67. </view>
  68. </view>
  69. <view class="prop-item">
  70. <view class="prop-item-left">锁定</view>
  71. <view class="prop-item-right">
  72. <u-switch inactiveColor="lightgray" activeColor="rgb(96,195,113)" v-model="lock.value" :loading ="lock.loading" @change="changeProp('LockControl')"></u-switch>
  73. </view>
  74. </view>
  75. <view v-for="item in inputProp" v-if="checkCommonProp(item)">
  76. <view class="prop-item">
  77. <view class="prop-item-left">{{item.name}}</view>
  78. <view class="prop-item-right">
  79. <view v-if="item.type === 'integer'" style="width:240rpx;position: absolute;left: -260rpx;top: -10rpx;">
  80. <u-input placeholder="请输入整数" v-model="item.shadow">
  81. </u-input>
  82. </view>
  83. <view style="padding:0 10rpx;width:260rpx;position: absolute;left: -270rpx;top: -10rpx;" v-if="item.type === 'string'">
  84. <u-input placeholder="请输入字符串" v-model="item.shadow">
  85. </u-input>
  86. </view>
  87. <view style="padding:0 10rpx;width:260rpx;position: absolute;left: -270rpx;top: -10rpx;" v-if="item.type === 'array'">
  88. <u-input placeholder="请使用英文逗号分隔的字符串" v-model="item.shadow">
  89. </u-input>
  90. </view>
  91. <view style="padding:0 10rpx;position: absolute;left: -300rpx;top: -10rpx;" v-if="item.type === 'enum'">
  92. <u-cell customStyle="border:0px;" size="mini" @click="chooseItemData(item)" arrow-direction="left" v-if="item.text != null && item.text.length>0" :title="item.text">
  93. <u-icon slot="icon" size="12" name="arrow-down"></u-icon>
  94. </u-cell>
  95. <u-cell customStyle="border:0px;" size="mini" @click="chooseItemData(item)" arrow-direction="down" v-else title="请选择">
  96. <u-icon slot="icon" size="12" name="arrow-down"></u-icon>
  97. </u-cell>
  98. </view>
  99. <view class="item" style="padding-top:14rpx">
  100. <u-button v-if="deviceInfo.status==3"
  101. @tap="send(item)"
  102. text="发送"
  103. type="success"
  104. size="mini"
  105. ></u-button>
  106. <u-button v-if="deviceInfo.status!=3"
  107. @tap="send(item)"
  108. text="发送"
  109. type="info"
  110. size="mini"
  111. ></u-button>
  112. </view>
  113. </view>
  114. </view>
  115. </view>
  116. <view style="margin-top:20rpx;margin-left:20rpx">
  117. <u--text text="属性监控" style="margin-top:20px"></u--text>
  118. </view>
  119. <view class="prop-item" v-if="checkCommonProp(item)" v-for="item in deviceInfo.readOnlyList">
  120. <view class="prop-item-left">{{item.name}}</view>
  121. <view class="prop-item-right" style="top:0rpx;">
  122. <u-input v-if="checkItemValue(item)" placeholder="请输入字符串" disabled="" :value="item.shadow+' '+item.unit">
  123. </u-input>
  124. </view>
  125. </view>
  126. </view>
  127. </view>
  128. </view>
  129. <!-- <u&#45;&#45;form>-->
  130. <!-- <u-form-item style="border:0px"-->
  131. <!-- label="设备名称:"-->
  132. <!-- labelWidth="auto"-->
  133. <!-- :borderBottom="false"-->
  134. <!-- >-->
  135. <!-- <u&#45;&#45;input disabled-->
  136. <!-- placeholder="请选择分组"-->
  137. <!-- border="none"-->
  138. <!-- color="gray"-->
  139. <!-- disabledColor="white"-->
  140. <!-- v-model="deviceInfo.deviceName"-->
  141. <!-- ></u&#45;&#45;input>-->
  142. <!-- </u-form-item>-->
  143. <!-- <u-form-item style="border:0px"-->
  144. <!-- label="所属机构:"-->
  145. <!-- labelWidth="auto"-->
  146. <!-- :borderBottom="false"-->
  147. <!-- >-->
  148. <!-- <u&#45;&#45;input v-if="sysDept != null" disabled-->
  149. <!-- placeholder="请选择分组22"-->
  150. <!-- border="none"-->
  151. <!-- color="gray"-->
  152. <!-- disabledColor="white"-->
  153. <!-- :value="sysDept.deptName"-->
  154. <!-- ></u&#45;&#45;input>-->
  155. <!-- <u&#45;&#45;input v-else-if="deviceInfo.deptId == -1" disabled-->
  156. <!-- placeholder="请选择分组11"-->
  157. <!-- border="none"-->
  158. <!-- color="gray"-->
  159. <!-- disabledColor="white"-->
  160. <!-- value="已注销"-->
  161. <!-- ></u&#45;&#45;input>-->
  162. <!-- <u&#45;&#45;input v-else disabled-->
  163. <!-- placeholder="未绑定"-->
  164. <!-- border="none"-->
  165. <!-- color="gray"-->
  166. <!-- disabledColor="white"-->
  167. <!-- value="未绑定"-->
  168. <!-- ></u&#45;&#45;input>-->
  169. <!-- </u-form-item>-->
  170. <!-- <u-form-item style="border:0px"-->
  171. <!-- label="设备编号:"-->
  172. <!-- labelWidth="auto"-->
  173. <!-- :borderBottom="false"-->
  174. <!-- ref="item1"-->
  175. <!-- >-->
  176. <!-- <u&#45;&#45;input disabled-->
  177. <!-- border="none"-->
  178. <!-- color="gray"-->
  179. <!-- disabledColor="white"-->
  180. <!-- v-model="deviceInfo.serialNumber"-->
  181. <!-- ></u&#45;&#45;input>-->
  182. <!-- </u-form-item>-->
  183. <!-- <u-form-item style="border:0px"-->
  184. <!-- label="二维码ID:"-->
  185. <!-- labelWidth="auto"-->
  186. <!-- :borderBottom="false"-->
  187. <!-- ref="item1"-->
  188. <!-- >-->
  189. <!-- <u&#45;&#45;input disabled-->
  190. <!-- border="none"-->
  191. <!-- color="gray"-->
  192. <!-- disabledColor="white"-->
  193. <!-- v-model="deviceInfo.qrcodeId"-->
  194. <!-- ></u&#45;&#45;input>-->
  195. <!-- </u-form-item>-->
  196. <!-- <u-form-item style="border:0px"-->
  197. <!-- label="激活时间:"-->
  198. <!-- labelWidth="auto"-->
  199. <!-- :borderBottom="false"-->
  200. <!-- ref="item1"-->
  201. <!-- >-->
  202. <!-- <u&#45;&#45;input disabled-->
  203. <!-- border="none"-->
  204. <!-- color="gray"-->
  205. <!-- disabledColor="white"-->
  206. <!-- :value="deviceInfo.activeTime"-->
  207. <!-- ></u&#45;&#45;input>-->
  208. <!-- </u-form-item>-->
  209. <!-- <u-form-item style="border:0px"-->
  210. <!-- label="运行时长:"-->
  211. <!-- labelWidth="auto"-->
  212. <!-- :borderBottom="false"-->
  213. <!-- ref="item1"-->
  214. <!-- >-->
  215. <!-- <view style="width: 20%">-->
  216. <!-- <u-button @click="seeTime()" type="primary" size="mini" text="查看时长"></u-button>-->
  217. <!-- </view>-->
  218. <!-- </u-form-item>-->
  219. <!-- <u-form-item style="border:0px"-->
  220. <!-- label="位置信息:"-->
  221. <!-- labelWidth="auto"-->
  222. <!-- :borderBottom="false"-->
  223. <!-- ref="item1"-->
  224. <!-- >-->
  225. <!-- <view style="width: 20%">-->
  226. <!-- <u-button @click="openLocation(deviceInfo)" type="primary" size="mini" text="查看位置"></u-button>-->
  227. <!-- </view>-->
  228. <!-- </u-form-item>-->
  229. <!-- <u-form-item style="border:0px"-->
  230. <!-- label="设备信号:"-->
  231. <!-- labelWidth="auto"-->
  232. <!-- :borderBottom="false"-->
  233. <!-- >-->
  234. <!-- <u&#45;&#45;input disabled-->
  235. <!-- border="none"-->
  236. <!-- color="gray"-->
  237. <!-- disabledColor="white"-->
  238. <!-- :value="deviceInfo.rssi"-->
  239. <!-- ></u&#45;&#45;input>-->
  240. <!-- </u-form-item>-->
  241. <!-- <u-form-item v-if="deviceInfo.networkAddress != null" style="border:0px"-->
  242. <!-- label="设备网络:"-->
  243. <!-- labelWidth="auto"-->
  244. <!-- :borderBottom="false"-->
  245. <!-- ref="item1"-->
  246. <!-- >-->
  247. <!-- <u&#45;&#45;input disabled-->
  248. <!-- border="none"-->
  249. <!-- color="gray"-->
  250. <!-- disabledColor="white"-->
  251. <!-- :value="deviceInfo.networkAddress+'('+deviceInfo.networkIp+')'"-->
  252. <!-- ></u&#45;&#45;input>-->
  253. <!-- </u-form-item>-->
  254. <!-- <u-form-item style="border:0px"-->
  255. <!-- label="设备状态:"-->
  256. <!-- labelWidth="auto"-->
  257. <!-- :borderBottom="false"-->
  258. <!-- >-->
  259. <!-- <view style="width:90rpx">-->
  260. <!-- <u-tag v-if="deviceInfo.status === 4" text="离线" size="mini" type="info"></u-tag>-->
  261. <!-- <u-tag v-if="deviceInfo.status === 3" text="在线" size="mini" type="success"></u-tag>-->
  262. <!-- <u-tag v-if="deviceInfo.status === 2" text="禁用" size="mini" type="error"></u-tag>-->
  263. <!-- <u-tag v-if="deviceInfo.status === 1" text="未激活" size="mini" type="error"></u-tag>-->
  264. <!-- </view>-->
  265. <!-- </u-form-item>-->
  266. <!-- </u&#45;&#45;form>-->
  267. <!-- </view>-->
  268. <!-- <view class="text-area">-->
  269. <!-- <u-tabs :list="summary" keyName="tabName" @change="getDeviceStatus"></u-tabs>-->
  270. <!-- <view class="prop-container" style="background: white;padding:10px ">-->
  271. <!-- <u-form>-->
  272. <!-- <u-form-item style="border:0px;position: relative"-->
  273. <!-- label=" "-->
  274. <!-- labelWidth="auto"-->
  275. <!-- :borderBottom="false"-->
  276. <!-- >-->
  277. <!-- <uni-row class="demo-uni-row">-->
  278. <!-- <uni-col :span="12">-->
  279. <!-- 开机: <u-switch v-model="power.value" :loading ="power.loading" @change="changeProp('PowerControl')"></u-switch>-->
  280. <!-- </uni-col>-->
  281. <!-- <uni-col :span="12">-->
  282. <!-- 锁定: <u-switch v-model="lock.value" :loading ="lock.loading" @change="changeProp('LockControl')"></u-switch>-->
  283. <!-- </uni-col>-->
  284. <!-- </uni-row>-->
  285. <!-- </u-form-item>-->
  286. <!-- <u-line></u-line>-->
  287. <!-- <view>-->
  288. <!-- <uni-row class="demo-uni-row" v-if="checkCommonProp(item)" v-for="item in deviceInfo.readOnlyList">-->
  289. <!-- <uni-col :span="10">-->
  290. <!-- <view class="item">{{item.name}}</view>-->
  291. <!-- </uni-col>-->
  292. <!-- <uni-col :span="10">-->
  293. <!-- <view style="padding:0 10rpx">-->
  294. <!-- <u-input placeholder="请输入字符串" disabled="" :value="item.shadow+' '+item.unit">-->
  295. <!-- </u-input>-->
  296. <!-- </view>-->
  297. <!-- </uni-col>-->
  298. <!-- </uni-row>-->
  299. <!-- </view>-->
  300. <!-- </u-form>-->
  301. <!-- </view>-->
  302. <u-picker @cancel="show=null" :show="show!=null" :columns="columns" @confirm="confirmItemData" keyName="text"></u-picker>
  303. <u-modal @cancel="cancel" :show="showErrDlg" title="异常上报" :showCancelButton="true" @confirm="doReportError" >
  304. <view class="slot-content">
  305. <view style="margin:10px">
  306. <textarea auto-height ="true" v-model="errorMsg" placeholder="请输入异常内容" ></textarea>
  307. </view>
  308. </view>
  309. </u-modal>
  310. <!-- <u-modal :show="showTimeDlg" title="查看时长" @confirm="closeTime" >-->
  311. <!-- <view class="slot-content">-->
  312. <!-- <view v-if="timeobj!=null && deviceInfo.status == 3">本次运行时长:{{ timeobj.runtime }}</view>-->
  313. <!-- <view v-if="timeobj!=null ">累计时长:{{ timeobj.alltime }}</view>-->
  314. <!-- <view v-if="timeobj!=null ">平均每天运行时长:{{ timeobj.avgtime }}</view>-->
  315. <!-- </view>-->
  316. <!-- </u-modal>-->
  317. </view>
  318. </view>
  319. </template>
  320. <script>
  321. import { getDetail,getDeviceStatus,cacheJsonThingsModel,reportError ,getDeviceRunTime} from '@/api/device/device.js'
  322. import UButton from "../../uni_modules/uview-ui/components/u-button/u-button";
  323. import UForm from "../../uni_modules/uview-ui/components/u--form/u--form";
  324. import UInput from "../../uni_modules/uview-ui/components/u--input/u--input";
  325. import UImage from "../../uni_modules/uview-ui/components/u--image/u--image";
  326. export default {
  327. components: {UImage, UInput, UForm, UButton},
  328. data(){
  329. return {
  330. modelKey:['PowerControl','LockControl'],
  331. power:{
  332. loading:true,
  333. value:0,
  334. },
  335. lock:{
  336. loading:true,
  337. value:0,
  338. },
  339. showTimeDlg:false,
  340. showErrDlg:null,
  341. errorMsg:"asdasdasdasd",
  342. show:null,
  343. value:"",
  344. deviceInfo:{},
  345. id:0,
  346. summary:[],
  347. activeName:0,
  348. childId:"",
  349. oneToMul:false,
  350. inputProp:[],
  351. watchProp:[],
  352. columns:[],
  353. location:{},
  354. sysDept:null,
  355. timeobj:{alltime:0,avgtime:0},
  356. }
  357. },
  358. onLoad: function(opt) {
  359. this.id = opt.id;
  360. this.id = 61;
  361. this.connectMqtt();
  362. this.getDetail();
  363. },
  364. destroyed() {
  365. // 取消订阅主题
  366. this.mqttUnSubscribe(this.deviceInfo);
  367. },
  368. methods:{
  369. checkItemValue(item){
  370. if(!item.shadow){
  371. item.shadow = 0;
  372. }
  373. if(!item.unit){
  374. item.unit = "";
  375. }
  376. return true;
  377. },
  378. changeProp(key){
  379. let item = null;
  380. let obj = null;
  381. if(key === "LockControl"){
  382. item = this.lock;
  383. }else if(key === "PowerControl"){
  384. item = this.power;
  385. }
  386. let value = item.value;
  387. obj = item.item;
  388. if(value){
  389. obj.value = 1;
  390. obj.shadow = 1;
  391. }else{
  392. obj.value = 0;
  393. obj.shadow = 0;
  394. }
  395. this.publishThingsModel(this.deviceInfo,obj);
  396. },
  397. checkCommonProp(item){
  398. let id =item.id;
  399. let isCommonKey = this.modelKey.some(res=>{
  400. return id === res;
  401. })
  402. return !isCommonKey;
  403. },
  404. getRunTime(){
  405. let self = this;
  406. getDeviceRunTime(this.id).then(res=>{
  407. self.timeobj = res.data;
  408. if(self.timeobj.avgtime == ""){
  409. self.timeobj.avgtime = 0;
  410. }
  411. if(self.timeobj.alltime == ""){
  412. self.timeobj.alltime = 0;
  413. }
  414. })
  415. },
  416. seeTime(){
  417. this.showTimeDlg = true;
  418. this.getRunTime();
  419. },
  420. closeTime(){
  421. this.showTimeDlg = false;
  422. },
  423. cancel(){
  424. this.showErrDlg = false;
  425. },
  426. reportError(){
  427. this.showErrDlg = true;
  428. },
  429. doReportError(){
  430. if(!this.errorMsg){
  431. this.$modal.showToast('异常信息不能为空')
  432. }else{
  433. let self = this;
  434. let errObj = {};
  435. errObj.deviceId = this.deviceInfo.deviceId;
  436. errObj.deviceName = this.deviceInfo.deviceName
  437. errObj.desc = this.errorMsg;
  438. errObj.deptId= this.deviceInfo.deptId;
  439. reportError(errObj).then(res=>{
  440. self.$modal.showToast(res.msg)
  441. self.cancel();
  442. })
  443. }
  444. },
  445. openLocation(){
  446. uni.openLocation({
  447. latitude: this.location.latitude,
  448. longitude: this.location.longitude,
  449. success: function () {
  450. console.log('success');
  451. }
  452. });
  453. },
  454. confirmItemData(e){
  455. let data = e.value[0];
  456. this.show.text = data.text;
  457. this.show.shadow=data.value;
  458. this.show = null;
  459. console.log(data);
  460. },
  461. send(item){
  462. if(this.deviceInfo.status != 3){
  463. uni.showToast({
  464. title:"设备暂未上线",
  465. icon:"error"
  466. })
  467. return;
  468. }
  469. if(!item.shadow){
  470. uni.showToast({
  471. title:"数据不能为空",
  472. icon:"error"
  473. })
  474. return;
  475. }
  476. this.publishThingsModel(this.deviceInfo,item)
  477. },
  478. /** 更新设备状态 */
  479. updateDeviceStatus(device) {
  480. },
  481. chooseItemData(data){
  482. if(this.deviceInfo.status != 3){
  483. uni.showToast({
  484. title:"设备暂未上线",
  485. icon:"error"
  486. })
  487. return;
  488. }
  489. this.columns = [data.enumList];
  490. this.show =data;
  491. },
  492. getDetail(){
  493. let self = this;
  494. getDetail(this.id).then(res=>{
  495. self.deviceInfo = res.data;
  496. self.location = {
  497. latitude: self.deviceInfo.latitude,
  498. longitude: self.deviceInfo.longitude};
  499. self.sysDept = self.deviceInfo.sysDept;
  500. self.parseSummay(res.data.summary)
  501. self.mqttSubscribe(res.data);
  502. self.getDeviceStatus();
  503. self.seeTime();
  504. });
  505. },
  506. getDeviceStatus(e){
  507. let self = this;
  508. if(!e){
  509. e = {index:0};
  510. }
  511. this.activeName = e.index;
  512. this.childId = this.summary[this.activeName].id;
  513. getDeviceStatus(this.id,this.childId).then(res=>{
  514. let data =res.data;
  515. this.deviceInfo = data;
  516. self.parseStatusData(data)
  517. });
  518. },
  519. parseEnumList(){
  520. let enumList = this.deviceInfo.enumList;
  521. for (let enumListElement of enumList) {
  522. let id = enumListElement.id;
  523. let isCommonKey = this.modelKey.some(res=>{
  524. return id === res;
  525. })
  526. if(isCommonKey){
  527. if(id.indexOf("LockControl") !=-1){
  528. let shadow = enumListElement.shadow;
  529. this.lock.item = enumListElement;
  530. if(shadow == 1){
  531. this.lock.value = true;
  532. this.lock.loading = false;
  533. }else if(shadow == 0){
  534. this.lock.value = false;
  535. this.lock.loading = false;
  536. }else{
  537. this.lock.loading = true;
  538. }
  539. }
  540. if(id.indexOf("PowerControl") !=-1){
  541. let shadow = enumListElement.shadow;
  542. this.power.item = enumListElement;
  543. if(shadow == 1){
  544. this.power.value = true;
  545. this.power.loading = false;
  546. }else if(shadow == 0){
  547. this.power.value = false;
  548. this.power.loading = false;
  549. }else{
  550. this.power.loading = true;
  551. }
  552. }
  553. }
  554. let shadow = enumListElement.shadow
  555. let valueList = enumListElement.enumList;
  556. for (let valueObj of valueList){
  557. if(valueObj.value == shadow){
  558. enumListElement.text = valueObj.text;
  559. }
  560. }
  561. }
  562. },
  563. parseStatusData(data){
  564. let arr = [];
  565. let arrayList = data.arrayList;
  566. arr = arr.concat(arrayList);
  567. let enumList = data.enumList;
  568. arr = arr.concat(enumList);
  569. let integerList = data.integerList;
  570. arr = arr.concat(integerList);
  571. let stringList = data.stringList;
  572. arr = arr.concat(stringList);
  573. this.inputProp = arr;
  574. let readOnlyList = data.readOnlyList;
  575. this.watchProp = readOnlyList;
  576. this.parseEnumList();
  577. },
  578. parseSummay(summary){
  579. let self = this;
  580. if(!summary){
  581. summary = "";
  582. }
  583. if(summary.length>0){
  584. this.summary = JSON.parse(summary);
  585. if(self.summary.length>0){
  586. this.oneToMul = true;
  587. }
  588. for (let i = 0; i < self.summary.length; i++) {
  589. self.summary[i].tabName = self.summary[i].id+"_"+self.summary[i].name
  590. }
  591. let childId = "";
  592. if(this.oneToMul){
  593. let info = self.summary[self.activeName];
  594. childId = info.id;
  595. }
  596. this.childId = childId;
  597. }else{
  598. this.summary = [{tabName:"详情查看"}]
  599. }
  600. },
  601. goDeviceDetail(id){
  602. uni.navigateTo({
  603. url: '/pages/device/detail/detail?id='+id
  604. });
  605. },
  606. async connectMqtt() {
  607. if (this.$mqttTool.client == null) {
  608. await this.$mqttTool.connect(this.vuex_token);
  609. }
  610. this.mqttCallback();
  611. },
  612. /** Mqtt订阅主题 */
  613. mqttSubscribe(device) {
  614. // 订阅当前设备状态和实时监测
  615. let topicStatus = '/' + device.productId + '/' + device.serialNumber + '/status/post';
  616. let topicProperty = '/' + device.productId + '/' + device.serialNumber + '/property/post';
  617. let topicFunction = '/' + device.productId + '/' + device.serialNumber + '/function/post';
  618. let topics = [];
  619. topics.push(topicStatus);
  620. topics.push(topicProperty);
  621. topics.push(topicFunction);
  622. this.$mqttTool.subscribe(topics);
  623. },
  624. /** Mqtt取消订阅主题 */
  625. mqttUnSubscribe(device) {
  626. // 订阅当前设备状态和实时监测
  627. let topicStatus = '/' + device.productId + '/' + device.serialNumber + '/status/post';
  628. let topicProperty = '/' + device.productId + '/' + device.serialNumber + '/property/post';
  629. let topicFunction = '/' + device.productId + '/' + device.serialNumber + '/function/post';
  630. let topics = [];
  631. topics.push(topicStatus);
  632. topics.push(topicProperty);
  633. topics.push(topicFunction);
  634. console.log('取消订阅', topics);
  635. this.$mqttTool.unsubscribe(topics);
  636. },
  637. /* Mqtt回调处理 */
  638. mqttCallback() {
  639. this.$mqttTool.client.on('message', (topic, message, buffer) => {
  640. let topics = topic.split('/');
  641. let productId = topics[1];
  642. let deviceNum = topics[2];
  643. console.log('接收到内容:'+message);
  644. message = JSON.parse(message.toString());
  645. if (topics[3] == 'status') {
  646. console.log('接收到【设备状态-运行】主题:', topic);
  647. console.log('接收到【设备状态-运行】内容:', message);
  648. // 更新列表中设备的状态
  649. if (this.deviceInfo.serialNumber == deviceNum) {
  650. this.deviceInfo.status = message.status;
  651. this.deviceInfo.isShadow = message.isShadow;
  652. this.deviceInfo.rssi = message.rssi;
  653. this.updateDeviceStatus(this.deviceInfo);
  654. }
  655. }
  656. if (topics[3] == 'property' || topics[3] == 'function') {
  657. console.log('接收到【物模型】主题:', topic);
  658. console.log('接收到【物模型】内容:', message);
  659. if(this.oneToMul){
  660. let curTabId = this.summary[this.activeName].id;
  661. let msg = [];
  662. for (let i = 0; i < message.length; i++) {
  663. let curMsg = message[i];
  664. let id = curMsg.id;
  665. let ids = id.split("_");
  666. let value = curMsg.value;
  667. if(ids.length == 2){
  668. if(curTabId == ids[1]){
  669. msg.push({id:ids[0],value:value});
  670. }
  671. }
  672. }
  673. message = msg;
  674. }
  675. // 更新列表中设备的属性
  676. if (this.deviceInfo.serialNumber == deviceNum) {
  677. for (let j = 0; j < message.length; j++) {
  678. let isComplete = false;
  679. // 布尔类型
  680. for (let k = 0; k < this.deviceInfo.boolList.length && !isComplete; k++) {
  681. if (this.deviceInfo.boolList[k].id == message[j].id) {
  682. this.deviceInfo.boolList[k].shadow = message[j].value;
  683. isComplete = true;
  684. break;
  685. }
  686. }
  687. // 枚举类型
  688. for (let k = 0; k < this.deviceInfo.enumList.length && !isComplete; k++) {
  689. if (this.deviceInfo.enumList[k].id == message[j].id) {
  690. this.deviceInfo.enumList[k].shadow = message[j].value;
  691. isComplete = true;
  692. break;
  693. }
  694. }
  695. // 字符串类型
  696. for (let k = 0; k < this.deviceInfo.stringList.length && !isComplete; k++) {
  697. if (this.deviceInfo.stringList[k].id == message[j].id) {
  698. this.deviceInfo.stringList[k].shadow = message[j].value;
  699. isComplete = true;
  700. break;
  701. }
  702. }
  703. // 数组类型
  704. for (let k = 0; k < this.deviceInfo.arrayList.length && !isComplete; k++) {
  705. if (this.deviceInfo.arrayList[k].id == message[j].id) {
  706. this.deviceInfo.arrayList[k].shadow = message[j].value;
  707. isComplete = true;
  708. break;
  709. }
  710. }
  711. // 整数类型
  712. for (let k = 0; k < this.deviceInfo.integerList.length && !isComplete; k++) {
  713. if (this.deviceInfo.integerList[k].id == message[j].id) {
  714. this.deviceInfo.integerList[k].shadow = message[j].value;
  715. isComplete = true;
  716. break;
  717. }
  718. }
  719. // 小数类型
  720. for (let k = 0; k < this.deviceInfo.decimalList.length && !isComplete; k++) {
  721. if (this.deviceInfo.decimalList[k].id == message[j].id) {
  722. this.deviceInfo.decimalList[k].shadow = message[j].value;
  723. isComplete = true;
  724. break;
  725. }
  726. }
  727. // 监测数据
  728. for (let k = 0; k < this.deviceInfo.readOnlyList.length && !isComplete; k++) {
  729. if (this.deviceInfo.readOnlyList[k].id == message[j].id) {
  730. this.deviceInfo.readOnlyList[k].shadow = message[j].value;
  731. // 更新图表
  732. // for (let m = 0; m < this.monitorChart.length; m++) {
  733. // if (message[j].id == this.monitorChart[m].data.id) {
  734. // let data = [{
  735. // value: message[j].value,
  736. // name: this.monitorChart[m].data.name
  737. // }];
  738. // this.monitorChart[m].chart.setOption({
  739. // series: [{
  740. // data: data
  741. // }]
  742. // });
  743. // break;
  744. // }
  745. // }
  746. isComplete = true;
  747. break;
  748. }
  749. }
  750. }
  751. this.parseEnumList();
  752. }
  753. }
  754. });
  755. },
  756. /** 发布物模型 类型(1=属性,2=功能) */
  757. publishThingsModel(device, model) {
  758. // 获取缓存的Json物模型
  759. cacheJsonThingsModel(device.productId).then(response => {
  760. let thingsModel = JSON.parse(response.data);
  761. let type = 0;
  762. for (let i = 0; i < thingsModel.functions.length; i++) {
  763. if (model.id == thingsModel.functions[i].id) {
  764. type = 2;
  765. break;
  766. }
  767. }
  768. if (type == 0) {
  769. for (let i = 0; i < thingsModel.properties.length; i++) {
  770. if (model.id == thingsModel.properties[i].id) {
  771. type = 1;
  772. break;
  773. }
  774. }
  775. }
  776. if (type != 0) {
  777. this.mqttPublish(type, device, model);
  778. }
  779. });
  780. },
  781. notifyError(res){
  782. uni.showToast({
  783. title:res,
  784. icon:"error"
  785. })
  786. },
  787. notifySuccess(res){
  788. uni.showToast({
  789. title:res,
  790. icon:"success"
  791. })
  792. },
  793. /**
  794. * Mqtt发布消息
  795. * @type 类型(1=属性,2=功能,3=OTA升级,4=实时监测)
  796. * @device 设备
  797. * @model 物模型
  798. * */
  799. mqttPublish(type, device, model) {
  800. let topic = "";
  801. let message = ""
  802. let oneToMul = false;
  803. if(this.summary.length>0){
  804. oneToMul = true;
  805. }
  806. let modelId = model.id;
  807. if(oneToMul){
  808. let info = this.summary[this.activeName];
  809. let childId = info.id;
  810. modelId = modelId+"_"+childId;
  811. }
  812. if (type == 1) {
  813. if (device.status == 3) {
  814. // 属性,在线模式
  815. topic = "/" + device.productId + "/" + device.serialNumber + "/property-online/get";
  816. } else if (device.isShadow) {
  817. // 属性,离线模式
  818. topic = "/" + device.productId + "/" + device.serialNumber + "/property-offline/post";
  819. }
  820. message = '[{"id":"' + modelId + '","value":"' + model.shadow + '"}]';
  821. } else if (type == 2) {
  822. if (device.status == 3) {
  823. // 功能,在线模式
  824. topic = "/" + device.productId + "/" + device.serialNumber + "/function-online/get";
  825. } else if (device.isShadow) {
  826. // 功能,离线模式
  827. topic = "/" + device.productId + "/" + device.serialNumber + "/function-offline/post";
  828. }
  829. message = '[{"id":"' + modelId + '","value":"' + model.shadow + '"}]';
  830. } else if (type == 3) {
  831. // OTA升级
  832. topic = "/" + device.productId + "/" + device.serialNumber + "/ota/get";
  833. message = '{"version":' + this.firmware.version + ',"downloadUrl":"' + this.getDownloadUrl(this.firmware.filePath) + '"}';
  834. } else {
  835. return;
  836. }
  837. if (topic != "") {
  838. // 发布
  839. this.$mqttTool.publish(topic, message, model.name).then(res => {
  840. this.notifySuccess(res);
  841. }).catch(res => {
  842. this.notifyError(res);
  843. });
  844. }
  845. },
  846. }
  847. }
  848. </script>
  849. <style>
  850. .header{
  851. width: 100%;
  852. background: white;
  853. padding:0px 20rpx;
  854. position: relative;
  855. }
  856. .content {
  857. display: flex;
  858. align-items: center;
  859. justify-content: center;
  860. }
  861. .logo {
  862. height: 200rpx;
  863. width: 200rpx;
  864. margin-top: 200rpx;
  865. margin-left: auto;
  866. margin-right: auto;
  867. margin-bottom: 50rpx;
  868. }
  869. .text-area {
  870. margin:10px;
  871. padding-bottom: 10px;
  872. justify-content: center;
  873. width: 100%;
  874. }
  875. .grid-text {
  876. font-size: 14px;
  877. color: #909399;
  878. padding: 10rpx 0 20rpx 0rpx;
  879. /* #ifndef APP-PLUS */
  880. box-sizing: border-box;
  881. /* #endif */
  882. }
  883. .title {
  884. font-size: 36rpx;
  885. color: #8f8f94;
  886. }
  887. .item{
  888. height: 80rpx;
  889. line-height: 80rpx;
  890. }
  891. .bg{
  892. position: relative;
  893. }
  894. .text-left{
  895. color: #8A92A5;
  896. }
  897. .text-right{
  898. color: #545454;
  899. }
  900. .prop-text{
  901. position: relative;
  902. margin:20rpx 0;
  903. font-size: 26rpx;
  904. }
  905. .prop-card-area{
  906. }
  907. .prop-card{
  908. width: 29%;
  909. height: 100rpx;
  910. text-align: center;
  911. display: inline-block;
  912. background: #F5FCFF;
  913. box-shadow: 0px 9rpx 8rpx 0px rgba(0,0,0,0.09);
  914. border-radius: 8rpx;
  915. margin:0px 15rpx;
  916. line-height: 48rpx;
  917. }
  918. .prop-card-top{
  919. color: #3E9CFC;
  920. }
  921. .prop-card-bottom{
  922. color: #8A92A5;
  923. }
  924. .tab-area {
  925. background: white;
  926. position: absolute;
  927. left: 0px;
  928. right: 0px;
  929. top:480rpx;
  930. bottom:-20px;
  931. min-height: 200rpx;
  932. box-shadow: 0rpx 5rpx 27rpx 0rpx rgba(195, 195, 195, 0.4);
  933. border-radius: 40rpx;
  934. overflow-y: auto;
  935. padding-bottom:80rpx;
  936. }
  937. .prop-item{
  938. justify-content:center;
  939. position: relative;
  940. border-bottom: 1px solid lightgray;
  941. height: 80rpx;
  942. margin:0 20rpx;
  943. }
  944. .prop-item-left{
  945. position: absolute;
  946. left:10rpx;
  947. top:22rpx;
  948. color: #545454;
  949. }
  950. .prop-item-right{
  951. position: absolute;
  952. right:10rpx;
  953. top:10rpx;
  954. }
  955. </style>