diff --git a/src/domain/battery.test.ts b/src/domain/battery.test.ts index a92d0da..fe8b770 100644 --- a/src/domain/battery.test.ts +++ b/src/domain/battery.test.ts @@ -56,6 +56,20 @@ describe('battery domain', () => { expect(response.items[0]?.createTime).toBe('2026-05-10T23:00:00.000Z') }) + test('keeps explicit window summaries for limited history slices', () => { + const now = new Date('2026-05-11T00:00:00.000Z') + const items = rows.map(toBatteryInfo) + const response = createBatteriesResponse(items, now, { + total: items.length, + lowPower: 1, + charging: 1, + }) + + expect(response.total).toBe(2) + expect(response.lowPower).toBe(1) + expect(response.charging).toBe(1) + }) + test('creates dashboard aggregate shape without using power as fake SOH', () => { const now = new Date('2026-05-11T00:00:00.000Z') const snapshot = createDashboardSnapshot(rows.map(toBatteryInfo), now) diff --git a/src/server/api/routers/battery.router.ts b/src/server/api/routers/battery.router.ts index d12f57e..f1c7625 100644 --- a/src/server/api/routers/battery.router.ts +++ b/src/server/api/routers/battery.router.ts @@ -1,4 +1,4 @@ -import { createBatteriesResponse, createDashboardSnapshot } from '@/domain/battery' +import { createBatteriesResponse, createDashboardSnapshot, POWER_STATUS } from '@/domain/battery' import { os } from '@/server/api/server' import { getBatteryHistory, @@ -63,5 +63,10 @@ export const batteries = os.battery.batteries.handler(async ({ input }) => { export const history = os.battery.history.handler(async ({ input }) => { const items = await getBatteryHistory(input.mac) - return createBatteriesResponse(items) + // History returns a limited window, so the counters must describe only this returned slice. + return createBatteriesResponse(items, new Date(), { + total: items.length, + lowPower: items.filter((item) => item.isLowPower).length, + charging: items.filter((item) => item.powerStatus === POWER_STATUS.CHARGING).length, + }) }) diff --git a/src/server/battery/mysql.ts b/src/server/battery/mysql.ts index 88eddd7..ec9cb6f 100644 --- a/src/server/battery/mysql.ts +++ b/src/server/battery/mysql.ts @@ -15,8 +15,6 @@ import { env } from '@/env' const historyLimit = 500 const predictionHistoryLimit = 10 -const dashboardLatestLimit = 100 - type BatteryInfoMysqlRow = RowDataPacket & BatteryInfoSourceRow type CountMysqlRow = RowDataPacket & { total: number @@ -314,16 +312,19 @@ export async function getLatestBatteryPage(input: LatestBatteryPageInput): Promi } } -export async function getLatestBatteryPerDevice(limit = dashboardLatestLimit): Promise { +export async function getLatestBatteryPerDevice(limit?: number): Promise { + const appliedLimit = typeof limit === 'number' && limit > 0 ? limit : undefined + const limitSql = appliedLimit ? '\n LIMIT :limit' : '' + const queryParams = appliedLimit ? { limit: appliedLimit } : {} + const [rows] = await getBatteryPool().query( ` SELECT ${sourceColumns} FROM ls_battery_info AS current_record WHERE ${latestRecordPredicate} - ORDER BY current_record.create_time DESC, current_record.id DESC - LIMIT :limit + ORDER BY current_record.create_time DESC, current_record.id DESC${limitSql} `, - { limit: Math.min(Math.max(limit, 1), dashboardLatestLimit) }, + queryParams, ) return rows.map(toBatteryInfo)