Tum пре 2 година
комит
3de4025a03

+ 4 - 0
charger-simulator/.gitignore

@@ -0,0 +1,4 @@
1
+.idea
2
+/dist
3
+*.iml
4
+node_modules

+ 3 - 0
charger-simulator/.npmignore

@@ -0,0 +1,3 @@
1
+.idea
2
+node_modules
3
+*.iml

+ 7 - 0
charger-simulator/.prettierrc.js

@@ -0,0 +1,7 @@
1
+module.exports = {
2
+  printWidth: 100,
3
+  semi: false,
4
+  trailingComma: "es5",
5
+  bracketSpacing: false,
6
+  htmlWhitespaceSensitivity: "ignore",
7
+};

+ 21 - 0
charger-simulator/LICENSE

@@ -0,0 +1,21 @@
1
+MIT License
2
+
3
+Copyright (c) 2020 Vasyl Stashuk
4
+
5
+Permission is hereby granted, free of charge, to any person obtaining a copy
6
+of this software and associated documentation files (the "Software"), to deal
7
+in the Software without restriction, including without limitation the rights
8
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+copies of the Software, and to permit persons to whom the Software is
10
+furnished to do so, subject to the following conditions:
11
+
12
+The above copyright notice and this permission notice shall be included in all
13
+copies or substantial portions of the Software.
14
+
15
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+SOFTWARE.

+ 88 - 0
charger-simulator/README.md

@@ -0,0 +1,88 @@
1
+EV charger simulator. Supports OCPP/J version 1.6 and OCPP/SOAP version 1.5. 
2
+Can be used as CLI program, or as library in any JS environment.
3
+
4
+# CLI usage
5
+
6
+## Getting started
7
+
8
+Install in project
9
+```
10
+yarn add vasyas/charger-simulator
11
+```
12
+
13
+or globally
14
+```
15
+yarn global add vasyas/charger-simulator
16
+```
17
+
18
+Then launch it with command
19
+```
20
+charger-simulator <URL to central system>
21
+```
22
+
23
+You can also run from a cloned git repository
24
+```
25
+yarn start <URL to central system>
26
+```
27
+
28
+On successfull launch, you will get this message
29
+
30
+```
31
+debug] OCPP connected
32
+[info] Connected to Central System
33
+[info] Supported keys:
34
+    Ctrl+C:   quit
35
+
36
+    Control connector 1
37
+    ---
38
+    a:        send Available status
39
+    p:        send Preparing status
40
+    c:        send Charging status
41
+    f:        send Finishing status
42
+```
43
+
44
+You can press keys to send connector status updates to central server.
45
+
46
+## CLI options
47
+```
48
+charger-simulator
49
+
50
+  Start OCPP charging station simulator, connect simulator to Central System
51
+  server.
52
+
53
+Options
54
+
55
+  -s, --csURL URL                 URL of the Central System server to connect to, ws://server.name/path.
56
+                                  This is also a default option.
57
+  -i, --chargerId ChargerId       OCPP ID to be used for simulating charger.
58
+                                  Default is 'test'.
59
+  -c, --connectorId ConnectorId   ID of the connector to send status when pressing keys.
60
+                                  Defaults to 1.
61
+  -t, --idTag idTag               ID Tag to start transaction.
62
+                                  Defaults to 123456.
63
+```
64
+
65
+## Default behavior
66
+
67
+By default simulator implements following OCPP operations.
68
+
69
+*RemoteStartTransaction*. Will successfully start new transaction. Call RemoteStartTransaction by server
70
+will result in StartTransaction and multiple MeterValues to be sent to central system.
71
+
72
+*RemoteStopTransaction*. Will stop running transaction.
73
+
74
+*GetConfiguration*. Return charge point configuration.
75
+*ChangeConfiguration*. Change charge point configuration.
76
+
77
+*ReserveNow, CancelReservation, Reset*. Return 'Accepted', but do nothing.
78
+
79
+All other methods are not implemented.
80
+
81
+# Library usage
82
+
83
+## Getting started
84
+TBD  
85
+
86
+## API
87
+TBD  
88
+

+ 2 - 0
charger-simulator/cli-index.js

@@ -0,0 +1,2 @@
1
+#!/usr/bin/env node
2
+require("./dist/chargerSimulatorCli.js")

Разлика између датотеке није приказан због своје велике величине
+ 2784 - 0
charger-simulator/package-lock.json


+ 37 - 0
charger-simulator/package.json

@@ -0,0 +1,37 @@
1
+{
2
+  "name": "charger-simulator",
3
+  "version": "1.0.2",
4
+  "main": "dist/index.js",
5
+  "bin": {
6
+    "charger-simulator": "cli-index.js"
7
+  },
8
+  "types": "dist/index.d.ts",
9
+  "scripts": {
10
+    "start": "ts-node src/chargerSimulatorCli.ts",
11
+    "prepublishOnly": "tsc",
12
+    "build": "tsc",
13
+    "docs": "typedoc --out docs ./src"
14
+  },
15
+  "license": "MIT",
16
+  "devDependencies": {
17
+    "@types/node": "^14.0.5",
18
+    "prettier": "^3.1.1",
19
+    "ts-node": "^10.9.2",
20
+    "typescript": "^5.3.3"
21
+  },
22
+  "repository": "https://github.com/vasyas/charger-simulator.git",
23
+  "author": "Vasyl Stashuk <vasyl@stashuk.com>",
24
+  "publishConfig": {
25
+    "access": "public"
26
+  },
27
+  "dependencies": {
28
+    "@push-rpc/core": "^1.8.2",
29
+    "@push-rpc/websocket": "^1.8.2",
30
+    "@types/ws": "^8.5.10",
31
+    "command-line-args": "^5.1.1",
32
+    "command-line-usage": "^6.1.0",
33
+    "strong-soap": "1.21.0",
34
+    "ws": "^8.15.1",
35
+    "xml2js": "^0.6.2"
36
+  }
37
+}

+ 239 - 0
charger-simulator/src/ChargerSimulator.ts

@@ -0,0 +1,239 @@
1
+import {createRpcClient} from "@push-rpc/core"
2
+import {wrapWebsocket} from "@push-rpc/websocket/dist/server"
3
+import * as WebSocket from "ws"
4
+import {log} from "./log"
5
+import {createCentralSystemClient, createChargePointServer} from "./soap/ocppSoap"
6
+
7
+export interface Config {
8
+  defaultHeartbeatIntervalSec?: number
9
+  chargePointVendor?: string
10
+  chargePointModel?: string
11
+  startDelayMs?: number
12
+  stopDelayMs?: number
13
+  keepAliveTimeoutMs?: number // set to null to disable pings
14
+  meterValuesIntervalSec?: number
15
+
16
+  centralSystemEndpoint: string
17
+  chargerIdentity: string
18
+  chargePointPort?: number
19
+}
20
+
21
+const defaultConfig: Partial<Config> = {
22
+  defaultHeartbeatIntervalSec: 30,
23
+  chargePointVendor: "Test",
24
+  chargePointModel: "1",
25
+  startDelayMs: 8 * 1000,
26
+  stopDelayMs: 8 * 1000,
27
+  keepAliveTimeoutMs: 50 * 1000,
28
+  meterValuesIntervalSec: 20,
29
+}
30
+
31
+let ws: WebSocket
32
+
33
+export class ChargerSimulator {
34
+  constructor(config: Config) {
35
+    this.config = {...defaultConfig, ...config}
36
+
37
+    this.configurationKeys = [
38
+      {key: "HeartBeatInterval", readonly: false, value: "" + config.defaultHeartbeatIntervalSec},
39
+      {key: "ResetRetries", readonly: false, value: "1"},
40
+      {key: "MeterValueSampleInterval", readonly: false, value: config.meterValuesIntervalSec},
41
+    ]
42
+  }
43
+
44
+  public async start() {
45
+    if (this.config.chargePointPort) {
46
+      await createChargePointServer(this.chargePoint, this.config.chargePointPort)
47
+      log.info(
48
+        `Started SOAP Charge Point server at http://localhost:${this.config.chargePointPort}/`
49
+      )
50
+
51
+      this.centralSystem = await createCentralSystemClient(
52
+        this.config.centralSystemEndpoint,
53
+        this.config.chargerIdentity,
54
+        `http://localhost:${this.config.chargePointPort}/`
55
+      )
56
+      log.info(`Will send messages to Central System at ${this.config.centralSystemEndpoint}`)
57
+    } else {
58
+      const {remote} = await createRpcClient(
59
+        async () => {
60
+          ws = new WebSocket(
61
+            this.config.centralSystemEndpoint + "/" + this.config.chargerIdentity,
62
+            "ocpp1.6"
63
+          )
64
+
65
+          return wrapWebsocket(ws)
66
+        },
67
+        {
68
+          local: this.chargePoint,
69
+          reconnect: true,
70
+          keepAliveTimeout: this.config.keepAliveTimeoutMs,
71
+
72
+          listeners: {
73
+            messageIn: (data) => {
74
+              log.debug("OCPP in", data)
75
+            },
76
+            messageOut: (data) => {
77
+              log.debug("OCPP out", data)
78
+            },
79
+            connected() {
80
+              log.debug("OCPP connected")
81
+            },
82
+            disconnected({code, reason}) {
83
+              log.debug("OCPP disconnected", {code, reason})
84
+            },
85
+            subscribed(subscriptions: number): void {},
86
+            unsubscribed(subscriptions: number): void {},
87
+          },
88
+        }
89
+      )
90
+
91
+      log.info(
92
+        `Connected to Central System at ${this.config.centralSystemEndpoint} using WebSocket`
93
+      )
94
+
95
+      this.centralSystem = remote
96
+    }
97
+
98
+    if (this.config.defaultHeartbeatIntervalSec) {
99
+      setInterval(() => {
100
+        this.centralSystem.Heartbeat()
101
+      }, this.config.defaultHeartbeatIntervalSec * 1000)
102
+    }
103
+  }
104
+
105
+  public startTransaction({connectorId, idTag}, delay) {
106
+    if (this.meterTimer) {
107
+      return false
108
+    }
109
+
110
+    setTimeout(
111
+      async () => {
112
+        this.transactionId = (
113
+          await this.centralSystem.StartTransaction({
114
+            connectorId,
115
+            idTag,
116
+            timestamp: new Date(),
117
+            meterStart: 0,
118
+          })
119
+        ).transactionId
120
+
121
+        this.charged = 0
122
+
123
+        this.meterTimer = setInterval(() => {
124
+          this.charged += Math.random() > 0.66 ? 30 : 20 // 26.6 W / 10s avg = 9.36 Kw
125
+
126
+          this.centralSystem.MeterValues({
127
+            connectorId,
128
+            transactionId: this.transactionId,
129
+            meterValue: [
130
+              {
131
+                timestamp: new Date(),
132
+                sampledValue: [
133
+                  {
134
+                    value: "" + this.charged,
135
+                    measurand: "Energy.Active.Import.Register",
136
+                    unit: "Wh",
137
+                  },
138
+                  {
139
+                    value: "38",
140
+                    measurand: "SoC",
141
+                    unit: "Percent",
142
+                  },
143
+                ],
144
+              },
145
+            ],
146
+          })
147
+        }, this.config.meterValuesIntervalSec * 1000)
148
+      },
149
+      delay ? this.config.startDelayMs : 0
150
+    )
151
+
152
+    return true
153
+  }
154
+
155
+  public stopTransaction(delay) {
156
+    if (!this.meterTimer) {
157
+      return false
158
+    }
159
+
160
+    clearInterval(this.meterTimer)
161
+
162
+    setTimeout(
163
+      async () => {
164
+        await this.centralSystem.StopTransaction({
165
+          transactionId: this.transactionId,
166
+          timestamp: new Date(),
167
+          meterStop: this.charged,
168
+        })
169
+
170
+        this.meterTimer = null
171
+        this.transactionId = null
172
+      },
173
+      delay ? this.config.stopDelayMs : 0
174
+    )
175
+
176
+    return true
177
+  }
178
+
179
+  disconnect() {
180
+    ws.close()
181
+  }
182
+
183
+  public centralSystem = null
184
+
185
+  private config: Config = null
186
+  private meterTimer = null
187
+  private charged = 0
188
+  private configurationKeys = []
189
+  private transactionId = null
190
+  private chargePoint = {
191
+    RemoteStartTransaction: async (req) => {
192
+      return {
193
+        status: this.startTransaction(req, true) ? "Accepted" : "Rejected",
194
+        // status: "Rejected",
195
+      }
196
+    },
197
+
198
+    RemoteStopTransaction: async (req) => {
199
+      return {
200
+        status: this.stopTransaction(true) ? "Accepted" : "Rejected",
201
+      }
202
+    },
203
+
204
+    GetConfiguration: async (req) => {
205
+      await new Promise((r) => setTimeout(r, 2000))
206
+
207
+      return {configurationKey: this.configurationKeys}
208
+    },
209
+    ChangeConfiguration: async (req) => {
210
+      for (let i = 0; i < this.configurationKeys.length; i++) {
211
+        if (this.configurationKeys[i].key == req.key) {
212
+          this.configurationKeys[i].value = "" + req.value
213
+        }
214
+      }
215
+
216
+      return {status: "Accepted"}
217
+    },
218
+
219
+    ReserveNow: async (req) => {
220
+      return {status: "Accepted"}
221
+    },
222
+
223
+    CancelReservation: async (req) => {
224
+      return {status: "Accepted"}
225
+    },
226
+
227
+    Reset: async (req) => {
228
+      return {status: "Accepted"}
229
+    },
230
+
231
+    TriggerMessage: async (req) => {
232
+      return {status: "Accepted"}
233
+    },
234
+
235
+    UpdateFirmware: async (req) => {
236
+      return {status: "Accepted"}
237
+    },
238
+  }
239
+}

+ 156 - 0
charger-simulator/src/chargerSimulatorCli.ts

