refactor 组件接口

V0.5.x
jay 2023-05-30 16:20:38 +08:00
parent 713e6d216a
commit 3e4c2b7b6d
9 changed files with 750 additions and 328 deletions

View File

@ -108,6 +108,11 @@
<artifactId>iot-common-satoken</artifactId>
</dependency>
<dependency>
<groupId>cc.iotkit</groupId>
<artifactId>iot-common-excel</artifactId>
</dependency>
</dependencies>
<build>

View File

@ -10,6 +10,7 @@
package cc.iotkit.manager.controller;
import cc.iotkit.common.api.PageRequest;
import cc.iotkit.common.api.Request;
import cc.iotkit.common.enums.ErrCode;
import cc.iotkit.common.exception.BizException;
import cc.iotkit.common.satoken.utils.AuthUtil;
@ -19,15 +20,24 @@ import cc.iotkit.comps.config.ComponentConfig;
import cc.iotkit.data.manager.IProtocolComponentData;
import cc.iotkit.data.manager.IProtocolConverterData;
import cc.iotkit.data.manager.IUserInfoData;
import cc.iotkit.manager.dto.bo.ChangeStateBo;
import cc.iotkit.manager.dto.bo.protocolcomponent.ProtocolComponentBo;
import cc.iotkit.manager.dto.bo.protocolconverter.ProtocolConverterBo;
import cc.iotkit.manager.dto.vo.protocolcomponent.ProtocolComponentVo;
import cc.iotkit.manager.dto.vo.protocolconverter.ProtocolConverterVo;
import cc.iotkit.manager.service.DataOwnerService;
import cc.iotkit.common.api.Paging;
import cc.iotkit.manager.service.IProtocolService;
import cc.iotkit.model.protocol.ProtocolComponent;
import cc.iotkit.model.protocol.ProtocolConverter;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
@ -38,315 +48,108 @@ import java.util.Objects;
import java.util.UUID;
@Api(tags = {"协议"})
@Slf4j
@RestController
@RequestMapping("/protocol")
public class ProtocolController {
@Autowired
private ComponentConfig componentConfig;
@Autowired
private IProtocolComponentData protocolComponentData;
@Autowired
private IProtocolConverterData protocolConverterData;
@Autowired
private DataOwnerService dataOwnerService;
@Autowired
private IUserInfoData userInfoData;
@Autowired
private ComponentManager componentManager;
private IProtocolService protocolService;
@ApiOperation("上传Jar包")
@PostMapping("/uploadJar")
public String uploadJar(
@RequestParam("file") MultipartFile file,
@RequestParam("id") String id) {
if (file == null) {
throw new BizException(ErrCode.PARAMS_EXCEPTION);
}
log.info("saving upload jar file:{}", file.getName());
String fileName = StringUtils.cleanPath(Objects.requireNonNull(file.getOriginalFilename()));
try {
if (StringUtils.hasLength(id)) {
getAndCheckComponent(id);
} else {
id = UUID.randomUUID().toString();
}
Path jarFilePath = componentConfig.getComponentFilePath(id);
Files.createDirectories(jarFilePath);
Path targetLocation = jarFilePath.resolve(fileName);
Files.copy(file.getInputStream(), targetLocation, StandardCopyOption.REPLACE_EXISTING);
return id;
} catch (IOException ex) {
throw new BizException(ErrCode.UPLOAD_FILE_ERROR, ex);
}
return protocolService.uploadJar(file, id);
}
@ApiOperation("添加组件")
@PostMapping("/addComponent")
public void addComponent(ProtocolComponent component) {
String id = component.getId();
//jar包上传后生成的id
if (!StringUtils.hasLength(id)) {
throw new BizException(ErrCode.COMPONENT_ID_BLANK);
}
Path jarPath = componentConfig.getComponentFilePath(id);
if (!jarPath.resolve(component.getJarFile()).toFile().exists()) {
throw new BizException(ErrCode.COMPONENT_JAR_NOT_FOUND);
}
ProtocolComponent protocolComponent = protocolComponentData.findById(id);
if (protocolComponent != null) {
throw new BizException(ErrCode.COMPONENT_ALREADY);
}
try {
component.setCreateAt(System.currentTimeMillis());
component.setUid(AuthUtil.getUserId());
protocolComponentData.save(component);
} catch (Throwable e) {
throw new BizException(ErrCode.ADD_COMPONENT_ERROR, e);
}
public boolean addComponent(ProtocolComponentBo component) {
return protocolService.addComponent(component);
}
@PostMapping("/saveComponent")
public void saveComponent(ProtocolComponent component) {
String id = component.getId();
if (!StringUtils.hasLength(id)) {
throw new BizException(ErrCode.COMPONENT_ID_BLANK);
}
Path jarPath = componentConfig.getComponentFilePath(id);
if (!jarPath.resolve(component.getJarFile()).toFile().exists()) {
throw new BizException(ErrCode.COMPONENT_JAR_NOT_FOUND);
}
ProtocolComponent oldComponent = getAndCheckComponent(id);
component = ReflectUtil.copyNoNulls(component, oldComponent);
try {
componentManager.deRegister(id);
protocolComponentData.save(component);
} catch (Throwable e) {
throw new BizException(ErrCode.ADD_COMPONENT_ERROR, e);
}
@ApiOperation("修改组件")
@PostMapping("/editComponent")
public String saveComponent(ProtocolComponentBo component) {
return protocolService.saveComponent(component);
}
@GetMapping("/getComponentScript/{id}")
public ProtocolComponent getComponentScript(@PathVariable("id") String id) {
ProtocolComponent component = getAndCheckComponent(id);
String script = component.getScript();
// 如果数据库里不存在,则从文件中读取脚本
if(!StringUtils.hasText(script)){
try {
File file = getComponentScriptFile(id);
script = FileUtils.readFileToString(file, "UTF-8");
} catch (Throwable e) {
log.error("read converter script file error", e);
script = "";
}
component.setScript(script);
}
return component;
@ApiOperation("获取组件详情")
@PostMapping("/getComponentDetail")
public ProtocolComponentVo getComponentScript(@Validated @RequestBody Request<String> req) {
String id = req.getData();
return protocolService.getProtocolComponent(id);
}
@PostMapping("/saveComponentScript/{id}")
public void saveComponentScript(
@PathVariable("id") String id,
@RequestBody ProtocolComponent upReq) {
ProtocolComponent old = getAndCheckComponent(id);
try {
// 保存到文件
File file = getComponentScriptFile(id);
String script = upReq.getScript();
FileUtils.writeStringToFile(file, script, "UTF-8", false);
// 保存到数据库,后续加版本号
old.setScript(upReq.getScript());
old.setScriptTyp(upReq.getScriptTyp());
protocolComponentData.save(old);
componentManager.deRegister(id);
} catch (Throwable e) {
throw new BizException(ErrCode.SAVE_COMPONENT_SCRIPT_ERROR, e);
}
@ApiOperation("保存组件脚本")
@PostMapping("/saveComponentScript")
public boolean saveComponentScript(
@RequestBody ProtocolComponentBo upReq) {
return protocolService.saveComponentScript(upReq);
}
private File getComponentScriptFile(String id) {
Path path = componentConfig.getComponentFilePath(id);
return path.resolve(ProtocolComponent.SCRIPT_FILE_NAME).toFile();
@ApiOperation("删除组件")
@PostMapping("/delete")
public boolean deleteComponent(@Validated @RequestBody Request<String> req) {
return protocolService.deleteComponent(req.getData());
}
private ProtocolComponent getAndCheckComponent(@PathVariable("id") String id) {
ProtocolComponent oldComponent = protocolComponentData.findById(id);
if (oldComponent == null) {
throw new BizException(ErrCode.COMPONENT_NOT_FOUND);
}
dataOwnerService.checkOwner(oldComponent);
return oldComponent;
}
@PostMapping("/deleteComponent/{id}")
public void deleteComponent(@PathVariable("id") String id) {
ProtocolComponent component = getAndCheckComponent(id);
try {
componentManager.deRegister(id);
Path path = Paths.get(String.format("%s/%s", componentConfig.getComponentDir(), id))
.toAbsolutePath().normalize();
File file = path.toFile();
try {
if (file.isDirectory()) {
FileUtils.deleteDirectory(file);
} else {
FileUtils.delete(file);
}
} catch (NoSuchFileException e) {
log.warn("delete component script error", e);
}
protocolComponentData.deleteById(component.getId());
} catch (Throwable e) {
throw new BizException(ErrCode.DELETE_COMPONENT_ERROR, e);
}
}
@PostMapping("/components/{size}/{page}")
public Paging<ProtocolComponent> getComponents(
PageRequest<ProtocolComponent> query ) {
Paging<ProtocolComponent> components = protocolComponentData.findAll(query);
components.getData().forEach(c -> c.setState(
componentManager.isRunning(c.getId()) ?
ProtocolComponent.STATE_RUNNING : ProtocolComponent.STATE_STOPPED
));
return components;
@ApiOperation("获取组件列表")
@PostMapping("/list")
public Paging<ProtocolComponentVo> getComponents(@Validated @RequestBody
PageRequest<ProtocolComponentBo> query) {
return protocolService.selectPageList(query);
}
@ApiOperation("获取转换脚本列表")
@PostMapping("/converters/list")
public Paging<ProtocolConverter> getConverters(PageRequest<ProtocolConverter> query) {
return protocolConverterData.findAll(query);
public Paging<ProtocolConverterVo> getConverters(@Validated @RequestBody PageRequest<ProtocolConverterBo> query) {
return protocolService.selectConvertersPageList(query);
}
@ApiOperation("新增转换脚本")
@PostMapping("/addConverter")
public void addConverter(ProtocolConverter converter) {
try {
converter.setId(null);
converter.setCreateAt(System.currentTimeMillis());
converter.setUid(AuthUtil.getUserId());
protocolConverterData.save(converter);
} catch (Throwable e) {
throw new BizException(ErrCode.ADD_CONVERT_ERROR, e);
}
}
@PostMapping("/saveConverter")
public void saveConverter(ProtocolConverter converter) {
ProtocolConverter oldConverter = getAndCheckConverter(converter.getId());
converter = ReflectUtil.copyNoNulls(converter, oldConverter);
try {
protocolConverterData.save(converter);
} catch (Throwable e) {
throw new BizException(ErrCode.ADD_CONVERT_ERROR, e);
}
}
private ProtocolConverter getAndCheckConverter(String id) {
ProtocolConverter converter = protocolConverterData.findById(id);
if (converter == null) {
throw new BizException(ErrCode.CONVERT_NOT_FOUND);
}
dataOwnerService.checkOwner(converter);
return converter;
}
@GetMapping("/getConverterScript/{id}")
public ProtocolConverter getConverterScript(@PathVariable("id") String id) {
ProtocolConverter converter = getAndCheckConverter(id);
String script = converter.getScript();
// 如果数据库里不存在,则从文件中读取脚本
if(!StringUtils.hasText(script)){
try {
Path path = componentConfig.getConverterFilePath(id);
File file = path.resolve(ProtocolConverter.SCRIPT_FILE_NAME).toFile();
script = FileUtils.readFileToString(file, "UTF-8");
} catch (Throwable e) {
log.error("read converter script file error", e);
script = "";
}
converter.setScript(script);
}
return converter;
public boolean addConverter(@Validated @RequestBody ProtocolConverterBo converter) {
return protocolService.addConverter(converter);
}
@PostMapping("/saveConverterScript/{id}")
public void saveConverterScript(
@PathVariable("id") String id,
@RequestBody ProtocolConverter converter) {
getAndCheckConverter(id);
try {
// 先存文件
Path path = componentConfig.getConverterFilePath(id);
File file = path.resolve(ProtocolConverter.SCRIPT_FILE_NAME).toFile();
String script = converter.getScript();
FileUtils.writeStringToFile(file, script, "UTF-8", false);
// 再存数据库
protocolConverterData.save(converter);
} catch (Throwable e) {
throw new BizException(ErrCode.SAVE_CONVERT_SCRIPT_ERROR, e);
}
@ApiOperation("修改转换脚本")
@PostMapping("/editConverter")
public boolean editConverter(ProtocolConverterBo req) {
return protocolService.editConverter(req);
}
@PostMapping("/deleteConverter/{id}")
public void deleteConverter(@PathVariable("id") String id) {
getAndCheckConverter(id);
try {
Path path = Paths.get(String.format("%s/%s", componentConfig.getConverterDir(), id))
.toAbsolutePath().normalize();
File file = path.toFile();
try {
if (file.isDirectory()) {
FileUtils.deleteDirectory(file);
} else {
FileUtils.delete(file);
}
} catch (NoSuchFileException e) {
log.warn("delete converter script error", e);
}
protocolConverterData.deleteById(id);
} catch (Throwable e) {
throw new BizException(ErrCode.DELETE_CONVERT_ERROR, e);
}
@ApiOperation("获取转换脚本详情")
@PostMapping("/getConverterScript/{id}")
public ProtocolConverterVo getConverter(@RequestBody Request<String> req) {
String id = req.getData();
return protocolService.getConverter(id);
}
@PostMapping("/saveConverterScript")
public boolean saveConverterScript(
@Validated @RequestBody ProtocolConverterBo req) {
return protocolService.saveConverterScript(req);
}
@PostMapping("/deleteConverter")
public boolean deleteConverter(@RequestBody @Validated Request<String> req) {
String id = req.getData();
return protocolService.deleteConverter(id);
}
@PostMapping("/component/{id}/state/{state}")
public void changeComponentState(@PathVariable("id") String id,
@PathVariable("state") String state) {
ProtocolComponent component = getAndCheckComponent(id);
if (ProtocolComponent.TYPE_DEVICE.equals(component.getType())&&ProtocolComponent.CONVER_TYPE_CUSTOM.equals(component.getConverType())) {
String converterId = component.getConverter();
getAndCheckConverter(converterId);
}
if (ProtocolComponent.STATE_RUNNING.equals(state)) {
File scriptFile = getComponentScriptFile(id);
if (!scriptFile.exists()) {
throw new BizException("请先编写组件脚本");
}
componentManager.register(component);
componentManager.start(component.getId());
component.setState(ProtocolComponent.STATE_RUNNING);
} else {
componentManager.deRegister(id);
component.setState(ProtocolComponent.STATE_STOPPED);
}
protocolComponentData.save(component);
public boolean changeComponentState(@RequestBody @Validated ChangeStateBo req) {
return protocolService.changeComponentState(req);
}
}

View File

@ -0,0 +1,33 @@
package cc.iotkit.manager.dto.bo;
import cc.iotkit.common.api.BaseDto;
import cc.iotkit.model.protocol.ProtocolComponent;
import io.github.linpeilie.annotations.AutoMapper;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Size;
@ApiModel(value = "ProtocolComponentBo")
@Data
@EqualsAndHashCode(callSuper = true)
@AutoMapper(target = ProtocolComponent.class, reverseConvertGenerate = false)
public class ChangeStateBo extends BaseDto {
private static final long serialVersionUID = -1L;
@NotBlank(message = "id不能为空")
@ApiModelProperty(value = "")
private String id;
@NotBlank(message = "state不能为空")
@ApiModelProperty(value = "运行状态")
@Size(max = 255, message = "运行状态长度不正确")
private String state;
}

View File

@ -1,22 +1,85 @@
package cc.iotkit.manager.dto.bo.protocolcomponent;
import cc.iotkit.common.api.PageRequest;
import cc.iotkit.model.protocol.ProtocolComponent;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonFormat;
import org.springframework.format.annotation.DateTimeFormat;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import javax.validation.constraints.Size;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.io.Serializable;
import java.util.Date;
import java.math.BigDecimal;
import cc.iotkit.common.api.BaseDto;
import cc.iotkit.common.validate.AddGroup;
import cc.iotkit.common.validate.EditGroup;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* @Author: jay
* @Date: 2023/5/29 10:43
* @Version: V1.0
* @Description:
*/
@ApiModel(value = "ProtocolComponentBo")
@Data
@EqualsAndHashCode(callSuper = true)
@AutoMapper(target = ProtocolComponent.class, reverseConvertGenerate = false)
public class ProtocolComponentBo extends PageRequest {
public class ProtocolComponentBo extends BaseDto {
@ApiModelProperty(value = "")
private String id;
private static final long serialVersionUID = -1L;
@ApiModelProperty(value = "")
@Size(max = 65535, message = "长度不正确")
private String config;
@ApiModelProperty(value = "转换器类型")
@Size(max = 255, message = "转换器类型长度不正确")
private String converType;
@ApiModelProperty(value = "转换脚本")
@Size(max = 255, message = "转换脚本长度不正确")
private String converter;
@ApiModelProperty(value = "创建时间")
private Long createAt;
@ApiModelProperty(value = "jar包")
@Size(max = 255, message = "jar包长度不正确")
private String jarFile;
@ApiModelProperty(value = "组件名称")
@Size(max = 255, message = "组件名称长度不正确")
private String name;
@ApiModelProperty(value = "通讯协议")
@Size(max = 255, message = "通讯协议长度不正确")
private String protocol;
@ApiModelProperty(value = "脚本内容")
@Size(max = 65535, message = "脚本内容长度不正确")
private String script;
@ApiModelProperty(value = "通讯脚本语言类型")
@Size(max = 255, message = "通讯脚本语言类型长度不正确")
private String scriptTyp;
@ApiModelProperty(value = "运行状态")
@Size(max = 255, message = "运行状态长度不正确")
private String state;
@ApiModelProperty(value = "组件类型")
@Size(max = 255, message = "组件类型长度不正确")
private String type;
@ApiModelProperty(value = "所属性用户id")
@Size(max = 255, message = "所属性用户id长度不正确")
private String uid;
}

View File

@ -1,20 +1,61 @@
package cc.iotkit.manager.dto.bo.protocolconverter;
import cc.iotkit.common.api.PageRequest;
import cc.iotkit.model.protocol.ProtocolConverter;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonFormat;
import org.springframework.format.annotation.DateTimeFormat;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import javax.validation.constraints.Size;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.io.Serializable;
import java.util.Date;
import java.math.BigDecimal;
import cc.iotkit.common.api.BaseDto;
import cc.iotkit.common.validate.AddGroup;
import cc.iotkit.common.validate.EditGroup;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* @Author: jay
* @Date: 2023/5/29 10:48
* @Version: V1.0
* @Description:
*/
@ApiModel(value = "ProtocolConverterBo")
@Data
@EqualsAndHashCode(callSuper = true)
@AutoMapper(target = ProtocolConverter.class, reverseConvertGenerate = false)
public class ProtocolConverterBo extends PageRequest {
public class ProtocolConverterBo extends BaseDto {
private static final long serialVersionUID = -1L;
@ApiModelProperty(value = "id")
private String id;
@ApiModelProperty(value = "创建时间")
private Long createAt;
@ApiModelProperty(value = "描述")
@Size(max = 255, message = "描述长度不正确")
private String desc;
@ApiModelProperty(value = "转换器名称")
@Size(max = 255, message = "转换器名称长度不正确")
private String name;
@ApiModelProperty(value = "脚本内容")
@Size(max = 65535, message = "脚本内容长度不正确")
private String script;
@ApiModelProperty(value = "转换脚本类型")
@Size(max = 255, message = "转换脚本类型长度不正确")
private String typ;
@ApiModelProperty(value = "所属性用户id")
@Size(max = 255, message = "所属性用户id长度不正确")
private String uid;
}

View File

@ -1,59 +1,80 @@
package cc.iotkit.manager.dto.vo.protocolcomponent;
import cc.iotkit.model.protocol.ProtocolComponent;
import io.github.linpeilie.annotations.AutoMapper;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.ToString;
import java.util.Date;
import java.io.Serializable;
import java.math.BigDecimal;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import io.github.linpeilie.annotations.AutoMapper;
/**
* @Author: jay
* @Date: 2023/5/29 10:54
* @Version: V1.0
* @Description: Vo
*/
@ApiModel(value = "ProtocolComponentVo")
@Data
@ExcelIgnoreUnannotated
@AutoMapper(target = ProtocolComponent.class)
public class ProtocolComponentVo implements Serializable {
private static final long serialVersionUID = 1L;
public class ProtocolComponentVo implements Serializable {
/**
* id
*/
@ApiModelProperty(value = "用户id")
private String uid;
private static final long serialVersionUID = -1L;
@ApiModelProperty(value = "名称")
private String name;
@ApiModelProperty(value="")
@ExcelProperty(value = "")
private String id;
@ApiModelProperty(value="")
@ExcelProperty(value = "")
private String config;
@ApiModelProperty(value = "协议类型")
@ApiModelProperty(value="转换器类型")
@ExcelProperty(value = "转换器类型")
private String converType;
private String protocol;
@ApiModelProperty(value="转换脚本")
@ExcelProperty(value = "转换脚本")
private String converter;
@ApiModelProperty(value = "jar包")
private String jarFile;
@ApiModelProperty(value="创建时间")
@ExcelProperty(value = "创建时间")
private Long createAt;
@ApiModelProperty(value = "配置")
private String config;
@ApiModelProperty(value="jar包")
@ExcelProperty(value = "jar包")
private String jarFile;
@ApiModelProperty(value = "转换器")
private String converter;
@ApiModelProperty(value="组件名称")
@ExcelProperty(value = "组件名称")
private String name;
@ApiModelProperty(value="通讯协议")
@ExcelProperty(value = "通讯协议")
private String protocol;
@ApiModelProperty(value="脚本内容")
@ExcelProperty(value = "脚本内容")
private String script;
@ApiModelProperty(value="通讯脚本语言类型")
@ExcelProperty(value = "通讯脚本语言类型")
private String scriptTyp;
@ApiModelProperty(value="运行状态")
@ExcelProperty(value = "运行状态")
private String state;
@ApiModelProperty(value="组件类型")
@ExcelProperty(value = "组件类型")
private String type;
@ApiModelProperty(value="所属性用户id")
@ExcelProperty(value = "所属性用户id")
private String uid;
@ApiModelProperty(value = "运行状态")
private String state;
private Long createAt;
@ApiModelProperty(value = "脚本类型")
private String scriptTyp;
@ApiModelProperty(value = "脚本内容")
private String script;
}

View File

@ -0,0 +1,57 @@
package cc.iotkit.manager.dto.vo.protocolconverter;
import cc.iotkit.model.protocol.ProtocolConverter;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.ToString;
import java.util.Date;
import java.io.Serializable;
import java.math.BigDecimal;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import io.github.linpeilie.annotations.AutoMapper;
@ApiModel(value = "ProtocolConverterVo")
@Data
@ExcelIgnoreUnannotated
@AutoMapper(target = ProtocolConverter.class)
public class ProtocolConverterVo implements Serializable {
private static final long serialVersionUID = -1L;
@ApiModelProperty(value = "")
@ExcelProperty(value = "")
private String id;
@ApiModelProperty(value = "创建时间")
@ExcelProperty(value = "创建时间")
private Long createAt;
@ApiModelProperty(value = "描述")
@ExcelProperty(value = "描述")
private String desc;
@ApiModelProperty(value = "转换器名称")
@ExcelProperty(value = "转换器名称")
private String name;
@ApiModelProperty(value = "脚本内容")
@ExcelProperty(value = "脚本内容")
private String script;
@ApiModelProperty(value = "转换脚本类型")
@ExcelProperty(value = "转换脚本类型")
private String typ;
@ApiModelProperty(value = "所属性用户id")
@ExcelProperty(value = "所属性用户id")
private String uid;
}

View File

@ -1,6 +1,15 @@
package cc.iotkit.manager.service;
import cc.iotkit.common.api.PageRequest;
import cc.iotkit.common.api.Paging;
import cc.iotkit.manager.dto.bo.ChangeStateBo;
import cc.iotkit.manager.dto.bo.protocolcomponent.ProtocolComponentBo;
import cc.iotkit.manager.dto.bo.protocolconverter.ProtocolConverterBo;
import cc.iotkit.manager.dto.vo.protocolcomponent.ProtocolComponentVo;
import cc.iotkit.manager.dto.vo.protocolconverter.ProtocolConverterVo;
import cc.iotkit.model.protocol.ProtocolComponent;
import cc.iotkit.model.protocol.ProtocolConverter;
import org.springframework.web.multipart.MultipartFile;
/**
* @Author: jay
@ -11,10 +20,34 @@ import cc.iotkit.model.protocol.ProtocolComponent;
public interface IProtocolService {
// 上传jar包
String uploadJar(String jarFile, String id);
String uploadJar(MultipartFile file, String id);
// 添加组件
boolean addComponent(ProtocolComponent component);
boolean addComponent(ProtocolComponentBo component);
String saveComponent(ProtocolComponentBo component);
ProtocolComponentVo getProtocolComponent(String id);
boolean saveComponentScript(ProtocolComponentBo upReq);
boolean deleteComponent(String data);
Paging<ProtocolComponentVo> selectPageList(PageRequest<ProtocolComponentBo> query);
Paging<ProtocolConverterVo> selectConvertersPageList(PageRequest<ProtocolConverterBo> query);
boolean addConverter(ProtocolConverterBo converter);
boolean editConverter(ProtocolConverterBo req);
ProtocolConverterVo getConverter(String id);
boolean saveConverterScript(ProtocolConverterBo req);
boolean deleteConverter(String id);
boolean changeComponentState(ChangeStateBo req);
}

View File

@ -0,0 +1,366 @@
package cc.iotkit.manager.service.impl;
import cc.iotkit.common.api.PageRequest;
import cc.iotkit.common.api.Paging;
import cc.iotkit.common.enums.ErrCode;
import cc.iotkit.common.exception.BizException;
import cc.iotkit.common.satoken.utils.AuthUtil;
import cc.iotkit.common.utils.MapstructUtils;
import cc.iotkit.common.utils.ReflectUtil;
import cc.iotkit.comps.ComponentManager;
import cc.iotkit.comps.config.ComponentConfig;
import cc.iotkit.data.manager.IProtocolComponentData;
import cc.iotkit.data.manager.IProtocolConverterData;
import cc.iotkit.data.manager.IUserInfoData;
import cc.iotkit.manager.dto.bo.ChangeStateBo;
import cc.iotkit.manager.dto.bo.protocolcomponent.ProtocolComponentBo;
import cc.iotkit.manager.dto.bo.protocolconverter.ProtocolConverterBo;
import cc.iotkit.manager.dto.vo.protocolcomponent.ProtocolComponentVo;
import cc.iotkit.manager.dto.vo.protocolconverter.ProtocolConverterVo;
import cc.iotkit.manager.service.DataOwnerService;
import cc.iotkit.manager.service.IProtocolService;
import cc.iotkit.model.protocol.ProtocolComponent;
import cc.iotkit.model.protocol.ProtocolConverter;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.io.IOException;
import java.nio.file.*;
import java.util.Objects;
import java.util.UUID;
/**
* @Author: jay
* @Date: 2023/5/30 10:48
* @Version: V1.0
* @Description:
*/
@Service
@Slf4j
public class ProtocolServiceImpl implements IProtocolService {
@Autowired
private ComponentConfig componentConfig;
@Autowired
private IProtocolComponentData protocolComponentData;
@Autowired
private IProtocolConverterData protocolConverterData;
@Autowired
private DataOwnerService dataOwnerService;
@Autowired
private IUserInfoData userInfoData;
@Autowired
private ComponentManager componentManager;
@Override
public String uploadJar(MultipartFile file, String id) {
if (file == null) {
throw new BizException(ErrCode.PARAMS_EXCEPTION);
}
log.info("saving upload jar file:{}", file.getName());
String fileName = StringUtils.cleanPath(Objects.requireNonNull(file.getOriginalFilename()));
try {
if (StringUtils.hasLength(id)) {
getAndCheckComponent(id);
} else {
id = UUID.randomUUID().toString();
}
Path jarFilePath = componentConfig.getComponentFilePath(id);
Files.createDirectories(jarFilePath);
Path targetLocation = jarFilePath.resolve(fileName);
Files.copy(file.getInputStream(), targetLocation, StandardCopyOption.REPLACE_EXISTING);
return id;
} catch (IOException ex) {
throw new BizException(ErrCode.UPLOAD_FILE_ERROR, ex);
}
}
@Override
public boolean addComponent(ProtocolComponentBo component) {
String id = component.getId();
//jar包上传后生成的id
if (!StringUtils.hasLength(id)) {
throw new BizException(ErrCode.COMPONENT_ID_BLANK);
}
Path jarPath = componentConfig.getComponentFilePath(id);
if (!jarPath.resolve(component.getJarFile()).toFile().exists()) {
throw new BizException(ErrCode.COMPONENT_JAR_NOT_FOUND);
}
ProtocolComponent protocolComponent = protocolComponentData.findById(id);
if (protocolComponent != null) {
throw new BizException(ErrCode.COMPONENT_ALREADY);
}
try {
component.setCreateAt(System.currentTimeMillis());
component.setUid(AuthUtil.getUserId());
protocolComponentData.save(component.to(ProtocolComponent.class));
} catch (Throwable e) {
throw new BizException(ErrCode.ADD_COMPONENT_ERROR, e);
}
return true;
}
@Override
public String saveComponent(ProtocolComponentBo req) {
ProtocolComponent component = req.to(ProtocolComponent.class);
String id = component.getId();
if (!StringUtils.hasLength(id)) {
throw new BizException(ErrCode.COMPONENT_ID_BLANK);
}
Path jarPath = componentConfig.getComponentFilePath(id);
if (!jarPath.resolve(component.getJarFile()).toFile().exists()) {
throw new BizException(ErrCode.COMPONENT_JAR_NOT_FOUND);
}
ProtocolComponent oldComponent = getAndCheckComponent(id);
component = ReflectUtil.copyNoNulls(component, oldComponent);
try {
componentManager.deRegister(id);
protocolComponentData.save(component);
return component.getId();
} catch (Throwable e) {
throw new BizException(ErrCode.ADD_COMPONENT_ERROR, e);
}
}
@Override
public ProtocolComponentVo getProtocolComponent(String id) {
ProtocolComponent component = getAndCheckComponent(id);
String script = component.getScript();
// 如果数据库里不存在,则从文件中读取脚本
if (!StringUtils.hasText(script)) {
try {
File file = getComponentScriptFile(id);
script = FileUtils.readFileToString(file, "UTF-8");
} catch (Throwable e) {
log.error("read converter script file error", e);
script = "";
}
component.setScript(script);
}
return MapstructUtils.convert(component, ProtocolComponentVo.class);
}
@Override
public boolean saveComponentScript(ProtocolComponentBo upReq) {
String id = upReq.getId();
ProtocolComponent old = getAndCheckComponent(id);
try {
// 保存到文件
File file = getComponentScriptFile(id);
String script = upReq.getScript();
FileUtils.writeStringToFile(file, script, "UTF-8", false);
// 保存到数据库,后续加版本号
old.setScript(upReq.getScript());
old.setScriptTyp(upReq.getScriptTyp());
protocolComponentData.save(old);
componentManager.deRegister(id);
} catch (Throwable e) {
throw new BizException(ErrCode.SAVE_COMPONENT_SCRIPT_ERROR, e);
}
return true;
}
@Override
public boolean deleteComponent(String id) {
ProtocolComponent component = getAndCheckComponent(id);
try {
componentManager.deRegister(id);
Path path = Paths.get(String.format("%s/%s", componentConfig.getComponentDir(), id))
.toAbsolutePath().normalize();
File file = path.toFile();
try {
if (file.isDirectory()) {
FileUtils.deleteDirectory(file);
} else {
FileUtils.delete(file);
}
} catch (NoSuchFileException e) {
log.warn("delete component script error", e);
}
protocolComponentData.deleteById(component.getId());
} catch (Throwable e) {
throw new BizException(ErrCode.DELETE_COMPONENT_ERROR, e);
}
return true;
}
@Override
public Paging<ProtocolComponentVo> selectPageList(PageRequest<ProtocolComponentBo> query) {
Paging<ProtocolComponentVo> components = protocolComponentData.findAll(query.to(ProtocolComponent.class)).to(ProtocolComponentVo.class);
components.getData().forEach(c -> c.setState(
componentManager.isRunning(c.getId()) ?
ProtocolComponent.STATE_RUNNING : ProtocolComponent.STATE_STOPPED
));
return components;
}
@Override
public Paging<ProtocolConverterVo> selectConvertersPageList(PageRequest<ProtocolConverterBo> query) {
return protocolConverterData.findAll(query.to(ProtocolConverter.class)).to(ProtocolConverterVo.class);
}
@Override
public boolean addConverter(ProtocolConverterBo req) {
try {
ProtocolConverter converter = req.to(ProtocolConverter.class);
converter.setId(null);
converter.setCreateAt(System.currentTimeMillis());
converter.setUid(AuthUtil.getUserId());
protocolConverterData.save(converter);
} catch (Throwable e) {
throw new BizException(ErrCode.ADD_CONVERT_ERROR, e);
}
return false;
}
@Override
public boolean editConverter(ProtocolConverterBo req) {
ProtocolConverter converter = req.to(ProtocolConverter.class);
ProtocolConverter oldConverter = getAndCheckConverter(converter.getId());
converter = ReflectUtil.copyNoNulls(converter, oldConverter);
try {
protocolConverterData.save(converter);
} catch (Throwable e) {
throw new BizException(ErrCode.ADD_CONVERT_ERROR, e);
}
return true;
}
@Override
public ProtocolConverterVo getConverter(String id) {
ProtocolConverter converter = getAndCheckConverter(id);
String script = converter.getScript();
// 如果数据库里不存在,则从文件中读取脚本
if (!StringUtils.hasText(script)) {
try {
Path path = componentConfig.getConverterFilePath(id);
File file = path.resolve(ProtocolConverter.SCRIPT_FILE_NAME).toFile();
script = FileUtils.readFileToString(file, "UTF-8");
} catch (Throwable e) {
log.error("read converter script file error", e);
script = "";
}
converter.setScript(script);
}
return MapstructUtils.convert(converter, ProtocolConverterVo.class);
}
@Override
public boolean saveConverterScript(ProtocolConverterBo req) {
ProtocolConverter converter = req.to(ProtocolConverter.class);
String id = req.getId();
getAndCheckConverter(id);
try {
// 先存文件
Path path = componentConfig.getConverterFilePath(id);
File file = path.resolve(ProtocolConverter.SCRIPT_FILE_NAME).toFile();
String script = converter.getScript();
FileUtils.writeStringToFile(file, script, "UTF-8", false);
// 再存数据库
protocolConverterData.save(converter);
} catch (Throwable e) {
throw new BizException(ErrCode.SAVE_CONVERT_SCRIPT_ERROR, e);
}
return true;
}
@Override
public boolean deleteConverter(String id) {
getAndCheckConverter(id);
try {
Path path = Paths.get(String.format("%s/%s", componentConfig.getConverterDir(), id))
.toAbsolutePath().normalize();
File file = path.toFile();
try {
if (file.isDirectory()) {
FileUtils.deleteDirectory(file);
} else {
FileUtils.delete(file);
}
} catch (NoSuchFileException e) {
log.warn("delete converter script error", e);
}
protocolConverterData.deleteById(id);
} catch (Throwable e) {
throw new BizException(ErrCode.DELETE_CONVERT_ERROR, e);
}
return true;
}
@Override
public boolean changeComponentState(ChangeStateBo req) {
String id = req.getId();
String state = req.getState();
ProtocolComponent component = getAndCheckComponent(id);
if (ProtocolComponent.TYPE_DEVICE.equals(component.getType()) && ProtocolComponent.CONVER_TYPE_CUSTOM.equals(component.getConverType())) {
String converterId = component.getConverter();
getAndCheckConverter(converterId);
}
if (ProtocolComponent.STATE_RUNNING.equals(state)) {
File scriptFile = getComponentScriptFile(id);
if (!scriptFile.exists()) {
throw new BizException("请先编写组件脚本");
}
componentManager.register(component);
componentManager.start(component.getId());
component.setState(ProtocolComponent.STATE_RUNNING);
} else {
componentManager.deRegister(id);
component.setState(ProtocolComponent.STATE_STOPPED);
}
protocolComponentData.save(component);
return true;
}
/******************************/
private File getComponentScriptFile(String id) {
Path path = componentConfig.getComponentFilePath(id);
return path.resolve(ProtocolComponent.SCRIPT_FILE_NAME).toFile();
}
private ProtocolComponent getAndCheckComponent(@PathVariable("id") String id) {
ProtocolComponent oldComponent = protocolComponentData.findById(id);
if (oldComponent == null) {
throw new BizException(ErrCode.COMPONENT_NOT_FOUND);
}
dataOwnerService.checkOwner(oldComponent);
return oldComponent;
}
private ProtocolConverter getAndCheckConverter(String id) {
ProtocolConverter converter = protocolConverterData.findById(id);
if (converter == null) {
throw new BizException(ErrCode.CONVERT_NOT_FOUND);
}
dataOwnerService.checkOwner(converter);
return converter;
}
}