Skip to content

Commit 800c0a9

Browse files
committed
Merge branch 'chore/repo-cleanup'
2 parents 7907f72 + 7125ece commit 800c0a9

File tree

2 files changed

+36
-11
lines changed

2 files changed

+36
-11
lines changed

src/common/utils/product.utils.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,3 +126,28 @@ export function getDeviceType(modelId: string): string | null {
126126
const decoded = decodeProductId(modelId);
127127
return decoded?.deviceType ?? null;
128128
}
129+
130+
/**
131+
* Resolve device type from raw API device data.
132+
* Uses productInfos[1] as the primary deviceTypeId source (always available from API),
133+
* which is more reliable than decoding the productId string (variable formats).
134+
*
135+
* @param device - Raw device object from IoT API
136+
* @returns { deviceType, deviceTypeId } or null if not resolvable
137+
*/
138+
export function resolveDeviceType(
139+
device: Record<string, unknown>,
140+
): { deviceType: string; deviceTypeId: number } | null {
141+
const productInfos = device.productInfos as number[] | undefined;
142+
if (!Array.isArray(productInfos) || productInfos.length < 2) {
143+
return null;
144+
}
145+
146+
const deviceTypeId = productInfos[1];
147+
if (deviceTypeId == null || deviceTypeId < 0) {
148+
return null;
149+
}
150+
151+
const deviceType = DEVICE_TYPE[deviceTypeId] ?? 'UNKNOWN';
152+
return { deviceType, deviceTypeId };
153+
}

src/tools/services/tool-executor.service.ts

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { Injectable, BadRequestException, UnauthorizedException } from '@nestjs/
88
import { CallToolResult } from '@modelcontextprotocol/sdk/types.js';
99
import { IotApiService } from '../../proxy/services/iot-api.service';
1010
import { decodeJwt, extractBearerToken, getUserIdFromToken } from '../../common/utils/jwt.utils';
11-
import { decodeProductId } from '../../common/utils/product.utils';
11+
import { decodeProductId, resolveDeviceType } from '../../common/utils/product.utils';
1212
import { FETCH_USER_TOOL, FetchUserParams } from '../definitions/fetch-user.tool';
1313
import { SEARCH_TOOL, SearchParams } from '../definitions/search.tool';
1414
import { FETCH_TOOL, FetchParams } from '../definitions/fetch.tool';
@@ -359,7 +359,7 @@ export class ToolExecutorService {
359359
d.label?.toLowerCase().includes(query) || d.desc?.toLowerCase().includes(query)
360360
)
361361
.map((d: any) => {
362-
const decoded = d.productId ? decodeProductId(d.productId as string) : null;
362+
const typeInfo = resolveDeviceType(d);
363363
return {
364364
uuid: d.uuid,
365365
label: d.label,
@@ -368,7 +368,7 @@ export class ToolExecutorService {
368368
locationId: d.locationId,
369369
groupId: d.groupId,
370370
features: d.features,
371-
...(decoded && { deviceType: decoded.deviceType, deviceTypeId: decoded.deviceTypeId }),
371+
...(typeInfo && { deviceType: typeInfo.deviceType, deviceTypeId: typeInfo.deviceTypeId }),
372372
};
373373
});
374374

@@ -567,11 +567,9 @@ export class ToolExecutorService {
567567
params.locationId ?? undefined,
568568
);
569569

570-
// Enrich each device with decoded product type, then slim for token efficiency
570+
// Enrich each device with device type from productInfos, then slim for token efficiency
571571
const slimDevices = devices.map((device: Record<string, unknown>) => {
572-
const decoded = device.productId
573-
? decodeProductId(device.productId as string)
574-
: null;
572+
const typeInfo = resolveDeviceType(device);
575573
return {
576574
uuid: device.uuid,
577575
label: device.label,
@@ -580,7 +578,7 @@ export class ToolExecutorService {
580578
locationId: device.locationId,
581579
groupId: device.groupId,
582580
features: device.features,
583-
...(decoded && { deviceType: decoded.deviceType, deviceTypeId: decoded.deviceTypeId }),
581+
...(typeInfo && { deviceType: typeInfo.deviceType, deviceTypeId: typeInfo.deviceTypeId }),
584582
};
585583
});
586584

@@ -800,13 +798,15 @@ export class ToolExecutorService {
800798
params.uuid,
801799
);
802800

803-
// Enrich with decoded product type info (keep full payload for detail view)
804-
const productInfo = device.productId
801+
// Enrich with device type from productInfos (primary) + full decode for brand/ownership
802+
const typeInfo = resolveDeviceType(device as Record<string, unknown>);
803+
const productDecoded = device.productId
805804
? decodeProductId(device.productId as string)
806805
: null;
807806
const enrichedDevice = {
808807
...device,
809-
...(productInfo && { deviceType: productInfo.deviceType, deviceTypeId: productInfo.deviceTypeId }),
808+
...(typeInfo && { deviceType: typeInfo.deviceType, deviceTypeId: typeInfo.deviceTypeId }),
809+
...(productDecoded && { brand: productDecoded.brand, ownership: productDecoded.ownership }),
810810
};
811811

812812
return {

0 commit comments

Comments
 (0)