public async listThings()

in source/packages/libraries/core/thing-list-builder/src/awsIotThingListBuilder.ts [107:258]


    public async listThings(req: ListThingsRequest): Promise<ListThingsResponse> {
        logger.debug(`awsIotThingListBuilder listThings: r:${JSON.stringify(req)}`);

        ow(req, ow.object.nonEmpty);

        const thingNamesResult: string[] = [];
        const arnsOutOfRegion: string[] = [];
        if ((req.thingNames?.length ?? 0) > 0) {
            thingNamesResult.push(...req.thingNames);
        }

        const assetLibraryGroupPathsToProcess: string[] = [];
        if (req.assetLibraryGroupPaths !== undefined) {
            assetLibraryGroupPathsToProcess.push(...req.assetLibraryGroupPaths);
        }

        // if we have an Asset Library query specified, retrieve all the asset library groups/devices it relates to
        if (req.assetLibraryQuery !== undefined) {
            logger.silly(`awsIotThingListBuilder listThings: processing assetLibraryQuery`);
            let searchResults = await this.assetLibrarySearchClient.search(req.assetLibraryQuery);
            logger.silly(
                `awsIotThingListBuilder listThings: searchResults:${JSON.stringify(searchResults)}`
            );
            while ((searchResults.results?.length ?? 0) > 0) {
                for (const r of searchResults.results) {
                    if (this.isDevice(r)) {
                        const awsIotThingArn = (r as Device10Resource).awsIotThingArn;
                        if (awsIotThingArn !== undefined) {
                            if (this.isInRegion(awsIotThingArn)) {
                                thingNamesResult.push(this.getName(awsIotThingArn));
                            } else {
                                arnsOutOfRegion.push(awsIotThingArn);
                            }
                        }
                    } else {
                        assetLibraryGroupPathsToProcess.push((r as Group10Resource).groupPath);
                    }
                }
                // possibly paginated results?
                if (searchResults.pagination !== undefined) {
                    const offset = searchResults.pagination.offset;
                    const count = searchResults.pagination.count;
                    searchResults = await this.assetLibrarySearchClient.search(
                        req.assetLibraryQuery,
                        offset + count
                    );
                } else {
                    searchResults.results = [];
                }
            }
        }

        // for Asset Library groups, we need to expand to retrieve the thing arn of all devices that are a member of the group
        if (assetLibraryGroupPathsToProcess.length > 0) {
            logger.silly(
                `awsIotThingListBuilder listThings: expanding assetLibraryGroupPathsToProcess: ${JSON.stringify(
                    assetLibraryGroupPathsToProcess
                )}`
            );
            for (const groupPath of assetLibraryGroupPathsToProcess) {
                let result = await this.assetLibraryGroupClient.listGroupMembersDevices(groupPath);
                logger.silly(
                    `awsIotThingListBuilder listThings: result: ${JSON.stringify(result)}`
                );
                while (result?.results !== undefined) {
                    for (const device of result.results) {
                        if (device.awsIotThingArn) {
                            if (this.isInRegion(device.awsIotThingArn)) {
                                thingNamesResult.push(this.getName(device.awsIotThingArn));
                            } else {
                                arnsOutOfRegion.push(device.awsIotThingArn);
                            }
                        }
                    }
                    if (result.pagination === undefined) {
                        break;
                    }
                    const offset = result.pagination.offset + result.pagination.count;
                    result = await this.assetLibraryGroupClient.listGroupMembersDevices(
                        groupPath,
                        undefined,
                        undefined,
                        offset,
                        result.pagination.count
                    );
                }
            }
        }

        // for Asset Library devices, we need to get its corresponding thing arn
        if ((req.assetLibraryDeviceIds?.length ?? 0) > 0) {
            logger.silly(
                `awsIotThingListBuilder listThings: expanding assetLibraryDeviceIds: ${JSON.stringify(
                    req.assetLibraryDeviceIds
                )}`
            );
            // TODO: performance improvement, process in parallel
            const result = await this.assetLibraryDeviceClient.getDevicesByID(
                req.assetLibraryDeviceIds,
                false,
                ['awsIotThingArn'],
                []
            );
            logger.silly(`awsIotThingListBuilder listThings: result: ${JSON.stringify(result)}`);
            for (const device of result.results) {
                if (device.awsIotThingArn) {
                    if (this.isInRegion(device.awsIotThingArn)) {
                        thingNamesResult.push(this.getName(device.awsIotThingArn));
                    } else {
                        arnsOutOfRegion.push(device.awsIotThingArn);
                    }
                }
            }
        }

        // for aws iot thing groups we need to expand to retrieve the group members
        if ((req.thingGroupNames?.length ?? 0) > 0) {
            logger.silly(
                `awsIotThingListBuilder listThings: expanding thingGroupNames: ${JSON.stringify(
                    req.thingGroupNames
                )}`
            );
            for (const thingGroup of req.thingGroupNames) {
                let result = await this.iot.send(
                    new ListThingsInThingGroupCommand({ thingGroupName: thingGroup })
                );
                logger.silly(`awsIotThingListBuilder listThings: r: ${JSON.stringify(req)}`);
                while ((result.things?.length ?? 0) > 0) {
                    thingNamesResult.push(...result.things);
                    if (result.nextToken !== undefined && result.nextToken !== null) {
                        result = await this.iot.send(
                            new ListThingsInThingGroupCommand({
                                thingGroupName: thingGroup,
                                nextToken: result.nextToken,
                            })
                        );
                    } else {
                        break;
                    }
                }
            }
        }

        // one final step, make sure they're unique
        const response: ListThingsResponse = {
            thingNames: [...new Set(thingNamesResult)],
            arnsOutOfRegion: [...new Set(arnsOutOfRegion)],
        };

        logger.debug(`awsIotThingListBuilder listThings: exit:${JSON.stringify(response)}`);
        return response;
    }