@@ -0,0 +1,156 @@
1
+import * as commandLineArgs from "command-line-args"
2
+import * as commandLineUsage from "command-line-usage"
3
+import * as readline from "readline"
4
+
5
+import {log} from "./log"
6
+import {ChargerSimulator} from "./ChargerSimulator"
7
+
8
+const optionList = [
9
+  {
10
+    name: "csURL",
11
+    type: String,
12
+    description:
13
+      "URL of the Central System server to connect to, ws://server.name/path.\nThis is also a default option.",
14
+    typeLabel: "{underline URL}",
15
+    alias: "s",
16
+    defaultOption: true,
17
+  },
18
+  {
19
+    name: "cpPort",
20
+    type: Number,
21
+    description:
22
+      "Port number to bind ChargePoint SOAP service. If specified, emulator will use SOAP protocol to connect to Central System, otherwise, WebSocket will be used",
23
+    typeLabel: "{underline Number}",
24
+    alias: "p",
25
+  },
26
+  {
27
+    name: "chargerId",
28
+    type: String,
29
+    description: "OCPP ID to be used for simulating charger.\nDefault is 'test'.",
30
+    typeLabel: "{underline ChargerId}",
31
+    alias: "i",
32
+    defaultValue: "test",
33
+  },
34
+  {
35
+    name: "connectorId",
36
+    type: String,
37
+    description: "ID of the connector to send status when pressing keys.\nDefaults to 1.",
38
+    typeLabel: "{underline ConnectorId}",
39
+    alias: "c",
40
+    defaultValue: 1,
41
+  },
42
+  {
43
+    name: "idTag",
44
+    type: String,
45
+    description: "ID Tag to start transaction.\nDefaults to 123456.",
46
+    typeLabel: "{underline idTag}",
47
+    alias: "t",
48
+    defaultValue: "12345678",
49
+  },
50
+]
51
+
52
+const usageSections = [
53
+  {
54
+    header: "charger-simulator",
55
+    content: "Start OCPP charging station simulator, connect simulator to Central System server.",
56
+  },
57
+  {
58
+    header: "Options",
59
+    optionList,
60
+  },
61
+]
62
+
63
+;(async () => {
64
+  const {connectorId, csURL, cpPort, chargerId, idTag} = commandLineArgs(optionList)
65
+
66
+  if (!connectorId || !csURL || !chargerId) {
67
+    const usage = commandLineUsage(usageSections)
68
+    console.log(usage)
69
+    return
70
+  }
71
+
72
+  log.info("Starting charger simulator", {
73
+    csURL,
74
+    connectorId,
75
+    chargerId,
76
+    idTag,
77
+  })
78
+
79
+  const simulator = new ChargerSimulator({
80
+    centralSystemEndpoint: csURL,
81
+    chargerIdentity: chargerId,
82
+    chargePointPort: cpPort,
83
+  })
84
+  await simulator.start()
85
+
86
+  log.info(`Supported keys:
87
+    Ctrl+C:   quit
88
+    
89
+    --
90
+    b:        send BootNotification
91
+    d:        send DataTransfer
92
+    i:        disconnect from Central System
93
+    
94
+    Connector ${connectorId} status
95
+    ---
96
+    a:        send Available status 
97
+    p:        send Preparing status
98
+    c:        send Charging status
99
+    e:        send SuspendedEV status
100
+    f:        send Finishing status
101
+    
102
+    Transaction on connector ${connectorId}, tag ${idTag}
103
+    --
104
+    u:        Authorize
105
+    s:        StartTransaction
106
+    t:        StopTransaction
107
+  `)
108
+
109
+  async function sendStatus(status: string) {
110
+    await simulator.centralSystem.StatusNotification({
111
+      connectorId: connectorId,
112
+      errorCode: "NoError",
113
+      status,
114
+    })
115
+  }
116
+
117
+  const commands = {
118
+    b: () =>
119
+      simulator.centralSystem.BootNotification({
120
+        chargePointVendor: "OC",
121
+        chargePointModel: "OCX",
122
+      }),
123
+    d: () =>
124
+      simulator.centralSystem.DataTransfer({
125
+        vendorId: "Emulator",
126
+        messageId: "MessageID",
127
+        data: "Data",
128
+      }),
129
+
130
+    i: () => simulator.disconnect(),
131
+
132
+    a: () => sendStatus("Available"),
133
+    p: () => sendStatus("Preparing"),
134
+    c: () => sendStatus("Charging"),
135
+    e: () => sendStatus("SuspendedEV"),
136
+    f: () => sendStatus("Finishing"),
137
+
138
+    u: () => simulator.centralSystem.Authorize({idTag}),
139
+    s: () => simulator.startTransaction({idTag, connectorId}, false),
140
+    t: () => simulator.stopTransaction(false),
141
+  }
142
+
143
+  readline.emitKeypressEvents(process.stdin)
144
+  process.stdin.setRawMode(true)
145
+
146
+  process.stdin.on("keypress", (ch, key) => {
147
+    if (key.ctrl && key.name === "c") {
148
+      process.exit()
149
+    }
150
+
151
+    if (ch) {
152
+      const command = commands[ch]
153
+      command && command()
154
+    }
155
+  })
156
+})()

+ 5 - 0
charger-simulator/src/log.ts

@@ -0,0 +1,5 @@
1
+export const log = {
2
+  info: (s, ...rest) => console.log(`[info] ${s}`, ...rest),
3
+  debug: (s, ...rest) => console.log(`[debug] ${s}`, ...rest),
4
+  error: (s, ...rest) => console.log(`[error] ${s}`, ...rest),
5
+}

+ 160 - 0
charger-simulator/src/soap/nodeSoapUtils.ts

@@ -0,0 +1,160 @@
1
+import * as fs from "fs"
2
+import * as http from "http"
3
+import {soap} from "strong-soap"
4
+import {convertDateToString, convertStringToDate, ISO8601, ISO8601_secs, proxify, proxy,} from "./serverUtils"
5
+import {prettyPrintXml} from "./xmlUtils"
6
+import {log} from "../log"
7
+
8
+let server = null
9
+
10
+export function createServer({
11
+  wsdlFile,
12
+  soapService,
13
+  path,
14
+  port,
15
+}): Promise<string> {
16
+  const wsdl = fs.readFileSync(wsdlFile, "utf8")
17
+
18
+  return new Promise((resolve, reject) => {
19
+    const createServer = () => {
20
+      server = http.createServer((request, response) => {
21
+        response.end(`404: Not Found: ${request.url}`)
22
+      })
23
+
24
+      server.listen(port, () => {
25
+        log.info(`OCPP Server is listening on port ${port}`)
26
+        resolve(server)
27
+      })
28
+
29
+      const soapServer = soap.listen(server, path, soapService, wsdl)
30
+      soapServer.log = soapServerLog
31
+    }
32
+
33
+    if (server) {
34
+      server.close(createServer)
35
+    } else {
36
+      createServer()
37
+    }
38
+  })
39
+}
40
+
41
+export async function createClient(chargeBoxId, wsdlFile, endpoint): Promise<any> {
42
+  return new Promise((resolve, reject) => {
43
+    soap.createClient(wsdlFile, {endpoint, attributesKey: "attributes"}, (err, client) => {
44
+      if (err) reject(err)
45
+      else {
46
+        const keys = getClientKeys(client)
47
+
48
+        promisifyClient(chargeBoxId, client, keys)
49
+        resolve(client)
50
+      }
51
+    })
52
+  })
53
+}
54
+
55
+export function getClientKeys(client): string[] {
56
+  const d = client.describe()
57
+
58
+  const service = d[Object.keys(d)[0]]
59
+  const binding = service[Object.keys(service)[0]]
60
+
61
+  return Object.keys(binding)
62
+}
63
+
64
+function uncap(s) {
65
+  return s[0].toLowerCase() + s.substring(1)
66
+}
67
+
68
+function promisifyClient(chargeBoxId, target, keys) {
69
+  target.on("request", (envelope) => {
70
+    logOcppRequest(chargeBoxId, envelope)
71
+  })
72
+
73
+  proxify(
74
+    target,
75
+    (impl, key, message) => {
76
+      return new Promise((resolve, reject) => {
77
+        const inputMessage = wrapMessage(key, soapDateToString(message), "Request")
78
+
79
+        impl(inputMessage, (err, result, envelope) => {
80
+          logOcppResponse(chargeBoxId, envelope)
81
+
82
+          if (err) {
83
+            const e = err.Fault ? err.Fault : err
84
+            log.error(`Failed to call ${key}`, e)
85
+            reject(e)
86
+          } else {
87
+            resolve(result)
88
+          }
89
+        })
90
+      })
91
+    },
92
+    keys
93
+  )
94
+}
95
+
96
+// see https://github.com/strongloop/strong-soap/issues/49
97
+// see https://github.com/strongloop/strong-soap/issues/113
98
+function wrapMessage(operationName, message, wrapperName) {
99
+  return {
100
+    [uncap(operationName) + wrapperName]: message,
101
+  }
102
+}
103
+
104
+function soapDateToString(message) {
105
+  return convertDateToString(message, (d) => d.toISOString())
106
+}
107
+
108
+function soapStringToDate(message) {
109
+  return convertStringToDate(
110
+    message,
111
+    (s) => ISO8601.test(s) || ISO8601_secs.test(s),
112
+    (s) => new Date(s)
113
+  )
114
+}
115
+
116
+/** Convert promise-based WS impl to node-soap compat, also date fixes */
117
+export function promisifyServer(target, keys) {
118
+  return proxy(
119
+    target,
120
+    (impl, key, args, callback, headers, req) => {
121
+      const promise = impl(soapStringToDate(args), headers, req)
122
+
123
+      promise
124
+        .then((r) => {
125
+          callback(wrapMessage(key, soapDateToString(r), "Response"))
126
+        })
127
+        .catch((e) => {
128
+          log.error(`Failed to serve ${key}`, e.Fault ? e.Fault : e)
129
+
130
+          callback(null, {
131
+            Fault: {
132
+              Code: {
133
+                Value: "soap:Sender",
134
+                Subcode: {value: "rpc:BadArguments"},
135
+              },
136
+              Reason: {Text: "Processing Error"},
137
+            },
138
+          })
139
+        })
140
+    },
141
+    keys
142
+  )
143
+}
144
+
145
+function soapServerLog(type, data) {
146
+  if (type == "error") log.error(data)
147
+}
148
+
149
+export async function logOcppRequest(chargeBoxId, envelope) {
150
+  if (process.env.noRequestLogging) return
151
+  const details = await prettyPrintXml(envelope)
152
+  log.debug("OCPP out", details)
153
+
154
+}
155
+
156
+export async function logOcppResponse(chargeBoxId, envelope) {
157
+  if (process.env.noRequestLogging) return
158
+  const details = await prettyPrintXml(envelope)
159
+  log.debug("OCPP in", details)
160
+}

+ 81 - 0
charger-simulator/src/soap/ocppSoap.ts

@@ -0,0 +1,81 @@
1
+// SOAP bindings for OCPP 1.5
2
+
3
+import * as path from "path"
4
+import * as UUID from "uuid-js"
5
+import {createClient, createServer, getClientKeys, promisifyServer} from "./nodeSoapUtils"
6
+import { proxy } from "./serverUtils"
7
+
8
+export function createChargePointServer(target, port) {
9
+  const keys = Object.keys(target)
10
+
11
+  const a = promisifyServer(target, keys)
12
+
13
+  const soapService = {
14
+    ChargePointService: {
15
+      ChargePointServiceSoap12: a,
16
+    },
17
+  }
18
+
19
+  return createServer({
20
+    wsdlFile: path.resolve(__dirname, "wsdl", "15", "ocpp_chargepointservice_1.5_final.wsdl"),
21
+
22
+    path: "/",
23
+    port,
24
+    soapService,
25
+  })
26
+}
27
+
28
+export async function createCentralSystemClient(
29
+  endpoint,
30
+  chargeBoxIdentity,
31
+  chargeBoxEndpoint
32
+): Promise<any> {
33
+  const client = await createClient(
34
+    chargeBoxIdentity,
35
+    path.resolve(__dirname, "wsdl", "15", "ocpp_centralsystemservice_1.5_final.wsdl"),
36
+    endpoint
37
+  )
38
+  return withSetWsAddressingHeaders(
39
+    client,
40
+    chargeBoxIdentity,
41
+    chargeBoxEndpoint,
42
+    endpoint,
43
+    getClientKeys(client),
44
+    "urn://Ocpp/Cs/2012/06/"
45
+  )
46
+}
47
+
48
+function withSetWsAddressingHeaders(
49
+  target,
50
+  chargeBoxIdentity,
51
+  fromEndPoint,
52
+  toEndPoint,
53
+  keys,
54
+  idNs
55
+) {
56
+  const wsa = `xmlns:a="http://www.w3.org/2005/08/addressing"`
57
+
58
+  return proxy(
59
+    target,
60
+    (impl, key, ...args) => {
61
+      target.clearSoapHeaders()
62
+
63
+      const action = "/" + key
64
+      const uuid = UUID.create()
65
+
66
+      target.addSoapHeader(
67
+        `<chargeBoxIdentity xmlns="${idNs}">${chargeBoxIdentity}</chargeBoxIdentity>`
68
+      )
69
+      target.addSoapHeader(`<a:MessageID ${wsa}>urn:uuid:${uuid}</a:MessageID>`)
70
+      target.addSoapHeader(`<a:From ${wsa}><a:Address>${fromEndPoint}</a:Address></a:From>`)
71
+      target.addSoapHeader(
72
+        `<a:ReplyTo ${wsa}><a:Address>http://www.w3.org/2005/08/addressing/anonymous</a:Address></a:ReplyTo>`
73
+      )
74
+      target.addSoapHeader(`<a:To ${wsa}>${toEndPoint}</a:To>`)
75
+      target.addSoapHeader(`<a:Action ${wsa} soap:mustUnderstand="1">${action}</a:Action>`)
76
+
77
+      return impl(...args)
78
+    },
79
+    keys
80
+  )
81
+}

+ 77 - 0
charger-simulator/src/soap/serverUtils.ts

@@ -0,0 +1,77 @@
1
+export type Invoker = (impl, name, ...args) => any
2
+
3
+export function proxy<T extends object>(target: T, invoker: Invoker, keys: string[]): T {
4
+  const r = {...(target as any)}
5
+
6
+  keys.forEach((key) => {
7
+    r[key] = function (...args) {
8
+      const impl = target[key]
9
+      return invoker(impl, key, ...args)
10
+    }
11
+  })
12
+
13
+  return r as any
14
+}
15
+
16
+export function proxify(target: object, invoker: Invoker, keys: string[]): void {
17
+  keys.forEach((key) => {
18
+    const impl = target[key]
19
+
20
+    target[key] = function (...args) {
21
+      return invoker(impl, key, ...args)
22
+    }
23
+  })
24
+}
25
+
26
+export function convertDateToString(message, format) {
27
+  if (!message) return message
28
+
29
+  Object.keys(message).forEach((key) => {
30
+    const prop = message[key]
31
+
32
+    if (typeof prop != "object") return
33
+
34
+    if (prop instanceof Date) {
35
+      message[key] = format(prop)
36
+      return
37
+    }
38
+
39
+    if (!Array.isArray(prop)) return convertDateToString(prop, format)
40
+
41
+    for (let i = 0; i < prop.length; i++) {
42
+      convertDateToString(prop[i], format)
43
+    }
44
+  })
45
+
46
+  return message
47
+}
48
+
49
+export function convertStringToDate(message, match, parse) {
50
+  if (!message) return message
51
+
52
+  Object.keys(message).forEach((key) => {
53
+    const prop = message[key]
54
+
55
+    if (!prop) return
56
+
57
+    if (typeof prop == "string") {
58
+      if (match(prop)) message[key] = parse(prop)
59
+
60
+      return
61
+    }
62
+
63
+    if (typeof prop != "object") return
64
+
65
+    if (!Array.isArray(prop)) return convertStringToDate(prop, match, parse)
66
+
67
+    for (let i = 0; i < prop.length; i++) {
68
+      convertStringToDate(prop[i], match, parse)
69
+    }
70
+  })
71
+
72
+  return message
73
+}
74
+
75
+export const ISO8601 = /^\d\d\d\d-\d\d-\d\dT\d\d:\d\d:\d\d.\d\d\dZ$/
76
+export const ISO8601_secs = /^\d\d\d\d-\d\d-\d\dT\d\d:\d\d:\d\dZ$/
77
+export const ISO8601_date = /^\d\d\d\d-\d\d-\d\d$/

+ 757 - 0
charger-simulator/src/soap/wsdl/15/ocpp_centralsystemservice_1.5_final.wsdl

