font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
- color: #2c3e50;
+ color: black;
+ background-color: white;
}
body {
height: fit-content;
width: fit-content;
- margin: 0.05%;
- padding: 0.05%;
- background-color: rgb(233, 227, 227);
+ margin: 0.001%;
+ padding: 0.001%;
}
</style>
justify-content: center;
align-items: center;
inset: 0;
- background-color: rgba(0, 0, 0, 0.2);
+ background-color: black;
}
</style>
<template>
- <td class="cs-table__column">
- <Button @click="startChargingStation()">Start Charging Station</Button>
- <Button @click="stopChargingStation()">Stop Charging Station</Button>
- <Button @click="openConnection()">Open Connection</Button>
- <Button @click="closeConnection()">Close Connection</Button>
- <Button @click="startTransaction()">Start Transaction</Button>
- <!-- <IdTagInputModal
- :visibility="state.isIdTagModalVisible"
- :id-tag="state.idTag"
- @close="hideIdTagModal()"
- @done="compose(state.transaction, hideIdTagModal)()"
- >
- Start Transaction
- </IdTagInputModal> -->
- <Button @click="stopTransaction()">Stop Transaction</Button>
- <Button @click="startAutomaticTransactionGenerator()">Start ATG</Button>
- <Button @click="stopAutomaticTransactionGenerator()">Stop ATG</Button>
- </td>
- <td class="cs-table__column">{{ connectorId }}</td>
- <td class="cs-table__column">{{ connector.status ?? 'Ø' }}</td>
- <td class="cs-table__column">{{ connector.transactionStarted === true ? 'Yes' : 'No' }}</td>
+ <tr class="connectors-table__row">
+ <td class="connectors-table__column">{{ connectorId }}</td>
+ <td class="connectors-table__column">{{ connector.status ?? 'Ø' }}</td>
+ <td class="connectors-table__column">
+ {{ connector.transactionStarted === true ? 'Yes' : 'No' }}
+ </td>
+ <td class="connectors-table__column">
+ {{ atgStatus?.start === true ? 'Yes' : 'No' }}
+ </td>
+ <td class="connectors-table__column">
+ <Button @click="startTransaction()">Start Transaction</Button>
+ <!-- <IdTagInputModal
+ :visibility="state.isIdTagModalVisible"
+ :id-tag="state.idTag"
+ @close="hideIdTagModal()"
+ @done="compose(state.transaction, hideIdTagModal)()"
+ >
+ Start Transaction
+ </IdTagInputModal> -->
+ <Button @click="stopTransaction()">Stop Transaction</Button>
+ <Button @click="startAutomaticTransactionGenerator()">Start ATG</Button>
+ <Button @click="stopAutomaticTransactionGenerator()">Stop ATG</Button>
+ </td>
+ </tr>
</template>
<script setup lang="ts">
import { getCurrentInstance } from 'vue'
-// import { reactive } 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 type { ConnectorStatus, Status } from '@/types'
// import { compose } from '@/composables'
const props = defineProps<{
hashId: string
- connector: ConnectorStatus
connectorId: number
+ connector: ConnectorStatus
+ atgStatus?: Status
transactionId?: number
idTag?: string
}>()
const UIClient = getCurrentInstance()?.appContext.config.globalProperties.$UIClient
-function startChargingStation(): void {
- UIClient.startChargingStation(props.hashId)
-}
-function stopChargingStation(): void {
- UIClient.stopChargingStation(props.hashId)
-}
-function openConnection(): void {
- UIClient.openConnection(props.hashId)
-}
-function closeConnection(): void {
- UIClient.closeConnection(props.hashId)
-}
function startTransaction(): void {
UIClient.startTransaction(props.hashId, props.connectorId, props.idTag)
}
<template>
- <tr v-for="(connector, index) in getConnectors()" class="cs-table__row">
- <CSConnector
- :hash-id="getHashId()"
- :connector="connector"
- :connector-id="index + 1"
- :transaction-id="connector.transactionId"
- :id-tag="props.idTag"
- />
+ <tr class="cs-table__row">
<td class="cs-table__column">{{ getId() }}</td>
<td class="cs-table__column">{{ getStarted() }}</td>
- <td class="cs-table__column">{{ getSupervisionUrl() }}</td>
+ <td class="cs-table__column">
+ {{ getSupervisionUrl() }}
+ </td>
<td class="cs-table__column">{{ getWsState() }}</td>
- <td class="cs-table__column">{{ getRegistrationStatus() }}</td>
- <td class="cs-table__column">{{ getInfo().templateName }}</td>
+ <td class="cs-table__column">
+ {{ getRegistrationStatus() }}
+ </td>
+ <td class="cs-table__column">
+ {{ getInfo().templateName }}
+ </td>
<td class="cs-table__column">{{ getVendor() }}</td>
<td class="cs-table__column">{{ getModel() }}</td>
- <td class="cs-table__column">{{ getFirmwareVersion() }}</td>
+ <td class="cs-table__column">
+ {{ getFirmwareVersion() }}
+ </td>
+ <td class="cs-table__column">
+ <Button @click="startChargingStation()">Start Charging Station</Button>
+ <Button @click="stopChargingStation()">Stop Charging Station</Button>
+ <Button @click="openConnection()">Open Connection</Button>
+ <Button @click="closeConnection()">Close Connection</Button>
+ </td>
+ <td class="cs-table__connectors-column">
+ <table id="connectors-table">
+ <thead id="connectors-table__head">
+ <tr class="connectors-table__row">
+ <th scope="col" class="connectors-table__column">Identifier</th>
+ <th scope="col" class="connectors-table__column">Status</th>
+ <th scope="col" class="connectors-table__column">Transaction</th>
+ <th scope="col" class="connectors-table__column">ATG Started</th>
+ <th scope="col" class="connectors-table__column">Actions</th>
+ </tr>
+ </thead>
+ <tbody id="connectors-table__body">
+ <!-- eslint-disable-next-line vue/valid-v-for -->
+ <CSConnector
+ v-for="(connector, index) in getConnectors()"
+ :hash-id="getHashId()"
+ :connector-id="index + 1"
+ :connector="connector"
+ :atg-status="getATGStatus(index + 1)"
+ :transaction-id="connector.transactionId"
+ :id-tag="props.idTag"
+ />
+ </tbody>
+ </table>
+ </td>
</tr>
</template>
<script setup lang="ts">
// import { reactive } from 'vue'
+import { getCurrentInstance } from 'vue'
import CSConnector from '@/components/charging-stations/CSConnector.vue'
-import type { ChargingStationData, ChargingStationInfo, ConnectorStatus } from '@/types'
+import type { ChargingStationData, ChargingStationInfo, ConnectorStatus, Status } from '@/types'
const props = defineProps<{
chargingStation: ChargingStationData
// idTag: ''
// })
-function getConnectors(): ConnectorStatus[] {
- if (Array.isArray(props.chargingStation.evses) && props.chargingStation.evses.length > 0) {
- const connectorsStatus: ConnectorStatus[] = []
- for (const [evseId, evseStatus] of props.chargingStation.evses.entries()) {
- if (evseId > 0 && Array.isArray(evseStatus.connectors) && evseStatus.connectors.length > 0) {
- for (const connectorStatus of evseStatus.connectors) {
- connectorsStatus.push(connectorStatus)
- }
- }
- }
- return connectorsStatus
- }
- return props.chargingStation.connectors?.slice(1)
+function getStarted(): string {
+ return props.chargingStation.started === true ? 'Yes' : 'No'
+}
+function getATGStatus(connectorId: number): Status | undefined {
+ return props.chargingStation.automaticTransactionGenerator
+ ?.automaticTransactionGeneratorStatuses?.[connectorId - 1]
}
function getInfo(): ChargingStationInfo {
return props.chargingStation.stationInfo
function getFirmwareVersion(): string {
return getInfo().firmwareVersion ?? 'Ø'
}
-function getStarted(): string {
- return props.chargingStation.started === true ? 'Yes' : 'No'
-}
function getSupervisionUrl(): string {
const supervisionUrl = new URL(props.chargingStation.supervisionUrl)
return `${supervisionUrl.protocol}//${supervisionUrl.host.split('.').join('.\u200b')}`
function getRegistrationStatus(): string {
return props.chargingStation?.bootNotificationResponse?.status ?? 'Ø'
}
+function getConnectors(): ConnectorStatus[] {
+ if (Array.isArray(props.chargingStation.evses) && props.chargingStation.evses.length > 0) {
+ const connectorsStatus: ConnectorStatus[] = []
+ for (const [evseId, evseStatus] of props.chargingStation.evses.entries()) {
+ if (evseId > 0 && Array.isArray(evseStatus.connectors) && evseStatus.connectors.length > 0) {
+ for (const connectorStatus of evseStatus.connectors) {
+ connectorsStatus.push(connectorStatus)
+ }
+ }
+ }
+ return connectorsStatus
+ }
+ return props.chargingStation.connectors?.slice(1)
+}
+
+const UIClient = getCurrentInstance()?.appContext.config.globalProperties.$UIClient
+
+function startChargingStation(): void {
+ UIClient.startChargingStation(getHashId())
+}
+function stopChargingStation(): void {
+ UIClient.stopChargingStation(getHashId())
+}
+function openConnection(): void {
+ UIClient.openConnection(getHashId())
+}
+function closeConnection(): void {
+ UIClient.closeConnection(getHashId())
+}
// function showTagModal(): void {
// state.isTagModalVisible = true
// }
// state.isTagModalVisible = false
// }
</script>
+
+<style>
+#connectors-table {
+ display: flex;
+ background-color: white;
+ flex-direction: column;
+ overflow: auto hidden;
+ border-collapse: collapse;
+ empty-cells: show;
+}
+
+#connectors-table__head,
+#connectors-table__body {
+ display: flex;
+ flex-direction: column;
+}
+
+.connectors-table__row {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+}
+
+#connectors-table__head .connectors-table__row {
+ background-color: lightgrey;
+}
+
+.connectors-table__row:nth-of-type(even) {
+ background-color: whitesmoke;
+}
+
+.connectors-table__column {
+ width: calc(100% / 5);
+ text-align: center;
+}
+</style>
<template>
<Modal :visibility="props.isVisible">
- <div class="card-info">vendor: {{ props.stationInfo.chargePointVendor }}</div>
+ <div>vendor: {{ props.stationInfo.chargePointVendor }}</div>
</Modal>
</template>
isVisible: boolean
}>()
</script>
-
-<style>
-.card-info {
- background-color: white;
-}
-</style>
</caption>
<thead id="cs-table__head">
<tr class="cs-table__row">
- <th scope="col" class="cs-table__column">Action</th>
- <th scope="col" class="cs-table__column">Connector</th>
- <th scope="col" class="cs-table__column">Status</th>
- <th scope="col" class="cs-table__column">Transaction</th>
<th scope="col" class="cs-table__column">Name</th>
<th scope="col" class="cs-table__column">Started</th>
<th scope="col" class="cs-table__column">Supervision Url</th>
<th scope="col" class="cs-table__column">Template</th>
<th scope="col" class="cs-table__column">Vendor</th>
<th scope="col" class="cs-table__column">Model</th>
- <th scope="col" class="cs-table__column">Firmware Version</th>
+ <th scope="col" class="cs-table__column">Firmware</th>
+ <th scope="col" class="cs-table__column">Actions</th>
+ <th scope="col" class="cs-table__connectors-column">Connector(s)</th>
</tr>
</thead>
<tbody id="cs-table__body">
flex-direction: column;
}
-#cs-table__body {
- overflow: visible overlay;
-}
-
#cs-table__caption {
+ color: white;
+ background-color: black;
font-size: 1.5rem;
font-weight: bold;
padding: 0.5rem;
}
#cs-table__head .cs-table__row {
- background-color: rgb(194, 188, 188);
+ background-color: lightgrey;
}
.cs-table__row:nth-of-type(even) {
- background-color: rgb(223, 217, 217);
+ background-color: whitesmoke;
}
.cs-table__column {
height: fit-content;
- width: calc(100% / 13);
+ width: calc(65% / 10);
+ text-align: center;
+}
+
+.cs-table__connectors-column {
+ height: fit-content;
+ width: 35%;
text-align: center;
}
</style>
import type { JsonObject } from './JsonType'
+export enum IdTagDistribution {
+ RANDOM = 'random',
+ ROUND_ROBIN = 'round-robin',
+ CONNECTOR_AFFINITY = 'connector-affinity'
+}
+
+export interface AutomaticTransactionGeneratorConfiguration {
+ enable: boolean
+ minDuration: number
+ maxDuration: number
+ minDelayBetweenTwoTransactions: number
+ maxDelayBetweenTwoTransactions: number
+ probabilityOfStart: number
+ stopAfterHours: number
+ stopAbsoluteDuration: boolean
+ requireAuthorize?: boolean
+ idTagDistribution?: IdTagDistribution
+}
+
+export interface ChargingStationAutomaticTransactionGeneratorConfiguration {
+ automaticTransactionGenerator?: AutomaticTransactionGeneratorConfiguration
+ automaticTransactionGeneratorStatuses?: Status[]
+}
+
export type ChargingStationData = {
started: boolean
stationInfo: ChargingStationInfo
| typeof WebSocket.CLOSING
| typeof WebSocket.CLOSED
bootNotificationResponse?: BootNotificationResponse
- automaticTransactionGenerator?: Status[]
+ automaticTransactionGenerator?: ChargingStationAutomaticTransactionGeneratorConfiguration
}
export enum OCPP16FirmwareStatus {
export type {
ChargingStationData,
ChargingStationInfo,
- ConnectorStatus
+ ConnectorStatus,
+ Status
} from './ChargingStationType'
export type { ConfigurationData } from './ConfigurationType'
export {
#charging-stations {
height: fit-content;
width: 100%;
- background-color: rgb(233, 227, 227);
display: flex;
flex-direction: column;
}
#reload-button {
flex: auto;
- background-color: rgb(25, 118, 210);
color: white;
+ background-color: blue;
font-size: 35px;
font-weight: bold;
}
#reload-button:hover {
- background-color: rgb(10, 113, 195);
+ background-color: rgb(0, 0, 225);
}
#reload-button:active {
- background-color: rgb(255, 113, 195);
+ background-color: red;
}
#simulator-button {
const wrapper = shallowMount(CSTable, {
props: { chargingStations, idTag: '0' }
})
- expect(wrapper.text()).to.include('Action')
- expect(wrapper.text()).to.include('Connector')
- expect(wrapper.text()).to.include('Status')
- expect(wrapper.text()).to.include('Transaction')
expect(wrapper.text()).to.include('Name')
expect(wrapper.text()).to.include('Started')
expect(wrapper.text()).to.include('Supervision Url')
expect(wrapper.text()).to.include('Template')
expect(wrapper.text()).to.include('Vendor')
expect(wrapper.text()).to.include('Model')
- expect(wrapper.text()).to.include('Firmware Version')
+ expect(wrapper.text()).to.include('Firmware')
+ expect(wrapper.text()).to.include('Actions')
+ expect(wrapper.text()).to.include('Connector(s)')
})