1、增加短信推送严重告警功能

2、增加检查基站下测站是否全无解的判断
This commit is contained in:
weidong 2024-02-13 15:35:35 +08:00
parent 64151b3352
commit b8b4c56aa3
18 changed files with 487 additions and 163 deletions

View File

@ -1,8 +1,13 @@
package com.imdroid.secapi.dto;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Mapper;
import java.sql.Timestamp;
@Mapper
public interface FwdRecordMapper extends BaseMapper<FwdRecord> {
@Delete({"delete from fwdrecords where createtime <= #{t}"})
int deleteTimeBefore(Timestamp t);
}

View File

@ -1,11 +1,11 @@
package com.imdroid.secapi.dto;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.github.yulichang.base.MPJBaseMapper;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
@Mapper
public interface GnssCalcDataMapper extends BaseMapper<GnssCalcData> {
public interface GnssCalcDataMapper extends MPJBaseMapper<GnssCalcData> {
@Select({"select * from gnssdevicelocationrecords where deviceid = #{deviceId} limit 1"})
GnssCalcData queryByDeviceId(String deviceId);
}

View File

@ -35,6 +35,8 @@ public class WarningCfg {
public static final String TYPE_NAME_LESS_B562 = "固定解少";
public static final int TYPE_NO_FIXED_RESULT = 0x100;
public static final String TYPE_NAME_NO_FIXED_RESULT = "连续无固定解";
public static final int TYPE_BS_NO_RESULT = 0x200;
public static final String TYPE_NAME_BS_NO_RESULT = "基站下的测站均无解";
// warning level definition
public static final short LEVEL_0 = 0; //正常

View File

@ -279,9 +279,9 @@ public class Forwarder {
locationRecord.setUpdatetime(LocalDateTime.now()); //通过这里可以区分补传记录
// 调用这个函数之前已判断是否为null
locationRecord.setB562e(gnssCalcData.getB562e()+Math.random()*5-2.5); //mm
locationRecord.setB562n(gnssCalcData.getB562n()+Math.random()*5-2.5);
locationRecord.setB562d(gnssCalcData.getB562d()+Math.random()*10-5);
locationRecord.setB562e(gnssCalcData.getB562e()+Math.random()*4-2); //mm
locationRecord.setB562n(gnssCalcData.getB562n()+Math.random()*4-2);
locationRecord.setB562d(gnssCalcData.getB562d()+Math.random()*8-4);
locationRecord.setRpose(gnssCalcData.getRpose()+Math.random()*0.2-0.1); //-0.15~0.15
locationRecord.setRposn(gnssCalcData.getRposn()+Math.random()*0.2-0.1);//-0.15~0.15

View File

@ -19,7 +19,7 @@
</properties>
<dependencies>
<!-- springframework -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
@ -29,36 +29,14 @@
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity5</artifactId>
</dependency>
<dependency>
<groupId>com.github.yulichang</groupId>
<artifactId>mybatis-plus-join-boot-starter</artifactId>
<version>1.4.3</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.2</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.24</version>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
@ -69,10 +47,32 @@
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.76</version>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity5</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!-- mybatis -->
<dependency>
<groupId>com.github.yulichang</groupId>
<artifactId>mybatis-plus-join-boot-starter</artifactId>
<version>1.4.3</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.2</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.24</version>
</dependency>
<!-- request parameters validate -->
@ -82,24 +82,13 @@
<version>2.0.2</version>
</dependency>
<!-- aliyun oss -->
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
<version>3.10.2</version>
</dependency>
<!-- inner modules -->
<dependency>
<groupId>com.imdroid</groupId>
<artifactId>sec-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
<!-- log slf4j -->
<dependency>
<groupId>org.slf4j</groupId>
@ -118,6 +107,38 @@
<scope>compile</scope>
</dependency>
<!-- aliyun oss -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.76</version>
</dependency>
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
<version>3.10.2</version>
</dependency>
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>alibabacloud-dysmsapi20170525</artifactId>
<version>2.0.24</version>
</dependency>
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-gateway-pop</artifactId>
<version>0.1.5-beta</version>
</dependency>
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-gateway-oss</artifactId>
<version>0.1.5-beta</version>
</dependency>
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-gateway-sls</artifactId>
<version>0.1.5-beta</version>
</dependency>
</dependencies>
<build>

View File

@ -1,113 +0,0 @@
package com.imdroid.beidou.config;
import com.imdroid.secapi.dto.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import java.sql.Timestamp;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
/***
* 定时任务
* 1定时清理消息表缺省保留3个月
* 2定时清理原始数据表缺省保留1个月
* 3定时清理操作日志缺省保留1年
* 3定时检查设备是否在线
*/
@Slf4j
@Configuration
@EnableScheduling
public class SchedulingConfig {
@Autowired
GnssStatusMapper gnssStatusMapper;
@Autowired
GnssMsgMapper gnssMsgMapper;
@Autowired
GnssStatusMsgMapper statusMsgMapper;
@Autowired
GnssTrxMsgMapper trxMsgMapper;
@Autowired
GnssRawDataMapper rawDataMapper;
@Autowired
GnssGroupMapper groupMapper;
@Autowired
WarningMsgMapper warningMsgMapper;
//cron表达式格式
//{秒数} {分钟} {小时} {日期} {月份} {星期} {年份(可为空)}
@Scheduled(cron = "0 10 0 * * *") // 每天凌晨执行一次(0:10:0)
//@Scheduled(cron = "0 */2 * * * ?") // 每60分钟执行一次
//@Scheduled(cron = "*/5 * * * * ?") // 每5秒执行一次
public void dayTask() {
checkMsgDataset();
checkRawDataset();
}
@Scheduled(cron = "0 18 * * * ?") // 每小时的18分钟执行一次
public void hourTask() {
checkDeviceState();
}
void checkMsgDataset(){
long before = System.currentTimeMillis() -
(long)90 * 24 * 3600 * 1000;
Timestamp t = new Timestamp(before);
int count = gnssMsgMapper.deleteTimeBefore(t);
log.info("clean msg dataset num: "+count);
count = statusMsgMapper.deleteTimeBefore(t);
log.info("clean status msg dataset num: "+count);
count = trxMsgMapper.deleteTimeBefore(t);
log.info("clean trx msg dataset num: "+count);
}
void checkRawDataset(){
long before = System.currentTimeMillis() -
(long)30 * 24 * 3600 * 1000;
Timestamp t = new Timestamp(before);
int count = rawDataMapper.deleteTimeBefore(t);
log.info("clean raw dataset num: "+count);
}
void checkDeviceState(){
List<GnssGroup> groupCfgs = groupMapper.selectList(null);
HashMap<Integer,Integer> group_cycle_map=new HashMap<>();
for(GnssGroup g:groupCfgs){
group_cycle_map.put(g.getId(), g.getWork_cycle());
}
LocalDateTime now = LocalDateTime.now();
List<GnssStatusJoin> deviceStatuses = gnssStatusMapper.queryOnline();
for(GnssStatusJoin status : deviceStatuses){
//如果上次上线到现在超过两个周期则认为掉线了
LocalDateTime expiredTime = status.getUpdatetime().plusMinutes(group_cycle_map.get(status.getGroup_id())*2);
if(now.isAfter(expiredTime)){
status.setState(GnssStatus.STATE_OFFLINE);
if(status.getWarningcode()==null) status.setWarningcode(0);
status.setWarningcode(status.getWarningcode() | WarningCfg.TYPE_DEVICE_OFF_LINE);
status.setWarning(WarningCfg.LEVEL_2);
gnssStatusMapper.setOfflineByDeviceId(status);
//告警消息
WarningMsg warningMsg = new WarningMsg();
warningMsg.setDevicetype(WarningCfg.TYPE_GNSS);
warningMsg.setTenantid(status.getTenantid());
warningMsg.setDeviceid(status.getDeviceid());
warningMsg.setCreatetime(now);
warningMsg.setLevel(WarningCfg.LEVEL_2);
warningMsg.setInfo(WarningCfg.TYPE_NAME_DEVICE_OFF_LINE);
warningMsg.setCode(WarningCfg.TYPE_DEVICE_OFF_LINE);
warningMsgMapper.insert(warningMsg);
}
}
}
}

View File

@ -2,6 +2,7 @@ package com.imdroid.beidou.controller;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.github.yulichang.query.MPJQueryWrapper;
import com.imdroid.beidou.entity.Tenant;
import com.imdroid.beidou.entity.TenantMapper;
import com.imdroid.beidou.service.CommonExcelService;
@ -74,4 +75,23 @@ public class GnssCalcDataController extends BasicController implements CommonExc
public void exportData(HttpSession session, HttpServletRequest request, HttpServletResponse response) throws Exception {
this.export(session, request, response);
}
@Override
public MPJQueryWrapper<GnssCalcData> prepareQueryWrapper() {
return new MPJQueryWrapper<GnssCalcData>()
.selectAll(GnssCalcData.class)
.leftJoin("gnssdevices d on t.deviceid = d.deviceid")
.orderByDesc("t.createtime");
}
/**
* 是否联表查询
*
* @return 是否联表查询
*/
@Override
public boolean isJoinSelect() {
return true;
}
}

View File

@ -95,7 +95,8 @@ public class GnssStatusController extends BasicController implements CommonExcel
return new MPJQueryWrapper<GnssStatus>()
.selectAll(GnssStatus.class)
.select("d.devicetype as devicetype","d.tenantid as tenantid")
.leftJoin("gnssdevices d on t.deviceid = d.deviceid");
.leftJoin("gnssdevices d on t.deviceid = d.deviceid")
.orderByDesc("t.updatetime");
}
/**

View File

@ -27,6 +27,7 @@ public class User {
private String mobile;
private String avatar_url;
private String openid;
private Boolean warning_enabled;
public String getUsername() {
return name;

View File

@ -0,0 +1,42 @@
package com.imdroid.beidou.service;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.imdroid.beidou.entity.User;
import com.imdroid.beidou.entity.UserMapper;
import com.imdroid.secapi.dto.WarningCfg;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutionException;
@Service
public class NotificationService {
@Autowired
UserMapper userMapper;
public void onWarning(String deviceIds, String content, String msgTime, short warningLevel) throws ExecutionException, InterruptedException {
// 严重告警推送短信
if(warningLevel == WarningCfg.LEVEL_2){
List<String> fwdPhoneList = getFwdPhones();
if(fwdPhoneList!=null) SmsService.send(deviceIds, content,
msgTime, fwdPhoneList);
}
}
List<String> getFwdPhones(){
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("warning_enabled",1);
queryWrapper.eq("locked",0);
queryWrapper.isNotNull("mobile");
List<User> userList = userMapper.selectList(queryWrapper);
if(userList.size() == 0) return null;
List<String> phoneList = new ArrayList<>();
for(User user:userList){
phoneList.add(user.getMobile());
}
return phoneList;
}
}

View File

@ -0,0 +1,69 @@
package com.imdroid.beidou.service;
import com.aliyun.auth.credentials.Credential;
import com.aliyun.auth.credentials.provider.StaticCredentialProvider;
import com.aliyun.sdk.service.dysmsapi20170525.AsyncClient;
import com.aliyun.sdk.service.dysmsapi20170525.models.SendSmsRequest;
import com.aliyun.sdk.service.dysmsapi20170525.models.SendSmsResponse;
import com.google.gson.Gson;
import darabonba.core.client.ClientOverrideConfiguration;
import lombok.Data;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
public class SmsService {
static final String signName = "英卓科技";
static final String templateCode = "SMS_465145810";
static final String ACCESS_KEY = "LTAI5tGyoSky5ZG14qYTv2Fv";
static final String ACCESS_KEY_SECRET ="jzfEqr9WV7ltSjO7BXV0WxozyFrvZu";
@Data
static class TemplateData{
String time;
String name;
String content;
}
static public void send(String deviceIds, String content, String msgTime,
List<String> phoneList) throws ExecutionException, InterruptedException {
StaticCredentialProvider provider = StaticCredentialProvider.create(Credential.builder()
.accessKeyId(ACCESS_KEY)
.accessKeySecret(ACCESS_KEY_SECRET)
.build());
// Configure the Client
AsyncClient client = AsyncClient.builder()
.region("cn-beijing") // Region ID
.credentialsProvider(provider)
.overrideConfiguration(
ClientOverrideConfiguration.create()
.setEndpointOverride("dysmsapi.aliyuncs.com")
//.setConnectTimeout(Duration.ofSeconds(30))
)
.build();
// Parameter settings for API request
TemplateData smsData = new TemplateData();
smsData.setTime(msgTime);
smsData.setName(deviceIds);
smsData.setContent(content);
for(String phoneNum : phoneList) {
SendSmsRequest sendSmsRequest = SendSmsRequest.builder()
.phoneNumbers(phoneNum)
.signName(signName)
.templateCode(templateCode)
.templateParam(new Gson().toJson(smsData))
.build();
// Asynchronously get the return value of the API request
CompletableFuture<SendSmsResponse> response = client.sendSms(sendSmsRequest);
// Synchronously get the return value of the API request
SendSmsResponse resp = response.get();
System.out.println(new Gson().toJson(resp));
}
// Finally, close the client
client.close();
}
}

View File

@ -0,0 +1,73 @@
package com.imdroid.beidou.task;
import com.imdroid.secapi.dto.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import java.sql.Timestamp;
/***
* 定时任务
* 1定时清理消息表缺省保留3个月
* 2定时清理原始数据表缺省保留1个月
* 3定时清理操作日志缺省保留1年
* 4定时检查设备是否在线
* 5定时检查FwdRecords(1 year)
*/
@Slf4j
@Configuration
@EnableScheduling
public class DatasetCleaner {
@Autowired
GnssMsgMapper gnssMsgMapper;
@Autowired
GnssStatusMsgMapper statusMsgMapper;
@Autowired
GnssTrxMsgMapper trxMsgMapper;
@Autowired
GnssRawDataMapper rawDataMapper;
//cron表达式格式
//{秒数} {分钟} {小时} {日期} {月份} {星期} {年份(可为空)}
@Scheduled(cron = "0 10 0 * * *") // 每天凌晨执行一次(0:10:0)
//@Scheduled(cron = "0 */2 * * * ?") // 每60分钟执行一次
//@Scheduled(cron = "*/5 * * * * ?") // 每5秒执行一次
public void dayTask() {
checkMsgDataset();
checkRawDataset();
checkFwdDataset();
}
void checkMsgDataset(){
long before = System.currentTimeMillis() -
(long)90 * 24 * 3600 * 1000;
Timestamp t = new Timestamp(before);
int count = gnssMsgMapper.deleteTimeBefore(t);
log.info("clean msg dataset num: "+count);
count = statusMsgMapper.deleteTimeBefore(t);
log.info("clean status msg dataset num: "+count);
count = trxMsgMapper.deleteTimeBefore(t);
log.info("clean trx msg dataset num: "+count);
}
void checkRawDataset(){
long before = System.currentTimeMillis() -
(long)30 * 24 * 3600 * 1000;
Timestamp t = new Timestamp(before);
int count = rawDataMapper.deleteTimeBefore(t);
log.info("clean raw dataset num: "+count);
}
void checkFwdDataset(){
long before = System.currentTimeMillis() -
(long)365 * 24 * 3600 * 1000;
Timestamp t = new Timestamp(before);
int count = rawDataMapper.deleteTimeBefore(t);
log.info("clean fwd dataset num: "+count);
}
}

View File

@ -0,0 +1,177 @@
package com.imdroid.beidou.task;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.yulichang.query.MPJQueryWrapper;
import com.imdroid.beidou.service.NotificationService;
import com.imdroid.secapi.dto.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.ExecutionException;
/***
* 定时任务
* 1定时清理消息表缺省保留3个月
* 2定时清理原始数据表缺省保留1个月
* 3定时清理操作日志缺省保留1年
* 4定时检查设备是否在线
* 5定时检查FwdRecords(1 year)
*/
@Slf4j
@Configuration
@EnableScheduling
public class DeviceStatusChecker {
@Autowired
GnssStatusMapper gnssStatusMapper;
@Autowired
GnssGroupMapper groupMapper;
@Autowired
WarningMsgMapper warningMsgMapper;
@Autowired
WarningCfgMapper warningCfgMapper;
@Autowired
NotificationService notificationService;
@Autowired
GnssCalcDataMapper dataMapper;
@Autowired
GnssDeviceMapper deviceMapper;
static final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
@Scheduled(cron = "0 18,48 * * * ?") // 每半时执行一次
public void checkDeviceState() throws ExecutionException, InterruptedException {
List<GnssGroup> groupCfgs = groupMapper.selectList(null);
HashMap<Integer,Integer> group_cycle_map=new HashMap<>();
for(GnssGroup g:groupCfgs){
group_cycle_map.put(g.getId(), g.getWork_cycle());
}
List<WarningCfg> cfgList = warningCfgMapper.selectList(null);
int noDataCycles = 2;
for(WarningCfg cfg: cfgList){
if(cfg.getType() == WarningCfg.TYPE_DEVICE_OFF_LINE){
noDataCycles = cfg.getValue();
break;
}
}
LocalDateTime now = LocalDateTime.now();
List<GnssStatusJoin> deviceStatuses = gnssStatusMapper.queryOnline();
String deviceIds = null;
for(GnssStatusJoin status : deviceStatuses){
//如果上次上线到现在超过两个周期则认为掉线了
LocalDateTime expiredTime = status.getUpdatetime().plusMinutes(group_cycle_map.get(status.getGroup_id())*noDataCycles);
if(now.isAfter(expiredTime)){
status.setState(GnssStatus.STATE_OFFLINE);
if(status.getWarningcode()==null) status.setWarningcode(0);
status.setWarningcode(status.getWarningcode() | WarningCfg.TYPE_DEVICE_OFF_LINE);
status.setWarning(WarningCfg.LEVEL_2);
gnssStatusMapper.setOfflineByDeviceId(status);
//告警消息
WarningMsg warningMsg = new WarningMsg();
warningMsg.setDevicetype(WarningCfg.TYPE_GNSS);
warningMsg.setTenantid(status.getTenantid());
warningMsg.setDeviceid(status.getDeviceid());
warningMsg.setCreatetime(now);
warningMsg.setLevel(WarningCfg.LEVEL_2);
warningMsg.setInfo(WarningCfg.TYPE_NAME_DEVICE_OFF_LINE);
warningMsg.setCode(WarningCfg.TYPE_DEVICE_OFF_LINE);
warningMsgMapper.insert(warningMsg);
//短信推送
if(deviceIds==null) deviceIds = status.getDeviceid();
else deviceIds = deviceIds+", "+status.getDeviceid();
}
}
if(deviceIds!=null) {
notificationService.onWarning(deviceIds,
WarningCfg.TYPE_NAME_DEVICE_OFF_LINE,
now.format(formatter), WarningCfg.LEVEL_2);
}
}
@Scheduled(cron = "0 28 * * * ?") // 每小时执行一次
void checkRoverStationCalcData() throws ExecutionException, InterruptedException {
//获取所有基站
String deviceIds = null;
QueryWrapper<GnssDevice> deviceQueryWrapper = new QueryWrapper<>();
deviceQueryWrapper.eq("devicetype", GnssDevice.TYPE_REFERENCE_STATION);
deviceQueryWrapper.eq("opmode", GnssDevice.OP_MODE_USE);
List<GnssDevice> bsList = deviceMapper.selectList(deviceQueryWrapper);
for(GnssDevice bs:bsList){
GnssStatus status = gnssStatusMapper.getByDeviceId(bs.getDeviceid());
if(status != null) {
int oldWarningCode = status.getWarningcode() & WarningCfg.TYPE_BS_NO_RESULT;
int newWarningCode = oldWarningCode;
if(!isRoverStationNormal(bs.getDeviceid())){
WarningMsg warningMsg = new WarningMsg();
warningMsg.setDeviceid(bs.getDeviceid());
warningMsg.setTenantid(bs.getTenantid());
warningMsg.setCreatetime(LocalDateTime.now());
warningMsg.setDevicetype(WarningCfg.TYPE_GNSS);
warningMsg.setCode(WarningCfg.TYPE_BS_NO_RESULT);
warningMsg.setLevel(WarningCfg.LEVEL_2);
warningMsg.setInfo(WarningCfg.TYPE_NAME_BS_NO_RESULT);
warningMsgMapper.insert(warningMsg);
newWarningCode = WarningCfg.TYPE_BS_NO_RESULT;
}
else{
newWarningCode = 0;
}
if(oldWarningCode!=newWarningCode){
//清除原来的告警
if(newWarningCode == 0) {
status.setWarningcode(status.getWarningcode() & ~WarningCfg.TYPE_BS_NO_RESULT);
}
else{
status.setWarningcode(status.getWarningcode() | WarningCfg.TYPE_BS_NO_RESULT);
if(deviceIds == null) deviceIds = bs.getDeviceid();
else deviceIds = deviceIds+","+bs.getDeviceid();
}
gnssStatusMapper.updateById(status);
}
}
}
// 发短信通知
if(deviceIds != null){
notificationService.onWarning(deviceIds,
WarningCfg.TYPE_NAME_BS_NO_RESULT,
LocalDateTime.now().format(formatter),
WarningCfg.LEVEL_2);
}
}
/***
* 检查基站下的测站最近一个小时是否全都无固定解
* @param parentId
*/
boolean isRoverStationNormal(String parentId){
//是否有关联测站
QueryWrapper<GnssDevice> deviceQueryWrapper = new QueryWrapper<>();
deviceQueryWrapper.eq("parentid", parentId);
deviceQueryWrapper.eq("opmode",GnssDevice.OP_MODE_USE);
if(deviceMapper.selectCount(deviceQueryWrapper) == 0) return true;
//如果有关联的测站检查解算结果
LocalDateTime endTime = LocalDateTime.now();
LocalDateTime beginTime = endTime.minusHours(1);
MPJQueryWrapper<GnssCalcData> queryWrapper =
new MPJQueryWrapper<GnssCalcData>()
.selectAll(GnssCalcData.class)
.leftJoin("gnssdevices d on t.deviceid = d.deviceid")
.eq("d.parentid",parentId)
.between("t.createtime",beginTime.format(formatter),endTime.format(formatter))
.eq("t.enabled",true);
List<GnssCalcData> dataList = dataMapper.selectList(queryWrapper);
return dataList.size()>0;
}
}

View File

@ -11,6 +11,7 @@ CREATE TABLE IF NOT EXISTS `UserCfg` (
`mobile` varchar(20) DEFAULT NULL,
`avatar_url` varchar(255) DEFAULT NULL,
`openid` varchar(64) DEFAULT NULL,
`warning_enabled` bit(1) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

View File

@ -21,25 +21,31 @@
<div class="layui-inline">
<label class="layui-form-label">设备号</label>
<div class="layui-input-inline">
<input type="text" name="sl_deviceid" id="deviceid" autocomplete="off" class="layui-input">
<input type="text" name="sl_t.deviceid" id="deviceid" autocomplete="off" class="layui-input">
</div>
</div>
<div class="layui-inline" th:if="${tenant_id==0}">
<label class="layui-form-label">所属部门</label>
<div class="layui-input-inline">
<select name="n_tenantid" id="n_tenantid" lay-search="">
<select name="n_t.tenantid" id="tenantid" lay-search="">
<option value="">全部</option>
<option th:each="item : ${tenant_list}" th:text="${item.name}" th:value="${item.id}"></option>
</select>
</div>
</div>
<div class="layui-inline">
<label class="layui-form-label">父设备号</label>
<div class="layui-input-inline">
<input type="text" name="sl_d.parentid" autocomplete="off" class="layui-input">
</div>
</div>
<div class="layui-inline">
<label class="layui-form-label">范围</label>
<div class="layui-input-inline">
<input type="text" name="dgt_createtime" autocomplete="off" id="ID-laydate-start-date" class="layui-input" placeholder="开始日期">
<input type="text" name="dgt_t.createtime" autocomplete="off" id="ID-laydate-start-date" class="layui-input" placeholder="开始日期">
</div>
<div class="layui-input-inline">
<input type="text" name="dlt_createtime" autocomplete="off" id="ID-laydate-end-date" class="layui-input" placeholder="结束日期">
<input type="text" name="dlt_t.createtime" autocomplete="off" id="ID-laydate-end-date" class="layui-input" placeholder="结束日期">
</div>
</div>

View File

@ -33,6 +33,12 @@
</select>
</div>
</div>
<div class="layui-inline">
<label class="layui-form-label">父设备号</label>
<div class="layui-input-inline">
<input type="text" name="sl_d.parentid" autocomplete="off" class="layui-input">
</div>
</div>
<div class="layui-inline">
<label class="layui-form-label">状态</label>
<div class="layui-input-inline">

View File

@ -70,6 +70,17 @@
</div>
</div>
</div>
<div class="layui-form-item">
<div class="layui-input-group">
<label class="layui-form-label">告警通知</label>
<div class="layui-input-inline">
<select name="warning_enabled" id="warning_enabled" lay-filter="warning_enabled">
<option value="0"></option>
<option value="1"></option>
</select>
</div>
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">头像位置</label>
<div class="layui-input-block">
@ -129,6 +140,7 @@
$('#tenantname').val(data.tenantname);
$('#role').val(data.role);
$('#locked').val(data.locked?'1':'0');
$('#warning_enabled').val(data.warning_enabled?'1':'0');
$('#avatar_url').val(data.avatar_url);
$('#openid').val(data.openid);
form.render();

View File

@ -75,6 +75,7 @@
{field: 'role', title: '角色'},
{field: 'tenantname', title: '所属组织'},
{field: 'locked', title: '是否冻结', templet: "<div>{{d.locked==1?'是':'否'}}</div>"},
{field: 'warning_enabled', title: '告警通知', templet: "<div>{{d.warning_enabled==1?'是':'否'}}</div>"},
{title: '操作', toolbar: '#currentTableBar', align: "center", minWidth: 120}
]],
limits: [10, 15, 20, 25, 50, 100],