@@ -0,0 +1,757 @@
1
+<?xml version="1.0" encoding="utf-8"?>
2
+<!--
3
+OCPP Central System service description
4
+Version 1.5 draft for approval (1.5 RC4)
5
+
6
+Copyright e-laad.nl. Free to use without modifications.
7
+
8
+See: http://ev-services.net/ocpp/
9
+-->
10
+<wsdl:definitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
11
+                  xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
12
+                  xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/"
13
+                  xmlns:s="http://www.w3.org/2001/XMLSchema"
14
+                  xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/"
15
+                  xmlns:http="http://schemas.xmlsoap.org/wsdl/http/"
16
+                  xmlns:tns="urn://Ocpp/Cs/2012/06/"
17
+                  targetNamespace="urn://Ocpp/Cs/2012/06/"
18
+                  xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
19
+                  xmlns:wsaw="http://www.w3.org/2006/05/addressing/wsdl"
20
+                  xmlns:wsa="http://www.w3.org/2005/08/addressing"
21
+                  xmlns:wsp="http://schemas.xmlsoapf.org/ws/2004/09/policy"
22
+                  xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
23
+
24
+    <wsp:Policy wsu:Id="ServicePolicy">
25
+        <wsp:ExactlyOne>
26
+            <wsp:All>
27
+                <wsaw:UsingAddressing/>
28
+            </wsp:All>
29
+        </wsp:ExactlyOne>
30
+    </wsp:Policy>
31
+
32
+    <wsdl:types>
33
+        <s:schema targetNamespace="urn://Ocpp/Cs/2012/06/" elementFormDefault="qualified">
34
+
35
+            <!-- Begin of types shared with ChargePointService -->
36
+            <s:simpleType name="IdToken">
37
+                <s:annotation>
38
+                    <s:documentation>Type of string defining identification token, e.g. RFID or credit card number. To be treated as case insensitive.</s:documentation>
39
+                </s:annotation>
40
+                <s:restriction base="s:string">
41
+                    <s:maxLength value="20"/>
42
+                </s:restriction>
43
+            </s:simpleType>
44
+
45
+            <s:simpleType name="AuthorizationStatus">
46
+                <s:annotation>
47
+                    <s:documentation>Defines the authorization-status-value</s:documentation>
48
+                </s:annotation>
49
+                <s:restriction base="s:string">
50
+                    <s:enumeration value="Accepted"/>
51
+                    <s:enumeration value="Blocked"/>
52
+                    <s:enumeration value="Expired"/>
53
+                    <s:enumeration value="Invalid"/>
54
+                    <s:enumeration value="ConcurrentTx"/>
55
+                </s:restriction>
56
+            </s:simpleType>
57
+
58
+            <s:complexType name="IdTagInfo">
59
+                <s:sequence>
60
+                    <s:element name="status" type="tns:AuthorizationStatus" minOccurs="1" maxOccurs="1"/>
61
+                    <s:element name="expiryDate" type="s:dateTime" minOccurs="0" maxOccurs="1"/>
62
+                    <s:element name="parentIdTag" type="tns:IdToken" minOccurs="0" maxOccurs="1"/>
63
+                </s:sequence>
64
+            </s:complexType>
65
+            <!-- End of types shared with ChargePointService -->
66
+
67
+            <s:simpleType name="ChargeBoxSerialNumber">
68
+                <s:annotation>
69
+                    <s:documentation>String type of max 25 chars that is to be treated as case insensitive.</s:documentation>
70
+                </s:annotation>
71
+                <s:restriction base="s:string">
72
+                    <s:maxLength value="25"/>
73
+                </s:restriction>
74
+            </s:simpleType>
75
+
76
+            <s:simpleType name="ChargePointModel">
77
+                <s:annotation>
78
+                    <s:documentation>String type of max 20 chars that is to be treated as case insensitive.</s:documentation>
79
+                </s:annotation>
80
+                <s:restriction base="s:string">
81
+                    <s:maxLength value="20"/>
82
+                </s:restriction>
83
+            </s:simpleType>
84
+
85
+            <s:simpleType name="ChargePointSerialNumber">
86
+                <s:annotation>
87
+                    <s:documentation>String type of max 25 chars that is to be treated as case insensitive.</s:documentation>
88
+                </s:annotation>
89
+                <s:restriction base="s:string">
90
+                    <s:maxLength value="25"/>
91
+                </s:restriction>
92
+            </s:simpleType>
93
+
94
+            <s:simpleType name="ChargePointVendor">
95
+                <s:annotation>
96
+                    <s:documentation>String type of max 20 chars that is to be treated as case insensitive.</s:documentation>
97
+                </s:annotation>
98
+                <s:restriction base="s:string">
99
+                    <s:maxLength value="20"/>
100
+                </s:restriction>
101
+            </s:simpleType>
102
+
103
+            <s:simpleType name="FirmwareVersion">
104
+                <s:annotation>
105
+                    <s:documentation>String type of max 50 chars that is to be treated as case insensitive.</s:documentation>
106
+                </s:annotation>
107
+                <s:restriction base="s:string">
108
+                    <s:maxLength value="50"/>
109
+                </s:restriction>
110
+            </s:simpleType>
111
+
112
+            <s:simpleType name="IccidString">
113
+                <s:annotation>
114
+                    <s:documentation>String type of max 20 chars that is to be treated as case insensitive.</s:documentation>
115
+                </s:annotation>
116
+                <s:restriction base="s:string">
117
+                    <s:maxLength value="20"/>
118
+                </s:restriction>
119
+            </s:simpleType>
120
+
121
+            <s:simpleType name="ImsiString">
122
+                <s:annotation>
123
+                    <s:documentation>String type of max 20 chars that is to be treated as case insensitive.</s:documentation>
124
+                </s:annotation>
125
+                <s:restriction base="s:string">
126
+                    <s:maxLength value="20"/>
127
+                </s:restriction>
128
+            </s:simpleType>
129
+
130
+            <s:simpleType name="MeterSerialNumber">
131
+                <s:annotation>
132
+                    <s:documentation>String type of max 25 chars that is to be treated as case insensitive.</s:documentation>
133
+                </s:annotation>
134
+                <s:restriction base="s:string">
135
+                    <s:maxLength value="25"/>
136
+                </s:restriction>
137
+            </s:simpleType>
138
+
139
+            <s:simpleType name="MeterType">
140
+                <s:annotation>
141
+                    <s:documentation>String type of max 25 chars that is to be treated as case insensitive.</s:documentation>
142
+                </s:annotation>
143
+                <s:restriction base="s:string">
144
+                    <s:maxLength value="25"/>
145
+                </s:restriction>
146
+            </s:simpleType>
147
+
148
+            <s:complexType name="AuthorizeRequest">
149
+                <s:annotation>
150
+                    <s:documentation>Defines the Authorize.req PDU</s:documentation>
151
+                </s:annotation>
152
+                <s:sequence>
153
+                    <s:element name="idTag" type="tns:IdToken" minOccurs="1" maxOccurs="1"/>
154
+                </s:sequence>
155
+            </s:complexType>
156
+
157
+            <s:complexType name="AuthorizeResponse">
158
+                <s:annotation>
159
+                    <s:documentation>Defines the Authorize.conf PDU</s:documentation>
160
+                </s:annotation>
161
+                <s:sequence>
162
+                    <s:element name="idTagInfo" type="tns:IdTagInfo" minOccurs="1" maxOccurs="1"/>
163
+                </s:sequence>
164
+            </s:complexType>
165
+
166
+            <s:complexType name="StartTransactionRequest">
167
+                <s:annotation>
168
+                    <s:documentation>Defines the StartTransaction.req PDU</s:documentation>
169
+                </s:annotation>
170
+                <s:sequence>
171
+                    <s:element name="connectorId" type="s:int" minOccurs="1" maxOccurs="1"/>
172
+                    <s:element name="idTag" type="tns:IdToken" minOccurs="1" maxOccurs="1"/>
173
+                    <s:element name="timestamp" type="s:dateTime" minOccurs="1" maxOccurs="1"/>
174
+                    <s:element name="meterStart" type="s:int" minOccurs="1" maxOccurs="1"/>
175
+                    <s:element name="reservationId" type="s:int" minOccurs="0" maxOccurs="1"/>
176
+                </s:sequence>
177
+            </s:complexType>
178
+
179
+            <s:complexType name="StartTransactionResponse">
180
+                <s:annotation>
181
+                    <s:documentation>Defines the StartTransaction.conf PDU</s:documentation>
182
+                </s:annotation>
183
+                <s:sequence>
184
+                    <s:element name="transactionId" type="s:int" minOccurs="1" maxOccurs="1"/>
185
+                    <s:element name="idTagInfo" type="tns:IdTagInfo" minOccurs="1" maxOccurs="1"/>
186
+                </s:sequence>
187
+            </s:complexType>
188
+
189
+            <s:complexType name="TransactionData">
190
+                <s:annotation>
191
+                    <s:documentation>This contains transaction usage details relevant for billing purposes in StopTransaction.req PDU</s:documentation>
192
+                </s:annotation>
193
+                <s:sequence>
194
+                    <s:element name="values" type="tns:MeterValue" minOccurs="0" maxOccurs="unbounded"/>
195
+                </s:sequence>
196
+            </s:complexType>
197
+
198
+            <s:complexType name="StopTransactionRequest">
199
+                <s:annotation>
200
+                    <s:documentation>Defines the StopTransaction.req PDU</s:documentation>
201
+                </s:annotation>
202
+                <s:sequence>
203
+                    <s:element name="transactionId" type="s:int" minOccurs="1" maxOccurs="1"/>
204
+                    <s:element name="idTag" type="tns:IdToken" minOccurs="0" maxOccurs="1"/>
205
+                    <s:element name="timestamp" type="s:dateTime" minOccurs="1" maxOccurs="1"/>
206
+                    <s:element name="meterStop" type="s:int" minOccurs="1" maxOccurs="1"/>
207
+                    <s:element name="transactionData" type="tns:TransactionData" minOccurs="0" maxOccurs="unbounded"/>
208
+                </s:sequence>
209
+            </s:complexType>
210
+
211
+            <s:complexType name="StopTransactionResponse">
212
+                <s:annotation>
213
+                    <s:documentation>Defines the StopTransaction.conf PDU</s:documentation>
214
+                </s:annotation>
215
+                <s:sequence>
216
+                    <s:element name="idTagInfo" type="tns:IdTagInfo" minOccurs="0" maxOccurs="1"/>
217
+                </s:sequence>
218
+            </s:complexType>
219
+
220
+            <s:complexType name="HeartbeatRequest">
221
+                <s:annotation>
222
+                    <s:documentation>Defines the Heartbeat.req PDU</s:documentation>
223
+                </s:annotation>
224
+            </s:complexType>
225
+
226
+            <s:complexType name="HeartbeatResponse">
227
+                <s:annotation>
228
+                    <s:documentation>Defines the Heartbeat.conf PDU</s:documentation>
229
+                </s:annotation>
230
+                <s:sequence>
231
+                    <s:element name="currentTime" type="s:dateTime" minOccurs="1" maxOccurs="1"/>
232
+                </s:sequence>
233
+            </s:complexType>
234
+
235
+            <s:simpleType name="ReadingContext">
236
+                <s:restriction base="s:string">
237
+                    <s:enumeration value="Interruption.Begin"/>
238
+                    <s:enumeration value="Interruption.End"/>
239
+                    <s:enumeration value="Sample.Clock"/>
240
+                    <s:enumeration value="Sample.Periodic"/>
241
+                    <s:enumeration value="Transaction.Begin"/>
242
+                    <s:enumeration value="Transaction.End"/>
243
+                </s:restriction>
244
+            </s:simpleType>
245
+
246
+            <s:simpleType name="Measurand">
247
+                <s:restriction base="s:string">
248
+                    <s:enumeration value="Energy.Active.Export.Register"/>
249
+                    <s:enumeration value="Energy.Active.Import.Register"/>
250
+                    <s:enumeration value="Energy.Reactive.Export.Register"/>
251
+                    <s:enumeration value="Energy.Reactive.Import.Register"/>
252
+                    <s:enumeration value="Energy.Active.Export.Interval"/>
253
+                    <s:enumeration value="Energy.Active.Import.Interval"/>
254
+                    <s:enumeration value="Energy.Reactive.Export.Interval"/>
255
+                    <s:enumeration value="Energy.Reactive.Import.Interval"/>
256
+                    <s:enumeration value="Power.Active.Export"/>
257
+                    <s:enumeration value="Power.Active.Import"/>
258
+                    <s:enumeration value="Power.Reactive.Export"/>
259
+                    <s:enumeration value="Power.Reactive.Import"/>
260
+                    <s:enumeration value="Current.Export"/>
261
+                    <s:enumeration value="Current.Import"/>
262
+                    <s:enumeration value="Voltage"/>
263
+                    <s:enumeration value="Temperature"/>
264
+                </s:restriction>
265
+            </s:simpleType>
266
+
267
+            <s:simpleType name="ValueFormat">
268
+                <s:restriction base="s:string">
269
+                    <s:enumeration value="Raw"/>
270
+                    <s:enumeration value="SignedData"/>
271
+                </s:restriction>
272
+            </s:simpleType>
273
+
274
+            <s:simpleType name="UnitOfMeasure">
275
+                <s:restriction base="s:string">
276
+                    <s:enumeration value="Wh"/>
277
+                    <s:enumeration value="kWh"/>
278
+                    <s:enumeration value="varh"/>
279
+                    <s:enumeration value="kvarh"/>
280
+                    <s:enumeration value="W"/>
281
+                    <s:enumeration value="kW"/>
282
+                    <s:enumeration value="var"/>
283
+                    <s:enumeration value="kvar"/>
284
+                    <s:enumeration value="Amp"/>
285
+                    <s:enumeration value="Volt"/>
286
+                    <s:enumeration value="Celsius"/>
287
+                </s:restriction>
288
+            </s:simpleType>
289
+
290
+            <s:simpleType name="Location">
291
+                <s:restriction base="s:string">
292
+                    <s:enumeration value="Inlet"/>
293
+                    <s:enumeration value="Outlet"/>
294
+                    <s:enumeration value="Body"/>
295
+                </s:restriction>
296
+            </s:simpleType>
297
+
298
+            <s:complexType name="MeterValue">
299
+                <s:annotation>
300
+                    <s:documentation>Defines single value of the meter-value-value</s:documentation>
301
+                </s:annotation>
302
+                <s:sequence>
303
+                    <s:element name="timestamp" type="s:dateTime"/>
304
+                    <s:element name="value" minOccurs="1" maxOccurs="unbounded">
305
+                        <s:complexType>
306
+                            <s:simpleContent>
307
+                                <s:extension base="s:string">
308
+                                    <s:attribute name="context" type="tns:ReadingContext" use="optional"/> <!-- default="Sample.Periodic" -->
309
+                                    <s:attribute name="format" type="tns:ValueFormat" use="optional"/> <!-- default="Raw" -->
310
+                                    <s:attribute name="measurand" type="tns:Measurand" use="optional"/> <!-- default="Energy.Active.Import.Register" -->
311
+                                    <s:attribute name="location" type="tns:Location" use="optional"/> <!-- default="Outlet" -->
312
+                                    <s:attribute name="unit" type="tns:UnitOfMeasure" use="optional"/> <!-- default="Wh" -->
313
+                                </s:extension>
314
+                            </s:simpleContent>
315
+                        </s:complexType>
316
+                    </s:element>
317
+                </s:sequence>
318
+            </s:complexType>
319
+
320
+            <s:complexType name="MeterValuesRequest">
321
+                <s:annotation>
322
+                    <s:documentation>Defines the MeterValues.req PDU</s:documentation>
323
+                </s:annotation>
324
+                <s:sequence>
325
+                    <s:element name="connectorId" type="s:int" minOccurs="1" maxOccurs="1"/>
326
+                    <s:element name="transactionId" type="s:int" minOccurs="0" maxOccurs="1"/>
327
+                    <s:element name="values" type="tns:MeterValue" minOccurs="0" maxOccurs="unbounded"/>
328
+                </s:sequence>
329
+            </s:complexType>
330
+
331
+            <s:complexType name="MeterValuesResponse">
332
+                <s:annotation>
333
+                    <s:documentation>Defines the MeterValues.conf PDU</s:documentation>
334
+                </s:annotation>
335
+            </s:complexType>
336
+
337
+            <s:complexType name="BootNotificationRequest">
338
+                <s:annotation>
339
+                    <s:documentation>Defines the BootNotification.req PDU</s:documentation>
340
+                </s:annotation>
341
+                <s:sequence>
342
+                    <s:element name="chargePointVendor" type="tns:ChargePointVendor" minOccurs="1" maxOccurs="1"/>
343
+                    <s:element name="chargePointModel" type="tns:ChargePointModel" minOccurs="1" maxOccurs="1"/>
344
+                    <s:element name="chargePointSerialNumber" type="tns:ChargePointSerialNumber" minOccurs="0" maxOccurs="1"/>
345
+                    <s:element name="chargeBoxSerialNumber" type="tns:ChargeBoxSerialNumber" minOccurs="0" maxOccurs="1"/>
346
+                    <s:element name="firmwareVersion" type="tns:FirmwareVersion" minOccurs="0" maxOccurs="1"/>
347
+                    <s:element name="iccid" type="tns:IccidString" minOccurs="0" maxOccurs="1"/>
348
+                    <s:element name="imsi" type="tns:ImsiString" minOccurs="0" maxOccurs="1"/>
349
+                    <s:element name="meterType" type="tns:MeterType" minOccurs="0" maxOccurs="1"/>
350
+                    <s:element name="meterSerialNumber" type="tns:MeterSerialNumber" minOccurs="0" maxOccurs="1"/>
351
+                </s:sequence>
352
+            </s:complexType>
353
+
354
+            <s:simpleType name="RegistrationStatus">
355
+                <s:annotation>
356
+                    <s:documentation>Defines the registration-status-value</s:documentation>
357
+                </s:annotation>
358
+                <s:restriction base="s:string">
359
+                    <s:enumeration value="Accepted"/>
360
+                    <s:enumeration value="Rejected"/>
361
+                </s:restriction>
362
+            </s:simpleType>
363
+
364
+            <s:complexType name="BootNotificationResponse">
365
+                <s:annotation>
366
+                    <s:documentation>Defines the BootNotification.conf PDU</s:documentation>
367
+                </s:annotation>
368
+                <s:sequence>
369
+                    <s:element name="status" type="tns:RegistrationStatus" minOccurs="1" maxOccurs="1"/>
370
+                    <s:element name="currentTime" type="s:dateTime" minOccurs="1" maxOccurs="1"/>
371
+                    <s:element name="heartbeatInterval" type="s:int" minOccurs="1" maxOccurs="1"/>
372
+                </s:sequence>
373
+            </s:complexType>
374
+
375
+            <s:simpleType name="ChargePointErrorCode">
376
+                <s:annotation>
377
+                    <s:documentation>Defines the charge-point-error-value</s:documentation>
378
+                </s:annotation>
379
+                <s:restriction base="s:string">
380
+                    <s:enumeration value="ConnectorLockFailure"/>
381
+                    <s:enumeration value="HighTemperature"/>
382
+                    <s:enumeration value="Mode3Error"/>
383
+                    <s:enumeration value="NoError"/>
384
+                    <s:enumeration value="PowerMeterFailure"/>
385
+                    <s:enumeration value="PowerSwitchFailure"/>
386
+                    <s:enumeration value="ReaderFailure"/>
387
+                    <s:enumeration value="ResetFailure"/>
388
+                    <s:enumeration value="GroundFailure"/>
389
+                    <s:enumeration value="OverCurrentFailure"/>
390
+                    <s:enumeration value="UnderVoltage"/>
391
+                    <s:enumeration value="WeakSignal"/>
392
+                    <s:enumeration value="OtherError"/>
393
+                </s:restriction>
394
+            </s:simpleType>
395
+
396
+            <s:simpleType name="ChargePointStatus">
397
+                <s:annotation>
398
+                    <s:documentation>Defines the charge-point-status-value</s:documentation>
399
+                </s:annotation>
400
+                <s:restriction base="s:string">
401
+                    <s:enumeration value="Available"/>
402
+                    <s:enumeration value="Occupied"/>
403
+                    <s:enumeration value="Faulted"/>
404
+                    <s:enumeration value="Unavailable"/>
405
+                    <s:enumeration value="Reserved"/>
406
+                </s:restriction>
407
+            </s:simpleType>
408
+
409
+            <s:complexType name="StatusNotificationRequest">
410
+                <s:annotation>
411
+                    <s:documentation>Defines the StatusNotification.req PDU</s:documentation>
412
+                </s:annotation>
413
+                <s:sequence>
414
+                    <s:element name="connectorId" type="s:int" minOccurs="1" maxOccurs="1"/>
415
+                    <s:element name="status" type="tns:ChargePointStatus" minOccurs="1" maxOccurs="1"/>
416
+                    <s:element name="errorCode" type="tns:ChargePointErrorCode" minOccurs="1" maxOccurs="1"/>
417
+                    <s:element name="info" type="s:string" minOccurs="0" maxOccurs="1"/>
418
+                    <s:element name="timestamp" type="s:dateTime" minOccurs="0" maxOccurs="1"/>
419
+                    <s:element name="vendorId" type="s:string" minOccurs="0" maxOccurs="1"/>
420
+                    <s:element name="vendorErrorCode" type="s:string" minOccurs="0" maxOccurs="1"/>
421
+                </s:sequence>
422
+            </s:complexType>
423
+
424
+            <s:complexType name="StatusNotificationResponse">
425
+                <s:annotation>
426
+                    <s:documentation>Defines the StatusNotification.conf PDU</s:documentation>
427
+                </s:annotation>
428
+            </s:complexType>
429
+
430
+            <s:simpleType name="FirmwareStatus">
431
+                <s:annotation>
432
+                    <s:documentation>Defines the firmware-status-value</s:documentation>
433
+                </s:annotation>
434
+                <s:restriction base="s:string">
435
+                    <s:enumeration value="Downloaded"/>
436
+                    <s:enumeration value="DownloadFailed"/>
437
+                    <s:enumeration value="InstallationFailed"/>
438
+                    <s:enumeration value="Installed"/>
439
+                </s:restriction>
440
+            </s:simpleType>
441
+
442
+            <s:complexType name="FirmwareStatusNotificationRequest">
443
+                <s:annotation>
444
+                    <s:documentation>Defines the FirmwareStatusNotification.req PDU</s:documentation>
445
+                </s:annotation>
446
+                <s:sequence>
447
+                    <s:element name="status" type="tns:FirmwareStatus" minOccurs="1" maxOccurs="1"/>
448
+                </s:sequence>
449
+            </s:complexType>
450
+
451
+            <s:complexType name="FirmwareStatusNotificationResponse">
452
+                <s:annotation>
453
+                    <s:documentation>Defines the FirmwareStatusNotification.conf PDU</s:documentation>
454
+                </s:annotation>
455
+            </s:complexType>
456
+
457
+            <s:simpleType name="DiagnosticsStatus">
458
+                <s:annotation>
459
+                    <s:documentation>Defines the diagnostics-status-value</s:documentation>
460
+                </s:annotation>
461
+                <s:restriction base="s:string">
462
+                    <s:enumeration value="Uploaded"/>
463
+                    <s:enumeration value="UploadFailed"/>
464
+                </s:restriction>
465
+            </s:simpleType>
466
+
467
+            <s:complexType name="DiagnosticsStatusNotificationRequest">
468
+                <s:annotation>
469
+                    <s:documentation>Defines the DiagnosticsStatusNotification.req PDU</s:documentation>
470
+                </s:annotation>
471
+                <s:sequence>
472
+                    <s:element name="status" type="tns:DiagnosticsStatus" minOccurs="1" maxOccurs="1"/>
473
+                </s:sequence>
474
+            </s:complexType>
475
+
476
+            <s:complexType name="DiagnosticsStatusNotificationResponse">
477
+                <s:annotation>
478
+                    <s:documentation>Defines the DiagnosticsStatusNotification.conf PDU</s:documentation>
479
+                </s:annotation>
480
+            </s:complexType>
481
+
482
+            <s:complexType name="DataTransferRequest">
483
+                <s:annotation>
484
+                    <s:documentation>Defines the DataTransfer.req PDU</s:documentation>
485
+                </s:annotation>
486
+                <s:sequence>
487
+                    <s:element name="vendorId" type="s:string" minOccurs="1" maxOccurs="1"/>
488
+                    <s:element name="messageId" type="s:string" minOccurs="0" maxOccurs="1"/>
489
+                    <s:element name="data" type="s:string" minOccurs="0" maxOccurs="1"/>
490
+                </s:sequence>
491
+            </s:complexType>
492
+
493
+            <s:simpleType name="DataTransferStatus">
494
+                <s:annotation>
495
+                    <s:documentation>Defines the status returned in DataTransfer.conf</s:documentation>
496
+                </s:annotation>
497
+                <s:restriction base="s:string">
498
+                    <s:enumeration value="Accepted"/>
499
+                    <s:enumeration value="Rejected"/>
500
+                    <s:enumeration value="UnknownMessageId"/>
501
+                    <s:enumeration value="UnknownVendorId"/>
502
+                </s:restriction>
503
+            </s:simpleType>
504
+
505
+            <s:complexType name="DataTransferResponse">
506
+                <s:annotation>
507
+                    <s:documentation>Defines the DataTransfer.conf PDU</s:documentation>
508
+                </s:annotation>
509
+                <s:sequence>
510
+                    <s:element name="status" type="tns:DataTransferStatus" minOccurs="1" maxOccurs="1"/>
511
+                    <s:element name="data" type="s:string" minOccurs="0" maxOccurs="1"/>
512
+                </s:sequence>
513
+            </s:complexType>
514
+
515
+            <s:element name="chargeBoxIdentity" type="s:string"/>
516
+            <s:element name="authorizeRequest" type="tns:AuthorizeRequest"/>
517
+            <s:element name="authorizeResponse" type="tns:AuthorizeResponse"/>
518
+            <s:element name="startTransactionRequest" type="tns:StartTransactionRequest"/>
519
+            <s:element name="startTransactionResponse" type="tns:StartTransactionResponse"/>
520
+            <s:element name="stopTransactionRequest" type="tns:StopTransactionRequest"/>
521
+            <s:element name="stopTransactionResponse" type="tns:StopTransactionResponse"/>
522
+            <s:element name="heartbeatRequest" type="tns:HeartbeatRequest"/>
523
+            <s:element name="heartbeatResponse" type="tns:HeartbeatResponse"/>
524
+            <s:element name="meterValuesRequest" type="tns:MeterValuesRequest"/>
525
+            <s:element name="meterValuesResponse" type="tns:MeterValuesResponse"/>
526
+            <s:element name="bootNotificationRequest" type="tns:BootNotificationRequest"/>
527
+            <s:element name="bootNotificationResponse" type="tns:BootNotificationResponse"/>
528
+            <s:element name="statusNotificationRequest" type="tns:StatusNotificationRequest"/>
529
+            <s:element name="statusNotificationResponse" type="tns:StatusNotificationResponse"/>
530
+            <s:element name="firmwareStatusNotificationRequest" type="tns:FirmwareStatusNotificationRequest"/>
531
+            <s:element name="firmwareStatusNotificationResponse" type="tns:FirmwareStatusNotificationResponse"/>
532
+            <s:element name="diagnosticsStatusNotificationRequest" type="tns:DiagnosticsStatusNotificationRequest"/>
533
+            <s:element name="diagnosticsStatusNotificationResponse" type="tns:DiagnosticsStatusNotificationResponse"/>
534
+            <s:element name="dataTransferRequest" type="tns:DataTransferRequest"/>
535
+            <s:element name="dataTransferResponse" type="tns:DataTransferResponse"/>
536
+        </s:schema>
537
+    </wsdl:types>
538
+    <wsdl:message name="Header">
539
+        <wsdl:part name="ChargeBoxIdentity" element="tns:chargeBoxIdentity"/>
540
+    </wsdl:message>
541
+    <wsdl:message name="AuthorizeInput">
542
+        <wsdl:part name="parameters" element="tns:authorizeRequest"/>
543
+    </wsdl:message>
544
+    <wsdl:message name="AuthorizeOutput">
545
+        <wsdl:part name="parameters" element="tns:authorizeResponse"/>
546
+    </wsdl:message>
547
+    <wsdl:message name="StartTransactionInput">
548
+        <wsdl:part name="parameters" element="tns:startTransactionRequest"/>
549
+    </wsdl:message>
550
+    <wsdl:message name="StartTransactionOutput">
551
+        <wsdl:part name="parameters" element="tns:startTransactionResponse"/>
552
+    </wsdl:message>
553
+    <wsdl:message name="StopTransactionInput">
554
+        <wsdl:part name="parameters" element="tns:stopTransactionRequest"/>
555
+    </wsdl:message>
556
+    <wsdl:message name="StopTransactionOutput">
557
+        <wsdl:part name="parameters" element="tns:stopTransactionResponse"/>
558
+    </wsdl:message>
559
+    <wsdl:message name="HeartbeatInput">
560
+        <wsdl:part name="parameters" element="tns:heartbeatRequest"/>
561
+    </wsdl:message>
562
+    <wsdl:message name="HeartbeatOutput">
563
+        <wsdl:part name="parameters" element="tns:heartbeatResponse"/>
564
+    </wsdl:message>
565
+    <wsdl:message name="MeterValuesInput">
566
+        <wsdl:part name="parameters" element="tns:meterValuesRequest"/>
567
+    </wsdl:message>
568
+    <wsdl:message name="MeterValuesOutput">
569
+        <wsdl:part name="parameters" element="tns:meterValuesResponse"/>
570
+    </wsdl:message>
571
+    <wsdl:message name="BootNotificationInput">
572
+        <wsdl:part name="parameters" element="tns:bootNotificationRequest"/>
573
+    </wsdl:message>
574
+    <wsdl:message name="BootNotificationOutput">
575
+        <wsdl:part name="parameters" element="tns:bootNotificationResponse"/>
576
+    </wsdl:message>
577
+    <wsdl:message name="StatusNotificationInput">
578
+        <wsdl:part name="parameters" element="tns:statusNotificationRequest"/>
579
+    </wsdl:message>
580
+    <wsdl:message name="StatusNotificationOutput">
581
+        <wsdl:part name="parameters" element="tns:statusNotificationResponse"/>
582
+    </wsdl:message>
583
+    <wsdl:message name="FirmwareStatusNotificationInput">
584
+        <wsdl:part name="parameters" element="tns:firmwareStatusNotificationRequest"/>
585
+    </wsdl:message>
586
+    <wsdl:message name="FirmwareStatusNotificationOutput">
587
+        <wsdl:part name="parameters" element="tns:firmwareStatusNotificationResponse"/>
588
+    </wsdl:message>
589
+    <wsdl:message name="DiagnosticsStatusNotificationInput">
590
+        <wsdl:part name="parameters" element="tns:diagnosticsStatusNotificationRequest"/>
591
+    </wsdl:message>
592
+    <wsdl:message name="DiagnosticsStatusNotificationOutput">
593
+        <wsdl:part name="parameters" element="tns:diagnosticsStatusNotificationResponse"/>
594
+    </wsdl:message>
595
+    <wsdl:message name="DataTransferInput">
596
+        <wsdl:part name="parameters" element="tns:dataTransferRequest"/>
597
+    </wsdl:message>
598
+    <wsdl:message name="DataTransferOutput">
599
+        <wsdl:part name="parameters" element="tns:dataTransferResponse"/>
600
+    </wsdl:message>
601
+    <wsdl:portType name="CentralSystemService">
602
+        <wsdl:operation name="Authorize">
603
+            <wsdl:input message="tns:AuthorizeInput" wsaw:Action="/Authorize"/>
604
+            <wsdl:output message="tns:AuthorizeOutput" wsaw:Action="/AuthorizeResponse"/>
605
+        </wsdl:operation>
606
+        <wsdl:operation name="StartTransaction">
607
+            <wsdl:input message="tns:StartTransactionInput" wsaw:Action="/StartTransaction"/>
608
+            <wsdl:output message="tns:StartTransactionOutput" wsaw:Action="/StartTransactionResponse"/>
609
+        </wsdl:operation>
610
+        <wsdl:operation name="StopTransaction">
611
+            <wsdl:input message="tns:StopTransactionInput" wsaw:Action="/StopTransaction"/>
612
+            <wsdl:output message="tns:StopTransactionOutput" wsaw:Action="/StopTransactionResponse"/>
613
+        </wsdl:operation>
614
+        <wsdl:operation name="Heartbeat">
615
+            <wsdl:input message="tns:HeartbeatInput" wsaw:Action="/Heartbeat"/>
616
+            <wsdl:output message="tns:HeartbeatOutput" wsaw:Action="/HeartbeatResponse"/>
617
+        </wsdl:operation>
618
+        <wsdl:operation name="MeterValues">
619
+            <wsdl:input message="tns:MeterValuesInput" wsaw:Action="/MeterValues"/>
620
+            <wsdl:output message="tns:MeterValuesOutput" wsaw:Action="/MeterValuesResponse"/>
621
+        </wsdl:operation>
622
+        <wsdl:operation name="BootNotification">
623
+            <wsdl:input message="tns:BootNotificationInput" wsaw:Action="/BootNotification"/>
624
+            <wsdl:output message="tns:BootNotificationOutput" wsaw:Action="/BootNotificationResponse"/>
625
+        </wsdl:operation>
626
+        <wsdl:operation name="StatusNotification">
627
+            <wsdl:input message="tns:StatusNotificationInput" wsaw:Action="/StatusNotification"/>
628
+            <wsdl:output message="tns:StatusNotificationOutput" wsaw:Action="/StatusNotificationResponse"/>
629
+        </wsdl:operation>
630
+        <wsdl:operation name="FirmwareStatusNotification">
631
+            <wsdl:input message="tns:FirmwareStatusNotificationInput" wsaw:Action="/FirmwareStatusNotification"/>
632
+            <wsdl:output message="tns:FirmwareStatusNotificationOutput" wsaw:Action="/FirmwareStatusNotificationResponse"/>
633
+        </wsdl:operation>
634
+        <wsdl:operation name="DiagnosticsStatusNotification">
635
+            <wsdl:input message="tns:DiagnosticsStatusNotificationInput" wsaw:Action="/DiagnosticsStatusNotification"/>
636
+            <wsdl:output message="tns:DiagnosticsStatusNotificationOutput" wsaw:Action="/DiagnosticsStatusNotificationResponse"/>
637
+        </wsdl:operation>
638
+        <wsdl:operation name="DataTransfer">
639
+            <wsdl:input message="tns:DataTransferInput" wsaw:Action="/DataTransfer"/>
640
+            <wsdl:output message="tns:DataTransferOutput" wsaw:Action="/DataTransferResponse"/>
641
+        </wsdl:operation>
642
+    </wsdl:portType>
643
+    <wsdl:binding name="CentralSystemServiceSoap" type="tns:CentralSystemService">
644
+        <soap12:binding transport="http://schemas.xmlsoap.org/soap/http"/>
645
+        <wsp:PolicyReference URI="#ServicePolicy"/>
646
+        <wsdl:operation name="Authorize">
647
+            <soap12:operation soapAction="/Authorize" style="document"/>
648
+            <wsdl:input>
649
+                <soap12:header message="tns:Header" part="ChargeBoxIdentity" use="literal"/>
650
+                <soap12:body use="literal"/>
651
+            </wsdl:input>
652
+            <wsdl:output>
653
+                <soap12:body use="literal"/>
654
+            </wsdl:output>
655
+        </wsdl:operation>
656
+        <wsdl:operation name="StartTransaction">
657
+            <soap12:operation soapAction="/StartTransaction" style="document"/>
658
+            <wsdl:input>
659
+                <soap12:header message="tns:Header" part="ChargeBoxIdentity" use="literal"/>
660
+                <soap12:body use="literal"/>
661
+            </wsdl:input>
662
+            <wsdl:output>
663
+                <soap12:body use="literal"/>
664
+            </wsdl:output>
665
+        </wsdl:operation>
666
+        <wsdl:operation name="StopTransaction">
667
+            <soap12:operation soapAction="/StopTransaction" style="document"/>
668
+            <wsdl:input>
669
+                <soap12:header message="tns:Header" part="ChargeBoxIdentity" use="literal"/>
670
+                <soap12:body use="literal"/>
671
+            </wsdl:input>
672
+            <wsdl:output>
673
+                <soap12:body use="literal"/>
674
+            </wsdl:output>
675
+        </wsdl:operation>
676
+        <wsdl:operation name="Heartbeat">
677
+            <soap12:operation soapAction="/Heartbeat" style="document"/>
678
+            <wsdl:input>
679
+                <soap12:header message="tns:Header" part="ChargeBoxIdentity" use="literal"/>
680
+                <soap12:body use="literal"/>
681
+            </wsdl:input>
682
+            <wsdl:output>
683
+                <soap12:body use="literal"/>
684
+            </wsdl:output>
685
+        </wsdl:operation>
686
+        <wsdl:operation name="MeterValues">
687
+            <soap12:operation soapAction="/MeterValues" style="document"/>
688
+            <wsdl:input>
689
+                <soap12:header message="tns:Header" part="ChargeBoxIdentity" use="literal"/>
690
+                <soap12:body use="literal"/>
691
+            </wsdl:input>
692
+            <wsdl:output>
693
+                <soap12:body use="literal"/>
694
+            </wsdl:output>
695
+        </wsdl:operation>
696
+        <wsdl:operation name="BootNotification">
697
+            <soap12:operation soapAction="/BootNotification" style="document"/>
698
+            <wsdl:input>
699
+                <soap12:header message="tns:Header" part="ChargeBoxIdentity" use="literal"/>
700
+                <soap12:body use="literal"/>
701
+            </wsdl:input>
702
+            <wsdl:output>
703
+                <soap12:body use="literal"/>
704
+            </wsdl:output>
705
+        </wsdl:operation>
706
+        <wsdl:operation name="StatusNotification">
707
+            <soap12:operation soapAction="/StatusNotification" style="document"/>
708
+            <wsdl:input>
709
+                <soap12:header message="tns:Header" part="ChargeBoxIdentity" use="literal"/>
710
+                <soap12:body use="literal"/>
711
+            </wsdl:input>
712
+            <wsdl:output>
713
+                <soap12:body use="literal"/>
714
+            </wsdl:output>
715
+        </wsdl:operation>
716
+        <wsdl:operation name="FirmwareStatusNotification">
717
+            <soap12:operation soapAction="/FirmwareStatusNotification" style="document"/>
718
+            <wsdl:input>
719
+                <soap12:header message="tns:Header" part="ChargeBoxIdentity" use="literal"/>
720
+                <soap12:body use="literal"/>
721
+            </wsdl:input>
722
+            <wsdl:output>
723
+                <soap12:body use="literal"/>
724
+            </wsdl:output>
725
+        </wsdl:operation>
726
+        <wsdl:operation name="DiagnosticsStatusNotification">
727
+            <soap12:operation soapAction="/DiagnosticsStatusNotification" style="document"/>
728
+            <wsdl:input>
729
+                <soap12:header message="tns:Header" part="ChargeBoxIdentity" use="literal"/>
730
+                <soap12:body use="literal"/>
731
+            </wsdl:input>
732
+            <wsdl:output>
733
+                <soap12:body use="literal"/>
734
+            </wsdl:output>
735
+        </wsdl:operation>
736
+        <wsdl:operation name="DataTransfer">
737
+            <soap12:operation soapAction="/DataTransfer" style="document"/>
738
+            <wsdl:input>
739
+                <soap12:header message="tns:Header" part="ChargeBoxIdentity" use="literal"/>
740
+                <soap12:body use="literal"/>
741
+            </wsdl:input>
742
+            <wsdl:output>
743
+                <soap12:body use="literal"/>
744
+            </wsdl:output>
745
+        </wsdl:operation>
746
+    </wsdl:binding>
747
+
748
+    <!-- The OCPP Central System Service -->
749
+    <wsdl:service name="CentralSystemService">
750
+        <wsdl:documentation>The Central System Service for the Open Charge Point Protocol</wsdl:documentation>
751
+        <wsdl:port name="CentralSystemServiceSoap12" binding="tns:CentralSystemServiceSoap">
752
+            <!-- <soap12:address location="http://localhost/Ocpp/CentralSystemService/"/> -->
753
+            <soap12:address location="http://127.0.0.1:9220/Ocpp/CentralSystemService"/>
754
+        </wsdl:port>
755
+    </wsdl:service>
756
+
757
+</wsdl:definitions>

