kuzzle-device-manager 2.11.0-dev.1 → 3.0.0-3-dev.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (193) hide show
  1. package/dist/index.d.ts +1 -0
  2. package/dist/index.js +1 -0
  3. package/dist/index.js.map +1 -1
  4. package/dist/lib/modules/asset/AssetModule.d.ts +1 -4
  5. package/dist/lib/modules/asset/AssetModule.js +0 -13
  6. package/dist/lib/modules/asset/AssetModule.js.map +1 -1
  7. package/dist/lib/modules/asset/AssetService.d.ts +7 -4
  8. package/dist/lib/modules/asset/AssetService.js +119 -50
  9. package/dist/lib/modules/asset/AssetService.js.map +1 -1
  10. package/dist/lib/modules/asset/AssetsController.d.ts +25 -7
  11. package/dist/lib/modules/asset/AssetsController.js +123 -36
  12. package/dist/lib/modules/asset/AssetsController.js.map +1 -1
  13. package/dist/lib/modules/asset/collections/assetsMappings.js +10 -15
  14. package/dist/lib/modules/asset/collections/assetsMappings.js.map +1 -1
  15. package/dist/lib/modules/asset/exports.d.ts +0 -4
  16. package/dist/lib/modules/asset/exports.js +0 -4
  17. package/dist/lib/modules/asset/exports.js.map +1 -1
  18. package/dist/lib/modules/asset/index.d.ts +1 -3
  19. package/dist/lib/modules/asset/index.js +1 -3
  20. package/dist/lib/modules/asset/index.js.map +1 -1
  21. package/dist/lib/modules/asset/model/AssetSerializer.js +0 -1
  22. package/dist/lib/modules/asset/model/AssetSerializer.js.map +1 -1
  23. package/dist/lib/modules/asset/roles/RoleAssetsAdmin.js +1 -1
  24. package/dist/lib/modules/asset/roles/RoleAssetsAdmin.js.map +1 -1
  25. package/dist/lib/modules/asset/types/AssetApi.d.ts +124 -9
  26. package/dist/lib/modules/asset/types/AssetContent.d.ts +9 -16
  27. package/dist/lib/modules/asset/types/AssetHistoryContent.d.ts +4 -11
  28. package/dist/lib/modules/decoder/DecodedPayload.d.ts +2 -0
  29. package/dist/lib/modules/decoder/DecodedPayload.js +13 -2
  30. package/dist/lib/modules/decoder/DecodedPayload.js.map +1 -1
  31. package/dist/lib/modules/decoder/Decoder.d.ts +1 -1
  32. package/dist/lib/modules/decoder/Decoder.js.map +1 -1
  33. package/dist/lib/modules/decoder/DecoderModule.js.map +1 -1
  34. package/dist/lib/modules/decoder/DecodersController.d.ts +4 -1
  35. package/dist/lib/modules/decoder/DecodersController.js +3 -0
  36. package/dist/lib/modules/decoder/DecodersController.js.map +1 -1
  37. package/dist/lib/modules/decoder/DecodersRegister.js +4 -1
  38. package/dist/lib/modules/decoder/DecodersRegister.js.map +1 -1
  39. package/dist/lib/modules/decoder/PayloadService.d.ts +1 -0
  40. package/dist/lib/modules/decoder/PayloadService.js +136 -26
  41. package/dist/lib/modules/decoder/PayloadService.js.map +1 -1
  42. package/dist/lib/modules/decoder/PayloadsController.js +1 -1
  43. package/dist/lib/modules/decoder/PayloadsController.js.map +1 -1
  44. package/dist/lib/modules/device/DeviceService.d.ts +6 -47
  45. package/dist/lib/modules/device/DeviceService.js +157 -291
  46. package/dist/lib/modules/device/DeviceService.js.map +1 -1
  47. package/dist/lib/modules/device/DevicesController.d.ts +5 -5
  48. package/dist/lib/modules/device/DevicesController.js +35 -23
  49. package/dist/lib/modules/device/DevicesController.js.map +1 -1
  50. package/dist/lib/modules/device/collections/deviceMappings.d.ts +6 -0
  51. package/dist/lib/modules/device/collections/deviceMappings.js +76 -6
  52. package/dist/lib/modules/device/collections/deviceMappings.js.map +1 -1
  53. package/dist/lib/modules/device/roles/RoleDevicesAdmin.d.ts +2 -2
  54. package/dist/lib/modules/device/roles/RoleDevicesAdmin.js +7 -4
  55. package/dist/lib/modules/device/roles/RoleDevicesAdmin.js.map +1 -1
  56. package/dist/lib/modules/device/roles/specificRoles/RoleDevicesAssetAssociation.js +4 -1
  57. package/dist/lib/modules/device/roles/specificRoles/RoleDevicesAssetAssociation.js.map +1 -1
  58. package/dist/lib/modules/device/types/DeviceApi.d.ts +69 -41
  59. package/dist/lib/modules/device/types/DeviceContent.d.ts +56 -5
  60. package/dist/lib/modules/device/types/DeviceEvents.d.ts +9 -24
  61. package/dist/lib/modules/group/GroupsController.d.ts +37 -0
  62. package/dist/lib/modules/group/GroupsController.js +472 -0
  63. package/dist/lib/modules/group/GroupsController.js.map +1 -0
  64. package/dist/lib/modules/group/GroupsModule.d.ts +10 -0
  65. package/dist/lib/modules/group/GroupsModule.js +25 -0
  66. package/dist/lib/modules/group/GroupsModule.js.map +1 -0
  67. package/dist/lib/modules/group/GroupsService.d.ts +118 -0
  68. package/dist/lib/modules/group/GroupsService.js +518 -0
  69. package/dist/lib/modules/group/GroupsService.js.map +1 -0
  70. package/dist/lib/modules/group/collections/groupsMappings.d.ts +2 -0
  71. package/dist/lib/modules/{asset/collections/assetsGroupsMapping.js → group/collections/groupsMappings.js} +4 -12
  72. package/dist/lib/modules/group/collections/groupsMappings.js.map +1 -0
  73. package/dist/lib/modules/group/exports.d.ts +5 -0
  74. package/dist/lib/modules/group/exports.js +22 -0
  75. package/dist/lib/modules/group/exports.js.map +1 -0
  76. package/dist/lib/modules/group/index.d.ts +4 -0
  77. package/dist/lib/modules/{measure/measures → group}/index.js +4 -5
  78. package/dist/lib/modules/group/index.js.map +1 -0
  79. package/dist/lib/modules/{asset/roles/RoleAssetsGroupsAdmin.d.ts → group/roles/RoleGroupsAdmin.d.ts} +3 -3
  80. package/dist/lib/modules/{asset/roles/RoleAssetsGroupsAdmin.js → group/roles/RoleGroupsAdmin.js} +7 -7
  81. package/dist/lib/modules/group/roles/RoleGroupsAdmin.js.map +1 -0
  82. package/dist/lib/modules/{asset/roles/RoleAssetsGroupsReader.d.ts → group/roles/RoleGroupsReader.d.ts} +3 -3
  83. package/dist/lib/modules/{asset/roles/RoleAssetsGroupsReader.js → group/roles/RoleGroupsReader.js} +7 -7
  84. package/dist/lib/modules/group/roles/RoleGroupsReader.js.map +1 -0
  85. package/dist/lib/modules/group/types/GroupContent.d.ts +10 -0
  86. package/dist/lib/modules/{asset/types/AssetGroupsApi.js → group/types/GroupContent.js} +1 -1
  87. package/dist/lib/modules/group/types/GroupContent.js.map +1 -0
  88. package/dist/lib/modules/group/types/GroupsApi.d.ts +141 -0
  89. package/dist/lib/modules/{asset/types/AssetGroupContent.js → group/types/GroupsApi.js} +1 -1
  90. package/dist/lib/modules/group/types/GroupsApi.js.map +1 -0
  91. package/dist/lib/modules/measure/MeasureExporter.js +14 -6
  92. package/dist/lib/modules/measure/MeasureExporter.js.map +1 -1
  93. package/dist/lib/modules/measure/MeasureService.d.ts +11 -43
  94. package/dist/lib/modules/measure/MeasureService.js +86 -375
  95. package/dist/lib/modules/measure/MeasureService.js.map +1 -1
  96. package/dist/lib/modules/measure/MeasureSourcesBuilder.d.ts +1 -2
  97. package/dist/lib/modules/measure/MeasureSourcesBuilder.js +5 -15
  98. package/dist/lib/modules/measure/MeasureSourcesBuilder.js.map +1 -1
  99. package/dist/lib/modules/measure/MeasureTargetBuilder.d.ts +1 -1
  100. package/dist/lib/modules/measure/MeasureTargetBuilder.js +2 -2
  101. package/dist/lib/modules/measure/MeasureTargetBuilder.js.map +1 -1
  102. package/dist/lib/modules/measure/collections/measuresMappings.d.ts +2 -91
  103. package/dist/lib/modules/measure/collections/measuresMappings.js +7 -11
  104. package/dist/lib/modules/measure/collections/measuresMappings.js.map +1 -1
  105. package/dist/lib/modules/measure/exports.d.ts +0 -1
  106. package/dist/lib/modules/measure/exports.js +0 -1
  107. package/dist/lib/modules/measure/exports.js.map +1 -1
  108. package/dist/lib/modules/measure/index.d.ts +0 -1
  109. package/dist/lib/modules/measure/index.js +0 -1
  110. package/dist/lib/modules/measure/index.js.map +1 -1
  111. package/dist/lib/modules/measure/types/MeasureContent.d.ts +9 -2
  112. package/dist/lib/modules/measure/types/MeasureEvents.d.ts +6 -149
  113. package/dist/lib/modules/measure/types/MeasureSources.d.ts +5 -0
  114. package/dist/lib/modules/measure/types/MeasureSources.js.map +1 -1
  115. package/dist/lib/modules/measure/types/MeasureTarget.d.ts +1 -1
  116. package/dist/lib/modules/measure/types/MeasureTarget.js +1 -1
  117. package/dist/lib/modules/measure/types/MeasureTarget.js.map +1 -1
  118. package/dist/lib/modules/model/ModelModule.js.map +1 -1
  119. package/dist/lib/modules/model/ModelSerializer.js +15 -0
  120. package/dist/lib/modules/model/ModelSerializer.js.map +1 -1
  121. package/dist/lib/modules/model/ModelService.d.ts +20 -14
  122. package/dist/lib/modules/model/ModelService.js +301 -117
  123. package/dist/lib/modules/model/ModelService.js.map +1 -1
  124. package/dist/lib/modules/model/ModelsController.d.ts +1 -1
  125. package/dist/lib/modules/model/ModelsController.js +32 -19
  126. package/dist/lib/modules/model/ModelsController.js.map +1 -1
  127. package/dist/lib/modules/model/ModelsRegister.d.ts +6 -5
  128. package/dist/lib/modules/model/ModelsRegister.js +10 -8
  129. package/dist/lib/modules/model/ModelsRegister.js.map +1 -1
  130. package/dist/lib/modules/model/collections/modelsMappings.js +20 -1
  131. package/dist/lib/modules/model/collections/modelsMappings.js.map +1 -1
  132. package/dist/lib/modules/model/types/ModelApi.d.ts +14 -9
  133. package/dist/lib/modules/model/types/ModelContent.d.ts +34 -3
  134. package/dist/lib/modules/model/types/ModelContent.js.map +1 -1
  135. package/dist/lib/modules/model/types/ModelDefinition.d.ts +6 -2
  136. package/dist/lib/modules/model/types/ModelEvents.d.ts +3 -1
  137. package/dist/lib/modules/plugin/DeviceManagerEngine.d.ts +15 -6
  138. package/dist/lib/modules/plugin/DeviceManagerEngine.js +151 -54
  139. package/dist/lib/modules/plugin/DeviceManagerEngine.js.map +1 -1
  140. package/dist/lib/modules/plugin/DeviceManagerPlugin.d.ts +10 -8
  141. package/dist/lib/modules/plugin/DeviceManagerPlugin.js +41 -44
  142. package/dist/lib/modules/plugin/DeviceManagerPlugin.js.map +1 -1
  143. package/dist/lib/modules/plugin/types/DeviceManagerConfiguration.d.ts +9 -14
  144. package/dist/lib/modules/plugin/types/InternalCollection.d.ts +1 -1
  145. package/dist/lib/modules/plugin/types/InternalCollection.js +1 -1
  146. package/dist/lib/modules/plugin/types/InternalCollection.js.map +1 -1
  147. package/dist/lib/modules/plugin/types/exports.d.ts +1 -0
  148. package/dist/lib/modules/plugin/types/exports.js +1 -0
  149. package/dist/lib/modules/plugin/types/exports.js.map +1 -1
  150. package/dist/lib/modules/shared/services/AbstractExporter.d.ts +3 -1
  151. package/dist/lib/modules/shared/services/AbstractExporter.js +7 -3
  152. package/dist/lib/modules/shared/services/AbstractExporter.js.map +1 -1
  153. package/dist/lib/modules/shared/services/BaseService.js.map +1 -1
  154. package/dist/lib/modules/shared/services/DigitalTwinExporter.d.ts +6 -1
  155. package/dist/lib/modules/shared/services/DigitalTwinExporter.js +49 -7
  156. package/dist/lib/modules/shared/services/DigitalTwinExporter.js.map +1 -1
  157. package/dist/lib/modules/shared/services/DigitalTwinService.d.ts +70 -2
  158. package/dist/lib/modules/shared/services/DigitalTwinService.js +309 -1
  159. package/dist/lib/modules/shared/services/DigitalTwinService.js.map +1 -1
  160. package/dist/lib/modules/shared/types/DigitalTwinContent.d.ts +4 -5
  161. package/dist/lib/modules/shared/types/DigitalTwinEvents.d.ts +30 -0
  162. package/package.json +15 -9
  163. package/dist/lib/modules/asset/AssetsGroupsController.d.ts +0 -24
  164. package/dist/lib/modules/asset/AssetsGroupsController.js +0 -239
  165. package/dist/lib/modules/asset/AssetsGroupsController.js.map +0 -1
  166. package/dist/lib/modules/asset/AssetsGroupsService.d.ts +0 -49
  167. package/dist/lib/modules/asset/AssetsGroupsService.js +0 -172
  168. package/dist/lib/modules/asset/AssetsGroupsService.js.map +0 -1
  169. package/dist/lib/modules/asset/collections/assetsGroupsMapping.d.ts +0 -2
  170. package/dist/lib/modules/asset/collections/assetsGroupsMapping.js.map +0 -1
  171. package/dist/lib/modules/asset/roles/RoleAssetsGroupsAdmin.js.map +0 -1
  172. package/dist/lib/modules/asset/roles/RoleAssetsGroupsReader.js.map +0 -1
  173. package/dist/lib/modules/asset/types/AssetGroupContent.d.ts +0 -11
  174. package/dist/lib/modules/asset/types/AssetGroupContent.js.map +0 -1
  175. package/dist/lib/modules/asset/types/AssetGroupsApi.d.ts +0 -59
  176. package/dist/lib/modules/asset/types/AssetGroupsApi.js.map +0 -1
  177. package/dist/lib/modules/measure/measures/BatteryMeasure.d.ts +0 -5
  178. package/dist/lib/modules/measure/measures/BatteryMeasure.js +0 -19
  179. package/dist/lib/modules/measure/measures/BatteryMeasure.js.map +0 -1
  180. package/dist/lib/modules/measure/measures/HumidityMeasure.d.ts +0 -5
  181. package/dist/lib/modules/measure/measures/HumidityMeasure.js +0 -19
  182. package/dist/lib/modules/measure/measures/HumidityMeasure.js.map +0 -1
  183. package/dist/lib/modules/measure/measures/MovementMeasure.d.ts +0 -5
  184. package/dist/lib/modules/measure/measures/MovementMeasure.js +0 -17
  185. package/dist/lib/modules/measure/measures/MovementMeasure.js.map +0 -1
  186. package/dist/lib/modules/measure/measures/PositionMeasure.d.ts +0 -10
  187. package/dist/lib/modules/measure/measures/PositionMeasure.js +0 -43
  188. package/dist/lib/modules/measure/measures/PositionMeasure.js.map +0 -1
  189. package/dist/lib/modules/measure/measures/TemperatureMeasure.d.ts +0 -5
  190. package/dist/lib/modules/measure/measures/TemperatureMeasure.js +0 -19
  191. package/dist/lib/modules/measure/measures/TemperatureMeasure.js.map +0 -1
  192. package/dist/lib/modules/measure/measures/index.d.ts +0 -5
  193. package/dist/lib/modules/measure/measures/index.js.map +0 -1
