This commit is contained in:
nutchayut
2024-05-31 00:38:31 +07:00
commit 88ddddd7c2
234 changed files with 37557 additions and 0 deletions

7
Simulators/ReadMe.txt Normal file
View File

@@ -0,0 +1,7 @@
Both simulators are from GitHub:
https://github.com/victormunoz/OCPP-1.6-Chargebox-Simulator
https://github.com/JavaIsJavaScript/OCPP-2.0-CP-Simulator
They needed some bugfixes and extensions.

950
Simulators/cp20_mod.html Normal file
View File

@@ -0,0 +1,950 @@
<html>
<head>
<title>ChargePoint Simulator</title>
<style>
body {
background: #000;
color: white;
}
button,
input,
select {
display: block;
width: 100%;
margin-bottom: 5px;
cursor: pointer;
}
button {
background: #369;
color: #fff;
padding: 5px 0;
border: none;
}
ul {
background: #000;
color: #eee;
}
li {}
#red,
#green,
#blue {
min-width: 10px;
}
#red {
background-color: red;
}
#green {
background-color: green;
}
#blue {
background-color: blue;
}
#yellow {
background-color: yellow;
}
table,
th,
tr,
td {
border: 1px solid white;
}
table {
margin: auto;
}
form {
padding-top: 20px;
}
.center {
text-align: center;
}
</style>
</head>
<body>
<select>
<option value="">
OCPP-J2.0
</option>
</select>
<input id="CP" type="text" placeholder="ChargePoint ID" value="ws://localhost:8081/OCPP/TestAAA" />
<button id="connect">Connect</button>
<button id="send">Authorize</button>
<button id="start">Start Transaction - EVDetected</button>
<button id="update">Update Transaction - EVDetected</button>
<button id="update_suspendedevse">Update Transaction - SuspendedEVSE</button>
<button id="update_suspendedev">Update Transaction - SuspendedEV</button>
<button id="update_charging">Update Transaction - Charging</button>
<button id="stop">Stop Transaction</button>
<button id="heartbeat">Heartbeat</button>
<button id="mv">Meter Values</button>
<button id="status">Status Notification</button>
<button id="data_transfer">Data Tranfer</button>
<button id="firmwarestatus">Firmware Status Notification</button>
<button id="clearedChargingLimit">Cleared Charging Limit</button>
<button id="logstatus_uploading">LogStatus Notification - Uploading</button>
<button id="logstatus_uploaded">LogStatus Notification - Uploaded</button>
<button id="notify_charging_limit">Notify Charging Limit - 10 A</button>
<button id="notify_ev_charging_schedule">Notify EV Charging Schedule - 10 A</button>
<div>
<span class="indicator" id="red">____</span>
<span class="indicator" id="green">____</span>
<span class="indicator" id="blue">____</span>
<span class="indicator" id="yellow">____</span>
</div>
<ul id="console"></ul>
<script src="https://code.jquery.com/jquery-3.3.1.min.js" integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=" crossorigin="anonymous"></script>
<script>
$('.indicator').hide();
$('#red').show();
function formatDate(date) {
var day = String(date.getUTCDate());
if (day.length < 2) {
day = ('0' + day.slice(-2));
}
var monthIndex = String(date.getUTCMonth() + 1);
if (monthIndex.length < 2) {
monthIndex = ('0' + monthIndex.slice(-2));
}
var year = date.getUTCFullYear();
var h = String(date.getUTCHours());
var m = String(date.getUTCMinutes());
var s = String(date.getUTCSeconds());
if (h.length < 2) {
h = ('0' + h.slice(-2));
}
if (m.length < 2) {
m = ('0' + m.slice(-2));
}
if (s.length < 2) {
s = ('0' + s.slice(-2));
}
return year + '-' + monthIndex + '-' + day + "T" + h + ":" + m + ":" + s + "Z";
}
var c = 0;
var start_id = "";
var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
var id = randonId();
var lastTranId;
var _websocket = null;
var connector_locked = false;
function randonId() {
id = "";
for (var i = 0; i < 36; i++) {
id += possible.charAt(Math.floor(Math.random() * possible.length));
}
return id;
}
function guid() {
function s4() {
return Math.floor((1 + Math.random()) * 0x10000)
.toString(16)
.substring(1);
}
return s4() + s4() + '-' + s4() + '-' + s4() + '-' + s4() + '-' + s4() + s4() + s4();
}
function wsConnect() {
var wsurl = $('select').val();
var CP = $('#CP').val();
if (_websocket) {
$('#red').show();
_websocket.close(3001);
} else {
_websocket = new WebSocket(wsurl + "" + CP, ["ocpp2.0", "ocpp1.5"]);
_websocket.onopen = function(authorizationData) {
sessionStorage.setItem('LastAction', "BootNotification");
$('#yellow').show();
BootNotification();
$('#connect').text('Disconnect').css('background', 'green');
};
_websocket.onmessage = function(msg) {
c++;
var ddata = (JSON.parse(msg.data));
if (c == 1) {
var hb_interval = handleData(ddata);
sessionStorage.setItem("Confriguration", hb_interval);
startHB(hb_interval * 1000);
}
if (ddata[0] === 3) {
la = getLastAction();
if (la == "startTransaction") {
ddata = ddata[2];
logMsg("Data exchange successful!");
var array = $.map(ddata, function(value, index) {
return [value];
});
var TransactionId = (array[0]);
sessionStorage.setItem('TransactionId', TransactionId);
}
logMsg("Response recieved successfully!");
} else if ((JSON.parse(msg.data))[0] === 4) {
logMsg("Data exchange failed - JSON is not accepted!");
} else if ((JSON.parse(msg.data))[0] === 2) {
logMsg((JSON.parse(msg.data))[2]);
id = (JSON.parse(msg.data))[1];
switch (ddata[2]) {
case "ChangeAvailability":
var changeAvail = JSON.stringify([3, id, {
"status": "Accepted"
}]);
_websocket.send(changeAvail);
break;
case "SetVariables":
var setVar = JSON.stringify([3, id, {
"setVariableResult": [{
"attributeStatus": "Accepted",
"component": {
"name": "AuthCtrlr"
},
"variable": {
"name": "variable name"
}
}]
}]);
_websocket.send(setVar);
break;
case "ClearCache":
var clearCache = JSON.stringify([3, id, {
"status": "Accepted"
}]);
_websocket.send(clearCache);
break;
case "GetLog":
var getLog = JSON.stringify([3, id, {
"status": "Accepted",
"filename": "somefile.txt"
}]);
_websocket.send(getLog);
break;
case "RequestStartTransaction":
var reqStartTrans = JSON.stringify([3, id, {
"status": "Accepted"
}]);
_websocket.send(reqStartTrans);
startTransaction();
break;
case "RequestStopTransaction":
var reqStopTrans = JSON.stringify([3, id, {
"status": "Accepted"
}]);
_websocket.send(reqStopTrans);
var stop_id = (JSON.parse(msg.data)[3].transactionId);
stopTransaction(stop_id);
break;
case "Reset":
var ResetS = JSON.stringify([3, id, {
"status": "Accepted"
}]);
_websocket.send(ResetS);
//location.reload();
break;
case "UnlockConnector":
var unlockCon = JSON.stringify([3, id, {
"status": "Unlocked"
}]);
_websocket.send(unlockCon);
connector_locked = false;
$('.indicator').hide();
$('#yellow').show();
logMsg("Connector status changed to: " + connector_locked);
statusNotification();
break;
case "UpdateFirmware":
var updFirm = JSON.stringify([3, id, {
"status": "Accepted"
}]);
_websocket.send(updFirm);
break;
case "ReserveNow":
var resNow = JSON.stringify([3, id, {
"status": "Accepted"
}]);
_websocket.send(resNow);
break;
case "CancelReservation":
var cancelRes = JSON.stringify([3, id, {
"status": "Accepted"
}]);
_websocket.send(cancelRes);
break;
case "DataTransfer":
var dataTrans = JSON.stringify([3, id, {
"status": "Accepted",
"data": "some data"
}]);
_websocket.send(dataTrans);
break;
case "GetVariables":
var getVars = JSON.stringify([3, id, {
"getVariableResult": [{
"attributeStatus": "Accepted",
"attributeValue": "true",
"variable": {
"name": "SampledDataAvailable"
},
"component": {
"name": "DeviceDataCtrlr"
}
}, {
"attributeStatus": "Accepted",
"attributeValue": "360",
"variable": {
"name": "AlignedDataInterval"
},
"component": {
"name": "DeviceDataCtrlr"
}
}, {
"attributeStatus": "UnknownVariable",
"attributeValue": "10",
"variable": {
"name": "RestartDelay"
},
"component": {
"name": "DeviceDataCtrlr"
}
}]
}]);
_websocket.send(getVars);
break;
case "GetLocalListVersion":
var gLocList = JSON.stringify([3, id, {
"versionNumber": 0
}]);
_websocket.send(gLocList);
break;
case "SendLocalList":
var sendLocList = JSON.stringify([3, id, {
"status": "Accepted"
}]);
_websocket.send(sendLocList);
break;
case "TriggerMessage":
var triggerMsg = JSON.stringify([3, id, {
"status": "Accepted"
}]);
_websocket.send(triggerMsg);
var req_message = (JSON.parse(msg.data)[3].requestedMessage);
if (req_message == "BootNotification") {
BootNotification();
}
if (req_message == "LogStatusNotification") {}
if (req_message == "FirmwareStatusNotification") {
FirmwareStatusNotification();
}
if (req_message == "Heartbeat") {
send_heartbeat();
}
if (req_message == "MeterValues") {
meterValues();
}
if (req_message == "SignChargingStationCertificate") {}
if (req_message == "SignV2GCertificate") {}
if (req_message == "StatusNotification") {
statusNotification();
}
if (req_message == "TransactionEvent") {}
break;
case "GetCompositeSchedule":
var getComp = JSON.stringify([3, id, {
"status": 'Accepted',
"evseId": 0,
"schedule": {
"startDateTime": formatDate(new Date()),
"chargingSchedule": {
"duration": 86400,
"chargingRateUnit": "W",
"chargingSchedulePeriod": [{
"startPeriod": 0,
"limit": 11000,
"numberPhases": 3
}, {
"startPeriod": 28800,
"limit": 6000,
"numberPhases": 3
}, {
"startPeriod": 72000,
"limit": 11000,
"numberPhases": 3
}]
}
}
}]);
_websocket.send(getComp);
break;
case "ClearChargingProfile":
var clearChargPrfl = JSON.stringify([3, id, {
"status": "Accepted"
}]);
_websocket.send(clearChargPrfl);
break;
case "SetChargingProfile":
var setChargPrlf = JSON.stringify([3, id, {
"status": "Accepted"
}]);
_websocket.send(setChargPrlf);
break;
case "CertificateSigned":
var certSigned = JSON.stringify([3, id, {
"status": "Accepted"
}]);
_websocket.send(certSigned);
break;
case "ClearDisplayMessage":
var clearDispMsg = JSON.stringify([3, id, {
"status": "Accepted"
}]);
_websocket.send(clearDispMsg);
break;
case "ClearVariableMonitoring":
var clearVarMon = JSON.stringify([3, id, {
"clearMonitoringResult": [{
"id": 1,
"status": "Accepted"
}, {
"id": 2,
"status": "Rejected"
}, {
"id": 3,
"status": "NotFound"
}]
}]);
_websocket.send(clearVarMon);
break;
case "GetBaseReport":
var getBaseRep = JSON.stringify([3, id, {
"status": "Accepted"
}]);
_websocket.send(getBaseRep);
break;
case "CostUpdated":
var costUpdtd = JSON.stringify([3, id, {}]);
_websocket.send(costUpdtd);
break;
case "GetMonitoringReport":
var getMonRep = JSON.stringify([3, id, {"status": "Accepted"}]);
_websocket.send(getMonRep);
break;
case "GetReport":
var getRep = JSON.stringify([3, id, {"status": "Accepted"}]);
_websocket.send(getRep);
break;
case "SetMonitoringBase":
var setMonBase = JSON.stringify([3, id, {"status": "Accepted"}]);
_websocket.send(setMonBase);
break;
case "SetMonitoringLevel":
var setMonLevel = JSON.stringify([3, id, {"status": "Accepted"}]);
_websocket.send(setMonLevel);
break;
case "SetVariableMonitoring":
var setVarMon = JSON.stringify([3, id, {"setMonitoringResult": [{
"id": 1,
"type": "Periodic",
"severity": 9,
"status": "Accepted",
"component": {
"name": "some component"
},
"variable":{
"name": "some variable"
}
}]}]);
_websocket.send(setVarMon);
break;
case "UnpublishFirmware":
var unpFirm = JSON.stringify([3, id, {"status": "Unpublished"}]);
_websocket.send(unpFirm);
break;
case "CustomerInformation":
var custmrInfo = JSON.stringify([3, id, {"status": "Accepted"}]);
_websocket.send(custmrInfo);
break;
case "SetDisplayMessage":
var setmessage = (JSON.parse(msg.data)[3].message.message.content);
logMsg("Display message: <b><i>" + setmessage + "</i></b>");
var setDispMsg = JSON.stringify([3, id, {"status": "Accepted"}]);
_websocket.send(setDispMsg);
break;
case "DeleteCertificate":
var delCert = JSON.stringify([3, id, {"status": "Accepted"}]);
_websocket.send(delCert);
break;
case "GetChargingProfiles":
var getChargPrfl = JSON.stringify([3, id, {"status": "Accepted"}]);
_websocket.send(getChargPrfl);
break;
case "GetDisplayMessages":
var getDispMsg = JSON.stringify([3, id, {"status": "Accepted"}]);
_websocket.send(getDispMsg);
break;
case "GetInstalledCertificateIds":
var getInstalledCertIds = JSON.stringify([3, id, {"status": "Accepted"}]);
_websocket.send(getInstalledCertIds);
break;
case "GetTransactionStatus":
var getTranStat = JSON.stringify([3, id, {"messagesInQueue": "true"}]);
_websocket.send(getTranStat);
break;
case "InstallCertificate":
var installCert = JSON.stringify([3, id, {"status": "Accepted"}]);
_websocket.send(installCert);
break;
case "NotifyCentralChargingNeeds":
var noCentChargNeed = JSON.stringify([3, id, {"status": "Accepted"}]);
_websocket.send(noCentChargNeed);
break;
case "PublishFirmware":
var pubFirmware = JSON.stringify([3, id, {"status": "Accepted"}]);
_websocket.send(pubFirmware);
break;
case "Renegotiate15118Schedule":
var renSchedule = JSON.stringify([3, id, {"status": "Accepted"}]);
_websocket.send(renSchedule);
break;
case "SetNetworkProfile":
var setNetProfl = JSON.stringify([3, id, {"status": "Accepted"}]);
_websocket.send(setNetProfl);
break;
default:
var error = JSON.stringify([4, id]);
_websocket.send(error);
break;
}
}
};
_websocket.onclose = function(evt) {
$('#connect').text('Connect').css('background', '#369');
if (evt.code == 3001) {
logMsg('ws closed');
_websocket = null;
} else {
logMsg('ws connection error: ' + evt.code);
$('#console').html("");
_websocket = null;
wsConnect();
}
//
};
_websocket.onerror = function(evt) {
if (_websocket.readyState == 1) {
$('#red').show();
logMsg('ws normal error: ' + evt.type);
}
};
}
}
function logMsg(err) {
console.log(err);
$('#console').append('<li>' + err + '</li>');
}
function Authorize() {
sessionStorage.setItem('LastAction', "Authorize");
var Auth = JSON.stringify([2, id, "Authorize", {
"idToken": {
"idToken": "TAG1",
"type": "Central"
}
}]);
_websocket.send(Auth);
}
function FirmwareStatusNotification() {
sessionStorage.setItem('LastAction', "FirmwareStatusNotification");
var FirmStat = JSON.stringify([2, id, "FirmwareStatusNotification", {
"status": "Installed",
"requestId": 0
}]);
_websocket.send(FirmStat);
}
function startTransaction(charge_state = "EVConnected") {
sessionStorage.setItem('LastAction', "startTransaction");
$('.indicator').hide();
$('#green').show();
connector_locked = true;
logMsg("Connector status changed to: " + connector_locked);
lastTranId = guid();
var strtT = JSON.stringify([2, id, "TransactionEvent", {
"eventType": "Started",
"timestamp": formatDate(new Date()),
"triggerReason": "Authorized",
"seqNo": 0,
"idToken": {
"idToken": "TAG1",
"type": "Central"
},
"evse": {
"id": 2,
"connectorId": 2
},
"transactionInfo": {
"transactionId": lastTranId,
"remoteStartId": 0,
"chargingState": charge_state
},
"meterValue": [{
"timestamp": formatDate(new Date()),
"sampledValue": [{
"value": 0
}]
}]
}]);
_websocket.send(strtT);
}
function updateTransaction(charger_state = "EVConnected") {
sessionStorage.setItem('LastAction', "updateTransaction");
var updTrns = JSON.stringify([2, id, "TransactionEvent", {
"eventType": "Updated",
"timestamp": formatDate(new Date()),
"triggerReason": "MeterValuePeriodic",
"seqNo": 0,
"idToken": {
"idToken": "TAG1",
"type": "Central"
},
"evse": {
"id": 2,
"connectorId": 2
},
"transactionInfo": {
"transactionId": lastTranId,
"remoteStartId": 0,
"chargingState": charger_state
},
"meterValue": [{
"timestamp": formatDate(new Date()),
"sampledValue": [{
"value": 10
}, {
"value": 15,
"context": "Sample.Periodic",
"measurand": "Energy.Reactive.Export.Register",
"phase": "L1",
"location": "EV",
"unitOfMeasure": {
"unit": "5"
}
}]
}]
}]);
_websocket.send(updTrns);
}
function stopTransaction(transaction_id = false) {
sessionStorage.setItem('LastAction', "stopTransaction");
transaction_id == false ? lastTranId = lastTranId : lastTranId = transaction_id;
$('.indicator').hide();
connector_locked = false;
logMsg("Connector status changed to: " + connector_locked);
$('#yellow').show();
var stpT = JSON.stringify([2, id, "TransactionEvent", {
"eventType": "Ended",
"timestamp": formatDate(new Date()),
"triggerReason": "Deauthorized",
"seqNo": 0,
"idToken": {
"idToken": "TAG1",
"type": "Central"
},
"evse": {
"id": 2,
"connectorId": 2
},
"transactionInfo": {
"transactionId": lastTranId,
"remoteStartId": 0
},
"meterValue": [{
"timestamp": formatDate(new Date()),
"sampledValue": [{
"value": 20
}]
}]
}]);
_websocket.send(stpT);
}
function getConfiguration() {
}
function handleData(data, request = false) {
var lastAction = getLastAction();
if (lastAction = "BootNotification") {
data = data[2];
heartbeat_interval = data.interval;
return heartbeat_interval;
} else if (lastAction = "StartTransaction") {
return "StartTransaction";
} else if (1 == 2) {
alert("else");
}
}
function getLastAction() {
var LastAction = sessionStorage.getItem("LastAction");
return LastAction;
}
function BootNotification() {
var BN = JSON.stringify([2, id, "BootNotification", {
"chargingStation": {
"serialNumber": "avt.001.13.1",
"model": "AVT-Express",
"modem": {
"iccid": "MMCCIINNNNNNNNNNNNCx",
"imsi": "520031234567890"
},
"vendorName": "AVT-Company",
"firmwareVersion": "0.9.87"
},
"reason": "PowerUp"
}]);
logMsg('ws connected');
_websocket.send(BN);
}
function statusNotification() {
sessionStorage.setItem('LastAction', "StatusNotification");
var SN = JSON.stringify([2, id, "StatusNotification", {
"timestamp": formatDate(new Date()),
"connectorStatus": "Available",
"evseId": 2,
"connectorId": 2
}]);
_websocket.send(SN);
}
function meterValues() {
sessionStorage.setItem('LastAction', "MeterValues");
var MV = JSON.stringify([2, id, "MeterValues", {
"evseId": 2,
"meterValue": [{
"timestamp": formatDate(new Date()),
"sampledValue": [{
"value": 0,
"measurand": "Energy.Active.Import.Register"
}, {
"value": 7200,
"measurand": "Power.Active.Import"
}]
}, {
"timestamp": formatDate(new Date()),
"sampledValue": [{
"value": 800,
"measurand": "Energy.Active.Import.Register"
}, {
"value": 20,
"measurand": "Energy.Reactive.Import.Register"
}]
}, {
"timestamp": formatDate(new Date()),
"sampledValue": [{
"value": 42,
"measurand": "SoC"
}]
}]
}]);
_websocket.send(MV);
}
function startHB(interval) {
setInterval(send_heartbeat, interval);
}
function send_heartbeat() {
sessionStorage.setItem('LastAction', "Heartbeat");
var HB = JSON.stringify([2, id, "Heartbeat", {}]);
_websocket.send(HB);
}
function LogStatusNotification(upload_status = "Uploading") {
sessionStorage.setItem('LastAction', "LogStatusNotification");
var LSN = JSON.stringify([2, id, "LogStatusNotification", {
"status": upload_status,
"requestId": 1,
}]);
_websocket.send(LSN);
}
function NotifyChargingLimit(charge_limit = 10, limit_source = "SO") {
sessionStorage.setItem('LastAction', "NotifyChargingLimit");
var LSN = JSON.stringify([2, id, "NotifyChargingLimit", {
"evseId": 1,
"chargingLimit": {
"chargingLimitSource": limit_source,
"isGridCritical": false,
},
"chargingSchedule": [charging_schedule(charge_limit)]
}]);
_websocket.send(LSN);
}
function NotifyEVChargingSchedule(charge_limit = 10, evse_id = 1) {
sessionStorage.setItem('LastAction', "NotifyEVChargingSchedule");
var NECS = JSON.stringify([2, id, "NotifyEVChargingSchedule", {
"evseId": evse_id,
"timeBase": formatDate(new Date()),
"chargingSchedule": charging_schedule(charge_limit)
}]);
_websocket.send(NECS);
}
function charging_schedule(charge_limit){
return {
"id": 0,
"chargingRateUnit": "A",
"chargingSchedulePeriod": [{
"startPeriod": 0,
"limit": charge_limit
}]
}
}
$('#connect').click(function() {
$('.indicator').hide();
$('#console').html("");
wsConnect();
});
$('#send').click(function() {
Authorize();
});
$('#start').click(function() {
startTransaction();
});
$('#update').click(function() {
updateTransaction();
});
$('#update_suspendedev').click(function() {
updateTransaction(charger_state = "SuspendedEV");
});
$('#update_suspendedevse').click(function() {
updateTransaction(charger_state = "SuspendedEVSE");
});
$('#update_charging').click(function() {
updateTransaction(charger_state = "Charging");
});
$('#stop').click(function() {
stopTransaction();
});
$('#firmwarestatus').click(function() {
FirmwareStatusNotification();
});
$('#mv').click(function() {
meterValues();
});
$('#heartbeat').click(function() {
send_heartbeat();
});
$('#status').click(function() {
statusNotification();
});
$('#data_transfer').click(function() {
sessionStorage.setItem('LastAction', "DataTransfer");
var DT = JSON.stringify([2, id, "DataTransfer", {
"vendorId": "rus.avt.cp",
"messageId": "GetChargeInstruction",
"data": ""
}]);
_websocket.send(DT);
});
$('#clearedChargingLimit').click(function() {
sessionStorage.setItem('LastAction', "ClearedChargingLimit");
var CCL = JSON.stringify([2, id, "ClearedChargingLimit", {
"chargingLimitSource": "Other",
"evseId": 2
}]);
_websocket.send(CCL);
});
$('#logstatus_uploading').click(function() {
LogStatusNotification();
});
$('#logstatus_uploaded').click(function() {
LogStatusNotification("Uploaded");
});
$('#notify_charging_limit').click(function() {
NotifyChargingLimit();
});
$('#notify_ev_charging_schedule').click(function() {
NotifyEVChargingSchedule();
});
$('#connect').on('change', function() {
if (_websocket) {
_websocket.close(3001);
}
});
</script>
</body>
</html>

