From 057e5674c5d247740a9c80c25ece51506a2314f2 Mon Sep 17 00:00:00 2001 From: Nasar Eddaoui Date: Sun, 5 May 2024 22:26:03 +0700 Subject: [PATCH 1/2] start charging implemented --- app/components/WebSocket.tsx | 12 +-- app/components/button.tsx | 18 ++++ app/components/evse.tsx | 38 ++++++--- app/components/input.tsx | 8 +- app/components/status.notification.tsx | 4 +- app/components/transaction.tsx | 82 +++++++++++++++++++ .../ocpp/charging/start.transaction.model.ts | 52 ++++++++++++ .../ocpp/charging/start.transaction.ts | 61 ++++++++++++++ ...on.model.ts => boot.notification.model.ts} | 0 ...otnotification.ts => boot.notification.ts} | 6 +- ...otificiation.ts => status.notification.ts} | 0 .../status-notification/statusnotification.ts | 2 +- app/service/ocpp/connector.ts | 2 +- app/service/ocpp/ocpp.handler.ts | 2 +- 14 files changed, 259 insertions(+), 28 deletions(-) create mode 100644 app/components/button.tsx create mode 100644 app/components/transaction.tsx create mode 100644 app/service/ocpp/charging/start.transaction.model.ts create mode 100644 app/service/ocpp/charging/start.transaction.ts rename app/service/ocpp/command/boot-notification/{bootnotification.model.ts => boot.notification.model.ts} (100%) rename app/service/ocpp/command/boot-notification/{bootnotification.ts => boot.notification.ts} (96%) rename app/service/ocpp/command/status-notification/{status.notificiation.ts => status.notification.ts} (100%) diff --git a/app/components/WebSocket.tsx b/app/components/WebSocket.tsx index 1f4965d..cf808e6 100644 --- a/app/components/WebSocket.tsx +++ b/app/components/WebSocket.tsx @@ -7,6 +7,7 @@ import { OnMessageEvent, } from '../service/websocket/websocket.model'; import WebSocketHook from '../hook/socketHook'; +import Button from './button'; type Url = { url: string; @@ -35,12 +36,11 @@ export default function WebSocket({ return (
- +
); } diff --git a/app/components/button.tsx b/app/components/button.tsx new file mode 100644 index 0000000..8230fb4 --- /dev/null +++ b/app/components/button.tsx @@ -0,0 +1,18 @@ +type button = { + text: string; + disabled: boolean; + onClick: () => void; +}; + +export default function Button({ text, disabled, onClick }: button) { + const disable = disabled ? 'bg-gray-400' : ''; + return ( + + ); +} diff --git a/app/components/evse.tsx b/app/components/evse.tsx index de07031..1b46b2f 100644 --- a/app/components/evse.tsx +++ b/app/components/evse.tsx @@ -6,13 +6,14 @@ import { ConState, IWriter } from '../service/websocket/websocket.model'; import WebSocket from './WebSocket'; import { ChargingSocket, IChargingSocket } from '../service/ocpp/connector'; import { HandleOcpp } from '../service/ocpp/ocpp.handler'; -import { SendBootNotification } from '../service/ocpp/command/boot-notification/bootnotification'; +import { SendBootNotification } from '../service/ocpp/command/boot-notification/boot.notification'; import StatusNotificationUI from './status.notification'; import { ChargePointErrorCodes, StatusNotification, -} from '../service/ocpp/command/status-notification/status.notificiation'; +} from '../service/ocpp/command/status-notification/status.notification'; import { SendStatusNotification } from '../service/ocpp/command/status-notification/statusnotification'; +import Transaction from './transaction'; const defaultValue = 'ws://localhost:8080/ocpp/JwNpTpPxPm/CHR202305102'; @@ -55,14 +56,31 @@ export default function Evse() { return (
- - - +
+ + + +
+ +
+ +
); } diff --git a/app/components/input.tsx b/app/components/input.tsx index 24b9a67..5de9dac 100644 --- a/app/components/input.tsx +++ b/app/components/input.tsx @@ -3,22 +3,26 @@ import { SyntheticEvent } from 'react'; type InputEvent = (event: SyntheticEvent) => void; type input = { + title: string; name: string; value: string; + placeholder: string; disabled: boolean; onChange: InputEvent; }; export default function Input({ + title, name, value, + placeholder, disabled, onChange, }: input): JSX.Element { return (
diff --git a/app/components/status.notification.tsx b/app/components/status.notification.tsx index 224a5d4..9a46b19 100644 --- a/app/components/status.notification.tsx +++ b/app/components/status.notification.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import { StatusNotification } from '../service/ocpp/command/status-notification/status.notificiation'; +import { StatusNotification } from '../service/ocpp/command/status-notification/status.notification'; import { ChangeState } from '../service/ocpp/ocpp.handler'; import Select, { Item, ReturnValue } from './select'; @@ -20,8 +20,6 @@ export default function StatusNotificationUI({ const onChange = (value: ReturnValue) => changeState(value as StatusNotification); - console.log(state); - return (
state: {state} diff --git a/app/components/transaction.tsx b/app/components/transaction.tsx new file mode 100644 index 0000000..382c55d --- /dev/null +++ b/app/components/transaction.tsx @@ -0,0 +1,82 @@ +import React, { SyntheticEvent, useState } from 'react'; +import { SendStartTransaction } from '../service/ocpp/charging/start.transaction'; +import Input from './input'; +import Button from './button'; +import { IWriter } from '../service/websocket/websocket.model'; +import { StatusNotification } from '../service/ocpp/command/status-notification/status.notification'; +import { IChargingSession } from '../service/ocpp/charging/start.transaction.model'; + +type transaction = { + writer: IWriter; + connectorId: number; + state: StatusNotification; +}; + +export default function Transaction({ + writer, + connectorId, + state, +}: transaction): React.JSX.Element { + const [idTag, setIdTag] = useState('cli013322'); + const onChange = (ev: SyntheticEvent) => { + setIdTag(ev.currentTarget.value); + }; + + const notConnected = () => { + if (writer == null) { + alert('Please connect to CSMS'); + } + }; + + const onStart = () => { + if (writer == null) { + notConnected(); + return; + } + + if ( + state == StatusNotification.AVAILABLE || + state == StatusNotification.PREPARING + ) { + if (idTag.trim() == '') return; + SendStartTransaction(writer, connectorId, idTag); + return; + } + + alert( + 'Please make sure that the charger is in Available or preparing state' + ); + }; + + const onStop = () => { + if (writer == null) { + notConnected(); + return; + } + }; + + return ( +
+ +
+
+
+ ); +} diff --git a/app/service/ocpp/charging/start.transaction.model.ts b/app/service/ocpp/charging/start.transaction.model.ts new file mode 100644 index 0000000..455bf3a --- /dev/null +++ b/app/service/ocpp/charging/start.transaction.model.ts @@ -0,0 +1,52 @@ +import { Min } from 'class-validator'; + +enum AuthorizationStatus { + ACCEPTED = 'Accepted', + BLOCKED = 'Blocked', + EXPIRED = 'Expired', + INVALID = 'Invalid', + CONCURRENT_TX = 'ConcurrentTx', +} + +interface IIdTagInfo { + expiryDate: Date; + parentIdTag: string; + status: string; +} + +interface IStartTransactionRes { + idTagInfo: IIdTagInfo; + transactionId: number; +} + +interface IStartTransaction { + connectorId: number; + idTag: string; + meterStart: number; + timestamp: Date; +} + +interface IChargingSession { + idTag: string; + transactionId: number; + connectorId: number; +} + +class StartTransactionsRes implements IStartTransactionRes { + idTagInfo: IIdTagInfo = { + expiryDate: new Date(), + status: AuthorizationStatus.BLOCKED, + parentIdTag: '', + }; + + @Min(0) + transactionId: number = 0; +} + +export type { + IIdTagInfo, + IStartTransaction, + IStartTransactionRes, + IChargingSession, +}; +export { AuthorizationStatus, StartTransactionsRes }; diff --git a/app/service/ocpp/charging/start.transaction.ts b/app/service/ocpp/charging/start.transaction.ts new file mode 100644 index 0000000..82de7ae --- /dev/null +++ b/app/service/ocpp/charging/start.transaction.ts @@ -0,0 +1,61 @@ +import Validate from '@/app/helper/validation.helper'; +import { IWriter } from '../../websocket/websocket.model'; +import { BootNotificationRes } from '../command/boot-notification/boot.notification.model'; +import { Action, CreateRequestFrame, GetRequestFrame } from '../ocpp.action'; +import { CreateError, ErrorCode } from '../ocpp.error'; +import { IResponse } from '../ocpp.frame'; +import { ChangeState } from '../ocpp.handler'; +import { CreateTransaction } from '../transaction/transaction.handler'; +import { + AuthorizationStatus, + IChargingSession, + IStartTransaction, + StartTransactionsRes, +} from './start.transaction.model'; +import { StatusNotification } from '../command/status-notification/status.notification'; + +let session: IChargingSession; + +function SendStartTransaction( + w: IWriter, + connectorId: number, + idTag: string +): void { + const transaction: IStartTransaction = { + connectorId, + idTag, + meterStart: 0, + timestamp: new Date(), + }; + + const frame = CreateRequestFrame(Action.START_TRANSACTION, transaction); + w.Write(frame); + CreateTransaction(GetRequestFrame(frame), StartTransaction); + session = { connectorId, idTag, transactionId: -1 }; +} + +function StartTransaction( + w: IWriter, + frame: IResponse, + changeState: ChangeState +): IChargingSession | undefined { + const [result, validation] = Validate( + StartTransactionsRes, + frame.payload + ); + + if (validation.length > 0) { + w.Write(CreateError(ErrorCode.PropertyConstraintViolation, validation)); + return; + } + + if (result.idTagInfo.status != AuthorizationStatus.ACCEPTED) { + return; + } + + changeState(StatusNotification.CHARGING); + session.transactionId = result.transactionId; + return session; +} + +export { SendStartTransaction, StartTransaction }; diff --git a/app/service/ocpp/command/boot-notification/bootnotification.model.ts b/app/service/ocpp/command/boot-notification/boot.notification.model.ts similarity index 100% rename from app/service/ocpp/command/boot-notification/bootnotification.model.ts rename to app/service/ocpp/command/boot-notification/boot.notification.model.ts diff --git a/app/service/ocpp/command/boot-notification/bootnotification.ts b/app/service/ocpp/command/boot-notification/boot.notification.ts similarity index 96% rename from app/service/ocpp/command/boot-notification/bootnotification.ts rename to app/service/ocpp/command/boot-notification/boot.notification.ts index 566ead1..ef09d93 100644 --- a/app/service/ocpp/command/boot-notification/bootnotification.ts +++ b/app/service/ocpp/command/boot-notification/boot.notification.ts @@ -6,10 +6,10 @@ import { BootNotificationRes, IBootNotification, Status, -} from './bootnotification.model'; +} from './boot.notification.model'; import { CreateError, ErrorCode } from '../../ocpp.error'; import Validate from '@/app/helper/validation.helper'; -import { StatusNotification } from '../status-notification/status.notificiation'; +import { StatusNotification } from '../status-notification/status.notification'; import { ChangeState } from '../../ocpp.handler'; const defaultValue: IBootNotification = { @@ -60,8 +60,6 @@ function BootNotification( frame.payload ); - console.log(validation); - if (validation.length > 0) { w.Write(CreateError(ErrorCode.PropertyConstraintViolation, validation)); return retry(w); diff --git a/app/service/ocpp/command/status-notification/status.notificiation.ts b/app/service/ocpp/command/status-notification/status.notification.ts similarity index 100% rename from app/service/ocpp/command/status-notification/status.notificiation.ts rename to app/service/ocpp/command/status-notification/status.notification.ts diff --git a/app/service/ocpp/command/status-notification/statusnotification.ts b/app/service/ocpp/command/status-notification/statusnotification.ts index 885dc33..8525a05 100644 --- a/app/service/ocpp/command/status-notification/statusnotification.ts +++ b/app/service/ocpp/command/status-notification/statusnotification.ts @@ -5,7 +5,7 @@ import { ChargePointErrorCodes, IStatusNotification, StatusNotification, -} from './status.notificiation'; +} from './status.notification'; function SendStatusNotification( w: IWriter, diff --git a/app/service/ocpp/connector.ts b/app/service/ocpp/connector.ts index 9b4e5fc..285adb6 100644 --- a/app/service/ocpp/connector.ts +++ b/app/service/ocpp/connector.ts @@ -1,4 +1,4 @@ -import { StatusNotification } from './command/status-notification/status.notificiation'; +import { StatusNotification } from './command/status-notification/status.notification'; interface IChargingSocket { State: StatusNotification; diff --git a/app/service/ocpp/ocpp.handler.ts b/app/service/ocpp/ocpp.handler.ts index dd77580..d4dd2ac 100644 --- a/app/service/ocpp/ocpp.handler.ts +++ b/app/service/ocpp/ocpp.handler.ts @@ -11,7 +11,7 @@ import { import { ChargePointErrorCodes, StatusNotification, -} from './command/status-notification/status.notificiation'; +} from './command/status-notification/status.notification'; import { FindTransaction } from './transaction/transaction.handler'; type OCPPData = IRequest | IResponse | IErrorFrame; From bcbaf85db2cc9074b7e88497ffe4d28dea475a0b Mon Sep 17 00:00:00 2001 From: Nasar Eddaoui Date: Sun, 5 May 2024 22:28:17 +0700 Subject: [PATCH 2/2] fix build issues --- app/components/transaction.tsx | 1 - app/service/ocpp/charging/start.transaction.ts | 1 - 2 files changed, 2 deletions(-) diff --git a/app/components/transaction.tsx b/app/components/transaction.tsx index 382c55d..4627247 100644 --- a/app/components/transaction.tsx +++ b/app/components/transaction.tsx @@ -4,7 +4,6 @@ import Input from './input'; import Button from './button'; import { IWriter } from '../service/websocket/websocket.model'; import { StatusNotification } from '../service/ocpp/command/status-notification/status.notification'; -import { IChargingSession } from '../service/ocpp/charging/start.transaction.model'; type transaction = { writer: IWriter; diff --git a/app/service/ocpp/charging/start.transaction.ts b/app/service/ocpp/charging/start.transaction.ts index 82de7ae..3044e5e 100644 --- a/app/service/ocpp/charging/start.transaction.ts +++ b/app/service/ocpp/charging/start.transaction.ts @@ -1,6 +1,5 @@ import Validate from '@/app/helper/validation.helper'; import { IWriter } from '../../websocket/websocket.model'; -import { BootNotificationRes } from '../command/boot-notification/boot.notification.model'; import { Action, CreateRequestFrame, GetRequestFrame } from '../ocpp.action'; import { CreateError, ErrorCode } from '../ocpp.error'; import { IResponse } from '../ocpp.frame';