doum
6 天以前 5e59a6a3b10c0990f494b5a20e1102fd79b0db1b
最新版本541200007最新版本541200007
已添加22个文件
已修改13个文件
2082 ■■■■■ 文件已修改
admin/src/api/business/device.js 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/api/business/deviceData.js 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/assets/style/style.scss 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/components/business/OperaDeviceDataListWindow.vue 134 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/components/business/OperaDeviceDuanluqiWindow.vue 189 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/components/business/OperaJkSketchLineListWindow.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/views/business/deviceDuanluqi.vue 212 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/doc/新增断路器设备功能(2025-12-24).sql 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/pom.xml 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/system_service/src/main/java/com/doumee/core/utils/CmdContants.java 45 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/system_service/src/main/java/com/doumee/core/utils/Constants.java 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/system_timer/src/main/java/com/doumee/jobs/fegin/VisitServiceFegin.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/system_timer/src/main/resources/bootstrap.yml 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/visits/admin_timer/src/main/java/com/doumee/api/DuanluqiTimerController.java 45 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/visits/admin_timer/src/main/resources/bootstrap.yml 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/visits/device_service/pom.xml 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/visits/device_service/src/main/java/com/doumee/Main.java 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/visits/device_service/src/main/java/com/doumee/mqtt/config/MqttClientInit.java 136 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/visits/device_service/src/main/java/com/doumee/mqtt/config/MqttConfig.java 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/visits/device_service/src/main/java/com/doumee/mqtt/service/MqttBizService.java 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/visits/device_service/src/main/java/com/doumee/mqtt/service/MqttToolService.java 109 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/visits/dmvisit_admin/src/main/java/com/doumee/cloud/admin/DeviceCloudController.java 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/visits/dmvisit_admin/src/main/java/com/doumee/cloud/admin/DeviceDataCloudController.java 51 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/visits/dmvisit_admin/src/main/java/com/doumee/service/impl/DeviceInitServiceImpl.java 45 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/visits/dmvisit_service/pom.xml 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/visits/dmvisit_service/src/main/java/com/doumee/dao/business/DeviceDataMapper.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/visits/dmvisit_service/src/main/java/com/doumee/dao/business/model/Device.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/visits/dmvisit_service/src/main/java/com/doumee/dao/business/model/DeviceData.java 97 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/visits/dmvisit_service/src/main/java/com/doumee/service/business/DeviceDataService.java 98 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/visits/dmvisit_service/src/main/java/com/doumee/service/business/DeviceService.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/visits/dmvisit_service/src/main/java/com/doumee/service/business/impl/DeviceDataServiceImpl.java 161 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/visits/dmvisit_service/src/main/java/com/doumee/service/business/impl/DeviceServiceImpl.java 326 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/visits/dmvisit_service/src/main/java/com/doumee/service/business/impl/mqtt/MqttClientCache.java 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/visits/dmvisit_service/src/main/java/com/doumee/service/business/impl/mqtt/MqttPushCallback.java 141 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/visits/dmvisit_service/src/main/java/com/doumee/service/business/impl/mqtt/MqttSubServiceImpl.java 43 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/api/business/device.js
@@ -36,6 +36,12 @@
export function updateEntranceById (data) {
  return request.post('/visitsAdmin/cloudService/business/device/updateEntranceById', data)
}
export function updateUsedById (data) {
  return request.post('/visitsAdmin/cloudService/business/device/updateUsedById', data)
}
export function duanluqiCmd (data) {
  return request.post('/visitsAdmin/cloudService/business/device/duanluqiCmd', data)
}
// å‘生led屏内容
export function setLedContent (data) {
  return request.post('/visitsAdmin/cloudService/business/hksync/setLedContent', data)
admin/src/api/business/deviceData.js
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,8 @@
import request from '../../utils/request'
// æŸ¥è¯¢
export function fetchList (data) {
  return request.post('/visitsAdmin/cloudService/business/deviceData/page', data, {
    trim: true
  })
}
admin/src/assets/style/style.scss
@@ -142,6 +142,18 @@
  }
}
.tip-header{
  font-size: 16px;
  font-weight: bold;
  margin-bottom: 20px;
}
.tip {
  em {
    font-style: normal;
    color: $primary-color;
    font-weight: bold;
  }
}
.main_app {
  background-color: #fff;
  margin-top: 10px;
admin/src/components/business/OperaDeviceDataListWindow.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,134 @@
<template>
  <GlobalWindow
      :title="title"
      width="85%"
      :visible.sync="visible"
  >
    <TableLayout >
      <!-- æœç´¢è¡¨å• -->
      <el-form ref="searchForm" slot="search-form" :model="searchForm" label-width="100px" inline>
        <div  style="display: block;margin-bottom: 60px;padding: 20px; border: 1px solid #f2f2f2;">
          <div style="display: block;font-size: 16px;font-weight: 600;margin-bottom: 20px;">设备信息</div>
          <div style="display: flex;">
            <div style="flex: 1"><span class="label">名称:</span>{{model.name ||''}}</div>
            <div style="flex: 1"><span  class="label">标志符:</span>{{model.no ||''}}</div>
            <div style="flex: 1"><span  class="label">设备号:</span>{{model.doorNo ||'-'}}</div>
            <div style="flex: 1"><span  class="label">开关序号:</span>{{model.channelNo ||'-'}}</div>
            <div style="flex: 1"><span  class="label">控制开关:</span>{{model.channelInfo ||'-'}}</div>
          </div>
          <div style="display: flex;margin-top: 20px;">
            <div style="flex: 1"><span  class="label">MQTT IP:</span>{{model.doorNameObj.mqttIp ||''}}</div>
            <div style="flex: 1"><span  class="label">MQTT端口:</span>{{model.doorNameObj.mqttPort||''}}</div>
            <div style="flex: 3"> <span class="label">最近控制操作:</span>{{model.remark||''}}</div>
          </div>
        </div>
        <el-form-item label="开关序号" prop="val1">
          <el-input v-model="searchForm.val1" placeholder="请输入开关序号" @keypress.enter.native="search"></el-input>
        </el-form-item>
        <section>
          <el-button type="primary" @click="search">搜索</el-button>
          <el-button @click="reset">重置</el-button>
        </section>
      </el-form>
      <!-- è¡¨æ ¼å’Œåˆ†é¡µ -->
      <template v-slot:table-wrap>
        <el-table
            :height="tableHeightNew"
            v-loading="isWorking.search"
            :data="tableData.list"
            stripe>
          <el-table-column prop="happenTime" label="上报时间" min-width="150px"></el-table-column>
          <el-table-column prop="val1" label="开关序号" min-width="120px"></el-table-column>
          <el-table-column prop="val7" label="闸状态" min-width="120px">
            <template slot-scope="{row}">
              <span v-if=" row.val7 === '1'" class="green">合闸</span>
              <span  v-else-if=" row.val7 === '0'" class="red">分闸</span>
              <span v-else>-</span>
            </template>
          </el-table-column>
          <el-table-column prop="val2" label="电流(A)" min-width="120px"></el-table-column>
          <el-table-column prop="val3" label="电圧(V)" min-width="120px"></el-table-column>
          <el-table-column prop="val4" label="温度(℃)" min-width="180px" ></el-table-column>
          <el-table-column prop="val5" label="有功功率值(kW)" min-width="120px"></el-table-column>
        </el-table>
        <pagination
            @size-change="handleSizeChange"
            @current-change="handlePageChange"
            :pagination="tableData.pagination"
        >
        </pagination>
      </template>
    </TableLayout>
    <template   v-slot:footer>
      <el-button @click="visible=false">返回</el-button>
    </template>
  </GlobalWindow>
</template>
<script>
import BaseTable from '@/components/base/BaseTable'
import TableLayout from '@/layouts/TableLayout'
import Pagination from '@/components/common/Pagination'
import GlobalWindow from '@/components/common/GlobalWindow'
export default {
  name: 'OperaJkSketchCustomerWindow',
  extends: BaseTable,
  components: { GlobalWindow, TableLayout, Pagination },
  data () {
    return {
      // è¡¨å•数据
      visible: false,
      title: '',
      model:{},
      searchForm: {
        deviceId:  null,
        val1:''
      }
    }
  },
  created () {
    this.config({
      module: '设备数据信息表',
      api: '/business/deviceData',
      'field.id': 'id',
      'field.main': 'id'
    })
    this.search()
  },
  methods: {
    open (title, row) {
      this.title = title +' ã€'+ (row.name)+'】'
      this.searchForm.deviceId = row.id
      if(!row.doorNameObj) {
        row.doorNameObj = {}
      }
      this.model=row
      this.visible = true
      this.tableData = {
        // å·²é€‰ä¸­çš„æ•°æ®
        selectedRows: [],
        // æŽ’序的字段
        sorts: [],
        // å½“前页数据
        list: [],
        // åˆ†é¡µ
        pagination: {
          pageIndex: 1,
          pageSize: 10,
          total: 0
        }
      }
      this.search()
    }
  }
}
</script>
<style>
.label{
/*  width: 80px;
  text-align: right;*/
  color: rgb(102, 102, 102);
  display: inline-block;
}
</style>
admin/src/components/business/OperaDeviceDuanluqiWindow.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,189 @@
<template>
    <GlobalWindow
        :title="title"
        :visible.sync="visible"
        width="65%"
        :confirm-working="isWorking"
        @confirm="confirm"
    >
        <el-form :model="form" ref="form" :rules="rules">
          <p class="tip-header" >基本信息</p>
          <el-form-item label="设备名称" prop="name">
            <el-input v-model="form.name" placeholder="请输入名称" v-trim/>
          </el-form-item>
          <el-form-item label="设备标识符" prop="no">
            <el-input v-model="form.no" placeholder="请输入设备标识符" v-trim/>
          </el-form-item>
          <el-form-item label="设备号" prop="doorNo">
            <el-input v-model="form.doorNo" placeholder="请输入序列号" v-trim/>
          </el-form-item>
          <el-form-item label="厂商" prop="manufature">
            <el-input v-model="form.manufature" placeholder="请输入所在位置" v-trim/>
          </el-form-item>
          <el-form-item label="安装位置" prop="regionPathName">
            <el-input v-model="form.regionPathName" placeholder="请输入设备位置" v-trim/>
          </el-form-item>
          <el-form-item label="连接IP" prop="ip">
            <el-input v-model="form.ip" placeholder="请输入设备连接IP地址" v-trim/>
          </el-form-item>
          <el-form-item label="连接端口" prop="port">
            <el-input v-model="form.port" placeholder="请输入连接端口" v-trim/>
          </el-form-item>
          <p class="tip-header" >配置参数</p>
          <p class="tip-warn" style="width: 100%;"><i class="el-icon-warning"></i>配置参数说明:<br>
            1.全部开关序号:参考设备实际配置,多个用英文逗号隔开,如 1,2,3;<br>
            2.控制开关序号:系统根据配置规则,判断开关当前空闲中进行【自动分闸】,多个用英文逗号隔开,如 1,2;<br>
            3.自动分闸规则:针对控制开关序号的配置,定时检测【空闲时长】内满足开关电流值都在【空闲电流阈值】范围内,则进行自动分闸控制;<br>
            4.空闲时长: è¯·è®¾ç½®è‡³å°‘空闲时长大于等于300秒(5分钟)。
            5.如需远程控制开关,请正确填写下述全部参数信息。
          </p>
          <div style="display: flex">
            <el-form-item label="全部开关序号" prop="channelNo" style="display: inline-block;width:300px;">
              <el-input v-model="form.channelNo" placeholder="请输入开关序号,多个用英文逗号隔开,如 1,2,3" v-trim style="width: 150px;"   />
            </el-form-item>
            <el-form-item label="控制开关序号"    prop="channelInfo" style="display: inline-block;width:300px;">
              <el-input v-model="form.channelInfo" placeholder="请输入控制开关序号,多个用英文逗号隔开,如 1,2,3" v-trim style="width: 150px;"   />
            </el-form-item>
          </div>
          <div style="display: flex">
            <!--    <el-form-item label="空闲电流阈值" prop="mqttPassword" style="display: inline-block;width:250px;">
                <el-input v-model="form.doorNameObj.min" style="width: 150px;" disabled type="number"  maxlength="30" placeholder="最小值"  >
                   <template slot="append">A</template>
                 </el-input>
               </el-form-item>
               <span style="margin: 5px 10px;">至</span>-->
            <el-form-item label="空闲电流阈值" label-width="105px" prop="max" style="display: inline-block;width:300px">
              <el-input v-model="form.doorNameObj.max" style="width: 150px;" type="number"  maxlength="30" placeholder="最大值"   >
                <template slot="append">A</template>
              </el-input>
            </el-form-item>
            <el-form-item label="空闲时长(秒)" prop="level"   style="display: inline-block;width:350px;margin-left: 0px;">
              <el-input v-model="form.level" style="width: 180px;" type="number"  maxlength="30" placeholder="请输入空闲时长"   >
                <template slot="append">秒</template>
              </el-input>
            </el-form-item>
          </div>
          <el-form-item label="MQTT服务IP" prop="mqttIp">
            <el-input v-model="form.doorNameObj.mqttIp" placeholder="请输入设备连接MQTT-IP" v-trim/>
          </el-form-item>
          <el-form-item label="MQTT服务端口" prop="mqttPort">
            <el-input v-model="form.doorNameObj.mqttPort" placeholder="请输入连接MQTT服务端口" v-trim/>
          </el-form-item>
          <el-form-item label="MQTT服务账号" prop="mqttUsername">
            <el-input v-model="form.doorNameObj.mqttUsername" placeholder="请输入设备连接MQTT服务账号" v-trim/>
          </el-form-item>
          <el-form-item label="MQTT服务密码" prop="mqttPassword">
            <el-input v-model="form.doorNameObj.mqttPassword" type="password"  maxlength="30" show-password></el-input>
          </el-form-item>
          <p class="tip-warn" style="width: 100%;"><i class="el-icon-warning"></i> éžå……电状态电流大小接入设备后,参照现场实际场景配置;</p>
        </el-form>
    </GlobalWindow>
</template>
<script>
import BaseOpera from '@/components/base/BaseOpera'
import GlobalWindow from '@/components/common/GlobalWindow'
export default {
  name: 'OperaDeviceDuanluqiWindow',
  extends: BaseOpera,
  components: { GlobalWindow },
  data () {
    return {
      // è¡¨å•数据
      form: {
        id: null,
        name: '',
        regionPathName: '',
        doorNo: '',
        no: '',
        type: 5,
        ip: '',
        port: '',
        level: '',
        doorName: '',
        doorId: '',
        doorNameObj: {
          mqttUsername: '',
          mqttPassword: '',
          mqttIp: '',
          mqttPort: '',
          max: null,
          min: null
        },
        channelInfo: '',
        manufature: '',
        channelNo: ''
      },
      // éªŒè¯è§„则
      rules: {
        name: [
          { required: true, message: '请输入设备名称' }
        ],
      /*  max: [
          { required: true, message: '请输入设备空闲电流阈值' }
        ],*/
        doorId: [
          { required: true, message: '请输入设备连接账号' }
        ],
        doorName: [
          { required: true, message: '请输入设备连接密码' }
        ],
        channelNo: [
          { required: true, message: '请输入开关序号' }
        ],
        doorNo: [
          { required: true, message: '请输入设备号' }
        ],
        no: [
          { required: true, message: '请输入设备标识符' }
        ]
      }
    }
  },
  created () {
    this.config({
      api: '/business/device',
      'field.id': 'id'
    })
  },
  methods: {
    open (title, target) {
      this.title = title
      this.visible = true
      this.form.doorName = ''
      this.form.doorNameObj = {
        mqttUsername: '',
        mqttPassword: '',
        mqttIp: '',
        mqttPort: '',
        max: null,
        min: 0
      }
      // debugger
      // æ–°å»º
      if (target == null) {
        this.$nextTick(() => {
          this.$refs.form.resetFields()
          this.form[this.configData['field.id']] = null
        })
        if(!this.form.doorNameObj){
          this.form.doorNameObj = {
            mqttUsername: '',
            mqttPassword: '',
            mqttIp: '',
            mqttPort: '',
            max: null,
            min: 0
          }
        }
        return
      }
      // ç¼–辑
      this.$nextTick(async () => {
        for (const key in this.form) {
          this.form[key] = target[key]
        }
      })
    }
  }
}
</script>
admin/src/components/business/OperaJkSketchLineListWindow.vue
@@ -98,7 +98,7 @@
import OperaJkSketchLineMapWindow from '@/components/business/OperaJkSketchLineMapWindow'
import { initOriginDistance } from '@/api/business/jkSketch'
export default {
  name: 'OperaJkSketchLineWindow',
  name: 'OperaDeviceDataListWindow',
  extends: BaseOpera,
  components: { GlobalWindow, OperaJkSketchCustomerWindow ,OperaJkSketchLineMapWindow},
  data () {
admin/src/views/business/deviceDuanluqi.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,212 @@
<template>
    <TableLayout :permissions="['business:device:query']">
        <!-- æœç´¢è¡¨å• -->
        <el-form ref="searchForm"  slot="search-form" :model="searchForm" label-width="100px" inline>
            <el-form-item title="名称" prop="name">
                <el-input v-model="searchForm.name" placeholder="请输入名称" @keypress.enter.native="search"></el-input>
            </el-form-item>
            <el-form-item title="标识符" prop="no">
                <el-input v-model="searchForm.no" placeholder="请输入设备标识符" @keypress.enter.native="search"></el-input>
            </el-form-item>
            <el-form-item title="设备号" prop="doorNo">
                <el-input v-model="searchForm.doorNo" placeholder="请输入设备号" @keypress.enter.native="search"></el-input>
            </el-form-item>
            <section>
                <el-button type="primary" @click="search">搜索</el-button>
                <el-button @click="reset">重置</el-button>
            </section>
        </el-form>
        <!-- è¡¨æ ¼å’Œåˆ†é¡µ -->
        <template v-slot:table-wrap>
          <ul class="toolbar" v-permissions="['business:device:create', 'business:device:delete']">
            <li><el-button type="primary" @click="$refs.operaDeviceWindow.open('新建断路器')" icon="el-icon-plus" v-permissions="['business:device:create']">新建</el-button></li>
            <li><el-button @click="deleteByIdInBatch" icon="el-icon-delete" v-permissions="['business:device:delete']">删除</el-button></li>
          </ul>
            <el-table
                :height="tableHeightNew"
                v-loading="isWorking.search"
                :data="tableData.list"
                stripe
            >
              <el-table-column type="selection" width="55"></el-table-column>
              <el-table-column prop="name" label="名称" fixed min-width="150" align="center"></el-table-column>
              <el-table-column prop="no" label="设备标识符" min-width="100" align="center" ></el-table-column>
              <el-table-column prop="doorNo" label="设备号"  min-width="120" align="center" show-overflow-tooltip></el-table-column>
              <el-table-column prop="channelNo" label="开关序号" align="center" min-width="100"></el-table-column>
              <el-table-column prop="manufature" label="厂商" align="center" min-width="100" show-overflow-tooltip></el-table-column>
              <el-table-column prop="regionPathName" align="center"  min-width="100" label="所在位置"></el-table-column>
              <el-table-column prop="ip" label="IP"  min-width="150" align="center" show-overflow-tooltip ></el-table-column>
              <el-table-column prop="port" label="端口" align="center"  ></el-table-column>
              <el-table-column prop="isUsed" label="是否使用">
                <template slot-scope="{row}">
                  <el-switch @change="changeUsed($event, row)" v-model="row.isUsed" active-color="#13ce66"
                             inactive-color="#ff4949" :active-value="0" :inactive-value="1">
                  </el-switch>
                </template>
              </el-table-column>
              <el-table-column prop="editDate" label="最近更新时间" align="center" min-width="150"></el-table-column>
              <el-table-column prop="channelParam" label="控制开关参数" align="center" min-width="100">
                <el-table-column prop="channelInfo" label="控制开关序号" align="center" min-width="100"></el-table-column>
                <el-table-column prop="level" label="空闲时间(秒)" align="center" min-width="100"></el-table-column>
                <el-table-column label="空闲电流阈值" align="center" min-width="120">
                  <template slot-scope="{row}">
                    <span >{{ row.doorNameObj.max || '-'}}A</span>
                  </template>
                </el-table-column>
              </el-table-column>
              <el-table-column prop="doorNameObj" label="MQTT配置参数" align="center">
                <el-table-column prop="doorNameObj.mqttIp" label="IP" min-width="120" align="center"></el-table-column>
                <el-table-column prop="doorNameObj.mqttPort" label="端口" min-width="80" align="center"></el-table-column>
                <el-table-column prop="doorNameObj.mqttUsername" label="账号" align="center"></el-table-column>
                <el-table-column prop="doorNameObj.mqttPassword" label="密码" align="center">
                  <template slot-scope="{row}">
                    <span :class=" 'blue'">{{row.showPwd?row.doorNameObj.mqttPassword:'******'}}</span>
                    <el-button  style="margin-left: 10px" v-if="row.doorNameObj.mqttPassword!=null"
                                @click.native.p.prevent="showPassward(row)" type="text">
                      <i class="el-icon-view" :class="row.showPwd?'red':'blue'" :title="row.showPwd?'隐藏':'显示'"></i>
                    </el-button>
                  </template>
                </el-table-column>
              </el-table-column>
              <el-table-column
                  label="操作"
                  align="center"
                  min-width="280"
                  fixed="right"
              >
                  <template slot-scope="{row}">
                    <el-button type="text" @click="$refs.operaDeviceWindow.open('编辑断路器', row)" icon="el-icon-edit" v-permissions="['business:device:update']">编辑</el-button>
                    <el-button type="text" @click="$refs.operaDeviceDataWindow.open('查看断路器数据', row)" icon="el-icon-view" v-permissions="['business:device:update']">数据</el-button>
                    <el-button type="text" @click="send(row,1)" icon="el-icon-circle-check"  v-permissions="['business:device:update']">开闸</el-button>
                    <el-button type="text" class="red" @click="send(row,0)" icon="el-icon-circle-close"  v-permissions="['business:device:update']">关闸</el-button>
                    <el-button type="text" class="red" @click="deleteById(row)" icon="el-icon-delete" v-permissions="['business:device:delete']">删除</el-button>
                  </template>
                </el-table-column>
            </el-table>
            <pagination
                @size-change="handleSizeChange"
                @current-change="handlePageChange"
                :pagination="tableData.pagination"
            >
            </pagination>
        </template>
      <el-dialog
          :visible.sync="visibleSend"
          style="z-index: 100000"
          append-to-body
          width="50%"
          height="50%"
          :title="'控制开关-【'+ form.name+'】'"
      >
        <el-form :model="form" ref="form"  :rules="rules">
          <el-form-item label="执行操作:"  >
            <b class="green" v-if="form.status ===1">开闸</b>
            <b class="red" v-else>关闸</b>
          </el-form-item>
          <el-form-item label="开关序号" prop="channelNo">
            <el-input v-model="form.channelNo" type="text" placeholder="请输入开关序号 ï¼Œå¤šä¸ªç”¨è‹±æ–‡é€—号隔开,如 1,2,3" v-trim/>
          </el-form-item>
          <p class="tip-warn" style="width: 100%;"><i class="el-icon-warning"></i>设备原始开关序号信息:{{form.channelNo1}},控制多个开关,请用英文逗号隔开,如 1,2;</p>
        </el-form>
        <template  v-slot:footer  >
          <el-button @click="sendAction()" type="primary" v-if="form.status === 1" :loading="isWorkSending">确认开闸</el-button>
          <el-button @click="sendAction()" type="danger" v-if="form.status !== 1" :loading="isWorkSending">确认关闸</el-button>
          <el-button @click="sendClose()">返回</el-button>
        </template>
      </el-dialog>
        <!-- æ–°å»º/修改 -->
    <OperaDeviceDuanluqiWindow ref="operaDeviceWindow" @success="handlePageChange"/>
    <OperaDeviceDataListWindow ref="operaDeviceDataWindow" @success="handlePageChange"/>
    </TableLayout>
</template>
<script>
import BaseTable from '@/components/base/BaseTable'
import TableLayout from '@/layouts/TableLayout'
import Pagination from '@/components/common/Pagination'
import OperaDeviceDataListWindow from '@/components/business/OperaDeviceDataListWindow'
import OperaDeviceDuanluqiWindow from '@/components/business/OperaDeviceDuanluqiWindow'
export default {
  name: 'DeviceDuanluqi',
  extends: BaseTable,
  components: { TableLayout, Pagination, OperaDeviceDuanluqiWindow ,OperaDeviceDataListWindow},
  data () {
    return {
      // æœç´¢
      searchForm: {
        doorName: '',
        doorNo: '',
        no: '',
        regionPathName: '',
        type: 5
      },
      isWorkSending: false,
      form: {
        id: '',
        name: '',
        channelNo: '',
        channelNo1: '',
        status: null
      },
      visibleSend: false,
      options: [],
      rules: {
        channelNo: [{ required: true, message: '请输入需要操作的开关序号', trigger: 'blur' }],
      }
    }
  },
  created () {
    this.config({
      module: '设备信息表',
      api: '/business/device',
      'field.id': 'id',
      'field.main': 'id'
    })
    this.search()
  },
  methods: {
    changeUsed (e, row) {
      this.api.updateUsedById({
        id: row.id,
        isUsed: e
      })
    },
    showPassward (row) {
      if (!row.showPwd) {
        this.$set(row, 'showPwd', true)
      } else {
        this.$set(row, 'showPwd', false)
      }
    },
    sendAction () {
      if (!this.form.channelNo) {
        return
      }
      this.$dialog.actionConfirm('确认进行断路器【' + (this.form.status === 1 ? '开闸' : '关闸') + '】操作吗?', '操作确认提醒')
        .then(() => {
          this.isWorkSending = true
          this.api.duanluqiCmd(this.form)
            .then(res => {
              this.$tip.apiSuccess(res || '请求成功')
              this.sendClose()
            })
            .catch(e => {
            })
            .finally(() => {
              this.isWorkSending = false
            })
        })
        .catch(() => {})
    },
    send (row, type) {
      this.visibleSend = true
      this.form = { id: row.id, name: row.name, channelNo: row.channelNo, status: type ,channelNo1:row.channelNo}
    },
    sendClose () {
      this.visibleSend = false
      this.isWorkSending = false
      this.form = { id: '', name: '', channelNo: '', status: '',channelNo1:'' }
    }
  }
}
</script>
server/doc/ÐÂÔö¶Ï·Æ÷É豸¹¦ÄÜ£¨2025-12-24£©.sql
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,27 @@
ALTER TABLE `wuhuyancao`.`device`
MODIFY COLUMN `door_no` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '门禁点编号' AFTER `install_location`;
INSERT INTO `wuhuyancao`.`quartz_job` (`id`, `bean_name`, `params`, `cron_expres`, `state`, `remark`, `create_time`, `module`) VALUES (NULL, 'visitServiceJob', '{}', '0 0/5 * * * ? *', 1, '【断路器】开启定时远程控制断路器分闸', '2023-07-26 13:17:17', 'autoCloseCmd');
CREATE TABLE `device_data` (
  `ID` int NOT NULL AUTO_INCREMENT COMMENT '主键',
  `CREATOR` int DEFAULT NULL COMMENT '创建人编码',
  `CREATE_DATE` datetime DEFAULT NULL COMMENT '创建时间',
  `EDITOR` int DEFAULT NULL COMMENT '更新人编码',
  `EDIT_DATE` datetime DEFAULT NULL COMMENT '更新时间',
  `ISDELETED` int DEFAULT NULL COMMENT '是否删除0否 1是',
  `REMARK` varchar(2000) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '备注',
  `DATA_JSON` text COLLATE utf8mb4_unicode_ci COMMENT '数据json对象',
  `DEVICE_ID` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '设备编码(关联device)',
  `HAPPEN_TIME` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '发生时间',
  `VAL1` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '属性值1',
  `VAL2` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '属性值2',
  `VAL3` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '属性值3',
  `VAL4` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '属性值4',
  `VAL5` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '属性值5',
  `VAL6` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '属性值6',
  `DATA_TYPE` int DEFAULT NULL COMMENT '数据来源 0mqtt上报 1其他',
  PRIMARY KEY (`ID`),
  UNIQUE KEY `eventIdnex` (`DEVICE_ID`,`HAPPEN_TIME`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=106097 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='门禁事件推送记录表';
server/pom.xml
@@ -17,6 +17,7 @@
      <module>system_timer</module>
      <module>system_gateway</module>
      <module>emaysms</module>
    <module>visits/device_service</module>
  </modules>
  <parent>
    <groupId>org.springframework.boot</groupId>
server/system_service/src/main/java/com/doumee/core/utils/CmdContants.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,45 @@
package com.doumee.core.utils;
/**
 * è®¾å¤‡æŒ‡ä»¤å‚数集合
 */
public class CmdContants {
    public interface T30A{
        String cmdParam ="{" +
                "  \"method\": 3," +
                "  \"dstID\" : 43008827854690816," +//设备号
                "  \"msgCode\": 120," +
                "  \"timeMS\": 0," +
                "  \"data\":" +
                "   [{" +
                "    \"tag\":305," +
                "    \"cmd\":\"$CMD\", " +//指令
                "    \"count\":3," +
                "    \"busAddr\":[$BUSADDR]" +//模块地址
                "   }]" +
                "}";
    }
    /**
     * è¯´æ˜Žï¼š ï¼ˆ1)针对空开设备操作,  ä¸€æ¬¡ä»…能执行一条命令,因此无需提供"busAddr"、"devID"和"count"字段,如果命令不需要携带参数,"para"字段也同样无需提供。
     * ï¼ˆ2)空开手动分闸会进入异常锁定模式,需对对应线路设备下发异常解锁指令后或手动合闸空开才能远程控制。
     */
    public interface T30ACmd{
        String do_lock =  "do_lock";//锁定
        String do_unlock =  "do_unlock";//解锁
        String do_err_clear =  "do_err_clear";//异常解锁
        String doLeakageCheck =  "do_leakage_check";//手动漏电自检
        String do_turn_off =  "do_turn_off";//一键分闸
        String do_turn_on =  "do_turn_on";//一键合闸
        String do_reboot =  "do_reboot";//远程重启
        String do_refresh_bus =  "do_refresh_bus";//刷新总线
        String do_set_factory =  "do_set_factory";//恢复出厂设置
        String do_auto_address =  "do_auto_address";//自动分配地址
        String do_mod_passwd =  "do_mod_passwd";//修改设备密码
        String do_updrade =  "do_updrade";//在线升级指令
    }
}
server/system_service/src/main/java/com/doumee/core/utils/Constants.java
@@ -218,6 +218,7 @@
    public static  boolean DEALING_HK_NOTICE_LIST = false;
    public static  boolean DEALING_FROM_HK_VISIT = false;
    public static  boolean DEALING_HK_EMPOWER = false;
    public static  boolean DEALING_DUANLUQI_CLOSE = false;
    public static  boolean DEALING_HK_EMPOWER_DETAIL = false;
    public static  boolean DEALING_HK_EMPOWER_RESULT = false;
    public static  boolean DEALING_HK_PARKBOOK = false;
@@ -288,6 +289,15 @@
        public static final  int depart = 3;
        public static final  int custom = 4;
        public static final  int self = -1;
    }
    //类型 0门禁 1车库 2LED 3广播点 4广播设备 5断路器空开
    public interface DEVICE_TYPE{
        public static final  int door = 0;
        public static final  int park = 1;
        public static final  int led = 2;
        public static final  int broadcaset = 3;
        public static final  int broadcasetChannel = 4;
        public static final  int duanluqi = 5;
    }
    /**
@@ -1529,6 +1539,14 @@
        return JSONObject.toJSONString(map);
    }
    public  interface MqttTopic{
        String mts_attr = "/dev/+/+/attr/json";//属性topic
        String mts_status = "/dev/+/+/status/json";//状态topic
        String mts_event= "/dev/+/+/event/json";//事件topic
        String mts_echo= "/dev/+/+/echo/json";//消息回复topic
        String mts_cmd= "/dev/$CATE/$DEVID/cmd/json";//命令topic
        String mts_resp= "/dev/+/+/resp/json";//命令响应topic
    }
    public  enum WarningConfig {
server/system_timer/src/main/java/com/doumee/jobs/fegin/VisitServiceFegin.java
@@ -118,4 +118,7 @@
    @ApiOperation("【钥匙柜】定时发送钥匙未及时归还通知")
    @PostMapping("/timer/jkCabinet/timeOutUnBackAlarm")
    ApiResponse timeOutUnBackAlarm();
    @ApiOperation("【断路器】开启定时远程控制断路器分闸")
    @PostMapping("/timer/duanluqi/autoCloseCmd")
    ApiResponse autoCloseCmd();
}
server/system_timer/src/main/resources/bootstrap.yml
@@ -1,6 +1,6 @@
spring:
  profiles:
    active: test
    active: dev
  application:
    name: systemTimer
    # å®‰å…¨é…ç½®
server/visits/admin_timer/src/main/java/com/doumee/api/DuanluqiTimerController.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,45 @@
package com.doumee.api;
import com.alibaba.fastjson.JSONObject;
import com.doumee.biz.system.SystemDictDataBiz;
import com.doumee.core.utils.Constants;
import com.doumee.core.utils.HttpsUtil;
import com.doumee.core.wx.WXConstant;
import com.doumee.dao.system.model.SystemDictData;
import com.doumee.service.business.DeviceService;
import com.doumee.service.business.third.model.ApiResponse;
import com.doumee.service.system.SystemDictDataService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.mgt.DefaultSecurityManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Date;
import java.util.Objects;
/**
 * @author æ±Ÿè¹„蹄
 * @date 2023/11/30 15:33
 */
@Api(tags = "断路器远程控制定时器")
@RestController
@RequestMapping("/timer/duanluqi")
public class DuanluqiTimerController extends BaseController {
    @Autowired
    private DeviceService deviceService;
    @ApiOperation("开启定时远程控制断路器分闸")
    @PostMapping("/autoCloseCmd")
    public ApiResponse autoCloseCmd() {
        deviceService.autoCloseCmdTimer();
        return ApiResponse.success("开启定时远程控制断路器分闸成功");
    }
}
server/visits/admin_timer/src/main/resources/bootstrap.yml
@@ -1,6 +1,6 @@
spring:
  profiles:
    active: pro
    active: dev
  application:
    name: visitsTimer
    # å®‰å…¨é…ç½®
server/visits/device_service/pom.xml
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,32 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>com.doumee</groupId>
        <artifactId>dmvisit</artifactId>
        <version>1.0.0-SNAPSHOT</version>
        <relativePath>../../pom.xml</relativePath>
    </parent>
    <artifactId>device_service</artifactId>
    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.eclipse.paho</groupId>
            <artifactId>org.eclipse.paho.client.mqttv3</artifactId>
            <version>1.2.2</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
    </dependencies>
</project>
server/visits/device_service/src/main/java/com/doumee/Main.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,7 @@
package com.doumee;
public class Main {
    public static void main(String[] args) {
        System.out.println("Hello world!");
    }
}
server/visits/device_service/src/main/java/com/doumee/mqtt/config/MqttClientInit.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,136 @@
package com.doumee.mqtt.config;
import org.eclipse.paho.client.mqttv3.*;
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;
public class MqttClientInit {
        static MqttClient client;
        static MqttClient subClient;
        public static synchronized MqttClient getPublishInstance(MqttConfig config ){
            if(client !=null){
                if(!client.isConnected()){
                    try {
                        client.reconnect();
                    } catch (MqttException e) {
                        throw new RuntimeException(e);
                    }
                }
                return  client;
            }
            try {
                // host为主机名,clientid即连接MQTT的客户端ID,一般以唯一标识符表示,MemoryPersistence设置clientid的保存形式,默认为以内存保存
                String clientId =config.getClientid() +config.getVersion();
                client = new org.eclipse.paho.client.mqttv3.MqttClient(config.getHost(), clientId,new MemoryPersistence());
                // MQTT的连接设置
                MqttConnectOptions   options = new MqttConnectOptions();
                // è®¾ç½®æ˜¯å¦æ¸…空session,这里如果设置为false表示服务器会保留客户端的连接记录,设置为true表示每次连接到服务器都以新的身份连接
                options.setCleanSession(false);
                // è®¾ç½®è¿žæŽ¥çš„用户名
                options.setUserName(config.getUsername());
                // è®¾ç½®è¿žæŽ¥çš„密码
                options.setPassword(config.getPassword().toCharArray());
                // è®¾ç½®è¶…æ—¶æ—¶é—´ å•位为秒
                options.setConnectionTimeout(10);
                // è®¾ç½®ä¼šè¯å¿ƒè·³æ—¶é—´ å•位为秒 æœåŠ¡å™¨ä¼šæ¯éš”1.5*20秒的时间向客户端发送个消息判断客户端是否在线,但这个方法并没有重连的机制
                options.setKeepAliveInterval(20);
                //设置断开后重新连接
                options.setAutomaticReconnect(true);
                MqttTopic topic = client.getTopic(clientId+"_close");
                //遗嘱
                options.setWill(topic, "close".getBytes(), 1, true);
                client.connect(options);
            } catch (Exception e) {
                e.printStackTrace();
            }
            return  client;
        }
        public static synchronized MqttClient getSubInstance(MqttConfig config, MqttCallback callBack){
            if(subClient !=null){
                refreshClient();
                return  subClient;
            }
            try {
                // host为主机名,clientid即连接MQTT的客户端ID,一般以唯一标识符表示,MemoryPersistence设置clientid的保存形式,默认为以内存保存
                String clientId =config.getSubclientid() +config.getVersion();
                subClient = new org.eclipse.paho.client.mqttv3.MqttClient(config.getHost(), clientId,new MemoryPersistence());
                // MQTT的连接设置
                MqttConnectOptions   options = new MqttConnectOptions();
                // è®¾ç½®æ˜¯å¦æ¸…空session,这里如果设置为false表示服务器会保留客户端的连接记录,设置为true表示每次连接到服务器都以新的身份连接
                options.setCleanSession(false);
                // è®¾ç½®è¿žæŽ¥çš„用户名
                options.setUserName(config.getUsername());
                // è®¾ç½®è¿žæŽ¥çš„密码
                options.setPassword(config.getPassword().toCharArray());
                // è®¾ç½®è¶…æ—¶æ—¶é—´ å•位为秒
                options.setConnectionTimeout(10);
                // è®¾ç½®ä¼šè¯å¿ƒè·³æ—¶é—´ å•位为秒 æœåŠ¡å™¨ä¼šæ¯éš”1.5*20秒的时间向客户端发送个消息判断客户端是否在线,但这个方法并没有重连的机制
                options.setKeepAliveInterval(20);
                // è®¾ç½®å›žè°ƒ
                subClient.setCallback(callBack);
                //设置断开后重新连接
                options.setAutomaticReconnect(true);
                MqttTopic topic = subClient.getTopic(clientId+"_close");
                //遗嘱
                options.setWill(topic, "close".getBytes(), 1, true);
                subClient.connect(options);
            } catch (Exception e) {
                e.printStackTrace();
            }
            return  subClient;
        }
    public static synchronized MqttClient getInstance(MqttClient clientModel,MqttConfig config, MqttCallback callBack){
        if(clientModel !=null){
            refreshClient(clientModel);
            return  clientModel;
        }
        try {
            // host为主机名,clientid即连接MQTT的客户端ID,一般以唯一标识符表示,MemoryPersistence设置clientid的保存形式,默认为以内存保存
            String clientId =config.getClientid() +config.getVersion();
            clientModel = new org.eclipse.paho.client.mqttv3.MqttClient(config.getHost(), clientId,new MemoryPersistence());
            // MQTT的连接设置
            MqttConnectOptions   options = new MqttConnectOptions();
            // è®¾ç½®æ˜¯å¦æ¸…空session,这里如果设置为false表示服务器会保留客户端的连接记录,设置为true表示每次连接到服务器都以新的身份连接
            options.setCleanSession(false);
            // è®¾ç½®è¿žæŽ¥çš„用户名
            options.setUserName(config.getUsername());
            // è®¾ç½®è¿žæŽ¥çš„密码
            options.setPassword(config.getPassword().toCharArray());
            // è®¾ç½®è¶…æ—¶æ—¶é—´ å•位为秒
            options.setConnectionTimeout(10);
            // è®¾ç½®ä¼šè¯å¿ƒè·³æ—¶é—´ å•位为秒 æœåŠ¡å™¨ä¼šæ¯éš”1.5*20秒的时间向客户端发送个消息判断客户端是否在线,但这个方法并没有重连的机制
            options.setKeepAliveInterval(20);
            // è®¾ç½®å›žè°ƒ
            clientModel.setCallback(callBack);
            //设置断开后重新连接
            options.setAutomaticReconnect(true);
            MqttTopic topic = clientModel.getTopic(clientId+"_close");
            //遗嘱
            options.setWill(topic, "close".getBytes(), 1, true);
            clientModel.connect(options);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return  clientModel;
    }
        public static synchronized void refreshClient(  ) {
            try {
                if(subClient !=null &&  !subClient.isConnected()){
                    subClient.reconnect();
                }
            }catch (Exception e){
                e.printStackTrace();
            }
        }
        public static synchronized void refreshClient(MqttClient clientModel  ) {
            try {
                if(clientModel !=null  &&  !clientModel.isConnected()){
                    clientModel.reconnect();
                }
            }catch (Exception e){
                e.printStackTrace();
            }
        }
}
server/visits/device_service/src/main/java/com/doumee/mqtt/config/MqttConfig.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,33 @@
package com.doumee.mqtt.config;
import lombok.Data;
@Data
public class MqttConfig {
        /**
         *服务器地址 ip+端口,如tcp://175.27.187.84:1883
         */
        private String host;
        /**
         * å®¢æˆ·ç«¯ç¼–码
         */
        private String clientid;
        /**
         * å®¢æˆ·ç«¯ç¼–码用户订阅
         */
        private String subclientid;
        /**
         * æŽˆæƒè´¦å·
         */
        private String username ;
        /**
         * æŽˆæƒå¯†ç 
         */
        private String password;
        /**
         * å®¢æˆ·ç«¯ç‰ˆæœ¬åŽç¼€
         */
        private String version;
}
server/visits/device_service/src/main/java/com/doumee/mqtt/service/MqttBizService.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,28 @@
package com.doumee.mqtt.service;
import com.doumee.mqtt.config.MqttConfig;
import org.eclipse.paho.client.mqttv3.MqttClient;
import org.eclipse.paho.client.mqttv3.MqttMessage;
/**
 * ä¸Žç¡¬ä»¶å¯¹æŽ¥æœåŠ¡
 * @author æ±Ÿè¹„蹄
 * @date 2023/10/09 18:06
 */
public interface MqttBizService {
    /**
     * æŒ‰é…ç½®è®¢é˜…
     * @param config
     * @param topics
     */
    MqttClient subscribe(MqttClient client,MqttConfig config, String[] topics);
    MqttClient unsubscribe(MqttClient client,MqttConfig config, String[] topics);
    /**
     * æŒ‰é…ç½®å‘布消息
     * @param config
     * @param topic
     */
    MqttClient publish(MqttClient client,MqttConfig config,String topic,String param);
}
server/visits/device_service/src/main/java/com/doumee/mqtt/service/MqttToolService.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,109 @@
package com.doumee.mqtt.service;
import com.doumee.mqtt.config.MqttClientInit;
import com.doumee.mqtt.config.MqttConfig;
import lombok.Data;
import org.eclipse.paho.client.mqttv3.MqttCallback;
import org.eclipse.paho.client.mqttv3.MqttClient;
import org.eclipse.paho.client.mqttv3.MqttMessage;
@Data
public class MqttToolService {
    /**
     * è®¢é˜…消息,启动加载一次
     * @param topics
     */
    public static MqttClient subscribe(MqttClient clientTemp,MqttConfig config,String[]  topics, MqttCallback callBack) {
        try {
            //订阅消息
            int[] Qos = new int[topics.length];//0:最多一次 ã€1:最少一次 ã€2:只有一次
            for (int i = 0; i < Qos.length; i++) {
                Qos[i] = 1;
                /*if(i ==2){
                    Qos[i] = 2;
                }else{
                    Qos[i] = 1;
                }*/
            }
            clientTemp =  MqttClientInit.getInstance(clientTemp,config,callBack);
            try {
                clientTemp.subscribe(topics, Qos);
            }catch (Exception e){
                e.printStackTrace();
            }
            return clientTemp;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return clientTemp;
    }
    public static MqttClient unsubscribe(MqttClient clientTemp,MqttConfig config,String[]  topics, MqttCallback callBack) {
        try {
            //订阅消息
            int[] Qos = new int[topics.length];//0:最多一次 ã€1:最少一次 ã€2:只有一次
            for (int i = 0; i < Qos.length; i++) {
                Qos[i] = 1;
                /*if(i ==2){
                    Qos[i] = 2;
                }else{
                    Qos[i] = 1;
                }*/
            }
            clientTemp =  MqttClientInit.getInstance(clientTemp,config,callBack);
            try {
                clientTemp.unsubscribe(topics);
            }catch (Exception e){
                e.printStackTrace();
            }
            return clientTemp;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return clientTemp;
    }
    /**
     * æ¶ˆæ¯å‘送
     * @param message
     * @param topic
     */
    public static MqttClient pubMessage(MqttClient clientTemp,MqttConfig config,String message,String topic, MqttCallback callBack){
        try {
            MqttMessage mess = new MqttMessage();
            mess.setQos(1);
            mess.setRetained(false);
            mess.setPayload(message.getBytes());
            clientTemp =  MqttClientInit.getInstance(clientTemp,config,callBack);
            try {
                clientTemp.publish(topic, mess);
            }catch (Exception e){
                e.printStackTrace();
            }
            return  clientTemp;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return clientTemp;
    }
    public static void main(String[] args) {
        MqttConfig config = (new MqttConfig());
        config.setHost("tcp://192.168.0.7:1883");
        config.setClientid("doumee1");
        config.setPassword("doumee@168");
        config.setUsername("doumee");
        config.setVersion("003");
        MqttToolService.pubMessage(null,config,"{" +
                "  \"method\": 3," +
                "  \"dstID\" :43008827854690816," +
                "  \"msgCode\": 120," +
                "  \"timeMS\": 0," +
                "  \"data\":" +
                "   [{" +
                "    \"tag\":305," +
                "    \"cmd\":\"do_turn_off\", " +
                "    \"count\":3," +
                "    \"busAddr\":[3]" +
                "   }]" +
                "}","/dev/MTS/98CC4D121E5A/cmd/json",null);
    }
}
server/visits/dmvisit_admin/src/main/java/com/doumee/cloud/admin/DeviceCloudController.java
@@ -55,9 +55,30 @@
        d.setId(param.getId());
        d.setEditDate(new Date());
        d.setIsEntrance(Constants.formatIntegerNum(param.getIsEntrance()));
        d.setLoginUserInfo(this.getLoginUser(token));
        deviceService.updateById(d);
        return ApiResponse.success(null);
    }
    @ApiOperation("修改是否系统使用")
    @PostMapping("/updateUsedById")
    @CloudRequiredPermission("business:company:update")
    public ApiResponse updateUsedById(@RequestBody Device param,@RequestHeader(Constants.HEADER_USER_TOKEN) String token){
        Device d = new Device();
        d.setId(param.getId());
        d.setEditDate(new Date());
        d.setLoginUserInfo(this.getLoginUser(token));
        d.setIsUsed(Constants.formatIntegerNum(param.getIsUsed()));
        deviceService.updateUsedById(d);
        return ApiResponse.success(null);
    }
    @ApiOperation("执行断路器开关闸操作")
    @PostMapping("/duanluqiCmd")
    @CloudRequiredPermission("business:company:update")
    public ApiResponse duanluqiCmd(@RequestBody Device param,@RequestHeader(Constants.HEADER_USER_TOKEN) String token){
        param.setLoginUserInfo(this.getLoginUser(token));
        deviceService.duanluqiCmd(param);
        return ApiResponse.success(null);
    }
    @ApiOperation("批量删除")
    @GetMapping("/delete/batch")
server/visits/dmvisit_admin/src/main/java/com/doumee/cloud/admin/DeviceDataCloudController.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,51 @@
package com.doumee.cloud.admin;
import com.doumee.api.BaseController;
import com.doumee.config.annotation.CloudRequiredPermission;
import com.doumee.core.annotation.excel.ExcelExporter;
import com.doumee.core.annotation.pr.PreventRepeat;
import com.doumee.core.utils.Constants;
import com.doumee.dao.business.model.Device;
import com.doumee.dao.business.model.DeviceData;
import com.doumee.service.business.DeviceDataService;
import com.doumee.service.business.DeviceService;
import com.doumee.service.business.third.model.ApiResponse;
import com.doumee.service.business.third.model.PageData;
import com.doumee.service.business.third.model.PageWrap;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
 * @author æ±Ÿè¹„蹄
 * @date 2023/11/30 15:33
 */
@Api(tags = "设备数据信息表")
@RestController
@RequestMapping(Constants.CLOUD_SERVICE_URL_INDEX+"/business/deviceData")
public class DeviceDataCloudController extends BaseController {
    @Autowired
    private DeviceDataService deviceDataService;
    @ApiOperation("分页查询")
    @PostMapping("/page")
    @CloudRequiredPermission("business:device:query")
    public ApiResponse<PageData<DeviceData>> findPage (@RequestBody PageWrap<DeviceData> pageWrap,@RequestHeader(Constants.HEADER_USER_TOKEN) String token){
        return ApiResponse.success(deviceDataService.findPage(pageWrap));
    }
    @ApiOperation("导出Excel")
    @PostMapping("/exportExcel")
    @CloudRequiredPermission("business:device:exportExcel")
    public void exportExcel (@RequestBody PageWrap<DeviceData> pageWrap, HttpServletResponse response, @RequestHeader(Constants.HEADER_USER_TOKEN) String token){
        ExcelExporter.build(DeviceData.class).export(deviceDataService.findPage(pageWrap).getRecords(), "设备信息表", response);
    }
}
server/visits/dmvisit_admin/src/main/java/com/doumee/service/impl/DeviceInitServiceImpl.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,45 @@
package com.doumee.service.impl;
import com.doumee.biz.system.SystemDictDataBiz;
import com.doumee.core.haikang.model.HKConstants;
import com.doumee.core.haikang.model.HKTools;
import com.doumee.core.haikang.model.param.BaseResponse;
import com.doumee.core.haikang.model.param.request.EventSubRequest;
import com.doumee.core.haikang.model.param.respose.OrgInfoResponse;
import com.doumee.core.haikang.service.HKService;
import com.doumee.core.utils.Constants;
import com.doumee.dao.business.WarningMapper;
import com.doumee.dao.system.model.SystemDictData;
import com.doumee.service.business.DeviceService;
import com.doumee.service.business.InterfaceLogService;
import com.doumee.service.business.impl.hksync.HkSyncBaseServiceImpl;
import com.hikvision.artemis.sdk.config.ArtemisConfig;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
import java.util.Date;
/**
 * æµ·åº·äº‹ä»¶è®¢é˜…表Service实现
 * @author æ±Ÿè¹„蹄
 * @date 2023/11/30 15:33
 */
@Service
public class DeviceInitServiceImpl extends HkSyncBaseServiceImpl {
    @Autowired
    private DeviceService deviceService;
    @Autowired
    private InterfaceLogService interfaceLogService;
    @Autowired
    private WarningMapper warningMapper;
    @PostConstruct
    public  int  startDuanluqiMqttJob(){
        //获取根组织编码
        deviceService.startCheckDuanluqiSubjob();
        return  0;
    }
}
server/visits/dmvisit_service/pom.xml
@@ -23,6 +23,11 @@
            <version>1.0.0-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>com.doumee</groupId>
            <artifactId>device_service</artifactId>
            <version>1.0.0-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>com.google.ortools</groupId>
            <artifactId>ortools-java</artifactId>
            <version>9.14.6206</version>
server/visits/dmvisit_service/src/main/java/com/doumee/dao/business/DeviceDataMapper.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,12 @@
package com.doumee.dao.business;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.doumee.dao.business.model.DeviceData;
/**
 * @author æ±Ÿè¹„蹄
 * @date 2025/12/25 10:04
 */
public interface DeviceDataMapper extends BaseMapper<DeviceData> {
}
server/visits/dmvisit_service/src/main/java/com/doumee/dao/business/model/Device.java
@@ -1,5 +1,6 @@
package com.doumee.dao.business.model;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.annotation.TableField;
import com.doumee.core.annotation.excel.ExcelColumn;
import com.doumee.service.business.third.model.LoginUserModel;
@@ -10,6 +11,7 @@
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.math.BigDecimal;
import java.util.Date;
/**
@@ -71,8 +73,8 @@
    @ExcelColumn(name="排序码")
    private Integer sortnum;
    @ApiModelProperty(value = "类型 0门禁 1车库 2LED 3广播点 4广播设备", example = "1")
    @ExcelColumn(name="类型 0门禁 1车库 2LED 3广播点 4广播设备")
    @ApiModelProperty(value = "类型 0门禁 1车库 2LED 3广播点 4广播设备 5断路器空开", example = "1")
    @ExcelColumn(name="类型 0门禁 1车库 2LED 3广播点 4广播设备 5断路器空开")
    private Integer type;
    @ApiModelProperty(value = "是否园区出入口 0不是 1是", example = "1")
    @ExcelColumn(name="是否园区出入口 0不是 1是")
@@ -154,12 +156,12 @@
    @ApiModelProperty(value = "门禁点名称")
    @ExcelColumn(name="门禁点名称")
    private String doorName;
    @ApiModelProperty(value = "播报内容")
    @TableField(exist = false)
    private String sendInfo;
    @ApiModelProperty(value = "配置参数")
    @TableField(exist = false)
    private JSONObject doorNameObj;
server/visits/dmvisit_service/src/main/java/com/doumee/dao/business/model/DeviceData.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,97 @@
package com.doumee.dao.business.model;
import com.doumee.core.annotation.excel.ExcelColumn;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import com.fasterxml.jackson.annotation.JsonFormat;
import java.util.Date;
/**
 * é—¨ç¦äº‹ä»¶æŽ¨é€è®°å½•表
 * @author æ±Ÿè¹„蹄
 * @date 2025/12/25 10:04
 */
@Data
@ApiModel("门禁事件推送记录表")
@TableName("`device_data`")
public class DeviceData {
    @TableId(type = IdType.AUTO)
    @ApiModelProperty(value = "主键", example = "1")
    @ExcelColumn(name="主键")
    private Integer id;
    @ApiModelProperty(value = "创建人编码", example = "1")
    @ExcelColumn(name="创建人编码")
    private Integer creator;
    @ApiModelProperty(value = "创建时间")
    @ExcelColumn(name="创建时间")
    @JsonFormat(pattern = "yyyy-MM-dd")
    private Date createDate;
    @ApiModelProperty(value = "更新人编码", example = "1")
    @ExcelColumn(name="更新人编码")
    private Integer editor;
    @ApiModelProperty(value = "更新时间")
    @ExcelColumn(name="更新时间")
    @JsonFormat(pattern = "yyyy-MM-dd")
    private Date editDate;
    @ApiModelProperty(value = "是否删除0否 1是", example = "1")
    @ExcelColumn(name="是否删除0否 1是")
    private Integer isdeleted;
    @ApiModelProperty(value = "备注")
    @ExcelColumn(name="备注")
    private String remark;
    @ApiModelProperty(value = "数据json对象", example = "1")
    @ExcelColumn(name="数据json对象")
    private String dataJson;
    @ApiModelProperty(value = "设备编码(关联device)")
    @ExcelColumn(name="设备编码(关联device)")
    private String deviceId;
    @ApiModelProperty(value = "发生时间")
    @ExcelColumn(name="发生时间")
    private String happenTime;
    @ApiModelProperty(value = "属性值1")
    @ExcelColumn(name="属性值1")
    private String val1;
    @ApiModelProperty(value = "属性值2")
    @ExcelColumn(name="属性值2")
    private String val2;
    @ApiModelProperty(value = "属性值3")
    @ExcelColumn(name="属性值3")
    private String val3;
    @ApiModelProperty(value = "属性值4")
    @ExcelColumn(name="属性值4")
    private String val4;
    @ApiModelProperty(value = "属性值5")
    @ExcelColumn(name="属性值5")
    private String val5;
    @ApiModelProperty(value = "属性值6")
    @ExcelColumn(name="属性值6")
    private String val6;
    @ApiModelProperty(value = "属性值7")
    @ExcelColumn(name="属性值7")
    private String val7;
    @ApiModelProperty(value = "数据来源 0mqtt上报 1其他", example = "1")
    @ExcelColumn(name="数据来源 0mqtt上报 1其他")
    private Integer dataType;
}
server/visits/dmvisit_service/src/main/java/com/doumee/service/business/DeviceDataService.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,98 @@
package com.doumee.service.business;
import com.doumee.dao.business.model.DeviceData;
import com.doumee.service.business.third.model.PageData;
import com.doumee.service.business.third.model.PageWrap;
import java.util.List;
/**
 * é—¨ç¦äº‹ä»¶æŽ¨é€è®°å½•表Service定义
 * @author æ±Ÿè¹„蹄
 * @date 2025/12/25 10:04
 */
public interface DeviceDataService {
    /**
     * åˆ›å»º
     *
     * @param deviceData å®žä½“对象
     * @return Integer
     */
    Integer create(DeviceData deviceData);
    /**
     * ä¸»é”®åˆ é™¤
     *
     * @param id ä¸»é”®
     */
    void deleteById(Integer id);
    /**
     * åˆ é™¤
     *
     * @param deviceData å®žä½“对象
     */
    void delete(DeviceData deviceData);
    /**
     * æ‰¹é‡ä¸»é”®åˆ é™¤
     *
     * @param ids ä¸»é”®é›†
     */
    void deleteByIdInBatch(List<Integer> ids);
    /**
     * ä¸»é”®æ›´æ–°
     *
     * @param deviceData å®žä½“对象
     */
    void updateById(DeviceData deviceData);
    /**
     * æ‰¹é‡ä¸»é”®æ›´æ–°
     *
     * @param deviceDatas å®žä½“集
     */
    void updateByIdInBatch(List<DeviceData> deviceDatas);
    /**
     * ä¸»é”®æŸ¥è¯¢
     *
     * @param id ä¸»é”®
     * @return DeviceData
     */
    DeviceData findById(Integer id);
    /**
     * æ¡ä»¶æŸ¥è¯¢å•条记录
     *
     * @param deviceData å®žä½“对象
     * @return DeviceData
     */
    DeviceData findOne(DeviceData deviceData);
    /**
     * æ¡ä»¶æŸ¥è¯¢
     *
     * @param deviceData å®žä½“对象
     * @return List<DeviceData>
     */
    List<DeviceData> findList(DeviceData deviceData);
    /**
     * åˆ†é¡µæŸ¥è¯¢
     *
     * @param pageWrap åˆ†é¡µå¯¹è±¡
     * @return PageData<DeviceData>
     */
    PageData<DeviceData> findPage(PageWrap<DeviceData> pageWrap);
    /**
     * æ¡ä»¶ç»Ÿè®¡
     *
     * @param deviceData å®žä½“对象
     * @return long
     */
    long count(DeviceData deviceData);
}
server/visits/dmvisit_service/src/main/java/com/doumee/service/business/DeviceService.java
@@ -5,6 +5,8 @@
import com.doumee.service.business.third.model.PageData;
import com.doumee.service.business.third.model.PageWrap;
import com.doumee.dao.business.model.Device;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import java.util.List;
/**
@@ -13,6 +15,7 @@
 * @date 2023/11/30 15:33
 */
public interface DeviceService {
    /**
     * åˆ›å»º
@@ -109,4 +112,11 @@
    void setBroadcaseBobao(Device body);
    String setBroadcaseBobaoHttp(Device body);
    void duanluqiCmd(Device param);
    void updateUsedById(Device d);
    void autoCloseCmdTimer();
    void startCheckDuanluqiSubjob();
}
server/visits/dmvisit_service/src/main/java/com/doumee/service/business/impl/DeviceDataServiceImpl.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,161 @@
package com.doumee.service.business.impl;
import com.doumee.core.utils.Utils;
import com.doumee.dao.business.DeviceDataMapper;
import com.doumee.dao.business.model.DeviceData;
import com.doumee.service.business.DeviceDataService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.doumee.service.business.third.model.PageData;
import com.doumee.service.business.third.model.PageWrap;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import java.util.List;
/**
 * é—¨ç¦äº‹ä»¶æŽ¨é€è®°å½•表Service实现
 * @author æ±Ÿè¹„蹄
 * @date 2025/12/25 10:04
 */
@Service
public class DeviceDataServiceImpl implements DeviceDataService {
    @Autowired
    private DeviceDataMapper deviceDataMapper;
    @Override
    public Integer create(DeviceData deviceData) {
        deviceDataMapper.insert(deviceData);
        return deviceData.getId();
    }
    @Override
    public void deleteById(Integer id) {
        deviceDataMapper.deleteById(id);
    }
    @Override
    public void delete(DeviceData deviceData) {
        UpdateWrapper<DeviceData> deleteWrapper = new UpdateWrapper<>(deviceData);
        deviceDataMapper.delete(deleteWrapper);
    }
    @Override
    public void deleteByIdInBatch(List<Integer> ids) {
        if (CollectionUtils.isEmpty(ids)) {
            return;
        }
        deviceDataMapper.deleteBatchIds(ids);
    }
    @Override
    public void updateById(DeviceData deviceData) {
        deviceDataMapper.updateById(deviceData);
    }
    @Override
    public void updateByIdInBatch(List<DeviceData> deviceDatas) {
        if (CollectionUtils.isEmpty(deviceDatas)) {
            return;
        }
        for (DeviceData deviceData: deviceDatas) {
            this.updateById(deviceData);
        }
    }
    @Override
    public DeviceData findById(Integer id) {
        return deviceDataMapper.selectById(id);
    }
    @Override
    public DeviceData findOne(DeviceData deviceData) {
        QueryWrapper<DeviceData> wrapper = new QueryWrapper<>(deviceData);
        return deviceDataMapper.selectOne(wrapper);
    }
    @Override
    public List<DeviceData> findList(DeviceData deviceData) {
        QueryWrapper<DeviceData> wrapper = new QueryWrapper<>(deviceData);
        return deviceDataMapper.selectList(wrapper);
    }
    @Override
    public PageData<DeviceData> findPage(PageWrap<DeviceData> pageWrap) {
        IPage<DeviceData> page = new Page<>(pageWrap.getPage(), pageWrap.getCapacity());
        QueryWrapper<DeviceData> queryWrapper = new QueryWrapper<>();
        Utils.MP.blankToNull(pageWrap.getModel());
        if (pageWrap.getModel().getId() != null) {
            queryWrapper.lambda().eq(DeviceData::getId, pageWrap.getModel().getId());
        }
        if (pageWrap.getModel().getCreator() != null) {
            queryWrapper.lambda().eq(DeviceData::getCreator, pageWrap.getModel().getCreator());
        }
        if (pageWrap.getModel().getCreateDate() != null) {
            queryWrapper.lambda().ge(DeviceData::getCreateDate, Utils.Date.getStart(pageWrap.getModel().getCreateDate()));
            queryWrapper.lambda().le(DeviceData::getCreateDate, Utils.Date.getEnd(pageWrap.getModel().getCreateDate()));
        }
        if (pageWrap.getModel().getEditor() != null) {
            queryWrapper.lambda().eq(DeviceData::getEditor, pageWrap.getModel().getEditor());
        }
        if (pageWrap.getModel().getEditDate() != null) {
            queryWrapper.lambda().ge(DeviceData::getEditDate, Utils.Date.getStart(pageWrap.getModel().getEditDate()));
            queryWrapper.lambda().le(DeviceData::getEditDate, Utils.Date.getEnd(pageWrap.getModel().getEditDate()));
        }
        if (pageWrap.getModel().getIsdeleted() != null) {
            queryWrapper.lambda().eq(DeviceData::getIsdeleted, pageWrap.getModel().getIsdeleted());
        }
        if (pageWrap.getModel().getRemark() != null) {
            queryWrapper.lambda().eq(DeviceData::getRemark, pageWrap.getModel().getRemark());
        }
        if (pageWrap.getModel().getDataJson() != null) {
            queryWrapper.lambda().eq(DeviceData::getDataJson, pageWrap.getModel().getDataJson());
        }
        if (pageWrap.getModel().getDeviceId() != null) {
            queryWrapper.lambda().eq(DeviceData::getDeviceId, pageWrap.getModel().getDeviceId());
        }
        if (pageWrap.getModel().getHappenTime() != null) {
            queryWrapper.lambda().eq(DeviceData::getHappenTime, pageWrap.getModel().getHappenTime());
        }
        if (pageWrap.getModel().getVal1() != null) {
            queryWrapper.lambda().eq(DeviceData::getVal1, pageWrap.getModel().getVal1());
        }
        if (pageWrap.getModel().getVal2() != null) {
            queryWrapper.lambda().eq(DeviceData::getVal2, pageWrap.getModel().getVal2());
        }
        if (pageWrap.getModel().getVal3() != null) {
            queryWrapper.lambda().eq(DeviceData::getVal3, pageWrap.getModel().getVal3());
        }
        if (pageWrap.getModel().getVal4() != null) {
            queryWrapper.lambda().eq(DeviceData::getVal4, pageWrap.getModel().getVal4());
        }
        if (pageWrap.getModel().getVal5() != null) {
            queryWrapper.lambda().eq(DeviceData::getVal5, pageWrap.getModel().getVal5());
        }
        if (pageWrap.getModel().getVal6() != null) {
            queryWrapper.lambda().eq(DeviceData::getVal6, pageWrap.getModel().getVal6());
        }
        if (pageWrap.getModel().getDataType() != null) {
            queryWrapper.lambda().eq(DeviceData::getDataType, pageWrap.getModel().getDataType());
        }
        queryWrapper.lambda().orderByDesc(DeviceData::getHappenTime);
        for(PageWrap.SortData sortData: pageWrap.getSorts()) {
            if (sortData.getDirection().equalsIgnoreCase(PageWrap.DESC)) {
                queryWrapper.orderByDesc(sortData.getProperty());
            } else {
                queryWrapper.orderByAsc(sortData.getProperty());
            }
        }
        return PageData.from(deviceDataMapper.selectPage(page, queryWrapper));
    }
    @Override
    public long count(DeviceData deviceData) {
        QueryWrapper<DeviceData> wrapper = new QueryWrapper<>(deviceData);
        return deviceDataMapper.selectCount(wrapper);
    }
}
server/visits/dmvisit_service/src/main/java/com/doumee/service/business/impl/DeviceServiceImpl.java
@@ -11,14 +11,15 @@
import com.doumee.core.haikang.model.param.request.CustomBroadcastRequest;
import com.doumee.core.haikang.model.param.request.TransparentChannelSingleRequest;
import com.doumee.core.haikang.service.HKService;
import com.doumee.core.utils.HttpsUtil;
import com.doumee.core.utils.*;
import com.doumee.dao.business.*;
import com.doumee.dao.business.model.*;
import com.doumee.mqtt.config.MqttConfig;
import com.doumee.mqtt.service.MqttBizService;
import com.doumee.service.business.impl.mqtt.MqttClientCache;
import com.doumee.service.business.third.model.LoginUserInfo;
import com.doumee.service.business.third.model.PageData;
import com.doumee.service.business.third.model.PageWrap;
import com.doumee.core.utils.Constants;
import com.doumee.core.utils.Utils;
import com.doumee.service.business.DeviceService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
@@ -28,11 +29,14 @@
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.eclipse.paho.client.mqttv3.MqttClient;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import java.util.*;
import java.util.Date;
import java.util.stream.Collectors;
/**
@@ -45,7 +49,11 @@
public class DeviceServiceImpl implements DeviceService {
    @Autowired
    private MqttBizService mqttBizService;
    @Autowired
    private DeviceMapper deviceMapper;
    @Autowired
    private DeviceDataMapper deviceDataMapper;
    @Autowired
    private PlatformMapper platformMapper;
    @Autowired
@@ -65,6 +73,14 @@
        model.setIsdeleted(Constants.ZERO);
        model.setEditDate(new Date());
        model.setCreateDate(model.getEditDate());
        if(model.getDoorNameObj()!=null && Constants.equalsInteger(model.getType(),Constants.DEVICE_TYPE.duanluqi)){
            model.setDoorName(JSONObject.toJSONString(model.getDoorNameObj()));
            if(StringUtils.isNotBlank(model.getLevel())){
                if(getNumberByStr(model.getLevel()) <300){
                    throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(),"对不起,控制时长必须大于等于300秒");
                }
            }
        }
        deviceMapper.insert(model);
        return model.getId();
    }
@@ -99,6 +115,9 @@
    public void updateById(Device device) {
        device.setEdirot(device.getLoginUserInfo().getId()+"");
        device.setEditDate(new Date());
        if(device.getDoorNameObj()!=null && Constants.equalsInteger(device.getType(),Constants.DEVICE_TYPE.duanluqi)){
            device.setDoorName(JSONObject.toJSONString(device.getDoorNameObj()));
        }
        deviceMapper.updateById(device);
    }
@@ -114,7 +133,16 @@
    @Override
    public Device findById(Integer id) {
        return deviceMapper.selectById(id);
        Device d = deviceMapper.selectById(id);
        if(StringUtils.isNotBlank(d.getDoorName()) &&Constants.equalsInteger(d.getType(),Constants.DEVICE_TYPE.duanluqi)){
            try {
                //断路器设备参数
                d.setDoorNameObj(JSONObject.parseObject(d.getDoorName()));
            }catch (Exception e){
            }
        }
        return d;
    }
    @Override
@@ -138,7 +166,20 @@
               .eq(null !=param.getIsdeleted(),Device::getIsdeleted,param.getIsdeleted())
               .eq(Objects.isNull(param.getIsdeleted()),Device::getIsdeleted,Constants.ZERO)
               .eq(null != param.getHkStatus(),Device::getHkStatus,param.getHkStatus());
        return deviceMapper.selectList(wrapper);
        List<Device> list = deviceMapper.selectList(wrapper);
        if(list!=null){
            for(Device d : list){
                if(StringUtils.isNotBlank(d.getDoorName()) &&Constants.equalsInteger(d.getType(),Constants.DEVICE_TYPE.duanluqi)){
                    try {
                        //断路器设备参数
                        d.setDoorNameObj(JSONObject.parseObject(d.getDoorName()));
                    }catch (Exception e){
                    }
                }
            }
        }
        return list;
    }
  
    @Override
@@ -247,7 +288,20 @@
                queryWrapper.orderByAsc(sortData.getProperty());
            }
        }
        return PageData.from(deviceMapper.selectPage(page, queryWrapper));
        IPage<Device> result = deviceMapper.selectPage(page, queryWrapper);
        if(result!=null){
            for(Device d : result.getRecords()){
                if(StringUtils.isNotBlank(d.getDoorName()) &&Constants.equalsInteger(d.getType(),Constants.DEVICE_TYPE.duanluqi)){
                    try {
                        //断路器设备参数
                        d.setDoorNameObj(JSONObject.parseObject(d.getDoorName()));
                    }catch (Exception e){
                    }
                }
            }
        }
        return PageData.from(result);
    }
    @Override
@@ -271,6 +325,125 @@
        if(response == null || !StringUtils.equals(response.getCode(), HKConstants.RESPONSE_SUCCEE)){
          throw  new BusinessException(ResponseStatus.SERVER_ERROR.getCode(),"发送失败:"+ JSONObject.toJSONString(response));
        }
    }
    @Override
    public   void updateUsedById(Device param){
        Device model = deviceMapper.selectById(param.getId());
        if(model ==null && Constants.equalsInteger(param.getType(),Constants.DEVICE_TYPE.duanluqi)){
            throw  new BusinessException(ResponseStatus.DATA_EMPTY);
        }
        MqttConfig config = getMqttConfigByParam(model,"device_");
        MqttClient mqttClient = MqttClientCache.clientMapCache.get("device"+param.getId());
        String[] topics =new String[]{Constants.MqttTopic.mts_status,
                Constants.MqttTopic.mts_attr,
                Constants.MqttTopic.mts_resp};
        if(Constants.equalsInteger(param.getIsUsed(),Constants.ONE)){
            //如果系统不用了,端口mqtt连接
            try {
                mqttClient = mqttBizService.unsubscribe(mqttClient,config  ,topics);
                if(mqttClient ==null){
                    throw new BusinessException(ResponseStatus.SERVER_ERROR.getCode(),"建立连接失败!");
                }
                if(mqttClient.isConnected()){
                    mqttClient.disconnect();
                }
            }catch (Exception e){
                log.error("==============端口mqtt链接失败:"+model.getName()+e.getMessage());
            }
        }else{
            //如果开始使用,开始订阅
            mqttClient = mqttBizService.subscribe(mqttClient,config ,topics);
            if(mqttClient ==null){
                throw new BusinessException(ResponseStatus.SERVER_ERROR.getCode(),"建立连接失败!");
            }
            MqttClientCache.clientMapCache.put("device"+param.getId(),mqttClient);
        }
        this.updateById(param);
    }
    @Override
    public  void duanluqiCmd(Device param){
        Device model = deviceMapper.selectById(param.getId());
        if(model ==null && Constants.equalsInteger(param.getType(),Constants.DEVICE_TYPE.duanluqi)){
            throw  new BusinessException(ResponseStatus.DATA_EMPTY);
        }
        dealDuanluqiCmd(model,param,"device_");
    }
    private void dealDuanluqiCmd(Device model, Device param,String clientIndex) {
        MqttConfig config = getMqttConfigByParam(model,clientIndex);
        MqttClient mqttClient = MqttClientCache.clientMapCache.get("device"+param.getId());
        String cmdTopic = Constants.MqttTopic.mts_cmd.replace("$CATE",model.getNo()).replace("$DEVID",model.getDoorNo());
        if(Constants.equalsInteger(param.getStatus(),Constants.ONE)){
            //如果是开闸,先解锁
            String cmdParamAction = CmdContants.T30A.cmdParam.replace("$DEVID", model.getDoorNo())
                    .replace("$CMD",  CmdContants.T30ACmd.do_err_clear)//异常解锁
                    .replace("$BUSADDR",model.getChannelNo());
            mqttClient = mqttBizService.publish(mqttClient,config,cmdTopic, cmdParamAction);//解锁命令
            if(mqttClient ==null){
                throw new BusinessException(ResponseStatus.SERVER_ERROR.getCode(),"指令发送失败!");
            }
        }
        String cmdParamAction =CmdContants.T30A.cmdParam.replace("$DEVID", model.getDoorNo())
                .replace("$CMD",(Constants.equalsInteger(param.getStatus(),Constants.ONE)?CmdContants.T30ACmd.do_turn_on:CmdContants.T30ACmd.do_turn_off))
                .replace("$BUSADDR", param.getChannelNo());
        mqttClient = mqttBizService.publish(mqttClient,config,cmdTopic, cmdParamAction);//开关闸命令
        if(mqttClient ==null){
            throw new BusinessException(ResponseStatus.SERVER_ERROR.getCode(),"指令发送失败!");
        }
        MqttClientCache.clientMapCache.put("device"+param.getId(),mqttClient);
        String curremak = "【"+param.getLoginUserInfo().getRealname()
                +"】于"+ DateUtil.getPlusTime2(new Date()) +"进行了"+(Constants.equalsInteger(param.getStatus(),Constants.ONE)?"【开闸】":"【关闸】")+"操作,开关【"+param.getChannelNo()+"】;";
        deviceMapper.update(null,new UpdateWrapper<Device>().lambda()
//                        .setSql("remark = concat(ifnull(remark,''),'"+curremak+"','\n')")
                .set(Device::getRemark,curremak)
                .set(Device::getEditDate,new Date())
                .set(Device::getEdirot,param.getLoginUserInfo().getId())
                .eq(Device::getId,param.getId()));
    }
    private MqttConfig getMqttConfigByParam(Device model,String index) {
        MqttConfig config = new MqttConfig();
        JSONObject mqtt = new JSONObject();
        if(StringUtils.isBlank(model.getNo())
                ||StringUtils.isBlank(model.getDoorNo()) ){
            throw  new BusinessException(ResponseStatus.BAD_REQUEST.getCode(),"对不起,设备标识符和设备号未配置!");
        }
        if(StringUtils.isNotBlank(model.getDoorName())){
            try {
                //断路器设备参数
                mqtt = (JSONObject.parseObject(model.getDoorName()));
            }catch (Exception e){
            }
        }
        if(mqtt == null
                ||StringUtils.isBlank(mqtt.getString("mqttUsername"))
                ||StringUtils.isBlank(mqtt.getString("mqttIp"))
                ||StringUtils.isBlank(mqtt.getString("mqttPort"))
                ||StringUtils.isBlank(mqtt.getString("mqttPassword"))){
            throw  new BusinessException(ResponseStatus.BAD_REQUEST.getCode(),"对不起,设备mqtt服务参数配置不正确!");
        }
        /**
         *   MqttConfig config = (new MqttConfig());
         *         config.setHost("tcp://192.168.0.7:1883");
         *         config.setClientid("doumee1");
         *         config.setPassword("doumee@168");
         *         config.setUsername("doumee");
         *         config.setVersion("003");
         */
        config.setVersion("003");
        config.setUsername( mqtt.getString("mqttUsername"));
        config.setPassword( mqtt.getString("mqttPassword"));
        config.setHost("tcp://"+ mqtt.getString("mqttIp")+":"+mqtt.getString("mqttPort"));
        config.setClientid(index+model.getId());
        return config;
    }
    public  void mqttCallbackService(String topic, MqttMessage message){
       log.error("mqtt收到消息=====topic:",topic);
       log.error("mqtt收到消息=====message:",JSONObject.toJSONString(message));
    }
    @Override
    public String setBroadcaseBobaoHttp(Device param){
@@ -382,4 +555,145 @@
        }
        log.error( "屏幕内容设置=======================结束========" );
    }
    /**
     * æœåŠ¡å¼€å¯è®¢é˜…ä»»åŠ¡
     */
    @Override
    public   void startCheckDuanluqiSubjob() {
        List<Device> devices = deviceMapper.selectList(new QueryWrapper<Device>().lambda()
                .eq(Device::getType,Constants.DEVICE_TYPE.duanluqi)//断路器
                .eq(Device::getIsUsed,Constants.ZERO)
                .eq(Device::getIsdeleted,Constants.ZERO)
        );
        if(devices!=null && devices.size()>0){
            for (Device model : devices){
                try {
                    MqttConfig config = getMqttConfigByParam(model,"device_");
                    MqttClient mqttClient = MqttClientCache.clientMapCache.get("device"+model.getId());
                    String[] topics =new String[]{Constants.MqttTopic.mts_status,
                            Constants.MqttTopic.mts_attr,
                            Constants.MqttTopic.mts_resp};
                        //如果开始使用,开始订阅
                    mqttClient = mqttBizService.subscribe(mqttClient,config ,topics);
                    if(mqttClient ==null){
                        throw new BusinessException(ResponseStatus.SERVER_ERROR.getCode(),"建立连接失败!");
                    }
                    MqttClientCache.clientMapCache.put("device"+model.getId(),mqttClient);
                    log.error("=======开始自动定于mqtt任务完成:"+model.getName() );
                }catch (Exception e){
                    log.error("=======开始自动定于mqtt任务失败:"+model.getName()+e.getMessage());
                }
            }
        }
    }
    /**
     * æ–­è·¯å™¨åˆ¤æ–­æ˜¯å¦éœ€è¦è¿œç¨‹åˆ†é—¸å®šäººä»»åŠ¡
     */
    @Override
    public   void autoCloseCmdTimer(){
        if(Constants.DEALING_DUANLUQI_CLOSE){
            return;
        }
        log.error("开启定时远程控制断路器开始=========");
        Constants.DEALING_DUANLUQI_CLOSE = true;
        try {
            List<Device> devices = deviceMapper.selectList(new QueryWrapper<Device>().lambda()
                    .eq(Device::getType,Constants.DEVICE_TYPE.duanluqi)//断路器
                    .isNotNull(Device::getLevel)//配置了空闲时长限制
                    .isNotNull(Device::getDoorName)//配置了MQTT参数
                    .isNotNull(Device::getChannelInfo)//配置了控制开关序号
                    .eq(Device::getIsUsed,Constants.ZERO)
                    .eq(Device::getIsdeleted,Constants.ZERO)
            );
            if(devices!=null && devices.size()>0){
                for(Device device : devices){
                    try {
                        long time = (long)getNumberByStr(device.getLevel());//控制时长
                        if(time < 300 ){
                            log.error("开启定时远程控制断路器分闸失败=========空闲时长未正确配置"+time);
                            continue;
                        }
                        double closeDianliu = getCloseDianliuByParam(device);
                        if(closeDianliu < 0 ){
                            log.error("开启定时远程控制断路器分闸失败=========空闲电流阈值设置错误"+closeDianliu);
                            continue;
                        }
                        List<String> closeBtn = new ArrayList<>();
                        String[] btns = device.getChannelInfo().split(",");
                        Date startDate = new Date((System.currentTimeMillis()-time*1000));//查询开始时间
                        List<DeviceData> dataList = deviceDataMapper.selectList(new QueryWrapper<DeviceData>().lambda()
                                .eq(DeviceData::getDeviceId,device.getId())
                                .in(DeviceData::getVal1,btns)
                                .ge(DeviceData::getHappenTime,DateUtil.getPlusTime2(startDate))
                                .orderByDesc(DeviceData::getHappenTime));
                        if(dataList != null && dataList.size()>0 ){
                           for(String b : btns){
                               DeviceData last = getLastDataByVal1(b,dataList,closeDianliu);
                               if(last !=null && StringUtils.equals(last.getVal7(),"1")){
                                   closeBtn.add(b);//需要分闸
                               }
                           }
                           if(StringUtils.equals( dataList.get(0).getVal7(),"0")){
                               log.error("开启定时远程控制断路器分闸结束======分闸状态无需操作==="+device.getName());
                               continue;
                           }
                        }
                        if(closeBtn.size()>0){
                            Device param = new Device();
                            param.setLoginUserInfo(new LoginUserInfo());
                            param.getLoginUserInfo().setRealname("系统自动控制");
                            param.setChannelNo(String.join(",",closeBtn));
                            param.setId(device.getId());
                            param.setStatus(Constants.ZERO);
                            dealDuanluqiCmd(device,param,"deviceTimer_");
                        }
                    }catch (Exception e){
                        log.error("开启定时远程控制断路器分闸失败========="+device.getName()+e.getMessage());
                    }
                }
            }
            log.error("开启定时远程控制断路器分闸数量========="+devices.size());
        }catch (Exception e){
            log.error("开启定时远程控制断路器分闸异常========="+e.getMessage());
        }finally {
            Constants.DEALING_DUANLUQI_CLOSE = false;
        }
        log.error("开启定时远程控制断路器分闸结束=========");
    }
    private double getCloseDianliuByParam(Device device) {
        try {
            JSONObject json = JSONObject.parseObject(device.getDoorName() );
            return json.getDouble("max");
        }catch (Exception e){
        }
        return 0;
    }
    private DeviceData getLastDataByVal1(String b, List<DeviceData> dataList,double limit) {
        List<DeviceData> list = new ArrayList<>();
        for(DeviceData d :dataList){
            if(StringUtils.equals(d.getVal1(),b)){
                if(limit <= getNumberByStr(d.getVal2())){
                    //如果有实时电流值大于空闲阈值,则表示工作中,不做处理
                    return null;
                }
                list.add(d);
            }
        }
        return list.size()>0?list.get(0):null;
    }
    private double getNumberByStr(String level) {
        try {
            return Double.parseDouble(level);
        }catch (Exception e){
        }
        return 0;
    }
}
server/visits/dmvisit_service/src/main/java/com/doumee/service/business/impl/mqtt/MqttClientCache.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,9 @@
package com.doumee.service.business.impl.mqtt;
import org.eclipse.paho.client.mqttv3.MqttClient;
import java.util.LinkedHashMap;
public class MqttClientCache {
    public static  LinkedHashMap<String, MqttClient> clientMapCache = new LinkedHashMap<>();
}
server/visits/dmvisit_service/src/main/java/com/doumee/service/business/impl/mqtt/MqttPushCallback.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,141 @@
package com.doumee.service.business.impl.mqtt;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.doumee.core.utils.Constants;
import com.doumee.core.utils.DateUtil;
import com.doumee.dao.business.DeviceDataMapper;
import com.doumee.dao.business.DeviceMapper;
import com.doumee.dao.business.model.Device;
import com.doumee.dao.business.model.DeviceData;
import com.doumee.mqtt.config.MqttClientInit;
import com.doumee.mqtt.config.MqttConfig;
import com.doumee.mqtt.service.MqttBizService;
import com.doumee.service.business.DeviceService;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.util.DataUtils;
import org.apache.commons.lang3.StringUtils;
import org.eclipse.paho.client.mqttv3.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
 * @author T14
 */
@Service
@Slf4j
public class MqttPushCallback implements MqttCallback {
        @Autowired
        private DeviceMapper deviceMapper;
        @Autowired
        private DeviceDataMapper deviceDataMapper;
        @Override
        public void connectionLost(Throwable cause) {
            // è¿žæŽ¥ä¸¢å¤±åŽï¼Œä¸€èˆ¬åœ¨è¿™é‡Œé¢è¿›è¡Œé‡è¿ž
           log.error("连接断开,重连中");
            MqttClientInit.refreshClient();
        }
        @Override
        public void deliveryComplete(IMqttDeliveryToken token) {
           log.error("deliveryComplete---------" + token.isComplete());
        }
        @Override
        public void messageArrived(String topic, MqttMessage message) throws Exception {
            // subscribe后得到的消息会执行到这里面
            try {
                Date date = new Date();
               log.error("接收消息主题 : " + DateUtil.getPlusTime2(date) + topic);
               log.error("接收消息Qos : " + DateUtil.getPlusTime2(date) +  message.getQos());
               log.error("接收消息内容 : " +  DateUtil.getPlusTime2(date) + new String(message.getPayload()));
                //  ------------TODO-----------监听数据
                //-----------------/dev/MTS/98CC4D121E5A/status/json
                if(StringUtils.contains(topic,"/status/json")){
                    dealDeviceDataT30A(topic,message);
                }
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    private void dealDeviceDataT30A(String topic, MqttMessage message) {
        try {
            Date date = new Date();
            //如果是空开上报数据
            String t[] = topic.replace("/dev/","").replace("/status/json","").split("/");
            String no =t[0];
            String doorNo = t[1];
            Device device = deviceMapper.selectOne(new QueryWrapper<Device>().lambda()
                    .eq(Device::getNo,no)
                    .eq(Device::getIsdeleted,no)
                    .eq(Device::getDoorNo,doorNo));
            if(device!=null && Constants.equalsInteger(device.getIsUsed(),Constants.ZERO)){
                //如果设备存在并且设备在用,记录上报数据
                List<DeviceData> dataList = new ArrayList<>();
                JSONObject jsob = JSONObject.parseObject(new String(message.getPayload()));
                if(jsob.getJSONArray("data")!=null && jsob.getJSONArray("data").size()>0){
                    for (int i = 0; i <  jsob.getJSONArray("data").size(); i++) {
                        JSONObject jsonObject = jsob.getJSONArray("data").getJSONObject(i);
                        DeviceData data = new DeviceData();
                        data.setDataJson(jsob.toJSONString());
                        data.setCreateDate(date);
                        data.setEditDate(date);
                        data.setVal2("0");//电流值
                        data.setVal3("0");
                        data.setVal4("0");
                        data.setVal5("0");
                        data.setVal6("0");
                        data.setHappenTime(DateUtil.getPlusTime2(new Date(jsob.getLong("timeMS"))));
                        //模块序号
                        if(jsonObject.getJSONObject("mcbComSta")!=null
                                && jsonObject.getJSONObject("mcbComSta").getString("busAddr")!=null){
                            data.setVal1(jsonObject.getJSONObject("mcbComSta").getString("busAddr"));
                            //<0>表示分闸,<1>表示合闸,无符号
                            data.setVal7(jsonObject.getJSONObject("mcbComSta").getString("on"));
                        }
                        if(jsonObject.getJSONObject("mcbSta")!=null){
                            //电流
                            if(jsonObject.getJSONObject("mcbSta").getString("cur")!=null){
                                data.setVal2(jsonObject.getJSONObject("mcbSta").getString("cur"));
                            }
                            //电压
                            if(jsonObject.getJSONObject("mcbSta").getString("vol")!=null){
                                data.setVal3(jsonObject.getJSONObject("mcbSta").getString("vol"));
                            }
                            //温度
                            if(jsonObject.getJSONObject("mcbSta").getString("tmp")!=null){
                                data.setVal4(jsonObject.getJSONObject("mcbSta").getString("tmp"));
                            }
                            //有功功率值,单位kW
                            if(jsonObject.getJSONObject("mcbSta").getString("pwrP")!=null){
                                data.setVal5(jsonObject.getJSONObject("mcbSta").getString("pwrP"));
                            }
                            //N相电流值,单位A
                            if(jsonObject.getJSONObject("mcbSta").getString("curN")!=null){
                                data.setVal6(jsonObject.getJSONObject("mcbSta").getString("curN"));
                            }
                        }
                        data.setDeviceId(device.getId().toString());
                        data.setDataType(Constants.ZERO);
                        if(StringUtils.isNotBlank(data.getVal1())){
                            dataList.add(data );
                        }
                    }
                }
                if(dataList.size()>0){
                    deviceDataMapper.insert(dataList);
                }
            }
        }catch (Exception e){
            log.error("===============topic数据记录失败:"+topic+e.getMessage());
        }
    }
}
server/visits/dmvisit_service/src/main/java/com/doumee/service/business/impl/mqtt/MqttSubServiceImpl.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,43 @@
package com.doumee.service.business.impl.mqtt;
import com.alibaba.fastjson.JSONObject;
import com.doumee.mqtt.config.MqttConfig;
import com.doumee.mqtt.service.MqttBizService;
import com.doumee.mqtt.service.MqttToolService;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.paho.client.mqttv3.MqttClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
 *  ä¸Žç¡¬ä»¶å¯¹æŽ¥æœåŠ¡
 * @author æ±Ÿè¹„蹄
 * @date 2023/10/09 18:06
 */
@Service
@Slf4j
public class MqttSubServiceImpl implements MqttBizService {
    @Autowired
    private MqttPushCallback callBack ;
    @Override
    public MqttClient subscribe(MqttClient client,MqttConfig config,String[] topics){
        log.error("mqtt订阅开始========开始"+ JSONObject.toJSONString(config));
        client = MqttToolService.subscribe(client,config, topics,callBack);
        log.error("mqtt订阅开始========结束"+ JSONObject.toJSONString(config));
        return client;
    }
    @Override
    public MqttClient unsubscribe(MqttClient client,MqttConfig config,String[] topics){
        log.error("mqtt订阅开始========开始"+ JSONObject.toJSONString(config));
        client = MqttToolService.unsubscribe(client,config, topics,callBack);
        log.error("mqtt订阅开始========结束"+ JSONObject.toJSONString(config));
        return client;
    }
    @Override
    public MqttClient publish(MqttClient client,MqttConfig config, String topic, String param){
        log.error("mqtt发布消息========开始"+ JSONObject.toJSONString(config)+"\n"+param);
        client = MqttToolService.pubMessage(client,config,param,topic,callBack);
        log.error("mqtt发布消息========结束"+ JSONObject.toJSONString(config));
        return client;
    }
}