Example #1
0
        protected SpeckleObject ToSpeckle(IBHoMObject bhomObject, SpecklePushConfig config)
        {
            // Assign SpeckleStreamId to the Fragments of the IBHoMObjects
            SetAdapterId(bhomObject, SpeckleClient.Stream.StreamId);

            // SpeckleObject "container". Top level has geometry representation of BHoM Object, so it can be visualised in the SpeckleViewer.
            SpeckleObject speckleObject = SpeckleRepresentation(bhomObject, config.RendermeshOptions);

            // If no Speckle representation is found, it will be sent as an "Abstract" SpeckleObject (no visualisation).
            if (speckleObject == null)
            {
                speckleObject = (SpeckleObject)SpeckleCore.Converter.Serialise(bhomObject);
            }

            // Save BHoMObject data inside the speckleObject.
            Modify.SetBHoMData(speckleObject, bhomObject, config.UseSpeckleSerialiser);

            speckleObject.SetDiffingHash(bhomObject, config);

            // If the BHoMObject has a "RevisionName" string field in the Customdata,
            // use that value to create a Layer for it, and set the SpeckleObject's layer.
            //object revisionValue = null;
            //string revisionName = "";
            //if (bhomObject.CustomData.TryGetValue("RevisionName", out revisionValue))
            //{
            //    revisionName = revisionValue as string;
            //    if (!string.IsNullOrWhiteSpace(revisionName))
            //        speckleObject.Properties["revisionName"] = revisionName;
            //}

            return(speckleObject);
        }
Example #2
0
        public override List <object> Push(IEnumerable <object> objects, string tag = "", PushType pushType = PushType.AdapterDefault, ActionConfig actionConfig = null)
        {
            // Clone objects for immutability in the UI
            List <object> objectsToPush = objects.Select(x => x.DeepClone()).ToList();

            // Initialize the SpeckleStream
            SpeckleClient.Stream.Objects = new List <SpeckleObject>(); // stream is immutable

            // //- Read config
            SpecklePushConfig pushConfig = (actionConfig as SpecklePushConfig) ?? new SpecklePushConfig();

            // //- Use "Speckle" history: produces a new stream at every push that corresponds to the old version. Enabled by default.
            if (pushConfig.EnableHistory)
            {
                SetupHistory();
            }

            // Actual creation and add to the stream
            for (int i = 0; i < objectsToPush.Count(); i++)
            {
                SpeckleObject speckleObject = ToSpeckle(objectsToPush[i] as dynamic, pushConfig); // Dynamic dispatch to most appropriate method

                // Add objects to the stream
                SpeckleClient.Stream.Objects.Add(speckleObject);
            }

            // // - Send the objects
            try
            {
                // Try the batch upload
                BatchUpdateStream(pushConfig);
            }
            catch (Exception e)
            {
                try
                {
                    // If the batch upload fails, try the standard SpeckleCore Update as a last resort.

                    //// - Issue: with `StreamUpdateAsync` Speckle doesn't seem to send anything if the Stream is initially empty.
                    //// - You need to Push twice if the Stream is initially empty.
                    var updateResponse = SpeckleClient.StreamUpdateAsync(SpeckleClient.Stream.StreamId, SpeckleClient.Stream).Result;
                    SpeckleClient.BroadcastMessage("stream", SpeckleClient.Stream.StreamId, new { eventType = "update-global" });
                }
                catch
                {
                    // If all has failed, return the first error.
                    BH.Engine.Reflection.Compute.RecordError($"Upload to Speckle failed. Message returned:\n{e.InnerException.Message}");
                    return(new List <object>());
                }
            }

            return(objectsToPush);
        }
Example #3
0
        protected SpeckleObject ToSpeckle(IObject iObject, SpecklePushConfig config)
        {
            // Convert the objects into the appropriate SpeckleObject using the available converters.
            SpeckleObject speckleObject = null;

            if (typeof(IGeometry).IsAssignableFrom(iObject.GetType()))
            {
                speckleObject = Speckle.Convert.IToSpeckle((IGeometry)iObject);
            }

            if (speckleObject == null)
            {
                BH.oM.Graphics.RenderMesh rm = null;

                try
                {
                    rm = BH.Engine.Representation.Compute.IRenderMesh(iObject);
                }
                catch
                {
                    BH.Engine.Reflection.Compute.RecordNote($"Could not compute the representation for an object of type {iObject.GetType().Name}.\n" +
                                                            $"This simply means that the object will not be viewable in the browser (SpeckleViewer).");
                }

                if (rm != null)
                {
                    speckleObject = Speckle.Convert.ToSpeckle(rm);
                }
                else
                {
                    speckleObject = (SpeckleObject)SpeckleCore.Converter.Serialise(iObject); // These will be exported as `Abstract` Speckle Objects.
                }
            }

            // Save BHoMObject data inside the speckleObject.
            Modify.SetBHoMData(speckleObject, iObject, config.UseSpeckleSerialiser);

            speckleObject.SetDiffingHash(iObject, config);

            return(speckleObject);
        }
