Skip to content

Commit

Permalink
2.0.5 - Add action to retrieve devices measures history (#257)
Browse files Browse the repository at this point in the history
Add a device-manager/devices:getMeasures action to retrieve measures history.

This action is the same as the one to retrieve assets measures.
  • Loading branch information
Aschen committed Jan 23, 2023
1 parent ae10884 commit 16fd8b6
Show file tree
Hide file tree
Showing 7 changed files with 177 additions and 5 deletions.
35 changes: 35 additions & 0 deletions features/Device/Controller/GetMeasures.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
Feature: Get measures list

Scenario: Get device measures history
Given I send the following "dummy-temp" payloads:
| deviceEUI | temperature |
| "linked1" | 42 |
| "linked1" | 41 |
| "linked1" | 40 |
And I refresh the collection "engine-ayse":"measures"
When I successfully execute the action "device-manager/devices":"getMeasures" with args:
| engineId | "engine-ayse" |
| _id | "DummyTemp-linked1" |
| size | 2 |
| body.sort | { "values.temperature": "desc" } |
Then I should receive a result matching:
| total | 3 |
| measures.length | 2 |
Then I should receive a "measures" array of objects matching:
| _source.values.temperature | _source.origin._id |
| 42 | "DummyTemp-linked1" |
| 41 | "DummyTemp-linked1" |
When I successfully execute the action "device-manager/devices":"getMeasures" with args:
| engineId | "engine-ayse" |
| _id | "DummyTemp-linked1" |
| body.query | { equals: { "values.temperature": 40 } } |
Then I should receive a "measures" array of objects matching:
| _source.values.temperature | _source.origin._id |
| 40 | "DummyTemp-linked1" |
When I successfully execute the action "device-manager/devices":"getMeasures" with args:
| engineId | "engine-ayse" |
| _id | "DummyTemp-linked1" |
| type | "position" |
Then I should receive a result matching:
| measures | [] |

1 change: 0 additions & 1 deletion lib/modules/asset/AssetsController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@ export class AssetsController {
handler: this.update.bind(this),
http: [{ path: "device-manager/:engineId/assets/:_id", verb: "put" }],
},

getMeasures: {
handler: this.getMeasures.bind(this),
http: [
Expand Down
68 changes: 67 additions & 1 deletion lib/modules/device/DeviceService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {
import { InternalCollection, DeviceManagerConfiguration } from "../../core";
import { Metadata, lock, ask, onAsk } from "../shared";
import { AskModelDeviceGet } from "../model";
import { MeasureContent } from "../measure";

import { DeviceContent } from "./types/DeviceContent";
import { DeviceSerializer } from "./model/DeviceSerializer";
Expand All @@ -27,7 +28,10 @@ import {
EventDeviceUpdateAfter,
EventDeviceUpdateBefore,
} from "./types/DeviceEvents";
import { ApiDeviceLinkAssetRequest } from "./exports";
import {
ApiDeviceLinkAssetRequest,
ApiDeviceGetMeasuresResult,
} from "./types/DeviceApi";

export class DeviceService {
private config: DeviceManagerConfiguration;
Expand Down Expand Up @@ -616,6 +620,68 @@ export class DeviceService {
});
}

async getMeasureHistory(
engineId: string,
deviceId: string,
{
size = 25,
from = 0,
endAt,
startAt,
query,
sort = { measuredAt: "desc" },
type,
}: {
sort?: JSONObject;
query?: JSONObject;
from?: number;
size?: number;
startAt?: string;
endAt?: string;
type?: string;
}
): Promise<ApiDeviceGetMeasuresResult> {
await this.get(engineId, deviceId);

const measuredAtRange = {
range: {
measuredAt: {
gte: 0,
lte: Number.MAX_SAFE_INTEGER,
},
},
};

if (startAt) {
measuredAtRange.range.measuredAt.gte = new Date(startAt).getTime();
}

if (endAt) {
measuredAtRange.range.measuredAt.lte = new Date(endAt).getTime();
}

const searchQuery: JSONObject = {
and: [{ equals: { "origin._id": deviceId } }, measuredAtRange],
};

if (type) {
searchQuery.and.push({ equals: { type } });
}

if (query) {
searchQuery.and.push(query);
}

const result = await this.sdk.document.search<MeasureContent>(
engineId,
InternalCollection.MEASURES,
{ query: searchQuery, sort },
{ from, lang: "koncorde", size: size }
);

return { measures: result.hits, total: result.total };
}

private async checkEngineExists(engineId: string) {
const {
result: { exists },
Expand Down
46 changes: 46 additions & 0 deletions lib/modules/device/DevicesController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {
ApiDeviceSearchResult,
ApiDeviceUnlinkAssetResult,
ApiDeviceUpdateResult,
ApiDeviceGetMeasuresResult,
} from "./types/DeviceApi";

export class DevicesController {
Expand Down Expand Up @@ -92,6 +93,19 @@ export class DevicesController {
},
],
},
getMeasures: {
handler: this.getMeasures.bind(this),
http: [
{
path: "device-manager/:engineId/devices/:_id/measures",
verb: "get",
},
{
path: "device-manager/:engineId/devices/:_id/measures",
verb: "post",
},
],
},
},
};
/* eslint-enable sort-keys */
Expand Down Expand Up @@ -262,4 +276,36 @@ export class DevicesController {
device: DeviceSerializer.serialize(device),
};
}

async getMeasures(
request: KuzzleRequest
): Promise<ApiDeviceGetMeasuresResult> {
const id = request.getId();
const engineId = request.getString("engineId");
const size = request.input.args.size;
const from = request.input.args.from;
const startAt = request.input.args.startAt
? request.getDate("startAt")
: null;
const endAt = request.input.args.endAt ? request.getDate("endAt") : null;
const query = request.input.body?.query;
const sort = request.input.body?.sort;
const type = request.input.args.type;

const { measures, total } = await this.deviceService.getMeasureHistory(
engineId,
id,
{
endAt,
from,
query,
size,
sort,
startAt,
type,
}
);

return { measures, total };
}
}
26 changes: 26 additions & 0 deletions lib/modules/device/types/DeviceApi.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { JSONObject, KDocument, KHit, SearchResult } from "kuzzle";

import { MeasureContent } from "../../measure";
import { AssetContent } from "../../asset";
import { Metadata } from "../../shared";

Expand Down Expand Up @@ -130,3 +131,28 @@ export type ApiDeviceLinkAssetResult = {
asset: KDocument<AssetContent>;
device: KDocument<DeviceContent>;
};

export interface ApiDeviceGetMeasuresRequest extends DevicesControllerRequest {
action: "getMeasures";

_id: string;

size?: number;

from?: number;

startAt?: string;

endAt?: string;

type?: string;

body?: {
query?: JSONObject;
sort?: JSONObject;
};
}
export type ApiDeviceGetMeasuresResult = {
measures: Array<KDocument<MeasureContent<JSONObject>>>;
total: number;
};
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "kuzzle-device-manager",
"version": "2.0.4",
"version": "2.0.5",
"description": "Manage your IoT devices and assets. Choose a provisioning strategy, receive and decode payload, handle your IoT business logic.",
"author": "The Kuzzle Team (support@kuzzle.io)",
"repository": {
Expand Down

0 comments on commit 16fd8b6

Please sign in to comment.