255 lines
7.8 KiB
TypeScript
255 lines
7.8 KiB
TypeScript
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
|
||
),
|
||
})
|
||
)
|