View File

@@ -0,0 +1,400 @@
<html>
<head>
<style>
body {
background: #000;
color: white;
font-family: Arial;
}
button, input, select {
display: block;
width: 100%;
margin-bottom: 5px;
cursor: pointer;
}
button {
background: #369;
color: #fff;
padding: 5px 0;
border: none;
}
ul {
background: #000;
color: #eee;
}
#red, #green, #blue {
min-width: 10px;
}
#red {
background-color: red;
}
#green {
background-color: green;
}
#blue {
background-color: blue;
}
#yellow {
background-color: yellow;
}
</style>
</head>
<body>
<h1>Simple OCPP 1.6 Chargebox Simulator</h1>
<select style="display:none;"><option value="">OCPP-J1.6</option></select>
<label>Central Station</label><input id="CP" type="text" placeholder="Id Station" value="ws://localhost:8081/OCPP/Test1234" value_old="ws://192.168.1.253:8080/steve/websocket/CentralSystemService/WB-Dallmann"/>
<label>Tag</label><input id="TAG" type="text" placeholder="Tag" value="B4A63CDF"/>
<h2>Actions</h2>
<button id="connect">Connect</button>
<button id="send">Authorize</button>
<button id="start">Start Transaction</button>
<button id="stop">Stop Transaction</button>
<button id="heartbeat">Heartbeat</button>
<label>Meter value</label><input id="metervalue" type="text" placeholder="Meter value" value="1"/>
<button id="mv">Send Meter Values</button>
<button id="status">Status Notification</button>
<button id="data_transfer">Data Tranfer</button>
<div>
<span class="indicator" id="red">____</span>
<span class="indicator" id="green">____</span>
<span class="indicator" id="blue">____</span>
<span class="indicator" id="yellow">____</span>
</div>
<ul id="console"></ul>
<script
src="https://code.jquery.com/jquery-3.3.1.min.js"
integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8="
crossorigin="anonymous"></script>
<script>
var c = 0;
var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
var id = randomId();
var _websocket = null;
var connector_locked = false;
function formatDate(date) {
var day = String(date.getUTCDate());
if (day.length <2){
day = ('0' + day.slice(-2));
}
var monthIndex = String(date.getUTCMonth()+1);
if (monthIndex.length <2){
monthIndex = ('0' + monthIndex.slice(-2));
}
var year = date.getUTCFullYear();
var h = String(date.getUTCHours());
var m = String(date.getUTCMinutes());
var s = String(date.getUTCSeconds());
if (h.length <2){
h = ('0' + h.slice(-2));
}
if (m.length <2){
m = ('0' + m.slice(-2));
}
if (s.length <2){
s = ('0' + s.slice(-2));
}
return year + '-' + monthIndex + '-' + day+"T"+h+":"+m+":"+s+"Z";
}
function randomId() {
id = "";
for (var i = 0; i < 36; i++) {
id += possible.charAt(Math.floor(Math.random() * possible.length));
}
return id;
}
function wsConnect() {
var wsurl = $('select').val();
var CP = $('#CP').val();
if (_websocket) {
$('#red').show();
_websocket.close(3001);
} else {
_websocket = new WebSocket(wsurl + "" + CP, ["ocpp1.6", "ocpp1.5"]);
_websocket.onopen = function (authorizationData) {
sessionStorage.setItem('LastAction', "BootNotification");
$('#yellow').show();
BootNotification();
$('#connect').text('Disconnect').css('background', 'green');
};
_websocket.onmessage = function (msg) {
c++;
var ddata = (JSON.parse(msg.data));
if(c==1){
var hb_interval = handleData(ddata);
sessionStorage.setItem("Configuration",hb_interval);
startHB(hb_interval*1000);
}
if (ddata[0] === 3) {
la = getLastAction();
if (la == "startTransaction"){
var dd = ddata[2];
logMsg("Data exchange successful!");
var array = $.map(dd, function (value, index) {
return [value];
});
//var TransactionId = (array[0]);
var TransactionId = (array[1]);
sessionStorage.setItem('TransactionId', TransactionId);
}
logMsg("Response: " + JSON.stringify(ddata[2]));
} else if ((JSON.parse(msg.data))[0] === 4) {
logMsg("Data exchange failed - JSON is not accepted!");
} else if ((JSON.parse(msg.data))[0] === 2) {
logMsg((JSON.parse(msg.data))[2]);
id = (JSON.parse(msg.data))[1];
switch (ddata[2]) {
case "Reset":
//Reset type SOFT, HARD
var ResetS = JSON.stringify([3, id, {"status": "Accepted"}]);
_websocket.send(ResetS);
location.reload();
break;
case "RemoteStopTransaction":
//TransactionID
var remStp = JSON.stringify([3, id, {"status": "Accepted"}]);
_websocket.send(remStp);
var stop_id = (JSON.parse(msg.data)[3].transactionId);
stopTransaction(stop_id);
$('.indicator').hide();
$('#yellow').show();
break;
case "RemoteStartTransaction":
//Need to get idTag, connectorId (map - ddata[3])
var remStrt = JSON.stringify([3, id, {"status": "Accepted"}]);
_websocket.send(remStrt);
startTransaction();
break;
case "UnlockConnector": /////////ERROR!!!!!!!!
//connectorId
var UC = JSON.stringify([3, id, {"status": "Unlocked"}]);
_websocket.send(UC);
connector_locked = false;
$('.indicator').hide();
$('#yellow').show();
logMsg("Connector status changed to: "+connector_locked);
break;
default:
var error = JSON.stringify([4, id]);
_websocket.send(error);
break;
}
}
};
_websocket.onclose = function (evt) {
$('#connect').text('Connect').css('background', '#369');
if (evt.code == 3001) {
logMsg('ws closed');
_websocket = null;
} else {
logMsg('ws connection error: ' + evt.code);
$('#console').html("");
_websocket = null;
wsConnect();
}
};
_websocket.onerror = function (evt) {
if (_websocket.readyState == 1) {
$('#red').show();
logMsg('ws normal error: ' + evt.type);
}
};
}
}
function logMsg(err) {
console.log(err);
$('#console').append('<li>' + err + '</li>');
}
function Authorize(){
sessionStorage.setItem('LastAction', "Authorize");
var Auth = JSON.stringify([2, id, "Authorize", {"idTag": $("#TAG").val()}]);
_websocket.send(Auth);
}
function startTransaction(){
sessionStorage.setItem('LastAction', "startTransaction");
$('.indicator').hide();
$('#green').show();
connector_locked = true;
logMsg("Connector status changed to: " + connector_locked);
var strtT = JSON.stringify([2, id, "StartTransaction", {
"connectorId": 2,
"idTag": $("#TAG").val(),
"timestamp": formatDate(new Date()),
"meterStart": 0,
"reservationId": 0
}]);
_websocket.send(strtT);
}
function stopTransaction(transaction_id = false){
sessionStorage.setItem('LastAction', "stopTransaction");
transaction_id == false ? ssid = sessionStorage.getItem('TransactionId') : ssid = transaction_id;
$('.indicator').hide();
connector_locked = false;
logMsg("Connector status changed to: " + connector_locked);
$('#yellow').show();
var stpT = JSON.stringify([2, id, "StopTransaction",{
"transactionId": parseInt(ssid),
"idTag": $("#TAG").val(),
"timestamp": formatDate(new Date()),
"meterStop": 20
}]);
_websocket.send(stpT);
}
function handleData(data, request = false){
var lastAction = getLastAction();
if(lastAction = "BootNotification"){
data = data[2];
heartbeat_interval = data.interval;
return heartbeat_interval;
}else if(lastAction = "StartTransaction"){
return "StartTransaction";
}else if (1==2){
alert("else");
}
}
function getLastAction(){
var LastAction = sessionStorage.getItem("LastAction");
return LastAction;
}
function BootNotification(){
var BN = JSON.stringify([2, id, "BootNotification", {
"chargePointVendor": "AVT-Company",
"chargePointModel": "AVT-Express",
"chargePointSerialNumber": "avt.001.13.1",
"chargeBoxSerialNumber": "avt.001.13.1.01",
"firmwareVersion": "0.9.87",
"iccid": "",
"imsi": "",
"meterType": "AVT NQC-ACDC",
"meterSerialNumber": "avt.001.13.1.01"
}]);
logMsg('ws connected');
_websocket.send(BN);
}
function startHB(interval){
logMsg("Setting heartbeat interval to "+interval);
setInterval(send_heartbeat,interval);
}
function send_heartbeat() {
sessionStorage.setItem('LastAction', "Heartbeat");
var HB = JSON.stringify([2, id, "Heartbeat", {}]);
_websocket.send(HB);
}
$( document ).ready(function() {
$('.indicator').hide();
$('#red').show();
//bind controls
$('#connect').click(function () {
$('.indicator').hide();
$('#console').html("");
wsConnect();
});
$('#send').click(function () {
Authorize();
});
$('#start').click(function () {
startTransaction();
});
$('#stop').click(function () {
stopTransaction();
});
$('#mv').click(function () {
sessionStorage.setItem('LastAction', "MeterValues");
ssid = sessionStorage.getItem('TransactionId');
var val = String($("#metervalue").val());
var MV;
if (ssid == null)
MV = JSON.stringify([2, id, "MeterValues", {"connectorId": 2, "meterValue": [{"timestamp": formatDate(new Date()), "sampledValue": [{"value": val, "measurand": "Energy.Active.Import.Register"},{"value": "800", "measurand": "Power.Active.Import"},{"value": "47", "measurand": "SoC"}]}]}]);
else
MV = JSON.stringify([2, id, "MeterValues", {"connectorId": 2, "transactionId": ssid, "meterValue": [{"timestamp": formatDate(new Date()), "sampledValue": [{"value": val, "measurand": "Energy.Active.Import.Register"},{"value": "800", "measurand": "Power.Active.Import"},{"value": "47", "measurand": "SoC"}]}]}]);
_websocket.send(MV);
});
$('#heartbeat').click(function () {
send_heartbeat();
});
$('#status').click(function () {
sessionStorage.setItem('LastAction', "StatusNotification");
var SN = JSON.stringify([2, id, "StatusNotification", {
"connectorId": 2,
"status": "Available",
"errorCode": "NoError",
"info": "",
"timestamp": formatDate(new Date()),
"vendorId": "",
"vendorErrorCode": ""
}]);
_websocket.send(SN);
});
$('#data_transfer').click(function () {
sessionStorage.setItem('LastAction', "DataTransfer");
var DT = JSON.stringify([2, id, "DataTransfer", {
"vendorId": "rus.avt.cp",
"messageId": "GetChargeInstruction",
"data": ""
}]);
_websocket.send(DT);
});
$('#connect').on('change', function () {
if (_websocket) {
_websocket.close(3001);
}
});
});
</script>
</body>
</html>

