Files
helios-evcs/apps/csms/src/ocpp/actions/boot-notification.ts
Timothy Yin 02a361488b feat(api): add stats chart endpoint for admin access with time series data
feat(dayjs): integrate dayjs for date handling and formatting across the application
refactor(routes): update date handling in id-tags, transactions, users, and dashboard routes to use dayjs
style(globals): improve CSS variable definitions for better readability and consistency
deps: add dayjs as a dependency for date manipulation
2026-03-11 21:34:21 +08:00

66 lines
2.2 KiB
TypeScript

import { useDrizzle } from '@/lib/db.js'
import dayjs from 'dayjs'
import { chargePoint } from '@/db/schema.js'
import type {
BootNotificationRequest,
BootNotificationResponse,
OcppConnectionContext,
} from '../types.ts'
const DEFAULT_HEARTBEAT_INTERVAL = 60
export async function handleBootNotification(
payload: BootNotificationRequest,
ctx: OcppConnectionContext,
): Promise<BootNotificationResponse> {
const db = useDrizzle()
const [cp] = await db
.insert(chargePoint)
.values({
id: crypto.randomUUID(),
chargePointIdentifier: ctx.chargePointIdentifier,
chargePointVendor: payload.chargePointVendor,
chargePointModel: payload.chargePointModel,
chargePointSerialNumber: payload.chargePointSerialNumber ?? null,
firmwareVersion: payload.firmwareVersion ?? null,
iccid: payload.iccid ?? null,
imsi: payload.imsi ?? null,
meterType: payload.meterType ?? null,
meterSerialNumber: payload.meterSerialNumber ?? null,
// New, unknown devices start as Pending — admin must manually accept them
registrationStatus: 'Pending',
heartbeatInterval: DEFAULT_HEARTBEAT_INTERVAL,
lastBootNotificationAt: dayjs().toDate(),
})
.onConflictDoUpdate({
target: chargePoint.chargePointIdentifier,
set: {
chargePointVendor: payload.chargePointVendor,
chargePointModel: payload.chargePointModel,
chargePointSerialNumber: payload.chargePointSerialNumber ?? null,
firmwareVersion: payload.firmwareVersion ?? null,
iccid: payload.iccid ?? null,
imsi: payload.imsi ?? null,
meterType: payload.meterType ?? null,
meterSerialNumber: payload.meterSerialNumber ?? null,
// Do NOT override registrationStatus — preserve whatever the admin set
heartbeatInterval: DEFAULT_HEARTBEAT_INTERVAL,
lastBootNotificationAt: dayjs().toDate(),
updatedAt: dayjs().toDate(),
},
})
.returning()
const status = cp.registrationStatus
ctx.isRegistered = status === 'Accepted'
console.log(`[OCPP] BootNotification ${ctx.chargePointIdentifier} status=${status}`)
return {
currentTime: dayjs().toISOString(),
interval: DEFAULT_HEARTBEAT_INTERVAL,
status,
}
}