+ 904 - 0
charger-simulator/src/soap/wsdl/15/ocpp_chargepointservice_1.5_final.wsdl

@@ -0,0 +1,904 @@
1
+<?xml version="1.0" encoding="utf-8"?>
2
+<!--
3
+OCPP Charge Point service description
4
+Version 1.5 draft for approval (1.5 RC4)
5
+
6
+Copyright e-laad.nl. Free to use without modifications.
7
+
8
+See: http://ev-services.net/ocpp/
9
+-->
10
+<wsdl:definitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
11
+                  xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
12
+                  xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/"
13
+                  xmlns:s="http://www.w3.org/2001/XMLSchema"
14
+                  xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/"
15
+                  xmlns:http="http://schemas.xmlsoap.org/wsdl/http/"
16
+                  xmlns:tns="urn://Ocpp/Cp/2012/06/"
17
+                  targetNamespace="urn://Ocpp/Cp/2012/06/"
18
+                  xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
19
+                  xmlns:wsaw="http://www.w3.org/2006/05/addressing/wsdl"
20
+                  xmlns:wsa="http://www.w3.org/2005/08/addressing"
21
+                  xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy"
22
+                  xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
23
+
24
+    <wsp:Policy wsu:Id="ServicePolicy">
25
+        <wsp:ExactlyOne>
26
+            <wsp:All>
27
+                <wsaw:UsingAddressing />
28
+            </wsp:All>
29
+        </wsp:ExactlyOne>
30
+    </wsp:Policy>
31
+
32
+    <wsdl:types>
33
+        <s:schema elementFormDefault="qualified" targetNamespace="urn://Ocpp/Cp/2012/06/">
34
+
35
+            <!-- Begin of types shared with CentralSystemService -->
36
+            <s:simpleType name="IdToken">
37
+                <s:annotation>
38
+                    <s:documentation>Type of string defining identification token, e.g. RFID or credit card number. To be treated as case insensitive.</s:documentation>
39
+                </s:annotation>
40
+                <s:restriction base="s:string">
41
+                    <s:maxLength value="20"/>
42
+                </s:restriction>
43
+            </s:simpleType>
44
+
45
+            <s:simpleType name="AuthorizationStatus">
46
+                <s:annotation>
47
+                    <s:documentation>Defines the authorization-status-value</s:documentation>
48
+                </s:annotation>
49
+                <s:restriction base="s:string">
50
+                    <s:enumeration value="Accepted"/>
51
+                    <s:enumeration value="Blocked"/>
52
+                    <s:enumeration value="Expired"/>
53
+                    <s:enumeration value="Invalid"/>
54
+                    <s:enumeration value="ConcurrentTx"/>
55
+                </s:restriction>
56
+            </s:simpleType>
57
+
58
+            <s:complexType name="IdTagInfo">
59
+                <s:sequence>
60
+                    <s:element name="status" type="tns:AuthorizationStatus" minOccurs="1" maxOccurs="1"/>
61
+                    <s:element name="expiryDate" type="s:dateTime" minOccurs="0" maxOccurs="1"/>
62
+                    <s:element name="parentIdTag" type="tns:IdToken" minOccurs="0" maxOccurs="1"/>
63
+                </s:sequence>
64
+            </s:complexType>
65
+            <!-- End of types shared with CentralSystemService -->
66
+
67
+            <s:simpleType name="UnlockStatus">
68
+                <s:annotation>
69
+                    <s:documentation>Defines the unlock-status-value</s:documentation>
70
+                </s:annotation>
71
+                <s:restriction base="s:string">
72
+                    <s:enumeration value="Accepted" />
73
+                    <s:enumeration value="Rejected" />
74
+                </s:restriction>
75
+            </s:simpleType>
76
+
77
+            <s:complexType name="UnlockConnectorRequest">
78
+                <s:annotation>
79
+                    <s:documentation>Defines the UnlockConnector.req PDU</s:documentation>
80
+                </s:annotation>
81
+                <s:sequence>
82
+                    <s:element name="connectorId" type="s:int" minOccurs="1" maxOccurs="1" />
83
+                </s:sequence>
84
+            </s:complexType>
85
+
86
+            <s:complexType name="UnlockConnectorResponse">
87
+                <s:annotation>
88
+                    <s:documentation>Defines the UnlockConnector.conf PDU</s:documentation>
89
+                </s:annotation>
90
+                <s:sequence>
91
+                    <s:element name="status" type="tns:UnlockStatus" minOccurs="1" maxOccurs="1" />
92
+                </s:sequence>
93
+            </s:complexType>
94
+
95
+            <s:simpleType name="ResetType">
96
+                <s:annotation>
97
+                    <s:documentation>Defines the reset-type-value</s:documentation>
98
+                </s:annotation>
99
+                <s:restriction base="s:string">
100
+                    <s:enumeration value="Hard" />
101
+                    <s:enumeration value="Soft" />
102
+                </s:restriction>
103
+            </s:simpleType>
104
+
105
+            <s:complexType name="ResetRequest">
106
+                <s:annotation>
107
+                    <s:documentation>Defines the Reset.req PDU</s:documentation>
108
+                </s:annotation>
109
+                <s:sequence>
110
+                    <s:element name="type" type="tns:ResetType" minOccurs="1" maxOccurs="1" />
111
+                </s:sequence>
112
+            </s:complexType>
113
+
114
+            <s:simpleType name="ResetStatus">
115
+                <s:annotation>
116
+                    <s:documentation>Defines the reset-status-value</s:documentation>
117
+                </s:annotation>
118
+                <s:restriction base="s:string">
119
+                    <s:enumeration value="Accepted" />
120
+                    <s:enumeration value="Rejected" />
121
+                </s:restriction>
122
+            </s:simpleType>
123
+
124
+            <s:complexType name="ResetResponse">
125
+                <s:sequence>
126
+                    <s:element name="status" type="tns:ResetStatus" minOccurs="1" maxOccurs="1" />
127
+                </s:sequence>
128
+            </s:complexType>
129
+
130
+            <s:simpleType name="AvailabilityType">
131
+                <s:annotation>
132
+                    <s:documentation>Defines the availability-type-value</s:documentation>
133
+                </s:annotation>
134
+                <s:restriction base="s:string">
135
+                    <s:enumeration value="Inoperative" />
136
+                    <s:enumeration value="Operative" />
137
+                </s:restriction>
138
+            </s:simpleType>
139
+
140
+            <s:complexType name="ChangeAvailabilityRequest">
141
+                <s:annotation>
142
+                    <s:documentation>Defines the ChangeAvailability.req PDU</s:documentation>
143
+                </s:annotation>
144
+                <s:sequence>
145
+                    <s:element name="connectorId" type="s:int" minOccurs="1" maxOccurs="1" />
146
+                    <s:element name="type" type="tns:AvailabilityType" minOccurs="1" maxOccurs="1" />
147
+                </s:sequence>
148
+            </s:complexType>
149
+
150
+            <s:simpleType name="AvailabilityStatus">
151
+                <s:annotation>
152
+                    <s:documentation>Defines the availability-status-value</s:documentation>
153
+                </s:annotation>
154
+                <s:restriction base="s:string">
155
+                    <s:enumeration value="Accepted" />
156
+                    <s:enumeration value="Rejected" />
157
+                    <s:enumeration value="Scheduled" />
158
+                </s:restriction>
159
+            </s:simpleType>
160
+
161
+            <s:complexType name="ChangeAvailabilityResponse">
162
+                <s:annotation>
163
+                    <s:documentation>Defines the ChangeAvailability.conf PDU</s:documentation>
164
+                </s:annotation>
165
+                <s:sequence>
166
+                    <s:element name="status" type="tns:AvailabilityStatus" minOccurs="1" maxOccurs="1" />
167
+                </s:sequence>
168
+            </s:complexType>
169
+
170
+            <s:complexType name="GetDiagnosticsRequest">
171
+                <s:annotation>
172
+                    <s:documentation>Defines the GetDiagnostics.req PDU</s:documentation>
173
+                </s:annotation>
174
+                <s:sequence>
175
+                    <s:element name="location" type="s:anyURI" minOccurs="1" maxOccurs="1" />
176
+                    <s:element name="startTime" type="s:dateTime" minOccurs="0" maxOccurs="1" />
177
+                    <s:element name="stopTime" type="s:dateTime" minOccurs="0" maxOccurs="1" />
178
+                    <s:element name="retries" type="s:int" minOccurs="0" maxOccurs="1" />
179
+                    <s:element name="retryInterval" type="s:int" minOccurs="0" maxOccurs="1" />
180
+                </s:sequence>
181
+            </s:complexType>
182
+
183
+            <s:complexType name="GetDiagnosticsResponse">
184
+                <s:annotation>
185
+                    <s:documentation>Defines the GetDiagnostics.conf PDU</s:documentation>
186
+                </s:annotation>
187
+                <s:sequence>
188
+                    <s:element name="fileName" type="s:string" minOccurs="0" maxOccurs="1" />
189
+                </s:sequence>
190
+            </s:complexType>
191
+
192
+            <s:complexType name="ClearCacheRequest">
193
+                <s:annotation>
194
+                    <s:documentation>Defines the ClearCache.req PDU</s:documentation>
195
+                </s:annotation>
196
+            </s:complexType>
197
+
198
+            <s:simpleType name="ClearCacheStatus">
199
+                <s:annotation>
200
+                    <s:documentation>Defines the clear-cache-status-value</s:documentation>
201
+                </s:annotation>
202
+                <s:restriction base="s:string">
203
+                    <s:enumeration value="Accepted" />
204
+                    <s:enumeration value="Rejected" />
205
+                </s:restriction>
206
+            </s:simpleType>
207
+
208
+            <s:complexType name="ClearCacheResponse">
209
+                <s:annotation>
210
+                    <s:documentation>Defines the ClearCache.conf PDU</s:documentation>
211
+                </s:annotation>
212
+                <s:sequence>
213
+                    <s:element name="status" type="tns:ClearCacheStatus" minOccurs="1" maxOccurs="1" />
214
+                </s:sequence>
215
+            </s:complexType>
216
+
217
+            <s:complexType name="UpdateFirmwareRequest">
218
+                <s:sequence>
219
+                    <s:element name="retrieveDate" type="s:dateTime" minOccurs="1" maxOccurs="1" />
220
+                    <s:element name="location" type="s:anyURI" minOccurs="1" maxOccurs="1" />
221
+                    <s:element name="retries" type="s:int" minOccurs="0" maxOccurs="1" />
222
+                    <s:element name="retryInterval" type="s:int" minOccurs="0" maxOccurs="1" />
223
+                </s:sequence>
224
+            </s:complexType>
225
+
226
+            <s:complexType name="UpdateFirmwareResponse">
227
+            </s:complexType>
228
+
229
+            <s:complexType name="ChangeConfigurationRequest">
230
+                <s:annotation>
231
+                    <s:documentation>Defines the ChangeConfiguration.req PDU</s:documentation>
232
+                </s:annotation>
233
+                <s:sequence>
234
+                    <s:element name="key" type="s:string" minOccurs="1" maxOccurs="1" />
235
+                    <s:element name="value" type="s:string" minOccurs="1" maxOccurs="1" />
236
+                </s:sequence>
237
+            </s:complexType>
238
+
239
+            <s:simpleType name="ConfigurationStatus">
240
+                <s:annotation>
241
+                    <s:documentation>Defines the configuration-status-value</s:documentation>
242
+                </s:annotation>
243
+                <s:restriction base="s:string">
244
+                    <s:enumeration value="Accepted" />
245
+                    <s:enumeration value="Rejected" />
246
+                    <s:enumeration value="NotSupported" />
247
+                </s:restriction>
248
+            </s:simpleType>
249
+
250
+            <s:complexType name="ChangeConfigurationResponse">
251
+                <s:annotation>
252
+                    <s:documentation>Defines the ChangeConfiguration.conf PDU</s:documentation>
253
+                </s:annotation>
254
+                <s:sequence>
255
+                    <s:element name="status" type="tns:ConfigurationStatus" minOccurs="1" maxOccurs="1" />
256
+                </s:sequence>
257
+            </s:complexType>
258
+
259
+            <s:complexType name="RemoteStartTransactionRequest">
260
+                <s:annotation>
261
+                    <s:documentation>Defines the RemoteStartTransaction.req PDU</s:documentation>
262
+                </s:annotation>
263
+                <s:sequence>
264
+                    <s:element name="idTag" type="tns:IdToken" minOccurs="1" maxOccurs="1" />
265
+                    <s:element name="connectorId" type="s:int" minOccurs="0" maxOccurs="1" />
266
+                </s:sequence>
267
+            </s:complexType>
268
+
269
+            <s:simpleType name="RemoteStartStopStatus">
270
+                <s:annotation>
271
+                    <s:documentation>Defines the remote-start-stop-status-value</s:documentation>
272
+                </s:annotation>
273
+                <s:restriction base="s:string">
274
+                    <s:enumeration value="Accepted" />
275
+                    <s:enumeration value="Rejected" />
276
+                </s:restriction>
277
+            </s:simpleType>
278
+
279
+            <s:complexType name="RemoteStartTransactionResponse">
280
+                <s:annotation>
281
+                    <s:documentation>Defines the RemoteStartTransaction.conf PDU</s:documentation>
282
+                </s:annotation>
283
+                <s:sequence>
284
+                    <s:element name="status" type="tns:RemoteStartStopStatus" minOccurs="1" maxOccurs="1" />
285
+                </s:sequence>
286
+            </s:complexType>
287
+
288
+            <s:complexType name="RemoteStopTransactionRequest">
289
+                <s:annotation>
290
+                    <s:documentation>Defines the RemoteStopTransaction.req PDU</s:documentation>
291
+                </s:annotation>
292
+                <s:sequence>
293
+                    <s:element name="transactionId" type="s:int" minOccurs="1" maxOccurs="1" />
294
+                </s:sequence>
295
+            </s:complexType>
296
+
297
+            <s:complexType name="RemoteStopTransactionResponse">
298
+                <s:annotation>
299
+                    <s:documentation>Defines the RemoteStopTransaction.conf PDU</s:documentation>
300
+                </s:annotation>
301
+                <s:sequence>
302
+                    <s:element name="status" type="tns:RemoteStartStopStatus" minOccurs="1" maxOccurs="1" />
303
+                </s:sequence>
304
+            </s:complexType>
305
+
306
+            <s:complexType name="CancelReservationRequest">
307
+                <s:annotation>
308
+                    <s:documentation>Defines the CancelReservation.req PDU</s:documentation>
309
+                </s:annotation>
310
+                <s:sequence>
311
+                    <s:element name="reservationId" type="s:int" minOccurs="1" maxOccurs="1" />
312
+                </s:sequence>
313
+            </s:complexType>
314
+
315
+            <s:simpleType name="CancelReservationStatus">
316
+                <s:restriction base="s:string">
317
+                    <s:enumeration value="Accepted"/>
318
+                    <s:enumeration value="Rejected"/>
319
+                </s:restriction>
320
+            </s:simpleType>
321
+
322
+            <s:complexType name="CancelReservationResponse">
323
+                <s:annotation>
324
+                    <s:documentation>Defines the CancelReservation.conf PDU</s:documentation>
325
+                </s:annotation>
326
+                <s:sequence>
327
+                    <s:element name="status" type="tns:CancelReservationStatus" minOccurs="1" maxOccurs="1" />
328
+                </s:sequence>
329
+            </s:complexType>
330
+
331
+            <s:complexType name="DataTransferRequest">
332
+                <s:annotation>
333
+                    <s:documentation>Defines the DataTransfer.req PDU</s:documentation>
334
+                </s:annotation>
335
+                <s:sequence>
336
+                    <s:element name="vendorId" type="s:string" minOccurs="1" maxOccurs="1" />
337
+                    <s:element name="messageId" type="s:string" minOccurs="0" maxOccurs="1" />
338
+                    <s:element name="data" type="s:string" minOccurs="0" maxOccurs="1" />
339
+                </s:sequence>
340
+            </s:complexType>
341
+
342
+            <s:simpleType name="DataTransferStatus">
343
+                <s:annotation>
344
+                    <s:documentation>Defines the status returned in DataTransfer.conf</s:documentation>
345
+                </s:annotation>
346
+                <s:restriction base="s:string">
347
+                    <s:enumeration value="Accepted" />
348
+                    <s:enumeration value="Rejected" />
349
+                    <s:enumeration value="UnknownMessageId" />
350
+                    <s:enumeration value="UnknownVendorId" />
351
+                </s:restriction>
352
+            </s:simpleType>
353
+
354
+            <s:complexType name="DataTransferResponse">
355
+                <s:annotation>
356
+                    <s:documentation>Defines the DataTransfer.conf PDU</s:documentation>
357
+                </s:annotation>
358
+                <s:sequence>
359
+                    <s:element name="status" type="tns:DataTransferStatus" minOccurs="1" maxOccurs="1" />
360
+                    <s:element name="data" type="s:string" minOccurs="0" maxOccurs="1" />
361
+                </s:sequence>
362
+            </s:complexType>
363
+
364
+            <s:complexType name="GetConfigurationRequest">
365
+                <s:annotation>
366
+                    <s:documentation>Defines the GetConfiguration.req PDU</s:documentation>
367
+                </s:annotation>
368
+                <s:sequence>
369
+                    <s:element name="key" type="s:string" minOccurs="0" maxOccurs="unbounded" />
370
+                </s:sequence>
371
+            </s:complexType>
372
+
373
+            <s:complexType name="KeyValue">
374
+                <s:annotation>
375
+                    <s:documentation>Key-Value pairs returned by GetConfiguration.conf PDU</s:documentation>
376
+                </s:annotation>
377
+                <s:sequence>
378
+                    <s:element name="key" type="s:string" minOccurs="1" maxOccurs="1" />
379
+                    <s:element name="readonly" type="s:boolean" minOccurs="1" maxOccurs="1" />
380
+                    <s:element name="value" type="s:string" minOccurs="0" maxOccurs="1" />
381
+                </s:sequence>
382
+            </s:complexType>
383
+
384
+            <s:complexType name="GetConfigurationResponse">
385
+                <s:annotation>
386
+                    <s:documentation>Defines the GetConfiguration.req PDU</s:documentation>
387
+                </s:annotation>
388
+                <s:sequence>
389
+                    <s:element name="configurationKey" type="tns:KeyValue" minOccurs="0" maxOccurs="unbounded" />
390
+                    <s:element name="unknownKey" type="s:string" minOccurs="0" maxOccurs="unbounded" />
391
+                </s:sequence>
392
+            </s:complexType>
393
+
394
+            <s:complexType name="GetLocalListVersionRequest">
395
+                <s:annotation>
396
+                    <s:documentation>Defines the GetLocalListVersion.req PDU</s:documentation>
397
+                </s:annotation>
398
+            </s:complexType>
399
+
400
+            <s:complexType name="GetLocalListVersionResponse">
401
+                <s:annotation>
402
+                    <s:documentation>Defines the GetLocalListVersion.conf PDU</s:documentation>
403
+                </s:annotation>
404
+                <s:sequence>
405
+                    <s:element name="listVersion" type="s:int" minOccurs="1" maxOccurs="1" />
406
+                </s:sequence>
407
+            </s:complexType>
408
+
409
+            <s:complexType name="ReserveNowRequest">
410
+                <s:annotation>
411
+                    <s:documentation>Defines the ReserveNow.req PDU</s:documentation>
412
+                </s:annotation>
413
+                <s:sequence>
414
+                    <s:element name="connectorId" type="s:int" minOccurs="1" maxOccurs="1" />
415
+                    <s:element name="expiryDate" type="s:dateTime" minOccurs="1" maxOccurs="1" />
416
+                    <s:element name="idTag" type="tns:IdToken" minOccurs="1" maxOccurs="1" />
417
+                    <s:element name="parentIdTag" type="tns:IdToken" minOccurs="0" maxOccurs="1" />
418
+                    <s:element name="reservationId" type="s:int" minOccurs="1" maxOccurs="1" />
419
+                </s:sequence>
420
+            </s:complexType>
421
+
422
+            <s:simpleType name="ReservationStatus">
423
+                <s:restriction base="s:string">
424
+                    <s:enumeration value="Accepted"/>
425
+                    <s:enumeration value="Faulted"/>
426
+                    <s:enumeration value="Occupied"/>
427
+                    <s:enumeration value="Rejected"/>
428
+                    <s:enumeration value="Unavailable"/>
429
+                </s:restriction>
430
+            </s:simpleType>
431
+
432
+            <s:complexType name="ReserveNowResponse">
433
+                <s:annotation>
434
+                    <s:documentation>Defines the ReserveNow.conf PDU</s:documentation>
435
+                </s:annotation>
436
+                <s:sequence>
437
+                    <s:element name="status" type="tns:ReservationStatus" minOccurs="1" maxOccurs="1" />
438
+                </s:sequence>
439
+            </s:complexType>
440
+
441
+            <s:complexType name="AuthorisationData">
442
+                <s:sequence>
443
+                    <s:element name="idTag" type="tns:IdToken" minOccurs="1" maxOccurs="1"/>
444
+                    <s:element name="idTagInfo" type="tns:IdTagInfo" minOccurs="0" maxOccurs="1"/>
445
+                </s:sequence>
446
+            </s:complexType>
447
+
448
+            <s:simpleType name="UpdateType">
449
+                <s:restriction base="s:string">
450
+                    <s:enumeration value="Differential"/>
451
+                    <s:enumeration value="Full"/>
452
+                </s:restriction>
453
+            </s:simpleType>
454
+
455
+            <s:complexType name="SendLocalListRequest">
456
+                <s:annotation>
457
+                    <s:documentation>Defines the SendLocalList.req PDU</s:documentation>
458
+                </s:annotation>
459
+                <s:sequence>
460
+                    <s:element name="updateType" type="tns:UpdateType" minOccurs="1" maxOccurs="1" />
461
+                    <s:element name="listVersion" type="s:int" minOccurs="1" maxOccurs="1" />
462
+                    <s:element name="localAuthorisationList" type="tns:AuthorisationData" minOccurs="0" maxOccurs="unbounded" />
463
+                    <s:element name="hash" type="s:string" minOccurs="0" maxOccurs="1" />
464
+                </s:sequence>
465
+            </s:complexType>
466
+
467
+            <s:simpleType name="UpdateStatus">
468
+                <s:restriction base="s:string">
469
+                    <s:enumeration value="Accepted"/>
470
+                    <s:enumeration value="Failed"/>
471
+                    <s:enumeration value="HashError"/>
472
+                    <s:enumeration value="NotSupported"/>
473
+                    <s:enumeration value="VersionMismatch"/>
474
+                </s:restriction>
475
+            </s:simpleType>
476
+
477
+            <s:complexType name="SendLocalListResponse">
478
+                <s:annotation>
479
+                    <s:documentation>Defines the SendLocalList.conf PDU</s:documentation>
480
+                </s:annotation>
481
+                <s:sequence>
482
+                    <s:element name="status" type="tns:UpdateStatus" minOccurs="1" maxOccurs="1" />
483
+                    <s:element name="hash" type="s:string" minOccurs="0" maxOccurs="1" />
484
+                </s:sequence>
485
+            </s:complexType>
486
+
487
+            <s:element name="chargeBoxIdentity" type="s:string" />
488
+            <s:element name="unlockConnectorRequest" type="tns:UnlockConnectorRequest" />
489
+            <s:element name="unlockConnectorResponse" type="tns:UnlockConnectorResponse" />
490
+            <s:element name="resetRequest" type="tns:ResetRequest" />
491
+            <s:element name="resetResponse" type="tns:ResetResponse" />
492
+            <s:element name="changeAvailabilityRequest" type="tns:ChangeAvailabilityRequest" />
493
+            <s:element name="changeAvailabilityResponse" type="tns:ChangeAvailabilityResponse" />
494
+            <s:element name="getDiagnosticsRequest" type="tns:GetDiagnosticsRequest" />
495
+            <s:element name="getDiagnosticsResponse" type="tns:GetDiagnosticsResponse" />
496
+            <s:element name="clearCacheRequest" type="tns:ClearCacheRequest" />
497
+            <s:element name="clearCacheResponse" type="tns:ClearCacheResponse" />
498
+            <s:element name="updateFirmwareRequest" type="tns:UpdateFirmwareRequest" />
499
+            <s:element name="updateFirmwareResponse" type="tns:UpdateFirmwareResponse" />
500
+            <s:element name="changeConfigurationRequest" type="tns:ChangeConfigurationRequest" />
501
+            <s:element name="changeConfigurationResponse" type="tns:ChangeConfigurationResponse" />
502
+            <s:element name="remoteStartTransactionRequest" type="tns:RemoteStartTransactionRequest" />
503
+            <s:element name="remoteStartTransactionResponse" type="tns:RemoteStartTransactionResponse" />
504
+            <s:element name="remoteStopTransactionRequest" type="tns:RemoteStopTransactionRequest" />
505
+            <s:element name="remoteStopTransactionResponse" type="tns:RemoteStopTransactionResponse" />
506
+            <s:element name="cancelReservationRequest" type="tns:CancelReservationRequest" />
507
+            <s:element name="cancelReservationResponse" type="tns:CancelReservationResponse" />
508
+            <s:element name="dataTransferRequest" type="tns:DataTransferRequest" />
509
+            <s:element name="dataTransferResponse" type="tns:DataTransferResponse" />
510
+            <s:element name="getConfigurationRequest" type="tns:GetConfigurationRequest" />
511
+            <s:element name="getConfigurationResponse" type="tns:GetConfigurationResponse" />
512
+            <s:element name="getLocalListVersionRequest" type="tns:GetLocalListVersionRequest" />
513
+            <s:element name="getLocalListVersionResponse" type="tns:GetLocalListVersionResponse" />
514
+            <s:element name="reserveNowRequest" type="tns:ReserveNowRequest" />
515
+            <s:element name="reserveNowResponse" type="tns:ReserveNowResponse" />
516
+            <s:element name="sendLocalListRequest" type="tns:SendLocalListRequest" />
517
+            <s:element name="sendLocalListResponse" type="tns:SendLocalListResponse" />
518
+        </s:schema>
519
+    </wsdl:types>
520
+
521
+    <wsdl:message name="Header">
522
+        <wsdl:part name="ChargeBoxIdentity" element="tns:chargeBoxIdentity" />
523
+    </wsdl:message>
524
+
525
+    <wsdl:message name="UnlockConnectorInput">
526
+        <wsdl:part name="parameters" element="tns:unlockConnectorRequest" />
527
+    </wsdl:message>
528
+
529
+    <wsdl:message name="UnlockConnectorOutput">
530
+        <wsdl:part name="parameters" element="tns:unlockConnectorResponse" />
531
+    </wsdl:message>
532
+
533
+    <wsdl:message name="ResetInput">
534
+        <wsdl:part name="parameters" element="tns:resetRequest" />
535
+    </wsdl:message>
536
+
537
+    <wsdl:message name="ResetOutput">
538
+        <wsdl:part name="parameters" element="tns:resetResponse" />
539
+    </wsdl:message>
540
+
541
+    <wsdl:message name="ChangeAvailabilityInput">
542
+        <wsdl:part name="parameters" element="tns:changeAvailabilityRequest" />
543
+    </wsdl:message>
544
+
545
+    <wsdl:message name="ChangeAvailabilityOutput">
546
+        <wsdl:part name="parameters" element="tns:changeAvailabilityResponse" />
547
+    </wsdl:message>
548
+
549
+    <wsdl:message name="GetDiagnosticsInput">
550
+        <wsdl:part name="parameters" element="tns:getDiagnosticsRequest" />
551
+    </wsdl:message>
552
+
553
+    <wsdl:message name="GetDiagnosticsOutput">
554
+        <wsdl:part name="parameters" element="tns:getDiagnosticsResponse" />
555
+    </wsdl:message>
556
+
557
+    <wsdl:message name="ClearCacheInput">
558
+        <wsdl:part name="parameters" element="tns:clearCacheRequest" />
559
+    </wsdl:message>
560
+
561
+    <wsdl:message name="ClearCacheOutput">
562
+        <wsdl:part name="parameters" element="tns:clearCacheResponse" />
563
+    </wsdl:message>
564
+
565
+    <wsdl:message name="UpdateFirmwareInput">
566
+        <wsdl:part name="parameters" element="tns:updateFirmwareRequest" />
567
+    </wsdl:message>
568
+
569
+    <wsdl:message name="UpdateFirmwareOutput">
570
+        <wsdl:part name="parameters" element="tns:updateFirmwareResponse" />
571
+    </wsdl:message>
572
+
573
+    <wsdl:message name="ChangeConfigurationInput">
574
+        <wsdl:part name="parameters" element="tns:changeConfigurationRequest" />
575
+    </wsdl:message>
576
+
577
+    <wsdl:message name="ChangeConfigurationOutput">
578
+        <wsdl:part name="parameters" element="tns:changeConfigurationResponse" />
579
+    </wsdl:message>
580
+
581
+    <wsdl:message name="RemoteStartTransactionInput">
582
+        <wsdl:part name="parameters" element="tns:remoteStartTransactionRequest" />
583
+    </wsdl:message>
584
+
585
+    <wsdl:message name="RemoteStartTransactionOutput">
586
+        <wsdl:part name="parameters" element="tns:remoteStartTransactionResponse" />
587
+    </wsdl:message>
588
+
589
+    <wsdl:message name="RemoteStopTransactionInput">
590
+        <wsdl:part name="parameters" element="tns:remoteStopTransactionRequest" />
591
+    </wsdl:message>
592
+
593
+    <wsdl:message name="RemoteStopTransactionOutput">
594
+        <wsdl:part name="parameters" element="tns:remoteStopTransactionResponse" />
595
+    </wsdl:message>
596
+
597
+    <wsdl:message name="CancelReservationInput">
598
+        <wsdl:part name="parameters" element="tns:cancelReservationRequest" />
599
+    </wsdl:message>
600
+
601
+    <wsdl:message name="CancelReservationOutput">
602
+        <wsdl:part name="parameters" element="tns:cancelReservationResponse" />
603
+    </wsdl:message>
604
+
605
+    <wsdl:message name="DataTransferInput">
606
+        <wsdl:part name="parameters" element="tns:dataTransferRequest" />
607
+    </wsdl:message>
608
+
609
+    <wsdl:message name="DataTransferOutput">
610
+        <wsdl:part name="parameters" element="tns:dataTransferResponse" />
611
+    </wsdl:message>
612
+
613
+    <wsdl:message name="GetConfigurationInput">
614
+        <wsdl:part name="parameters" element="tns:getConfigurationRequest" />
615
+    </wsdl:message>
616
+
617
+    <wsdl:message name="GetConfigurationOutput">
618
+        <wsdl:part name="parameters" element="tns:getConfigurationResponse" />
619
+    </wsdl:message>
620
+
621
+    <wsdl:message name="GetLocalListVersionInput">
622
+        <wsdl:part name="parameters" element="tns:getLocalListVersionRequest" />
623
+    </wsdl:message>
624
+
625
+    <wsdl:message name="GetLocalListVersionOutput">
626
+        <wsdl:part name="parameters" element="tns:getLocalListVersionResponse" />
627
+    </wsdl:message>
628
+
629
+    <wsdl:message name="ReserveNowInput">
630
+        <wsdl:part name="parameters" element="tns:reserveNowRequest" />
631
+    </wsdl:message>
632
+
633
+    <wsdl:message name="ReserveNowOutput">
634
+        <wsdl:part name="parameters" element="tns:reserveNowResponse" />
635
+    </wsdl:message>
636
+
637
+    <wsdl:message name="SendLocalListInput">
638
+        <wsdl:part name="parameters" element="tns:sendLocalListRequest" />
639
+    </wsdl:message>
640
+
641
+    <wsdl:message name="SendLocalListOutput">
642
+        <wsdl:part name="parameters" element="tns:sendLocalListResponse" />
643
+    </wsdl:message>
644
+
645
+    <wsdl:portType name="ChargePointService">
646
+
647
+        <wsdl:operation name="UnlockConnector">
648
+            <wsdl:input message="tns:UnlockConnectorInput" wsaw:Action="/UnlockConnector" />
649
+            <wsdl:output message="tns:UnlockConnectorOutput" wsaw:Action="/UnlockConnectorResponse" />
650
+        </wsdl:operation>
651
+
652
+        <wsdl:operation name="Reset">
653
+            <wsdl:input message="tns:ResetInput" wsaw:Action="/Reset" />
654
+            <wsdl:output message="tns:ResetOutput" wsaw:Action="/ResetResponse" />
655
+        </wsdl:operation>
656
+
657
+        <wsdl:operation name="ChangeAvailability">
658
+            <wsdl:input message="tns:ChangeAvailabilityInput" wsaw:Action="/ChangeAvailability" />
659
+            <wsdl:output message="tns:ChangeAvailabilityOutput" wsaw:Action="/ChangeAvailabilityResponse" />
660
+        </wsdl:operation>
661
+
662
+        <wsdl:operation name="GetDiagnostics">
663
+            <wsdl:input message="tns:GetDiagnosticsInput" wsaw:Action="/GetDiagnostics" />
664
+            <wsdl:output message="tns:GetDiagnosticsOutput" wsaw:Action="/GetDiagnosticsResponse" />
665
+        </wsdl:operation>
666
+
667
+        <wsdl:operation name="ClearCache">
668
+            <wsdl:input message="tns:ClearCacheInput" wsaw:Action="/ClearCache" />
669
+            <wsdl:output message="tns:ClearCacheOutput" wsaw:Action="/ClearCacheResponse" />
670
+        </wsdl:operation>
671
+
672
+        <wsdl:operation name="UpdateFirmware">
673
+            <wsdl:input message="tns:UpdateFirmwareInput" wsaw:Action="/UpdateFirmware" />
674
+            <wsdl:output message="tns:UpdateFirmwareOutput" wsaw:Action="/UpdateFirmwareResponse" />
675
+        </wsdl:operation>
676
+
677
+        <wsdl:operation name="ChangeConfiguration">
678
+            <wsdl:input message="tns:ChangeConfigurationInput" wsaw:Action="/ChangeConfiguration" />
679
+            <wsdl:output message="tns:ChangeConfigurationOutput" wsaw:Action="/ChangeConfigurationResponse" />
680
+        </wsdl:operation>
681
+
682
+        <wsdl:operation name="RemoteStartTransaction">
683
+            <wsdl:input message="tns:RemoteStartTransactionInput" wsaw:Action="/RemoteStartTransaction" />
684
+            <wsdl:output message="tns:RemoteStartTransactionOutput" wsaw:Action="/RemoteStartTransactionResponse" />
685
+        </wsdl:operation>
686
+
687
+        <wsdl:operation name="RemoteStopTransaction">
688
+            <wsdl:input message="tns:RemoteStopTransactionInput" wsaw:Action="/RemoteStopTransaction" />
689
+            <wsdl:output message="tns:RemoteStopTransactionOutput" wsaw:Action="/RemoteStopTransactionResponse" />
690
+        </wsdl:operation>
691
+
692
+        <wsdl:operation name="CancelReservation">
693
+            <wsdl:input message="tns:CancelReservationInput" wsaw:Action="/CancelReservation" />
694
+            <wsdl:output message="tns:CancelReservationOutput" wsaw:Action="/CancelReservationResponse" />
695
+        </wsdl:operation>
696
+
697
+        <wsdl:operation name="DataTransfer">
698
+            <wsdl:input message="tns:DataTransferInput" wsaw:Action="/DataTransfer" />
699
+            <wsdl:output message="tns:DataTransferOutput" wsaw:Action="/DataTransferResponse" />
700
+        </wsdl:operation>
701
+
702
+        <wsdl:operation name="GetConfiguration">
703
+            <wsdl:input message="tns:GetConfigurationInput" wsaw:Action="/GetConfiguration" />
704
+            <wsdl:output message="tns:GetConfigurationOutput" wsaw:Action="/GetConfigurationResponse" />
705
+        </wsdl:operation>
706
+
707
+        <wsdl:operation name="GetLocalListVersion">
708
+            <wsdl:input message="tns:GetLocalListVersionInput" wsaw:Action="/GetLocalListVersion" />
709
+            <wsdl:output message="tns:GetLocalListVersionOutput" wsaw:Action="/GetLocalListVersionResponse" />
710
+        </wsdl:operation>
711
+
712
+        <wsdl:operation name="ReserveNow">
713
+            <wsdl:input message="tns:ReserveNowInput" wsaw:Action="/ReserveNow" />
714
+            <wsdl:output message="tns:ReserveNowOutput" wsaw:Action="/ReserveNowResponse" />
715
+        </wsdl:operation>
716
+
717
+        <wsdl:operation name="SendLocalList">
718
+            <wsdl:input message="tns:SendLocalListInput" wsaw:Action="/SendLocalList" />
719
+            <wsdl:output message="tns:SendLocalListOutput" wsaw:Action="/SendLocalListResponse" />
720
+        </wsdl:operation>
721
+
722
+    </wsdl:portType>
723
+
724
+    <wsdl:binding name="ChargePointServiceSoap" type="tns:ChargePointService">
725
+
726
+        <wsp:PolicyReference URI="#ServicePolicy" />
727
+        <soap12:binding transport="http://schemas.xmlsoap.org/soap/http" />
728
+
729
+        <wsdl:operation name="UnlockConnector">
730
+            <soap12:operation soapAction="/UnlockConnector" style="document" />
731
+            <wsdl:input>
732
+                <soap12:header use="literal" message="tns:Header" part="ChargeBoxIdentity"/>
733
+                <soap12:body use="literal" />
734
+            </wsdl:input>
735
+            <wsdl:output>
736
+                <soap12:body use="literal" />
737
+            </wsdl:output>
738
+        </wsdl:operation>
739
+
740
+        <wsdl:operation name="Reset">
741
+            <soap12:operation soapAction="/Reset" style="document" />
742
+            <wsdl:input>
743
+                <soap12:header use="literal" message="tns:Header" part="ChargeBoxIdentity"/>
744
+                <soap12:body use="literal" />
745
+            </wsdl:input>
746
+            <wsdl:output>
747
+                <soap12:body use="literal" />
748
+            </wsdl:output>
749
+        </wsdl:operation>
750
+
751
+        <wsdl:operation name="ChangeAvailability">
752
+            <soap12:operation soapAction="/ChangeAvailability" style="document" />
753
+            <wsdl:input>
754
+                <soap12:header use="literal" message="tns:Header" part="ChargeBoxIdentity"/>
755
+                <soap12:body use="literal" />
756
+            </wsdl:input>
757
+            <wsdl:output>
758
+                <soap12:body use="literal" />
759
+            </wsdl:output>
760
+        </wsdl:operation>
761
+
762
+        <wsdl:operation name="GetDiagnostics">
763
+            <soap12:operation soapAction="/GetDiagnostics" style="document" />
764
+            <wsdl:input>
765
+                <soap12:header use="literal" message="tns:Header" part="ChargeBoxIdentity"/>
766
+                <soap12:body use="literal" />
767
+            </wsdl:input>
768
+            <wsdl:output>
769
+                <soap12:body use="literal" />
770
+            </wsdl:output>
771
+        </wsdl:operation>
772
+
773
+        <wsdl:operation name="ClearCache">
774
+            <soap12:operation soapAction="/ClearCache" style="document" />
775
+            <wsdl:input>
776
+                <soap12:header use="literal" message="tns:Header" part="ChargeBoxIdentity"/>
777
+                <soap12:body use="literal" />
778
+            </wsdl:input>
779
+            <wsdl:output>
780
+                <soap12:body use="literal" />
781
+            </wsdl:output>
782
+        </wsdl:operation>
783
+
784
+        <wsdl:operation name="UpdateFirmware">
785
+            <soap12:operation soapAction="/UpdateFirmware" style="document" />
786
+            <wsdl:input>
787
+                <soap12:header use="literal" message="tns:Header" part="ChargeBoxIdentity"/>
788
+                <soap12:body use="literal" />
789
+            </wsdl:input>
790
+            <wsdl:output>
791
+                <soap12:body use="literal" />
792
+            </wsdl:output>
793
+        </wsdl:operation>
794
+
795
+        <wsdl:operation name="ChangeConfiguration">
796
+            <soap12:operation soapAction="/ChangeConfiguration" style="document" />
797
+            <wsdl:input>
798
+                <soap12:header use="literal" message="tns:Header" part="ChargeBoxIdentity"/>
799
+                <soap12:body use="literal" />
800
+            </wsdl:input>
801
+            <wsdl:output>
802
+                <soap12:body use="literal" />
803
+            </wsdl:output>
804
+        </wsdl:operation>
805
+
806
+        <wsdl:operation name="RemoteStartTransaction">
807
+            <soap12:operation soapAction="/RemoteStartTransaction" style="document" />
808
+            <wsdl:input>
809
+                <soap12:header use="literal" message="tns:Header" part="ChargeBoxIdentity"/>
810
+                <soap12:body use="literal" />
811
+            </wsdl:input>
812
+            <wsdl:output>
813
+                <soap12:body use="literal" />
814
+            </wsdl:output>
815
+        </wsdl:operation>
816
+
817
+        <wsdl:operation name="RemoteStopTransaction">
818
+            <soap12:operation soapAction="/RemoteStopTransaction" style="document" />
819
+            <wsdl:input>
820
+                <soap12:header use="literal" message="tns:Header" part="ChargeBoxIdentity"/>
821
+                <soap12:body use="literal" />
822
+            </wsdl:input>
823
+            <wsdl:output>
824
+                <soap12:body use="literal" />
825
+            </wsdl:output>
826
+        </wsdl:operation>
827
+
828
+        <wsdl:operation name="CancelReservation">
829
+            <soap12:operation soapAction="/CancelReservation" style="document" />
830
+            <wsdl:input>
831
+                <soap12:header use="literal" message="tns:Header" part="ChargeBoxIdentity"/>
832
+                <soap12:body use="literal" />
833
+            </wsdl:input>
834
+            <wsdl:output>
835
+                <soap12:body use="literal" />
836
+            </wsdl:output>
837
+        </wsdl:operation>
838
+
839
+        <wsdl:operation name="DataTransfer">
840
+            <soap12:operation soapAction="/DataTransfer" style="document" />
841
+            <wsdl:input>
842
+                <soap12:header use="literal" message="tns:Header" part="ChargeBoxIdentity"/>
843
+                <soap12:body use="literal" />
844
+            </wsdl:input>
845
+            <wsdl:output>
846
+                <soap12:body use="literal" />
847
+            </wsdl:output>
848
+        </wsdl:operation>
849
+
850
+        <wsdl:operation name="GetConfiguration">
851
+            <soap12:operation soapAction="/GetConfiguration" style="document" />
852
+            <wsdl:input>
853
+                <soap12:header use="literal" message="tns:Header" part="ChargeBoxIdentity"/>
854
+                <soap12:body use="literal" />
855
+            </wsdl:input>
856
+            <wsdl:output>
857
+                <soap12:body use="literal" />
858
+            </wsdl:output>
859
+        </wsdl:operation>
860
+
861
+        <wsdl:operation name="GetLocalListVersion">
862
+            <soap12:operation soapAction="/GetLocalListVersion" style="document" />
863
+            <wsdl:input>
864
+                <soap12:header use="literal" message="tns:Header" part="ChargeBoxIdentity"/>
865
+                <soap12:body use="literal" />
866
+            </wsdl:input>
867
+            <wsdl:output>
868
+                <soap12:body use="literal" />
869
+            </wsdl:output>
870
+        </wsdl:operation>
871
+
872
+        <wsdl:operation name="ReserveNow">
873
+            <soap12:operation soapAction="/ReserveNow" style="document" />
874
+            <wsdl:input>
875
+                <soap12:header use="literal" message="tns:Header" part="ChargeBoxIdentity"/>
876
+                <soap12:body use="literal" />
877
+            </wsdl:input>
878
+            <wsdl:output>
879
+                <soap12:body use="literal" />
880
+            </wsdl:output>
881
+        </wsdl:operation>
882
+
883
+        <wsdl:operation name="SendLocalList">
884
+            <soap12:operation soapAction="/SendLocalList" style="document" />
885
+            <wsdl:input>
886
+                <soap12:header use="literal" message="tns:Header" part="ChargeBoxIdentity"/>
887
+                <soap12:body use="literal" />
888
+            </wsdl:input>
889
+            <wsdl:output>
890
+                <soap12:body use="literal" />
891
+            </wsdl:output>
892
+        </wsdl:operation>
893
+
894
+    </wsdl:binding>
895
+
896
+
897
+    <!-- The OCPP ChargePoint service -->
898
+    <wsdl:service name="ChargePointService">
899
+        <wsdl:documentation>The ChargePoint Service for the Open Charge Point Protocol</wsdl:documentation>
900
+        <wsdl:port name="ChargePointServiceSoap12" binding="tns:ChargePointServiceSoap">
901
+            <soap12:address location="http://localhost:9000/Ocpp/ChargePointService/" />
902
+        </wsdl:port>
903
+    </wsdl:service>
904
+</wsdl:definitions>