View File

@@ -0,0 +1,474 @@
<html>
<head>
<style>
body {
background: #000;
color: white;
font-family: Arial;
}
button {
display: block;
width: 100%;
margin-bottom: 5px;
cursor: pointer;
}
input, select {
margin-bottom: 5px;
cursor: pointer;
}
.FullLine {
display: block;
width: 100%;
margin-bottom: 5px;
cursor: pointer;
}
button {
background: #369;
color: #fff;
padding: 5px 0;
border: none;
}
ul {
background: #000;
color: #eee;
}
</style>
</head>
<body>
<h1>Simple OCPP 1.6 Chargebox Simulator</h1>
<select style="display:none;"><option value="">OCPP-J1.6</option></select>
<label>Central Station</label><input id="CP" type="text" class="FullLine" placeholder="Id Station" value="ws://localhost:8081/OCPP/Test1234" />
<label>Tag</label><input id="TAG" type="text" class="FullLine" placeholder="Tag" value="B4A63CDF"/>
<h2>Actions</h2>
<button id="connect">Connect</button>
<button id="heartbeat">Heartbeat</button>
<button id="data_transfer">Data Tranfer</button>
<button id="send">Authorize</button>
<table style="width: 100%">
<tr>
<td style="width: 40%">
<fieldset>
<legend><span id="connector1">Connector 1</span></legend>
<button id="start1">Start Transaction</button>
<button id="stop1">Stop Transaction</button>
<label>Meter value</label>&nbsp;<input id="metervalue1" type="text" placeholder="Meter value" value="100" />
<label>State of Charge</label>&nbsp;<input id="soc1" type="text" placeholder="SoC" value="23" />
<button id="mv1">Send Meter Values</button>
<label>Status</label>&nbsp;<select id="statusValue1" >
<option selected="selected">Available</option>
<option>Preparing</option>
<option>Charging</option>
<option>SuspendedEVSE</option>
<option>SuspendedEV</option>
<option>Finishing</option>
<option>Reserved</option>
<option>Unavailable</option>
<option>Faulted</option>
</select>
<button id="status1">Status Notification</button>
</fieldset>
</td>
<td style="width: 40%">
<fieldset>
<legend><span id="connector2">Connector 2</span></legend>
<button id="start2">Start Transaction</button>
<button id="stop2">Stop Transaction</button>
<label>Meter value</label>&nbsp;<input id="metervalue2" type="text" placeholder="Meter value" value="500" />
<label>State of Charge</label>&nbsp;<input id="soc2" type="text" placeholder="SoC" value="63" />
<button id="mv2">Send Meter Values</button>
<label>Status</label>&nbsp;<select id="statusValue2" >
<option selected="selected">Available</option>
<option>Preparing</option>
<option>Charging</option>
<option>SuspendedEVSE</option>
<option>SuspendedEV</option>
<option>Finishing</option>
<option>Reserved</option>
<option>Unavailable</option>
<option>Faulted</option>
</select>
<button id="status2">Status Notification</button>
</fieldset>
</td>
</tr>
</table>
<ul id="console"></ul>
<script
src="https://code.jquery.com/jquery-3.3.1.min.js"
integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8="
crossorigin="anonymous"></script>
<script>
var c = 0;
var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
var id = randomId();
var _websocket = null;
var connector_locked = false;
function formatDate(date) {
var day = String(date.getUTCDate());
if (day.length <2){
day = ('0' + day.slice(-2));
}
var monthIndex = String(date.getUTCMonth()+1);
if (monthIndex.length <2){
monthIndex = ('0' + monthIndex.slice(-2));
}
var year = date.getUTCFullYear();
var h = String(date.getUTCHours());
var m = String(date.getUTCMinutes());
var s = String(date.getUTCSeconds());
if (h.length <2){
h = ('0' + h.slice(-2));
}
if (m.length <2){
m = ('0' + m.slice(-2));
}
if (s.length <2){
s = ('0' + s.slice(-2));
}
return year + '-' + monthIndex + '-' + day+"T"+h+":"+m+":"+s+"Z";
}
function randomId() {
id = "";
for (var i = 0; i < 36; i++) {
id += possible.charAt(Math.floor(Math.random() * possible.length));
}
return id;
}
function wsConnect() {
var wsurl = $('select').val();
var CP = $('#CP').val();
if (_websocket) {
setConnectionStatus(false);
_websocket.close(3001);
} else {
_websocket = new WebSocket(wsurl + "" + CP, ["ocpp1.6", "ocpp1.5"]);
_websocket.onopen = function (authorizationData) {
sessionStorage.setItem('LastAction', "BootNotification");
setConnectionStatus(true);
BootNotification();
$('#connect').text('Disconnect').css('background', 'green');
};
_websocket.onmessage = function (msg) {
c++;
var ddata = (JSON.parse(msg.data));
if(c==1){
var hb_interval = handleData(ddata);
sessionStorage.setItem("Configuration",hb_interval);
startHB(hb_interval*1000);
}
if (ddata[0] === 3) {
la = getLastAction();
if (la.startsWith("startTransaction")){
var dd = ddata[2];
var status = dd.idTagInfo.status;
var txId = dd.transactionId;
if (status == 'Accepted')
{
logMsg("Data exchange successful!");
sessionStorage.setItem('TransactionId'+la.charAt(16), txId);
setTransactionStatus(parseInt(la.charAt(16)), true);
}
else
{
logMsg("Transaction rejected: "+status);
}
}
logMsg("Response: " + JSON.stringify(ddata[2]));
} else if ((JSON.parse(msg.data))[0] === 4) {
logMsg("Data exchange failed - JSON is not accepted!");
} else if ((JSON.parse(msg.data))[0] === 2) {
logMsg((JSON.parse(msg.data))[2]);
id = (JSON.parse(msg.data))[1];
switch (ddata[2]) {
case "Reset":
//Reset type SOFT, HARD
var ResetS = JSON.stringify([3, id, {"status": "Accepted"}]);
_websocket.send(ResetS);
location.reload();
break;
case "RemoteStopTransaction":
//TransactionID
var remStp = JSON.stringify([3, id, {"status": "Accepted"}]);
_websocket.send(remStp);
var stop_id = (JSON.parse(msg.data)[3].transactionId);
stopTransaction(stop_id);
break;
case "RemoteStartTransaction":
//Need to get idTag, connectorId (map - ddata[3])
var remStrt = JSON.stringify([3, id, {"status": "Accepted"}]);
_websocket.send(remStrt);
startTransaction();
break;
case "UnlockConnector": /////////ERROR!!!!!!!!
//connectorId
var UC = JSON.stringify([3, id, {"status": "Unlocked"}]);
_websocket.send(UC);
connector_locked = false;
setTransactionStatus(1, false);
logMsg("Connector status changed to: "+connector_locked);
break;
default:
var error = JSON.stringify([4, id]);
_websocket.send(error);
break;
}
}
};
_websocket.onclose = function (evt) {
$('#connect').text('Connect').css('background', '#369');
if (evt.code == 3001) {
logMsg('ws closed');
_websocket = null;
} else {
logMsg('ws connection error: ' + evt.code);
$('#console').html("");
_websocket = null;
wsConnect();
}
};
_websocket.onerror = function (evt) {
if (_websocket.readyState == 1) {
setConnectionStatus(false);
logMsg('ws normal error: ' + evt.type);
}
};
}
}
function logMsg(err) {
console.log(err);
$('#console').append('<li>' + err + '</li>');
}
function Authorize(){
sessionStorage.setItem('LastAction', "Authorize");
var Auth = JSON.stringify([2, id, "Authorize", {"idTag": $("#TAG").val()}]);
_websocket.send(Auth);
}
function startTransaction(connectorId){
sessionStorage.setItem('LastAction', "startTransaction"+connectorId);
connector_locked = true;
logMsg("Connector"+connectorId+" status changed to: " + connector_locked);
var strtT = JSON.stringify([2, id, "StartTransaction", {
"connectorId": connectorId,
"idTag": $("#TAG").val(),
"timestamp": formatDate(new Date()),
"meterStart": 0,
"reservationId": 0
}]);
_websocket.send(strtT);
}
function stopTransaction(connectorId, transaction_id = false){
sessionStorage.setItem('LastAction', "stopTransaction"+connectorId);
transaction_id == false ? ssid = sessionStorage.getItem('TransactionId'+connectorId) : ssid = transaction_id;
connector_locked = false;
logMsg("Connector"+connectorId+" status changed to: " + connector_locked);
setConnectionStatus(true);
var stpT = JSON.stringify([2, id, "StopTransaction",{
"transactionId": parseInt(ssid),
"idTag": $("#TAG").val(),
"timestamp": formatDate(new Date()),
"meterStop": 20
}]);
_websocket.send(stpT);
}
function handleData(data, request = false){
var lastAction = getLastAction();
if(lastAction = "BootNotification"){
data = data[2];
heartbeat_interval = data.interval;
return heartbeat_interval;
}else if(lastAction.startsWith("StartTransaction")){
return "StartTransaction";
}else if (1==2){
alert("else");
}
}
function getLastAction(){
var LastAction = sessionStorage.getItem("LastAction");
return LastAction;
}
function BootNotification(){
var BN = JSON.stringify([2, id, "BootNotification", {
"chargePointVendor": "AVT-Company",
"chargePointModel": "AVT-Express",
"chargePointSerialNumber": "avt.001.13.1",
"chargeBoxSerialNumber": "avt.001.13.1.01",
"firmwareVersion": "0.9.87",
"iccid": "",
"imsi": "",
"meterType": "AVT NQC-ACDC",
"meterSerialNumber": "avt.001.13.1.01"
}]);
logMsg('ws connected');
_websocket.send(BN);
}
function startHB(interval){
logMsg("Setting heartbeat interval to "+interval);
setInterval(send_heartbeat,interval);
}
function send_heartbeat() {
sessionStorage.setItem('LastAction', "Heartbeat");
var HB = JSON.stringify([2, id, "Heartbeat", {}]);
_websocket.send(HB);
}
function send_MeterValues(connectorId)
{
sessionStorage.setItem('LastAction', "MeterValues"+connectorId);
ssid = sessionStorage.getItem('TransactionId');
var meterVal = String($("#metervalue"+connectorId).val());
var socVal = String($("#soc"+connectorId).val());
var MV;
if (ssid == null)
MV = JSON.stringify([2, id, "MeterValues", {"connectorId": connectorId, "meterValue": [{"timestamp": formatDate(new Date()), "sampledValue": [{"value": meterVal, "measurand": "Energy.Active.Import.Register"},{"value": "800", "measurand": "Power.Active.Import"},{"value": socVal, "measurand": "SoC"}]}]}]);
else
MV = JSON.stringify([2, id, "MeterValues", {"connectorId": connectorId, "transactionId": ssid, "meterValue": [{"timestamp": formatDate(new Date()), "sampledValue": [{"value": meterVal, "measurand": "Energy.Active.Import.Register"},{"value": "800", "measurand": "Power.Active.Import"},{"value": socVal, "measurand": "SoC"}]}]}]);
_websocket.send(MV);
}
function send_StatusNotification(connectorId)
{
sessionStorage.setItem('LastAction', "StatusNotification"+connectorId);
var statusVal = String($("#statusValue"+connectorId).val());
var SN = JSON.stringify([2, id, "StatusNotification", {
"connectorId": connectorId,
"status": statusVal,
"errorCode": "NoError",
"info": "",
"timestamp": formatDate(new Date()),
"vendorId": "",
"vendorErrorCode": ""
}]);
_websocket.send(SN);
}
function setConnectionStatus(connected)
{
if (connected)
{
setTransactionStatus(1, false);
setTransactionStatus(2, false);
}
else
{
$('#connector1').css("background-color", "");
$('#connector2').css("background-color", "");
}
}
function setTransactionStatus(connectorId, active)
{
if (active)
$('#connector'+connectorId).css("background-color", "green");
else
$('#connector'+connectorId).css("background-color", "#C0C000");
}
$( document ).ready(function() {
setConnectionStatus(false);
//bind controls
$('#connect').click(function () {
$('#console').html("");
wsConnect();
});
$('#send').click(function () {
Authorize();
});
$('#start1').click(function () {
startTransaction(1);
});
$('#start2').click(function () {
startTransaction(2);
});
$('#stop1').click(function () {
stopTransaction(1);
});
$('#stop2').click(function () {
stopTransaction(2);
});
$('#mv1').click(function () {
send_MeterValues(1);
});
$('#mv2').click(function () {
send_MeterValues(2);
});
$('#heartbeat').click(function () {
send_heartbeat();
});
$('#status1').click(function () {
send_StatusNotification(1);
});
$('#status2').click(function () {
send_StatusNotification(2);
});
$('#data_transfer').click(function () {
sessionStorage.setItem('LastAction', "DataTransfer");
var DT = JSON.stringify([2, id, "DataTransfer", {
"vendorId": "rus.avt.cp",
"messageId": "GetChargeInstruction",
"data": ""
}]);
_websocket.send(DT);
});
$('#connect').on('change', function () {
if (_websocket) {
_websocket.close(3001);
}
});
});
</script>
</body>
</html>