String gets converted to SpeckleAbstract

Hello everyone

In the last few days I wrote some code to extract data from Navisworks to Speckle. I can send data to Speckle, but the string data only gets converted to SpeckleAbstract and not to SpeckleString.

using System;
using System.Collections.Generic;
using System.Windows;

using Autodesk.Navisworks.Api.Plugins;

using SpeckleCore;

public static string CreateStream(Account account)
        {
            var name = "New Stream";
            var myStream = new SpeckleStream()
            {
                Objects = new List<SpeckleObject>(),
                Name = name != "" ? name : "Test Stream",
                Description = "Data from Navisworks",
                Tags = new List<string>() { "test", "navisworks" }
            };

            var sampleSize = 10;
            var myStrings = new List<object>();
            for (int i = 0; i < sampleSize; i++)
            {
                myStrings.Add($"Element {i}");
            }

            var conversionResult = SpeckleCore.Converter.Serialise(myStrings);
            myStream.Objects = conversionResult;

            var client = new SpeckleApiClient(account.RestApi, false, "navisworks_app");
            client.AuthToken = account.Token;

            try
            {
                var result = client.StreamCreateAsync(myStream).Result;
                MessageBox.Show(result.Message);

                return result.Resource.StreamId;
            }
            catch (Exception e)
            {
                MessageBox.Show(e.Message);

                return null;
            }
        }

In the debug log I can see that the SpeckleKits are getting loaded.

After second execution of the command, I have many “System.IO.FileNotFoundExceptions” exceptions in mscorlib.dll. But at the moment I don’t know why.

I hope there are enough informations to understand my problem. Thanks for your help!

Heya @jotpunktbee! Welcome to the forum, and thanks for the detailed question.

SpeckleCore, when trying to convert stuff (the SpeckleCore.Converter.Serialise call), will look for methods from kits called ToSpeckle() that are hoisted on that specific type, in your case, string. The ones that are present are in the Rhino/Dynamo parts of the kit as far as I know.

There’s two options to solve your issue:

(1) Quick one: just create a new SpeckleString() { Value = "your actual strings" } straight away. This should be quite easy to implement :slight_smile:

(2) Longer one: create a SpeckleCoreGeometryNavisworks project inside SpeckleCoreGeometry (you’ll need to clone it first). In there you can define your conversion routines that are relevant to Navisworks, including, I guess, the one for string. Also, make sure that it’s being built correctly and its dll copied to %localappdata%/SpeckleKits/SpeckleCoreGeometry (that’s where SpeckleCore looks for kits & conversions!).


(1) vs (2): I would go for (1) if you don’t forsee adding any other conversion routines, or you just want to experiment for now. I’m not an expert on Navis, so I can’t really tell what other object types there are… (2) is most welcome as a contribution, and relevant, if you see adding more conversion routines for other object types. It’s though a bit more difficult to debug (we usually either debug conversion routines, or the actual plugin, separately).

A place to read more about how kits are handled, etc. is here: https://speckle.systems/docs/developers/object-models (there’s some other, more philosophical, blogposts on the website too).

Hey @dimitrie , thanks for your fast response.

Option (1) works perfect. I think I already tried this. But I thought if there is already a method for Dynamo to convert a string to a SpeckleString, then this method would also be used to convert a string from an other software (in this case Navisworks). Is there somewhere a check from which software the data is coming?

I think what you’re looking for is the conversion routines for a kit. There’s no direct way to check where data is originally coming from, but there shouldn’t be the need for one, as plugins should be agnostic to source:

Software A <---> Speckle Kit of Choice <---> Software B
                           ^
                           |
                           v
                       Software C

When in C, you shouldn’t care if data comes from B or A, you only care wether you can convert it to the native representation in C.


If you really want to check the source of a stream, api/streams/{streamId}/clients —> will give you all the clients of that stream, namely receivers and the sender. The sender’s documentType field will tell you where it comes from. See this example:

{
    "success": true,
    "resources": [
        {
            "private": false,
            "canRead": [],
            "canWrite": [],
            "anonymousComments": false,
            "comments": [],
            "online": true,
            "_id": "5de90b085e40ac673a8e5ca5",
            "documentType": "Revit", //<---- the document type usually contains the source. 
            "streamId": "Rk0hyisas",
            "documentName": "Various",
            "documentGuid": "e084182e1a7639b22382a5b59dcaba77",
            "role": "sender",
            "owner": "5ac0c6f2cc774c3379247c1b",
            "createdAt": "2019-12-05T13:50:00.330Z",
            "updatedAt": "2019-12-05T13:50:00.330Z",
            "__v": 0
        }
    ],
    "message": "Client list for stream Rk0hyisas returned."
}

Thanks for your explanations. I will try out some more stuff :wink: