Skip to content

Commit 6b85630

Browse files
committed
Set sites as root
Requested by Yanik
1 parent 9c07e91 commit 6b85630

18 files changed

+114
-80
lines changed

USER_GUIDE.md

+4-2
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,9 @@ Once configured, the app starts Continuous Asset Creation (CAC). Discovered reso
7979

8080
After creation of assets, the assets are organized in Eliona the same way they are organized in OpenBOS. This structure is kept synchronized, and any movements in Eliona (e.g. renaming asset or moving a room to a different building) will be overwritten with next ontology update.
8181

82-
Only exception is the asset "OpenBOS root" asset. You can rename or move this asset wherever you want, and the whole ontology will be moved with it.
82+
Only exception are the root assets. Root assets are created in the top-level directory, and correspond to the root of OpenBOS places structure. Typically, there is one Site in this role. Another root asset is the "OpenBOS unassigned" asset, containing unassigned assets and datapoints.
83+
84+
You can rename or move the root assets wherever you want, and the whole ontology will be moved with it.
8385

8486
It is not possible to change GAIs in Eliona for any of assets.
8587

@@ -107,7 +109,7 @@ Complex data types from OpenBOS are split into separate attributes in Eliona.
107109

108110
### Orphan datapoints
109111

110-
In case an asset is deleted from OpenBOS and there is still an alarm linked to that datapoint, OpenBOS leaves that datapoint in the ontology. Eliona respects that behaviour, and assigns those datapoints to a root asset.
112+
In case an asset is deleted from OpenBOS and there is still an alarm linked to that datapoint, OpenBOS leaves that datapoint in the ontology. Eliona respects that behaviour, and assigns those datapoints to an "OpenBOS unassigned" asset.
111113

112114
## Alarms
113115

broker/broker.go

+28-15
Original file line numberDiff line numberDiff line change
@@ -278,29 +278,22 @@ func FetchOntology(config appmodel.Configuration) (ontologyVersion int32, assetT
278278
assetTypes = append(assetTypes, assetType)
279279
}
280280

281-
root := eliona.Asset{
282-
ID: "",
283-
TemplateID: "root",
284-
Name: "OpenBOS",
285-
Config: &config,
286-
LocationalParentGAI: "",
287-
FunctionalParentGAI: "",
288-
}
289-
290-
// Initialize spaces map with root space
291281
spaces := make(map[string]*ontologySpaceDTO)
292-
spaces[""] = &ontologySpaceDTO{}
293282
// Build spaces map
294283
for _, space := range ontology.Spaces {
295284
spaceCopy := space
296285
spaces[space.ID] = &spaceCopy
297286
}
298287

288+
var rootSpaces []ontologySpaceDTO
299289
// Build parent-child relationships
300290
for _, space := range ontology.Spaces {
301291
if parentSpace, exists := spaces[space.ParentID]; exists {
302292
parentSpace.children = append(parentSpace.children, *spaces[space.ID])
303293
// No need to reassign parentSpace back to the map since it's a pointer
294+
} else {
295+
// This is a Site, serviving as a root
296+
rootSpaces = append(rootSpaces, space)
304297
}
305298
}
306299

@@ -310,8 +303,28 @@ func FetchOntology(config appmodel.Configuration) (ontologyVersion int32, assetT
310303
assetsMap[asset.ID] = asset
311304
}
312305

313-
// Build the asset hierarchy based on spaces
314-
buildAssetHierarchy(&root, &assets, spaces, assetsMap, config)
306+
for _, rootSpace := range rootSpaces {
307+
asset := eliona.Asset{
308+
ID: rootSpace.ID,
309+
Name: rootSpace.Name,
310+
TemplateID: rootSpace.TemplateID,
311+
Config: &config,
312+
IsRootSpace: true,
313+
}
314+
// Build the asset hierarchy based on spaces
315+
buildAssetHierarchy(&asset, &assets, spaces, assetsMap, config)
316+
}
317+
318+
unassigned := eliona.Asset{
319+
ID: "",
320+
TemplateID: "unassigned",
321+
Name: "OpenBOS unassigned",
322+
Config: &config,
323+
LocationalParentGAI: "",
324+
FunctionalParentGAI: "",
325+
IsRootSpace: true,
326+
}
327+
assets = append(assets, unassigned)
315328

