I’m trying to use the Python API to update a stream by adding layers and objects, but I’m having trouble with the objects not updating as I’d expect. in Hestia, the stream name and layers all update, but the objects do not. if I go directly to the object url though, I’m able to see that the object value has been updated. I can also get the updated object value using another API call.
I’ve tried it both with a direct call and with the PySpeckle wrapper and the result is the same. this is my input:
# Format the parameters
params={
'name': 'Load Calc Results',
'layers': [],
'objects': [],
}
for room,load in load_results.items():
params['layers'].append({'name': room})
params['objects'].append({'type': 'Number', 'value': load})
# Update the stream
update = requests.put('https://hestia.speckle.works/api/v1/streams/{}'.format(out_stream), json = params, headers = headers)
print(update.json())
it runs fine and I get a success message {'success': True, 'message': 'Patched stream fields: name,layers,objects'} and calling the objects gives me the correct result. I guess it’s not a huge deal since when I ask for the data I’m getting what I want, but it would be great if I could work out how to get the values to update in Hestia so the other members of my team can see the results.
if anyone has any insight, I’d greatly appreciate any help!
Hmmm, so if i understand correctly, the UI in the frontend is not showing the updated numbers, right? If possible, can i have the streamId so i can look into debugging it (PM if you don’t want to share).
Might be that you’re not defining the layers correctly. I see you add them only with their name, but they need a couple of extra properties to work correctly, namely. Check the specs for the layer for the full info.
Off the top of my head, they will need the following extra props:
a guid of sorts
a startIndex value (integer), defined by the index of the first object in the stream’s object list that is on that layer
an objectCount, ie how many objects are on that layer - as determined by the stream’s object list.
Simple example (in js):
let objects = [ a, b, c, d, e, f ]
let firstLayer = { name: "First Layer", guid: "id of sorts", startIndex: 0, objectCount: 2 } // [ a, b ]
let secondLayer = { name: "Second Layer", guid:"use a lib to generate it", startIndex: 2, objectCount:3 } // [ c, d, e ]
let thirdLayer = { name: "Third Layer", guid:"use a lib to generate it", startIndex: 5, objectCount:1 } // [ f ]
You can also look at the logic to generate them in the frontend ui (the view is here and the state commits methods are here.
You might also need to add topology (i don’t remember if Grasshopper or Dynamo will crap out without it, in theory they shouldn’t).
yes, the frontend isn’t showing the numbers. the streamId is ZLw_1GkWS2.
thanks for the help! yeah I’m only defining the layers with a name; I didn’t realise the other fields were required. I’ll try that out now and see if I can fix it!
If you have problems receiving it in grasshopper, then it might be the topology field. That’s easy to create actually if you don’t have nested data (trees, etc) - just define it as 0-${layer's object count}. Ie, { topology: "0-2" } if you have two objects on that layer.
@dimitrie is there something other than the topology that could be causing issues reading objects in Dynamo? I’m running into a problem where objects written to the stream in Python are coming through as null in Dynamo despite them showing up in the frontend UI.
Stream EBw4nQ7gD was manually entered by hand in the UI and Lbjn7PdIKf was pushed to the stream from Python. I’m defining the objects simply with 'name', 'type', and 'value' like this:
if lists_yes_no == 'yes':
params['description'] = 'This stream was updated from `load-collector-v2.py` by {} on {} \n\n '.format(creds['name'],datetime.datetime.now().strftime("%Y-%m-%d %H:%M"))
for i,name in enumerate(data['room 1'].keys()):
params['layers'].append({
'name': name,
'guid': str(uuid.uuid4()),
'startIndex': i*len(room_data),
'objectCount': len(room_data),
'topology': '0-{}'.format(len(room_data)),
})
for room,load in data.items():
params['objects'].append({'name': name, 'type': 'Number', 'value': load[name]})
I can’t really seem to find a difference between an object from the manual stream and an object from the python stream as it looks like it generates its own _id and hash and the other fields are similarly empty/default in the working objects. I must be missing something, but I can’t quite work it out. any help on this would be fab!
This sounds stupid, but try adding an empty space at the end of the topology string for each layer. I suspect/smell some bad string splitting on the client side… (off the top of my head, can debug around lunchtime)
Okay, got it! You’ll need to provide the orderIndex property on each layer, gh is dependent on it. I’ve made a pr with a fix to this, but in the meantime add a orderIndex prop to your layers - start at 0 for the first one and increment by one as you go