hoffmation-base 2.14.1 → 2.15.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (25) hide show
  1. package/lib/index.d.ts +1 -0
  2. package/lib/index.js +5 -0
  3. package/lib/models/rooms/RoomBase.d.ts +2 -2
  4. package/lib/models/rooms/RoomBase.js +4 -1
  5. package/lib/server/devices/baseDeviceInterfaces/iBluetoothDetector.d.ts +2 -1
  6. package/lib/server/devices/espresense/detectedBluetoothDevice.d.ts +2 -0
  7. package/lib/server/devices/espresense/detectedBluetoothDevice.js +18 -0
  8. package/lib/server/devices/espresense/espresenseDevice.d.ts +3 -1
  9. package/lib/server/devices/espresense/espresenseDevice.js +6 -1
  10. package/lib/server/devices/espresense/index.d.ts +5 -0
  11. package/lib/server/devices/espresense/index.js +5 -0
  12. package/lib/server/devices/espresense/trilateration.d.ts +14 -0
  13. package/lib/server/devices/espresense/trilateration.js +94 -0
  14. package/lib/server/devices/espresense/trilaterationBasePoint.d.ts +15 -0
  15. package/lib/server/devices/espresense/trilaterationBasePoint.js +49 -0
  16. package/lib/server/devices/espresense/trilaterationPoint.d.ts +12 -0
  17. package/lib/server/devices/espresense/trilaterationPoint.js +35 -0
  18. package/lib/server/devices/espresense/trilaterationPointDistance.d.ts +5 -0
  19. package/lib/server/devices/espresense/trilaterationPointDistance.js +10 -0
  20. package/lib/server/devices/espresense/trilaterationRatedCoordinate.d.ts +6 -0
  21. package/lib/server/devices/espresense/trilaterationRatedCoordinate.js +11 -0
  22. package/lib/server/services/utils/utils.d.ts +1 -0
  23. package/lib/server/services/utils/utils.js +5 -0
  24. package/lib/tsconfig.tsbuildinfo +1 -1
  25. package/package.json +1 -1