316329
// Handle assets not associated with any space
317330
associatedAssetIDs := make(map[string]struct{})
@@ -328,8 +341,8 @@ func FetchOntology(config appmodel.Configuration) (ontologyVersion int32, assetT
328341
Name: asset.Name,
329342
TemplateID: asset.TemplateID,
330343
Config: &config,
331-
LocationalParentGAI: root.GetGAI(),
332-
FunctionalParentGAI: root.GetGAI(),
344+
LocationalParentGAI: unassigned.GetGAI(),
345+
FunctionalParentGAI: unassigned.GetGAI(),
333346
})
334347
}
335348
}

broker/broker_test.go

+14-14
Original file line numberDiff line numberDiff line change
@@ -132,17 +132,17 @@ func TestFetchOntology(t *testing.T) {
132132
t.Fatalf("Expected 2 assets, got %v", len(assets))
133133
}
134134

135-
rootAsset := assets[0] // Root should be the first asset in the slice
136-
if rootAsset.Name != "OpenBOS" {
137-
t.Errorf("Expected root asset name 'OpenBOS', got '%s'", rootAsset.Name)
135+
unassignedCatcherAsset := assets[0] // unassignedCatcher should be the first asset in the slice
136+
if unassignedCatcherAsset.Name != "OpenBOS unassigned" {
137+
t.Errorf("Expected unassignedCatcher asset name 'OpenBOS unassigned', got '%s'", unassignedCatcherAsset.Name)
138138
}
139139

140140
childAsset := assets[1]
141141
if childAsset.Name != "Sensor 1" {
142142
t.Errorf("Expected child asset name 'Sensor 1', got '%s'", childAsset.Name)
143143
}
144-
if childAsset.LocationalParentGAI != rootAsset.GetGAI() {
145-
t.Errorf("childAsset LocationalParentGAI = %v, expected %v", childAsset.LocationalParentGAI, rootAsset.GetGAI())
144+
if childAsset.LocationalParentGAI != unassignedCatcherAsset.GetGAI() {
145+
t.Errorf("childAsset LocationalParentGAI = %v, expected %v", childAsset.LocationalParentGAI, unassignedCatcherAsset.GetGAI())
146146
}
147147
}
148148

@@ -488,24 +488,24 @@ func TestFetchOntologyWithSpaces(t *testing.T) {
488488

489489
assert.Equal(t, 4, len(assets), "There should be all assets")
490490

491-
rootAsset := assets[0]
492-
assert.Equal(t, "OpenBOS", rootAsset.Name, "Root asset name mismatch")
493-
494-
// Check that "Building 1" has root asset as a parent
495-
building1 := assets[1]
496-
assert.Equal(t, rootAsset.GetGAI(), building1.FunctionalParentGAI, "Building 1 Functional parent")
497-
assert.Equal(t, rootAsset.GetGAI(), building1.LocationalParentGAI, "Building 1 Locational parent")
491+
// Check that "Building 1" is a root (typically it would be a "site")
492+
building1 := assets[0]
493+
assert.Equal(t, "", building1.FunctionalParentGAI, "Building 1 Functional parent")
494+
assert.Equal(t, "", building1.LocationalParentGAI, "Building 1 Locational parent")
498495
assert.Equal(t, "Building 1", building1.Name, "Building should come first")
499496

500497
// Check that 'Building 1' has 'Floor 1' as a locational child
501-
floor1 := assets[2]
498+
floor1 := assets[1]
502499
assert.Equal(t, building1.GetGAI(), floor1.FunctionalParentGAI, "Floor 1 Functional parent")
503500
assert.Equal(t, building1.GetGAI(), floor1.LocationalParentGAI, "Floor 1 Locational parent")
504501
assert.Equal(t, "Floor 1", floor1.Name, "Floor should come second")
505502

506503
// Check that 'Floor 1' has 'Sensor 1'
507-
sensor1 := assets[3]
504+
sensor1 := assets[2]
508505
assert.Equal(t, floor1.GetGAI(), sensor1.FunctionalParentGAI, "Sensor 1 Functional parent")
509506
assert.Equal(t, floor1.GetGAI(), sensor1.LocationalParentGAI, "Sensor 1 Locational parent")
510507
assert.Equal(t, "Sensor 1", sensor1.Name, "Sensor should come last")
508+
509+
rootAsset := assets[3]
510+
assert.Equal(t, "OpenBOS unassigned", rootAsset.Name, "Root asset name mismatch")
511511
}

broker/client.go

+6-6
Original file line numberDiff line numberDiff line change
@@ -378,16 +378,16 @@ func (ontology ontologyDTO) getAssetTemplates(orphanDatapoints []ontologyDatapoi
378378
}
379379
}
380380

