feat(firmware): add OCPP schema and constants for charge point management

This commit is contained in:
2026-03-10 10:14:39 +08:00
parent 6014114098
commit 0f47b3d382
4 changed files with 279 additions and 3 deletions

View File

@@ -0,0 +1,254 @@
import {
pgTable,
timestamp,
varchar,
integer,
text,
index,
} from 'drizzle-orm/pg-core'
/**
* 充电桩表
* 对应OCPP 1.6-J BootNotification.req中的基本信息
*/
export const chargePoint = pgTable('charge_point', {
id: varchar('id').primaryKey(),
chargePointIdentifier: varchar('charge_point_identifier', {
length: 100,
})
.unique()
.notNull(),
chargePointSerialNumber: varchar('charge_point_serial_number', {
length: 25,
}),
chargePointModel: varchar('charge_point_model', { length: 20 }).notNull(),
chargePointVendor: varchar('charge_point_vendor', { length: 20 }).notNull(),
firmwareVersion: varchar('firmware_version', { length: 50 }),
iccid: varchar('iccid', { length: 20 }),
imsi: varchar('imsi', { length: 20 }),
meterSerialNumber: varchar('meter_serial_number', { length: 25 }),
meterType: varchar('meter_type', { length: 25 }),
createdAt: timestamp('created_at').notNull().defaultNow(),
updatedAt: timestamp('updated_at')
.notNull()
.defaultNow()
.$onUpdate(() => new Date()),
})
/**
* 连接器表
* OCPP 1.6-J 2.2术语定义:
* "Connector" 指充电桩上可独立操作和管理的电气插座。通常对应单个物理连接器,
* 但某些情况下一个插座可能有多个物理插座类型和/或拴住的电缆/连接器安排
* 以适应不同的车辆类型(如四轮电动汽车和电动滑板车)。
*
* 连接器ID规范
* - 第一个连接器的ID必须是1
* - 额外的连接器必须按顺序编号(不能跳过)
* - 连接器ID不能超过充电桩的总连接器数
* - ID为0保留用于主控制器在报告时或整个充电桩在中央系统的操作时
*/
export const connector = pgTable(
'connector',
{
id: varchar('id').primaryKey(),
chargePointId: varchar('charge_point_id')
.notNull()
.references(() => chargePoint.id, { onDelete: 'cascade' }),
/**
* 连接器编号connectorId
* OCPP 1.6-J 6.47 StatusNotification.req
* "The id of the connector for which the status is reported.
* Id '0' (zero) is used if the status is for the Charge Point main controller."
* connectorId > 0 对实际连接器, connectorId = 0 表示主控制器
*/
connectorId: integer('connector_id').notNull(),
/**
* 当前状态status字段
* OCPP 1.6-J 7.7 ChargePointStatus
* - Available: 连接器可用于新用户
* - Preparing: 用户提示卡、插入电缆或车辆占用停泊位时
* - Charging: 接触器闭合,允许车辆充电
* - SuspendedEVSE: EV连接但EVSE不提供能量
* - SuspendedEV: EVSE提供能量但EV不取用
* - Finishing: 交易已停止但连接器未准备好新用户
* - Reserved: 连接器因ReserveNow命令被保留
* - Unavailable: 因ChangeAvailability命令不可用非运行态
* - Faulted: 充电桩或连接器报告错误且不可用(非运行态)
*/
status: varchar('status', {
enum: [
'Available',
'Preparing',
'Charging',
'SuspendedEVSE',
'SuspendedEV',
'Finishing',
'Reserved',
'Unavailable',
'Faulted',
],
}).notNull(),
/**
* 错误代码errorCode字段
* OCPP 1.6-J 7.6 ChargePointErrorCode
*/
errorCode: varchar('error_code', {
enum: [
'NoError',
'ConnectorLockFailure',
'EVCommunicationError',
'GroundFailure',
'HighTemperature',
'InternalError',
'LocalListConflict',
'OtherError',
'OverCurrentFailure',
'OverVoltage',
'PowerMeterFailure',
'PowerSwitchFailure',
'ReaderFailure',
'ResetFailure',
'UnderVoltage',
'WeakSignal',
],
})
.notNull()
.default('NoError'),
/**
* 供应商标识vendorId字段
* OCPP 1.6-J 6.47: "This identifies the vendor-specific implementation."
* CiString255Type - 不超过255个字符
*/
vendorId: varchar('vendor_id', { length: 255 }),
/**
* 供应商特定错误代码vendorErrorCode字段
* OCPP 1.6-J 6.47: "This contains the vendor-specific error code."
* CiString50Type - 不超过50个字符
*/
vendorErrorCode: varchar('vendor_error_code', { length: 50 }),
/**
* 附加信息info字段
* OCPP 1.6-J 6.47: "Additional free format information related to the error."
* CiString50Type - 不超过50个字符
*/
info: varchar('info', { length: 50 }),
/**
* 最后一次状态更新时间
* OCPP 1.6-J 6.47: "The time for which the status is reported.
* If absent time of receipt of the message will be assumed."
*/
lastStatusUpdate: timestamp('last_status_update').notNull().defaultNow(),
createdAt: timestamp('created_at').notNull().defaultNow(),
updatedAt: timestamp('updated_at')
.notNull()
.defaultNow()
.$onUpdate(() => new Date()),
},
(table) => ({
chargePointIdIdx: index('idx_connector_charge_point_id').on(
table.chargePointId
),
connectorIdIdx: index('idx_connector_connector_id').on(
table.chargePointId,
table.connectorId
),
})
)
/**
* 连接器状态历史表
* 记录StatusNotification.req的完整消息内容用于审计和历史查询
* 对应 OCPP 1.6-J 6.47 StatusNotification.req 消息
*/
export const connectorStatusHistory = pgTable(
'connector_status_history',
{
id: varchar('id').primaryKey(),
connectorId: varchar('connector_id')
.notNull()
.references(() => connector.id, { onDelete: 'cascade' }),
/**
* 连接器编号connectorId
* OCPP 1.6-J 6.47: connectorId >= 0
*/
connectorNumber: integer('connector_number').notNull(),
/**
* 状态值
* OCPP 1.6-J 7.7 ChargePointStatus
*/
status: varchar('status', {
enum: [
'Available',
'Preparing',
'Charging',
'SuspendedEVSE',
'SuspendedEV',
'Finishing',
'Reserved',
'Unavailable',
'Faulted',
],
}).notNull(),
/**
* 错误代码
* OCPP 1.6-J 7.6 ChargePointErrorCode
*/
errorCode: varchar('error_code', {
enum: [
'NoError',
'ConnectorLockFailure',
'EVCommunicationError',
'GroundFailure',
'HighTemperature',
'InternalError',
'LocalListConflict',
'OtherError',
'OverCurrentFailure',
'OverVoltage',
'PowerMeterFailure',
'PowerSwitchFailure',
'ReaderFailure',
'ResetFailure',
'UnderVoltage',
'WeakSignal',
],
}).notNull(),
/**
* 附加信息
* OCPP 1.6-J 6.47: "Additional free format information related to the error."
*/
info: varchar('info', { length: 50 }),
/**
* 供应商标识
* OCPP 1.6-J 6.47: "This identifies the vendor-specific implementation."
*/
vendorId: varchar('vendor_id', { length: 255 }),
/**
* 供应商错误代码
* OCPP 1.6-J 6.47: "This contains the vendor-specific error code."
*/
vendorErrorCode: varchar('vendor_error_code', { length: 50 }),
/**
* 状态报告时间戳
* OCPP 1.6-J 6.47: "The time for which the status is reported.
* If absent time of receipt of the message will be assumed."
*/
statusTimestamp: timestamp('status_timestamp'),
/**
* 消息接收时间
*/
receivedAt: timestamp('received_at').notNull().defaultNow(),
},
(table) => ({
connectorIdIdx: index('idx_status_history_connector_id').on(
table.connectorId
),
statusTimestampIdx: index('idx_status_history_timestamp').on(
table.statusTimestamp
),
receivedAtIdx: index('idx_status_history_received_at').on(
table.receivedAt
),
})
)