diff --git a/iot-common/iot-common-core/src/main/java/cc/iotkit/common/enums/ErrCode.java b/iot-common/iot-common-core/src/main/java/cc/iotkit/common/enums/ErrCode.java
index b467cce2..930792e4 100644
--- a/iot-common/iot-common-core/src/main/java/cc/iotkit/common/enums/ErrCode.java
+++ b/iot-common/iot-common-core/src/main/java/cc/iotkit/common/enums/ErrCode.java
@@ -19,6 +19,13 @@ public enum ErrCode implements IEnum {
UNSUPPORTED_OPERATION_EXCEPTION(10000009, "方法未实现"),
DATA_NOT_EXIST(10000010, "数据不存在"),
+ /**
+ * openapi通用异常段
+ */
+ IDENTIFIER_ERROR(00000000, "签名验证失败"),
+ API_LOGIN_ERROR(00000000, "登录验证失败"),
+
+
/**
* 组件通用异常段
*/
@@ -70,6 +77,7 @@ public enum ErrCode implements IEnum {
DEVICE_NOT_FOUND(00000000, "设备不存在"),
DEVICE_OFFLINE(00000000, "设备已离线"),
DEVICE_ALREADY(00000000, "设备已存在"),
+ MODEL_DEVICE_ALREADY(00000000, "设备DN已存在"),
DEVICE_HAS_ASSOCIATED(00000000, "设备已关联"),
MODEL_ALREADY(00000000, "型号已存在"),
@@ -99,6 +107,7 @@ public enum ErrCode implements IEnum {
FILE_NAME_IS_NULL(00000000, "文件名为空,获取文件名失败");
+
private int code;
private String message;
diff --git a/iot-common/iot-common-core/src/main/java/cc/iotkit/common/enums/UserType.java b/iot-common/iot-common-core/src/main/java/cc/iotkit/common/enums/UserType.java
index 7eb2fd04..ce4d00e0 100644
--- a/iot-common/iot-common-core/src/main/java/cc/iotkit/common/enums/UserType.java
+++ b/iot-common/iot-common-core/src/main/java/cc/iotkit/common/enums/UserType.java
@@ -20,6 +20,11 @@ public enum UserType {
*/
SYS_USER("sys_user"),
+ /**
+ * 第三方api
+ */
+ API_USER("api_user"),
+
/**
* app端
*/
diff --git a/iot-module/iot-manager/src/main/java/cc/iotkit/manager/service/impl/DeviceServiceImpl.java b/iot-module/iot-manager/src/main/java/cc/iotkit/manager/service/impl/DeviceServiceImpl.java
index 0ec3b110..c88835ec 100644
--- a/iot-module/iot-manager/src/main/java/cc/iotkit/manager/service/impl/DeviceServiceImpl.java
+++ b/iot-module/iot-manager/src/main/java/cc/iotkit/manager/service/impl/DeviceServiceImpl.java
@@ -120,7 +120,11 @@ public class DeviceServiceImpl implements IDeviceService {
if (product == null) {
throw new BizException(ErrCode.PRODUCT_NOT_FOUND);
}
-
+ //同产品不可重复设备名
+ DeviceInfo deviceRepetition = deviceInfoData.findByProductKeyAndDeviceName(productKey, deviceName);
+ if (deviceRepetition != null) {
+ throw new BizException(ErrCode.MODEL_DEVICE_ALREADY);
+ }
//生成设备密钥
String chars = "ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678";
int maxPos = chars.length();
diff --git a/iot-module/iot-openapi/pom.xml b/iot-module/iot-openapi/pom.xml
new file mode 100644
index 00000000..dc1baf17
--- /dev/null
+++ b/iot-module/iot-openapi/pom.xml
@@ -0,0 +1,144 @@
+
+
+
+ iot-module
+ cc.iotkit
+ 0.4.5-SNAPSHOT
+
+ 4.0.0
+
+ iot-openapi
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+ org.bouncycastle
+ bcprov-jdk15on
+
+
+
+ com.aliyun.oss
+ aliyun-sdk-oss
+
+
+
+ joda-time
+ joda-time
+
+
+
+ it.ozimov
+ embedded-redis
+
+
+ slf4j-simple
+ org.slf4j
+
+
+
+
+
+ cc.iotkit
+ iot-common-model
+
+
+
+ cc.iotkit
+ iot-common-core
+
+
+
+ cc.iotkit
+ iot-rule-engine
+
+
+
+ cc.iotkit
+ iot-screen
+
+
+
+ cc.iotkit
+ iot-component-server
+
+
+
+ cc.iotkit
+ iot-component-converter
+
+
+
+ cc.iotkit
+ iot-virtual-device
+
+
+
+ cc.iotkit
+ iot-message-core
+
+
+
+ cc.iotkit
+ iot-common-oss
+
+
+
+ cc.iotkit
+ iot-temporal-service
+
+
+
+ cc.iotkit
+ iot-data-serviceImpl-rdb
+
+
+
+ cc.iotkit
+ iot-data-serviceImpl-cache
+
+
+
+ cc.iotkit
+ iot-common-web
+
+
+
+ cc.iotkit
+ iot-common-doc
+
+
+ cc.iotkit
+ iot-common-satoken
+
+
+
+ cc.iotkit
+ iot-common-excel
+
+
+ cc.iotkit
+ iot-common-log
+
+
+ io.github.linpeilie
+ mapstruct-plus-spring-boot-starter
+
+
+ cc.iotkit
+ iot-system
+
+
+
+
+ 11
+ 11
+
+
+
\ No newline at end of file
diff --git a/iot-module/iot-openapi/src/main/java/cc/iotkit/openapi/controller/OpenBaseController.java b/iot-module/iot-openapi/src/main/java/cc/iotkit/openapi/controller/OpenBaseController.java
new file mode 100644
index 00000000..7da850de
--- /dev/null
+++ b/iot-module/iot-openapi/src/main/java/cc/iotkit/openapi/controller/OpenBaseController.java
@@ -0,0 +1,34 @@
+package cc.iotkit.openapi.controller;
+
+import cc.iotkit.common.api.Request;
+import cc.iotkit.model.InvokeResult;
+import cc.iotkit.openapi.dto.bo.TokenVerifyBo;
+import cc.iotkit.openapi.service.OpenBaseService;
+import cc.iotkit.openapi.service.OpenDeviceService;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+@Api(tags = {"openapi-基础"})
+@Slf4j
+@RestController
+@RequestMapping("/openapi")
+public class OpenBaseController {
+
+ @Autowired
+ private OpenBaseService openBaseService;
+
+ @ApiOperation(value = "token获取", notes = "token获取", httpMethod = "POST")
+ @PostMapping("/v1/getToken")
+ public InvokeResult OpenApiGetToken(@RequestBody @Validated Request request) {
+ return new InvokeResult(openBaseService.getToken(request.getData()));
+ }
+
+
+}
diff --git a/iot-module/iot-openapi/src/main/java/cc/iotkit/openapi/controller/OpenDeviceController.java b/iot-module/iot-openapi/src/main/java/cc/iotkit/openapi/controller/OpenDeviceController.java
new file mode 100644
index 00000000..25b640ae
--- /dev/null
+++ b/iot-module/iot-openapi/src/main/java/cc/iotkit/openapi/controller/OpenDeviceController.java
@@ -0,0 +1,36 @@
+package cc.iotkit.openapi.controller;
+
+import cc.iotkit.common.api.Request;
+import cc.iotkit.model.device.DeviceInfo;
+import cc.iotkit.openapi.dto.bo.device.OpenapiDeviceBo;
+import cc.iotkit.openapi.service.OpenBaseService;
+import cc.iotkit.openapi.service.OpenDeviceService;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+@Api(tags = {"openapi-设备"})
+@Slf4j
+@RestController
+@RequestMapping("/openapi/v1/device")
+public class OpenDeviceController {
+
+ @Autowired
+ private OpenBaseService openBaseService;
+
+ @Autowired
+ private OpenDeviceService openDeviceService;
+
+ @ApiOperation("获取设备详情")
+ @PostMapping("/detail")
+ public DeviceInfo getDetail(@RequestBody @Validated Request request) {
+ return openDeviceService.getDetail(request.getData());
+ }
+
+}
diff --git a/iot-module/iot-openapi/src/main/java/cc/iotkit/openapi/dto/bo/TokenVerifyBo.java b/iot-module/iot-openapi/src/main/java/cc/iotkit/openapi/dto/bo/TokenVerifyBo.java
new file mode 100644
index 00000000..24696550
--- /dev/null
+++ b/iot-module/iot-openapi/src/main/java/cc/iotkit/openapi/dto/bo/TokenVerifyBo.java
@@ -0,0 +1,30 @@
+package cc.iotkit.openapi.dto.bo;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import jakarta.validation.constraints.NotBlank;
+import lombok.Data;
+
+@ApiModel(value = "DeviceConsumerBo")
+@Data
+public class TokenVerifyBo {
+ private static final long serialVersionUID = -1L;
+
+ @NotBlank(message = "appid不能为空")
+ @ApiModelProperty(value = "appid")
+ private String appid;
+
+ @NotBlank(message = "timeStamp不能为空")
+ @ApiModelProperty(value = "时间戳")
+ private String timeStamp;
+
+ @NotBlank(message = "identifier不能为空")
+ @ApiModelProperty(value = "标识符")
+ private String identifier;
+
+ @NotBlank(message = "{tenant.number.not.blank}")
+ @ApiModelProperty(value = "租户ID")
+ private String tenantId;
+
+
+}
diff --git a/iot-module/iot-openapi/src/main/java/cc/iotkit/openapi/dto/bo/device/OpenapiDeviceBo.java b/iot-module/iot-openapi/src/main/java/cc/iotkit/openapi/dto/bo/device/OpenapiDeviceBo.java
new file mode 100644
index 00000000..06a35fa4
--- /dev/null
+++ b/iot-module/iot-openapi/src/main/java/cc/iotkit/openapi/dto/bo/device/OpenapiDeviceBo.java
@@ -0,0 +1,20 @@
+package cc.iotkit.openapi.dto.bo.device;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import jakarta.validation.constraints.NotBlank;
+import lombok.Data;
+
+@ApiModel(value = "OpenapiDeviceBo")
+@Data
+public class OpenapiDeviceBo {
+ private static final long serialVersionUID = -1L;
+
+ @NotBlank(message = "deviceName不能为空")
+ @ApiModelProperty(value = "产品名称")
+ private String deviceName;
+
+ @NotBlank(message = "productKey不能为空")
+ @ApiModelProperty(value = "产品key")
+ private String productKey;
+}
diff --git a/iot-module/iot-openapi/src/main/java/cc/iotkit/openapi/service/OpenBaseService.java b/iot-module/iot-openapi/src/main/java/cc/iotkit/openapi/service/OpenBaseService.java
new file mode 100644
index 00000000..43c952ea
--- /dev/null
+++ b/iot-module/iot-openapi/src/main/java/cc/iotkit/openapi/service/OpenBaseService.java
@@ -0,0 +1,14 @@
+package cc.iotkit.openapi.service;
+
+import cc.iotkit.openapi.dto.bo.TokenVerifyBo;
+
+/**
+ * @Author: dsy
+ * @Date: 2023/7/24 11:30
+ * @Version: V1.0
+ * @Description: openapi基础服务接口
+ */
+public interface OpenBaseService {
+
+ String getToken(TokenVerifyBo bo);
+}
diff --git a/iot-module/iot-openapi/src/main/java/cc/iotkit/openapi/service/OpenDeviceService.java b/iot-module/iot-openapi/src/main/java/cc/iotkit/openapi/service/OpenDeviceService.java
new file mode 100644
index 00000000..a37ab774
--- /dev/null
+++ b/iot-module/iot-openapi/src/main/java/cc/iotkit/openapi/service/OpenDeviceService.java
@@ -0,0 +1,14 @@
+package cc.iotkit.openapi.service;
+
+import cc.iotkit.model.device.DeviceInfo;
+import cc.iotkit.openapi.dto.bo.device.OpenapiDeviceBo;
+
+/**
+ * @Author: dsy
+ * @Date: 2023/7/24 11:05
+ * @Version: V1.0
+ * @Description: openapi设备服务接口
+ */
+public interface OpenDeviceService {
+ DeviceInfo getDetail(OpenapiDeviceBo bo);
+}
diff --git a/iot-module/iot-openapi/src/main/java/cc/iotkit/openapi/service/impl/OpenBaseServiceImpl.java b/iot-module/iot-openapi/src/main/java/cc/iotkit/openapi/service/impl/OpenBaseServiceImpl.java
new file mode 100644
index 00000000..d9dcce6b
--- /dev/null
+++ b/iot-module/iot-openapi/src/main/java/cc/iotkit/openapi/service/impl/OpenBaseServiceImpl.java
@@ -0,0 +1,125 @@
+package cc.iotkit.openapi.service.impl;
+
+import cc.iotkit.common.constant.Constants;
+import cc.iotkit.common.enums.DeviceType;
+import cc.iotkit.common.enums.ErrCode;
+import cc.iotkit.common.enums.LoginType;
+import cc.iotkit.common.exception.BizException;
+import cc.iotkit.common.log.event.LogininforEvent;
+import cc.iotkit.common.satoken.utils.LoginHelper;
+import cc.iotkit.common.undefined.LoginUser;
+import cc.iotkit.common.undefined.RoleDTO;
+import cc.iotkit.common.utils.CodecUtil;
+import cc.iotkit.common.utils.DateUtils;
+import cc.iotkit.common.utils.MessageUtils;
+import cc.iotkit.common.utils.SpringUtils;
+import cc.iotkit.common.web.utils.ServletUtils;
+import cc.iotkit.data.system.ISysUserData;
+import cc.iotkit.model.system.SysUser;
+import cc.iotkit.openapi.dto.bo.TokenVerifyBo;
+import cc.iotkit.openapi.service.OpenBaseService;
+import cc.iotkit.system.service.ISysPermissionService;
+import cn.dev33.satoken.secure.BCrypt;
+import cn.dev33.satoken.stp.StpUtil;
+import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.core.util.ObjectUtil;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+@Service
+public class OpenBaseServiceImpl implements OpenBaseService {
+
+ @Value("${openapi.appid}")
+ private String appid;
+
+ @Value("${openapi.password}")
+ private String password;
+
+ @Autowired
+ private ISysUserData userData;
+
+ @Autowired
+ private ISysPermissionService permissionService;
+
+ @Override
+ public String getToken(TokenVerifyBo bo) {
+ String boAppid = bo.getAppid();
+ String boIdentifier = bo.getIdentifier();
+ String boTimeStamp = bo.getTimeStamp();
+
+ // 校验租户
+ checkTenant(bo.getTenantId());
+
+ if (!CodecUtil.md5Str(boAppid + password + boTimeStamp).equals(boIdentifier)){
+ throw new BizException(ErrCode.IDENTIFIER_ERROR);
+ }
+ if (!boAppid.equals(appid)){
+ throw new BizException(ErrCode.API_LOGIN_ERROR);
+ }
+ SysUser sysUser = userData.selectUserByUserName(appid);
+ if (sysUser == null){
+ //用户不存在是否新建?
+ }
+ LoginUser loginUser = buildLoginUser(sysUser);
+ // 生成token
+ LoginHelper.loginByDevice(loginUser, DeviceType.PC);
+
+ recordLoginInfo(loginUser.getTenantId(), bo.getAppid(), Constants.LOGIN_SUCCESS, MessageUtils.message("openapi.login.success"));
+ recordLoginInfo(sysUser.getId());
+ return StpUtil.getTokenValue();
+ }
+
+ private void checkTenant(String tenantId) {
+
+ }
+ /**
+ * 构建登录用户
+ */
+ private LoginUser buildLoginUser(SysUser user) {
+ LoginUser loginUser = new LoginUser();
+ loginUser.setTenantId(user.getTenantId());
+ loginUser.setUserId(user.getId());
+ loginUser.setDeptId(user.getDeptId());
+ loginUser.setUsername(user.getUserName());
+ loginUser.setUserType(user.getUserType());
+ loginUser.setMenuPermission(permissionService.getMenuPermission(user.getId()));
+ loginUser.setRolePermission(permissionService.getRolePermission(user.getId()));
+ loginUser.setDeptName(ObjectUtil.isNull(user.getDept()) ? "" : user.getDept().getDeptName());
+ List roles = BeanUtil.copyToList(user.getRoles(), RoleDTO.class);
+ loginUser.setRoles(roles);
+ return loginUser;
+ }
+
+ /**
+ * 记录登录信息
+ *
+ * @param tenantId 租户ID
+ * @param username 用户名
+ * @param status 状态
+ * @param message 消息内容
+ */
+ private void recordLoginInfo(String tenantId, String username, String status, String message) {
+ LogininforEvent logininforEvent = new LogininforEvent();
+ logininforEvent.setTenantId(tenantId);
+ logininforEvent.setUsername(username);
+ logininforEvent.setStatus(status);
+ logininforEvent.setMessage(message);
+ logininforEvent.setRequest(ServletUtils.getRequest());
+ SpringUtils.context().publishEvent(logininforEvent);
+ }
+ /**
+ * 记录登录信息
+ *
+ * @param userId 用户ID
+ */
+ public void recordLoginInfo(Long userId) {
+ SysUser sysUser = userData.findById(userId);
+ sysUser.setLoginIp(ServletUtils.getClientIP());
+ sysUser.setLoginDate(DateUtils.getNowDate());
+ sysUser.setUpdateBy(userId);
+ userData.save(sysUser);
+ }
+}
diff --git a/iot-module/iot-openapi/src/main/java/cc/iotkit/openapi/service/impl/OpenDeviceServiceImpl.java b/iot-module/iot-openapi/src/main/java/cc/iotkit/openapi/service/impl/OpenDeviceServiceImpl.java
new file mode 100644
index 00000000..3a9d6703
--- /dev/null
+++ b/iot-module/iot-openapi/src/main/java/cc/iotkit/openapi/service/impl/OpenDeviceServiceImpl.java
@@ -0,0 +1,24 @@
+package cc.iotkit.openapi.service.impl;
+
+import cc.iotkit.data.manager.IDeviceInfoData;
+import cc.iotkit.model.device.DeviceInfo;
+import cc.iotkit.openapi.dto.bo.device.OpenapiDeviceBo;
+import cc.iotkit.openapi.service.OpenDeviceService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.stereotype.Service;
+
+@Service
+public class OpenDeviceServiceImpl implements OpenDeviceService {
+
+ @Autowired
+ @Qualifier("deviceInfoDataCache")
+ private IDeviceInfoData deviceInfoData;
+
+ @Override
+ public DeviceInfo getDetail(OpenapiDeviceBo data) {
+ DeviceInfo deviceInfo = deviceInfoData.findByProductKeyAndDeviceName(data.getProductKey(), data.getDeviceName());
+ deviceInfo.setProperty(deviceInfoData.getProperties(deviceInfo.getDeviceId()));
+ return deviceInfo;
+ }
+}
diff --git a/iot-module/pom.xml b/iot-module/pom.xml
index 144f180b..6d796b8e 100644
--- a/iot-module/pom.xml
+++ b/iot-module/pom.xml
@@ -20,6 +20,7 @@
iot-generator
iot-screen
iot-contribution
+ iot-openapi
diff --git a/iot-starter/src/main/resources/application.yml b/iot-starter/src/main/resources/application.yml
index 6ac99fb9..7a8ea07d 100644
--- a/iot-starter/src/main/resources/application.yml
+++ b/iot-starter/src/main/resources/application.yml
@@ -184,6 +184,12 @@ user:
# 密码锁定时间(默认10分钟)
lockTime: 10
+# openapi配置
+openapi:
+ appid: 123456789
+ password: 123456
+
+
oss:
region: xxxxx
endpoint: xxxxx