+ 20 - 0
charger-simulator/src/soap/xmlUtils.ts

@@ -0,0 +1,20 @@
1
+import {Builder, parseString} from "xml2js"
2
+
3
+export async function prettyPrintXml(xml): Promise<string> {
4
+  return new Promise<string>((resolve, reject) => {
5
+    parseString(xml, (err, parsed) => {
6
+      if (err) {
7
+        reject(err)
8
+        return
9
+      }
10
+
11
+      try {
12
+        const formatted = new Builder({headless: true}).buildObject(parsed)
13
+
14
+        resolve("\n" + formatted.replace(/n\/  \n/g))
15
+      } catch (e) {
16
+        reject(e)
17
+      }
18
+    })
19
+  })
20
+}

+ 12 - 0
charger-simulator/tsconfig.json

@@ -0,0 +1,12 @@
1
+{
2
+  "compilerOptions": {
3
+    "target": "es5",
4
+    "module": "CommonJS",
5
+    "outDir": "dist",
6
+    "lib": [
7
+      "es6"
8
+    ],
9
+    "declaration": true
10
+  },
11
+  "include": ["src/**/*.ts"]
12
+}

Разлика између датотеке није приказан због своје велике величине
+ 1094 - 0
charger-simulator/yarn.lock


+ 65 - 0
cs.py

