iTwin / connector-samples

iTwin Connector Samples
MIT License
5 stars 2 forks source link

Link to ECInstanceId #6

Open lmborione opened 2 years ago

lmborione commented 2 years ago

I like to run a connector with the following type of input information :

ECInsanceId Name AssetType
0x20000000022 My asset Viaduct

I configure my connector with the following

const subject1 = new pcf.SubjectNode(this, { key: "Pablo-Handover" }); const lnkModel = new pcf.ModelNode(this, { key: "LinkModel1", subject: subject1, modelClass: LinkModel, partitionClass: LinkPartition }); const phyModel = new pcf.ModelNode(this, { key: "PhysicalModel1", subject: subject1, modelClass: PhysicalModel, partitionClass: PhysicalPartition }); const jsonLoader = new pcf.LoaderNode(this, { key: "pablo-xlsx-loader", model: lnkModel, loader: new pcf.XLSXLoader({ format: "xlsx", entities: ["Asset"], relationships: [], primaryKeyMap: { Asset: "ECInstanceId" }, defaultPrimaryKey: "ECInstanceId", }), }); const asset = new pcf.ElementNode(this, { key: "Asset", model: phyModel, dmo: elements.Asset, });

And the element with :

export const Asset: pcf.ElementDMO = { irEntity: "Asset", ecElement: { name: "Asset", baseClass: "BisCore:PhysicalElement", properties: [ { name: "Name", type: "String", }, { name: "Type", type: "String", }, ], }, categoryAttr: "ECInstanceId", };

Unfortunately I got :

Checking to see if there is an authorization response to be delivered. Info |itwin.pcf| Your Connector Job has started Info |itwin.pcf| Started Domain Schema Update... Info |itwin.pcf| Completed Domain Schema Update... Info |itwin.pcf| Started Dynamic Schema Update... Info |itwin.pcf| Dynamic Schema State: Unchanged Info |itwin.pcf| Completed Dynamic Schema Update. Info |itwin.pcf| Started Subject Update... Info |itwin.pcf| Subject State = Unchanged Info |itwin.pcf| Completed Subject Update. Info |itwin.pcf| Started Data Update... Info |itwin.pcf| Loader State = New Error |itwin.pcf| Error inserting element, class=PabloDynamic:Asset

ziyzhu commented 2 years ago

This error occurred because PCF could not find the Category referenced by your Asset Elements. For ElementNodes with DMO mapping to GeometricElement/PhysicalElement, you need to attach an additional property - category.

See an example here and here

// In your ./src/dmos/Element.ts

// define a new ElementDMO to populate Categories to be consumed by Assets
// This step requires you to have an additional table "AssetType" in your data source to represent categories. You could give it any name.
export const AssetType: pcf.ElementDMO = { 
irEntity: "AssetType",
ecElement: "BisCore:SpatialCategory",
};

export const Asset: pcf.ElementDMO = {
irEntity: "Asset",
ecElement: { name: "Asset", baseClass: "BisCore:PhysicalElement", properties: [ { name: "Name", type: "String", }, { name: "Type", type: "String", }, ], },
categoryAttr: "AssetType",
};
// In your Connector class

// add this line
const assetType= new pcf.ElementNode(this, { key: "AssetType", model: phyModel, dmo: elements.AssetType });

// since elements.Asset has property "categoryAttr" defined, you need to add "category" property
// PCF will then automatically link assets with their corresponding categories.
const asset = new pcf.ElementNode(this, { key: "Asset", model: phyModel, dmo: elements.Asset, category: assetType });
lmborione commented 2 years ago

Hi,

Thanks for the reply. Now it works (ie: there are no errors in the console) but I am not sure of what it did actually on the model ! When I open it I could not see the additional properties in the viewer property panel.

And when, in the imodelconsole, I run :

SELECT * FROM bis.PhysicalElement

I don't see new elements or properties either.

The other issue, is that I don't have AssetType, is it mandatory to set an categoryAttr when creating an ElementDMO ? I tried with the following:

// In your ./src/dmos/Element.ts
export const Asset: pcf.ElementDMO = {
  irEntity: "Asset",
  ecElement: {
    name: "Asset", baseClass: "BisCore:PhysicalElement",
    properties: [
      { name: "Name", type: "String", },
      { name: "Type", type: "String", },
    ],
  },
}
// In Connector class
const jsonLoader = new pcf.LoaderNode(this, {
      key: "pablo-xlsx-loader",
      model: lnkModel,
      loader: new pcf.XLSXLoader({
        format: "xlsx",
        entities: ["Asset"],
        relationships: [],
        primaryKeyMap: { Asset: "ECInstanceId" },
        defaultPrimaryKey: "ECInstanceId",
      }),
    });

const asset = new pcf.ElementNode(this, { key: "Asset", model: phyModel, dmo: elements.Asset });

And again I got the erro:

Error |itwin.pcf| Error inserting element, class=PabloDynamic:Asset:

I don't understand what is required in the ecElement field when defining an ElementDMO ? Also what is the purpose and difference between lnkModel, phyModel, defModel, ... ?

lmborione commented 2 years ago

After several test,

I changed my Asset to be:

export const Asset: pcf.ElementDMO = {
  irEntity: "Asset",  
  ecElement: {
    name: "Asset", baseClass: "BisCore:InformationRecordElement",
  },
}

Now when I run this query in imodelconsole:

Select * from bis.InformationRecordElement

It return the input from my Excel file.

Now how do I link those information to an existing 3D objects within my model ? Thanks

ziyzhu commented 2 years ago

Background: PCF provides constructs (Node, DMO) that overlay the ones you see in iTwin.js such as PhysicalElement, etc.

The other issue, is that I don't have AssetType, is it mandatory to set a categoryAttr when creating an ElementDMO

You cannot create a PhysicalElement without a Category. InformationRecordElement does not require it so you did not run into any errors.

Only GeometricElement and its subclasses can attach geometry.

categoryAttr is treated as a foreign key and used to link your Asset table (PhysicalElement) to the AssetType table (may be used as Category). Given that you don't have an AssetType table, I'd try to create one to populate Category instances that can be used to filter geometries in the viewer. If you're using Excel, you can create another sheet called "AssetType" and add it to the Loader config.

I don't understand what is required in the ecElement field when defining an ElementDMO?

ecElement dictates the schema of the Elements populated by the ElementDMO. See its type definition for further details.

Also what is the purpose and difference between lnkModel, phyModel, defModel, ... ?

Elements must be contained in Models of the same type. In your use case, you need to create PhysicalElements & Categories, which require PhysicalModel & DefinitionModel.

For more, see:

Now how do I link those information to an existing 3D objects within my model ?

To attach geometries to your GeometricElements, you can add a new callback property "modifyProps" to your ElementDMO. See an example based on pcf@0.1.2.

My advice: most documentation is embedded as comments, try to look up type definitions through your IDE to find them.