feat: ASW-46 新增 device 接口

This commit is contained in:
shizhendong
2024-08-27 15:58:41 +08:00
parent 9051cd3fac
commit 16fc3a4bc2
11 changed files with 465 additions and 0 deletions

View File

@@ -0,0 +1,90 @@
package net.geedge.asw.module.device.controller;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.json.JSONObject;
import cn.hutool.log.Log;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import net.geedge.asw.common.util.R;
import net.geedge.asw.common.util.RCode;
import net.geedge.asw.common.util.T;
import net.geedge.asw.module.device.entity.DeviceEntity;
import net.geedge.asw.module.device.service.IDeviceService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.Map;
@RestController
@RequestMapping("/api/v1/device")
public class DeviceController {
private static final Log log = Log.get();
@Autowired
private IDeviceService deviceService;
@GetMapping("/{id}")
public R detail(@PathVariable("id") String id) {
DeviceEntity entity = deviceService.queryInfo(id);
return R.ok().putData("record", entity);
}
@GetMapping
public R list(@RequestParam Map<String, Object> params) {
T.VerifyUtil.is(params).notNull()
.and(T.MapUtil.getStr(params, "workspaceId")).notEmpty(RCode.WORKSPACE_ID_CANNOT_EMPTY);
Page page = deviceService.queryList(params);
return R.ok(page);
}
@PostMapping
public R add(@RequestBody DeviceEntity entity) {
T.VerifyUtil.is(entity).notNull()
.and(entity.getName()).notEmpty(RCode.NAME_CANNOT_EMPTY)
.and(entity.getWorkspaceId()).notEmpty(RCode.WORKSPACE_ID_CANNOT_EMPTY);
DeviceEntity deviceEntity = deviceService.saveDevice(entity);
return R.ok().putData("id", deviceEntity.getId());
}
@DeleteMapping
public R delete(String[] ids) {
T.VerifyUtil.is(ids).notEmpty();
deviceService.removeDevice(T.ListUtil.of(ids));
return R.ok();
}
@PostMapping("/test")
public R testConnect(@RequestBody DeviceEntity entity) {
T.VerifyUtil.is(entity).notNull()
.and(entity.getParam()).notEmpty(RCode.PARAM_CANNOT_EMPTY);
JSONObject jsonObject = entity.getParamJSONObject();
String host = jsonObject.getStr("host");
String port = jsonObject.getStr("port");
String token = jsonObject.getStr("token");
if (T.StrUtil.hasEmpty(host, port, token)) {
return R.error(RCode.PARAM_CANNOT_EMPTY);
}
try {
HttpRequest request = T.HttpUtil.createGet(String.format("http://%s:%s/api/v1/device/status", host, port));
request.header("Authorization", token);
HttpResponse response = request.execute();
log.info("[testConnect] [status: {}]", response.getStatus());
if (response.getStatus() == 401) {
return R.error(401, "Unauthorized");
}
if (response.isOk()) {
return R.ok();
}
} catch (Exception e) {
log.error(e);
return R.error(RCode.ERROR);
}
return R.error(RCode.ERROR);
}
}

View File

@@ -0,0 +1,16 @@
package net.geedge.asw.module.device.dao;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import net.geedge.asw.module.device.entity.DeviceEntity;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
import java.util.Map;
@Mapper
public interface DeviceDao extends BaseMapper<DeviceEntity> {
List<DeviceEntity> queryList(Page page, Map<String, Object> params);
}

View File

@@ -0,0 +1,10 @@
package net.geedge.asw.module.device.dao;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import net.geedge.asw.module.device.entity.DeviceLogEntity;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface DeviceLogDao extends BaseMapper<DeviceLogEntity> {
}

View File