@@ -0,0 +1,65 @@
1
+import asyncio
2
+import logging
3
+import websockets
4
+from datetime import datetime
5
+
6
+from ocpp.routing import on
7
+from ocpp.v201 import ChargePoint as cp
8
+from ocpp.v201 import call_result
9
+from ocpp.v201.enums import RegistrationStatusType
10
+
11
+logging.basicConfig(level=logging.INFO)
12
+
13
+
14
+class ChargePoint(cp):
15
+    @on('BootNotification')
16
+    async def on_boot_notification(self, charging_station, reason, **kwargs):
17
+        return call_result.BootNotificationPayload(
18
+            current_time=datetime.utcnow().isoformat(),
19
+            interval=10,
20
+            status=RegistrationStatusType.accepted
21
+        )
22
+
23
+
24
+async def on_connect(websocket, path):
25
+    """ For every new charge point that connects, create a ChargePoint
26
+    instance and start listening for messages.
27
+    """
28
+    try:
29
+        requested_protocols = websocket.request_headers[
30
+            'Sec-WebSocket-Protocol']
31
+    except KeyError:
32
+        logging.info("Client hasn't requested any Subprotocol. "
33
+                 "Closing Connection")
34
+        return await websocket.close()
35
+
36
+    if websocket.subprotocol:
37
+        logging.info("Protocols Matched: %s", websocket.subprotocol)
38
+    else:
39
+        # In the websockets lib if no subprotocols are supported by the
40
+        # client and the server, it proceeds without a subprotocol,
41
+        # so we have to manually close the connection.
42
+        logging.warning('Protocols Mismatched | Expected Subprotocols: %s,'
43
+                        ' but client supports  %s | Closing connection',
44
+                        websocket.available_subprotocols,
45
+                        requested_protocols)
46
+        return await websocket.close()
47
+
48
+    charge_point_id = path.strip('/')
49
+    cp = ChargePoint(charge_point_id, websocket)
50
+
51
+    await cp.start()
52
+
53
+
54
+async def main():
55
+    server = await websockets.serve(
56
+        on_connect,
57
+        '0.0.0.0',
58
+        9000,
59
+        subprotocols=['ocpp1.6']
60
+    )
61
+    logging.info("WebSocket Server Started")
62
+    await server.wait_closed()
63
+
64
+if __name__ == '__main__':
65
+    asyncio.run(main())

