Obtain a list of asset's children via API

Hello all.

My goal is to create a system involving dynamic assets.
Assets within OpenRemote will be created / deleted to match whats happening in my data.
My issue is that I shouldn’t rely on my external clients to remember each Asset ID for each asset, for various reasons.
I would prefer to use a request or series of requests to obtain an array of all my Asset IDs.
I have them all parented by a Group Asset, where it’s ID should remain constant.

There’s no “children” key, or anything similar, within the JSON returned by ‘/api/master/asset/’ or other GET requests. Nor, do I believe, there is a GET children Request.

How can I go about this?

I was thinking of comparing the paths of Assets - try to check if they contain the Group Asset’s ID. But how would I get every Asset paths to check?

When viewing the Group Asset, you can see “Underlying Assets”. I know this isn’t a real attribute, but being able to obtain this would be perfect.

There also might be a way of re-creating my own “Underlying Assets” attribute which is automated through Groovy. But I am not sure if rules can be used in this way.

Thanks a lot.

Hi Haydn, this group control Groovy rule is including a way to retrieve dynamically all children assets of a group. Does this help to figure out what you are looking for? openremote/ChildAssetControl.groovy at master · openremote/openremote · GitHub

Hello Pierre,

Thank you for the link.
I have worked on it today and have built a solution that works for me.
My rule automates an array attribute in the parent, given a few options.

Here’s the GROOVY code:

* This rule will Automate an array of children for a parent Asset
* parentAssetId   --    The AssetID of the parent which you would like to automate
* arrayAttribute  --    The name of the Attribute within the parent which acts as the child array
* idAttribute     --    The name of the Attribute within each child that contains the Integer to use as array index

package org.openremote.test.rules

import org.openremote.manager.rules.RulesBuilder
import org.openremote.model.attribute.AttributeEvent
import org.openremote.model.query.AssetQuery
import org.openremote.model.rules.AssetState
import org.openremote.model.rules.Assets
import org.openremote.model.rules.Notifications
import org.openremote.model.rules.Users

import java.util.logging.Logger

Logger LOG = binding.LOG
RulesBuilder rules = binding.rules
Users users = binding.users
Notifications notifications = binding.notifications
Assets assets = binding.assets

// Options
String parentAssetId = "3kHesLOoFlis8aNGxWPlqB"
String arrayAttribute = "children"
String idAttribute = "id"


        .name("Obtain Group Asset Children")
            { facts ->
                //LOG.info("RAW Facts: "+ facts)
                //Get array of children
                //Obtain assets with Parent
                def children = facts.matchAssetState(
                    new AssetQuery().parents(parentAssetId)
                ).map { childState ->
                    //LOG.info("RAW CHILD STATE: "+childState)
                    //Obtain Details
                    def name = childState.assetName
                    def assetId = childState.id
                    def childId = childState.value
                    //LOG.info("Found: "+name+", '"+assetId+"'")
                    //Return as list of pairs
                    [childId, assetId]
                //LOG.info("Children: " + children)
                //Array of children, to be built
                def childArray = []
                children.each{ key, val ->
                    //Convert Optional to Int to use as key
                    def intKey = key.mapToInt(x -> x)
                      childArray[intKey.getAsInt()] = val
                //LOG.info("ARRAY: "+childArray)
                //Compare to previous
                //Get Parent
                def parent = facts.matchAssetState(
                    new AssetQuery().ids(parentAssetId).attributeName(arrayAttribute)
                //LOG.info("PARENT: "+parent)
                //Get previous value
                def optVal = parent.value
                def oldVal = []
                  oldVal = optVal.get()
                //LOG.info("VALUE: "+oldVal)
                def eq = Arrays.equals(oldVal, childArray.toArray())
                //LOG.info("OLD: "+oldVal+"\nNEW: "+childArray+"\nEQUAL: "+eq)
                //Bind child array
                facts.bind("children", childArray)
                return !eq
            { facts ->
                //LOG.info("RAW Facts: "+facts)
                //Get array and format into AttributeEvent
                def children = facts.bound("children")
                //LOG.info("RETAINED: "+children)
                //Get Parent
                def parent = facts.matchAssetState(
                    new AssetQuery().ids(parentAssetId).attributeName(arrayAttribute)
                //LOG.info("Parent: "+parent)
                //Create AttributeEvent to update parent
                def assetId = parent.id
                def pub = new AttributeEvent(assetId, arrayAttribute, children, new Date().getTime())
                //LOG.info("PUBLISH EVENT: "+pub)

Thanks again.

1 Like

Thanks for sharing Haydn!