Files
helios-evcs/apps/csms/src/db/ocpp-schema.ts

255 lines
7.8 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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
),
})
)