Browse Source

refactor: sensor

Casper Dai 3 years ago
parent
commit
801b2609c7

+ 1 - 1
package.json

@@ -14,6 +14,7 @@
     "app-info-parser": "^1.1.3",
     "axios": "^0.24.0",
     "core-js": "^3.6.5",
+    "crypto-js": "^4.1.1",
     "dom-to-image": "^2.6.0",
     "echarts": "^5.3.1",
     "element-ui": "^2.15.6",
@@ -44,7 +45,6 @@
     "chokidar": "^3.5.2",
     "commitizen": "^4.2.4",
     "conventional-changelog-cli": "^2.1.1",
-    "crypto-js": "^4.1.1",
     "cz-conventional-changelog": "^3.3.0",
     "eslint": "^8.17.0",
     "eslint-plugin-vue": "^8.0.3",

+ 60 - 11
src/api/external.js

@@ -49,15 +49,8 @@ export function getBoundThirdPartyDevices (deviceId, chain = false) {
   return request({
     url: `/device/bind/${deviceId}`,
     method: 'GET',
-    params: { chain }
-  })
-}
-
-export function getSensors (options) {
-  return request({
-    url: '/device/sensorType',
-    method: 'GET',
-    ...options
+    params: { chain },
+    custom: true
   })
 }
 
@@ -263,11 +256,14 @@ export function getPLCs (query) {
   })
 }
 
-export function addPLC (data) {
+export function addPLC (gatewayId, plc) {
   return add({
     url: '/device/thirdplc/add',
     method: 'POST',
-    data
+    data: {
+      gatewayId,
+      ...plc
+    }
   })
 }
 
@@ -296,3 +292,56 @@ export function getBoundPLCs (deviceId) {
     method: 'GET'
   }).then(({ data }) => data)
 }
+
+export function getSensors (gatewayId, options) {
+  return request({
+    url: '/device/thirdPartyGateway/listSensor',
+    method: 'GET',
+    params: { gatewayId },
+    ...options
+  })
+}
+
+export function addSensor (gatewayId, sensor) {
+  return add({
+    url: '/device/thirdPartyGateway/addSensor',
+    method: 'POST',
+    data: {
+      gatewayId,
+      ...sensor
+    }
+  })
+}
+
+export function updateSensor (data) {
+  return update({
+    url: '/device/thirdPartyGateway/updateSensor',
+    method: 'PUT',
+    data
+  })
+}
+
+export function deleteSensor ({ id, name }) {
+  return del({
+    url: '/device/thirdPartyGateway/deleteSensor',
+    method: 'DELETE',
+    params: { sensorId: id }
+  }, name)
+}
+
+export function getSensorRecords (params, options) {
+  return request({
+    url: '/device/thirdPartyGateway/sensorRecord',
+    method: 'GET',
+    params,
+    ...options
+  })
+}
+
+export function getSensorRecordsForOld (options) {
+  return request({
+    url: '/device/sensorType',
+    method: 'GET',
+    ...options
+  })
+}

+ 7 - 0
src/constant.js

@@ -130,3 +130,10 @@ export const AlarmStrategies = [
   { key: 'wechat', label: '微信' },
   { key: 'wechatApplet', label: '小程序' }
 ]
+
+export const Sensor = {
+  SMOKE: 0,
+  TEMPERATURE: 1,
+  LIGHT: 2,
+  FLOODING: 3
+}

+ 68 - 19
src/views/device/detail/components/DeviceExternal/external/Gateway/index.vue

@@ -50,6 +50,43 @@
             </div>
           </div>
         </div>
+        <div class="c-sibling-item--v far c-info">
+          <div class="l-flex--row has-bottom-padding u-bold">传感器信息</div>
+          <warning
+            v-if="sensorOptions.error"
+            @click="getSensors"
+          />
+          <div v-else-if="sensorOptions.loading">
+            <i class="el-icon el-icon-loading" />
+          </div>
+          <div
+            v-else-if="sensorOptions.list.length === 0"
+            class="u-color--info"
+          >
+            暂未绑定
+          </div>
+          <div
+            v-for="sensor in sensorOptions.list"
+            :key="sensor.id"
+            class="l-flex--row c-info__block"
+          >
+            <div class="l-flex--row l-flex__fill c-info__item">
+              <div class="l-flex__none c-info__title">名称</div>
+              <auto-text
+                class="l-flex__fill c-info__value"
+                :text="sensor.name"
+              />
+            </div>
+            <div class="l-flex--row l-flex__fill c-info__item">
+              <div class="l-flex__none c-info__title">标识</div>
+              <div class="l-flex__fill c-info__value">{{ sensor.identifier }}</div>
+            </div>
+            <div class="l-flex--row l-flex__fill c-info__item">
+              <div class="l-flex__none c-info__title">类型</div>
+              <div class="l-flex__fill c-info__value">{{ sensor.type }}</div>
+            </div>
+          </div>
+        </div>
       </template>
     </template>
   </div>
