Compare commits

...

2 Commits
master ... dev

18 changed files with 537 additions and 3 deletions

19
pom.xml
View File

@ -25,6 +25,7 @@
<lombok.version>1.18.30</lombok.version>
<hutool.version>5.8.26</hutool.version>
<commons.version>2.11.0</commons.version>
</properties>
<dependencyManagement>
@ -61,11 +62,27 @@
<artifactId>sa-token-spring-boot-starter</artifactId>
<version>${sa-token.version}</version>
</dependency>
<!-- 数据库相关 -->
<dependency>
<groupId>org.xerial</groupId>
<artifactId>sqlite-jdbc</artifactId>
<version>3.45.2.0</version>
</dependency>
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-core</artifactId>
<version>7.15.0</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.3.1</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.11.0</version>
<version>${commons.version}</version>
</dependency>
<!-- HuTool -->

View File

@ -1,14 +1,18 @@
package com.bcrjl.miwifi;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;
/**
* 项目启动类
*
* @author yanqs
*/
@EnableScheduling
@SpringBootApplication
@MapperScan("com.bcrjl.miwifi.mapper")
public class WebApplication {
public static void main(String[] args) {
SpringApplication.run(WebApplication.class, args);

View File

@ -0,0 +1,29 @@
package com.bcrjl.miwifi.common.response;
import com.baomidou.mybatisplus.core.metadata.IPage;
import lombok.Data;
import java.io.Serializable;
import java.util.Collections;
import java.util.List;
/**
* @author yanqs
*/
@Data
public class BasePageList<T> implements Serializable {
private long total;
private long page;
private long pageSize;
private List<T> rows = Collections.emptyList();
public static <T> BasePageList<T> of(IPage<T> page) {
BasePageList<T> bladePage = new BasePageList<>();
bladePage.setRows(page.getRecords());
bladePage.setTotal(page.getTotal());
bladePage.setPageSize(page.getSize());
bladePage.setPage(page.getCurrent());
return bladePage;
}
}

View File

@ -0,0 +1,21 @@
package com.bcrjl.miwifi.common.response;
import lombok.Data;
/**
* 分页参数
*
* @author yanqs
*/
@Data
public class Query {
/**
* 当前页
*/
private long page;
/**
* 每页的数量
*/
private long pageSize;
}

View File

@ -0,0 +1,21 @@
package com.bcrjl.miwifi.common.util;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.bcrjl.miwifi.common.response.Query;
/**
* @author yanqs
*/
public class Condition {
/**
* 转化成mybatis plus中的Page
*
* @param query 查询条件
* @return IPage
*/
public static <T> IPage<T> getPage(Query query) {
Page<T> page = new Page<>(query.getPage(), query.getPageSize());
return page;
}
}

View File

@ -0,0 +1,45 @@
package com.bcrjl.miwifi.config;
import cn.hutool.core.util.StrUtil;
import org.flywaydb.core.Flyway;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import javax.sql.DataSource;
import java.sql.SQLException;
import java.util.Locale;
/**
* 数据库初始化
*
* @author yanqs
*/
@DependsOn("myBatisPlusConfig")
@Configuration
public class FlywayDbInitializer {
@Resource
private DataSource dataSource;
/**
* 启动时根据当前数据库类型执行数据库初始化
*/
@PostConstruct
public void migrateFlyway() {
try {
String databaseProductName = dataSource.getConnection().getMetaData().getDatabaseProductName();
String dbType = databaseProductName.toLowerCase(Locale.ROOT);
// 检查当前数据库类型是否支持
if (!StrUtil.equalsAnyIgnoreCase(dbType, "sqlite")) {
throw new RuntimeException("不支持的数据库类型 [" + dbType + "]");
}
Flyway load = Flyway.configure().dataSource(dataSource).outOfOrder(true).locations("db/migration-sqlite").load();
load.migrate();
} catch (SQLException e) {
e.printStackTrace();
}
}
}

View File

@ -0,0 +1,64 @@
package com.bcrjl.miwifi.config;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import javax.sql.DataSource;
import java.sql.SQLException;
/**
* mybatis-plus 配置类
*
* @author yanqs
*/
@Slf4j
@Configuration
public class MyBatisPlusConfig {
@Resource
private DataSource dataSource;
@Value("${spring.datasource.driver-class-name}")
private String datasourceDriveClassName;
@Value("${spring.datasource.url}")
private String datasourceUrl;
/**
* 如果是 sqlite 数据库自动创建数据库文件所在目录
*/
@PostConstruct
public void init() {
if (StrUtil.equals(datasourceDriveClassName, "org.sqlite.JDBC")) {
String path = datasourceUrl.replace("jdbc:sqlite:", "");
String folderPath = FileUtil.getParent(path, 1);
log.info("SQLite 数据库文件所在目录: [{}]", folderPath);
if (!FileUtil.exist(folderPath)) {
FileUtil.mkdir(folderPath);
log.info("检测到 SQLite 数据库文件所在目录不存在, 已自动创建.");
} else {
log.info("检测到 SQLite 数据库文件所在目录已存在, 无需自动创建.");
}
}
}
/**
* mybatis plus 分页插件配置
*/
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() throws SQLException {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
String databaseProductName = dataSource.getConnection().getMetaData().getDatabaseProductName();
DbType dbType = DbType.getDbType(databaseProductName);
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(dbType));
return interceptor;
}
}

View File

@ -3,7 +3,9 @@ package com.bcrjl.miwifi.controller;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.crypto.SecureUtil;
import com.bcrjl.miwifi.common.response.R;
import com.bcrjl.miwifi.common.util.MiWifiUtil;
import com.bcrjl.miwifi.model.param.LoginParam;
import com.bcrjl.miwifi.service.DeviceDayTrafficService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.PostMapping;
@ -11,6 +13,10 @@ import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.util.Map;
import java.util.Objects;
/**
* 鉴权服务
*
@ -21,6 +27,11 @@ import org.springframework.web.bind.annotation.RestController;
@RequestMapping("/auth")
public class AuthController {
@Resource
private DeviceDayTrafficService deviceDayTrafficService;
@Resource
private MiWifiUtil miWifiUtil;
/**
* 系统密码
*/
@ -36,7 +47,12 @@ public class AuthController {
@PostMapping("/login")
public R login(@RequestBody LoginParam param) {
if (SecureUtil.md5(PASSWORD).equals(param.getPassword())) {
Map<String, Object> loginInfo = miWifiUtil.getLoginInfo();
if (Objects.isNull(loginInfo)) {
return R.fail("无法链接路由器信息");
}
StpUtil.login(10001);
deviceDayTrafficService.initTraffic();
return R.data(StpUtil.getTokenInfo());
} else {
return R.fail("密码错误:");

View File

@ -0,0 +1,43 @@
package com.bcrjl.miwifi.controller;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.bcrjl.miwifi.common.response.BasePageList;
import com.bcrjl.miwifi.common.response.Query;
import com.bcrjl.miwifi.common.response.R;
import com.bcrjl.miwifi.common.util.Condition;
import com.bcrjl.miwifi.model.domain.DeviceDayTraffic;
import com.bcrjl.miwifi.model.param.DeviceDayTrafficParam;
import com.bcrjl.miwifi.service.DeviceDayTrafficService;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
/**
* 设备每日流量统计
*
* @author yanqs
*/
@RestController
@RequestMapping("/api/device/traffic")
public class DeviceDayTrafficController {
@Resource
private DeviceDayTrafficService deviceDayTrafficService;
@PostMapping("/update")
public R updateDeviceDayTraffic(@RequestBody DeviceDayTraffic deviceDayTraffic) {
return R.data("");
}
@GetMapping("/list")
public R list(DeviceDayTrafficParam param, Query query) {
IPage<DeviceDayTraffic> deviceDayTrafficIPage = deviceDayTrafficService.pageList(Condition.getPage(query), param);
return R.data(BasePageList.of(deviceDayTrafficIPage));
}
@GetMapping("test")
public R test(){
deviceDayTrafficService.writeEverydayDeviceTraffic();
return R.success();
}
}

View File

@ -0,0 +1,31 @@
package com.bcrjl.miwifi.job;
import com.bcrjl.miwifi.service.DeviceDayTrafficService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
/**
* 设备任务
*
* @author yanqs
*/
@Slf4j
@Component
public class DeviceJob {
@Resource
private DeviceDayTrafficService deviceDayTrafficService;
@Scheduled(cron = "0 0 0 * * ?")
public void writeEverydayDeviceTraffic() {
log.info("每日凌晨执行写入设备流量开始");
try {
deviceDayTrafficService.writeEverydayDeviceTraffic();
} catch (Exception e) {
log.error("每日写入数据异常", e);
}
log.info("每日凌晨执行写入设备流量结束");
}
}

View File

@ -0,0 +1,18 @@
package com.bcrjl.miwifi.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.bcrjl.miwifi.model.domain.DeviceDayTraffic;
import com.bcrjl.miwifi.model.param.DeviceDayTrafficParam;
import org.apache.ibatis.annotations.Mapper;
/**
* 设备每日统计表 Mapper 接口
*
* @author yanqs
*/
@Mapper
public interface DeviceDayTrafficMapper extends BaseMapper<DeviceDayTraffic> {
IPage<DeviceDayTraffic> pageList(IPage<DeviceDayTraffic> page, DeviceDayTrafficParam param);
}

View File

@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.bcrjl.miwifi.mapper.DeviceDayTrafficMapper">
<resultMap id="BaseResultMap" type="com.bcrjl.miwifi.model.domain.DeviceDayTraffic">
<id column="id" jdbcType="INTEGER" property="id"/>
<result column="date" jdbcType="VARCHAR" property="date"/>
<result column="ip" jdbcType="VARCHAR" property="ip"/>
<result column="mac" jdbcType="VARCHAR" property="mac"/>
<result column="device_name" jdbcType="VARCHAR" property="deviceName"/>
<result column="upload" jdbcType="VARCHAR" property="upload"/>
<result column="download" jdbcType="VARCHAR" property="download"/>
<result column="total" jdbcType="VARCHAR" property="total"/>
</resultMap>
<select id="pageList" resultMap="BaseResultMap">
SELECT * FROM device_day_traffic
<where>
<if test="param2.date == null or param2.date == ''">
and date = DATE('now', '-1 day')
</if>
<if test="param2.date != null and param2.date != ''">
and date = #{param2.date}
</if>
</where>
ORDER BY ID DESC
</select>
</mapper>

View File

@ -0,0 +1,35 @@
package com.bcrjl.miwifi.model.domain;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.io.Serializable;
/**
* 设备每日流量统计表
*
* @author yanqs
*/
@Data
@TableName("device_day_traffic")
public class DeviceDayTraffic implements Serializable {
@TableId(value = "id", type = IdType.AUTO)
private Long id;
@TableField("date")
private String date;
@TableField("ip")
private String ip;
@TableField("mac")
private String mac;
@TableField("device_name")
private String deviceName;
@TableField("upload")
private String upload;
@TableField("download")
private String download;
@TableField("total")
private String total;
}

View File

@ -0,0 +1,11 @@
package com.bcrjl.miwifi.model.param;
import com.bcrjl.miwifi.model.domain.DeviceDayTraffic;
import lombok.Data;
/**
* @author yanqs
*/
@Data
public class DeviceDayTrafficParam extends DeviceDayTraffic {
}

View File

@ -0,0 +1,130 @@
package com.bcrjl.miwifi.service;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bcrjl.miwifi.common.util.MiWifiUtil;
import com.bcrjl.miwifi.mapper.DeviceDayTrafficMapper;
import com.bcrjl.miwifi.model.domain.DeviceDayTraffic;
import com.bcrjl.miwifi.model.param.DeviceDayTrafficParam;
import com.bcrjl.miwifi.model.result.StatusResult;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;
/**
* 设备每日流量 Service
*
* @author yanqs
*/
@Service
@AllArgsConstructor
public class DeviceDayTrafficService extends ServiceImpl<DeviceDayTrafficMapper, DeviceDayTraffic> {
private final MiWifiUtil miWifiUtil;
public IPage<DeviceDayTraffic> pageList(IPage<DeviceDayTraffic> page, DeviceDayTrafficParam param) {
return this.baseMapper.pageList(page, param);
}
/**
* 定时任务写入每日数据
*/
public void writeEverydayDeviceTraffic() {
Date date = DateUtil.date();
Date firstYesterday = DateUtil.offsetDay(date, -2);
Date yesterday = DateUtil.offsetDay(date, -1);
String dateStr = DateUtil.format(firstYesterday, "yyyy-MM-dd");
String yesterdayDateStr = DateUtil.format(yesterday, "yyyy-MM-dd");
List<DeviceDayTraffic> list = this.list(new LambdaQueryWrapper<DeviceDayTraffic>().eq(DeviceDayTraffic::getDate, dateStr));
if (CollUtil.isEmpty(list)) {
dayTraffic();
} else {
StatusResult status = miWifiUtil.getStatus();
List<StatusResult.Dev> devList = status.getDev();
List<DeviceDayTraffic> dbList = new ArrayList<>();
for (DeviceDayTraffic dayTraffic : list) {
StatusResult.Dev device = devList.stream().filter(t -> t.getMac().equals(dayTraffic.getMac())).findFirst().orElse(null);
DeviceDayTraffic deviceDayTraffic = new DeviceDayTraffic();
deviceDayTraffic.setDate(yesterdayDateStr);
if (Objects.isNull(device)) {
deviceDayTraffic.setMac(dayTraffic.getMac());
deviceDayTraffic.setDeviceName(dayTraffic.getDeviceName());
deviceDayTraffic.setUpload("0");
deviceDayTraffic.setDownload("0");
deviceDayTraffic.setTotal("0");
dbList.add(deviceDayTraffic);
} else {
// 如果不是null 则今日流量减去昨日流量 等于今日流量
deviceDayTraffic.setMac(device.getMac());
deviceDayTraffic.setDeviceName(device.getDevName());
long download = Long.parseLong(device.getDownload());
long upload = Long.parseLong(device.getUpload());
long total = download + upload;
long yesterdayTotal = Long.parseLong(dayTraffic.getTotal());
if (total - yesterdayTotal <= 0) {
// 今日流量就是当日流量
upload = Long.parseLong(device.getUpload());
download = Long.parseLong(device.getDownload());
total = download + upload;
deviceDayTraffic.setDownload(device.getDownload());
deviceDayTraffic.setUpload(device.getUpload());
deviceDayTraffic.setTotal(String.valueOf(total));
dbList.add(deviceDayTraffic);
} else {
// 减去的数据就是今日流量
deviceDayTraffic.setTotal(String.valueOf(total - yesterdayTotal));
upload = Long.parseLong(device.getUpload()) - Long.parseLong(dayTraffic.getUpload());
deviceDayTraffic.setUpload(String.valueOf(upload));
download = Long.parseLong(device.getDownload()) - Long.parseLong(dayTraffic.getDownload());
deviceDayTraffic.setDownload(String.valueOf(download));
dbList.add(deviceDayTraffic);
}
}
}
this.saveBatch(dbList);
}
}
/**
* 系统启动初始化数据
*/
public void initTraffic() {
List<DeviceDayTraffic> list = this.list();
if (CollUtil.isEmpty(list)) {
dayTraffic();
}
}
/**
* 每日流量写入
*/
private void dayTraffic() {
StatusResult status = miWifiUtil.getStatus();
if (Objects.nonNull(status) && CollUtil.isNotEmpty(status.getDev())) {
List<DeviceDayTraffic> dbList = new ArrayList<>();
Date date = DateUtil.date();
Date yesterday = DateUtil.offsetDay(date, -1);
String dateStr = DateUtil.format(yesterday, "yyyy-MM-dd");
status.getDev().forEach(dev -> {
DeviceDayTraffic deviceDayTraffic = new DeviceDayTraffic();
deviceDayTraffic.setMac(dev.getMac());
deviceDayTraffic.setDate(dateStr);
deviceDayTraffic.setDeviceName(dev.getDevName());
deviceDayTraffic.setUpload(dev.getUpload());
deviceDayTraffic.setDownload(dev.getDownload());
Long total = Long.parseLong(dev.getUpload()) + Long.valueOf(dev.getDownload());
deviceDayTraffic.setTotal(String.valueOf(total));
dbList.add(deviceDayTraffic);
});
this.saveBatch(dbList);
}
}
}

View File

@ -1,4 +1,11 @@
bmw:
url: 192.168.31.1
password: 123456
web-password: 123456
web-password: 123456
db:
path: ${user.home}/.miwifi-agent/db/agent
spring:
datasource:
url: jdbc:sqlite:${bmw.db.path}.db

View File

@ -32,6 +32,9 @@ spring:
web:
resources:
static-locations: classpath:/static/
datasource:
driver-class-name: org.sqlite.JDBC
############## Sa-Token 配置 (文档: https://sa-token.cc) ##############
sa-token:
@ -52,4 +55,4 @@ sa-token:
log:
path: log/
encoder: UTF-8
encoder: UTF-8

View File

@ -0,0 +1,12 @@
CREATE TABLE "device_day_traffic"
(
"id" integer NOT NULL,
"date" text,
"mac" TEXT,
"device_name" TEXT,
"ip" TEXT,
"upload" TEXT,
"download" TEXT,
"total" TEXT,
PRIMARY KEY ("id")
);