if: ${{ matrix.os == 'ubuntu-latest' && matrix.node == '20.x' }}
run: pnpm lint
- name: pnpm build
- run: |
- pnpm build:prepare
- pnpm build
+ run: pnpm build
- name: pnpm test
run: pnpm test
- name: pnpm coverage
&& pnpm set progress=false \
&& pnpm config set depth 0 \
&& pnpm install --ignore-scripts --frozen-lockfile \
- && pnpm build:prepare \
&& pnpm build
FROM node:lts-alpine
.DS_Store
node_modules
/dist
-/src/assets/config.ts
+/public/config.json
# Created by git for backups. To disable backups in git:
# $ git config --global mergetool.keepBackup false
#### Web UI configuration
-Copy the configuration template [src/assets/config-template.ts](src/assets/config-template.ts) to `src/assets/config.ts`.
+Copy the configuration template [src/assets/config-template.json](src/assets/config-template.json) to `public/config.json`.
### Run
For both options above you can then follow the link displayed in the terminal at the end of compilation. The Web UI looks like the following
-![webui](./assets/webui.png)
+![webui](./src/assets/webui.png)
1. With the top 2 buttons you can now stop and afterwards start the simulator and inspect the server console for the number of charging stations, e.g. with the default configuration: `Charging stations simulator ... started with 10 charging station(s)`
2. Each charging station is a row in the table below, try "Stop Charging Station" and refresh with the large blue button and see the status Started turns from Yes into No.
"start": "pnpm build && node start.js",
"dev": "vite",
"preview": "vite preview",
- "build:prepare": "node build-prepare.js",
"build": "vite build",
"clean:dist": "npx rimraf dist",
"clean:node_modules": "npx rimraf node_modules",
--- /dev/null
+{
+ "uiServer": {
+ "host": "localhost",
+ "port": 8080,
+ "protocol": "ui",
+ "version": "0.0.1",
+ "authentication": {
+ "enabled": false,
+ "type": "basic-auth",
+ "username": "admin",
+ "password": "admin"
+ }
+ }
+}
+++ /dev/null
-import { AuthenticationType, type ConfigurationData, Protocol, ProtocolVersion } from '@/types'
-
-const configuration: ConfigurationData = {
- uiServer: {
- host: 'localhost',
- port: 8080,
- protocol: Protocol.UI,
- version: ProtocolVersion['0.0.1'],
- authentication: {
- enabled: false,
- type: AuthenticationType.BASIC_AUTH,
- username: 'admin',
- password: 'admin'
- }
- }
-}
-
-export default configuration
</template>
<script setup lang="ts">
-// import { reactive } from 'vue'
-import Button from '../buttons/Button.vue'
-// import IdTagInputModal from './IdTagInputModal.vue'
+import { getCurrentInstance } from 'vue'
+// import { reactive } from 'vue';
+// import IdTagInputModal from '@/components/charging-stations/IdTagInputModal.vue'
+import Button from '@/components/buttons/Button.vue'
import type { ConnectorStatus } from '@/types'
-import { UIClient } from '@/composables/UIClient'
-// import { compose } from '@/composables/Utils'
+// import { compose } from '@/composables'
const props = defineProps<{
hashId: string
// state.isIdTagModalVisible = false
// }
+const UIClient = getCurrentInstance()?.appContext.config.globalProperties.$UIClient
+
function startChargingStation(): void {
- UIClient.getInstance().startChargingStation(props.hashId)
+ UIClient.startChargingStation(props.hashId)
}
function stopChargingStation(): void {
- UIClient.getInstance().stopChargingStation(props.hashId)
+ UIClient.stopChargingStation(props.hashId)
}
function openConnection(): void {
- UIClient.getInstance().openConnection(props.hashId)
+ UIClient.openConnection(props.hashId)
}
function closeConnection(): void {
- UIClient.getInstance().closeConnection(props.hashId)
+ UIClient.closeConnection(props.hashId)
}
function startTransaction(): void {
- UIClient.getInstance().startTransaction(props.hashId, props.connectorId, props.idTag)
+ UIClient.startTransaction(props.hashId, props.connectorId, props.idTag)
}
function stopTransaction(): void {
- UIClient.getInstance().stopTransaction(props.hashId, props.transactionId)
+ UIClient.stopTransaction(props.hashId, props.transactionId)
}
function startAutomaticTransactionGenerator(): void {
- UIClient.getInstance().startAutomaticTransactionGenerator(props.hashId, props.connectorId)
+ UIClient.startAutomaticTransactionGenerator(props.hashId, props.connectorId)
}
function stopAutomaticTransactionGenerator(): void {
- UIClient.getInstance().stopAutomaticTransactionGenerator(props.hashId, props.connectorId)
+ UIClient.stopAutomaticTransactionGenerator(props.hashId, props.connectorId)
}
</script>
<script setup lang="ts">
// import { reactive } from 'vue'
-import CSConnector from './CSConnector.vue'
+import CSConnector from '@/components/charging-stations/CSConnector.vue'
import type { ChargingStationData, ChargingStationInfo, ConnectorStatus } from '@/types'
const props = defineProps<{
</template>
<script setup lang="ts">
-import CSData from './CSData.vue'
+import CSData from '@/components/charging-stations/CSData.vue'
import type { ChargingStationData } from '@/types'
const props = defineProps<{
</template>
<script setup lang="ts">
-import Button from '../buttons/Button.vue'
+import Button from '@/components/buttons/Button.vue'
import Modal from '@/components/Modal.vue'
const props = defineProps<{
import {
ApplicationProtocol,
+ type ConfigurationData,
ProcedureName,
type ProtocolResponse,
type RequestPayload,
type ResponsePayload,
ResponseStatus
} from '@/types'
-// @ts-expect-error: configuration file can be non existent
-// eslint-disable-next-line import/no-unresolved
-import configuration from '@/assets/config'
type ResponseHandler = {
procedureName: ProcedureName
private ws!: WebSocket
private responseHandlers: Map<string, ResponseHandler>
- private constructor() {
+ private constructor(private configuration: ConfigurationData) {
this.openWS()
this.responseHandlers = new Map<string, ResponseHandler>()
}
- public static getInstance() {
+ public static getInstance(configuration: ConfigurationData) {
if (UIClient.instance === null) {
- UIClient.instance = new UIClient()
+ UIClient.instance = new UIClient(configuration)
}
return UIClient.instance
}
private openWS(): void {
this.ws = new WebSocket(
- `${configuration.uiServer.secure === true ? ApplicationProtocol.WSS : ApplicationProtocol.WS}://${configuration.uiServer.host}:${configuration.uiServer.port}`,
- `${configuration.uiServer.protocol}${configuration.uiServer.version}`
+ `${this.configuration.uiServer.secure === true ? ApplicationProtocol.WSS : ApplicationProtocol.WS}://${this.configuration.uiServer.host}:${this.configuration.uiServer.port}`,
+ `${this.configuration.uiServer.protocol}${this.configuration.uiServer.version}`
)
this.ws.onmessage = this.responseHandler.bind(this)
this.ws.onerror = errorEvent => {
const sendTimeout = setTimeout(() => {
this.responseHandlers.delete(uuid)
return reject(new Error(`Send request '${procedureName}' message timeout`))
- }, 60 * 1000)
+ }, 60000)
try {
this.ws.send(msg)
this.responseHandlers.set(uuid, { procedureName, resolve, reject })
-// export const compose = <T>(...fns: ((arg: T) => T)[]): ((x: T) => T) => {
-// return (x: T) => fns.reduceRight((y, fn) => fn(y), x)
-// }
+export const compose = <T>(...fns: ((arg: T) => T)[]): ((x: T) => T) => {
+ return (x: T) => fns.reduceRight((y, fn) => fn(y), x)
+}
--- /dev/null
+export { UIClient } from './UIClient'
+export { compose } from './Utils'
import { createApp } from 'vue'
-import App from './App.vue'
-import router from './router'
+import router from '@/router'
+import { UIClient } from '@/composables'
+import App from '@/App.vue'
-createApp(App).use(router).mount('#app')
+const app = createApp(App)
+
+fetch('/config.json')
+ .then(response => response.json())
+ .then(config => {
+ app.config.globalProperties.$UIClient = UIClient.getInstance(config)
+ app.use(router).mount('#app')
+ })
</template>
<script setup lang="ts">
-import { onMounted, reactive } from 'vue'
+import { getCurrentInstance, onMounted, reactive } from 'vue'
import CSTable from '@/components/charging-stations/CSTable.vue'
import type { ChargingStationData } from '@/types'
import Container from '@/components/Container.vue'
import ReloadButton from '@/components/buttons/ReloadButton.vue'
-import { UIClient } from '@/composables/UIClient'
-const UIClientInstance = UIClient.getInstance()
+const UIClient = getCurrentInstance()?.appContext.config.globalProperties.$UIClient
onMounted(() => {
- UIClientInstance.registerWSonOpenListener(load)
+ UIClient.registerWSonOpenListener(load)
})
type State = {
async function load(): Promise<void> {
if (state.isLoading === true) return
state.isLoading = true
- const listChargingStationsPayload = await UIClientInstance.listChargingStations()
+ const listChargingStationsPayload = await UIClient.listChargingStations()
state.chargingStations =
listChargingStationsPayload.chargingStations as unknown as ChargingStationData[]
state.isLoading = false
}
function startSimulator(): void {
- UIClientInstance.startSimulator()
+ UIClient.startSimulator()
}
function stopSimulator(): void {
- UIClientInstance.stopSimulator()
+ UIClient.stopSimulator()
}
</script>