Example #4
0
        public static void SetDiffingHash(this SpeckleObject speckleObject, IObject sourceObj, SpecklePushConfig config)
        {
            // SETTING THE HASH(ES)
            // SpeckleObjects have 2 hash properties: `Hash` and `GeometryHash`.
            // `Hash` is the "main" one, on which Speckle bases its diffing.
            // Therefore, what we want is that `Hash` should be set based only on the BHoM class properties -
            // not on any Speckle Object property, because we use the SpeckleObject only as a Representational container for our BHoMObject.
            // This way objects from BHoM can be diffed by the Speckle Server the same way we would diff them on the client side.

            // HOWEVER
            // This poses an issue with the fact tha speckle will not update the view in SpeckleViewer if only changes to the object REPRESENTATION are made.
            // E.g. If at some point I change how I want to see the bars, from 'extruded' to 'simple line',
            // then SpeckleViewer will not update the view (bars will stay extruded);
            // only newly pushed bars will be simple lines.

            // This is because Speckle really does not make any use of the `GeometryHash`:
            speckleObject.GeometryHash = speckleObject.Hash; // this is unfortunately useless; Speckle doesn't use it.

            // Set the "main" speckle hash equal to the diffing hash, so Speckle can do the diffing as we expect.
            string diffingHash = BH.Engine.Diffing.Compute.DiffingHash(sourceObj, config.DiffConfig);

            speckleObject.Hash = diffingHash;

            // FOR DEVELOPMENT ONLY:
            if (config.UniqueRandomHash)
            {
                speckleObject.Hash += speckleObject.GeometryHash + System.DateTime.Now.Ticks;
            }
        }
Example #5
0
        public void BatchUpdateStream(SpecklePushConfig pushConfig)
        {
            List <SpeckleObject> convertedObjects = SpeckleClient.Stream.Objects;

            SpeckleCore.SpeckleInitializer.Initialize();
            SpeckleCore.LocalContext.Init();

            LocalContext.PruneExistingObjects(convertedObjects, SpeckleClient.BaseUrl);
            List <SpeckleObject> persistedObjects = new List <SpeckleObject>();

            OrderedDictionary JobQueue = new OrderedDictionary();

            if (convertedObjects.Count(obj => obj.Type == "Placeholder") != convertedObjects.Count)
            {
                // create the update payloads
                int  count = 0;
                var  objectUpdatePayloads = new List <List <SpeckleObject> >();
                long totalBucketSize      = 0;
                long currentBucketSize    = 0;
                var  currentBucketObjects = new List <SpeckleObject>();
                var  allObjects           = new List <SpeckleObject>();
                foreach (SpeckleObject convertedObject in convertedObjects)
                {
                    if (count++ % 100 == 0)
                    {
                        //Message = "Converted " + count + " objects out of " + convertedObjects.Count() + ".";
                    }

                    // size checking & bulk object creation payloads creation
                    long size = Converter.getBytes(convertedObject).Length;
                    currentBucketSize += size;
                    totalBucketSize   += size;
                    currentBucketObjects.Add(convertedObject);

                    // Object is too big?
                    if (size > 2e6)
                    {
                        BH.Engine.Reflection.Compute.RecordWarning("An object is too big for the current Speckle limitations.");
                        currentBucketObjects.Remove(convertedObject);
                    }

                    if (currentBucketSize > 3e5) // restrict max to ~300kb;
                    {
                        //BH.Engine.Reflection.Compute.RecordNote("Reached payload limit. Making a new one, current  #: " + objectUpdatePayloads.Count);

                        objectUpdatePayloads.Add(currentBucketObjects);
                        currentBucketObjects = new List <SpeckleObject>();
                        currentBucketSize    = 0;
                    }
                }

                // add in the last bucket
                if (currentBucketObjects.Count > 0)
                {
                    objectUpdatePayloads.Add(currentBucketObjects);
                }

                if (objectUpdatePayloads.Count > 1)
                {
                    BH.Engine.Reflection.Compute.RecordNote($"Payload has been split in { objectUpdatePayloads.Count } batches. Total size is {totalBucketSize / 1024} kB.");
                }

                // create bulk object creation tasks
                List <ResponseObject> responses = new List <ResponseObject>();

                foreach (var payload in objectUpdatePayloads)
                {
                    //Message = String.Format("{0}/{1}", k++, objectUpdatePayloads.Count);
                    try
                    {
                        var objResponse = SpeckleClient.ObjectCreateAsync(payload).Result;
                        responses.Add(objResponse);
                        persistedObjects.AddRange(objResponse.Resources);

                        int m = 0;
                        foreach (var oL in payload)
                        {
                            oL._id = objResponse.Resources[m++]._id;
                        }

                        // push sent objects in the cache non-blocking
                        Task.Run(() =>
                        {
                            foreach (var oL in payload)
                            {
                                if (oL.Type != "Placeholder")
                                {
                                    LocalContext.AddSentObject(oL, SpeckleClient.BaseUrl);
                                }
                            }
                        });
                    }
                    catch (Exception err)
                    {
                        BH.Engine.Reflection.Compute.RecordWarning(err.Message);
                        continue;
                    }
                }
            }
            else
            {
                persistedObjects = convertedObjects;
            }

            // create placeholders for stream update payload
            List <SpeckleObject> placeholders = new List <SpeckleObject>();

            //foreach ( var myResponse in responses )
            foreach (var obj in persistedObjects)
            {
                placeholders.Add(new SpecklePlaceholder()
                {
                    _id = obj._id
                });
            }

            SpeckleClient.Stream.Objects = placeholders;

            // set some base properties (will be overwritten)
            var baseProps = new Dictionary <string, object>();

            baseProps["units"]                  = "m";
            baseProps["tolerance"]              = "0.001";
            baseProps["angleTolerance"]         = "0.01";
            SpeckleClient.Stream.BaseProperties = baseProps;

            var response = SpeckleClient.StreamUpdateAsync(SpeckleClient.StreamId, SpeckleClient.Stream).Result;

            SpeckleClient.BroadcastMessage("stream", SpeckleClient.StreamId, new { eventType = "update-global" });
        }
Example #6
0
 protected SpeckleObject ToSpeckle(object obj, SpecklePushConfig config)
 {
     // Convert the objects into "Abstract" SpeckleObjects
     return(SpeckleCore.Converter.Serialise(obj) as SpeckleObject);
 }