@@ -0,0 +1,53 @@
package net.geedge.asw.module.device.entity;
import cn.hutool.json.JSONObject;
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 com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.Data;
import net.geedge.asw.common.util.T;
import net.geedge.asw.module.sys.entity.SysUserEntity;
@Data
@TableName("device")
public class DeviceEntity {
@TableId(type = IdType.ASSIGN_UUID)
private String id;
private String name;
private String location;
private String platform;
private Object param;
private String description;
private Integer status;
private Long lastHealthCheck;
private Long createTimestamp;
private Long updateTimestamp;
private String createUserId;
private String updateUserId;
private String workspaceId;
@TableField(exist = false)
private SysUserEntity createUser;
@TableField(exist = false)
private SysUserEntity updateUser;
@TableField(exist = false)
private JSONObject useUser;
@JsonIgnore
public String getParamStr() {
return null == this.param ? "{}" : T.JSONUtil.toJsonStr(this.param);
}
@JsonIgnore
public JSONObject getParamJSONObject() {
return null == this.param ? new JSONObject() : T.JSONUtil.parseObj(this.getParamStr());
}
}

View File

@@ -0,0 +1,24 @@
package net.geedge.asw.module.device.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
@Data
@TableName("device_log")
public class DeviceLogEntity {
@TableId(type = IdType.ASSIGN_UUID)
private String id;
private String deviceId;
private String userId;
private Integer status;
private String jobId;
private Long startTimestamp;
private Long endTimestamp;
private String workspaceId;
}

View File

@@ -0,0 +1,8 @@
package net.geedge.asw.module.device.service;
import com.baomidou.mybatisplus.extension.service.IService;
import net.geedge.asw.module.device.entity.DeviceLogEntity;
public interface IDeviceLogService extends IService<DeviceLogEntity>{
}

View File

@@ -0,0 +1,20 @@
package net.geedge.asw.module.device.service;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import net.geedge.asw.module.device.entity.DeviceEntity;
import java.util.List;
import java.util.Map;
public interface IDeviceService extends IService<DeviceEntity>{
DeviceEntity queryInfo(String id);
Page queryList(Map<String, Object> params);
DeviceEntity saveDevice(DeviceEntity entity);
void removeDevice(List<String> ids);
}

View File

@@ -0,0 +1,15 @@
package net.geedge.asw.module.device.service.impl;
import cn.hutool.log.Log;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import net.geedge.asw.module.device.dao.DeviceLogDao;
import net.geedge.asw.module.device.entity.DeviceLogEntity;
import net.geedge.asw.module.device.service.IDeviceLogService;
import org.springframework.stereotype.Service;
@Service
public class DeviceLogServiceImpl extends ServiceImpl<DeviceLogDao, DeviceLogEntity> implements IDeviceLogService {
private static final Log log = Log.get();
}

View File

