"prettier": "^2.8.1",
         "release-it": "^15.5.1",
         "robohydra": "^0.6.9",
-        "rollup": "^3.8.0",
+        "rollup": "^3.8.1",
         "rollup-plugin-analyzer": "^4.0.0",
         "rollup-plugin-copy": "^3.4.0",
         "rollup-plugin-delete": "^2.0.0",
       }
     },
     "node_modules/rollup": {
-      "version": "3.8.0",
-      "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.8.0.tgz",
-      "integrity": "sha512-+UR6PnUslneJNiJfLSzy4XH6R50ZGF0MS7UCv20ftXrktF/TkvZDwiBtXX65esblLR5p8w6LmXgPwt2f2B8SoQ==",
+      "version": "3.8.1",
+      "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.8.1.tgz",
+      "integrity": "sha512-4yh9eMW7byOroYcN8DlF9P/2jCpu6txVIHjEqquQVSx7DI0RgyCCN3tjrcy4ra6yVtV336aLBB3v2AarYAxePQ==",
       "dev": true,
       "bin": {
         "rollup": "dist/bin/rollup"
       }
     },
     "rollup": {
-      "version": "3.8.0",
-      "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.8.0.tgz",
-      "integrity": "sha512-+UR6PnUslneJNiJfLSzy4XH6R50ZGF0MS7UCv20ftXrktF/TkvZDwiBtXX65esblLR5p8w6LmXgPwt2f2B8SoQ==",
+      "version": "3.8.1",
+      "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.8.1.tgz",
+      "integrity": "sha512-4yh9eMW7byOroYcN8DlF9P/2jCpu6txVIHjEqquQVSx7DI0RgyCCN3tjrcy4ra6yVtV336aLBB3v2AarYAxePQ==",
       "dev": true,
       "requires": {
         "fsevents": "~2.3.2"
 
     "prettier": "^2.8.1",
     "release-it": "^15.5.1",
     "robohydra": "^0.6.9",
-    "rollup": "^3.8.0",
+    "rollup": "^3.8.1",
     "rollup-plugin-analyzer": "^4.0.0",
     "rollup-plugin-copy": "^3.4.0",
     "rollup-plugin-delete": "^2.0.0",
 
   "baseName": "CS-ABB",
   "chargePointModel": "MD_TERRA_53",
   "chargePointVendor": "ABB",
+  "firmwareVersionPattern": "^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)$",
   "firmwareVersion": "4.0.4.22",
   "power": 50000,
   "powerSharedByConnectors": true,
 
   "baseName": "CS-ABB",
   "chargePointModel": "MD_TERRA_53",
   "chargePointVendor": "ABB",
+  "firmwareVersionPattern": "^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)$",
   "firmwareVersion": "4.0.4.22",
   "power": 50000,
   "powerSharedByConnectors": true,
 
   "chargePointModel": "MONOBLOCK",
   "chargePointVendor": "Schneider Electric",
   "chargeBoxSerialNumberPrefix": "EV.2S7P04",
+  "firmwareVersionPattern": "^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)$",
   "firmwareVersion": "3.3.0.10",
   "power": 7360,
   "powerUnit": "W",
 
   "chargePointModel": "MONOBLOCK",
   "chargePointVendor": "Schneider Electric",
   "chargeBoxSerialNumberPrefix": "EV.2S22P04",
+  "firmwareVersionPattern": "^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)$",
   "firmwareVersion": "3.3.0.10",
   "power": 22080,
   "powerUnit": "W",
 
   "chargePointModel": "MONOBLOCK",
   "chargePointVendor": "Schneider Electric",
   "chargeBoxSerialNumberPrefix": "EV.2S22P44",
+  "firmwareVersionPattern": "^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)$",
   "firmwareVersion": "3.3.0.10",
   "power": 44160,
   "powerUnit": "W",
 
       'supervisionUrl',
       'supervisionUrls'
     );
+    const firmwareVersionRegExp = stationTemplate.firmwareVersionPattern
+      ? new RegExp(stationTemplate.firmwareVersionPattern)
+      : Constants.SEMVER_REGEXP;
+    if (
+      stationTemplate.firmwareVersion &&
+      firmwareVersionRegExp.test(stationTemplate.firmwareVersion) === false
+    ) {
+      logger.warn(
+        `${this.logPrefix()} Firmware version '${
+          stationTemplate.firmwareVersion
+        }' does not match regular expression '${firmwareVersionRegExp.toString()}'`
+      );
+    }
     const stationInfo: ChargingStationInfo =
       ChargingStationUtils.stationTemplateToStationInfo(stationTemplate);
     stationInfo.hashId = ChargingStationUtils.getHashId(this.index, stationTemplate);
 
 
 export type WsOptions = ClientOptions & ClientRequestArgs;
 
+type FirmwareUpgrade = {
+  versionUpgrade: {
+    patternGroup?: number | number[];
+    to?: string;
+  };
+  reset?: boolean;
+  resetDelay?: number;
+  checkIntegrity?: boolean;
+};
+
 type CommandsSupport = {
   incomingCommands: Record<IncomingRequestCommand, boolean>;
   outgoingCommands?: Record<RequestCommand, boolean>;
   chargePointVendor: string;
   chargePointSerialNumberPrefix?: string;
   chargeBoxSerialNumberPrefix?: string;
+  firmwareVersionPattern?: string;
   firmwareVersion?: string;
+  firmwareUpgrade?: FirmwareUpgrade;
   iccid?: string;
   imsi?: string;
   meterSerialNumberPrefix?: string;
 
   static readonly CHARGING_STATION_ATG_INITIALIZATION_TIME = 1000; // Ms
   static readonly CHARGING_STATION_ATG_DEFAULT_STOP_AFTER_HOURS = 0.25; // Hours
 
+  // See https://semver.org/#is-there-a-suggested-regular-expression-regex-to-check-a-semver-string
+  static readonly SEMVER_REGEXP =
+    /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/;
+
   static readonly DEFAULT_CIRCULAR_BUFFER_CAPACITY = Number.MAX_SAFE_INTEGER;
 
   static readonly DEFAULT_HASH_ALGORITHM = 'sha384';
 
   chargingStationId?: string;
   chargePointModel: string;
   chargePointVendor: string;
+  firmwareVersionPattern?: string;
   firmwareVersion?: string;
   numberOfConnectors?: number | number[];
   baseName: string;