]> Piment Noir Git Repositories - e-mobility-charging-stations-simulator.git/commitdiff
fix(ui-server): harmonize setSupervisionUrl semantics and text descriptions
authorJérôme Benoit <jerome.benoit@sap.com>
Wed, 22 Apr 2026 18:28:07 +0000 (20:28 +0200)
committerJérôme Benoit <jerome.benoit@sap.com>
Wed, 22 Apr 2026 18:28:07 +0000 (20:28 +0200)
- Fix SetSupervisionUrl.vue passing empty credentials that silently
  clear existing values; align with AddChargingStations.vue pattern
- Fix double saveStationInfo() call and missing updated event when
  only URL changes in ChargingStation.setSupervisionUrl
- Remove verbose JSDoc, redundant comment, and parenthetical UI label
- Harmonize MCP descriptions: use natural language instead of camelCase
  code names, unify credential field descriptions across schemas

src/charging-station/ChargingStation.ts
src/charging-station/ui-server/mcp/MCPToolSchemas.ts
ui/web/src/components/actions/AddChargingStations.vue
ui/web/src/components/actions/SetSupervisionUrl.vue
ui/web/tests/unit/SetSupervisionUrl.test.ts

index 170f376ded340768c63ab2c1ca5158e051b23a73..674825e1c14b60f48fa516c13a52ca97c77fb03a 100644 (file)
@@ -993,10 +993,10 @@ export class ChargingStation extends EventEmitter {
   }
 
   /**
-   * Updates the supervision server URL and optionally the CSMS basic auth credentials in configuration or station info.
-   * @param url - The new supervision server URL
-   * @param supervisionUser - The new CSMS basic auth user (optional; "" clears, undefined preserves)
-   * @param supervisionPassword - The new CSMS basic auth password (optional; "" clears, undefined preserves)
+   * Updates the supervision server URL and optionally the CSMS basic auth credentials.
+   * @param url
+   * @param supervisionUser
+   * @param supervisionPassword
    */
   public setSupervisionUrl (
     url: string,
@@ -1011,9 +1011,8 @@ export class ChargingStation extends EventEmitter {
     } else if (this.stationInfo != null) {
       this.stationInfo.supervisionUrls = url
       this.configuredSupervisionUrl = this.getConfiguredSupervisionUrl()
-      this.saveStationInfo()
     }
-    if (this.stationInfo != null && (supervisionUser != null || supervisionPassword != null)) {
+    if (this.stationInfo != null) {
       if (supervisionUser != null) {
         this.stationInfo.supervisionUser = supervisionUser
       }
@@ -1576,9 +1575,6 @@ export class ChargingStation extends EventEmitter {
       checkEvsesConfiguration(stationTemplate, this.logPrefix(), this.templateFile)
     }
     const stationInfo = stationTemplateToStationInfo(stationTemplate)
-    // hashId and chargingStationId are intentionally not set here. They are derived
-    // at the end of getStationInfo() so that any identity overrides coming from
-    // ChargingStationOptions (baseName, fixedName, nameSuffix) are honoured.
     stationInfo.templateIndex = this.index
     stationInfo.templateName = buildTemplateName(this.templateFile)
     createSerialNumber(stationTemplate, stationInfo)
index 703cabf4023030c55b77824ad8499f8f40428e0a..30c910989dea22d1d2a6f6e6690ed415edeb7bb7 100644 (file)
@@ -35,16 +35,18 @@ const chargingStationOptionsSchema = z.object({
   baseName: z
     .string()
     .optional()
-    .describe('Override the template base name used to derive the chargingStationId'),
+    .describe('Override the template base name used to derive the charging station id'),
   enableStatistics: z.boolean().optional().describe('Enable charging station statistics'),
   fixedName: z
     .boolean()
     .optional()
-    .describe('Use baseName verbatim as chargingStationId instead of appending index/suffix'),
+    .describe('Use base name verbatim as charging station id instead of appending index/suffix'),
   nameSuffix: z
     .string()
     .optional()
-    .describe('Suffix appended to the derived chargingStationId (ignored when fixedName is true)'),
+    .describe(
+      'Suffix appended to the derived charging station id (ignored when fixed name is true)'
+    ),
   ocppStrictCompliance: z
     .boolean()
     .optional()
@@ -338,17 +340,17 @@ export const mcpToolSchemas = new Map<ProcedureName, MCPToolSchema>([
     ProcedureName.SET_SUPERVISION_URL,
     {
       description:
-        'Set the OCPP server supervision URL for one or more charging stations. Optionally updates the CSMS basic auth credentials (empty string clears a credential, undefined preserves it).',
+        'Set the OCPP server supervision URL and optionally the CSMS basic auth credentials for one or more charging stations',
       inputSchema: z.object({
         hashIds,
         supervisionPassword: z
           .string()
           .optional()
-          .describe('CSMS basic auth password (empty string clears)'),
+          .describe('CSMS basic auth password used on the supervision WebSocket'),
         supervisionUser: z
           .string()
           .optional()
-          .describe('CSMS basic auth user (empty string clears)'),
+          .describe('CSMS basic auth user used on the supervision WebSocket'),
         url: z.url().describe('The OCPP server supervision URL to set'),
       }),
     },
index dbd968bc7b296e0d2defa5a619db8812b0c8b4c1..8a7f3264ebc22d7f46b5096ddd2229ecd264d5aa 100644 (file)
@@ -43,7 +43,7 @@
         placeholder="<template value>"
         type="text"
       >
-      Fixed name (base name is full station name):
+      Fixed name:
       <input
         v-model="state.fixedName"
         false-value="false"
index e6dbbe165889439c5244ef7c2947f240101045e4..cb761991b0017c0d7c9bf47ae9780414e38ed09f 100644 (file)
@@ -76,8 +76,8 @@ const setSupervisionUrl = (): void => {
     $uiClient.setSupervisionUrl(
       props.hashId,
       state.value.supervisionUrl,
-      state.value.supervisionUser,
-      state.value.supervisionPassword
+      state.value.supervisionUser.length > 0 ? state.value.supervisionUser : undefined,
+      state.value.supervisionPassword.length > 0 ? state.value.supervisionPassword : undefined
     ),
     'Supervision url successfully set',
     'Error at setting supervision url',
index 9c610866ed16ef03268a2af3ca60f22e15e4e028..92efac66a9948b1b7c5559b400c05366da365f77 100644 (file)
@@ -63,7 +63,7 @@ describe('SetSupervisionUrl', () => {
     expect(wrapper.find('#supervision-password').exists()).toBe(true)
   })
 
-  it('should send empty credential strings when only url is set', async () => {
+  it('should preserve existing credentials when only url is set', async () => {
     const wrapper = mountComponent()
     await wrapper.find('#supervision-url').setValue('wss://new-server.com:9000')
     await wrapper.find('button').trigger('click')
@@ -71,8 +71,8 @@ describe('SetSupervisionUrl', () => {
     expect(mockClient.setSupervisionUrl).toHaveBeenCalledWith(
       TEST_HASH_ID,
       'wss://new-server.com:9000',
-      '',
-      ''
+      undefined,
+      undefined
     )
   })
 
@@ -91,7 +91,7 @@ describe('SetSupervisionUrl', () => {
     )
   })
 
-  it('should send empty password when only user is typed', async () => {
+  it('should preserve password when only user is typed', async () => {
     const wrapper = mountComponent()
     await wrapper.find('#supervision-url').setValue('wss://new-server.com:9000')
     await wrapper.find('#supervision-user').setValue('alice')
@@ -101,7 +101,7 @@ describe('SetSupervisionUrl', () => {
       TEST_HASH_ID,
       'wss://new-server.com:9000',
       'alice',
-      ''
+      undefined
     )
   })