From 735e7e51b8b377fead79ac3b4c02c4047b364aed Mon Sep 17 00:00:00 2001 From: Quentin Date: Tue, 21 May 2024 16:41:05 +0200 Subject: [PATCH 01/12] feat(measureModel): add possibility to add locales information to measures --- .../measure/measures/TemperatureMeasure.ts | 10 ++++++ .../measure/types/MeasureDefinition.ts | 33 +++++++++++++++++++ lib/modules/model/ModelService.ts | 8 ++++- lib/modules/model/ModelsController.ts | 3 +- lib/modules/model/ModelsRegister.ts | 6 +++- .../model/collections/modelsMappings.ts | 4 +++ 6 files changed, 61 insertions(+), 3 deletions(-) diff --git a/lib/modules/measure/measures/TemperatureMeasure.ts b/lib/modules/measure/measures/TemperatureMeasure.ts index 799c5a1b..cf2c67be 100644 --- a/lib/modules/measure/measures/TemperatureMeasure.ts +++ b/lib/modules/measure/measures/TemperatureMeasure.ts @@ -8,4 +8,14 @@ export type TemperatureMeasurement = { export const temperatureMeasureDefinition: MeasureDefinition = { valuesMappings: { temperature: { type: "float" } }, + locales: { + en: { + name: "Temperature", + unit: "°C", + }, + fr: { + name: "Température", + unit: "°C", + }, + }, }; diff --git a/lib/modules/measure/types/MeasureDefinition.ts b/lib/modules/measure/types/MeasureDefinition.ts index 3dd9b196..85a6c21a 100644 --- a/lib/modules/measure/types/MeasureDefinition.ts +++ b/lib/modules/measure/types/MeasureDefinition.ts @@ -1,11 +1,43 @@ import { JSONObject } from "kuzzle-sdk"; +/* * + * Represents a measure information and localization + * + * @example + * { + * locales: { + * en:{ + * name:"Temperature", + * unit:"°C" + * },fr:{ + * name:"Température", + * unit:"°C" + * } + * }, + * } + */ +export interface MeasureLocales { + [localeString: string]: { + name: string; + unit: string; + }; +} + /** * Represents a measure definition registered by the Device Manager * * @example * { * valuesMappings: { temperature: { type: 'float' } }, + * locales: { + * en:{ + * name:"Temperature", + * unit:"°C" + * },fr:{ + * name:"Température", + * unit:"°C" + * } + * }, * } */ export interface MeasureDefinition { @@ -13,4 +45,5 @@ export interface MeasureDefinition { * Mappings for the measurement values in order to index the fields */ valuesMappings: JSONObject; + locales?: MeasureLocales; } diff --git a/lib/modules/model/ModelService.ts b/lib/modules/model/ModelService.ts index 12aee759..ef3a2cff 100644 --- a/lib/modules/model/ModelService.ts +++ b/lib/modules/model/ModelService.ts @@ -36,6 +36,7 @@ import { AskModelMeasureGet, } from "./types/ModelEvents"; import { MappingsConflictsError } from "./MappingsConflictsError"; +import { MeasureLocales } from "../measure"; export class ModelService extends BaseService { constructor(plugin: DeviceManagerPlugin) { @@ -316,9 +317,14 @@ export class ModelService extends BaseService { async writeMeasure( type: string, valuesMappings: JSONObject, + locales?: MeasureLocales, ): Promise> { const modelContent: MeasureModelContent = { - measure: { type, valuesMappings }, + measure: { + locales, + type, + valuesMappings, + }, type: "measure", }; diff --git a/lib/modules/model/ModelsController.ts b/lib/modules/model/ModelsController.ts index 5b495a43..56394c6d 100644 --- a/lib/modules/model/ModelsController.ts +++ b/lib/modules/model/ModelsController.ts @@ -154,10 +154,11 @@ export class ModelsController { ): Promise { const type = request.getBodyString("type"); const valuesMappings = request.getBodyObject("valuesMappings"); - + const locales = request.getBodyObject("locales", {}); const measureModel = await this.modelService.writeMeasure( type, valuesMappings, + locales, ); return measureModel; diff --git a/lib/modules/model/ModelsRegister.ts b/lib/modules/model/ModelsRegister.ts index d6f12e28..c468c2aa 100644 --- a/lib/modules/model/ModelsRegister.ts +++ b/lib/modules/model/ModelsRegister.ts @@ -132,7 +132,11 @@ export class ModelsRegister { registerMeasure(type: string, measureDefinition: MeasureDefinition) { this.measureModels.push({ - measure: { type, valuesMappings: measureDefinition.valuesMappings }, + measure: { + locales: measureDefinition.locales, + type, + valuesMappings: measureDefinition.valuesMappings, + }, type: "measure", }); } diff --git a/lib/modules/model/collections/modelsMappings.ts b/lib/modules/model/collections/modelsMappings.ts index 955b628f..b9222af8 100644 --- a/lib/modules/model/collections/modelsMappings.ts +++ b/lib/modules/model/collections/modelsMappings.ts @@ -21,6 +21,10 @@ export const modelsMappings: CollectionMappings = { dynamic: "false", properties: {}, }, + locales: { + dynamic: "false", + properties: {}, + }, }, }, From dd17098937db973fdc35fbc7a00c685bb565d3a4 Mon Sep 17 00:00:00 2001 From: Quentin Date: Wed, 22 May 2024 11:22:47 +0200 Subject: [PATCH 02/12] feat(measure definition): add local names and unit to default measure definitions --- lib/modules/measure/measures/BatteryMeasure.ts | 10 ++++++++++ lib/modules/measure/measures/HumidityMeasure.ts | 10 ++++++++++ lib/modules/measure/measures/MovementMeasure.ts | 10 ++++++++++ lib/modules/measure/measures/PositionMeasure.ts | 8 ++++++++ lib/modules/measure/types/MeasureDefinition.ts | 2 +- 5 files changed, 39 insertions(+), 1 deletion(-) diff --git a/lib/modules/measure/measures/BatteryMeasure.ts b/lib/modules/measure/measures/BatteryMeasure.ts index f81d020b..dfcd7be0 100644 --- a/lib/modules/measure/measures/BatteryMeasure.ts +++ b/lib/modules/measure/measures/BatteryMeasure.ts @@ -8,4 +8,14 @@ export type BatteryMeasurement = { export const batteryMeasureDefinition: MeasureDefinition = { valuesMappings: { battery: { type: "integer" } }, + locales: { + en: { + name: "Battery level", + unit: "%", + }, + fr: { + name: "Niveau de batterie", + unit: "%", + }, + }, }; diff --git a/lib/modules/measure/measures/HumidityMeasure.ts b/lib/modules/measure/measures/HumidityMeasure.ts index db74d5c4..0c8d5977 100644 --- a/lib/modules/measure/measures/HumidityMeasure.ts +++ b/lib/modules/measure/measures/HumidityMeasure.ts @@ -8,4 +8,14 @@ export type HumidityMeasurement = { export const humidityMeasureDefinition: MeasureDefinition = { valuesMappings: { humidity: { type: "float" } }, + locales: { + en: { + name: "Relative humidity", + unit: "%", + }, + fr: { + name: "Humidité relative", + unit: "%", + }, + }, }; diff --git a/lib/modules/measure/measures/MovementMeasure.ts b/lib/modules/measure/measures/MovementMeasure.ts index cbe72690..c209dbc1 100644 --- a/lib/modules/measure/measures/MovementMeasure.ts +++ b/lib/modules/measure/measures/MovementMeasure.ts @@ -8,4 +8,14 @@ export type MovementMeasurement = { export const movementMeasureDefinition: MeasureDefinition = { valuesMappings: { movement: { type: "boolean" } }, + locales: { + en: { + name: "Movement detection", + unit: "true/false", + }, + fr: { + name: "Détection de mouvement", + unit: "vrai/faux", + }, + }, }; diff --git a/lib/modules/measure/measures/PositionMeasure.ts b/lib/modules/measure/measures/PositionMeasure.ts index 1046b182..ff79558e 100644 --- a/lib/modules/measure/measures/PositionMeasure.ts +++ b/lib/modules/measure/measures/PositionMeasure.ts @@ -17,4 +17,12 @@ export const positionMeasureDefinition: MeasureDefinition = { accuracy: { type: "float" }, altitude: { type: "float" }, }, + locales: { + en: { + name: "Localization", + }, + fr: { + name: "Localisation", + }, + }, }; diff --git a/lib/modules/measure/types/MeasureDefinition.ts b/lib/modules/measure/types/MeasureDefinition.ts index 85a6c21a..0f6fa0ea 100644 --- a/lib/modules/measure/types/MeasureDefinition.ts +++ b/lib/modules/measure/types/MeasureDefinition.ts @@ -19,7 +19,7 @@ import { JSONObject } from "kuzzle-sdk"; export interface MeasureLocales { [localeString: string]: { name: string; - unit: string; + unit?: string; }; } From 98ac743745f4679086e1b90f80a0bc4af3a7e092 Mon Sep 17 00:00:00 2001 From: Quentin Date: Thu, 23 May 2024 10:59:35 +0200 Subject: [PATCH 03/12] feat(measureDefinition): Changed locales field to valueDetails and added info to default measure models --- .../measure/measures/BatteryMeasure.ts | 19 ++++++++------- .../measure/measures/HumidityMeasure.ts | 18 +++++++------- .../measure/measures/MovementMeasure.ts | 16 ++++++------- .../measure/measures/PositionMeasure.ts | 24 +++++++++++++++---- .../measure/measures/TemperatureMeasure.ts | 18 +++++++------- .../measure/types/MeasureDefinition.ts | 16 +++++++++---- lib/modules/model/ModelService.ts | 6 ++--- lib/modules/model/ModelsController.ts | 4 ++-- lib/modules/model/ModelsRegister.ts | 2 +- .../model/collections/modelsMappings.ts | 2 +- 10 files changed, 76 insertions(+), 49 deletions(-) diff --git a/lib/modules/measure/measures/BatteryMeasure.ts b/lib/modules/measure/measures/BatteryMeasure.ts index dfcd7be0..572eb541 100644 --- a/lib/modules/measure/measures/BatteryMeasure.ts +++ b/lib/modules/measure/measures/BatteryMeasure.ts @@ -8,14 +8,17 @@ export type BatteryMeasurement = { export const batteryMeasureDefinition: MeasureDefinition = { valuesMappings: { battery: { type: "integer" } }, - locales: { - en: { - name: "Battery level", - unit: "%", - }, - fr: { - name: "Niveau de batterie", - unit: "%", + + valuesDetails: { + battery: { + en: { + friendlyName: "Battery level", + unit: "%", + }, + fr: { + friendlyName: "Niveau de batterie", + unit: "%", + }, }, }, }; diff --git a/lib/modules/measure/measures/HumidityMeasure.ts b/lib/modules/measure/measures/HumidityMeasure.ts index 0c8d5977..b55eb918 100644 --- a/lib/modules/measure/measures/HumidityMeasure.ts +++ b/lib/modules/measure/measures/HumidityMeasure.ts @@ -8,14 +8,16 @@ export type HumidityMeasurement = { export const humidityMeasureDefinition: MeasureDefinition = { valuesMappings: { humidity: { type: "float" } }, - locales: { - en: { - name: "Relative humidity", - unit: "%", - }, - fr: { - name: "Humidité relative", - unit: "%", + valuesDetails: { + humidity: { + en: { + friendlyName: "Relative humidity", + unit: "%", + }, + fr: { + friendlyName: "Humidité relative", + unit: "%", + }, }, }, }; diff --git a/lib/modules/measure/measures/MovementMeasure.ts b/lib/modules/measure/measures/MovementMeasure.ts index c209dbc1..62f0da94 100644 --- a/lib/modules/measure/measures/MovementMeasure.ts +++ b/lib/modules/measure/measures/MovementMeasure.ts @@ -8,14 +8,14 @@ export type MovementMeasurement = { export const movementMeasureDefinition: MeasureDefinition = { valuesMappings: { movement: { type: "boolean" } }, - locales: { - en: { - name: "Movement detection", - unit: "true/false", - }, - fr: { - name: "Détection de mouvement", - unit: "vrai/faux", + valuesDetails: { + movement: { + en: { + friendlyName: "Movement detection", + }, + fr: { + friendlyName: "Détection de mouvement", + }, }, }, }; diff --git a/lib/modules/measure/measures/PositionMeasure.ts b/lib/modules/measure/measures/PositionMeasure.ts index ff79558e..3dbbf72e 100644 --- a/lib/modules/measure/measures/PositionMeasure.ts +++ b/lib/modules/measure/measures/PositionMeasure.ts @@ -17,12 +17,26 @@ export const positionMeasureDefinition: MeasureDefinition = { accuracy: { type: "float" }, altitude: { type: "float" }, }, - locales: { - en: { - name: "Localization", + valuesDetails: { + position: { + en: { + friendlyName: "Localization", + unit: "(lat,lon)", + }, + fr: { + friendlyName: "Localisation", + unit: "(lat,lon)", + }, }, - fr: { - name: "Localisation", + altitude: { + en: { + friendlyName: "Altitude", + unit: "m", + }, + fr: { + friendlyName: "Altitude", + unit: "m", + }, }, }, }; diff --git a/lib/modules/measure/measures/TemperatureMeasure.ts b/lib/modules/measure/measures/TemperatureMeasure.ts index cf2c67be..de92f05d 100644 --- a/lib/modules/measure/measures/TemperatureMeasure.ts +++ b/lib/modules/measure/measures/TemperatureMeasure.ts @@ -8,14 +8,16 @@ export type TemperatureMeasurement = { export const temperatureMeasureDefinition: MeasureDefinition = { valuesMappings: { temperature: { type: "float" } }, - locales: { - en: { - name: "Temperature", - unit: "°C", - }, - fr: { - name: "Température", - unit: "°C", + valuesDetails: { + temperature: { + en: { + friendlyName: "Temperature", + unit: "°C", + }, + fr: { + friendlyName: "Température", + unit: "°C", + }, }, }, }; diff --git a/lib/modules/measure/types/MeasureDefinition.ts b/lib/modules/measure/types/MeasureDefinition.ts index 0f6fa0ea..e3ea7e11 100644 --- a/lib/modules/measure/types/MeasureDefinition.ts +++ b/lib/modules/measure/types/MeasureDefinition.ts @@ -16,20 +16,23 @@ import { JSONObject } from "kuzzle-sdk"; * }, * } */ -export interface MeasureLocales { +interface MeasureLocales { [localeString: string]: { - name: string; + friendlyName: string; unit?: string; }; } - +export interface MeasureValuesDetails { + [valueName: string]: MeasureLocales; +} /** * Represents a measure definition registered by the Device Manager * * @example * { * valuesMappings: { temperature: { type: 'float' } }, - * locales: { + * valuesDetails: { + * temperature:{ * en:{ * name:"Temperature", * unit:"°C" @@ -37,6 +40,7 @@ export interface MeasureLocales { * name:"Température", * unit:"°C" * } + * } * }, * } */ @@ -45,5 +49,7 @@ export interface MeasureDefinition { * Mappings for the measurement values in order to index the fields */ valuesMappings: JSONObject; - locales?: MeasureLocales; + valuesDetails?: { + [valueName: string]: MeasureLocales; + }; } diff --git a/lib/modules/model/ModelService.ts b/lib/modules/model/ModelService.ts index ef3a2cff..130d56d8 100644 --- a/lib/modules/model/ModelService.ts +++ b/lib/modules/model/ModelService.ts @@ -36,7 +36,7 @@ import { AskModelMeasureGet, } from "./types/ModelEvents"; import { MappingsConflictsError } from "./MappingsConflictsError"; -import { MeasureLocales } from "../measure"; +import { MeasureValuesDetails } from "../measure"; export class ModelService extends BaseService { constructor(plugin: DeviceManagerPlugin) { @@ -317,12 +317,12 @@ export class ModelService extends BaseService { async writeMeasure( type: string, valuesMappings: JSONObject, - locales?: MeasureLocales, + valuesDetails?: MeasureValuesDetails, ): Promise> { const modelContent: MeasureModelContent = { measure: { - locales, type, + valuesDetails, valuesMappings, }, type: "measure", diff --git a/lib/modules/model/ModelsController.ts b/lib/modules/model/ModelsController.ts index 56394c6d..71553d0b 100644 --- a/lib/modules/model/ModelsController.ts +++ b/lib/modules/model/ModelsController.ts @@ -154,11 +154,11 @@ export class ModelsController { ): Promise { const type = request.getBodyString("type"); const valuesMappings = request.getBodyObject("valuesMappings"); - const locales = request.getBodyObject("locales", {}); + const valuesDetails = request.getBodyObject("valuesDetails", {}); const measureModel = await this.modelService.writeMeasure( type, valuesMappings, - locales, + valuesDetails, ); return measureModel; diff --git a/lib/modules/model/ModelsRegister.ts b/lib/modules/model/ModelsRegister.ts index c468c2aa..8ad00939 100644 --- a/lib/modules/model/ModelsRegister.ts +++ b/lib/modules/model/ModelsRegister.ts @@ -133,8 +133,8 @@ export class ModelsRegister { registerMeasure(type: string, measureDefinition: MeasureDefinition) { this.measureModels.push({ measure: { - locales: measureDefinition.locales, type, + valuesDetails: measureDefinition.valuesDetails, valuesMappings: measureDefinition.valuesMappings, }, type: "measure", diff --git a/lib/modules/model/collections/modelsMappings.ts b/lib/modules/model/collections/modelsMappings.ts index b9222af8..61056c08 100644 --- a/lib/modules/model/collections/modelsMappings.ts +++ b/lib/modules/model/collections/modelsMappings.ts @@ -21,7 +21,7 @@ export const modelsMappings: CollectionMappings = { dynamic: "false", properties: {}, }, - locales: { + valuesDetails: { dynamic: "false", properties: {}, }, From 7248f07d58df64c9f9ecb324b8bd45f93095b7a8 Mon Sep 17 00:00:00 2001 From: Quentin Date: Thu, 23 May 2024 16:12:19 +0200 Subject: [PATCH 04/12] feat(tests): add test for measure valuesDetails and fix tests --- lib/modules/model/types/ModelApi.ts | 2 + tests/fixtures/rights.ts | 31 +++++++++++ tests/hooks/engines.ts | 10 ++++ tests/hooks/security.ts | 6 +++ .../migrated/asset-controller.test.ts | 4 +- .../device-controller-attach-engine.test.ts | 4 +- .../device-controller-detach-engine.test.ts | 2 +- .../migrated/model-controller.test.ts | 53 ++++++++++-------- .../assets/asset-migrate-tenant.test.ts | 37 +++++++------ .../devices/action-attach-engine.test.ts | 4 +- .../devices/action-export-measures.test.ts | 5 -- .../modules/devices/action-link-asset.test.ts | 8 +-- .../modules/devices/action-scrud.test.ts | 4 +- .../modules/models/model-controller.test.ts | 54 +++++++++++++++++++ .../dynamicaly-register-device-model.test.ts | 4 +- 15 files changed, 168 insertions(+), 60 deletions(-) diff --git a/lib/modules/model/types/ModelApi.ts b/lib/modules/model/types/ModelApi.ts index b16fc713..e3af7d92 100644 --- a/lib/modules/model/types/ModelApi.ts +++ b/lib/modules/model/types/ModelApi.ts @@ -8,6 +8,7 @@ import { MetadataGroups, MetadataMappings, } from "./ModelContent"; +import { MeasureValuesDetails } from "../../measure/types/MeasureDefinition"; interface ModelsControllerRequest { controller: "device-manager/models"; @@ -67,6 +68,7 @@ export interface ApiModelWriteMeasureRequest extends ModelsControllerRequest { body: { type: string; valuesMappings: JSONObject; + valuesDetails?: MeasureValuesDetails; }; } export type ApiModelWriteMeasureResult = KDocument; diff --git a/tests/fixtures/rights.ts b/tests/fixtures/rights.ts index 0aa0588c..c8883246 100644 --- a/tests/fixtures/rights.ts +++ b/tests/fixtures/rights.ts @@ -22,6 +22,14 @@ export default { }, }, }, + "default-user": { + content: { + profileIds: ["default-user"], + }, + credentials: { + local: { username: "default-user", password: "password" }, + }, + }, }, profiles: { "ayse-admin": { @@ -70,7 +78,21 @@ export default { }, ], }, + "default-user": { + rateLimit: 0, + policies: [ + { + roleId: "default-user", + }, + ], + optimizedPolicies: [ + { + roleId: "default-user", + }, + ], + }, }, + roles: { tests: { controllers: { @@ -92,5 +114,14 @@ export default { }, }, }, + "default-user": { + controllers: { + "device-manager/assets": { + actions: { + "*": true, + }, + }, + }, + }, }, }; diff --git a/tests/hooks/engines.ts b/tests/hooks/engines.ts index f1fe3bea..ce878e9c 100644 --- a/tests/hooks/engines.ts +++ b/tests/hooks/engines.ts @@ -1,4 +1,5 @@ import { BaseRequest, JSONObject, Kuzzle } from "kuzzle-sdk"; +import { loadSecurityDefault } from "./security"; async function createEngineIfNotExists( sdk: Kuzzle, @@ -24,9 +25,18 @@ async function createEngineIfNotExists( } export async function beforeAllCreateEngines(sdk: Kuzzle) { + await loadSecurityDefault(sdk); + if ((await sdk.auth.getCurrentUser())._id !== "test-admin") { + await sdk.auth.login("local", { + username: "test-admin", + password: "password", + }); + } await Promise.all([ createEngineIfNotExists(sdk, "engine-ayse"), createEngineIfNotExists(sdk, "engine-kuzzle"), createEngineIfNotExists(sdk, "engine-other-group", "other-group"), + // Timeout to avoid too many login per seconds error + new Promise((resolve) => setTimeout(resolve, 300)), ]); } diff --git a/tests/hooks/security.ts b/tests/hooks/security.ts index e1d25ca0..d6333a4e 100644 --- a/tests/hooks/security.ts +++ b/tests/hooks/security.ts @@ -4,6 +4,12 @@ import rights from "../fixtures/rights"; export async function loadSecurityDefault(sdk: Kuzzle) { sdk.jwt = null; + if (!(await sdk.auth.getCurrentUser())._id.includes("admin")) { + await sdk.auth.login("local", { + username: "admin", + password: "password", + }); + } await sdk.query({ controller: "admin", diff --git a/tests/scenario/migrated/asset-controller.test.ts b/tests/scenario/migrated/asset-controller.test.ts index 34efafe9..7c858f1b 100644 --- a/tests/scenario/migrated/asset-controller.test.ts +++ b/tests/scenario/migrated/asset-controller.test.ts @@ -45,7 +45,7 @@ describe("features/Asset/Controller", () => { position: null, }, linkedDevices: [], - _kuzzle_info: { author: "-1" }, + _kuzzle_info: { author: "test-admin" }, }, }); @@ -62,7 +62,7 @@ describe("features/Asset/Controller", () => { ).resolves.toMatchObject({ _source: { metadata: { height: 5, weight: 1250 }, - _kuzzle_info: { updater: "-1" }, + _kuzzle_info: { updater: "test-admin" }, }, }); diff --git a/tests/scenario/migrated/device-controller-attach-engine.test.ts b/tests/scenario/migrated/device-controller-attach-engine.test.ts index 20194e20..79bee61e 100644 --- a/tests/scenario/migrated/device-controller-attach-engine.test.ts +++ b/tests/scenario/migrated/device-controller-attach-engine.test.ts @@ -37,13 +37,13 @@ describe("features/Device/Controller/AttachEngine", () => { await expect( sdk.document.get("device-manager", "devices", "DummyTemp-detached1") ).resolves.toMatchObject({ - _source: { engineId: "engine-kuzzle", _kuzzle_info: { updater: "-1" } }, + _source: { engineId: "engine-kuzzle", _kuzzle_info: { updater: "test-admin" } }, }); await expect( sdk.document.get("engine-kuzzle", "devices", "DummyTemp-detached1") ).resolves.toMatchObject({ - _source: { engineId: "engine-kuzzle", _kuzzle_info: { author: "-1" } }, + _source: { engineId: "engine-kuzzle", _kuzzle_info: { author: "test-admin" } }, }); response = await sendPayloads(sdk, "dummy-temp", [ diff --git a/tests/scenario/migrated/device-controller-detach-engine.test.ts b/tests/scenario/migrated/device-controller-detach-engine.test.ts index 4cb10fc5..81007baa 100644 --- a/tests/scenario/migrated/device-controller-detach-engine.test.ts +++ b/tests/scenario/migrated/device-controller-detach-engine.test.ts @@ -44,7 +44,7 @@ describe("features/Device/Controller/DetachEngine", () => { await expect( sdk.document.get("device-manager", "devices", "DummyTemp-detached1") ).resolves.toMatchObject({ - _source: { engineId: null, _kuzzle_info: { updater: "-1" } }, + _source: { engineId: null, _kuzzle_info: { updater: "test-admin" } }, }); await expect( diff --git a/tests/scenario/migrated/model-controller.test.ts b/tests/scenario/migrated/model-controller.test.ts index 7810f398..b0179f9e 100644 --- a/tests/scenario/migrated/model-controller.test.ts +++ b/tests/scenario/migrated/model-controller.test.ts @@ -475,11 +475,12 @@ describe("features/Model/Controller", () => { }); expect(response.result).toMatchObject({ - total: 7, + total: 8, models: [ { _id: "model-measure-acceleration" }, { _id: "model-measure-battery" }, { _id: "model-measure-humidity" }, + { _id: "model-measure-light" }, { _id: "model-measure-movement" }, { _id: "model-measure-position" }, { _id: "model-measure-presence" }, @@ -504,55 +505,63 @@ describe("features/Model/Controller", () => { model: "AdvancedPlane", metadataMappings: { company: { type: "keyword" }, - year: { type: "integer" } + year: { type: "integer" }, }, - measures: [ - { name: "temperatureExt", type: "temperature" }, - ], + measures: [{ name: "temperatureExt", type: "temperature" }], metadataDetails: { company: { group: "companyInfo", locales: { en: { friendlyName: "Manufacturer", - description: "The company that manufactured the plane" + description: "The company that manufactured the plane", }, fr: { friendlyName: "Fabricant", - description: "L'entreprise qui a fabriqué l'avion" - } - } - } + description: "L'entreprise qui a fabriqué l'avion", + }, + }, + }, }, metadataGroups: { companyInfo: { locales: { - en: { groupFriendlyName: "Company Information", description: "All company related informations" }, - fr: { groupFriendlyName: "Informations sur l'entreprise", description: "Toutes les informations relatives a l'entreprise" } - } - } - } + en: { + groupFriendlyName: "Company Information", + description: "All company related informations", + }, + fr: { + groupFriendlyName: "Informations sur l'entreprise", + description: "Toutes les informations relatives a l'entreprise", + }, + }, + }, + }, }; // Write the asset model with metadata details and groups await sdk.query({ controller: "device-manager/models", action: "writeAsset", - body: assetModelWithDetailsAndGroups + body: assetModelWithDetailsAndGroups, }); // Retrieve and assert the asset model - const response = await sdk.document.get("device-manager", "models", "model-asset-AdvancedPlane"); - expect(response._source.asset).toHaveProperty('metadataDetails'); - expect(response._source.asset).toHaveProperty('metadataGroups'); - delete assetModelWithDetailsAndGroups.engineGroup + const response = await sdk.document.get( + "device-manager", + "models", + "model-asset-AdvancedPlane" + ); + expect(response._source.asset).toHaveProperty("metadataDetails"); + expect(response._source.asset).toHaveProperty("metadataGroups"); + delete assetModelWithDetailsAndGroups.engineGroup; expect(response._source).toMatchObject({ type: "asset", engineGroup: "commons", - asset: assetModelWithDetailsAndGroups + asset: assetModelWithDetailsAndGroups, }); }); - + it("Register models from the framework", async () => { let response; let promise; diff --git a/tests/scenario/modules/assets/asset-migrate-tenant.test.ts b/tests/scenario/modules/assets/asset-migrate-tenant.test.ts index 2916a8aa..df068711 100644 --- a/tests/scenario/modules/assets/asset-migrate-tenant.test.ts +++ b/tests/scenario/modules/assets/asset-migrate-tenant.test.ts @@ -23,28 +23,14 @@ describe("AssetsController:migrateTenant", () => { sdk.disconnect(); }); - it("should fail if the user is not an admin", async () => { - await expect( - sdk.query({ - controller: "device-manager/assets", - action: "migrateTenant", - engineId: "engine-ayse", - body: { - assetsList: ["Container-linked1", "Container-linked2"], - newEngineId: "engine-kuzzle", - }, - }), - ).rejects.toThrow("User -1 is not authorized to migrate assets"); - }); - it("should fail if both engine does not belong to same group", async () => { - // We connect only here to avoid failing the first test - // If we do it in the beforeAll hook, the first test will fail - // And if we run it each time we might encounter "Too many login attempts per second" await sdk.auth.login("local", { username: "test-admin", password: "password", }); + // We connect only here to avoid failing the first test + // If we do it in the beforeAll hook, the first test will fail + // And if we run it each time we might encounter "Too many login attempts per second" await expect( sdk.query({ @@ -158,4 +144,21 @@ describe("AssetsController:migrateTenant", () => { expect(response.status).toBe(200); expect(assets.result.hits).toHaveLength(2); }); + it("should fail if the user is not an admin", async () => { + await sdk.auth.login("local", { + username: "default-user", + password: "password", + }); + await expect( + sdk.query({ + controller: "device-manager/assets", + action: "migrateTenant", + engineId: "engine-ayse", + body: { + assetsList: ["Container-linked1", "Container-linked2"], + newEngineId: "engine-kuzzle", + }, + }), + ).rejects.toThrow("User default-user is not authorized to migrate assets"); + }); }); diff --git a/tests/scenario/modules/devices/action-attach-engine.test.ts b/tests/scenario/modules/devices/action-attach-engine.test.ts index fa4e8157..03f7b32f 100644 --- a/tests/scenario/modules/devices/action-attach-engine.test.ts +++ b/tests/scenario/modules/devices/action-attach-engine.test.ts @@ -21,7 +21,7 @@ describe("DevicesController:attachEngine", () => { _source: { engineId: "engine-kuzzle", _kuzzle_info: { - updater: "-1", + updater: "test-admin", }, }, }); @@ -32,7 +32,7 @@ describe("DevicesController:attachEngine", () => { _source: { engineId: "engine-kuzzle", _kuzzle_info: { - author: "-1", + author: "test-admin", }, }, }); diff --git a/tests/scenario/modules/devices/action-export-measures.test.ts b/tests/scenario/modules/devices/action-export-measures.test.ts index 9ce66c62..1b31de5c 100644 --- a/tests/scenario/modules/devices/action-export-measures.test.ts +++ b/tests/scenario/modules/devices/action-export-measures.test.ts @@ -176,11 +176,6 @@ describe("DevicesController:exportMeasures", () => { }); it("should generate a authenticated link", async () => { - await sdk.auth.login("local", { - username: "test-admin", - password: "password", - }); - await sendPayloads(sdk, "dummy-temp", [ { deviceEUI: "linked1", temperature: 37 }, ]); diff --git a/tests/scenario/modules/devices/action-link-asset.test.ts b/tests/scenario/modules/devices/action-link-asset.test.ts index 35f09f99..e6352141 100644 --- a/tests/scenario/modules/devices/action-link-asset.test.ts +++ b/tests/scenario/modules/devices/action-link-asset.test.ts @@ -47,7 +47,7 @@ describe("DeviceController: receiveMeasure", () => { ).resolves.toMatchObject({ assetId: "Container-unlinked1", _kuzzle_info: { - updater: "-1", + updater: "test-admin", }, }); await expect( @@ -55,7 +55,7 @@ describe("DeviceController: receiveMeasure", () => { ).resolves.toMatchObject({ assetId: "Container-unlinked1", _kuzzle_info: { - updater: "-1", + updater: "test-admin", }, }); await expect( @@ -68,7 +68,7 @@ describe("DeviceController: receiveMeasure", () => { }, ], _kuzzle_info: { - updater: "-1", + updater: "test-admin", }, }); @@ -103,7 +103,7 @@ describe("DeviceController: receiveMeasure", () => { }, ], _kuzzle_info: { - updater: "-1", + updater: "test-admin", }, }); }); diff --git a/tests/scenario/modules/devices/action-scrud.test.ts b/tests/scenario/modules/devices/action-scrud.test.ts index 596bbab7..52c72838 100644 --- a/tests/scenario/modules/devices/action-scrud.test.ts +++ b/tests/scenario/modules/devices/action-scrud.test.ts @@ -58,8 +58,8 @@ describe("Device SCRUD", () => { color: "RED", }, _kuzzle_info: { - author: "-1", - updater: "-1", + author: "test-admin", + updater: "test-admin", }, }); diff --git a/tests/scenario/modules/models/model-controller.test.ts b/tests/scenario/modules/models/model-controller.test.ts index ee288c2a..5aca6379 100644 --- a/tests/scenario/modules/models/model-controller.test.ts +++ b/tests/scenario/modules/models/model-controller.test.ts @@ -284,4 +284,58 @@ describe("features/Model/Controller", () => { ), ).rejects.toThrow(); }); + + it("can accept valuesDetails when writing a measure", async () => { + await sdk.query({ + controller: "device-manager/models", + action: "writeMeasure", + body: { + type: "light", + valuesMappings: { + light: { type: "float" }, + }, + valuesDetails: { + light: { + en: { + friendlyName: "Light intensity", + unit: "lux", + }, + fr: { + friendlyName: "Intensité lumineuse", + unit: "lux", + }, + }, + }, + }, + }); + await expect( + sdk.document.get( + "device-manager", + "models", + "model-measure-light", + ), + ).resolves.toMatchObject>>({ + _source: { + type: "measure", + measure: { + type: "light", + valuesMappings: { + light: { type: "float" }, + }, + valuesDetails: { + light: { + en: { + friendlyName: "Light intensity", + unit: "lux", + }, + fr: { + friendlyName: "Intensité lumineuse", + unit: "lux", + }, + }, + }, + }, + }, + }); + }); }); diff --git a/tests/scenario/usecase/dynamicaly-register-device-model.test.ts b/tests/scenario/usecase/dynamicaly-register-device-model.test.ts index 4ad4fb1a..e9b8122b 100644 --- a/tests/scenario/usecase/dynamicaly-register-device-model.test.ts +++ b/tests/scenario/usecase/dynamicaly-register-device-model.test.ts @@ -8,12 +8,10 @@ import { } from "../../../index"; import { setupHooks } from "../../helpers"; - +const sdk = setupHooks(); jest.setTimeout(10000); describe("DeviceScenario: dynamicaly register device model and receive a measure", () => { - const sdk = setupHooks(); - it("register a new device model, create a device from this model and receive a formated measure", async () => { await sdk.query({ controller: "device-manager/models", From d7e6a0e97a3ba518369a93220c31b30180489c80 Mon Sep 17 00:00:00 2001 From: Quentin Date: Thu, 23 May 2024 16:15:03 +0200 Subject: [PATCH 05/12] fix(tests): extend timeout between logins to avoid too many login error --- tests/hooks/engines.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/hooks/engines.ts b/tests/hooks/engines.ts index ce878e9c..a8dd1ab9 100644 --- a/tests/hooks/engines.ts +++ b/tests/hooks/engines.ts @@ -37,6 +37,6 @@ export async function beforeAllCreateEngines(sdk: Kuzzle) { createEngineIfNotExists(sdk, "engine-kuzzle"), createEngineIfNotExists(sdk, "engine-other-group", "other-group"), // Timeout to avoid too many login per seconds error - new Promise((resolve) => setTimeout(resolve, 300)), + new Promise((resolve) => setTimeout(resolve, 1000)), ]); } From 175f88896461345802307d00d2a7ec4191cb013a Mon Sep 17 00:00:00 2001 From: Quentin Date: Mon, 27 May 2024 12:02:02 +0200 Subject: [PATCH 06/12] feat(measuremodel): add documentation on measure models --- doc/2/concepts/models/index.md | 49 +++++++++++++++++++++++++++++++++- tests/hooks/security.ts | 1 + 2 files changed, 49 insertions(+), 1 deletion(-) diff --git a/doc/2/concepts/models/index.md b/doc/2/concepts/models/index.md index 13c26cb3..276ed145 100644 --- a/doc/2/concepts/models/index.md +++ b/doc/2/concepts/models/index.md @@ -2,7 +2,7 @@ code: false type: page title: Models -description: Assets and Devices Models +description: Assets, Measure and Devices Models --- # Models @@ -58,6 +58,53 @@ The API also allows to: - list available models `device-manager/models:listDevices` - get a model `device-manager/models:getDevices` + +## Measure Model + +A measure model contains the following information: + +- `model`: model name +- `measure`: type of the measure +- `valuesMappings`: measurements mappings (See [Collection Mappings](https://docs.kuzzle.io/core/2/guides/main-concepts/data-storage/#collection-mappings)) +- `valuesDetails`: (optional) Metadata and translations of measurements. You can use it to keep consistency on translations between your apps + +It is possible to create new models on the Kuzzle IoT Platform using either: + +- the API through the action `device-manager/models:writeMeasure` +- the framework with the method `deviceManager.models.registerMeasure` + +**Example: declaration of a model via API** + +```typescript +await sdk.query({ + controller: 'device-manager/models', + action: 'writeMeasure', + body: { + type: 'light', + valuesMappings: { + light: { type: 'integer' }, + }, + valuesDetails: { + light: { + en: { + friendlyName: 'Light intensity', + unit: 'lux', + }, + fr: { + friendlyName: 'Intensité lumineuse', + unit: 'lux', + }, + }, + }, + }, + }); +``` + +The API also allows to: + +- list registered measures `device-manager/models:listMeasures` +- get a measure model `device-manager/models:getMeasure` + ## Asset Model Unlike sensors and metrics which are available for all engine groups, asset models are specific to a particular engine group. diff --git a/tests/hooks/security.ts b/tests/hooks/security.ts index d6333a4e..70c86de8 100644 --- a/tests/hooks/security.ts +++ b/tests/hooks/security.ts @@ -4,6 +4,7 @@ import rights from "../fixtures/rights"; export async function loadSecurityDefault(sdk: Kuzzle) { sdk.jwt = null; + // TODO check how to load the fixtures in the CI to pass the test if (!(await sdk.auth.getCurrentUser())._id.includes("admin")) { await sdk.auth.login("local", { username: "admin", From 5fd352a5a5a296707ce373bb01def354aa264dfc Mon Sep 17 00:00:00 2001 From: Quentin Date: Mon, 27 May 2024 12:07:00 +0200 Subject: [PATCH 07/12] feat(measuremodel): add documentation on writeMeasure for valuesDetails field --- doc/2/controllers/models/write-measure/index.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/doc/2/controllers/models/write-measure/index.md b/doc/2/controllers/models/write-measure/index.md index 76d96591..781a417e 100644 --- a/doc/2/controllers/models/write-measure/index.md +++ b/doc/2/controllers/models/write-measure/index.md @@ -31,6 +31,10 @@ Method: POST "valuesMappings": { // Values mappings }, + // Optional + "valuesDetails":{ + // Values details and translation + } } } ``` @@ -41,6 +45,7 @@ Method: POST - `model`: Measure model name - `valuesMappings`: Mappings of the measure values in Elasticsearch format +- `valuesDetails`: (optional) Measurement translations and units --- From 39190fc97f2d183addea5208fb41ad6b581c8add Mon Sep 17 00:00:00 2001 From: Quentin Date: Tue, 28 May 2024 09:51:50 +0200 Subject: [PATCH 08/12] fix(test): remove admin connexion before all --- tests/hooks/security.ts | 7 ------- 1 file changed, 7 deletions(-) diff --git a/tests/hooks/security.ts b/tests/hooks/security.ts index 70c86de8..e1d25ca0 100644 --- a/tests/hooks/security.ts +++ b/tests/hooks/security.ts @@ -4,13 +4,6 @@ import rights from "../fixtures/rights"; export async function loadSecurityDefault(sdk: Kuzzle) { sdk.jwt = null; - // TODO check how to load the fixtures in the CI to pass the test - if (!(await sdk.auth.getCurrentUser())._id.includes("admin")) { - await sdk.auth.login("local", { - username: "admin", - password: "password", - }); - } await sdk.query({ controller: "admin", From f72ab660d60144ad259d666b4654d5a807724373 Mon Sep 17 00:00:00 2001 From: Quentin Date: Tue, 28 May 2024 10:04:01 +0200 Subject: [PATCH 09/12] fix(test): revert write and list a measure model test --- tests/scenario/migrated/model-controller.test.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/scenario/migrated/model-controller.test.ts b/tests/scenario/migrated/model-controller.test.ts index b0179f9e..65dc7f1f 100644 --- a/tests/scenario/migrated/model-controller.test.ts +++ b/tests/scenario/migrated/model-controller.test.ts @@ -475,12 +475,11 @@ describe("features/Model/Controller", () => { }); expect(response.result).toMatchObject({ - total: 8, + total: 7, models: [ { _id: "model-measure-acceleration" }, { _id: "model-measure-battery" }, { _id: "model-measure-humidity" }, - { _id: "model-measure-light" }, { _id: "model-measure-movement" }, { _id: "model-measure-position" }, { _id: "model-measure-presence" }, From 2234677b01adef940355e675b455d525f7c0aeb1 Mon Sep 17 00:00:00 2001 From: Quentin Date: Tue, 28 May 2024 10:17:55 +0200 Subject: [PATCH 10/12] fix(test): revert to tests as anonymous --- tests/hooks/engines.ts | 8 -------- tests/scenario/migrated/asset-controller.test.ts | 4 ++-- .../migrated/device-controller-attach-engine.test.ts | 4 ++-- .../scenario/modules/devices/action-attach-engine.test.ts | 4 ++-- tests/scenario/modules/devices/action-link-asset.test.ts | 8 ++++---- 5 files changed, 10 insertions(+), 18 deletions(-) diff --git a/tests/hooks/engines.ts b/tests/hooks/engines.ts index a8dd1ab9..99112b73 100644 --- a/tests/hooks/engines.ts +++ b/tests/hooks/engines.ts @@ -26,17 +26,9 @@ async function createEngineIfNotExists( export async function beforeAllCreateEngines(sdk: Kuzzle) { await loadSecurityDefault(sdk); - if ((await sdk.auth.getCurrentUser())._id !== "test-admin") { - await sdk.auth.login("local", { - username: "test-admin", - password: "password", - }); - } await Promise.all([ createEngineIfNotExists(sdk, "engine-ayse"), createEngineIfNotExists(sdk, "engine-kuzzle"), createEngineIfNotExists(sdk, "engine-other-group", "other-group"), - // Timeout to avoid too many login per seconds error - new Promise((resolve) => setTimeout(resolve, 1000)), ]); } diff --git a/tests/scenario/migrated/asset-controller.test.ts b/tests/scenario/migrated/asset-controller.test.ts index 7c858f1b..34efafe9 100644 --- a/tests/scenario/migrated/asset-controller.test.ts +++ b/tests/scenario/migrated/asset-controller.test.ts @@ -45,7 +45,7 @@ describe("features/Asset/Controller", () => { position: null, }, linkedDevices: [], - _kuzzle_info: { author: "test-admin" }, + _kuzzle_info: { author: "-1" }, }, }); @@ -62,7 +62,7 @@ describe("features/Asset/Controller", () => { ).resolves.toMatchObject({ _source: { metadata: { height: 5, weight: 1250 }, - _kuzzle_info: { updater: "test-admin" }, + _kuzzle_info: { updater: "-1" }, }, }); diff --git a/tests/scenario/migrated/device-controller-attach-engine.test.ts b/tests/scenario/migrated/device-controller-attach-engine.test.ts index 79bee61e..20194e20 100644 --- a/tests/scenario/migrated/device-controller-attach-engine.test.ts +++ b/tests/scenario/migrated/device-controller-attach-engine.test.ts @@ -37,13 +37,13 @@ describe("features/Device/Controller/AttachEngine", () => { await expect( sdk.document.get("device-manager", "devices", "DummyTemp-detached1") ).resolves.toMatchObject({ - _source: { engineId: "engine-kuzzle", _kuzzle_info: { updater: "test-admin" } }, + _source: { engineId: "engine-kuzzle", _kuzzle_info: { updater: "-1" } }, }); await expect( sdk.document.get("engine-kuzzle", "devices", "DummyTemp-detached1") ).resolves.toMatchObject({ - _source: { engineId: "engine-kuzzle", _kuzzle_info: { author: "test-admin" } }, + _source: { engineId: "engine-kuzzle", _kuzzle_info: { author: "-1" } }, }); response = await sendPayloads(sdk, "dummy-temp", [ diff --git a/tests/scenario/modules/devices/action-attach-engine.test.ts b/tests/scenario/modules/devices/action-attach-engine.test.ts index 03f7b32f..fa4e8157 100644 --- a/tests/scenario/modules/devices/action-attach-engine.test.ts +++ b/tests/scenario/modules/devices/action-attach-engine.test.ts @@ -21,7 +21,7 @@ describe("DevicesController:attachEngine", () => { _source: { engineId: "engine-kuzzle", _kuzzle_info: { - updater: "test-admin", + updater: "-1", }, }, }); @@ -32,7 +32,7 @@ describe("DevicesController:attachEngine", () => { _source: { engineId: "engine-kuzzle", _kuzzle_info: { - author: "test-admin", + author: "-1", }, }, }); diff --git a/tests/scenario/modules/devices/action-link-asset.test.ts b/tests/scenario/modules/devices/action-link-asset.test.ts index e6352141..35f09f99 100644 --- a/tests/scenario/modules/devices/action-link-asset.test.ts +++ b/tests/scenario/modules/devices/action-link-asset.test.ts @@ -47,7 +47,7 @@ describe("DeviceController: receiveMeasure", () => { ).resolves.toMatchObject({ assetId: "Container-unlinked1", _kuzzle_info: { - updater: "test-admin", + updater: "-1", }, }); await expect( @@ -55,7 +55,7 @@ describe("DeviceController: receiveMeasure", () => { ).resolves.toMatchObject({ assetId: "Container-unlinked1", _kuzzle_info: { - updater: "test-admin", + updater: "-1", }, }); await expect( @@ -68,7 +68,7 @@ describe("DeviceController: receiveMeasure", () => { }, ], _kuzzle_info: { - updater: "test-admin", + updater: "-1", }, }); @@ -103,7 +103,7 @@ describe("DeviceController: receiveMeasure", () => { }, ], _kuzzle_info: { - updater: "test-admin", + updater: "-1", }, }); }); From eef803b6ca56306f5335e2cea5375bd703ed1a88 Mon Sep 17 00:00:00 2001 From: Quentin Date: Tue, 28 May 2024 10:28:12 +0200 Subject: [PATCH 11/12] fix(test): changed 'author' fields to -1 to fit anonymous --- .../scenario/migrated/device-controller-detach-engine.test.ts | 2 +- tests/scenario/modules/devices/action-scrud.test.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/scenario/migrated/device-controller-detach-engine.test.ts b/tests/scenario/migrated/device-controller-detach-engine.test.ts index 81007baa..4cb10fc5 100644 --- a/tests/scenario/migrated/device-controller-detach-engine.test.ts +++ b/tests/scenario/migrated/device-controller-detach-engine.test.ts @@ -44,7 +44,7 @@ describe("features/Device/Controller/DetachEngine", () => { await expect( sdk.document.get("device-manager", "devices", "DummyTemp-detached1") ).resolves.toMatchObject({ - _source: { engineId: null, _kuzzle_info: { updater: "test-admin" } }, + _source: { engineId: null, _kuzzle_info: { updater: "-1" } }, }); await expect( diff --git a/tests/scenario/modules/devices/action-scrud.test.ts b/tests/scenario/modules/devices/action-scrud.test.ts index 52c72838..596bbab7 100644 --- a/tests/scenario/modules/devices/action-scrud.test.ts +++ b/tests/scenario/modules/devices/action-scrud.test.ts @@ -58,8 +58,8 @@ describe("Device SCRUD", () => { color: "RED", }, _kuzzle_info: { - author: "test-admin", - updater: "test-admin", + author: "-1", + updater: "-1", }, }); From 9184a6ab2faf6bc350a53576d4b3b6cd551f79dd Mon Sep 17 00:00:00 2001 From: Quentin Date: Fri, 31 May 2024 10:24:53 +0200 Subject: [PATCH 12/12] chore(measure definition): fix linter and jsdoc --- .../measure/types/MeasureDefinition.ts | 51 ++++++++++--------- 1 file changed, 27 insertions(+), 24 deletions(-) diff --git a/lib/modules/measure/types/MeasureDefinition.ts b/lib/modules/measure/types/MeasureDefinition.ts index e3ea7e11..3015227a 100644 --- a/lib/modules/measure/types/MeasureDefinition.ts +++ b/lib/modules/measure/types/MeasureDefinition.ts @@ -5,23 +5,24 @@ import { JSONObject } from "kuzzle-sdk"; * * @example * { - * locales: { - * en:{ - * name:"Temperature", - * unit:"°C" - * },fr:{ - * name:"Température", - * unit:"°C" - * } - * }, - * } + * en: { + * friendlyName: "Temperature", + * unit: "°C", + * }, + * fr: { + * friendlyName: "Température", + * unit: "°C", + * }, + *} */ + interface MeasureLocales { [localeString: string]: { friendlyName: string; unit?: string; }; } + export interface MeasureValuesDetails { [valueName: string]: MeasureLocales; } @@ -29,21 +30,23 @@ export interface MeasureValuesDetails { * Represents a measure definition registered by the Device Manager * * @example - * { - * valuesMappings: { temperature: { type: 'float' } }, - * valuesDetails: { - * temperature:{ - * en:{ - * name:"Temperature", - * unit:"°C" - * },fr:{ - * name:"Température", - * unit:"°C" - * } - * } - * }, - * } + *{ + * valuesMappings: { temperature: { type: "float" } }, + * valuesDetails: { + * temperature: { + * en: { + * friendlyName: "Temperature", + * unit: "°C", + * }, + * fr: { + * friendlyName: "Température", + * unit: "°C", + * }, + * }, + * }, + *} */ + export interface MeasureDefinition { /** * Mappings for the measurement values in order to index the fields