@@ -1,15 +1,12 @@
1
1
  "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
2
  Object.defineProperty(exports, "__esModule", { value: true });
6
3
  exports.DeviceService = void 0;
7
4
  const kuzzle_1 = require("kuzzle");
8
5
  const kuzzle_plugin_commons_1 = require("kuzzle-plugin-commons");
9
6
  const plugin_1 = require("../plugin");
10
7
  const shared_1 = require("../shared");
8
+ const asset_1 = require("../asset");
11
9
  const DeviceSerializer_1 = require("./model/DeviceSerializer");
12
- const lodash_1 = __importDefault(require("lodash"));
13
10
  class DeviceService extends shared_1.DigitalTwinService {
14
11
  constructor(plugin, logger) {
15
12
  super(plugin, plugin_1.InternalCollection.DEVICES);
@@ -17,14 +14,6 @@ class DeviceService extends shared_1.DigitalTwinService {
17
14
  }
18
15
  registerAskEvents() {
19
16
  super.registerAskEvents();
20
- (0, kuzzle_plugin_commons_1.onAsk)("ask:device-manager:device:link-asset", async ({ deviceId, engineId, user, assetId, measureNames }) => {
21
- const request = new kuzzle_1.KuzzleRequest({ refresh: "false" }, { user });
22
- await this.linkAsset(engineId, deviceId, assetId, measureNames, false, request);
23
- });
24
- (0, kuzzle_plugin_commons_1.onAsk)("ask:device-manager:device:unlink-asset", async ({ deviceId, user }) => {
25
- const request = new kuzzle_1.KuzzleRequest({ refresh: "false" }, { user });
26
- await this.unlinkAsset(deviceId, request);
27
- });
28
17
  (0, kuzzle_plugin_commons_1.onAsk)("ask:device-manager:device:detach-engine", async ({ deviceId, user }) => {
29
18
  const request = new kuzzle_1.KuzzleRequest({ refresh: "false" }, { user });
30
19
  await this.detachEngine(deviceId, request);
@@ -33,41 +22,32 @@ class DeviceService extends shared_1.DigitalTwinService {
33
22
  const request = new kuzzle_1.KuzzleRequest({ refresh: "false" }, { user });
34
23
  await this.attachEngine(engineId, deviceId, request);
35
24
  });
25
+ (0, kuzzle_plugin_commons_1.onAsk)("ask:device-manager:device:refresh-model", this.refreshModel.bind(this));
36
26
  }
37
27
  async _create(deviceId, model, reference, metadata, request) {
38
- var _a;
39
28
  let device = {
40
29
  _id: deviceId,
41
30
  _source: {
42
- assetId: null,
43
31
  engineId: null,
44
- lastMeasuredAt: 0,
45
- measures: {},
32
+ groups: [],
33
+ linkedMeasures: [],
34
+ measureSlots: [],
46
35
  metadata,
47
36
  model,
48
37
  reference,
49
38
  },
50
39
  };
51
40
  const deviceModel = await this.getDeviceModel(model);
52
- const engineId = request.getString("engineId");
53
- for (const metadataName of Object.keys(deviceModel.device.metadataMappings)) {
54
- (_a = device._source.metadata)[metadataName] ?? (_a[metadataName] = null);
55
- }
56
- for (const [metadataName, metadataValue] of Object.entries(deviceModel.device.defaultMetadata)) {
57
- lodash_1.default.set(device._source.metadata, metadataName, metadataValue);
58
- }
41
+ const engineId = request.getString("engineId", "");
42
+ device._source.measureSlots = deviceModel.device.measures;
59
43
  const refreshableCollections = [];
60
- const { _source } = await this.createDocument(request, device, {
61
- collection: plugin_1.InternalCollection.DEVICES,
62
- engineId: this.config.adminIndex,
63
- });
64
- device._source = _source;
44
+ await this._createDeviceProvisioning(device, request);
65
45
  refreshableCollections.push({
66
46
  collection: plugin_1.InternalCollection.DEVICES,
67
- index: this.config.adminIndex,
47
+ index: this.config.platformIndex,
68
48
  });
69
- if (engineId && engineId !== this.config.adminIndex) {
70
- device = await this._attachEngine(engineId, device._id, request);
49
+ if (engineId.trim() !== "" && engineId !== this.config.platformIndex) {
50
+ device = await this._attachEngine(engineId, device._id, request, metadata);
71
51
  refreshableCollections.push({
72
52
  collection: plugin_1.InternalCollection.DEVICES,
73
53
  index: engineId,
@@ -78,16 +58,32 @@ class DeviceService extends shared_1.DigitalTwinService {
78
58
  }
79
59
  return device;
80
60
  }
61
+ async _createDeviceProvisioning(device, request) {
62
+ const deviceProvisioning = await this.createDocument(request, {
63
+ _id: device._id,
64
+ _source: {
65
+ engineId: null,
66
+ lastMeasuredAt: null,
67
+ lastMeasures: [],
68
+ measureSlots: device._source.measureSlots,
69
+ model: device._source.model,
70
+ provisionedAt: Date.now(),
71
+ reference: device._source.reference,
72
+ },
73
+ }, {
74
+ collection: plugin_1.InternalCollection.DEVICES,
75
+ engineId: this.config.platformIndex,
76
+ });
77
+ return deviceProvisioning;
78
+ }
81
79
  /**
82
80
  * Create a new device.
83
81
  *
84
- * @todo creating a device in the "device-manager" index should be a separate
85
- * method since in this case "engineId" is not really an engine ID but still
86
- * required as an argument (in part to check the tenant rights)
87
82
  */
88
83
  async create(model, reference, metadata, request) {
89
84
  const deviceId = DeviceSerializer_1.DeviceSerializer.id(model, reference);
90
- return (0, shared_1.lock)(`device:${deviceId}`, async () => this._create(deviceId, model, reference, metadata, request));
85
+ const device = await (0, shared_1.lock)(`device:${deviceId}`, async () => this._create(deviceId, model, reference, metadata, request));
86
+ return device;
91
87
  }
92
88
  async get(engineId, deviceId, request) {
93
89
  return this.getDocument(request, deviceId, {
@@ -95,9 +91,6 @@ class DeviceService extends shared_1.DigitalTwinService {
95
91
  engineId,
96
92
  });
97
93
  }
98
- async getInternalDevices(deviceId) {
99
- return this.sdk.document.get(this.config.adminIndex, plugin_1.InternalCollection.DEVICES, deviceId);
100
- }
101
94
  /**
102
95
  * Replace a device metadata
103
96
  */
@@ -124,19 +117,19 @@ class DeviceService extends shared_1.DigitalTwinService {
124
117
  async upsert(engineId, model, reference, metadata, request) {
125
118
  const deviceId = DeviceSerializer_1.DeviceSerializer.id(model, reference);
126
119
  return (0, shared_1.lock)(`device:${deviceId}`, async () => {
127
- const adminIndexDevice = await this.get(this.config.adminIndex, deviceId, request).catch(() => null);
128
- if (!adminIndexDevice) {
120
+ const deviceProvisioning = await this.get(this.config.platformIndex, deviceId, request).catch(() => null);
121
+ if (!deviceProvisioning) {
129
122
  return this._create(deviceId, model, reference, metadata, request);
130
123
  }
131
- if (adminIndexDevice._source.engineId &&
132
- adminIndexDevice._source.engineId !== engineId) {
133
- throw new kuzzle_1.BadRequestError(`Device "${adminIndexDevice._id}" already exists on another engine. Abort`);
124
+ if (deviceProvisioning._source.engineId &&
125
+ deviceProvisioning._source.engineId !== engineId) {
126
+ throw new kuzzle_1.BadRequestError(`Device "${deviceProvisioning._id}" already exists on another engine. Abort`);
134
127
  }
135
128
  const engineDevice = await this.get(engineId, deviceId, request).catch(() => null);
136
129
  if (!engineDevice) {
137
130
  await this._attachEngine(engineId, deviceId, request);
138
131
  }
139
- const updatedPayload = await this.app.trigger("device-manager:device:update:before", { device: adminIndexDevice, metadata });
132
+ const updatedPayload = await this.app.trigger("device-manager:device:update:before", { device: deviceProvisioning, metadata });
140
133
  const updatedDevice = await this.updateDocument(request, {
141
134
  _id: deviceId,
142
135
  _source: { metadata: updatedPayload.metadata },
@@ -170,38 +163,37 @@ class DeviceService extends shared_1.DigitalTwinService {
170
163
  return (0, shared_1.lock)(`device:${deviceId}`, async () => {
171
164
  const device = await this.get(engineId, deviceId, request);
172
165
  const promises = [];
173
- if (device._source.assetId) {
174
- const asset = await this.sdk.document.get(engineId, plugin_1.InternalCollection.ASSETS, device._source.assetId);
175
- const linkedDevices = asset._source.linkedDevices.filter((link) => link._id !== device._id);
176
- promises.push(
177
- // Potential race condition if someone update the asset linkedDevices
178
- // at the same time (e.g link or unlink asset)
179
- this.updateDocument(request, {
180
- _id: device._source.assetId,
181
- _source: { linkedDevices },
182
- }, { collection: plugin_1.InternalCollection.ASSETS, engineId }).then(async (updatedAsset) => {
183
- const event = {
184
- name: "unlink",
185
- unlink: {
186
- deviceId,
187
- },
188
- };
189
- await (0, kuzzle_plugin_commons_1.ask)("ask:device-manager:asset:history:add", {
190
- engineId,
191
- histories: [
192
- {
193
- asset: updatedAsset._source,
194
- event,
195
- id: updatedAsset._id,
196
- timestamp: Date.now(),
166
+ if (device._source.linkedMeasures?.length) {
167
+ const { successes: assets } = await this.sdk.document.mGet(engineId, plugin_1.InternalCollection.ASSETS, device._source.linkedMeasures.map((link) => link.assetId));
168
+ for (const asset of assets) {
169
+ const linkedDevices = asset._source.linkedMeasures.filter((link) => link.deviceId !== device._id);
170
+ promises.push((0, shared_1.lock)(`asset:${engineId}:${asset._id}`, async () => this.updateDocument(request, {
171
+ _id: asset._id,
172
+ _source: { linkedMeasures: linkedDevices },
173
+ }, { collection: plugin_1.InternalCollection.ASSETS, engineId }).then(async (updatedAsset) => {
174
+ const event = {
175
+ name: "unlink",
176
+ unlink: {
177
+ deviceId,
197
178
  },
198
- ],
199
- });
200
- }));
179
+ };
180
+ await (0, kuzzle_plugin_commons_1.ask)("ask:device-manager:asset:history:add", {
181
+ engineId,
182
+ histories: [
183
+ {
184
+ asset: updatedAsset._source,
185
+ event,
186
+ id: updatedAsset._id,
187
+ timestamp: Date.now(),
188
+ },
189
+ ],
190
+ });
191
+ })));
192
+ }
201
193
  }
202
194
  promises.push(this.deleteDocument(request, deviceId, {
203
195
  collection: plugin_1.InternalCollection.DEVICES,
204
- engineId: this.config.adminIndex,
196
+ engineId: this.config.platformIndex,
205
197
  }));
206
198
  promises.push(this.deleteDocument(request, deviceId, {
207
199
  collection: plugin_1.InternalCollection.DEVICES,
@@ -216,16 +208,47 @@ class DeviceService extends shared_1.DigitalTwinService {
216
208
  engineId,
217
209
  });
218
210
  }
211
+ async unlinkAssets(deviceId, allMeasures, assetIds, measureSlots, request) {
212
+ const engineId = request.getString("engineId");
213
+ let device = await this.get(engineId, deviceId, request);
214
+ const assets = [];
215
+ // CASE ALL MEASURES TO UNLINK
216
+ if (allMeasures) {
217
+ const assetsToUnlink = device._source.linkedMeasures.map((m) => m.assetId);
218
+ if (assetsToUnlink.length === 0) {
219
+ throw new kuzzle_1.BadRequestError(`Device ${deviceId} has no measure to be unlinked`);
220
+ }
221
+ for (const asset of assetsToUnlink) {
222
+ const { asset: updatedAsset, device: updatedDevice } = await this.unlinkAssetDevice(deviceId, asset, [], true, request);
223
+ assets.push(asset_1.AssetSerializer.serialize(updatedAsset));
224
+ device = DeviceSerializer_1.DeviceSerializer.serialize(updatedDevice);
225
+ }
226
+ return { assets, device };
227
+ }
228
+ // CASE ALL MEASURES FROM SPECIFIC ASSETS TO UNLINK
229
+ for (const asset of assetIds) {
230
+ const { asset: updatedAsset, device: updatedDevice } = await this.unlinkAssetDevice(deviceId, asset, [], true, request);
231
+ assets.push(asset_1.AssetSerializer.serialize(updatedAsset));
232
+ device = DeviceSerializer_1.DeviceSerializer.serialize(updatedDevice);
233
+ }
234
+ // CASE SPECIFIC DEVICE SLOTS
235
+ // FOR EVERY LINK THAT HAS A SLOT TO UNLINK
236
+ for (const linkedMeasures of device._source.linkedMeasures.filter((l) => l.measureSlots.some((s) => measureSlots.includes(s.device)))) {
237
+ const { asset: updatedAsset, device: updatedDevice } = await this.unlinkAssetDevice(deviceId, linkedMeasures.assetId, linkedMeasures.measureSlots.filter((slot) => measureSlots.includes(slot.device)), false, request);
238
+ assets.push(asset_1.AssetSerializer.serialize(updatedAsset));
239
+ device = DeviceSerializer_1.DeviceSerializer.serialize(updatedDevice);
240
+ }
241
+ return { assets, device };
242
+ }
219
243
  /**
220
244
  * Internal logic to attach the device to an engine
221
245
  *
222
246
  * @param engineId Engine id to attach to
223
247
  * @param deviceId Device id to attach
224
248
  * @param options.refresh Wait for ES indexation
225
- * @param options.strict If true, throw if an operation isn't possible
226
249
  */
227
- async _attachEngine(engineId, deviceId, request) {
228
- const device = await this.getInternalDevices(deviceId);
250
+ async _attachEngine(engineId, deviceId, request, metadata) {
251
+ const device = await this.getDeviceProvisioning(deviceId);
229
252
  if (device._source.engineId) {
230
253
  throw new kuzzle_1.BadRequestError(`Device "${device._id}" is already attached to an engine.`);
231
254
  }
@@ -233,18 +256,36 @@ class DeviceService extends shared_1.DigitalTwinService {
233
256
  device._source.engineId = engineId;
234
257
  await this.updateDocument(request, device, {
235
258
  collection: plugin_1.InternalCollection.DEVICES,
236
- engineId: this.config.adminIndex,
259
+ engineId: this.config.platformIndex,
237
260
  });
238
261
  // Make sure the device is cleaned when attached to tenant
239
- device._source.lastMeasuredAt = null;
240
- device._source.measures = {};
241
- const updatedDevice = await this.createDocument(request, device, {
262
+ const engineDevice = {
263
+ _id: device._id,
264
+ _source: {
265
+ engineId,
266
+ groups: [],
267
+ linkedMeasures: [],
268
+ measureSlots: device._source.measureSlots,
269
+ metadata: {},
270
+ model: device._source.model,
271
+ reference: device._source.reference,
272
+ },
273
+ };
274
+ const deviceModel = await this.getDeviceModel(engineDevice._source.model);
275
+ // Initialize metadata
276
+ for (const metadataName of Object.keys(deviceModel.device.metadataMappings)) {
277
+ engineDevice._source.metadata[metadataName] =
278
+ metadata?.[metadataName] ??
279
+ deviceModel.device.defaultMetadata[metadataName] ??
280
+ null;
281
+ }
282
+ const updatedDevice = await this.createDocument(request, engineDevice, {
242
283
  collection: plugin_1.InternalCollection.DEVICES,
243
284
  engineId,
244
285
  });
245
286
  if (request.getRefresh() === "wait_for") {
246
287
  await Promise.all([
247
- this.sdk.collection.refresh(this.config.adminIndex, plugin_1.InternalCollection.DEVICES),
288
+ this.sdk.collection.refresh(this.config.platformIndex, plugin_1.InternalCollection.DEVICES),
248
289
  this.sdk.collection.refresh(device._source.engineId, plugin_1.InternalCollection.DEVICES),
249
290
  ]);
250
291
  }
@@ -269,114 +310,29 @@ class DeviceService extends shared_1.DigitalTwinService {
269
310
  */
270
311
  async detachEngine(deviceId, request) {
271
312
  return (0, shared_1.lock)(`device:${deviceId}`, async () => {
272
- const device = await this.getInternalDevices(deviceId);
273
- this.checkAttachedToEngine(device);
274
- if (device._source.assetId) {
275
- await this.unlinkAsset(deviceId, request);
313
+ const deviceProvisioning = await this.getDeviceProvisioning(deviceId);
314
+ this.checkAttachedToEngine(deviceProvisioning);
315
+ const device = await this.sdk.document.get(deviceProvisioning._source.engineId, plugin_1.InternalCollection.DEVICES, deviceId);
316
+ if (device._source.linkedMeasures?.length) {
317
+ await Promise.all(device._source.linkedMeasures.map((link) => this.unlinkAssetDevice(deviceId, link.assetId, [], true, request)));
276
318
  }
277
319
  await Promise.all([
278
320
  this.updateDocument(request, {
279
- _id: device._id,
321
+ _id: deviceProvisioning._id,
280
322
  _source: { engineId: null },
281
323
  }, {
282
324
  collection: plugin_1.InternalCollection.DEVICES,
283
- engineId: this.config.adminIndex,
325
+ engineId: this.config.platformIndex,
284
326
  }),
285
- this.sdk.document.delete(device._source.engineId, plugin_1.InternalCollection.DEVICES, device._id),
327
+ this.sdk.document.delete(deviceProvisioning._source.engineId, plugin_1.InternalCollection.DEVICES, deviceProvisioning._id),
286
328
  ]);
287
329
  if (request.getRefresh() === "wait_for") {
288
330
  await Promise.all([
289
- this.sdk.collection.refresh(this.config.adminIndex, plugin_1.InternalCollection.DEVICES),
290
- this.sdk.collection.refresh(device._source.engineId, plugin_1.InternalCollection.DEVICES),
331
+ this.sdk.collection.refresh(this.config.platformIndex, plugin_1.InternalCollection.DEVICES),
332
+ this.sdk.collection.refresh(deviceProvisioning._source.engineId, plugin_1.InternalCollection.DEVICES),
291
333
  ]);
292
334
  }
293
- return device;
294
- });
295
- }
296
- /**
297
- * Link a device to an asset.
298
- */
299
- async linkAsset(engineId, deviceId, assetId, measureNames, implicitMeasuresLinking, request) {
300
- return (0, shared_1.lock)(`device:${deviceId}`, async () => {
301
- const device = await this.getInternalDevices(deviceId);
302
- const engine = await this.getEngine(engineId);
303
- this.checkAttachedToEngine(device);
304
- if (device._source.engineId !== engineId) {
305
- throw new kuzzle_1.BadRequestError(`Device "${device._id}" is not attached to the specified engine.`);
306
- }
307
- if (device._source.assetId && device._source.assetId !== assetId) {
308
- throw new kuzzle_1.BadRequestError(`Device "${device._id}" is already linked to another asset.`);
309
- }
310
- const asset = await this.sdk.document.get(device._source.engineId, plugin_1.InternalCollection.ASSETS, assetId);
311
- // Remove existing links for this device
312
- asset._source.linkedDevices = asset._source.linkedDevices.filter((link) => {
313
- return link._id !== deviceId;
314
- });
315
- const [assetModel, deviceModel] = await Promise.all([
316
- this.getAssetModel(engine.group, asset._source.model),
317
- this.getDeviceModel(device._source.model),
318
- ]);
319
- const updatedMeasureNames = [];
320
- for (const measure of measureNames) {
321
- const foundMeasure = deviceModel.device.measures.find((deviceMeasure) => deviceMeasure.name === measure.device);
322
- if (!foundMeasure && !implicitMeasuresLinking) {
323
- throw new kuzzle_1.BadRequestError(`Measure "${measure.asset}" is not declared in the device model "${measure.device}".`);
324
- }
325
- const { type } = foundMeasure;
326
- updatedMeasureNames.push({
327
- asset: measure.asset,
328
- device: measure.device,
329
- type,
330
- });
331
- }
332
- this.checkAlreadyProvidedMeasures(asset, updatedMeasureNames);
333
- if (implicitMeasuresLinking) {
334
- this.generateMissingAssetMeasureNames(asset, assetModel, deviceModel, updatedMeasureNames);
335
- }
336
- device._source.assetId = assetId;
337
- asset._source.linkedDevices.push({
338
- _id: deviceId,
339
- measureNames: updatedMeasureNames,
340
- });
341
- const [updatedDevice, , updatedAsset] = await Promise.all([
342
- this.updateDocument(request, device, {
343
- collection: plugin_1.InternalCollection.DEVICES,
344
- engineId: this.config.adminIndex,
345
- }, { source: true }),
346
- this.updateDocument(request, device, {
347
- collection: plugin_1.InternalCollection.DEVICES,
348
- engineId: device._source.engineId,
349
- }),
350
- this.updateDocument(request, asset, {
351
- collection: plugin_1.InternalCollection.ASSETS,
352
- engineId: device._source.engineId,
353
- }, { source: true }),
354
- ]);
355
- const event = {
356
- link: {
357
- deviceId: device._id,
358
- },
359
- name: "link",
360
- };
361
- await (0, kuzzle_plugin_commons_1.ask)("ask:device-manager:asset:history:add", {
362
- engineId,
363
- histories: [
364
- {
365
- asset: updatedAsset._source,
366
- event,
367
- id: updatedAsset._id,
368
- timestamp: Date.now(),
369
- },
370
- ],
371
- });
372
- if (request.getRefresh() === "wait_for") {
373
- await Promise.all([
374
- this.sdk.collection.refresh(this.config.adminIndex, plugin_1.InternalCollection.DEVICES),
375
- this.sdk.collection.refresh(device._source.engineId, plugin_1.InternalCollection.DEVICES),
376
- this.sdk.collection.refresh(device._source.engineId, plugin_1.InternalCollection.ASSETS),
377
- ]);
378
- }
379
- return { asset: updatedAsset, device: updatedDevice };
335
+ return deviceProvisioning;
380
336
  });
381
337
  }
382
338
  async receiveMeasures(engineId, deviceId, measures, payloadUuids, request) {
@@ -394,113 +350,6 @@ class DeviceService extends shared_1.DigitalTwinService {
394
350
  payloadUuids,
395
351
  });
396
352
  }
397
- /**
398
- * Checks if the asset does not already have a linked device using one of the
399
- * requested measure names.
400
- */
401
- checkAlreadyProvidedMeasures(asset, requestedMeasureNames) {
402
- const measureAlreadyProvided = (assetMeasureName) => {
403
- return asset._source.linkedDevices.some((link) => link.measureNames.some((names) => names.asset === assetMeasureName));
404
- };
405
- for (const name of requestedMeasureNames) {
406
- if (measureAlreadyProvided(name.asset)) {
407
- throw new kuzzle_1.BadRequestError(`Measure name "${name.asset}" is already provided by another device on this asset.`);
408
- }
409
- }
410
- }
411
- /**
412
- * Goes through the device available measures and add them into the link if:
413
- * - they are not already provided by another device
414
- * - they are not already present in the link request
415
- * - they are declared in the asset model
416
- */
417
- generateMissingAssetMeasureNames(asset, assetModel, deviceModel, requestedMeasureNames) {
418
- const measureAlreadyProvided = (deviceMeasureName) => {
419
- return asset._source.linkedDevices.some((link) => link.measureNames.some((names) => names.device === deviceMeasureName));
420
- };
421
- const measureAlreadyRequested = (deviceMeasureName) => {
422
- return requestedMeasureNames.some((names) => names.device === deviceMeasureName);
423
- };
424
- const measureUndeclared = (deviceMeasureName) => {
425
- return !assetModel.asset.measures.some((measure) => measure.name === deviceMeasureName);
426
- };
427
- for (const deviceMeasure of deviceModel.device.measures) {
428
- if (measureAlreadyRequested(deviceMeasure.name) ||
429
- measureAlreadyProvided(deviceMeasure.name) ||
430
- measureUndeclared(deviceMeasure.name)) {
431
- continue;
432
- }
433
- requestedMeasureNames.push({
434
- asset: deviceMeasure.name,
435
- device: deviceMeasure.name,
436
- type: deviceMeasure.type,
437
- });
438
- }
439
- }
440
- /**
441
- * Internal logic of unlink a device of an asset
442
- *
443
- * @param {string} deviceId Id of the device
444
- * @param {KuzzleRequest} request kuzzle request
445
- */
446
- async _unlinkAsset(deviceId, request) {
447
- const device = await this.getInternalDevices(deviceId);
448
- const engineId = device._source.engineId;
449
- this.checkAttachedToEngine(device);
450
- if (!device._source.assetId) {
451
- throw new kuzzle_1.BadRequestError(`Device "${device._id}" is not linked to an asset.`);
452
- }
453
- const asset = await this.sdk.document.get(engineId, plugin_1.InternalCollection.ASSETS, device._source.assetId);
454
- const linkedDevices = asset._source.linkedDevices.filter((link) => link._id !== device._id);
455
- const [updatedDevice, , updatedAsset] = await Promise.all([
456
- this.updateDocument(request, { _id: device._id, _source: { assetId: null } }, {
457
- collection: plugin_1.InternalCollection.DEVICES,
458
- engineId: this.config.adminIndex,
459
- }, { source: true }),
460
- this.updateDocument(request, { _id: device._id, _source: { assetId: null } }, {
461
- collection: plugin_1.InternalCollection.DEVICES,
462
- engineId,
463
- }),
464
- this.updateDocument(request, { _id: asset._id, _source: { linkedDevices } }, {
465
- collection: plugin_1.InternalCollection.ASSETS,
466
- engineId,
467
- }, { source: true }),
468
- ]);
469
- const event = {
470
- name: "unlink",
471
- unlink: {
472
- deviceId,
473
- },
474
- };
475
- await (0, kuzzle_plugin_commons_1.ask)("ask:device-manager:asset:history:add", {
476
- engineId,
477
- histories: [
478
- {
479
- asset: updatedAsset._source,
480
- event,
481
- id: updatedAsset._id,
482
- timestamp: Date.now(),
483
- },
484
- ],
485
- });
486
- if (request.getRefresh() === "wait_for") {
487
- await Promise.all([
488
- this.sdk.collection.refresh(this.config.adminIndex, plugin_1.InternalCollection.DEVICES),
489
- this.sdk.collection.refresh(engineId, plugin_1.InternalCollection.DEVICES),
490
- this.sdk.collection.refresh(engineId, plugin_1.InternalCollection.ASSETS),
491
- ]);
492
- }
493
- return { asset: updatedAsset, device: updatedDevice };
494
- }
495
- /**
496
- * Unlink a device of an asset with lock
497
- *
498
- * @param {string} deviceId Id of the device
499
- * @param {KuzzleRequest} request kuzzle request
500
- */
501
- async unlinkAsset(deviceId, request) {
502
- return (0, shared_1.lock)(`device:${deviceId}`, async () => this._unlinkAsset(deviceId, request));
503
- }
504
353
  async checkEngineExists(engineId) {
505
354
  const { result: { exists }, } = await this.sdk.query({
506
355
  action: "exists",
@@ -516,16 +365,33 @@ class DeviceService extends shared_1.DigitalTwinService {
516
365
  throw new kuzzle_1.BadRequestError(`Device "${device._id}" is not attached to an engine.`);
517
366
  }
518
367
  }
519
- getDeviceModel(model) {
520
- return (0, kuzzle_plugin_commons_1.ask)("ask:device-manager:model:device:get", {
521
- model,
368
+ async refreshModel({ deviceModel, }) {
369
+ const engines = await (0, kuzzle_plugin_commons_1.ask)("ask:device-manager:engine:list", {
370
+ group: null,
522
371
  });
523
- }
524
- getAssetModel(engineGroup, model) {
525
- return (0, kuzzle_plugin_commons_1.ask)("ask:device-manager:model:asset:get", {
526
- engineGroup,
527
- model,
372
+ const targets = engines.map((engine) => ({
373
+ collections: [plugin_1.InternalCollection.DEVICES],
374
+ index: engine.index,
375
+ }));
376
+ const devices = await this.sdk.query({
377
+ action: "search",
378
+ body: { query: { equals: { model: deviceModel.device.model } } },
379
+ controller: "document",
380
+ lang: "koncorde",
381
+ targets,
528
382
  });
383
+ const updatedDevicesPerIndex = devices.result.hits.reduce((acc, device) => {
384
+ device._source.measureSlots = deviceModel.device.measures;
385
+ acc[device.index].push(device);
386
+ return acc;
387
+ }, Object.fromEntries(engines.map((engine) => [
388
+ engine.index,
389
+ [],
390
+ ])));
391
+ await Promise.all(Object.entries(updatedDevicesPerIndex).map(([index, updatedDevices]) => this.sdk.document.mReplace(index, plugin_1.InternalCollection.DEVICES, updatedDevices.map((device) => ({
392
+ _id: device._id,
393
+ body: device._source,
394
+ })), { refresh: "wait_for" })));
529
395
  }
530
396
  }
531
397
  exports.DeviceService = DeviceService;