package/lib/index.d.ts CHANGED
@@ -10,6 +10,7 @@ export declare class HoffmationInitializationObject {
10
10
  export declare class HoffmationBase {
11
11
  static ioMain: ioBrokerMain;
12
12
  static initializeBeforeIoBroker(initObject: HoffmationInitializationObject): Promise<void>;
13
+ static initializePostRoomCreationBeforeIoBroker(): void;
13
14
  static initializePostIoBroker(defaultMuellSonos?: iSpeaker): void;
14
15
  static startIoBroker(devices: Devices): void;
15
16
  }
package/lib/index.js CHANGED
@@ -66,6 +66,11 @@ class HoffmationBase {
66
66
  server_1.TimeCallbackService.init();
67
67
  server_1.ServerLogService.writeLog(models_1.LogLevel.Info, `Hoffmation-Base First Initializations finished`);
68
68
  }
69
+ static initializePostRoomCreationBeforeIoBroker() {
70
+ server_1.ServerLogService.writeLog(models_1.LogLevel.Info, `Hoffmation-Base Post Room Creation`);
71
+ server_1.Trilateration.initialize();
72
+ server_1.ServerLogService.writeLog(models_1.LogLevel.Info, `Hoffmation-Base Post Room Creation finished`);
73
+ }
69
74
  static initializePostIoBroker(defaultMuellSonos) {
70
75
  var _a, _b;
71
76
  server_1.ServerLogService.writeLog(models_1.LogLevel.Info, `Hoffmation-Base Post ioBrokerInitializations`);
@@ -1,5 +1,5 @@
1
1
  import { TimeCallback } from '../timeCallback';
2
- import { BaseGroup, DeviceCluster, GroupType, HeatGroup, LightGroup, PresenceGroup, SmokeGroup, SpeakerGroup, TasterGroup, WaterGroup, WindowGroup } from '../../server';
2
+ import { BaseGroup, DeviceCluster, GroupType, HeatGroup, LightGroup, PresenceGroup, SmokeGroup, SpeakerGroup, TasterGroup, TrilaterationPoint, WaterGroup, WindowGroup } from '../../server';
3
3
  import { LogLevel } from '../logLevel';
4
4
  import { RoomSettingsController } from './RoomSettings';
5
5
  import { iRoomBase } from './iRoomBase';
@@ -10,7 +10,7 @@ export declare class RoomBase implements iRoomBase, iIdHolder {
10
10
  info: RoomInfo;
11
11
  skipNextRolloUp: boolean;
12
12
  settings: RoomSettingsController;
13
- constructor(groupMap: Map<GroupType, BaseGroup>, roomName: string, etage?: number);
13
+ constructor(groupMap: Map<GroupType, BaseGroup>, roomName: string, etage?: number, startPoint?: TrilaterationPoint, endPoint?: TrilaterationPoint);
14
14
  get sonnenUntergangLichtCallback(): TimeCallback | undefined;
15
15
  get sonnenAufgangLichtCallback(): TimeCallback | undefined;
16
16
  get sunriseShutterCallback(): TimeCallback | undefined;
@@ -11,13 +11,16 @@ const RoomSettings_1 = require("./RoomSettings");
11
11
  const roomInfo_1 = require("./roomInfo");
12
12
  const lodash_1 = __importDefault(require("lodash"));
13
13
  class RoomBase {
14
- constructor(groupMap, roomName, etage = 99) {
14
+ constructor(groupMap, roomName, etage = 99, startPoint, endPoint) {
15
15
  this.groupMap = groupMap;
16
16
  this.skipNextRolloUp = false;
17
17
  this._deviceCluster = new server_1.DeviceCluster();
18
18
  this.info = new roomInfo_1.RoomInfo(roomName, etage);
19
19
  this.settings = new RoomSettings_1.RoomSettingsController(this);
20
20
  server_1.RoomService.addToRoomList(this);
21
+ if (startPoint && endPoint) {
22
+ server_1.Trilateration.addRoom(this, startPoint, endPoint);
23
+ }
21
24
  }
22
25
  get sonnenUntergangLichtCallback() {
23
26
  var _a;
@@ -1,6 +1,7 @@
1
1
  import { iRoomDevice } from './iRoomDevice';
2
- import { ProximityCallback } from '../espresense';
2
+ import { ProximityCallback, TrilaterationBasePoint } from '../espresense';
3
3
  export interface iBluetoothDetector extends iRoomDevice {
4
+ position: TrilaterationBasePoint;
4
5
  /**
5
6
  * Add callback to react on a specified device entering/leaving a given zone
6
7
  * @param cb
@@ -14,6 +14,7 @@ export declare class DetectedBluetoothDevice implements iBaseDevice {
14
14
  readonly deviceCapabilities: DeviceCapability[];
15
15
  deviceType: DeviceType;
16
16
  info: DeviceInfo;
17
+ lastRoom: string | undefined;
17
18
  constructor(id: string, settings?: iBluetoothTrackingSettings);
18
19
  get customName(): string;
19
20
  get name(): string;
@@ -27,4 +28,5 @@ export declare class DetectedBluetoothDevice implements iBaseDevice {
27
28
  private static deviceKeyBySettings;
28
29
  persistDeviceInfo(): void;
29
30
  loadDeviceSettings(): void;
31
+ guessRoom(): void;
30
32
  }
@@ -7,6 +7,8 @@ const deviceType_1 = require("../deviceType");
7
7
  const services_1 = require("../../services");
8
8
  const devices_1 = require("../devices");
9
9
  const trackedDistanceData_1 = require("./trackedDistanceData");
10
+ const trilateration_1 = require("./trilateration");
11
+ const trilaterationPointDistance_1 = require("./trilaterationPointDistance");
10
12
  class DetectedBluetoothDevice {
11
13
  constructor(id, settings) {
12
14
  this.id = id;
@@ -15,6 +17,7 @@ class DetectedBluetoothDevice {
15
17
  this.deviceCapabilities = [DeviceCapability_1.DeviceCapability.trackableDevice];
16
18
  this.deviceType = deviceType_1.DeviceType.TrackableDevice;
17
19
  this.info = new DeviceInfo_1.DeviceInfo();
20
+ this.lastRoom = undefined;
18
21
  if (settings === undefined) {
19
22
  return;
20
23
  }
@@ -98,5 +101,20 @@ class DetectedBluetoothDevice {
98
101
  loadDeviceSettings() {
99
102
  // Nothing
100
103
  }
104
+ guessRoom() {
105
+ const distances = [];
106
+ for (const key of this.distanceMap.keys()) {
107
+ const tracker = services_1.API.getDevice(key);
108
+ if (tracker === undefined) {
109
+ continue;
110
+ }
111
+ const distance = this.getDistance(key);
112
+ if ((distance === null || distance === void 0 ? void 0 : distance.distance) === undefined) {
113
+ continue;
114
+ }
115
+ distances.push(new trilaterationPointDistance_1.TrilaterationPointDistance(tracker.position.ownPoint.coordinateName, distance.distance));
116
+ }
117
+ this.lastRoom = trilateration_1.Trilateration.checkRoom(distances);
118
+ }
101
119
  }
102
120
  exports.DetectedBluetoothDevice = DetectedBluetoothDevice;
@@ -6,14 +6,16 @@ import { DeviceInfo } from '../DeviceInfo';
6
6
  import { DeviceType } from '../deviceType';
7
7
  import { LogDebugType } from '../../services';
8
8
  import { ProximityCallback } from './proximityCallback';
9
+ import { TrilaterationBasePoint } from './trilaterationBasePoint';
9
10
  export declare class EspresenseDevice implements iRoomDevice, iBluetoothDetector {
11
+ readonly position: TrilaterationBasePoint;
10
12
  settings: undefined;
11
13
  readonly deviceCapabilities: DeviceCapability[];
12
14
  deviceType: DeviceType;
13
15
  readonly name: string;
14
16
  private deviceMap;
15
17
  private proximityCallback;
16
- constructor(name: string, roomName: string);
18
+ constructor(name: string, roomName: string, x: number, y: number, z: number);
17
19
  get customName(): string;
18
20
  protected _info: DeviceInfo;
19
21
  get info(): DeviceInfo;
@@ -9,13 +9,16 @@ const services_1 = require("../../services");
9
9
  const devices_1 = require("../devices");
10
10
  const detectedBluetoothDevice_1 = require("./detectedBluetoothDevice");
11
11
  const espresenseCoordinator_1 = require("./espresenseCoordinator");
12
+ const trilaterationBasePoint_1 = require("./trilaterationBasePoint");
13
+ const trilateration_1 = require("./trilateration");
12
14
  class EspresenseDevice {
13
- constructor(name, roomName) {
15
+ constructor(name, roomName, x, y, z) {
14
16
  this.settings = undefined;
15
17
  this.deviceCapabilities = [DeviceCapability_1.DeviceCapability.bluetoothDetector];
16
18
  this.deviceType = deviceType_1.DeviceType.Espresense;
17
19
  this.deviceMap = new Map();
18
20
  this.proximityCallback = new Map();
21
+ this.position = new trilaterationBasePoint_1.TrilaterationBasePoint(x, y, z, roomName);
19
22
  this.name = name;
20
23
  this._info = new DeviceInfo_1.DeviceInfo();
21
24
  this._info.fullName = `Espresense ${roomName} ${name}`;
@@ -26,6 +29,7 @@ class EspresenseDevice {
26
29
  espresenseCoordinator_1.EspresenseCoordinator.addDevice(this, name);
27
30
  this.persistDeviceInfo();
28
31
  this.loadDeviceSettings();
32
+ trilateration_1.Trilateration.basePoints.push(this.position);
29
33
  }
30
34
  get customName() {
31
35
  return this.info.customName;
@@ -72,6 +76,7 @@ class EspresenseDevice {
72
76
  dev = this.addDeviceTracking(devName);
73
77
  }
74
78
  dev.updateDistance(this, data.distance);
79
+ dev.guessRoom();
75
80
  const cbs = this.proximityCallback.get(dev.name);
76
81
  if (cbs === undefined) {
77
82
  return;
@@ -3,3 +3,8 @@ export * from './espresenseCoordinator';
3
3
  export * from './espresenseDevice';
4
4
  export * from './proximityCallback';
5
5
  export * from './trackedDistanceData';
6
+ export * from './trilateration';
7
+ export * from './trilaterationBasePoint';
8
+ export * from './trilaterationRatedCoordinate';
9
+ export * from './trilaterationPoint';
10
+ export * from './trilaterationPointDistance';
@@ -19,3 +19,8 @@ __exportStar(require("./espresenseCoordinator"), exports);
19
19
  __exportStar(require("./espresenseDevice"), exports);
20
20
  __exportStar(require("./proximityCallback"), exports);
21
21
  __exportStar(require("./trackedDistanceData"), exports);
22
+ __exportStar(require("./trilateration"), exports);
23
+ __exportStar(require("./trilaterationBasePoint"), exports);
24
+ __exportStar(require("./trilaterationRatedCoordinate"), exports);
25
+ __exportStar(require("./trilaterationPoint"), exports);
26
+ __exportStar(require("./trilaterationPointDistance"), exports);
@@ -0,0 +1,14 @@
1
+ import { TrilaterationBasePoint } from './trilaterationBasePoint';
2
+ import { TrilaterationPoint } from './trilaterationPoint';
3
+ import { TrilaterationPointDistance } from './trilaterationPointDistance';
4
+ import { RoomBase } from '../../../models';
5
+ export declare class Trilateration {
6
+ static readonly basePoints: TrilaterationBasePoint[];
7
+ static possiblePoints: TrilaterationPoint[];
8
+ static addRoom(room: RoomBase, startPoint: TrilaterationPoint, endPoint: TrilaterationPoint): void;
9
+ static initialize(): void;
10
+ static getBestMatches(distances: TrilaterationPointDistance[]): TrilaterationPoint[];
11
+ private static getBestRatedCoordinates;
12
+ static checkRoom(distances: TrilaterationPointDistance[]): string | undefined;
13
+ private static getBestRatedCoordinatesFromMap;
14
+ }
@@ -0,0 +1,94 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Trilateration = void 0;
4
+ const trilaterationPoint_1 = require("./trilaterationPoint");
5
+ const models_1 = require("../../../models");
6
+ const services_1 = require("../../services");
7
+ class Trilateration {
8
+ static addRoom(room, startPoint, endPoint) {
9
+ const points = trilaterationPoint_1.TrilaterationPoint.getPointsInRange(startPoint, endPoint, room.roomName);
10
+ this.possiblePoints.push(...points);
11
+ }
12
+ static initialize() {
13
+ services_1.ServerLogService.writeLog(models_1.LogLevel.Info, `Initializing Trilateration for ${this.basePoints.length} base points, with ${this.possiblePoints.length} possible points.`);
14
+ for (const basePoint of this.basePoints) {
15
+ basePoint.fillMap(this.possiblePoints);
16
+ }
17
+ }
18
+ static getBestMatches(distances) {
19
+ const bestRatedCoordinates = this.getBestRatedCoordinates(distances);
20
+ if (bestRatedCoordinates.length === 0) {
21
+ return [];
22
+ }
23
+ const bestMatches = [];
24
+ for (const bestRatedCoordinate of bestRatedCoordinates) {
25
+ const point = this.possiblePoints.find((point) => point.coordinateName === bestRatedCoordinate.coordinateName);
26
+ if (point === undefined) {
27
+ continue;
28
+ }
29
+ bestMatches.push(point);
30
+ }
31
+ return bestMatches;
32
+ }
33
+ static getBestRatedCoordinates(distances) {
34
+ const allRatedCoordinates = new Map();
35
+ for (const dist of distances) {
36
+ const point = this.basePoints.find((basePoint) => basePoint.ownPoint.coordinateName === dist.pointName);
37
+ if (point === undefined) {
38
+ continue;
39
+ }
40
+ const ratedCoordinates = point.getRatedCoordinates(dist.distance);
41
+ for (const ratedCoordinate of ratedCoordinates) {
42
+ const existingCoordinate = allRatedCoordinates.get(ratedCoordinate.coordinateName);
43
+ if (existingCoordinate === undefined) {
44
+ allRatedCoordinates.set(ratedCoordinate.coordinateName, ratedCoordinate);
45
+ continue;
46
+ }
47
+ existingCoordinate.rating += ratedCoordinate.rating;
48
+ existingCoordinate.matchCount++;
49
+ }
50
+ }
51
+ return this.getBestRatedCoordinatesFromMap(allRatedCoordinates);
52
+ }
53
+ static checkRoom(distances) {
54
+ var _a;
55
+ const bestMatches = this.getBestMatches(distances);
56
+ if (bestMatches.length === 0) {
57
+ return undefined;
58
+ }
59
+ if (bestMatches.length === 1) {
60
+ return bestMatches[0].roomName;
61
+ }
62
+ // As we have multiple possible winners, we need to check how often which room occurs
63
+ const roomCount = new Map();
64
+ for (const point of bestMatches) {
65
+ const room = point.roomName;
66
+ const existingCount = (_a = roomCount.get(room)) !== null && _a !== void 0 ? _a : 0;
67
+ roomCount.set(room, existingCount + 1);
68
+ }
69
+ return Array.from(roomCount.entries()).sort((a, b) => b[1] - a[1])[0][0];
70
+ }
71
+ static getBestRatedCoordinatesFromMap(allRatedCoordinates) {
72
+ const sortedCoordinates = Array.from(allRatedCoordinates.values()).sort((a, b) => {
73
+ if (a.matchCount !== b.matchCount) {
74
+ return b.matchCount - a.matchCount;
75
+ }
76
+ return b.rating - a.rating;
77
+ });
78
+ const possibleWinner = [];
79
+ for (const coordinate of sortedCoordinates) {
80
+ if (possibleWinner.length === 0) {
81
+ possibleWinner.push(coordinate);
82
+ continue;
83
+ }
84
+ if (possibleWinner[0].rating !== coordinate.matchCount) {
85
+ break;
86
+ }
87
+ possibleWinner.push(coordinate);
88
+ }
89
+ return possibleWinner;
90
+ }
91
+ }
92
+ exports.Trilateration = Trilateration;
93
+ Trilateration.basePoints = [];
94
+ Trilateration.possiblePoints = [];
@@ -0,0 +1,15 @@
1
+ import { TrilaterationRatedCoordinate } from './trilaterationRatedCoordinate';
2
+ import { TrilaterationPoint } from './trilaterationPoint';
3
+ export declare class TrilaterationBasePoint {
4
+ readonly x: number;
5
+ readonly y: number;
6
+ readonly z: number;
7
+ readonly roomName: string;
8
+ private readonly _maximumDistance;
9
+ readonly ownPoint: TrilaterationPoint;
10
+ readonly precalculatedDistances: Map<number, string[]>;
11
+ constructor(x: number, y: number, z: number, roomName: string, _maximumDistance?: number);
12
+ getRatedCoordinates(distance: number): TrilaterationRatedCoordinate[];
13
+ private rateCoordinates;
14
+ fillMap(points: TrilaterationPoint[]): void;
15
+ }
@@ -0,0 +1,49 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TrilaterationBasePoint = void 0;
4
+ const trilaterationRatedCoordinate_1 = require("./trilaterationRatedCoordinate");
5
+ const trilaterationPoint_1 = require("./trilaterationPoint");
6
+ class TrilaterationBasePoint {
7
+ constructor(x, y, z, roomName, _maximumDistance = 8) {
8
+ this.x = x;
9
+ this.y = y;
10
+ this.z = z;
11
+ this.roomName = roomName;
12
+ this._maximumDistance = _maximumDistance;
13
+ this.precalculatedDistances = new Map();
14
+ this.ownPoint = new trilaterationPoint_1.TrilaterationPoint(x, y, z, roomName);
15
+ }
16
+ getRatedCoordinates(distance) {
17
+ const result = [];
18
+ this.rateCoordinates(distance, result, 100);
19
+ this.rateCoordinates(distance - 0.5, result, 30);
20
+ this.rateCoordinates(distance + 0.5, result, 30);
21
+ this.rateCoordinates(distance + 1, result, 15);
22
+ this.rateCoordinates(distance - 1, result, 15);
23
+ this.rateCoordinates(distance + 1.5, result, 7.5);
24
+ this.rateCoordinates(distance - 1.5, result, 7.5);
25
+ return result;
26
+ }
27
+ rateCoordinates(distance, result, rating) {
28
+ const possiblePoints = this.precalculatedDistances.get(distance);
29
+ if (possiblePoints !== undefined) {
30
+ for (const point of possiblePoints) {
31
+ result.push(new trilaterationRatedCoordinate_1.TrilaterationRatedCoordinate(point, rating));
32
+ }
33
+ }
34
+ }
35
+ fillMap(points) {
36
+ var _a;
37
+ for (const point of points) {
38
+ const distance = point.getDot5Distance(this.ownPoint);
39
+ if (distance > this._maximumDistance) {
40
+ continue;
41
+ }
42
+ if (!this.precalculatedDistances.has(distance)) {
43
+ this.precalculatedDistances.set(distance, []);
44
+ }
45
+ (_a = this.precalculatedDistances.get(distance)) === null || _a === void 0 ? void 0 : _a.push(point.coordinateName);
46
+ }
47
+ }
48
+ }
49
+ exports.TrilaterationBasePoint = TrilaterationBasePoint;
@@ -0,0 +1,12 @@
1
+ export declare class TrilaterationPoint {
2
+ x: number;
3
+ y: number;
4
+ z: number;
5
+ roomName: string;
6
+ matchPoints: number;
7
+ static getPointsInRange(a: TrilaterationPoint, b: TrilaterationPoint, roomName?: string): TrilaterationPoint[];
8
+ readonly coordinateName: string;
9
+ constructor(x: number, y: number, z: number, roomName: string, matchPoints?: number);
10
+ getDistance(other: TrilaterationPoint): number;
11
+ getDot5Distance(other: TrilaterationPoint): number;
12
+ }
@@ -0,0 +1,35 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TrilaterationPoint = void 0;
4
+ const services_1 = require("../../services");
5
+ class TrilaterationPoint {
6
+ static getPointsInRange(a, b, roomName = '') {
7
+ const points = [];
8
+ if (a.x > b.x || a.y > b.y || a.z > b.z) {
9
+ throw new Error('Room Coordinates are not in order left-front-bottom to right-back-top');
10
+ }
11
+ for (let x = a.x; x <= b.x; x++) {
12
+ for (let y = a.y; y <= b.y; y++) {
13
+ for (let z = a.z; z <= b.z; z++) {
14
+ points.push(new TrilaterationPoint(x, y, z, roomName));
15
+ }
16
+ }
17
+ }
18
+ return points;
19
+ }
20
+ constructor(x, y, z, roomName, matchPoints = 0) {
21
+ this.x = x;
22
+ this.y = y;
23
+ this.z = z;
24
+ this.roomName = roomName;
25
+ this.matchPoints = matchPoints;
26
+ this.coordinateName = `${this.x}-${this.y}-${this.z}`;
27
+ }
28
+ getDistance(other) {
29
+ return Math.sqrt((this.x - other.x) ** 2 + (this.y - other.y) ** 2 + (this.z - other.z) ** 2);
30
+ }
31
+ getDot5Distance(other) {
32
+ return services_1.Utils.roundDot5(this.getDistance(other));
33
+ }
34
+ }
35
+ exports.TrilaterationPoint = TrilaterationPoint;
@@ -0,0 +1,5 @@
1
+ export declare class TrilaterationPointDistance {
2
+ readonly pointName: string;
3
+ readonly distance: number;
4
+ constructor(pointName: string, distance: number);
5
+ }
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TrilaterationPointDistance = void 0;
4
+ class TrilaterationPointDistance {
5
+ constructor(pointName, distance) {
6
+ this.pointName = pointName;
7
+ this.distance = distance;
8
+ }
9
+ }
10
+ exports.TrilaterationPointDistance = TrilaterationPointDistance;
@@ -0,0 +1,6 @@
1
+ export declare class TrilaterationRatedCoordinate {
2
+ coordinateName: string;
3
+ rating: number;
4
+ matchCount: number;
5
+ constructor(coordinateName: string, rating: number, matchCount?: number);
6
+ }
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TrilaterationRatedCoordinate = void 0;
4
+ class TrilaterationRatedCoordinate {
5
+ constructor(coordinateName, rating, matchCount = 1) {
6
+ this.coordinateName = coordinateName;
7
+ this.rating = rating;
8
+ this.matchCount = matchCount;
9
+ }
10
+ }
11
+ exports.TrilaterationRatedCoordinate = TrilaterationRatedCoordinate;
@@ -21,6 +21,7 @@ export declare class Utils {
21
21
  static testInitializeServices(): void;
22
22
  static kWh(wattage: number, durationInMs: number): number;
23
23
  static round(number: number, digits: number): number;
24
+ static roundDot5(number: number): number;
24
25
  static beetweenDays(date: Date, startDay: number, endDay: number): boolean;
25
26
  static nowTime(): {
26
27
  hours: number;
@@ -135,6 +135,11 @@ class Utils {
135
135
  const factor = Math.pow(10, digits);
136
136
  return Math.round(number * factor) / factor;
137
137
  }
138
+ static roundDot5(number) {
139
+ const x = Math.round(number * 10);
140
+ const roundToClosest5 = x % 5 >= 2.5 ? Math.floor(x / 5) * 5 + 5 : Math.floor(x / 5) * 5;
141
+ return roundToClosest5 / 10;
142
+ }
138
143
  static beetweenDays(date, startDay, endDay) {
139
144
  const yearStart = new Date(date.getTime());
140
145
  yearStart.setMonth(0, 1);