@@ -58,7 +95,8 @@
 <script>
 import {
   getGateway,
-  getBoundPLCs
+  getBoundPLCs,
+  getSensors
 } from '@/api/external'
 
 export default {
@@ -73,7 +111,12 @@ export default {
     return {
       loading: false,
       error: false,
-      info: null
+      info: null,
+      sensorOptions: {
+        list: [],
+        loading: false,
+        error: false
+      }
     }
   },
   computed: {
@@ -88,29 +131,15 @@ export default {
     this.getInfo()
   },
   methods: {
-    getInfo (type) {
+    getInfo () {
       if (this.loading) {
         return
       }
       this.loading = true
       this.error = false
 
-      let arr
-      if (this.info && type) {
-        switch (type) {
-          case 'PLC':
-            arr = [Promise.resolve(this.info.gateway), this.getBoundPLCs()]
-            break
-          default:
-            arr = [this.getGateway(), Promise.resolve(this.info.plcs)]
-            break
-        }
-      } else {
-        arr = [this.getGateway(), this.getBoundPLCs()]
-      }
-
       this.info = null
-      Promise.all(arr).then(
+      Promise.all([this.getGateway(), this.getBoundPLCs()]).then(
         data => {
           this.info = {
             gateway: data[0],
@@ -118,10 +147,13 @@ export default {
           }
         },
         () => {
-          this.error = false
+          this.error = true
         }
       ).finally(() => {
         this.loading = false
+        if (this.gateway) {
+          this.getSensors()
+        }
       })
     },
     getGateway () {
@@ -129,6 +161,23 @@ export default {
     },
     getBoundPLCs () {
       return getBoundPLCs(this.device.id)
+    },
+    getSensors () {
+      this.sensorOptions.loading = true
+      this.sensorOptions.error = false
+      getSensors(this.gateway.id).then(
+        ({ data }) => {
+          this.sensorOptions.list = data.map(sensor => {
+            sensor.type = ['烟雾', '温度', '光照', '水浸'][sensor.sensorType]
+            return sensor
+          })
+        },
+        () => {
+          this.sensorOptions.error = true
+        }
+      ).finally(() => {
+        this.sensorOptions.loading = false
+      })
     }
   }
 }

+ 2 - 2
src/views/device/detail/monitor.js

@@ -1,4 +1,4 @@
-import { getSensors } from '@/api/external'
+import { getSensorRecordsForOld } from '@/api/external'
 import {
   publish,
   subscribe,
@@ -303,7 +303,7 @@ export function stopSensor () {
 }
 
 function updateSensors (inst) {
-  inst.running && getSensors({ custom: true }).then(({ data }) => {
+  inst.running && getSensorRecordsForOld({ custom: true }).then(({ data }) => {
     inst.running && onUpdate(inst, data)
     return 5000
   }, () => 2000).then(delay => {

+ 2 - 6
src/views/external/gateway/PLC.vue

@@ -20,8 +20,7 @@
         <span class="c-grid-form__label required">地址</span>
         <el-input
           v-model.trim="plc.identifier"
-          placeholder="最多50个字符"
-          maxlength="50"
+          placeholder="PLC网络地址"
           clearable
         />
         <span class="c-grid-form__label">备注</span>
@@ -119,10 +118,7 @@ export default {
       }
     },
     onConfirmAdd (plc, done) {
-      addPLC({
-        gatewayId: this.gateway.id,
-        ...plc
-      }).then(() => {
+      addPLC(this.gateway.id, { ...plc }).then(() => {
         done()
         this.$refs.table.resetCondition()
       })

+ 148 - 0
src/views/external/gateway/Sensor.vue

@@ -0,0 +1,148 @@
+<template>
+  <schema-table
+    ref="table"
+    :schema="schema"
+  >
+    <confirm-dialog
+      ref="editDialog"
+      :title="dialogTitle"
+      :append-to-body="true"
+      @confirm="onConfirm"
+    >
+      <div class="c-grid-form u-align-self--center">
+        <span class="c-grid-form__label required">名称</span>
+        <el-input
+          v-model.trim="sensor.name"
+          placeholder="最多50个字符"
+          maxlength="50"
+          clearable
+        />
+        <span class="c-grid-form__label required">标识</span>
+        <el-input
+          v-model.trim="sensor.identifier"
+          placeholder="最多50个字符"
+          maxlength="50"
+          :disabled="!isAdd"
+          clearable
+        />
+        <span class="c-grid-form__label required">类型</span>
+        <schema-select
+          v-model="sensor.sensorType"
+          :schema="sensorTypeOptionsSchema"
+          :disabled="!isAdd"
+        />
+      </div>
+    </confirm-dialog>
+  </schema-table>
+</template>
+
+<script>
+import {
+  getSensors,
+  addSensor,
+  updateSensor,
+  deleteSensor
+} from '@/api/external'
+import { Sensor } from '@/constant'
+
+export default {
+  name: 'SensorList',
+  props: {
+    gateway: {
+      type: Object,
+      required: true
+    }
+  },
+  data () {
+    return {
+      sensor: {},
+      sensorTypeOptionsSchema: {
+        options: [
+          { value: Sensor.SMOKE, label: '烟雾' },
+          { value: Sensor.TEMPERATURE, label: '温度' },
+          { value: Sensor.LIGHT, label: '光照' },
+          { value: Sensor.FLOODING, label: '水浸' }
+        ]
+      },
+      schema: {
+        list: this.getSensors,
+        buttons: [
+          { type: 'add', on: this.onAdd }
+        ],
+        cols: [
+          { prop: 'name', label: '名称' },
+          { prop: 'identifier', label: '标识' },
+          { prop: 'sensorType', label: '类型', render: ({ sensorType }) => ['烟雾', '温度', '光照', '水浸'][sensorType] },
+          { type: 'invoke', render: [
+            { label: '编辑', on: this.onEdit },
+            { label: '删除', on: this.onDel }
+          ] }
+        ]
+      }
+    }
+  },
+  computed: {
+    isAdd () {
+      return !this.sensor.id
+    },
+    dialogTitle () {
+      return this.isAdd ? '新增传感器' : '编辑传感器'
+    }
+  },
+  methods: {
+    getSensors () {
+      return getSensors(this.gateway.id)
+    },
+    onAdd () {
+      this.sensor = {
+        name: '',
+        identifier: '',
+        sensorType: Sensor.TEMPERATURE
+      }
+      this.$refs.editDialog.show()
+    },
+    onEdit ({ id, gatewayId, name, identifier, sensorType }) {
+      this.sensor = { id, gatewayId, name, identifier, sensorType }
+      this.$refs.editDialog.show()
+    },
+    onConfirm (done) {
+      if (!this.sensor.name) {
+        this.$message({
+          type: 'warning',
+          message: '请填写传感器名称'
+        })
+        return
+      }
+      if (!this.sensor.identifier) {
+        this.$message({
+          type: 'warning',
+          message: '请填写传感器标识'
+        })
+        return
+      }
+      if (this.isAdd) {
+        this.onConfirmAdd(this.sensor, done)
+      } else {
+        this.onConfirmEdit(this.sensor, done)
+      }
+    },
+    onConfirmAdd (sensor, done) {
+      addSensor(this.gateway.id, { ...sensor }).then(() => {
+        done()
+        this.$refs.table.resetCondition()
+      })
+    },
+    onConfirmEdit (sensor, done) {
+      updateSensor(sensor).then(() => {
+        done()
+        this.$refs.table.pageTo()
+      })
+    },
+    onDel (sensor) {
+      deleteSensor(sensor).then(() => {
+        this.$refs.table.decrease(1)
+      })
+    }
+  }
+}
+</script>

+ 43 - 12
src/views/external/gateway/index.vue

@@ -25,8 +25,7 @@
         <span class="c-grid-form__label required">地址</span>
         <el-input
           v-model.trim="gateway.ip"
-          placeholder="最多50个字符"
-          maxlength="50"
+          placeholder="网关网络地址"
           clearable
         />
         <span class="c-grid-form__label">备注</span>
@@ -40,15 +39,22 @@
       </div>
     </confirm-dialog>
     <el-dialog
-      :visible.sync="showPlc"
-      title="PLC"
+      :visible.sync="showSubDialog"
+      :title="subDialogTitle"
       custom-class="c-dialog"
       :close-on-click-modal="false"
+      @close="onCloseSubDialog"
     >
-      <plc
-        v-if="showPlc"
-        :gateway="gateway"
-      />
+      <template v-if="showSubDialog">
+        <plc
+          v-if="showPLC"
+          :gateway="gateway"
+        />
+        <sensor
+          v-if="showSensor"
+          :gateway="gateway"
+        />
+      </template>
     </el-dialog>
   </wrapper>
 </template>
@@ -61,11 +67,13 @@ import {
   deleteGateway
 } from '@/api/external'
 import PLC from './PLC'
+import Sensor from './Sensor'
 
 export default {
   name: 'GatewayList',
   components: {
-    plc: PLC
+    plc: PLC,
+    Sensor
   },
   data () {
     return {
@@ -79,19 +87,32 @@ export default {
           { prop: 'name', label: '名称' },
           { prop: 'ip', label: '地址' },
           { prop: 'remark', label: '备注' },
-          { type: 'invoke', width: 160, render: [
+          { type: 'invoke', width: 200, render: [
             { label: '编辑', on: this.onEdit },
             { label: 'PLC', on: this.onEditPLC },
+            { label: '传感器', on: this.onEditSensor },
             { label: '删除', on: this.onDel }
           ] }
         ]
       },
-      showPlc: false
+      showSubDialog: false,
+      showPLC: false,
+      showSensor: false
     }
   },
   computed: {
     dialogTitle () {
       return this.gateway.id ? '编辑网关' : '新增网关'
+    },
+    subDialogTitle () {
+      switch (true) {
+        case this.showPLC:
+          return 'PLC'
+        case this.showSensor:
+          return '传感器'
+        default:
+          return ' '
+      }
     }
   },
   methods: {
@@ -150,7 +171,17 @@ export default {
     },
     onEditPLC (gateway) {
       this.gateway = gateway
-      this.showPlc = true
+      this.showPLC = true
+      this.showSubDialog = true
+    },
+    onEditSensor (gateway) {
+      this.gateway = gateway
+      this.showSensor = true
+      this.showSubDialog = true
+    },
+    onCloseSubDialog () {
+      this.showPLC = false
+      this.showSensor = false
     }
   }
 }

+ 67 - 4
src/views/realm/device/settings/components/external/Gateway/index.vue

@@ -78,6 +78,43 @@
               </div>
             </div>
           </div>
+          <div class="c-sibling-item--v far c-info">
+            <div class="l-flex--row has-bottom-padding u-bold">传感器信息</div>
+            <warning
+              v-if="sensorOptions.error"
+              @click="getSensors"
+            />
+            <div v-else-if="sensorOptions.loading">
+              <i class="el-icon el-icon-loading" />
+            </div>
+            <div
+              v-else-if="sensorOptions.list.length === 0"
+              class="u-color--info"
+            >
+              暂未绑定
+            </div>
+            <div
+              v-for="sensor in sensorOptions.list"
+              :key="sensor.id"
+              class="l-flex--row c-info__block"
+            >
+              <div class="l-flex--row l-flex__fill c-info__item">
+                <div class="l-flex__none c-info__title">名称</div>
+                <auto-text
+                  class="l-flex__fill c-info__value"
+                  :text="sensor.name"
+                />
+              </div>
+              <div class="l-flex--row l-flex__fill c-info__item">
+                <div class="l-flex__none c-info__title">标识</div>
+                <div class="l-flex__fill c-info__value">{{ sensor.identifier }}</div>
+              </div>
+              <div class="l-flex--row l-flex__fill c-info__item">
+                <div class="l-flex__none c-info__title">类型</div>
+                <div class="l-flex__fill c-info__value">{{ sensor.type }}</div>
+              </div>
+            </div>
+          </div>
         </template>
         <div
           v-else
@@ -111,7 +148,8 @@ import {
   getBoundPLCs,
   getPLCs,
   bindPLC,
-  unbind
+  unbind,
+  getSensors
 } from '@/api/external'
 
 export default {
@@ -127,7 +165,12 @@ export default {
       loading: false,
       error: false,
       info: null,
-      deviceType: 'GATEWAY'
+      deviceType: 'GATEWAY',
+      sensorOptions: {
+        list: [],
+        loading: false,
+        error: false
+      }
     }
   },
   computed: {
@@ -185,7 +228,7 @@ export default {
             arr = [Promise.resolve(this.info.gateway), this.getBoundPLCs()]
             break
           default:
-            arr = [this.getGateway(), Promise.resolve(this.info.plcs)]
+            arr = [this.getGateway(), this.getBoundPLCs()]
             break
         }
       } else {
@@ -201,10 +244,13 @@ export default {
           }
         },
         () => {
-          this.error = false
+          this.error = true
         }
       ).finally(() => {
         this.loading = false
+        if (this.gateway) {
+          this.getSensors()
+        }
       })
     },
     getGateway () {
@@ -259,6 +305,23 @@ export default {
           this.plcs.splice(this.plcs.indexOf(plc), 1)
         })
       })
+    },
+    getSensors () {
+      this.sensorOptions.loading = true
+      this.sensorOptions.error = false
+      getSensors(this.gateway.id).then(
+        ({ data }) => {
+          this.sensorOptions.list = data.map(sensor => {
+            sensor.type = ['烟雾', '温度', '光照', '水浸'][sensor.sensorType]
+            return sensor
+          })
+        },
+        () => {
+          this.sensorOptions.error = true
+        }
+      ).finally(() => {
+        this.sensorOptions.loading = false
+      })
     }
   }
 }