381-
// Root asset containing orphan datapoints
382-
rootAsset := ontologyAssetOrSpaceTemplateDTO{
383-
ID: "root",
384-
Name: "root",
381+
// Asset containing orphan datapoints
382+
unassignedAsset := ontologyAssetOrSpaceTemplateDTO{
383+
ID: "unassigned",
384+
Name: "unassigned",
385385
}
386-
ontology.SpaceTemplates = append(ontology.SpaceTemplates, rootAsset)
386+
ontology.SpaceTemplates = append(ontology.SpaceTemplates, unassignedAsset)
387387
for _, orphanDatapoint := range orphanDatapoints {
388388
for _, dt := range ontology.DatapointTemplates {
389389
if orphanDatapoint.TemplateID == dt.ID {
390-
datapointTemplateMap["root"] = append(datapointTemplateMap["root"], dt)
390+
datapointTemplateMap["unassigned"] = append(datapointTemplateMap["unassigned"], dt)
391391
}
392392
}
393393
}

db/generated/alarm.go

+2-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

db/generated/asset.go

+20-4
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

db/generated/boil_queries.go

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

db/generated/boil_table_names.go

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

db/generated/boil_types.go

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

db/generated/boil_view_names.go

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

db/generated/configuration.go

+2-11
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

db/generated/eliona_attribute.go

+2-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

db/generated/openbos_datapoint.go

+2-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

db/generated/psql_upsert.go

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

db/helper/conf.go

+2-1
Original file line numberDiff line numberDiff line change
@@ -198,13 +198,14 @@ func SetAllConfigsInactive(ctx context.Context) (int64, error) {
198198
})
199199
}
200200

201-
func InsertAsset(ctx context.Context, config appmodel.Configuration, projId string, globalAssetID string, assetId int32, providerId string) (assetID int64, err error) {
201+
func InsertAsset(ctx context.Context, config appmodel.Configuration, projId string, globalAssetID string, assetId int32, providerId string, isRootSpace bool) (assetID int64, err error) {
202202
var dbAsset dbgen.Asset
203203
dbAsset.ConfigurationID = config.Id
204204
dbAsset.ProjectID = projId
205205
dbAsset.GlobalAssetID = globalAssetID
206206
dbAsset.AssetID = null.Int32From(assetId)
207207
dbAsset.ProviderID = providerId
208+
dbAsset.IsRootSpace = isRootSpace
208209
if err := dbAsset.InsertG(ctx, boil.Infer()); err != nil {
209210
return 0, fmt.Errorf("inserting asset: %v", err)
210211
}

0 commit comments

Comments
 (0)