+ 190 - 0
cs1_6.py

@@ -0,0 +1,190 @@
1
+import asyncio
2
+import logging
3
+from datetime import datetime
4
+from pprint import pprint
5
+
6
+try:
7
+	import websockets
8
+except ModuleNotFoundError:
9
+	print("This example relies on the 'websockets' package.")
10
+	print("Please install it by running: ")
11
+	print()
12
+	print(" $ pip install websockets")
13
+	import sys
14
+
15
+	sys.exit(1)
16
+
17
+from ocpp.routing import on, after
18
+from ocpp.v16 import ChargePoint as cp
19
+from ocpp.v16 import call_result
20
+from ocpp.v16.datatypes import IdTagInfo
21
+from ocpp.v16.enums import Action, RegistrationStatus, AuthorizationStatus
22
+from ocpp.messages import Call, MessageType, unpack, validate_payload
23
+
24
+
25
+logging.basicConfig(level=logging.INFO)
26
+
27
+class CustomCP(cp):
28
+    def __init__(self, id, connection, response_timeout=30):
29
+        super().__init__(id, connection, response_timeout)
30
+
31
+    async def _handle_call(self, msg):
32
+        """
33
+        Execute all hooks installed for based on the Action of the message.
34
+
35
+        First the '_on_action' hook is executed and its response is returned to
36
+        the client. If there is no '_on_action' hook for Action in the message
37
+        a CallError with a NotImplementedError is returned. If the Action is
38
+        not supported by the OCPP version a NotSupportedError is returned.
39
+
40
+        Next the '_after_action' hook is executed.
41
+
42
+        """
43
+        try:
44
+            handlers = self.route_map[msg.action]
45
+        except KeyError:
46
+            _raise_key_error(msg.action, self._ocpp_version)
47
+            return
48
+
49
+        if not handlers.get("_skip_schema_validation", False):
50
+            validate_payload(msg, self._ocpp_version)
51
+        # OCPP uses camelCase for the keys in the payload. It's more pythonic
52
+        # to use snake_case for keyword arguments. Therefore the keys must be
53
+        # 'translated'. Some examples:
54
+        #
55
+        # * chargePointVendor becomes charge_point_vendor
56
+        # * firmwareVersion becomes firmwareVersion
57
+        if msg.payload is None:
58
+            msg.payload = {}
59
+        snake_case_payload = camel_to_snake_case(msg.payload)
60
+
61
+        try:
62
+            handler = handlers["_on_action"]
63
+        except KeyError:
64
+            _raise_key_error(msg.action, self._ocpp_version)
65
+
66
+        try:
67
+            response = handler(**snake_case_payload)
68
+            if inspect.isawaitable(response):
69
+                response = await response
70
+        except Exception as e:
71
+            LOGGER.exception("Error while handling request '%s'", msg)
72
+            response = msg.create_call_error(e).to_json()
73
+            await self._send(response)
74
+
75
+            return
76
+
77
+        temp_response_payload = asdict(response)
78
+
79
+        # Remove nones ensures that we strip out optional arguments
80
+        # which were not set and have a default value of None
81
+        response_payload = remove_nones(temp_response_payload)
82
+
83
+        # The response payload must be 'translated' from snake_case to
84
+        # camelCase. So:
85
+        #
86
+        # * charge_point_vendor becomes chargePointVendor
87
+        # * firmware_version becomes firmwareVersion
88
+        camel_case_payload = snake_to_camel_case(response_payload)
89
+
90
+        response = msg.create_call_result(camel_case_payload)
91
+
92
+        if not handlers.get("_skip_schema_validation", False):
93
+            validate_payload(response, self._ocpp_version)
94
+
95
+        await self._send(response.to_json())
96
+
97
+        try:
98
+            handler = handlers["_after_action"]
99
+            # Create task to avoid blocking when making a call inside the
100
+            # after handler
101
+            response = handler(**snake_case_payload)
102
+            if inspect.isawaitable(response):
103
+                asyncio.ensure_future(response)
104
+        except KeyError:
105
+            # '_on_after' hooks are not required. Therefore ignore exception
106
+            # when no '_on_after' hook is installed.
107
+            pass
108
+        return response
109
+	
110
+
111
+class ChargePoint(cp):
112
+
113
+	@on(Action.BootNotification)
114
+	def on_boot_notification(
115
+			self, charge_point_vendor: str, charge_point_model: str, **kwargs):
116
+		pprint(kwargs)
117
+		return call_result.BootNotificationPayload(
118
+				current_time=datetime.utcnow().isoformat(),
119
+				interval=10,
120
+				status=RegistrationStatus.accepted,
121
+				)
122
+
123
+	@on(Action.Authorize)
124
+	def on_authorization(self, id_tag):
125
+		# pprint(kwargs)
126
+		idti = IdTagInfo(status=AuthorizationStatus.accepted)
127
+		# idti.status = AuthorizationStatus.accepted
128
+
129
+		return call_result.AuthorizePayload(
130
+				id_tag_info=idti
131
+				)
132
+
133
+	@on(Action.StatusNotification)
134
+	def on_status_notification(self, id_tag):
135
+		# pprint(kwargs)
136
+		# idti = IdTagInfo(status=AuthorizationStatus.accepted)
137
+		# idti.status = AuthorizationStatus.accepted
138
+		return call_result.StatusNotificationPayload()
139
+
140
+	@on(Action.Heartbeat, skip_schema_validation=True)
141
+	def on_heartbeat(self, **kwargs):  # receives empty payload from CP
142
+		print("--HeartBeat--")
143
+		print(kwargs)
144
+		return call_result.HeartbeatPayload(
145
+				current_time=datetime.utcnow().strftime("%Y-%m-%dT%H:%M:%SZ")
146
+				)
147
+
148
+
149
+
150
+async def on_connect(websocket, path):
151
+	"""For every new charge point that connects, create a ChargePoint
152
+	instance and start listening for messages.
153
+	"""
154
+	try:
155
+		requested_protocols = websocket.request_headers["Sec-WebSocket-Protocol"]
156
+	except KeyError:
157
+		logging.error("Client hasn't requested any Subprotocol. Closing Connection")
158
+		return await websocket.close()
159
+	if websocket.subprotocol:
160
+		logging.info("Protocols Matched: %s", websocket.subprotocol)
161
+	else:
162
+		# In the websockets lib if no subprotocols are supported by the
163
+		# client and the server, it proceeds without a subprotocol,
164
+		# so we have to manually close the connection.
165
+		logging.warning(
166
+				"Protocols Mismatched | Expected Subprotocols: %s,"
167
+				" but client supports  %s | Closing connection",
168
+				websocket.available_subprotocols,
169
+				requested_protocols,
170
+				)
171
+		return await websocket.close()
172
+
173
+	charge_point_id = path.strip("/")
174
+	cp = ChargePoint(charge_point_id, websocket)
175
+
176
+	await cp.start()
177
+
178
+
179
+async def main():
180
+	server = await websockets.serve(
181
+			on_connect, "0.0.0.0", 9000, subprotocols=["ocpp1.6"]
182
+			)
183
+
184
+	logging.info("Server Started listening to new connections...")
185
+	await server.wait_closed()
186
+
187
+
188
+if __name__ == "__main__":
189
+	# asyncio.run() is used when running this example with Python >= 3.7v
190
+	asyncio.run(main())

+ 1 - 0
ocpp

@@ -0,0 +1 @@
1
+Subproject commit a9df8ebdaee922c323be1d06eace2d5a35a5f747