Skip to content

Commit

Permalink
Merge pull request #6 from shiv3/add/auto-metervalue-setting
Browse files Browse the repository at this point in the history
Add auto metervalue setting
  • Loading branch information
shiv3 authored Aug 26, 2024
2 parents 0b687b1 + e3bf140 commit 96defb2
Show file tree
Hide file tree
Showing 8 changed files with 199 additions and 33 deletions.
10 changes: 3 additions & 7 deletions src/components/Connector.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,8 @@ const Connector: React.FC<ConnectorProps> = ({id: connector_id, cp,idTag}) => {
useEffect(() => {
if (cp) {
cp.setConnectorStatusChangeCallback(connector_id, setConnectorStatus);
cp.setConnectorTransactionIDChangeCallback(
connector_id,
setCpTransactionID
);
cp.setConnectorTransactionIDChangeCallback(connector_id, setCpTransactionID);
cp.setConnectorMeterValueChangeCallback(connector_id, setMeterValue);
cp.setAvailabilityChangeCallback(connector_id, setAvailability);
}
}, []);
Expand Down Expand Up @@ -226,9 +224,7 @@ const ConnectorStatus: React.FC<{ status: string }> = ({status}) => {
return <span className={statusColor(status)}>{status}</span>;
};

const ConnectorAvailability: React.FC<{ availability: string }> = ({
availability,
}) => {
const ConnectorAvailability: React.FC<{ availability: string }> = ({availability,}) => {
const availabilityColor = (a: string) => {
switch (a) {
case ocpp.OCPPAvailability.Operative:
Expand Down
96 changes: 95 additions & 1 deletion src/components/Settings.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,20 @@
import React, {useState, useEffect} from "react";
import {configAtom} from "../store/store.ts";
import {useAtom} from "jotai/index";
import {DefaultBootNotification} from "../cp/OcppTypes.ts";

const Settings: React.FC = () => {
const [wsURL, setWsURL] = useState<string>("");
const [connectorNumber, setConnectorNumber] = useState<number>(2);
const [cpID, setCpID] = useState<string>("");
const [tagID, setTagID] = useState<string>("");
const [ocppVersion, setOcppVersion] = useState<string>("OCPP-1.6J");
const [autoMeterValueEnabled, setAutoMeterValueEnabled] = useState<boolean>(false);
const [autoMeterValueInterval, setAutoMeterValueInterval] = useState<number>(0);
const [autoMeterValue, setAutoMeterValue] = useState<number>(0);

const [experimental, setExperimental] = useState<string | null>(null);
const [bootNotification, setBootNotification] = useState<string | null>(JSON.stringify(DefaultBootNotification));
const [config, setConfig] = useAtom(configAtom);


Expand All @@ -19,7 +25,13 @@ const Settings: React.FC = () => {
setCpID(config.ChargePointID);
setTagID(config.tagID);
setOcppVersion(config.ocppVersion);

setAutoMeterValueEnabled(config.autoMeterValueSetting?.enabled);
setAutoMeterValueInterval(config.autoMeterValueSetting?.interval);
setAutoMeterValue(config.autoMeterValueSetting?.value);

setExperimental(config.Experimental ? JSON.stringify(config.Experimental) : null);
setBootNotification(config.BootNotification ? JSON.stringify(config.BootNotification) : null);
}
}, [config]);

Expand All @@ -31,7 +43,13 @@ const Settings: React.FC = () => {
ChargePointID: cpID,
tagID,
ocppVersion,
autoMeterValueSetting: {
enabled: autoMeterValueEnabled,
interval: autoMeterValueInterval,
value: autoMeterValue
},
Experimental: experimental !== "" ? experimental && JSON.parse(experimental) : null,
BootNotification: bootNotification !== "" ? bootNotification && JSON.parse(bootNotification) : null,
});
// navigate(`/${location.hash}`)
};
Expand Down Expand Up @@ -130,6 +148,45 @@ const Settings: React.FC = () => {
<option value="OCPP-1.6J">OCPP-1.6J</option>
</select>
</div>
<div className="mb-4">
<input
className="shadow border rounded w-fit py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline"
id="AutoMeterValue"
type="checkbox"
checked={autoMeterValueEnabled}
onChange={(e) => setAutoMeterValueEnabled(e.target.checked)}
/>
<label className="text-gray-700 text-sm font-bold ml-2" htmlFor="AutoMeterValue">
Auto Meter Value
</label>
{autoMeterValueEnabled && (
<div className="flex items-center">
<input
className="shadow appearance-none border rounded w-1/3 py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline"
id="AutoMeterValueInterval"
type="number"
value={autoMeterValueInterval}
onChange={(e) => setAutoMeterValueInterval(parseInt(e.target.value))}
placeholder="30"
style={{maxWidth: "20ch"}}
required
/>
<span className="text-gray-700 text-sm font-bold ml-2">seconds</span>

<input
className="shadow appearance-none border rounded w-1/3 py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline"
id="AutoMeterValue"
type="number"
value={autoMeterValue}
onChange={(e) => setAutoMeterValue(parseInt(e.target.value))}
placeholder="10"
style={{maxWidth: "20ch"}}
required
/>
<span className="text-gray-700 text-sm font-bold ml-2">kWh</span>
</div>
)}
</div>
<div className="mb-4">
<label
className="block text-gray-700 text-sm font-bold mb-2"
Expand All @@ -140,12 +197,49 @@ const Settings: React.FC = () => {
<textarea
className="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline"
id="Experimental"
placeholder="Experimental features"
placeholder="{
&quot;ChargePointIDs&quot;: [
{
&quot;ChargePointID&quot;: &quot;CP001&quot;,
&quot;ConnectorNumber&quot;: 1
}
],
&quot;TagIDs&quot;: [
&quot;123456&quot;
]
}"
style={{height: "100px"}}
value={experimental || ""}
onChange={(e) => setExperimental(e.target.value)
}></textarea>
</div>
<div className="mb-4">
<label
className="block text-gray-700 text-sm font-bold mb-2"
htmlFor="BootNotification"
>
Boot Notification
</label>
<textarea
className="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline"
id="BootNotification"
placeholder="{
&quot;ChargeBoxSerialNumber&quot;: &quot;123456&quot;,
&quot;ChargePointModel&quot;: &quot;Model 3&quot;,
&quot;ChargePointSerialNumber&quot;: &quot;123456&quot;,
&quot;ChargePointVendor&quot;: &quot;Vendor&quot;,
&quot;FirmwareVersion&quot;: &quot;1.0.0&quot;,
&quot;Iccid&quot;: &quot;123456&quot;,
&quot;Imsi&quot;: &quot;123456&quot;,
&quot;MeterSerialNumber&quot;: &quot;123456&quot;,
&quot;MeterType&quot;: &quot;Model 3&quot;
}"
style={{height: "100px"}}
value={bootNotification || ""}
onChange={(e) => setBootNotification(e.target.value)
}></textarea>
</div>

<div className="flex items-center justify-between">
<button
className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded focus:outline-none focus:shadow-outline"
Expand Down
16 changes: 11 additions & 5 deletions src/components/TopPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {ChargePoint as OCPPChargePoint} from "../cp/ChargePoint.ts";
// import {HiStatusOnline, HiStatusOffline} from "react-icons/hi";
import {useAtom} from 'jotai'
import {configAtom} from "../store/store.ts";
import {BootNotification, DefaultBootNotification} from "../cp/OcppTypes.ts";


const TopPage: React.FC = () => {
Expand All @@ -15,13 +16,14 @@ const TopPage: React.FC = () => {

useEffect(() => {
console.log(`Connector Number: ${config?.connectorNumber} WSURL: ${config?.wsURL} CPID: ${config?.ChargePointID} TagID: ${config?.tagID}`);

if (config?.Experimental === null) {
setConnectorNumber(config?.connectorNumber || 2);
setCps([NewChargePoint(connectorNumber, config.ChargePointID, config.wsURL)]);
setCps([
NewChargePoint(connectorNumber, config.ChargePointID, config.BootNotification ?? DefaultBootNotification, config.wsURL, config.autoMeterValueSetting)
]);
} else {
const cps = config?.Experimental?.ChargePointIDs.map((cp) =>
NewChargePoint(cp.ConnectorNumber, cp.ChargePointID, config.wsURL)
NewChargePoint(cp.ConnectorNumber, cp.ChargePointID, config.BootNotification ?? DefaultBootNotification, config.wsURL,config.autoMeterValueSetting)
)
setCps(cps ?? []);
const tagIDs = config?.Experimental?.TagIDs;
Expand Down Expand Up @@ -200,9 +202,13 @@ const ExperimentalView: React.FC<ExperimentalProps> = ({cps, tagIDs}) => {
}


const NewChargePoint = (ConnectorNumber: number, ChargePointID: string, WSURL: string,) => {
const NewChargePoint = (ConnectorNumber: number, ChargePointID: string, BootNotification: BootNotification, WSURL: string,
autoMeterValueSetting: {
interval: number;
value: number
} | null) => {
console.log(`Creating new ChargePoint with ID: ${ChargePointID} Connector Number: ${ConnectorNumber} WSURL: ${WSURL}`);
return new OCPPChargePoint(ChargePointID, ConnectorNumber, WSURL);
return new OCPPChargePoint(ChargePointID, BootNotification, ConnectorNumber, WSURL, autoMeterValueSetting);
}

export default TopPage;
39 changes: 36 additions & 3 deletions src/cp/ChargePoint.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,27 @@ import {Connector} from "./Connector";
import {OCPPWebSocket} from "./OCPPWebSocket";
import {OCPPMessageHandler} from "./OCPPMessageHandler";
import {Logger} from "./Logger";
import {OCPPStatus, OCPPAvailability} from "./OcppTypes";
import {OCPPStatus, OCPPAvailability, BootNotification} from "./OcppTypes";
import {Transaction} from "./Transaction.ts";
import * as ocpp from "./OcppTypes.ts";

export class ChargePoint {
private _id: string;
private _bootNotification: ocpp.BootNotification;
private _connectors: Map<number, Connector>;
private _webSocket: OCPPWebSocket;
private _messageHandler: OCPPMessageHandler;
private _logger: Logger;
private _autoMeterValueSetting: { interval: number; value: number } | null;

public _status: OCPPStatus = OCPPStatus.Unavailable;
private _error: string = "";
public _errorCallback: (error: string) => void = () => {
};

private _heartbeat: number | null = null;
private _autoMeterValueIntervals: Map<number, number> = new Map();

private _statusChangeCallback:
| ((status: string, message?: string) => void)
| null = null;
Expand All @@ -27,8 +31,10 @@ export class ChargePoint {
(availability: string) => void
> = new Map();

constructor(id: string, connectorCount: number, wsUrl: string) {
constructor(id: string, _bootNotification: BootNotification, connectorCount: number, wsUrl: string,
autoMeterValueSetting: { interval: number; value: number } | null) {
this._id = id;
this._bootNotification = _bootNotification;
this._connectors = new Map();
for (let i = 1; i <= connectorCount; i++) {
this._connectors.set(i, new Connector(i));
Expand All @@ -40,6 +46,7 @@ export class ChargePoint {
this._webSocket,
this._logger
);
this._autoMeterValueSetting = autoMeterValueSetting;
}

// Getters
Expand Down Expand Up @@ -101,6 +108,13 @@ export class ChargePoint {
this.connectors.get(connectorId)?.setStatusChangeCallbacks(callback);
}

setConnectorMeterValueChangeCallback(
connectorId: number,
callback: (meterValue: number) => void
): void {
this.connectors.get(connectorId)?.setMeterValueChangeCallbacks(callback);
}

setAvailabilityChangeCallback(
connectorId: number,
callback: (availability: string) => void
Expand All @@ -111,7 +125,7 @@ export class ChargePoint {
public connect(): void {
this._webSocket.connect(
() => {
this._messageHandler.sendBootNotification();
this._messageHandler.sendBootNotification(this._bootNotification);
this.status = OCPPStatus.Available;
this.updateAllConnectorsStatus(OCPPStatus.Available);
this.error = "";
Expand Down Expand Up @@ -161,6 +175,8 @@ export class ChargePoint {
connector.transaction = transaction;
this._messageHandler.startTransaction(transaction, connectorId);
this.updateConnectorStatus(connectorId, OCPPStatus.Preparing);
this._autoMeterValueSetting && this.startAutoMeterValue(connectorId, this._autoMeterValueSetting.interval, this._autoMeterValueSetting.value);

} else {
this._logger.error(`Connector ${connectorId} not found`);
}
Expand All @@ -176,6 +192,7 @@ export class ChargePoint {
connector.id
);
this.updateConnectorStatus(connector.id, OCPPStatus.Finishing);
this._autoMeterValueSetting && this.stopAutoMeterValue(connectorId);
} else {
this._logger.error(`Transaction for tag ${tagId} not found`);
}
Expand Down Expand Up @@ -222,6 +239,22 @@ export class ChargePoint {
}
}

public startAutoMeterValue(connectorId: number, intervalSec: number, value: number): void {
const intervalNum = setInterval(() => {
this.setMeterValue(connectorId, this.getConnector(connectorId)!.meterValue + value);
this.sendMeterValue(connectorId);
}, intervalSec * 1000);
this._autoMeterValueIntervals.set(connectorId, intervalNum);
}

public stopAutoMeterValue(connectorId: number): void {
const intervalNum = this._autoMeterValueIntervals.get(connectorId);
if (intervalNum) {
clearInterval(intervalNum);
this._autoMeterValueIntervals.delete(connectorId);
}
}

public getConnector(connectorId: number): Connector | undefined {
return this._connectors.get(connectorId);
}
Expand Down
21 changes: 15 additions & 6 deletions src/cp/Connector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ export class Connector {

private _transactionIDChangeCallbacks:
| ((transactionId: number | null) => void)[]
private _statusChangeCallbacks: ((status: ocpp.OCPPStatus) => void) | null;
private _statusChangeCallbacks: ((status: ocpp.OCPPStatus) => void)[];
private _meterValueChangeCallbacks: ((meterValue: number) => void)[];

constructor(id: number) {
this._id = id;
Expand All @@ -21,7 +22,8 @@ export class Connector {
this._transaction = null;

this._transactionIDChangeCallbacks = [];
this._statusChangeCallbacks = null;
this._statusChangeCallbacks = [];
this._meterValueChangeCallbacks = [];
}

get id(): number {
Expand All @@ -38,9 +40,9 @@ export class Connector {

set status(newStatus: ocpp.OCPPStatus) {
this._status = newStatus;
if (this._statusChangeCallbacks) {
this._statusChangeCallbacks(newStatus);
}
this._statusChangeCallbacks && this._statusChangeCallbacks.forEach((callback) => {
callback(newStatus);
})
}

get availability(): string {
Expand All @@ -57,6 +59,9 @@ export class Connector {

set meterValue(value: number) {
this._meterValue = value;
this._meterValueChangeCallbacks && this._meterValueChangeCallbacks.forEach((callback) => {
callback(value);
})
}

get transaction(): Transaction | null {
Expand Down Expand Up @@ -85,7 +90,11 @@ export class Connector {
}

public setStatusChangeCallbacks(callback: (status: ocpp.OCPPStatus) => void) {
this._statusChangeCallbacks = callback;
this._statusChangeCallbacks.push(callback);
}

public setMeterValueChangeCallbacks(callback: (meterValue: number) => void) {
this._meterValueChangeCallbacks.push(callback);
}

}
Loading

0 comments on commit 96defb2

Please sign in to comment.