autodesk-forgeautodesk-viewerautodeskautodesk-model-derivativeautodesk-data-visualization

Autodesk platform service model translation issue for aps-iot-extensions


I've been testing the APS IoT extension code with one Revit model below. I have used both the APS plugin on VScode and this site (https://oss-manager.autodesk.io) to upload and translate my model. With the same Revit file, I got 2 different kinds of models below with different URNs and did.

The weird thing is that I've managed to get the heatmaps and sensors to work in the second model ( the second picture), but not with the the first model (first picture). Recently, I accidentally deleted the second model (the working one) from my buckets. Now, whenever I upload my model with the above bucket tools, I always end up getting the first model which doesn't show any heatmaps.

I'd like to know if there is any way I can translate my model so that it will give me back the second model. Or how can I get the first model to work with heatmaps? I guess it might be something related to the model derivative or the model translation part.

Thank you.

https://github.com/autodesk-platform-services/aps-iot-extensions-demo

First model 1st model Second model 2nd model


Solution

  • Thanks for the test model. Everything looks fine on my side. Please check my email for the snapshots.

    Here is my code for producing sensor data in services/iot.mocked.js:

    async function findRoomRootNode(name, model) {
        return new Promise(function (resolve, reject) {
          model.getObjectTree(function (tree) {
            let dbId = null;
            tree.enumNodeChildren(tree.getRootId(), function (dbid) {
              let n = tree.getNodeName(dbid, true);
              if (n && n.indexOf(name) >= 0) {
                  dbId = dbid;
              }
            });
    
            resolve(dbId);
          }, reject);
        });
    }
    
    async function findLeafNodes(rootId, model) {
        return new Promise(function (resolve, reject) {
          model.getObjectTree(function (tree) {
            let leaves = [];
            tree.enumNodeChildren(rootId, function (dbid) {
              if (tree.getChildCount(dbid) === 0) {
                leaves.push(dbid);
              }
            }, true /* recursively enumerate children's children as well */);
            resolve(leaves);
          }, reject);
        });
    }
    
    function getBoundingBox(dbId, model) {
        const it = model.getInstanceTree();
        const fragList = model.getFragmentList();
        let bounds = new THREE.Box3();
    
        it.enumNodeFragments(dbId, (fragId) => {
            let box = new THREE.Box3();
            fragList.getWorldBounds(fragId, box);
            bounds.union(box);
        }, true);
    
        return bounds;
    }
    
    async function getRoomsInfo(roomIds, model) {
        return new Promise((resolve, reject) => {
            model.getBulkProperties2(
                roomIds,
                { propFilter: ['name', 'Name', 'Level', 'level' ], ignoreHidden: true },
                (result) => {
                    let sensors = {};
                    for (let i = 0; i < result.length; i++) {
                        const data = result[i];
                        const dbId = data.dbId;
                        const levelProp = data.properties.find(p => p.attributeName.toLowerCase() === 'level');
                        const bounds = getBoundingBox(dbId, model);
                        const position = bounds.center();
    
                        sensors[`sensor-${i+1}`] = {
                            name: data.name,
                            description: '',
                            groupName: levelProp.displayValue,
                            location: {
                                x: position.x,
                                y: position.y,
                                z: position.z
                            },
                            objectId: dbId
                        }
                    }
    
                    resolve(sensors);
                },
                (error) => reject(error)
            );
        });
    }
    
    var roomRootId = await findRoomRootNode('Rooms', viewer)
    var roomIds = await findLeafNodes(roomRootId, viewer.model);
    
    await getRoomsInfo(roomIds, viewer.model);
    

    Aftward, you must adjust the sensor data in the getSamples function in services/iot.mocked.js to make the number consistent with the sensor amount like below

    async function getSamples(timerange, resolution = 32) {
        return {
            count: resolution,
            timestamps: generateTimestamps(timerange.start, timerange.end, resolution),
            data: {
                'sensor-1': {
                    'temp': generateRandomValues(18.0, 28.0, resolution, 1.0),
                    'co2': generateRandomValues(540.0, 600.0, resolution, 5.0)
                },
                'sensor-2': {
                    'temp': generateRandomValues(20.0, 24.0, resolution, 1.0),
                    'co2': generateRandomValues(540.0, 600.0, resolution, 5.0)
                },
                'sensor-3': {
                    'temp': generateRandomValues(24.0, 28.0, resolution, 1.0),
                    'co2': generateRandomValues(500.0, 620.0, resolution, 5.0)
                },
                'sensor-4': {
                    'temp': generateRandomValues(20.0, 24.0, resolution, 1.0),
                    'co2': generateRandomValues(600.0, 640.0, resolution, 5.0)
                },
                'sensor-5': {
                    'temp': generateRandomValues(18.0, 28.0, resolution, 1.0),
                    'co2': generateRandomValues(540.0, 600.0, resolution, 5.0)
                },
                'sensor-6': {
                    'temp': generateRandomValues(20.0, 24.0, resolution, 1.0),
                    'co2': generateRandomValues(540.0, 600.0, resolution, 5.0)
                },
                'sensor-7': {
                    'temp': generateRandomValues(24.0, 28.0, resolution, 1.0),
                    'co2': generateRandomValues(500.0, 620.0, resolution, 5.0)
                },
                'sensor-8': {
                    'temp': generateRandomValues(20.0, 24.0, resolution, 1.0),
                    'co2': generateRandomValues(600.0, 640.0, resolution, 5.0)
                },
                'sensor-9': {
                    'temp': generateRandomValues(24.0, 28.0, resolution, 1.0),
                    'co2': generateRandomValues(500.0, 620.0, resolution, 5.0)
                },
                'sensor-10': {
                    'temp': generateRandomValues(20.0, 24.0, resolution, 1.0),
                    'co2': generateRandomValues(600.0, 640.0, resolution, 5.0)
                },
                'sensor-11': {
                    'temp': generateRandomValues(18.0, 28.0, resolution, 1.0),
                    'co2': generateRandomValues(540.0, 600.0, resolution, 5.0)
                },
                'sensor-12': {
                    'temp': generateRandomValues(20.0, 24.0, resolution, 1.0),
                    'co2': generateRandomValues(540.0, 600.0, resolution, 5.0)
                },
                'sensor-13': {
                    'temp': generateRandomValues(24.0, 28.0, resolution, 1.0),
                    'co2': generateRandomValues(500.0, 620.0, resolution, 5.0)
                },
                'sensor-14': {
                    'temp': generateRandomValues(20.0, 24.0, resolution, 1.0),
                    'co2': generateRandomValues(600.0, 640.0, resolution, 5.0)
                },
                'sensor-15': {
                    'temp': generateRandomValues(18.0, 28.0, resolution, 1.0),
                    'co2': generateRandomValues(540.0, 600.0, resolution, 5.0)
                },
                'sensor-16': {
                    'temp': generateRandomValues(20.0, 24.0, resolution, 1.0),
                    'co2': generateRandomValues(540.0, 600.0, resolution, 5.0)
                },
                'sensor-17': {
                    'temp': generateRandomValues(24.0, 28.0, resolution, 1.0),
                    'co2': generateRandomValues(500.0, 620.0, resolution, 5.0)
                },
                'sensor-18': {
                    'temp': generateRandomValues(20.0, 24.0, resolution, 1.0),
                    'co2': generateRandomValues(600.0, 640.0, resolution, 5.0)
                },
                'sensor-19': {
                    'temp': generateRandomValues(24.0, 28.0, resolution, 1.0),
                    'co2': generateRandomValues(500.0, 620.0, resolution, 5.0)
                },
                'sensor-20': {
                    'temp': generateRandomValues(20.0, 24.0, resolution, 1.0),
                    'co2': generateRandomValues(600.0, 640.0, resolution, 5.0)
                },
                'sensor-21': {
                    'temp': generateRandomValues(18.0, 28.0, resolution, 1.0),
                    'co2': generateRandomValues(540.0, 600.0, resolution, 5.0)
                },
                'sensor-22': {
                    'temp': generateRandomValues(20.0, 24.0, resolution, 1.0),
                    'co2': generateRandomValues(540.0, 600.0, resolution, 5.0)
                },
                'sensor-23': {
                    'temp': generateRandomValues(24.0, 28.0, resolution, 1.0),
                    'co2': generateRandomValues(500.0, 620.0, resolution, 5.0)
                },
                'sensor-24': {
                    'temp': generateRandomValues(20.0, 24.0, resolution, 1.0),
                    'co2': generateRandomValues(600.0, 640.0, resolution, 5.0)
                },
                'sensor-25': {
                    'temp': generateRandomValues(18.0, 28.0, resolution, 1.0),
                    'co2': generateRandomValues(540.0, 600.0, resolution, 5.0)
                },
                'sensor-26': {
                    'temp': generateRandomValues(20.0, 24.0, resolution, 1.0),
                    'co2': generateRandomValues(540.0, 600.0, resolution, 5.0)
                },
                'sensor-27': {
                    'temp': generateRandomValues(24.0, 28.0, resolution, 1.0),
                    'co2': generateRandomValues(500.0, 620.0, resolution, 5.0)
                },
                'sensor-28': {
                    'temp': generateRandomValues(20.0, 24.0, resolution, 1.0),
                    'co2': generateRandomValues(600.0, 640.0, resolution, 5.0)
                },
                'sensor-29': {
                    'temp': generateRandomValues(24.0, 28.0, resolution, 1.0),
                    'co2': generateRandomValues(500.0, 620.0, resolution, 5.0)
                },
                'sensor-30': {
                    'temp': generateRandomValues(20.0, 24.0, resolution, 1.0),
                    'co2': generateRandomValues(600.0, 640.0, resolution, 5.0)
                },
                'sensor-31': {
                    'temp': generateRandomValues(18.0, 28.0, resolution, 1.0),
                    'co2': generateRandomValues(540.0, 600.0, resolution, 5.0)
                },
                'sensor-32': {
                    'temp': generateRandomValues(20.0, 24.0, resolution, 1.0),
                    'co2': generateRandomValues(540.0, 600.0, resolution, 5.0)
                },
                'sensor-33': {
                    'temp': generateRandomValues(24.0, 28.0, resolution, 1.0),
                    'co2': generateRandomValues(500.0, 620.0, resolution, 5.0)
                },
                'sensor-34': {
                    'temp': generateRandomValues(20.0, 24.0, resolution, 1.0),
                    'co2': generateRandomValues(600.0, 640.0, resolution, 5.0)
                },
                'sensor-35': {
                    'temp': generateRandomValues(18.0, 28.0, resolution, 1.0),
                    'co2': generateRandomValues(540.0, 600.0, resolution, 5.0)
                },
                'sensor-36': {
                    'temp': generateRandomValues(20.0, 24.0, resolution, 1.0),
                    'co2': generateRandomValues(540.0, 600.0, resolution, 5.0)
                },
                'sensor-37': {
                    'temp': generateRandomValues(24.0, 28.0, resolution, 1.0),
                    'co2': generateRandomValues(500.0, 620.0, resolution, 5.0)
                },
                'sensor-38': {
                    'temp': generateRandomValues(20.0, 24.0, resolution, 1.0),
                    'co2': generateRandomValues(600.0, 640.0, resolution, 5.0)
                },
                'sensor-39': {
                    'temp': generateRandomValues(24.0, 28.0, resolution, 1.0),
                    'co2': generateRandomValues(500.0, 620.0, resolution, 5.0)
                },
                'sensor-40': {
                    'temp': generateRandomValues(20.0, 24.0, resolution, 1.0),
                    'co2': generateRandomValues(600.0, 640.0, resolution, 5.0)
                },
                'sensor-41': {
                    'temp': generateRandomValues(18.0, 28.0, resolution, 1.0),
                    'co2': generateRandomValues(540.0, 600.0, resolution, 5.0)
                },
                'sensor-42': {
                    'temp': generateRandomValues(20.0, 24.0, resolution, 1.0),
                    'co2': generateRandomValues(540.0, 600.0, resolution, 5.0)
                },
                'sensor-43': {
                    'temp': generateRandomValues(24.0, 28.0, resolution, 1.0),
                    'co2': generateRandomValues(500.0, 620.0, resolution, 5.0)
                },
                'sensor-44': {
                    'temp': generateRandomValues(20.0, 24.0, resolution, 1.0),
                    'co2': generateRandomValues(600.0, 640.0, resolution, 5.0)
                },
                'sensor-45': {
                    'temp': generateRandomValues(18.0, 28.0, resolution, 1.0),
                    'co2': generateRandomValues(540.0, 600.0, resolution, 5.0)
                },
                'sensor-46': {
                    'temp': generateRandomValues(20.0, 24.0, resolution, 1.0),
                    'co2': generateRandomValues(540.0, 600.0, resolution, 5.0)
                },
                'sensor-47': {
                    'temp': generateRandomValues(24.0, 28.0, resolution, 1.0),
                    'co2': generateRandomValues(500.0, 620.0, resolution, 5.0)
                },
                'sensor-48': {
                    'temp': generateRandomValues(20.0, 24.0, resolution, 1.0),
                    'co2': generateRandomValues(600.0, 640.0, resolution, 5.0)
                },
                'sensor-49': {
                    'temp': generateRandomValues(24.0, 28.0, resolution, 1.0),
                    'co2': generateRandomValues(500.0, 620.0, resolution, 5.0)
                },
                'sensor-50': {
                    'temp': generateRandomValues(20.0, 24.0, resolution, 1.0),
                    'co2': generateRandomValues(600.0, 640.0, resolution, 5.0)
                },
                'sensor-51': {
                    'temp': generateRandomValues(18.0, 28.0, resolution, 1.0),
                    'co2': generateRandomValues(540.0, 600.0, resolution, 5.0)
                },
                'sensor-52': {
                    'temp': generateRandomValues(20.0, 24.0, resolution, 1.0),
                    'co2': generateRandomValues(540.0, 600.0, resolution, 5.0)
                },
                'sensor-53': {
                    'temp': generateRandomValues(24.0, 28.0, resolution, 1.0),
                    'co2': generateRandomValues(500.0, 620.0, resolution, 5.0)
                },
                'sensor-54': {
                    'temp': generateRandomValues(20.0, 24.0, resolution, 1.0),
                    'co2': generateRandomValues(600.0, 640.0, resolution, 5.0)
                },
                'sensor-55': {
                    'temp': generateRandomValues(18.0, 28.0, resolution, 1.0),
                    'co2': generateRandomValues(540.0, 600.0, resolution, 5.0)
                },
                'sensor-56': {
                    'temp': generateRandomValues(20.0, 24.0, resolution, 1.0),
                    'co2': generateRandomValues(540.0, 600.0, resolution, 5.0)
                },
                'sensor-57': {
                    'temp': generateRandomValues(24.0, 28.0, resolution, 1.0),
                    'co2': generateRandomValues(500.0, 620.0, resolution, 5.0)
                },
                'sensor-58': {
                    'temp': generateRandomValues(20.0, 24.0, resolution, 1.0),
                    'co2': generateRandomValues(600.0, 640.0, resolution, 5.0)
                },
                'sensor-59': {
                    'temp': generateRandomValues(24.0, 28.0, resolution, 1.0),
                    'co2': generateRandomValues(500.0, 620.0, resolution, 5.0)
                },
                'sensor-60': {
                    'temp': generateRandomValues(20.0, 24.0, resolution, 1.0),
                    'co2': generateRandomValues(600.0, 640.0, resolution, 5.0)
                },
                'sensor-61': {
                    'temp': generateRandomValues(18.0, 28.0, resolution, 1.0),
                    'co2': generateRandomValues(540.0, 600.0, resolution, 5.0)
                },
                'sensor-62': {
                    'temp': generateRandomValues(20.0, 24.0, resolution, 1.0),
                    'co2': generateRandomValues(540.0, 600.0, resolution, 5.0)
                },
                'sensor-63': {
                    'temp': generateRandomValues(24.0, 28.0, resolution, 1.0),
                    'co2': generateRandomValues(500.0, 620.0, resolution, 5.0)
                },
                'sensor-64': {
                    'temp': generateRandomValues(20.0, 24.0, resolution, 1.0),
                    'co2': generateRandomValues(600.0, 640.0, resolution, 5.0)
                },
                'sensor-65': {
                    'temp': generateRandomValues(18.0, 28.0, resolution, 1.0),
                    'co2': generateRandomValues(540.0, 600.0, resolution, 5.0)
                },
                'sensor-66': {
                    'temp': generateRandomValues(20.0, 24.0, resolution, 1.0),
                    'co2': generateRandomValues(540.0, 600.0, resolution, 5.0)
                },
                'sensor-67': {
                    'temp': generateRandomValues(24.0, 28.0, resolution, 1.0),
                    'co2': generateRandomValues(500.0, 620.0, resolution, 5.0)
                },
                'sensor-68': {
                    'temp': generateRandomValues(20.0, 24.0, resolution, 1.0),
                    'co2': generateRandomValues(600.0, 640.0, resolution, 5.0)
                },
                'sensor-69': {
                    'temp': generateRandomValues(24.0, 28.0, resolution, 1.0),
                    'co2': generateRandomValues(500.0, 620.0, resolution, 5.0)
                },
                'sensor-70': {
                    'temp': generateRandomValues(20.0, 24.0, resolution, 1.0),
                    'co2': generateRandomValues(600.0, 640.0, resolution, 5.0)
                },
                'sensor-71': {
                    'temp': generateRandomValues(18.0, 28.0, resolution, 1.0),
                    'co2': generateRandomValues(540.0, 600.0, resolution, 5.0)
                },
                'sensor-72': {
                    'temp': generateRandomValues(20.0, 24.0, resolution, 1.0),
                    'co2': generateRandomValues(540.0, 600.0, resolution, 5.0)
                },
                'sensor-73': {
                    'temp': generateRandomValues(24.0, 28.0, resolution, 1.0),
                    'co2': generateRandomValues(500.0, 620.0, resolution, 5.0)
                },
                'sensor-74': {
                    'temp': generateRandomValues(20.0, 24.0, resolution, 1.0),
                    'co2': generateRandomValues(600.0, 640.0, resolution, 5.0)
                },
                'sensor-75': {
                    'temp': generateRandomValues(18.0, 28.0, resolution, 1.0),
                    'co2': generateRandomValues(540.0, 600.0, resolution, 5.0)
                },
                'sensor-76': {
                    'temp': generateRandomValues(20.0, 24.0, resolution, 1.0),
                    'co2': generateRandomValues(540.0, 600.0, resolution, 5.0)
                },
                'sensor-77': {
                    'temp': generateRandomValues(24.0, 28.0, resolution, 1.0),
                    'co2': generateRandomValues(500.0, 620.0, resolution, 5.0)
                },
                'sensor-78': {
                    'temp': generateRandomValues(20.0, 24.0, resolution, 1.0),
                    'co2': generateRandomValues(600.0, 640.0, resolution, 5.0)
                },
                'sensor-79': {
                    'temp': generateRandomValues(24.0, 28.0, resolution, 1.0),
                    'co2': generateRandomValues(500.0, 620.0, resolution, 5.0)
                },
                'sensor-80': {
                    'temp': generateRandomValues(20.0, 24.0, resolution, 1.0),
                    'co2': generateRandomValues(600.0, 640.0, resolution, 5.0)
                },
                'sensor-81': {
                    'temp': generateRandomValues(18.0, 28.0, resolution, 1.0),
                    'co2': generateRandomValues(540.0, 600.0, resolution, 5.0)
                },
                'sensor-82': {
                    'temp': generateRandomValues(20.0, 24.0, resolution, 1.0),
                    'co2': generateRandomValues(540.0, 600.0, resolution, 5.0)
                },
                'sensor-83': {
                    'temp': generateRandomValues(24.0, 28.0, resolution, 1.0),
                    'co2': generateRandomValues(500.0, 620.0, resolution, 5.0)
                }
            }
        };
    }
    

    Regarding the second model, if you used the same APS_MODEL_VIEW from the first model, then your view would be incorrect. The master views are generated during the Model Derivative translation, so their guid or viewable id will be different. You cannot reuse the same value and set it to APS_MODEL_VIEW in public/config.js. After retranslating the model, you must find the correct guid for the master view in the model manifest again.

    To prevent this issue, we could give APS_MODEL_VIEW an empty value and then modify public/viewer.js

    // public/config.js
    
    export const APS_MODEL_URN = 'dXJ....Z0';
    export const APS_MODEL_VIEW = '';
    export const APS_MODEL_DEFAULT_FLOOR_INDEX = 1;
    export const DEFAULT_TIMERANGE_START = new Date('2023-12-30');
    export const DEFAULT_TIMERANGE_END = new Date('2024-01-15');
    
    // Replace the function `loadModel` in public/viewer.js with the below one
    
    export function loadModel(viewer, urn, guid) {
        return new Promise(function (resolve, reject) {
            function onDocumentLoadSuccess(doc) {
                const viewable = guid ? doc.getRoot().findByGuid(guid) : doc.getRoot().getDefaultGeometry(true);
                resolve(viewer.loadDocumentNode(doc, viewable));
            }
            function onDocumentLoadFailure(code, message, errors) {
                reject({ code, message, errors });
            }
            Autodesk.Viewing.Document.load('urn:' + urn, onDocumentLoadSuccess, onDocumentLoadFailure);
        });
    }