@golemio/fypr 1.10.0 → 1.10.1-dev.2784614109
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.
- package/db/migrations/postgresql/20260814093009-add-device-statuses.js +16 -0
- package/db/migrations/postgresql/sqls/20260814093009-add-device-statuses-down.sql +1 -0
- package/db/migrations/postgresql/sqls/20260814093009-add-device-statuses-up.sql +6 -0
- package/dist/integration-engine/data-sources/DCIPStatusOverviewDataSourceFactory.d.ts +8 -0
- package/dist/integration-engine/data-sources/DCIPStatusOverviewDataSourceFactory.js +45 -0
- package/dist/integration-engine/data-sources/DCIPStatusOverviewDataSourceFactory.js.map +1 -0
- package/dist/integration-engine/ioc/Di.js +9 -3
- package/dist/integration-engine/ioc/Di.js.map +1 -1
- package/dist/integration-engine/ioc/FYPRIEContainerTokens.d.ts +3 -0
- package/dist/integration-engine/ioc/FYPRIEContainerTokens.js +5 -0
- package/dist/integration-engine/ioc/FYPRIEContainerTokens.js.map +1 -1
- package/dist/integration-engine/repositories/DeviceStatusRepository.d.ts +17 -0
- package/dist/integration-engine/repositories/DeviceStatusRepository.js +81 -0
- package/dist/integration-engine/repositories/DeviceStatusRepository.js.map +1 -0
- package/dist/integration-engine/workers/FYPRWorker.js +1 -0
- package/dist/integration-engine/workers/FYPRWorker.js.map +1 -1
- package/dist/integration-engine/workers/tasks/FetchDCIPStatusTask.d.ts +12 -0
- package/dist/integration-engine/workers/tasks/FetchDCIPStatusTask.js +55 -0
- package/dist/integration-engine/workers/tasks/FetchDCIPStatusTask.js.map +1 -0
- package/dist/output-gateway/fypr/controllers/v1/V1FyprElementKindsController.js +1 -1
- package/dist/output-gateway/fypr/controllers/v1/V1FyprElementKindsController.js.map +1 -1
- package/dist/output-gateway/fypr/data-access/FyprElementRepository.js +10 -6
- package/dist/output-gateway/fypr/data-access/FyprElementRepository.js.map +1 -1
- package/dist/output-gateway/fypr/routers/middlewares/cacheMiddleware.d.ts +12 -0
- package/dist/output-gateway/fypr/routers/middlewares/cacheMiddleware.js +14 -0
- package/dist/output-gateway/fypr/routers/middlewares/cacheMiddleware.js.map +1 -0
- package/dist/output-gateway/fypr/routers/v1/V1FyprElementKindsRouter.js +14 -6
- package/dist/output-gateway/fypr/routers/v1/V1FyprElementKindsRouter.js.map +1 -1
- package/dist/output-gateway/fypr/routers/v1/V1FyprMetadataRouter.js +2 -3
- package/dist/output-gateway/fypr/routers/v1/V1FyprMetadataRouter.js.map +1 -1
- package/dist/output-gateway/fypr/transformations/InformationPanelOutputTransformation.js +12 -2
- package/dist/output-gateway/fypr/transformations/InformationPanelOutputTransformation.js.map +1 -1
- package/dist/output-gateway/interfaces/IOGInformationPanelScopes.d.ts +3 -0
- package/dist/schema-definitions/const.d.ts +1 -0
- package/dist/schema-definitions/const.js +10 -1
- package/dist/schema-definitions/const.js.map +1 -1
- package/dist/schema-definitions/data-sources/DCIPStatusOverviewJSONSchema.d.ts +3 -0
- package/dist/schema-definitions/data-sources/DCIPStatusOverviewJSONSchema.js +25 -0
- package/dist/schema-definitions/data-sources/DCIPStatusOverviewJSONSchema.js.map +1 -0
- package/dist/schema-definitions/data-sources/interfaces/IDCIPStatusOverview.d.ts +7 -0
- package/dist/schema-definitions/data-sources/interfaces/IDCIPStatusOverview.js +3 -0
- package/dist/schema-definitions/data-sources/interfaces/IDCIPStatusOverview.js.map +1 -0
- package/dist/schema-definitions/index.d.ts +6 -0
- package/dist/schema-definitions/index.js +17 -2
- package/dist/schema-definitions/index.js.map +1 -1
- package/dist/schema-definitions/models/DeviceStatusModel.d.ts +11 -0
- package/dist/schema-definitions/models/DeviceStatusModel.js +22 -0
- package/dist/schema-definitions/models/DeviceStatusModel.js.map +1 -0
- package/dist/schema-definitions/models/interfaces/IDeviceStatus.d.ts +6 -0
- package/dist/schema-definitions/models/interfaces/IDeviceStatus.js +3 -0
- package/dist/schema-definitions/models/interfaces/IDeviceStatus.js.map +1 -0
- package/docs/asyncapi.yaml +17 -0
- package/docs/implementation_documentation.md +57 -2
- package/docs/openapi-output.yaml +70 -8
- package/package.json +1 -1
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.v1FyprMetadataRouter = exports.V1FyprMetadataRouter = void 0;
|
|
4
4
|
const Di_1 = require("../../../ioc/Di");
|
|
5
5
|
const FYPROGContainerTokens_1 = require("../../../ioc/FYPROGContainerTokens");
|
|
6
|
+
const cacheMiddleware_1 = require("../middlewares/cacheMiddleware");
|
|
6
7
|
const CoreToken_1 = require("@golemio/core/dist/helpers/ioc/CoreToken");
|
|
7
8
|
const AbstractRouter_1 = require("@golemio/core/dist/helpers/routing/AbstractRouter");
|
|
8
9
|
const ioc_1 = require("@golemio/core/dist/output-gateway/ioc");
|
|
@@ -17,9 +18,7 @@ class V1FyprMetadataRouter extends AbstractRouter_1.AbstractRouter {
|
|
|
17
18
|
}
|
|
18
19
|
initRoutes() {
|
|
19
20
|
const config = ioc_1.OutputGatewayContainer.resolve(CoreToken_1.CoreToken.SimpleConfig);
|
|
20
|
-
const
|
|
21
|
-
const staleWhileRevalidate = config.getValue("module.fypr.output-gateway.elements.cache.staleWhileRevalidate", 60);
|
|
22
|
-
const cacheMiddleware = this.cacheHeaderMiddleware.getMiddleware(maxAge, staleWhileRevalidate);
|
|
21
|
+
const cacheMiddleware = (0, cacheMiddleware_1.resolveCacheMiddleware)(this.cacheHeaderMiddleware, config, "module.fypr.output-gateway.elements.cache", { maxAge: 5 * 60, staleWhileRevalidate: 60 });
|
|
23
22
|
this.router.get("/", cacheMiddleware, this.controller.getMetadata(`/${this.version}/fypr/elements`));
|
|
24
23
|
}
|
|
25
24
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"V1FyprMetadataRouter.js","sourceRoot":"","sources":["../../../../../src/output-gateway/fypr/routers/v1/V1FyprMetadataRouter.ts"],"names":[],"mappings":";;;AACA,wCAA6C;AAC7C,8EAAsE;
|
|
1
|
+
{"version":3,"file":"V1FyprMetadataRouter.js","sourceRoot":"","sources":["../../../../../src/output-gateway/fypr/routers/v1/V1FyprMetadataRouter.ts"],"names":[],"mappings":";;;AACA,wCAA6C;AAC7C,8EAAsE;AACtE,oEAAsF;AAEtF,wEAAqE;AACrE,sFAAmF;AAEnF,+DAA+F;AAC/F,+DAA2D;AAE3D,MAAa,oBAAqB,SAAQ,+BAAc;IAKpD;QACI,KAAK,CAAC,IAAI,EAAE,eAAe,CAAC,CAAC;QAL1B,WAAM,GAAW,IAAA,gBAAM,GAAE,CAAC;QAM7B,IAAI,CAAC,qBAAqB,GAAG,4BAAsB,CAAC,OAAO,CAAwB,oBAAc,CAAC,qBAAqB,CAAC,CAAC;QACzH,IAAI,CAAC,UAAU,GAAG,oBAAe,CAAC,OAAO,CAA2B,6CAAqB,CAAC,wBAAwB,CAAC,CAAC;QACpH,IAAI,CAAC,UAAU,EAAE,CAAC;IACtB,CAAC;IAES,UAAU;QAChB,MAAM,MAAM,GAAG,4BAAsB,CAAC,OAAO,CAAgB,qBAAS,CAAC,YAAY,CAAC,CAAC;QACrF,MAAM,eAAe,GAAG,IAAA,wCAAsB,EAC1C,IAAI,CAAC,qBAAqB,EAC1B,MAAM,EACN,2CAA2C,EAC3C,EAAE,MAAM,EAAE,CAAC,GAAG,EAAE,EAAE,oBAAoB,EAAE,EAAE,EAAE,CAC/C,CAAC;QACF,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,eAAe,EAAE,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC,IAAI,IAAI,CAAC,OAAO,gBAAgB,CAAC,CAAC,CAAC;IACzG,CAAC;CACJ;AAtBD,oDAsBC;AAEY,QAAA,oBAAoB,GAAmB,IAAI,oBAAoB,EAAE,CAAC"}
|
|
@@ -7,6 +7,7 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
7
7
|
};
|
|
8
8
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
9
|
exports.InformationPanelOutputTransformation = void 0;
|
|
10
|
+
const _sch_1 = require("../../../schema-definitions");
|
|
10
11
|
const AbstractTransformation_1 = require("@golemio/core/dist/helpers/transformation/AbstractTransformation");
|
|
11
12
|
const tsyringe_1 = require("@golemio/core/dist/shared/tsyringe");
|
|
12
13
|
let InformationPanelOutputTransformation = class InformationPanelOutputTransformation extends AbstractTransformation_1.AbstractTransformation {
|
|
@@ -16,13 +17,13 @@ let InformationPanelOutputTransformation = class InformationPanelOutputTransform
|
|
|
16
17
|
this.transformArray = (data, embeds) => data.map((item) => this.transformInternal(item.toJSON ? item.toJSON() : item, embeds));
|
|
17
18
|
this.transformElement = (element, embeds) => this.transformInternal(element.toJSON ? element.toJSON() : element, embeds);
|
|
18
19
|
this.transformInternal = (panel, embeds) => {
|
|
19
|
-
const { preset, panel_size, presetsRoutesAgg, ...rest } = panel;
|
|
20
|
+
const { preset, panel_size, presetsRoutesAgg, deviceStatus, ...rest } = panel;
|
|
20
21
|
const result = {
|
|
21
22
|
...rest,
|
|
22
23
|
presets: this.convertDelimitedStringToArray(preset),
|
|
23
24
|
panel_size: this.parsePanelSize(panel_size),
|
|
24
25
|
};
|
|
25
|
-
if (embeds?.includes(
|
|
26
|
+
if (embeds?.includes(_sch_1.SCOPE_ROUTES) && presetsRoutesAgg?.length) {
|
|
26
27
|
result.routes = presetsRoutesAgg.map(({ route_name, note, is_testing, routes }) => ({
|
|
27
28
|
route_name,
|
|
28
29
|
note,
|
|
@@ -30,6 +31,15 @@ let InformationPanelOutputTransformation = class InformationPanelOutputTransform
|
|
|
30
31
|
routes,
|
|
31
32
|
}));
|
|
32
33
|
}
|
|
34
|
+
if (embeds?.includes(_sch_1.SCOPE_DEVICE_STATUS)) {
|
|
35
|
+
result.deviceStatus = deviceStatus
|
|
36
|
+
? {
|
|
37
|
+
device_id: deviceStatus.device_id,
|
|
38
|
+
last_contact: deviceStatus.last_contact ? new Date(deviceStatus.last_contact).toISOString() : null,
|
|
39
|
+
status: deviceStatus.status,
|
|
40
|
+
}
|
|
41
|
+
: null;
|
|
42
|
+
}
|
|
33
43
|
return result;
|
|
34
44
|
};
|
|
35
45
|
}
|
package/dist/output-gateway/fypr/transformations/InformationPanelOutputTransformation.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"InformationPanelOutputTransformation.js","sourceRoot":"","sources":["../../../../src/output-gateway/fypr/transformations/InformationPanelOutputTransformation.ts"],"names":[],"mappings":";;;;;;;;;
|
|
1
|
+
{"version":3,"file":"InformationPanelOutputTransformation.js","sourceRoot":"","sources":["../../../../src/output-gateway/fypr/transformations/InformationPanelOutputTransformation.ts"],"names":[],"mappings":";;;;;;;;;AAEA,sDAAyE;AAGzE,6GAA0G;AAC1G,iEAAgE;AAGzD,IAAM,oCAAoC,GAA1C,MAAM,oCAAqC,SAAQ,+CAA2D;IAA9G;;QACa,SAAI,GAAG,sCAAsC,CAAC;QAE9C,mBAAc,GAAG,CAAC,IAAsB,EAAE,MAAiB,EAAyB,EAAE,CAClG,IAAI,CAAC,GAAG,CAAC,CAAC,IAAwD,EAAE,EAAE,CAClE,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,CACrE,CAAC;QAEU,qBAAgB,GAAG,CAC/B,OAA2D,EAC3D,MAAiB,EACE,EAAE,CAAC,IAAI,CAAC,iBAAiB,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QAE5F,sBAAiB,GAAG,CAAC,KAAqB,EAAE,MAAiB,EAAuB,EAAE;YAC5F,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,gBAAgB,EAAE,YAAY,EAAE,GAAG,IAAI,EAAE,GAAG,KAGvE,CAAC;YACF,MAAM,MAAM,GAAwB;gBAChC,GAAG,IAAI;gBACP,OAAO,EAAE,IAAI,CAAC,6BAA6B,CAAC,MAAM,CAAC;gBACnD,UAAU,EAAE,IAAI,CAAC,cAAc,CAAC,UAAU,CAAC;aAC9C,CAAC;YACF,IAAI,MAAM,EAAE,QAAQ,CAAC,mBAAY,CAAC,IAAI,gBAAgB,EAAE,MAAM,EAAE,CAAC;gBAC7D,MAAM,CAAC,MAAM,GAAG,gBAAgB,CAAC,GAAG,CAAC,CAAC,EAAE,UAAU,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,CAAC;oBAChF,UAAU;oBACV,IAAI;oBACJ,UAAU;oBACV,MAAM;iBACT,CAAC,CAAC,CAAC;YACR,CAAC;YACD,IAAI,MAAM,EAAE,QAAQ,CAAC,0BAAmB,CAAC,EAAE,CAAC;gBACxC,MAAM,CAAC,YAAY,GAAG,YAAY;oBAC9B,CAAC,CAAC;wBACI,SAAS,EAAE,YAAY,CAAC,SAAS;wBACjC,YAAY,EAAE,YAAY,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,YAAY,CAAC,YAAY,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,IAAI;wBAClG,MAAM,EAAE,YAAY,CAAC,MAAM;qBAC9B;oBACH,CAAC,CAAC,IAAI,CAAC;YACf,CAAC;YACD,OAAO,MAAM,CAAC;QAClB,CAAC,CAAC;IAgBN,CAAC;IAdW,6BAA6B,CAAC,KAAoB;QACtD,IAAI,CAAC,KAAK;YAAE,OAAO,IAAI,CAAC;QACxB,MAAM,KAAK,GAAG,KAAK;aACd,KAAK,CAAC,QAAQ,CAAC;aACf,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;aACpB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QACjC,OAAO,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC;IAC3C,CAAC;IAEO,cAAc,CAAC,KAAoB;QACvC,IAAI,KAAK,IAAI,IAAI;YAAE,OAAO,IAAI,CAAC;QAC/B,MAAM,MAAM,GAAG,QAAQ,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;QACrD,OAAO,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC;IACzC,CAAC;CACJ,CAAA;AAzDY,oFAAoC;+CAApC,oCAAoC;IADhD,IAAA,qBAAU,GAAE;GACA,oCAAoC,CAyDhD"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { IDCIPStatusOverview } from "../../schema-definitions/data-sources/interfaces/IDCIPStatusOverview";
|
|
1
2
|
import { IPresetRouteAgg } from "../../schema-definitions/models/interfaces/IPresetRouteAgg";
|
|
2
3
|
export type IOGPresetRoute = IPresetRouteAgg;
|
|
3
4
|
export interface IOGPresetRoutes {
|
|
@@ -6,6 +7,8 @@ export interface IOGPresetRoutes {
|
|
|
6
7
|
is_testing: boolean;
|
|
7
8
|
routes: IOGPresetRoute[];
|
|
8
9
|
}
|
|
10
|
+
export type IOGDeviceStatus = IDCIPStatusOverview;
|
|
9
11
|
export interface IOGInformationPanelScopes {
|
|
10
12
|
routes: IOGPresetRoutes[];
|
|
13
|
+
deviceStatus: IOGDeviceStatus | null;
|
|
11
14
|
}
|
|
@@ -52,6 +52,7 @@ export declare const nullableInteger: {
|
|
|
52
52
|
readonly nullable: true;
|
|
53
53
|
}];
|
|
54
54
|
};
|
|
55
|
+
export declare const deviceStatusValues: readonly ["not_charging", "low_power", "ok", "not_ok", "intermittent_outages", "not_monitored", "off"];
|
|
55
56
|
export declare const stateEnum: {
|
|
56
57
|
readonly type: "string";
|
|
57
58
|
readonly enum: readonly ["Plánováno", "V přípravě", "Hotovo", "Zrušeno", "Neplánováno"];
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.stateEnum = exports.nullableInteger = exports.nullableStringArray = exports.nullableDateString = exports.nullableBoolean = exports.nullableNumber = exports.nullableString = exports.STALE_ROW_THRESHOLD = exports.PG_SCHEMA = void 0;
|
|
3
|
+
exports.stateEnum = exports.deviceStatusValues = exports.nullableInteger = exports.nullableStringArray = exports.nullableDateString = exports.nullableBoolean = exports.nullableNumber = exports.nullableString = exports.STALE_ROW_THRESHOLD = exports.PG_SCHEMA = void 0;
|
|
4
4
|
const fyprElementStates_1 = require("./models/interfaces/fyprElementStates");
|
|
5
5
|
exports.PG_SCHEMA = "fypr";
|
|
6
6
|
exports.STALE_ROW_THRESHOLD = "NOW() - INTERVAL '1 minute'";
|
|
@@ -21,6 +21,15 @@ exports.nullableStringArray = {
|
|
|
21
21
|
],
|
|
22
22
|
};
|
|
23
23
|
exports.nullableInteger = { oneOf: [{ type: "integer" }, { type: "null", nullable: true }] };
|
|
24
|
+
exports.deviceStatusValues = [
|
|
25
|
+
"not_charging",
|
|
26
|
+
"low_power",
|
|
27
|
+
"ok",
|
|
28
|
+
"not_ok",
|
|
29
|
+
"intermittent_outages",
|
|
30
|
+
"not_monitored",
|
|
31
|
+
"off",
|
|
32
|
+
];
|
|
24
33
|
// Required `state` / source `stav_prvku` enum fragment (non-null).
|
|
25
34
|
exports.stateEnum = { type: "string", enum: fyprElementStates_1.fyprElementStates };
|
|
26
35
|
//# sourceMappingURL=const.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"const.js","sourceRoot":"","sources":["../../src/schema-definitions/const.ts"],"names":[],"mappings":";;;AAAA,6EAA0E;AAE7D,QAAA,SAAS,GAAG,MAAM,CAAC;AACnB,QAAA,mBAAmB,GAAG,6BAA6B,CAAC;AAEjE,yDAAyD;AAC5C,QAAA,cAAc,GAAG,EAAE,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,EAAW,CAAC;AAC5F,QAAA,cAAc,GAAG,EAAE,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,EAAW,CAAC;AAC5F,QAAA,eAAe,GAAG,EAAE,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,EAAW,CAAC;AAC9F,QAAA,kBAAkB,GAAG;IAC9B,KAAK,EAAE;QACH,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE;QAClC,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE;KACnC;CACK,CAAC;AACE,QAAA,mBAAmB,GAAG;IAC/B,KAAK,EAAE;QACH,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE;QAC5C,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE;KACnC;CACK,CAAC;AACE,QAAA,eAAe,GAAG,EAAE,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,EAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"const.js","sourceRoot":"","sources":["../../src/schema-definitions/const.ts"],"names":[],"mappings":";;;AAAA,6EAA0E;AAE7D,QAAA,SAAS,GAAG,MAAM,CAAC;AACnB,QAAA,mBAAmB,GAAG,6BAA6B,CAAC;AAEjE,yDAAyD;AAC5C,QAAA,cAAc,GAAG,EAAE,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,EAAW,CAAC;AAC5F,QAAA,cAAc,GAAG,EAAE,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,EAAW,CAAC;AAC5F,QAAA,eAAe,GAAG,EAAE,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,EAAW,CAAC;AAC9F,QAAA,kBAAkB,GAAG;IAC9B,KAAK,EAAE;QACH,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE;QAClC,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE;KACnC;CACK,CAAC;AACE,QAAA,mBAAmB,GAAG;IAC/B,KAAK,EAAE;QACH,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE;QAC5C,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE;KACnC;CACK,CAAC;AACE,QAAA,eAAe,GAAG,EAAE,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,EAAW,CAAC;AAE9F,QAAA,kBAAkB,GAAG;IAC9B,cAAc;IACd,WAAW;IACX,IAAI;IACJ,QAAQ;IACR,sBAAsB;IACtB,eAAe;IACf,KAAK;CACC,CAAC;AAEX,mEAAmE;AACtD,QAAA,SAAS,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,qCAAiB,EAAW,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.dcipStatusOverviewJSONSchema = void 0;
|
|
4
|
+
const const_1 = require("../const");
|
|
5
|
+
// additionalProperties is intentionally left permissive (not `false`): DCIP may add fields to its
|
|
6
|
+
// response over time, and rejecting the whole record over an unrecognized field would silently
|
|
7
|
+
// freeze the entire feed rather than just ignoring data we don't use.
|
|
8
|
+
exports.dcipStatusOverviewJSONSchema = {
|
|
9
|
+
type: "array",
|
|
10
|
+
items: {
|
|
11
|
+
type: "object",
|
|
12
|
+
properties: {
|
|
13
|
+
device_id: { type: "string" },
|
|
14
|
+
last_contact: {
|
|
15
|
+
oneOf: [
|
|
16
|
+
{ type: "string", format: "date-time" },
|
|
17
|
+
{ type: "null", nullable: true },
|
|
18
|
+
],
|
|
19
|
+
},
|
|
20
|
+
status: { type: "string", enum: const_1.deviceStatusValues },
|
|
21
|
+
},
|
|
22
|
+
required: ["device_id", "last_contact", "status"],
|
|
23
|
+
},
|
|
24
|
+
};
|
|
25
|
+
//# sourceMappingURL=DCIPStatusOverviewJSONSchema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DCIPStatusOverviewJSONSchema.js","sourceRoot":"","sources":["../../../src/schema-definitions/data-sources/DCIPStatusOverviewJSONSchema.ts"],"names":[],"mappings":";;;AACA,oCAAgD;AAGhD,kGAAkG;AAClG,+FAA+F;AAC/F,sEAAsE;AACzD,QAAA,4BAA4B,GAA0C;IAC/E,IAAI,EAAE,OAAO;IACb,KAAK,EAAE;QACH,IAAI,EAAE,QAAQ;QACd,UAAU,EAAE;YACR,SAAS,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;YAC7B,YAAY,EAAE;gBACV,KAAK,EAAE;oBACH,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE;oBACvC,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE;iBACnC;aACJ;YACD,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,0BAAkB,EAAE;SACvD;QACD,QAAQ,EAAE,CAAC,WAAW,EAAE,cAAc,EAAE,QAAQ,CAAC;KACpD;CACqC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"IDCIPStatusOverview.js","sourceRoot":"","sources":["../../../../src/schema-definitions/data-sources/interfaces/IDCIPStatusOverview.ts"],"names":[],"mappings":""}
|
|
@@ -1,12 +1,18 @@
|
|
|
1
1
|
import { Model, ModelAttributes } from "@golemio/core/dist/shared/sequelize";
|
|
2
2
|
export { AnyFyprElement } from "./FyprElementTypes";
|
|
3
3
|
export { fyprElementStates, FyprElementState } from "./models/interfaces/fyprElementStates";
|
|
4
|
+
export declare const SCOPE_ROUTES = "routes";
|
|
5
|
+
export declare const SCOPE_DEVICE_STATUS = "device_status";
|
|
6
|
+
export declare const informationPanelScopes: readonly ["routes", "device_status"];
|
|
7
|
+
export type InformationPanelScope = typeof informationPanelScopes[number];
|
|
4
8
|
export type FyprEmbedConfig = {
|
|
5
9
|
tableName: string;
|
|
6
10
|
as: string;
|
|
7
11
|
foreignKey: string;
|
|
8
12
|
sourceKey: string;
|
|
9
13
|
attributeModel: ModelAttributes<Model>;
|
|
14
|
+
/** Relation cardinality from the parent element to the embed's table. Defaults to "many". */
|
|
15
|
+
cardinality?: "one" | "many";
|
|
10
16
|
};
|
|
11
17
|
type FyprElementConfig = {
|
|
12
18
|
cs_singular: string;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.fyprElementKinds = exports.FyprElementsConfig = exports.fyprElementStates = void 0;
|
|
3
|
+
exports.fyprElementKinds = exports.FyprElementsConfig = exports.informationPanelScopes = exports.SCOPE_DEVICE_STATUS = exports.SCOPE_ROUTES = exports.fyprElementStates = void 0;
|
|
4
|
+
const DeviceStatusModel_1 = require("./models/DeviceStatusModel");
|
|
4
5
|
const DisplayCaseModel_1 = require("./models/DisplayCaseModel");
|
|
5
6
|
const InformationPanelModel_1 = require("./models/InformationPanelModel");
|
|
6
7
|
const InformationPanelPresetsRoutesAggModel_1 = require("./models/InformationPanelPresetsRoutesAggModel");
|
|
@@ -9,6 +10,12 @@ const SignpostModel_1 = require("./models/SignpostModel");
|
|
|
9
10
|
const TotemModel_1 = require("./models/TotemModel");
|
|
10
11
|
var fyprElementStates_1 = require("./models/interfaces/fyprElementStates");
|
|
11
12
|
Object.defineProperty(exports, "fyprElementStates", { enumerable: true, get: function () { return fyprElementStates_1.fyprElementStates; } });
|
|
13
|
+
// Single source of truth for ?scopes=... values on information-panels. Each value doubles as the
|
|
14
|
+
// key of the matching embeds config below — a typo in either place is a compile/validation error,
|
|
15
|
+
// not a silently dropped embed.
|
|
16
|
+
exports.SCOPE_ROUTES = "routes";
|
|
17
|
+
exports.SCOPE_DEVICE_STATUS = "device_status";
|
|
18
|
+
exports.informationPanelScopes = [exports.SCOPE_ROUTES, exports.SCOPE_DEVICE_STATUS];
|
|
12
19
|
exports.FyprElementsConfig = {
|
|
13
20
|
"display-cases": {
|
|
14
21
|
cs_singular: "vitrína",
|
|
@@ -24,13 +31,21 @@ exports.FyprElementsConfig = {
|
|
|
24
31
|
tableName: InformationPanelModel_1.InformationPanelModel.tableName,
|
|
25
32
|
attributeModel: InformationPanelModel_1.InformationPanelModel.attributeModel,
|
|
26
33
|
embeds: {
|
|
27
|
-
|
|
34
|
+
[exports.SCOPE_ROUTES]: {
|
|
28
35
|
tableName: InformationPanelPresetsRoutesAggModel_1.InformationPanelPresetsRoutesAggModel.tableName,
|
|
29
36
|
as: "presetsRoutesAgg",
|
|
30
37
|
foreignKey: "information_panel_document_id",
|
|
31
38
|
sourceKey: "document_id",
|
|
32
39
|
attributeModel: InformationPanelPresetsRoutesAggModel_1.InformationPanelPresetsRoutesAggModel.attributeModel,
|
|
33
40
|
},
|
|
41
|
+
[exports.SCOPE_DEVICE_STATUS]: {
|
|
42
|
+
tableName: DeviceStatusModel_1.DeviceStatusModel.tableName,
|
|
43
|
+
as: "deviceStatus",
|
|
44
|
+
foreignKey: "device_id",
|
|
45
|
+
sourceKey: "device_id",
|
|
46
|
+
attributeModel: DeviceStatusModel_1.DeviceStatusModel.attributeModel,
|
|
47
|
+
cardinality: "one",
|
|
48
|
+
},
|
|
34
49
|
},
|
|
35
50
|
},
|
|
36
51
|
obelisks: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/schema-definitions/index.ts"],"names":[],"mappings":";;;AACA,gEAA6D;AAC7D,0EAAuE;AACvE,0GAAuG;AACvG,wDAAqD;AACrD,0DAAuD;AACvD,oDAAiD;AAGjD,2EAA4F;AAAnF,sHAAA,iBAAiB,OAAA;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/schema-definitions/index.ts"],"names":[],"mappings":";;;AACA,kEAA+D;AAC/D,gEAA6D;AAC7D,0EAAuE;AACvE,0GAAuG;AACvG,wDAAqD;AACrD,0DAAuD;AACvD,oDAAiD;AAGjD,2EAA4F;AAAnF,sHAAA,iBAAiB,OAAA;AAE1B,iGAAiG;AACjG,kGAAkG;AAClG,gCAAgC;AACnB,QAAA,YAAY,GAAG,QAAQ,CAAC;AACxB,QAAA,mBAAmB,GAAG,eAAe,CAAC;AACtC,QAAA,sBAAsB,GAAG,CAAC,oBAAY,EAAE,2BAAmB,CAAU,CAAC;AAsBtE,QAAA,kBAAkB,GAM3B;IACA,eAAe,EAAE;QACb,WAAW,EAAE,SAAS;QACtB,EAAE,EAAE,SAAS;QACb,SAAS,EAAE,eAAe;QAC1B,SAAS,EAAE,mCAAgB,CAAC,SAAS;QACrC,cAAc,EAAE,mCAAgB,CAAC,cAAc;KAClD;IACD,oBAAoB,EAAE;QAClB,WAAW,EAAE,kBAAkB;QAC/B,EAAE,EAAE,mBAAmB;QACvB,SAAS,EAAE,oBAAoB;QAC/B,SAAS,EAAE,6CAAqB,CAAC,SAAS;QAC1C,cAAc,EAAE,6CAAqB,CAAC,cAAc;QACpD,MAAM,EAAE;YACJ,CAAC,oBAAY,CAAC,EAAE;gBACZ,SAAS,EAAE,6EAAqC,CAAC,SAAS;gBAC1D,EAAE,EAAE,kBAAkB;gBACtB,UAAU,EAAE,+BAA+B;gBAC3C,SAAS,EAAE,aAAa;gBACxB,cAAc,EAAE,6EAAqC,CAAC,cAAc;aACvE;YACD,CAAC,2BAAmB,CAAC,EAAE;gBACnB,SAAS,EAAE,qCAAiB,CAAC,SAAS;gBACtC,EAAE,EAAE,cAAc;gBAClB,UAAU,EAAE,WAAW;gBACvB,SAAS,EAAE,WAAW;gBACtB,cAAc,EAAE,qCAAiB,CAAC,cAAc;gBAChD,WAAW,EAAE,KAAK;aACrB;SACJ;KACJ;IACD,QAAQ,EAAE;QACN,WAAW,EAAE,SAAS;QACtB,EAAE,EAAE,UAAU;QACd,SAAS,EAAE,UAAU;QACrB,SAAS,EAAE,2BAAY,CAAC,SAAS;QACjC,cAAc,EAAE,2BAAY,CAAC,cAAc;KAC9C;IACD,SAAS,EAAE;QACP,WAAW,EAAE,WAAW;QACxB,EAAE,EAAE,YAAY;QAChB,SAAS,EAAE,WAAW;QACtB,SAAS,EAAE,6BAAa,CAAC,SAAS;QAClC,cAAc,EAAE,6BAAa,CAAC,cAAc;KAC/C;IACD,MAAM,EAAE;QACJ,WAAW,EAAE,OAAO;QACpB,EAAE,EAAE,QAAQ;QACZ,SAAS,EAAE,QAAQ;QACnB,SAAS,EAAE,uBAAU,CAAC,SAAS;QAC/B,cAAc,EAAE,uBAAU,CAAC,cAAc;KAC5C;CACJ,CAAC;AAIW,QAAA,gBAAgB,GAAG,MAAM,CAAC,IAAI,CAAC,0BAAkB,CAAsB,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { CreationOptional, InferAttributes, InferCreationAttributes, Model, ModelAttributes } from "@golemio/core/dist/shared/sequelize";
|
|
2
|
+
import { IDeviceStatus } from "./interfaces/IDeviceStatus";
|
|
3
|
+
export declare class DeviceStatusModel extends Model<InferAttributes<DeviceStatusModel>, InferCreationAttributes<DeviceStatusModel>> implements IDeviceStatus {
|
|
4
|
+
static readonly tableName = "device_statuses";
|
|
5
|
+
device_id: string;
|
|
6
|
+
last_contact: Date | null;
|
|
7
|
+
status: IDeviceStatus["status"];
|
|
8
|
+
updated_at: CreationOptional<Date>;
|
|
9
|
+
static readonly attributeModel: ModelAttributes<DeviceStatusModel>;
|
|
10
|
+
static getUpdateAttributes(): string[];
|
|
11
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DeviceStatusModel = void 0;
|
|
4
|
+
const sequelize_1 = require("@golemio/core/dist/shared/sequelize");
|
|
5
|
+
class DeviceStatusModel extends sequelize_1.Model {
|
|
6
|
+
static getUpdateAttributes() {
|
|
7
|
+
return ["last_contact", "status", "updated_at"];
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
exports.DeviceStatusModel = DeviceStatusModel;
|
|
11
|
+
DeviceStatusModel.tableName = "device_statuses";
|
|
12
|
+
DeviceStatusModel.attributeModel = {
|
|
13
|
+
device_id: {
|
|
14
|
+
primaryKey: true,
|
|
15
|
+
allowNull: false,
|
|
16
|
+
type: sequelize_1.DataTypes.STRING(255),
|
|
17
|
+
},
|
|
18
|
+
last_contact: { type: sequelize_1.DataTypes.DATE, allowNull: true },
|
|
19
|
+
status: { type: sequelize_1.DataTypes.STRING(50), allowNull: false },
|
|
20
|
+
updated_at: { type: sequelize_1.DataTypes.DATE, allowNull: false, defaultValue: sequelize_1.DataTypes.NOW },
|
|
21
|
+
};
|
|
22
|
+
//# sourceMappingURL=DeviceStatusModel.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DeviceStatusModel.js","sourceRoot":"","sources":["../../../src/schema-definitions/models/DeviceStatusModel.ts"],"names":[],"mappings":";;;AAAA,mEAO6C;AAI7C,MAAa,iBACT,SAAQ,iBAAqF;IAqBtF,MAAM,CAAC,mBAAmB;QAC7B,OAAO,CAAC,cAAc,EAAE,QAAQ,EAAE,YAAY,CAAC,CAAC;IACpD,CAAC;;AAxBL,8CAyBC;AArB0B,2BAAS,GAAG,iBAAiB,CAAC;AAO9B,gCAAc,GAAuC;IACxE,SAAS,EAAE;QACP,UAAU,EAAE,IAAI;QAChB,SAAS,EAAE,KAAK;QAChB,IAAI,EAAE,qBAAS,CAAC,MAAM,CAAC,GAAG,CAAC;KAC9B;IACD,YAAY,EAAE,EAAE,IAAI,EAAE,qBAAS,CAAC,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE;IACvD,MAAM,EAAE,EAAE,IAAI,EAAE,qBAAS,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE;IACxD,UAAU,EAAE,EAAE,IAAI,EAAE,qBAAS,CAAC,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,YAAY,EAAE,qBAAS,CAAC,GAAG,EAAE;CACtF,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"IDeviceStatus.js","sourceRoot":"","sources":["../../../../src/schema-definitions/models/interfaces/IDeviceStatus.ts"],"names":[],"mappings":""}
|
package/docs/asyncapi.yaml
CHANGED
|
@@ -36,6 +36,11 @@ operations:
|
|
|
36
36
|
channel:
|
|
37
37
|
$ref: "#/channels/fypr.updateTotems"
|
|
38
38
|
|
|
39
|
+
fypr.fetchDCIPStatus:
|
|
40
|
+
action: "send"
|
|
41
|
+
channel:
|
|
42
|
+
$ref: "#/channels/fypr.fetchDCIPStatus"
|
|
43
|
+
|
|
39
44
|
channels:
|
|
40
45
|
fypr.fetchDBFYPR:
|
|
41
46
|
address: vehicle-positions.fypr.fetchDBFYPR
|
|
@@ -49,6 +54,18 @@ channels:
|
|
|
49
54
|
empty:
|
|
50
55
|
$ref: "#/components/messages/emptyMessage"
|
|
51
56
|
|
|
57
|
+
fypr.fetchDCIPStatus:
|
|
58
|
+
address: vehicle-positions.fypr.fetchDCIPStatus
|
|
59
|
+
description: Fetch device status overview from DCIP and upsert it into fypr.device_statuses
|
|
60
|
+
bindings:
|
|
61
|
+
amqp:
|
|
62
|
+
is: queue
|
|
63
|
+
queue:
|
|
64
|
+
durable: true
|
|
65
|
+
messages:
|
|
66
|
+
empty:
|
|
67
|
+
$ref: "#/components/messages/emptyMessage"
|
|
68
|
+
|
|
52
69
|
fypr.updateDisplayCases:
|
|
53
70
|
address: vehicle-positions.fypr.updateDisplayCases
|
|
54
71
|
description: Update display cases data in database
|
|
@@ -39,6 +39,35 @@ Modul slouží k ukládání a poskytování informací o fyzických informačn
|
|
|
39
39
|
- název RabbitMQ fronty
|
|
40
40
|
- `vehicle-positions.fypr.fetchDBFYPR`
|
|
41
41
|
|
|
42
|
+
#### *DCIP status-overview*
|
|
43
|
+
|
|
44
|
+
- zdroj dat
|
|
45
|
+
- base URL: `module.fypr.dcipApi.baseUrl`
|
|
46
|
+
- URL path: `module.fypr.dcipApi.statusOverviewPath` (výchozí `/api/v1/status-overview`)
|
|
47
|
+
- autentizace: hlavička `X-Api-Key`, hodnota z `module.fypr.dcipApi.apiKey`
|
|
48
|
+
- timeout: `module.fypr.dcipApi.clientTimeoutInSeconds` (výchozí 20 s; musí být výrazně pod TTL fronty 55 s, aby se zpracování nepřekrývalo s dalším cron během)
|
|
49
|
+
- poznámka: `last_contact: null` znamená, že zařízení nikdy neposlalo stavovou zprávu (není v provozu, bylo zrušeno bez fyzické likvidace, nebo ho nelze sledovat) — nejedná se o chybu
|
|
50
|
+
- významy stavů (`status`):
|
|
51
|
+
- `ok` — zařízení funguje
|
|
52
|
+
- `not_ok` — nefunguje už delší souvislou dobu (zařízení nefunguje, ale mělo by)
|
|
53
|
+
- `intermittent_outages` — hodně krátkých výpadků po sobě
|
|
54
|
+
- `not_monitored` — zařízení evidujeme, ale nemáme jak sledovat
|
|
55
|
+
- `off` — zařízení nefunguje a víme o tom (nastavuje se ručně)
|
|
56
|
+
- `not_charging` — rezervováno (zařízení funguje, ale nedobíjí)
|
|
57
|
+
- `low_power` — rezervováno (zařízení funguje, ale má vybitou baterku)
|
|
58
|
+
- formát dat
|
|
59
|
+
- protokol: HTTP
|
|
60
|
+
- datový typ: JSON
|
|
61
|
+
- data source: [`DCIPStatusOverviewDataSourceFactory`](../src/integration-engine/data-sources/DCIPStatusOverviewDataSourceFactory.ts)
|
|
62
|
+
- validační schéma: [`dcipStatusOverviewJSONSchema`](../src/schema-definitions/data-sources/DCIPStatusOverviewJSONSchema.ts) (validace probíhá na úrovni data source)
|
|
63
|
+
- frekvence stahování
|
|
64
|
+
- cron definice
|
|
65
|
+
- cron.vehicle-positions.fypr.fetchDCIPStatus
|
|
66
|
+
- rabin 1min
|
|
67
|
+
- prod 1min
|
|
68
|
+
- název RabbitMQ fronty
|
|
69
|
+
- `vehicle-positions.fypr.fetchDCIPStatus`
|
|
70
|
+
|
|
42
71
|
|
|
43
72
|
|
|
44
73
|
## Zpracování dat / transformace
|
|
@@ -166,6 +195,26 @@ Worker má na starost stahování dat o fyzických prvcích z DBFYPR backend (St
|
|
|
166
195
|
- repository: [`TotemRepository`](../src/integration-engine/repositories/TotemRepository.ts)
|
|
167
196
|
- tabulka: `fypr.totems`
|
|
168
197
|
|
|
198
|
+
#### Task *FetchDCIPStatus*
|
|
199
|
+
|
|
200
|
+
- vstupní RabbitMQ fronta
|
|
201
|
+
- název: `vehicle-positions.fypr.fetchDCIPStatus`
|
|
202
|
+
- TTL: 55 sekund
|
|
203
|
+
- parametry: žádné
|
|
204
|
+
- závislé fronty (do kterých jsou odesílány zprávy z metody workeru)
|
|
205
|
+
- žádné (fetch i upsert probíhá přímo v rámci tasku, viz `UpdatePresetsTask` pro obdobný vzor)
|
|
206
|
+
- datové zdroje
|
|
207
|
+
- DCIP status-overview
|
|
208
|
+
- transformace
|
|
209
|
+
- žádné
|
|
210
|
+
- data modely
|
|
211
|
+
- výstupní model: [`DeviceStatusModel`](../src/schema-definitions/models/DeviceStatusModel.ts)
|
|
212
|
+
- rozhraní: [`IDeviceStatus`](../src/schema-definitions/models/interfaces/IDeviceStatus.ts)
|
|
213
|
+
- repository: [`DeviceStatusRepository`](../src/integration-engine/repositories/DeviceStatusRepository.ts)
|
|
214
|
+
- tabulka: `fypr.device_statuses`
|
|
215
|
+
- poznámka: pouze UPSERT dle `device_id`, bez mazání
|
|
216
|
+
- validace: probíhá na úrovni data source (viz výše); schéma toleruje neznámá pole (forward-compatible s budoucím rozšířením DCIP API); duplicitní `device_id` v jedné odpovědi se deduplikuje (vyhrává záznam s nejnovějším `last_contact`)
|
|
217
|
+
- alerting: při chybě task vyhodí chybu s klíčovým slovem `DCIP_STATUS_IMPORT_FAILED` na začátku zprávy včetně počtu selhání po sobě — na to lze navázat alert v Loki (např. 3+ selhání po sobě)
|
|
169
218
|
|
|
170
219
|
|
|
171
220
|
## Uložení dat
|
|
@@ -186,9 +235,11 @@ Popis ukládání dat.
|
|
|
186
235
|
- `obelisks` - obelisky
|
|
187
236
|
- `signposts` - směrovníky
|
|
188
237
|
- `totems` - totemy
|
|
238
|
+
- samostatná tabulka `device_statuses` (stav DCIP zařízení, klíč `device_id`; není element a nedědí z `elements`)
|
|
189
239
|
- data jsou ukládána bez automatického promazávání
|
|
190
240
|
- aktualizace dat probíhá pomocí UPSERT
|
|
191
241
|
- starší verze dat jsou přepsány novými daty ze zdroje
|
|
242
|
+
- výjimka: `device_statuses` se pouze UPSERTuje — zařízení chybějící v aktuální DCIP odpovědi si ponechá poslední známý stav (nikdy se nemaže)
|
|
192
243
|
|
|
193
244
|
### Datové modely
|
|
194
245
|
|
|
@@ -199,6 +250,7 @@ Pro podrobnou strukturu jednotlivých tabulek viz:
|
|
|
199
250
|
- [SignpostModel](../src/schema-definitions/models/SignpostModel.ts)
|
|
200
251
|
- [TotemModel](../src/schema-definitions/models/TotemModel.ts)
|
|
201
252
|
- [AbstractElementModel](../src/schema-definitions/models/AbstractElementModel.ts) (společné atributy)
|
|
253
|
+
- [DeviceStatusModel](../src/schema-definitions/models/DeviceStatusModel.ts) (`device_statuses`, samostatná tabulka)
|
|
202
254
|
|
|
203
255
|
|
|
204
256
|
## Output API
|
|
@@ -210,10 +262,12 @@ Pro podrobnou strukturu jednotlivých tabulek viz:
|
|
|
210
262
|
- rabin: <https://rabin.golemio.cz/pid/docs/openapi/>
|
|
211
263
|
- golem: <https://api.golemio.cz/pid/docs/openapi/>
|
|
212
264
|
|
|
213
|
-
- cache hlavičky: `max-age=300, stale-while-revalidate=60` (5 minut / 1 minuta)
|
|
265
|
+
- cache hlavičky: `max-age=300, stale-while-revalidate=60` (5 minut / 1 minuta), konfigurace: `module.fypr.output-gateway.elements.cache.{maxAge,staleWhileRevalidate}`
|
|
266
|
+
- výjimka: odpovědi na `GET /v1/fypr/elements/information-panels` s `scopes=device_status` mají kratší cache `max-age=60, stale-while-revalidate=30` (1 minuta / 30 sekund), konfigurace: `module.fypr.output-gateway.deviceStatuses.cache.{maxAge,staleWhileRevalidate}` — odpovídá frekvenci stahování dat z DCIP (1×/min), aby změna stavu nebyla vidět se zpožděním až 5 minut jako u běžného výpisu prvků
|
|
214
267
|
- architektura:
|
|
215
268
|
- router: [`V1FyprElementKindsRouter`](../src/output-gateway/fypr/routers/v1/V1FyprElementKindsRouter.ts) — base path `v1/fypr/elements`
|
|
216
269
|
- router: [`V1FyprMetadataRouter`](../src/output-gateway/fypr/routers/v1/V1FyprMetadataRouter.ts) — base path `v1/fypr/metadata`
|
|
270
|
+
- middleware pro cache hlavičky: [`src/output-gateway/fypr/routers/middlewares/cacheMiddleware.ts`](../src/output-gateway/fypr/routers/middlewares/cacheMiddleware.ts)
|
|
217
271
|
- controller: [`V1FyprElementKindsController`](../src/output-gateway/fypr/controllers/v1/V1FyprElementKindsController.ts)
|
|
218
272
|
- controller: [`V1FyprMetadataController`](../src/output-gateway/fypr/controllers/v1/V1FyprMetadataController.ts)
|
|
219
273
|
- repository: [`FyprElementRepository<T>`](../src/output-gateway/fypr/data-access/FyprElementRepository.ts) — generická třída, 5 instancí (jedna pro každý druh prvku)
|
|
@@ -294,8 +348,9 @@ Výsledky jsou řazeny dle `source_created_at ASC` (nejstarší záznamy první,
|
|
|
294
348
|
(`state=Hotovo&state=Plánováno`); platné hodnoty: `Plánováno`, `V přípravě`, `Hotovo`, `Zrušeno`, `Neplánováno`
|
|
295
349
|
- `hasDeviceId` (boolean) — `true` vrátí infopanely s vyplněným `device_id`, `false` infopanely bez něj
|
|
296
350
|
|
|
297
|
-
- volitelné query parametry pro připojení souvisejících dat (embed/join, pouze pro `information-panels`):
|
|
351
|
+
- volitelné query parametry pro připojení souvisejících dat (embed/join, pouze pro `information-panels`); parametr lze opakovat pro připojení více zdrojů najednou (`scopes=routes&scopes=device_status`):
|
|
298
352
|
- `scopes=routes` — připojí k infopanelům související linky (`routes`) z navázaných tabulek presetů
|
|
353
|
+
- `scopes=device_status` — připojí k infopanelu aktuální DCIP stav zařízení (`deviceStatus: { device_id, last_contact, status } | null`) dle shody `device_id`
|
|
299
354
|
|
|
300
355
|
- chybové stavové kódy:
|
|
301
356
|
- `400` — neznámý `:kind`, neplatný `limit` (mimo rozsah 1–10000), záporný `offset`,
|
package/docs/openapi-output.yaml
CHANGED
|
@@ -151,14 +151,22 @@ paths:
|
|
|
151
151
|
- name: scopes
|
|
152
152
|
in: query
|
|
153
153
|
required: false
|
|
154
|
+
style: form
|
|
155
|
+
explode: true
|
|
154
156
|
schema:
|
|
155
|
-
type:
|
|
156
|
-
|
|
157
|
-
|
|
157
|
+
type: array
|
|
158
|
+
items:
|
|
159
|
+
type: string
|
|
160
|
+
enum:
|
|
161
|
+
- routes
|
|
162
|
+
- device_status
|
|
158
163
|
description: >-
|
|
159
|
-
Extend the panel response with related resources.
|
|
160
|
-
|
|
161
|
-
preset
|
|
164
|
+
Extend the panel response with related resources. Repeat the parameter to
|
|
165
|
+
request more than one (e.g. scopes=routes&scopes=device_status). "routes" adds
|
|
166
|
+
routes directly to each panel with preset routes grouped by preset name.
|
|
167
|
+
"device_status" adds the latest DCIP device status (matched by device_id) as a
|
|
168
|
+
deviceStatus object, or null when no status has been reported for that device.
|
|
169
|
+
Only valid for information-panels.
|
|
162
170
|
- name: state
|
|
163
171
|
in: query
|
|
164
172
|
required: false
|
|
@@ -450,6 +458,48 @@ components:
|
|
|
450
458
|
- error_status
|
|
451
459
|
|
|
452
460
|
schemas:
|
|
461
|
+
DeviceStatus:
|
|
462
|
+
type: object
|
|
463
|
+
required:
|
|
464
|
+
- device_id
|
|
465
|
+
- last_contact
|
|
466
|
+
- status
|
|
467
|
+
properties:
|
|
468
|
+
device_id:
|
|
469
|
+
type: string
|
|
470
|
+
example: "bustec127"
|
|
471
|
+
description: Identifier of the device, as reported by DCIP.
|
|
472
|
+
last_contact:
|
|
473
|
+
type: string
|
|
474
|
+
format: date-time
|
|
475
|
+
nullable: true
|
|
476
|
+
example: "2026-08-14T08:00:00.000Z"
|
|
477
|
+
description: >-
|
|
478
|
+
Timestamp of the device's last reported contact. Null means the device
|
|
479
|
+
has never reported a status (not yet in service, decommissioned but not
|
|
480
|
+
physically removed, or its source cannot be monitored).
|
|
481
|
+
status:
|
|
482
|
+
type: string
|
|
483
|
+
enum:
|
|
484
|
+
- not_charging
|
|
485
|
+
- low_power
|
|
486
|
+
- ok
|
|
487
|
+
- not_ok
|
|
488
|
+
- intermittent_outages
|
|
489
|
+
- not_monitored
|
|
490
|
+
- off
|
|
491
|
+
example: "ok"
|
|
492
|
+
description: >-
|
|
493
|
+
Current operational status of the device, as reported by DCIP.
|
|
494
|
+
Approximate meaning of the values:
|
|
495
|
+
`ok` — device is working normally;
|
|
496
|
+
`not_ok` — device has been down for a longer continuous period (it should be working, but is not);
|
|
497
|
+
`intermittent_outages` — many short outages in a row;
|
|
498
|
+
`not_monitored` — device is registered, but there is no way to monitor it;
|
|
499
|
+
`off` — device is not working and this is known (set manually);
|
|
500
|
+
`not_charging` — reserved (device works, but is not charging);
|
|
501
|
+
`low_power` — reserved (device works, but its battery is drained).
|
|
502
|
+
|
|
453
503
|
ElementStateEnum:
|
|
454
504
|
type: string
|
|
455
505
|
nullable: true
|
|
@@ -1127,6 +1177,8 @@ components:
|
|
|
1127
1177
|
Returned by the list endpoint GET /v1/information-panels.
|
|
1128
1178
|
When ?scopes=routes is provided, the response includes a routes array directly
|
|
1129
1179
|
on each panel with preset routes grouped by preset name.
|
|
1180
|
+
When ?scopes=device_status is provided, the response includes a deviceStatus object
|
|
1181
|
+
(or null) with the latest DCIP status matched by device_id.
|
|
1130
1182
|
allOf:
|
|
1131
1183
|
- $ref: "#/components/schemas/ElementReadOnly"
|
|
1132
1184
|
- $ref: "#/components/schemas/InformationPanelBase"
|
|
@@ -1138,10 +1190,20 @@ components:
|
|
|
1138
1190
|
|
|
1139
1191
|
InformationPanelScopes:
|
|
1140
1192
|
description: >-
|
|
1141
|
-
Additional resources included when ?scopes=routes is
|
|
1142
|
-
|
|
1193
|
+
Additional resources included when ?scopes=routes or ?scopes=device_status is
|
|
1194
|
+
requested. routes is present only when the panel has presets with associated
|
|
1195
|
+
routes; deviceStatus is present (possibly null) whenever ?scopes=device_status
|
|
1196
|
+
is requested.
|
|
1143
1197
|
type: object
|
|
1144
1198
|
properties:
|
|
1199
|
+
deviceStatus:
|
|
1200
|
+
allOf:
|
|
1201
|
+
- $ref: "#/components/schemas/DeviceStatus"
|
|
1202
|
+
nullable: true
|
|
1203
|
+
description: >-
|
|
1204
|
+
Latest DCIP status for the panel's device_id, or null when no status
|
|
1205
|
+
has been reported for that device. Only present when ?scopes=device_status
|
|
1206
|
+
is requested.
|
|
1145
1207
|
routes:
|
|
1146
1208
|
type: array
|
|
1147
1209
|
description: Preset routes grouped by preset name.
|