@@ -0,0 +1,103 @@
package net.geedge.asw.module.device.service.impl;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.log.Log;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import net.geedge.asw.common.util.RCode;
import net.geedge.asw.common.util.T;
import net.geedge.asw.module.device.dao.DeviceDao;
import net.geedge.asw.module.device.entity.DeviceEntity;
import net.geedge.asw.module.device.entity.DeviceLogEntity;
import net.geedge.asw.module.device.service.IDeviceLogService;
import net.geedge.asw.module.device.service.IDeviceService;
import net.geedge.asw.module.sys.entity.SysUserEntity;
import net.geedge.asw.module.sys.service.ISysUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
import java.util.Map;
@Service
public class DeviceServiceImpl extends ServiceImpl<DeviceDao, DeviceEntity> implements IDeviceService {
private static final Log log = Log.get();
@Autowired
private ISysUserService sysUserService;
@Autowired
private IDeviceLogService deviceLogService;
@Override
public DeviceEntity queryInfo(String id) {
DeviceEntity device = this.getById(id);
T.VerifyUtil.is(device).notNull(RCode.SYS_RECORD_NOT_FOUND);
// param
device.setParam(device.getParamJSONObject());
SysUserEntity createUser = sysUserService.getById(device.getCreateUserId());
SysUserEntity updateUser = sysUserService.getById(device.getUpdateUserId());
device.setCreateUser(createUser);
device.setUpdateUser(updateUser);
DeviceLogEntity deviceLog = deviceLogService.getOne(new LambdaQueryWrapper<DeviceLogEntity>().eq(DeviceLogEntity::getDeviceId, device.getId()));
if (null != deviceLog) {
SysUserEntity useUser = sysUserService.getById(deviceLog.getUserId());
JSONObject jsonObject = new JSONObject();
jsonObject.set("id", useUser.getId());
jsonObject.set("name", useUser.getName());
jsonObject.set("startTimestamp", deviceLog.getStartTimestamp());
jsonObject.set("endTimestamp", deviceLog.getEndTimestamp());
device.setUseUser(jsonObject);
}
return device;
}
@Override
public Page queryList(Map<String, Object> params) {
Page page = T.PageUtil.getPage(params);
List<DeviceEntity> packageList = this.getBaseMapper().queryList(page, params);
for (DeviceEntity entity : packageList) {
entity.setParam(entity.getParamJSONObject());
}
page.setRecords(packageList);
return page;
}
@Override
public DeviceEntity saveDevice(DeviceEntity entity) {
// param
entity.setParam(entity.getParamStr());
// default android
entity.setPlatform(T.StrUtil.emptyToDefault(entity.getPlatform(), "android"));
entity.setCreateTimestamp(System.currentTimeMillis());
entity.setUpdateTimestamp(System.currentTimeMillis());
entity.setCreateUserId(StpUtil.getLoginIdAsString());
entity.setUpdateUserId(StpUtil.getLoginIdAsString());
// save
this.save(entity);
return entity;
}
@Override
@Transactional(rollbackFor = Exception.class)
public void removeDevice(List<String> ids) {
// remove
this.removeBatchByIds(ids);
// log
deviceLogService.remove(new LambdaQueryWrapper<DeviceLogEntity>().in(DeviceLogEntity::getDeviceId, ids));
}
}

View File

