瀏覽代碼

第三方接入接口完善

xiwa 3 年之前
父節點
當前提交
52daf45a69

+ 66 - 11
common/src/main/java/cc/iotkit/common/Constants.java

@@ -1,5 +1,7 @@
 package cc.iotkit.common;
 
+import lombok.Data;
+
 public interface Constants {
 
     String PRODUCT_SECRET = "xdkKUymrEGSCYWswqCvSPyRSFvH5j7CU";
@@ -54,11 +56,6 @@ public interface Constants {
      */
     String PWD_SYSTEM_USER = "s123456";
 
-    /**
-     * 设备原始上报消息的topic
-     */
-    String DEVICE_RAW_MESSAGE_TOPIC = "device_raw";
-
     /**
      * 设备物模型消息的topic
      */
@@ -69,33 +66,91 @@ public interface Constants {
      */
     String HTTP_CONSUMER_DEVICE_INFO_TOPIC = "device_info:";
 
-    interface API {
+    /**
+     * 三方平台类型
+     */
+    enum ThirdPlatform {
+        dueros("小度"),
+        aligenie("天猫精灵"),
+        miiot("小爱");
+
+        public String desc;
+
+        ThirdPlatform(String desc) {
+            this.desc = desc;
+        }
+
+    }
+
+    interface API_DEVICE {
 
         /**
          * 设备-基路径
          */
-        String DEVICE_BASE = "/device";
+        String BASE = "/device";
 
         /**
          * 设备-设备列表
          */
-        String DEVICE_LIST = "/list/{size}/{page}";
+        String LIST = "/list/{size}/{page}";
 
         /**
          * 设备-设备详情
          */
-        String DEVICE_DETAIL = "/{deviceId}/detail";
+        String DETAIL = "/{deviceId}/detail";
 
         /**
          * 设备-属性设置
          */
-        String DEVICE_SET_PROPERTIES = "/{deviceId}/service/property/set";
+        String SET_PROPERTIES = "/{deviceId}/service/property/set";
 
         /**
          * 设备-服务调用
          */
-        String DEVICE_INVOKE_SERVICE = "/{deviceId}/service/{service}/invoke";
+        String INVOKE_SERVICE = "/{deviceId}/service/{service}/invoke";
 
     }
 
+    interface API_SPACE {
+
+        /**
+         * 空间-基路径
+         */
+        String BASE = "/space";
+
+        /**
+         * 最近使用设备列表
+         */
+        String RECENT_DEVICES = "/myRecentDevices";
+
+        /**
+         * 我的空间设备列表
+         */
+        String SPACE_DEVICES = "/myDevices/{spaceId}";
+
+        /**
+         * 查找设备
+         */
+        String FIND_DEVICE = "/findDevice";
+
+        /**
+         * 空间添加设备
+         */
+        String ADD_DEVICE = "/addDevice";
+
+        /**
+         * 空间删除设备
+         */
+        String REMOVE_DEVICE = "/removeDevice";
+
+        /**
+         * 空间修改设备
+         */
+        String SAVE_DEVICE = "/saveDevice";
+
+        /**
+         * 获取空间设备信息
+         */
+        String GET_DEVICE = "/device/{deviceId}";
+    }
 }

+ 2 - 0
dao/src/main/java/cc/iotkit/dao/SpaceDeviceRepository.java

@@ -11,6 +11,8 @@ public interface SpaceDeviceRepository extends MongoRepository<SpaceDevice, Stri
 
     List<SpaceDevice> findByUidOrderByUseAtDesc(String uid);
 
+    List<SpaceDevice> findByUidOrderByAddAtDesc(String uid);
+
     List<SpaceDevice> findByUidAndSpaceIdOrderByAddAtDesc(String uid, String spaceId);
 
     SpaceDevice findByDeviceId(String deviceId);

+ 4 - 2
dao/src/main/java/cc/iotkit/dao/UserAccountRepository.java → dao/src/main/java/cc/iotkit/dao/ThirdUserSessionRepository.java

@@ -1,9 +1,11 @@
 package cc.iotkit.dao;
 
-import cc.iotkit.model.UserAccount;
+import cc.iotkit.model.ThirdUserSession;
 import org.springframework.data.mongodb.repository.MongoRepository;
 import org.springframework.stereotype.Repository;
 
 @Repository
-public interface UserAccountRepository extends MongoRepository<UserAccount, String> {
+public interface ThirdUserSessionRepository extends MongoRepository<ThirdUserSession, String> {
+
+
 }

+ 3 - 3
manager/src/main/java/cc/iotkit/manager/controller/DeviceController.java

@@ -59,7 +59,7 @@ public class DeviceController {
     @Autowired
     DeferredDataConsumer deferredDataConsumer;
 
-    @PostMapping(Constants.API.DEVICE_INVOKE_SERVICE)
+    @PostMapping(Constants.API_DEVICE.INVOKE_SERVICE)
     public InvokeResult invokeService(@PathVariable("deviceId") String deviceId,
                                       @PathVariable("service") String service,
                                       @RequestBody Map<String, Object> args) {
@@ -69,7 +69,7 @@ public class DeviceController {
         return new InvokeResult(deviceService.invokeService(deviceId, service, args));
     }
 
-    @PostMapping(Constants.API.DEVICE_SET_PROPERTIES)
+    @PostMapping(Constants.API_DEVICE.SET_PROPERTIES)
     public InvokeResult setProperty(@PathVariable("deviceId") String deviceId,
                                     @RequestBody Map<String, Object> args) {
         return new InvokeResult(deviceService.setProperty(deviceId, args));
@@ -136,7 +136,7 @@ public class DeviceController {
                                 .build())));
     }
 
-    @GetMapping(Constants.API.DEVICE_DETAIL)
+    @GetMapping(Constants.API_DEVICE.DETAIL)
     public DeviceInfo getDetail(@PathVariable("deviceId") String deviceId) {
         return dataOwnerService.checkOwner(deviceRepository.findById(deviceId).orElse(new DeviceInfo()));
     }

+ 49 - 13
manager/src/main/java/cc/iotkit/manager/controller/SpaceDeviceController.java

@@ -1,11 +1,13 @@
 package cc.iotkit.manager.controller;
 
+import cc.iotkit.common.Constants;
 import cc.iotkit.common.exception.BizException;
 import cc.iotkit.dao.*;
 import cc.iotkit.manager.model.vo.FindDeviceVo;
 import cc.iotkit.manager.model.vo.SpaceDeviceVo;
 import cc.iotkit.manager.service.DataOwnerService;
 import cc.iotkit.manager.utils.AuthUtil;
+import cc.iotkit.model.UserInfo;
 import cc.iotkit.model.device.DeviceInfo;
 import cc.iotkit.model.product.Category;
 import cc.iotkit.model.product.Product;
@@ -14,10 +16,12 @@ import cc.iotkit.model.space.SpaceDevice;
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.data.domain.Example;
+import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.web.bind.annotation.*;
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Map;
 import java.util.Optional;
 import java.util.stream.Collectors;
 
@@ -42,11 +46,13 @@ public class SpaceDeviceController {
     private SpaceRepository spaceRepository;
     @Autowired
     private DataOwnerService dataOwnerService;
+    @Autowired
+    private UserInfoRepository userInfoRepository;
 
     /**
      * 我最近使用的设备列表
      */
-    @GetMapping("/myRecentDevices")
+    @GetMapping(Constants.API_SPACE.RECENT_DEVICES)
     public List<SpaceDeviceVo> getMyRecentDevices() {
         List<SpaceDevice> spaceDevices = spaceDeviceRepository.findByUidOrderByUseAtDesc(AuthUtil.getUserId());
         return spaceDevices.stream().map((this::parseSpaceDevice)).collect(Collectors.toList());
@@ -57,14 +63,21 @@ public class SpaceDeviceController {
      *
      * @param spaceId 空间id
      */
-    @GetMapping("/myDevices/{spaceId}")
+    @GetMapping(Constants.API_SPACE.SPACE_DEVICES)
     public List<SpaceDeviceVo> getMyDevices(@PathVariable("spaceId") String spaceId) {
-        List<SpaceDevice> spaceDevices = spaceDeviceRepository.
-                findByUidAndSpaceIdOrderByAddAtDesc(AuthUtil.getUserId(), spaceId);
+        String uid = AuthUtil.getUserId();
+        List<SpaceDevice> spaceDevices;
+        if ("all".equals(spaceId)) {
+            //全部设备
+            spaceDevices = spaceDeviceRepository.findByUidOrderByUseAtDesc(uid);
+        } else {
+            //按空间获取
+            spaceDevices = spaceDeviceRepository.
+                    findByUidAndSpaceIdOrderByAddAtDesc(uid, spaceId);
+        }
         return spaceDevices.stream().map((this::parseSpaceDevice)).collect(Collectors.toList());
     }
 
-
     private SpaceDeviceVo parseSpaceDevice(SpaceDevice sd) {
         DeviceInfo device = deviceRepository.findByDeviceId(sd.getDeviceId());
         Space space = spaceCache.getSpace(sd.getSpaceId());
@@ -90,13 +103,14 @@ public class SpaceDeviceController {
                 .build();
     }
 
+    @PreAuthorize("hasRole('iot_system_user')")
     @GetMapping("/{userId}/devices")
     public List<SpaceDeviceVo> getDevices(@PathVariable("userId") String userId) {
         List<SpaceDevice> spaceDevices = spaceDeviceRepository.findAll(Example.of(SpaceDevice.builder().uid(userId).build()));
         return spaceDevices.stream().map((this::parseSpaceDevice)).collect(Collectors.toList());
     }
 
-    @GetMapping("/findDevice")
+    @GetMapping(Constants.API_SPACE.FIND_DEVICE)
     List<FindDeviceVo> findDevice(String mac) {
         if (StringUtils.isBlank(mac)) {
             throw new BizException("mac is blank");
@@ -143,7 +157,7 @@ public class SpaceDeviceController {
         return findDeviceVo;
     }
 
-    @PostMapping("/addDevice")
+    @PostMapping(Constants.API_SPACE.ADD_DEVICE)
     public void addDevice(SpaceDevice device) {
         String deviceId = device.getDeviceId();
         DeviceInfo deviceInfo = deviceRepository.findByDeviceId(deviceId);
@@ -182,13 +196,26 @@ public class SpaceDeviceController {
         }
 
         String uid = AuthUtil.getUserId();
+        Optional<UserInfo> optUser = userInfoRepository.findById(uid);
+        if (!optUser.isPresent()) {
+            throw new BizException("user does not exist");
+        }
         if (!subUid.contains(uid)) {
             subUid.add(uid);
         }
+
+        //更新设备标签
+        List<String> platforms = optUser.get().getUsePlatforms();
+        Map<String, DeviceInfo.Tag> tags = deviceInfo.getTag();
+        for (String platform : platforms) {
+            Constants.ThirdPlatform thirdPlatform = Constants.ThirdPlatform.valueOf(platform);
+            tags.put(platform, new DeviceInfo.Tag(platform, thirdPlatform.desc, "是"));
+        }
+
         deviceRepository.save(deviceInfo);
     }
 
-    @DeleteMapping("/removeDevice")
+    @DeleteMapping(Constants.API_SPACE.REMOVE_DEVICE)
     public void removeDevice(String deviceId) {
         String uid = AuthUtil.getUserId();
         SpaceDevice spaceDevice = spaceDeviceRepository.findByDeviceIdAndUid(deviceId, uid);
@@ -199,14 +226,23 @@ public class SpaceDeviceController {
 
         spaceDeviceRepository.deleteById(spaceDevice.getId());
         DeviceInfo deviceInfo = deviceRepository.findByDeviceId(deviceId);
+        Optional<UserInfo> optUser = userInfoRepository.findById(uid);
+        if (!optUser.isPresent()) {
+            throw new BizException("user does not exist");
+        }
+
+        List<String> platforms = optUser.get().getUsePlatforms();
         List<String> subUid = deviceInfo.getSubUid();
-        if (subUid != null) {
-            subUid.remove(uid);
-            deviceRepository.save(deviceInfo);
+        subUid.remove(uid);
+        //删除设备标签
+        for (String platform : platforms) {
+            deviceInfo.getTag().remove(platform);
         }
+
+        deviceRepository.save(deviceInfo);
     }
 
-    @PostMapping("/saveDevice")
+    @PostMapping(Constants.API_SPACE.SAVE_DEVICE)
     public void saveDevice(SpaceDevice spaceDevice) {
         dataOwnerService.checkOwner(spaceDevice);
         Optional<SpaceDevice> optData = spaceDeviceRepository.findById(spaceDevice.getId());
@@ -219,7 +255,7 @@ public class SpaceDeviceController {
         spaceDeviceRepository.save(oldData);
     }
 
-    @GetMapping("/device/{deviceId}")
+    @GetMapping(Constants.API_SPACE.GET_DEVICE)
     public SpaceDeviceVo getSpaceDevice(@PathVariable("deviceId") String deviceId) {
         String uid = AuthUtil.getUserId();
         SpaceDevice spaceDevice = spaceDeviceRepository.findByDeviceIdAndUid(deviceId, uid);

+ 0 - 30
manager/src/main/java/cc/iotkit/manager/controller/SystemController.java

@@ -1,30 +0,0 @@
-package cc.iotkit.manager.controller;
-
-import cc.iotkit.common.Constants;
-import cc.iotkit.common.utils.CodecUtil;
-import cc.iotkit.dao.UserAccountRepository;
-import cc.iotkit.model.UserAccount;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.RestController;
-
-@RestController
-public class SystemController {
-
-    @Autowired
-    private UserAccountRepository userAccountRepository;
-
-    @PostMapping("/user/login")
-    public String login(String uid, String pwd) throws Exception {
-        UserAccount account = userAccountRepository.findById(uid).orElse(new UserAccount());
-        String encodePwd = CodecUtil.aesEncrypt(uid + pwd, Constants.ACCOUNT_SECRET);
-        if (encodePwd.equals(account.getPwd())) {
-            return CodecUtil.aesEncrypt(System.currentTimeMillis() + "_" + uid, Constants.ACCOUNT_SECRET);
-        }
-        throw new RuntimeException("用户名或密码错误");
-    }
-
-    public static void main(String[] args) throws Exception {
-        System.out.println(CodecUtil.aesEncrypt("aaa123", Constants.ACCOUNT_SECRET));
-    }
-}

+ 106 - 0
manager/src/main/java/cc/iotkit/manager/controller/ThirdAuthController.java

@@ -0,0 +1,106 @@
+package cc.iotkit.manager.controller;
+
+import cc.iotkit.common.utils.JsonUtil;
+import cc.iotkit.dao.ThirdUserSessionRepository;
+import cc.iotkit.model.ThirdUserSession;
+import lombok.Data;
+import lombok.extern.slf4j.Slf4j;
+import okhttp3.*;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.net.URLEncoder;
+import java.util.Base64;
+import java.util.Enumeration;
+
+/**
+ * 第三方接入认证
+ */
+@Slf4j
+@RestController
+@RequestMapping("/auth")
+public class ThirdAuthController {
+
+    private final OkHttpClient client = new OkHttpClient().newBuilder().build();
+
+    @Autowired
+    private ThirdUserSessionRepository thirdUserSessionRepository;
+
+    @PostMapping("/token/{type}")
+    public void getToken(
+            @PathVariable("type") String type,
+            HttpServletRequest servletRequest,
+            HttpServletResponse servletResponse)
+            throws UnsupportedEncodingException {
+
+        log.info("request:{}", JsonUtil.toJsonString(servletRequest.getParameterMap()));
+        Enumeration<String> names = servletRequest.getParameterNames();
+        StringBuilder sb = new StringBuilder();
+        while (names.hasMoreElements()) {
+            String name = names.nextElement();
+            sb.append(name).append("=")
+                    .append(URLEncoder.encode(servletRequest.getParameter(name), "UTF-8"))
+                    .append("&");
+        }
+
+        MediaType mediaType = MediaType.parse("application/x-www-form-urlencoded");
+        RequestBody body = RequestBody.create(mediaType, sb.toString());
+
+        Request.Builder builder = new Request.Builder();
+        Request request = builder.url("https://auth.iotkit.cc/realms/iotkit/protocol/openid-connect/token")
+                .method("POST", body)
+                .build();
+        log.info("send request body:{}", sb.toString());
+
+        Response response;
+        try {
+            response = client.newCall(request).execute();
+            servletResponse.setStatus(response.code());
+            Headers headers = response.headers();
+            for (String name : headers.names()) {
+                log.info("response header,name:{},value:{}", name, headers.get(name));
+                servletResponse.setHeader(name, headers.get(name));
+            }
+            String bodyStr = response.body().string();
+            log.info("response body:{}", bodyStr);
+            TokenInfo tokenInfo = JsonUtil.parse(bodyStr, TokenInfo.class);
+            String accessToken = tokenInfo.getAccess_token();
+            String[] tokenParts = accessToken.split("\\.");
+            Base64.Decoder decoder = Base64.getUrlDecoder();
+            String payloadStr = new String(decoder.decode(tokenParts[1]));
+            TokenPayload payload = JsonUtil.parse(payloadStr, TokenPayload.class);
+            log.info("token payload:{}", payloadStr);
+
+            //保存用户授权token
+            String uid = payload.getSub();
+            thirdUserSessionRepository.save(ThirdUserSession.builder()
+                    .uid(uid)
+                    .token(accessToken)
+                    .type(type)
+                    .authAt(System.currentTimeMillis())
+                    .build());
+
+            servletResponse.setContentType("application/json");
+            servletResponse.getWriter().write(bodyStr);
+        } catch (IOException e) {
+            log.error("request error", e);
+        }
+    }
+
+    @Data
+    public static class TokenInfo {
+        private String access_token;
+    }
+
+    @Data
+    public static class TokenPayload {
+        private String sub;
+    }
+}

+ 0 - 16
manager/src/main/java/cc/iotkit/manager/controller/api/AccountController.java

@@ -3,8 +3,6 @@ package cc.iotkit.manager.controller.api;
 import cc.iotkit.dao.AppInfoRepository;
 import cc.iotkit.dao.HomeRepository;
 import cc.iotkit.dao.UserInfoRepository;
-import cc.iotkit.manager.model.vo.LoginResult;
-import cc.iotkit.manager.service.AccountService;
 import cc.iotkit.manager.utils.AuthUtil;
 import cc.iotkit.model.AppInfo;
 import cc.iotkit.model.space.Home;
@@ -22,8 +20,6 @@ import org.springframework.web.bind.annotation.RestController;
 @RequestMapping("/api/account")
 public class AccountController {
 
-    @Autowired
-    private AccountService accountService;
     @Autowired
     private HomeRepository homeRepository;
     @Autowired
@@ -31,18 +27,6 @@ public class AccountController {
     @Autowired
     private AppInfoRepository appInfoRepository;
 
-    @ApiOperation("用户注册")
-    @PostMapping("/register")
-    public void register(String uid, String pwd) {
-        accountService.register(uid, pwd);
-    }
-
-    @ApiOperation("用户登录")
-    @PostMapping("/login")
-    public LoginResult login(String uid, String pwd) {
-        return new LoginResult(accountService.login(uid, pwd));
-    }
-
     @ApiOperation("设置当前家庭")
     @PostMapping("/setHomeId")
     public void setHomeId(String homeId) {

+ 0 - 3
manager/src/main/java/cc/iotkit/manager/controller/api/DeviceController.java

@@ -3,7 +3,6 @@ package cc.iotkit.manager.controller.api;
 import cc.iotkit.dao.AppDesignRepository;
 import cc.iotkit.dao.DeviceRepository;
 import cc.iotkit.dao.SpaceDeviceRepository;
-import cc.iotkit.dao.UserActionLogRepository;
 import cc.iotkit.manager.model.vo.AppPageNode;
 import cc.iotkit.manager.service.AppDesignService;
 import cc.iotkit.manager.service.DeviceService;
@@ -39,8 +38,6 @@ public class DeviceController {
     @Autowired
     private AppDesignRepository appDesignRepository;
     @Autowired
-    private UserActionLogRepository userActionLogRepository;
-    @Autowired
     private AppDesignService appDesignService;
 
     @ApiOperation("设备列表")

+ 0 - 43
manager/src/main/java/cc/iotkit/manager/service/AccountService.java

@@ -1,43 +0,0 @@
-package cc.iotkit.manager.service;
-
-import cc.iotkit.common.Constants;
-import cc.iotkit.common.utils.CodecUtil;
-import cc.iotkit.dao.UserAccountRepository;
-import cc.iotkit.dao.UserInfoRepository;
-import cc.iotkit.model.UserAccount;
-import cc.iotkit.model.UserInfo;
-import lombok.SneakyThrows;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.data.domain.Example;
-import org.springframework.stereotype.Service;
-
-@Service
-public class AccountService {
-    @Autowired
-    private UserAccountRepository accountRepository;
-    @Autowired
-    private UserInfoRepository userInfoRepository;
-
-    @SneakyThrows
-    public String login(String uid, String pwd) {
-        UserAccount account = accountRepository.findOne(Example.of(UserAccount.builder().uid(uid).build()))
-                .orElseThrow(() -> new RuntimeException("用户名或密码错误"));
-        String encodePwd = CodecUtil.aesEncrypt(uid + pwd, Constants.ACCOUNT_SECRET);
-        if (!account.getPwd().equals(encodePwd)) {
-            throw new RuntimeException("用户名或密码错误");
-        }
-        return CodecUtil.aesEncrypt(System.currentTimeMillis() + "_" + uid, Constants.ACCOUNT_SECRET);
-    }
-
-    @SneakyThrows
-    public void register(String uid, String pwd) {
-        if (accountRepository.exists(Example.of(UserAccount.builder().uid(uid).build()))) {
-            throw new RuntimeException("用户名已存在");
-        }
-        accountRepository.save(UserAccount.builder().uid(uid)
-                .pwd(CodecUtil.aesEncrypt(uid + pwd, Constants.ACCOUNT_SECRET))
-                .build());
-        userInfoRepository.save(UserInfo.builder().uid(uid).build());
-    }
-
-}

+ 40 - 0
model/src/main/java/cc/iotkit/model/ThirdUserSession.java

@@ -0,0 +1,40 @@
+package cc.iotkit.model;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.springframework.data.annotation.Id;
+import org.springframework.data.mongodb.core.mapping.Document;
+
+/**
+ * 第三方接入用户会话
+ */
+@Data
+@Document
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class ThirdUserSession {
+
+    /**
+     * 账号id
+     */
+    @Id
+    private String uid;
+
+    /**
+     * 账号类型
+     */
+    private String type;
+
+    /**
+     * 登录授权后的token
+     */
+    private String token;
+
+    /**
+     * 授权时间
+     */
+    private Long authAt;
+}

+ 3 - 8
model/src/main/java/cc/iotkit/model/UserInfo.java

@@ -8,6 +8,7 @@ import lombok.NoArgsConstructor;
 import org.springframework.data.annotation.Id;
 import org.springframework.data.mongodb.core.mapping.Document;
 
+import java.util.ArrayList;
 import java.util.List;
 
 @JsonIgnoreProperties(ignoreUnknown = true)
@@ -72,16 +73,10 @@ public class UserInfo implements Owned {
 
     /**
      * 用户使用的平台
+     * 见:Constants.THIRD_PLATFORM
      */
-    private Platforms usePlatforms = new Platforms();
+    private List<String> usePlatforms = new ArrayList<>();
 
     private Long createAt;
 
-    @Data
-    public static class Platforms {
-        /**
-         * 天猫精灵
-         */
-        private boolean aligenie;
-    }
 }

+ 5 - 3
model/src/main/java/cc/iotkit/model/device/DeviceInfo.java

@@ -8,6 +8,8 @@ import lombok.NoArgsConstructor;
 import org.springframework.data.annotation.Id;
 import org.springframework.data.mongodb.core.mapping.Document;
 
+import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
@@ -39,16 +41,16 @@ public class DeviceInfo implements Owned {
     /**
      * 关联子用户ID列表
      */
-    private List<String> subUid;
+    private List<String> subUid = new ArrayList<>();
 
     private State state = new State();
 
-    private Map<String, Object> property;
+    private Map<String, Object> property = new HashMap<>();
 
     /**
      * 设备标签
      */
-    private Map<String, Tag> tag;
+    private Map<String, Tag> tag = new HashMap<>();
 
     private Long createAt;
 

+ 30 - 6
protocol-gateway/component-server/src/main/java/cc/iotkit/comps/ApiTool.java

@@ -51,8 +51,32 @@ public class ApiTool {
         this.timeout = timeout;
     }
 
-    private String getPath(String path) {
-        return Paths.get(Constants.API.DEVICE_BASE, path).toString();
+    private String getDevicePath(String path) {
+        return Paths.get(Constants.API_DEVICE.BASE, path).toString();
+    }
+
+    private String getSpacePath(String path) {
+        return Paths.get(Constants.API_SPACE.BASE, path).toString();
+    }
+
+    /**
+     * 获取用户空间中设备列表
+     */
+    public ApiResponse getSpaceDevices(String token) {
+        HttpRequest<Buffer> request = client
+                .get(port, host, getSpacePath(Constants.API_SPACE.SPACE_DEVICES
+                        .replace("{spaceId}", "all")));
+        return send(token, HttpMethod.GET, request, new HashMap<>());
+    }
+
+    /**
+     * 获取空间设备详情
+     */
+    public ApiResponse getSpaceDeviceDetail(String token, String deviceId) {
+        HttpRequest<Buffer> request = client
+                .get(port, host, getSpacePath(Constants.API_SPACE.GET_DEVICE
+                        .replace("{deviceId}", deviceId)));
+        return send(token, HttpMethod.GET, request, new HashMap<>());
     }
 
     /**
@@ -60,7 +84,7 @@ public class ApiTool {
      */
     public ApiResponse getDevices(String token) {
         HttpRequest<Buffer> request = client
-                .post(port, host, getPath(Constants.API.DEVICE_LIST
+                .post(port, host, getDevicePath(Constants.API_DEVICE.LIST
                         .replace("{size}", "1000")
                         .replace("{page}", "1")));
         return send(token, HttpMethod.POST, request, new HashMap<>());
@@ -71,7 +95,7 @@ public class ApiTool {
      */
     public ApiResponse getDeviceDetail(String token, String deviceId) {
         HttpRequest<Buffer> request = client
-                .get(port, host, getPath(Constants.API.DEVICE_DETAIL
+                .get(port, host, getDevicePath(Constants.API_DEVICE.DETAIL
                         .replace("{deviceId}", deviceId)));
         return send(token, HttpMethod.GET, request, new HashMap<>());
     }
@@ -81,7 +105,7 @@ public class ApiTool {
      */
     public ApiResponse setProperties(String token, String deviceId, Map<String, Object> properties) {
         HttpRequest<Buffer> request = client
-                .post(port, host, getPath(Constants.API.DEVICE_SET_PROPERTIES
+                .post(port, host, getDevicePath(Constants.API_DEVICE.SET_PROPERTIES
                         .replace("{deviceId}", deviceId)));
         return send(token, HttpMethod.POST, request, properties);
     }
@@ -91,7 +115,7 @@ public class ApiTool {
      */
     public ApiResponse invokeService(String token, String deviceId, String service, Map<String, Object> params) {
         HttpRequest<Buffer> request = client
-                .post(port, host, getPath(Constants.API.DEVICE_INVOKE_SERVICE
+                .post(port, host, getDevicePath(Constants.API_DEVICE.INVOKE_SERVICE
                         .replace("{deviceId}", deviceId)
                         .replace("{service}", service)));
         return send(token, HttpMethod.POST, request, params);

+ 1 - 0
protocol-gateway/component-server/src/main/java/cc/iotkit/comps/BizComponentManager.java

@@ -69,6 +69,7 @@ public class BizComponentManager {
                     resolve(ProtocolComponent.SCRIPT_FILE_NAME).toFile(), "UTF-8");
             componentInstance.setScript(componentScript);
             componentInstance.putScriptEnv("deviceBehaviour", deviceBehaviourService);
+            componentInstance.putScriptEnv("apiTool", new ApiTool());
         } catch (IOException e) {
             throw new BizException("get component script error", e);
         }