@@ -0,0 +1,79 @@
<?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="net.geedge.asw.module.device.dao.DeviceDao">
<resultMap id="deviceResult" type="net.geedge.asw.module.device.entity.DeviceEntity">
<result property="id" column="id"/>
<result property="name" column="name"/>
<result property="platform" column="platform"/>
<result property="param" column="param"/>
<result property="description" column="description"/>
<result property="status" column="status"/>
<result property="lastHealthCheck" column="last_health_check"/>
<result property="createTimestamp" column="create_timestamp"/>
<result property="updateTimestamp" column="update_timestamp"/>
<result property="createUserId" column="create_user_id"/>
<result property="updateUserId" column="update_user_id"/>
<result property="workspaceId" column="workspace_id"/>
<association property="createUser" columnPrefix="cu_" javaType="net.geedge.asw.module.sys.entity.SysUserEntity">
<id property="id" column="id"/>
<result property="name" column="name"/>
</association>
<association property="updateUser" columnPrefix="uu_" javaType="net.geedge.asw.module.sys.entity.SysUserEntity">
<id property="id" column="id"/>
<result property="name" column="name"/>
</association>
<association property="useUser" columnPrefix="u_" javaType="cn.hutool.json.JSONObject">
<result property="id" column="id"/>
<result property="name" column="name"/>
<result property="startTimestamp" column="start_timestamp"/>
<result property="endTimestamp" column="end_timestamp"/>
</association>
</resultMap>
<select id="queryList" resultMap="deviceResult">
SELECT
d.*,
cu.id AS cu_id,
cu.name AS cu_name,
uu.id AS uu_id,
uu.name AS uu_name,
log.user_id AS u_id,
u.name AS u_name,
log.start_timestamp AS u_start_timestamp,
log.end_timestamp AS u_end_timestamp
FROM device d
LEFT JOIN sys_user cu ON d.create_user_id = cu.id
LEFT JOIN sys_user uu ON d.update_user_id = uu.id
LEFT JOIN device_log log ON d.id = log.device_id
LEFT JOIN sys_user u ON log.user_id = u.id
<where>
<if test="params.ids != null and params.ids != ''">
d.id in
<foreach item="id" collection="params.ids.split(',')" separator="," open="(" close=")">
#{id}
</foreach>
</if>
<if test="params.q != null and params.q != ''">
AND ( locate(#{params.q}, d.name) OR locate(#{params.q}, d.description) )
</if>
<if test="params.workspaceId != null and params.workspaceId != ''">
AND d.workspace_id = #{params.workspaceId}
</if>
</where>
<if test="params.orderBy == null or params.orderBy == ''">
ORDER BY d.create_timestamp
</if>
</select>
</mapper>

View File

@@ -456,3 +456,50 @@ CREATE TABLE `workspace_member` (
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
INSERT INTO `workspace_member` (`workspace_id`, `user_id`, `role_id`, `create_timestamp`, `create_user_id`) VALUES ('1', 'admin', 'admin', 1724291229000, 'admin');
/**
* 新增 device 表
*/
DROP TABLE IF EXISTS `device`;
CREATE TABLE `device` (
`id` varchar(64) NOT NULL COMMENT '主键',
`name` varchar(256) NOT NULL DEFAULT '' COMMENT '名称',
`location` varchar(256) NOT NULL DEFAULT '' COMMENT '位置',
`platform` varchar(256) NOT NULL DEFAULT 'android' COMMENT '支持的平台可选android',
`param` varchar(1024) NOT NULL DEFAULT '' COMMENT '连接参数',
`description` text NOT NULL DEFAULT '' COMMENT '描述信息',
`status` int(1) NOT NULL DEFAULT 0 COMMENT '状态,0离线1在线',
`last_health_check` bigint(20) NOT NULL DEFAULT -1 COMMENT '最后健康检查时间',
`create_timestamp` bigint(20) NOT NULL COMMENT '创建时间戳',
`update_timestamp` bigint(20) NOT NULL COMMENT '更新时间戳',
`create_user_id` varchar(64) NOT NULL COMMENT '创建人',
`update_user_id` varchar(64) NOT NULL COMMENT '更新人',
`workspace_id` varchar(64) NOT NULL DEFAULT '' COMMENT '工作空间ID',
PRIMARY KEY (`id`) USING BTREE,
KEY `idx_name` (`name`) USING BTREE,
KEY `idx_status` (`status`) USING BTREE,
KEY `idx_workspace_id` (`workspace_id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
/**
* 新增 device_log 表
*/
DROP TABLE IF EXISTS `device_log`;
CREATE TABLE `device_log` (
`id` varchar(64) NOT NULL COMMENT '主键',
`device_id` varchar(64) NOT NULL DEFAULT '' COMMENT '设备id',
`user_id` varchar(64) NOT NULL DEFAULT '' COMMENT '用户id',
`start_timestamp` bigint(20) NOT NULL COMMENT '开始时间',
`end_timestamp` bigint(20) NOT NULL COMMENT '结束时间',
`status` int(1) NOT NULL DEFAULT 1 COMMENT '状态,1使用中;2已结束',
`job_id` varchar(64) NOT NULL DEFAULT '' COMMENT '任务id',
`workspace_id` varchar(64) NOT NULL DEFAULT '' COMMENT '工作空间ID',
PRIMARY KEY (`id`) USING BTREE,
KEY `idx_status` (`status`) USING BTREE,
KEY `idx_device_id` (`device_id`) USING BTREE,
KEY `idx_user_id` (`user_id`) USING BTREE,
KEY `idx_job_id` (`job_id`) USING BTREE,
KEY `idx_workspace_id` (`workspace_id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;