From: Jérôme Benoit Date: Sat, 10 Jul 2021 19:50:01 +0000 (+0200) Subject: Add GetDiagnostics command support X-Git-Tag: v1.0.27~2 X-Git-Url: https://git.piment-noir.org/?a=commitdiff_plain;h=47e224777669f935f45d443b6da948e7977fd9b7;p=e-mobility-charging-stations-simulator.git Add GetDiagnostics command support Signed-off-by: Jérôme Benoit --- diff --git a/.gitignore b/.gitignore index 102f38e5..5dfe331f 100644 --- a/.gitignore +++ b/.gitignore @@ -88,3 +88,5 @@ Thumbs.db # MTA *.mta mta_archives/ + +*.tar.gz diff --git a/README.md b/README.md index 45fee8ad..bcdefa60 100644 --- a/README.md +++ b/README.md @@ -63,6 +63,7 @@ numberOfConnectors | | | integer\|integer[] | charging stations number of connec useConnectorId0 | true/false | true | boolean | use connector id 0 definition from the template randomConnectors | true/false | false | boolean | randomize runtime connector id affectation from the connector id definition in template resetTime | | 60 | integer | seconds to wait before the charging stations come back at reset +autoRegister | true/false | false | boolean | set the charging station as registered at boot notification for testing purpose autoReconnectMaxRetries | | -1 (unlimited) | integer | connection retries to the OCPP-J server reconnectExponentialDelay | true/false | false | boolean | connection delay retry to the OCPP-J server registrationMaxRetries | | -1 (unlimited) | integer | charging stations boot notification retries diff --git a/package-lock.json b/package-lock.json index 03650d0d..943cfc83 100644 --- a/package-lock.json +++ b/package-lock.json @@ -960,12 +960,12 @@ } }, "@es-joy/jsdoccomment": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.8.0.tgz", - "integrity": "sha512-Xd3GzYsL2sz2pcdtYt5Q0Wz1ol/o9Nt2UQL4nFPDcaEomvPmwjJsbjkKx1SKhl2h3TgwazNBLdcNr2m0UiGiFA==", + "version": "0.9.0-alpha.1", + "resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.9.0-alpha.1.tgz", + "integrity": "sha512-Clxxc0PwpISoYYBibA+1L2qFJ7gvFVhI2Hos87S06K+Q0cXdOhZQJNKWuaQGPAeHjZEuUB/YoWOfwjuF2wirqA==", "dev": true, "requires": { - "comment-parser": "^1.1.5", + "comment-parser": "1.1.6-beta.0", "esquery": "^1.4.0", "jsdoc-type-pratt-parser": "1.0.4" } @@ -1028,6 +1028,23 @@ } } }, + "@humanwhocodes/config-array": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.5.0.tgz", + "integrity": "sha512-FagtKFz74XrTl7y6HCzQpwDfXP0yhxe9lHLD1UZxjvZIcbyRz8zTFF/yYNfSfzU414eDwZ1SrO0Qvtyf+wFMQg==", + "dev": true, + "requires": { + "@humanwhocodes/object-schema": "^1.2.0", + "debug": "^4.1.1", + "minimatch": "^3.0.4" + } + }, + "@humanwhocodes/object-schema": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.0.tgz", + "integrity": "sha512-wdppn25U8z/2yiaT6YGquE6X8sSv7hNMWSXYSSU1jGv/yd6XqjXgTDJ8KP4NgjTXfJ3GbRjeeb8RTV7a/VpM+w==", + "dev": true + }, "@iarna/toml": { "version": "2.2.5", "resolved": "https://registry.npmjs.org/@iarna/toml/-/toml-2.2.5.tgz", @@ -1675,21 +1692,21 @@ } }, "@tsconfig/node10": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.7.tgz", - "integrity": "sha512-aBvUmXLQbayM4w3A8TrjwrXs4DZ8iduJnuJLLRGdkWlyakCf1q6uHZJBzXoRA/huAEknG5tcUyQxN3A+In5euQ==", + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.8.tgz", + "integrity": "sha512-6XFfSQmMgq0CFLY1MslA/CPUfhIL919M1rMsa5lP2P097N2Wd1sSX0tx1u4olM16fLNhtHZpRhedZJphNJqmZg==", "dev": true }, "@tsconfig/node12": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.7.tgz", - "integrity": "sha512-dgasobK/Y0wVMswcipr3k0HpevxFJLijN03A8mYfEPvWvOs14v0ZlYTR4kIgMx8g4+fTyTFv8/jLCIfRqLDJ4A==", + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.9.tgz", + "integrity": "sha512-/yBMcem+fbvhSREH+s14YJi18sp7J9jpuhYByADT2rypfajMZZN4WQ6zBGgBKp53NKmqI36wFYDb3yaMPurITw==", "dev": true }, "@tsconfig/node14": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.0.tgz", - "integrity": "sha512-RKkL8eTdPv6t5EHgFKIVQgsDapugbuOptNd9OOunN/HAkzmmTnZELx1kNCK0rSdUYGmiFMM3rRQMAWiyp023LQ==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.1.tgz", + "integrity": "sha512-509r2+yARFfHHE7T6Puu2jjkoycftovhXRqW328PDXTVGKihlb1P8Z9mMZH04ebyajfRY7dedfGynlrFHJUQCg==", "dev": true }, "@tsconfig/node16": { @@ -1766,9 +1783,9 @@ } }, "@types/json-schema": { - "version": "7.0.7", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.7.tgz", - "integrity": "sha512-cxWFQVseBm6O9Gbw1IWb8r6OS4OhSt3hPZLkFApLjM8TEXROBuQGLAH2i2gZpcXdLBIrpXuTDhH7Vbm1iXmNGA==", + "version": "7.0.8", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.8.tgz", + "integrity": "sha512-YSBPTLTVm2e2OoQIDYx8HaeWJ5tTToLH67kXR7zYNGupXMEHa2++G8k+DczX2cFVgalypqtyZIcU19AFcmOpmg==", "dev": true }, "@types/json5": { @@ -1792,25 +1809,34 @@ "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==", "dev": true }, + "@types/minipass": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@types/minipass/-/minipass-2.2.0.tgz", + "integrity": "sha512-wuzZksN4w4kyfoOv/dlpov4NOunwutLA/q7uc00xU02ZyUY+aoM5PWIXEKBMnm0NHd4a+N71BMjq+x7+2Af1fg==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, "@types/mocha": { - "version": "8.2.2", - "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-8.2.2.tgz", - "integrity": "sha512-Lwh0lzzqT5Pqh6z61P3c3P5nm6fzQK/MMHl9UKeneAeInVflBSz1O2EkX6gM6xfJd7FBXBY5purtLx7fUiZ7Hw==", + "version": "8.2.3", + "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-8.2.3.tgz", + "integrity": "sha512-ekGvFhFgrc2zYQoX4JeZPmVzZxw6Dtllga7iGHzfbYIYkAMUx/sAFP2GdFpLff+vdHXu5fl7WX9AT+TtqYcsyw==", "dev": true }, "@types/mochawesome": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/@types/mochawesome/-/mochawesome-6.2.0.tgz", - "integrity": "sha512-OiwEcIy47t99YEW479OuQe9Ljvu3y6PPPQyPChV0GO0MtraZq9FgGVIBPU1DxqlsIjxw7Edij6j49HutvQOzKQ==", + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/@types/mochawesome/-/mochawesome-6.2.1.tgz", + "integrity": "sha512-AhQdBkT/CBdx3sI9ATeljqa5uJ3dGNKEJnsgzw9IkPeg9d9Lzxsz1eKFnenxq1qQojIW0XkIsCgdheRRXP2SQA==", "dev": true, "requires": { "@types/mocha": "*" } }, "@types/node": { - "version": "14.17.4", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.17.4.tgz", - "integrity": "sha512-8kQ3+wKGRNN0ghtEn7EGps/B8CzuBz1nXZEIGGLP2GnwbqYn4dbTs7k+VKLTq1HvZLRCIDtN3Snx1Ege8B7L5A==", + "version": "14.17.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.17.5.tgz", + "integrity": "sha512-bjqH2cX/O33jXT/UmReo2pM7DIJREPMnarixbQ57DOOzzFaI6D2+IcwaJQaJpv0M1E9TIhPCYVxrkcityLjlqA==", "dev": true }, "@types/offscreencanvas": { @@ -1846,10 +1872,20 @@ "integrity": "sha512-RJJrrySY7A8havqpGObOB4W92QXKJo63/jFLLgpvOtsGUqbQZ9Sbgl35KMm1DjC6j7AvmmU2bIno+3IyEaemaw==", "dev": true }, + "@types/tar": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/@types/tar/-/tar-4.0.5.tgz", + "integrity": "sha512-cgwPhNEabHaZcYIy5xeMtux2EmYBitfqEceBUi2t5+ETy4dW6kswt6WX4+HqLeiiKOo42EXbGiDmVJ2x+vi37Q==", + "dev": true, + "requires": { + "@types/minipass": "*", + "@types/node": "*" + } + }, "@types/uuid": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-8.3.0.tgz", - "integrity": "sha512-eQ9qFW/fhfGJF8WKHGEHZEyVWfZxrT+6CLIJGBcZPfxUh/+BnEj+UCGYMlr9qZuX/2AltsvwrGqp0LhEW8D0zQ==", + "version": "8.3.1", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-8.3.1.tgz", + "integrity": "sha512-Y2mHTRAbqfFkpjldbkHGY8JIzRN6XqYRliG8/24FcHm2D2PwW24fl5xMRTVGdrb7iMrwCaIEbLWerGIkXuFWVg==", "dev": true }, "@types/webgl-ext": { @@ -1865,9 +1901,9 @@ "dev": true }, "@types/ws": { - "version": "7.4.5", - "resolved": "https://registry.npmjs.org/@types/ws/-/ws-7.4.5.tgz", - "integrity": "sha512-8mbDgtc8xpxDDem5Gwj76stBDJX35KQ3YBoayxlqUQcL5BZUthiqP/VQ4PQnLHqM4PmlbyO74t98eJpURO+gPA==", + "version": "7.4.6", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-7.4.6.tgz", + "integrity": "sha512-ijZ1vzRawI7QoWnTNL8KpHixd2b2XVb9I9HAqI3triPsh1EC0xH0Eg6w2O3TKbDCgiNNlJqfrof6j4T2I+l9vw==", "dev": true, "requires": { "@types/node": "*" @@ -1889,13 +1925,13 @@ "dev": true }, "@typescript-eslint/eslint-plugin": { - "version": "4.28.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.28.1.tgz", - "integrity": "sha512-9yfcNpDaNGQ6/LQOX/KhUFTR1sCKH+PBr234k6hI9XJ0VP5UqGxap0AnNwBnWFk1MNyWBylJH9ZkzBXC+5akZQ==", + "version": "4.28.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.28.2.tgz", + "integrity": "sha512-PGqpLLzHSxq956rzNGasO3GsAPf2lY9lDUBXhS++SKonglUmJypaUtcKzRtUte8CV7nruwnDxtLUKpVxs0wQBw==", "dev": true, "requires": { - "@typescript-eslint/experimental-utils": "4.28.1", - "@typescript-eslint/scope-manager": "4.28.1", + "@typescript-eslint/experimental-utils": "4.28.2", + "@typescript-eslint/scope-manager": "4.28.2", "debug": "^4.3.1", "functional-red-black-tree": "^1.0.1", "regexpp": "^3.1.0", @@ -1904,9 +1940,9 @@ }, "dependencies": { "debug": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", - "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", + "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", "dev": true, "requires": { "ms": "2.1.2" @@ -1945,15 +1981,15 @@ } }, "@typescript-eslint/experimental-utils": { - "version": "4.28.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.28.1.tgz", - "integrity": "sha512-n8/ggadrZ+uyrfrSEchx3jgODdmcx7MzVM2sI3cTpI/YlfSm0+9HEUaWw3aQn2urL2KYlWYMDgn45iLfjDYB+Q==", + "version": "4.28.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.28.2.tgz", + "integrity": "sha512-MwHPsL6qo98RC55IoWWP8/opTykjTp4JzfPu1VfO2Z0MshNP0UZ1GEV5rYSSnZSUI8VD7iHvtIPVGW5Nfh7klQ==", "dev": true, "requires": { "@types/json-schema": "^7.0.7", - "@typescript-eslint/scope-manager": "4.28.1", - "@typescript-eslint/types": "4.28.1", - "@typescript-eslint/typescript-estree": "4.28.1", + "@typescript-eslint/scope-manager": "4.28.2", + "@typescript-eslint/types": "4.28.2", + "@typescript-eslint/typescript-estree": "4.28.2", "eslint-scope": "^5.1.1", "eslint-utils": "^3.0.0" }, @@ -1970,21 +2006,21 @@ } }, "@typescript-eslint/parser": { - "version": "4.28.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.28.1.tgz", - "integrity": "sha512-UjrMsgnhQIIK82hXGaD+MCN8IfORS1CbMdu7VlZbYa8LCZtbZjJA26De4IPQB7XYZbL8gJ99KWNj0l6WD0guJg==", + "version": "4.28.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.28.2.tgz", + "integrity": "sha512-Q0gSCN51eikAgFGY+gnd5p9bhhCUAl0ERMiDKrTzpSoMYRubdB8MJrTTR/BBii8z+iFwz8oihxd0RAdP4l8w8w==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "4.28.1", - "@typescript-eslint/types": "4.28.1", - "@typescript-eslint/typescript-estree": "4.28.1", + "@typescript-eslint/scope-manager": "4.28.2", + "@typescript-eslint/types": "4.28.2", + "@typescript-eslint/typescript-estree": "4.28.2", "debug": "^4.3.1" }, "dependencies": { "debug": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", - "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", + "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", "dev": true, "requires": { "ms": "2.1.2" @@ -1999,29 +2035,29 @@ } }, "@typescript-eslint/scope-manager": { - "version": "4.28.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.28.1.tgz", - "integrity": "sha512-o95bvGKfss6705x7jFGDyS7trAORTy57lwJ+VsYwil/lOUxKQ9tA7Suuq+ciMhJc/1qPwB3XE2DKh9wubW8YYA==", + "version": "4.28.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.28.2.tgz", + "integrity": "sha512-MqbypNjIkJFEFuOwPWNDjq0nqXAKZvDNNs9yNseoGBB1wYfz1G0WHC2AVOy4XD7di3KCcW3+nhZyN6zruqmp2A==", "dev": true, "requires": { - "@typescript-eslint/types": "4.28.1", - "@typescript-eslint/visitor-keys": "4.28.1" + "@typescript-eslint/types": "4.28.2", + "@typescript-eslint/visitor-keys": "4.28.2" } }, "@typescript-eslint/types": { - "version": "4.28.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.28.1.tgz", - "integrity": "sha512-4z+knEihcyX7blAGi7O3Fm3O6YRCP+r56NJFMNGsmtdw+NCdpG5SgNz427LS9nQkRVTswZLhz484hakQwB8RRg==", + "version": "4.28.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.28.2.tgz", + "integrity": "sha512-Gr15fuQVd93uD9zzxbApz3wf7ua3yk4ZujABZlZhaxxKY8ojo448u7XTm/+ETpy0V0dlMtj6t4VdDvdc0JmUhA==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "4.28.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.28.1.tgz", - "integrity": "sha512-GhKxmC4sHXxHGJv8e8egAZeTZ6HI4mLU6S7FUzvFOtsk7ZIDN1ksA9r9DyOgNqowA9yAtZXV0Uiap61bIO81FQ==", + "version": "4.28.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.28.2.tgz", + "integrity": "sha512-86lLstLvK6QjNZjMoYUBMMsULFw0hPHJlk1fzhAVoNjDBuPVxiwvGuPQq3fsBMCxuDJwmX87tM/AXoadhHRljg==", "dev": true, "requires": { - "@typescript-eslint/types": "4.28.1", - "@typescript-eslint/visitor-keys": "4.28.1", + "@typescript-eslint/types": "4.28.2", + "@typescript-eslint/visitor-keys": "4.28.2", "debug": "^4.3.1", "globby": "^11.0.3", "is-glob": "^4.0.1", @@ -2036,9 +2072,9 @@ "dev": true }, "debug": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", - "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", + "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", "dev": true, "requires": { "ms": "2.1.2" @@ -2091,12 +2127,12 @@ } }, "@typescript-eslint/visitor-keys": { - "version": "4.28.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.28.1.tgz", - "integrity": "sha512-K4HMrdFqr9PFquPu178SaSb92CaWe2yErXyPumc8cYWxFmhgJsNY9eSePmO05j0JhBvf2Cdhptd6E6Yv9HVHcg==", + "version": "4.28.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.28.2.tgz", + "integrity": "sha512-aT2B4PLyyRDUVUafXzpZFoc0C9t0za4BJAKP5sgWIhG+jHECQZUEjuQSCIwZdiJJ4w4cgu5r3Kh20SOdtEBl0w==", "dev": true, "requires": { - "@typescript-eslint/types": "4.28.1", + "@typescript-eslint/types": "4.28.2", "eslint-visitor-keys": "^2.0.0" } }, @@ -2626,6 +2662,11 @@ "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", "dev": true }, + "basic-ftp": { + "version": "4.6.6", + "resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-4.6.6.tgz", + "integrity": "sha512-5nTclY5mVxjeFoq9cBTzgQvcM1UfeGTd4hCCvb8AgC88wHMDQCD4UX5hZo2jaiSh96Nf+gFy1joNI9iH639bvQ==" + }, "bcrypt-pbkdf": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", @@ -2668,6 +2709,72 @@ "request-promise": "^4.2.4", "tar": "^4.4.10", "unzip-stream": "^0.3.0" + }, + "dependencies": { + "chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", + "dev": true + }, + "fs-minipass": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.7.tgz", + "integrity": "sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==", + "dev": true, + "requires": { + "minipass": "^2.6.0" + } + }, + "minipass": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz", + "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==", + "dev": true, + "requires": { + "safe-buffer": "^5.1.2", + "yallist": "^3.0.0" + } + }, + "minizlib": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.3.3.tgz", + "integrity": "sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==", + "dev": true, + "requires": { + "minipass": "^2.9.0" + } + }, + "mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "dev": true, + "requires": { + "minimist": "^1.2.5" + } + }, + "tar": { + "version": "4.4.13", + "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.13.tgz", + "integrity": "sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA==", + "dev": true, + "requires": { + "chownr": "^1.1.1", + "fs-minipass": "^1.2.5", + "minipass": "^2.8.6", + "minizlib": "^1.2.1", + "mkdirp": "^0.5.0", + "safe-buffer": "^5.1.2", + "yallist": "^3.0.3" + } + }, + "yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + } } }, "bit-twiddle": { @@ -3294,26 +3401,25 @@ "dev": true }, "chokidar": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.1.tgz", - "integrity": "sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw==", + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.2.tgz", + "integrity": "sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ==", "dev": true, "requires": { - "anymatch": "~3.1.1", + "anymatch": "~3.1.2", "braces": "~3.0.2", - "fsevents": "~2.3.1", - "glob-parent": "~5.1.0", + "fsevents": "~2.3.2", + "glob-parent": "~5.1.2", "is-binary-path": "~2.1.0", "is-glob": "~4.0.1", "normalize-path": "~3.0.0", - "readdirp": "~3.5.0" + "readdirp": "~3.6.0" } }, "chownr": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", - "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", - "dev": true + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==" }, "ci-info": { "version": "1.6.0", @@ -4091,9 +4197,9 @@ "dev": true }, "comment-parser": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-1.1.5.tgz", - "integrity": "sha512-RePCE4leIhBlmrqiYTvaqEeGYg7qpSl4etaIabKtdOQVi+mSTIBBklGUwIr79GXYnl3LpMwmDw4KeR2stNc6FA==", + "version": "1.1.6-beta.0", + "resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-1.1.6-beta.0.tgz", + "integrity": "sha512-q3cA8TSMyqW7wcPSYWzbO/rMahnXgzs4SLG/UIWXdEsnXTFPZkEkWAdNgPiHig2OzxgpPLOh4WwsmClDxndwHw==", "dev": true }, "commist": { @@ -5061,6 +5167,15 @@ "safer-buffer": "^2.1.0" } }, + "ejs": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.6.tgz", + "integrity": "sha512-9lt9Zse4hPucPkoP7FHDF0LQAlGyF9JVpnClFLFH3aSSbxmyoqINRpp/9wePWJTUl4KOQwRL72Iw3InHPDkoGw==", + "dev": true, + "requires": { + "jake": "^10.6.1" + } + }, "electron-to-chromium": { "version": "1.3.742", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.742.tgz", @@ -5358,13 +5473,14 @@ } }, "eslint": { - "version": "7.29.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.29.0.tgz", - "integrity": "sha512-82G/JToB9qIy/ArBzIWG9xvvwL3R86AlCjtGw+A29OMZDqhTybz/MByORSukGxeI+YPCR4coYyITKk8BFH9nDA==", + "version": "7.30.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.30.0.tgz", + "integrity": "sha512-VLqz80i3as3NdloY44BQSJpFw534L9Oh+6zJOUaViV4JPd+DaHwutqP7tcpkW3YiXbK6s05RZl7yl7cQn+lijg==", "dev": true, "requires": { "@babel/code-frame": "7.12.11", "@eslint/eslintrc": "^0.4.2", + "@humanwhocodes/config-array": "^0.5.0", "ajv": "^6.10.0", "chalk": "^4.0.0", "cross-spawn": "^7.0.2", @@ -5903,14 +6019,14 @@ } }, "eslint-plugin-jsdoc": { - "version": "35.4.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-35.4.1.tgz", - "integrity": "sha512-lnpu2Bj+ta2eAqwCWnb6f3Xjc78TWKo/oMCpDH5NfpPhYnePNtGZJzoAMgU5uo9BQqmXJ8pql8aiodOhg82ofw==", + "version": "35.4.3", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-35.4.3.tgz", + "integrity": "sha512-hBEn+VNjVX0IKoZ2OdZs0Z1fU8CqZkBSzLqD8ZpwZEamrdi2TUgKvujvETe8gXYQ/67hpRtbR5iPFTgmWpRevw==", "dev": true, "requires": { - "@es-joy/jsdoccomment": "^0.8.0", - "comment-parser": "1.1.5", - "debug": "^4.3.1", + "@es-joy/jsdoccomment": "^0.9.0-alpha.1", + "comment-parser": "1.1.6-beta.0", + "debug": "^4.3.2", "esquery": "^1.4.0", "jsdoc-type-pratt-parser": "^1.0.4", "lodash": "^4.17.21", @@ -5920,9 +6036,9 @@ }, "dependencies": { "debug": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", - "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", + "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", "dev": true, "requires": { "ms": "2.1.2" @@ -6347,6 +6463,15 @@ "moment": "^2.11.2" } }, + "filelist": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.2.tgz", + "integrity": "sha512-z7O0IS8Plc39rTCq6i6iHxk43duYOn8uFJiWSewIq0Bww1RNybVHSCjahmcC87ZqAm4OTvFzlzeGu3XAzG1ctQ==", + "dev": true, + "requires": { + "minimatch": "^3.0.4" + } + }, "fill-range": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", @@ -6480,9 +6605,9 @@ "dev": true }, "flatted": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.1.1.tgz", - "integrity": "sha512-zAoAQiudy+r5SvnSw3KJy5os/oRJYHzrzja/tBDqrZtNhUw8bt6y8OBzMWcjWr+8liV8Eb6yOhw8WZ7VFZ5ZzA==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.0.tgz", + "integrity": "sha512-XprP7lDrVT+kE2c2YlfiV+IfS9zxukiIOvNamPNsImNhXadSsQEbosItdL9bUQlCZXR13SvPk20BjWSWLA7m4A==", "dev": true }, "fn.name": { @@ -6611,12 +6736,11 @@ } }, "fs-minipass": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.7.tgz", - "integrity": "sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==", - "dev": true, + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", "requires": { - "minipass": "^2.6.0" + "minipass": "^3.0.0" } }, "fs.realpath": { @@ -8053,6 +8177,26 @@ "istanbul-lib-report": "^3.0.0" } }, + "jake": { + "version": "10.8.2", + "resolved": "https://registry.npmjs.org/jake/-/jake-10.8.2.tgz", + "integrity": "sha512-eLpKyrfG3mzvGE2Du8VoPbeSkRry093+tyNjdYaBbJS9v17knImYGNXQCUV0gLxQtF82m3E8iRb/wdSQZLoq7A==", + "dev": true, + "requires": { + "async": "0.9.x", + "chalk": "^2.4.2", + "filelist": "^1.0.1", + "minimatch": "^3.0.4" + }, + "dependencies": { + "async": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz", + "integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0=", + "dev": true + } + } + }, "jest-diff": { "version": "27.0.6", "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-27.0.6.tgz", @@ -8867,6 +9011,12 @@ "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=", "dev": true }, + "markdown": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/markdown/-/markdown-0.3.1.tgz", + "integrity": "sha1-XZXBqGDRSFNSl4MqFX5L5Z6YgNQ=", + "dev": true + }, "mbt": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/mbt/-/mbt-1.2.1.tgz", @@ -8960,6 +9110,12 @@ } } }, + "mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "dev": true + }, "mime-db": { "version": "1.44.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz", @@ -9054,37 +9210,40 @@ "dev": true }, "minipass": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz", - "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==", - "dev": true, + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.3.tgz", + "integrity": "sha512-Mgd2GdMVzY+x3IJ+oHnVM+KG3lA5c8tnabyJKmHSaG2kAGpudxuOf8ToDkhumF7UzME7DecbQE9uOZhNm7PuJg==", "requires": { - "safe-buffer": "^5.1.2", - "yallist": "^3.0.0" + "yallist": "^4.0.0" }, "dependencies": { "yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "dev": true + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" } } }, "minizlib": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.3.3.tgz", - "integrity": "sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==", - "dev": true, + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", "requires": { - "minipass": "^2.9.0" + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "dependencies": { + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + } } }, "mkdirp": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==" }, "mkdirp-classic": { "version": "0.5.3", @@ -9174,15 +9333,15 @@ "dev": true }, "mocha": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-9.0.1.tgz", - "integrity": "sha512-9zwsavlRO+5csZu6iRtl3GHImAbhERoDsZwdRkdJ/bE+eVplmoxNKE901ZJ9LdSchYBjSCPbjKc5XvcAri2ylw==", + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-9.0.2.tgz", + "integrity": "sha512-FpspiWU+UT9Sixx/wKimvnpkeW0mh6ROAKkIaPokj3xZgxeRhcna/k5X57jJghEr8X+Cgu/Vegf8zCX5ugSuTA==", "dev": true, "requires": { "@ungap/promise-all-settled": "1.1.2", "ansi-colors": "4.1.1", "browser-stdout": "1.3.1", - "chokidar": "3.5.1", + "chokidar": "3.5.2", "debug": "4.3.1", "diff": "5.0.0", "escape-string-regexp": "4.0.0", @@ -9195,12 +9354,12 @@ "minimatch": "3.0.4", "ms": "2.1.3", "nanoid": "3.1.23", - "serialize-javascript": "5.0.1", + "serialize-javascript": "6.0.0", "strip-json-comments": "3.1.1", "supports-color": "8.1.1", "which": "2.0.2", "wide-align": "1.1.3", - "workerpool": "6.1.4", + "workerpool": "6.1.5", "yargs": "16.2.0", "yargs-parser": "20.2.4", "yargs-unparser": "2.0.0" @@ -9367,9 +9526,9 @@ "dev": true }, "serialize-javascript": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-5.0.1.tgz", - "integrity": "sha512-SaaNal9imEO737H2c05Og0/8LUXG7EnsZyMa8MzkmuHoELfT6txuj0cMqRj6zfPKnmQ1yasR4PCJc8x+M4JSPA==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", + "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", "dev": true, "requires": { "randombytes": "^2.1.0" @@ -9659,9 +9818,9 @@ "integrity": "sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ==" }, "mongodb": { - "version": "3.6.9", - "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.6.9.tgz", - "integrity": "sha512-1nSCKgSunzn/CXwgOWgbPHUWOO5OfERcuOWISmqd610jn0s8BU9K4879iJVabqgpPPbA6hO7rG48eq+fGED3Mg==", + "version": "3.6.10", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.6.10.tgz", + "integrity": "sha512-fvIBQBF7KwCJnDZUnFFy4WqEFP8ibdXeFANnylW19+vOwdjOAvqIzPdsNCEMT6VKTHnYu4K64AWRih0mkFms6Q==", "requires": { "bl": "^2.2.1", "bson": "^1.1.4", @@ -10690,6 +10849,12 @@ "word-wrap": "~1.2.3" } }, + "options": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/options/-/options-0.0.6.tgz", + "integrity": "sha1-7CLTEoBrtT5zF3Pnza788cZDEo8=", + "dev": true + }, "ora": { "version": "5.4.0", "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.0.tgz", @@ -11761,9 +11926,9 @@ } }, "readdirp": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz", - "integrity": "sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==", + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", "dev": true, "requires": { "picomatch": "^2.2.1" @@ -13258,10 +13423,36 @@ "inherits": "^2.0.1" } }, + "robohydra": { + "version": "0.6.9", + "resolved": "https://registry.npmjs.org/robohydra/-/robohydra-0.6.9.tgz", + "integrity": "sha512-kSLoeDBfnGnIkln+nmyfWPHsQSOPz9K/Lb0CDWvCj70Af6K4R5qM54q6DW/IeUUxJY7pI6zi5rHNQZCZnWgfgw==", + "dev": true, + "requires": { + "commander": "^2.19.0", + "ejs": "3.1.6", + "markdown": "^0.3.1", + "mime": "^1.0.0", + "qs": "^6.3.1", + "ws": "1.1.5" + }, + "dependencies": { + "ws": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/ws/-/ws-1.1.5.tgz", + "integrity": "sha512-o3KqipXNUdS7wpQzBHSe180lBGO60SoK0yVo3CYJgb2MkobuWuBX6dhkYP5ORCLd55y+SaflMOV5fqAB53ux4w==", + "dev": true, + "requires": { + "options": ">=0.0.5", + "ultron": "1.0.x" + } + } + } + }, "rollup": { - "version": "2.52.3", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.52.3.tgz", - "integrity": "sha512-QF3Sju8Kl2z0osI4unyOLyUudyhOMK6G0AeqJWgfiyigqLAlnNrfBcDWDx+f1cqn+JU2iIYVkDrgQ6/KtwEfrg==", + "version": "2.53.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.53.0.tgz", + "integrity": "sha512-spgrY78Toh+m0+zaOoeaayJKuzFuWy6o1PdFIBMVwRcuxT0xCOX9A5rChyKe+2ruL4lePKWUMImS4mMW1QAkmQ==", "dev": true, "requires": { "fsevents": "~2.3.2" @@ -14343,34 +14534,22 @@ "dev": true }, "tar": { - "version": "4.4.13", - "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.13.tgz", - "integrity": "sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA==", - "dev": true, + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.0.tgz", + "integrity": "sha512-DUCttfhsnLCjwoDoFcI+B2iJgYa93vBnDUATYEeRx6sntCTdN01VnqsIuTlALXla/LWooNg0yEGeB+Y8WdFxGA==", "requires": { - "chownr": "^1.1.1", - "fs-minipass": "^1.2.5", - "minipass": "^2.8.6", - "minizlib": "^1.2.1", - "mkdirp": "^0.5.0", - "safe-buffer": "^5.1.2", - "yallist": "^3.0.3" + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^3.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" }, "dependencies": { - "mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", - "dev": true, - "requires": { - "minimist": "^1.2.5" - } - }, "yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "dev": true + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" } } }, @@ -14595,9 +14774,9 @@ "integrity": "sha512-XrHUvV5HpdLmIj4uVMxHggLbFSZYIn7HEWsqePZcI50pco+MPqJ50wMGY794X7AOOhxOBAjbkqfAbEe/QMp2Lw==" }, "ts-node": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.0.0.tgz", - "integrity": "sha512-ROWeOIUvfFbPZkoDis0L/55Fk+6gFQNZwwKPLinacRl6tsxstTF1DbAcLKkovwnpKMVvOMHP1TIbnwXwtLg1gg==", + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.1.0.tgz", + "integrity": "sha512-6szn3+J9WyG2hE+5W8e0ruZrzyk1uFLYye6IGMBadnOzDh8aP7t8CbFpsfCiEx2+wMixAhjFt7lOZC4+l+WbEA==", "dev": true, "requires": { "@tsconfig/node10": "^1.0.7", @@ -14747,9 +14926,9 @@ } }, "typescript": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.3.4.tgz", - "integrity": "sha512-uauPG7XZn9F/mo+7MrsRjyvbxFpzemRjKEZXS4AK83oP2KKOJPvb+9cO/gmnv8arWZvhnjVOXz7B49m1l0e9Ew==", + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.3.5.tgz", + "integrity": "sha512-DqQgihaQ9cUrskJo9kIyW/+g0Vxsk8cDtZ52a3NGh0YNTfpUSArXSohyUGnvbPazEPLu398C0UxmKSOrPumUzA==", "dev": true }, "uglify-js": { @@ -14759,6 +14938,12 @@ "dev": true, "optional": true }, + "ultron": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.0.2.tgz", + "integrity": "sha1-rOEWq1V80Zc4ak6I9GhTeMiy5Po=", + "dev": true + }, "umd": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/umd/-/umd-3.0.3.tgz", @@ -15227,9 +15412,9 @@ "dev": true }, "workerpool": { - "version": "6.1.4", - "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.1.4.tgz", - "integrity": "sha512-jGWPzsUqzkow8HoAvqaPWTUPCrlPJaJ5tY8Iz7n1uCz3tTp6s3CDG0FF1NsX42WNlkRSW6Mr+CDZGnNoSsKa7g==", + "version": "6.1.5", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.1.5.tgz", + "integrity": "sha512-XdKkCK0Zqc6w3iTxLckiuJ81tiD/o5rBE/m+nXpRCB+/Sq4DqkfXZ/x0jW02DG1tGsfUGXbTJyZDP+eu67haSw==", "dev": true }, "wrap-ansi": { @@ -15289,9 +15474,9 @@ } }, "ws": { - "version": "7.5.1", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.1.tgz", - "integrity": "sha512-2c6faOUH/nhoQN6abwMloF7Iyl0ZS2E9HGtsiLrWn0zOOMWlhtDmdf/uihDt6jnuCxgtwGBNy6Onsoy2s2O2Ow==" + "version": "7.5.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.3.tgz", + "integrity": "sha512-kQ/dHIzuLrS6Je9+uv81ueZomEwH0qVYstcAQ4/Z93K8zeko9gtAbttJWzoC5ukqXY1PpoouV3+VSOqEAFt5wg==" }, "xdg-basedir": { "version": "3.0.0", diff --git a/package.json b/package.json index fa61637c..9cce1eb1 100644 --- a/package.json +++ b/package.json @@ -43,13 +43,13 @@ "lint": "cross-env TIMING=1 eslint --ext .js,.ts src", "lint:fix": "cross-env TIMING=1 eslint --fix --ext .js,.ts src", "import-sort": "npx import-sort-cli --write 'src/**/*.ts{,x}'", - "tsc": "tsc", "pretest": "npm run build:dev", "test": "cross-env TS_NODE_COMPILER_OPTIONS='{\"module\": \"commonjs\"}' nyc mocha test/**/*Test.ts", "coverage": "nyc report --reporter=lcov", "coverage:html": "nyc report --reporter=html", "clinic:clean": "clinic clean", "npm-check": "npm-check", + "robohydra": "robohydra test/robohydra/config.json", "git:sinit": "git submodule update --init --recursive --force", "git:sdiff": "git diff && git submodule foreach 'git diff'", "git:supdate": "git submodule update --remote --recursive --merge", @@ -57,14 +57,16 @@ "release": "release-it" }, "dependencies": { - "mongodb": "^3.6.9", + "basic-ftp": "^4.6.6", + "mongodb": "^3.6.10", "poolifier": "^2.0.2", "source-map-support": "^0.5.19", + "tar": "^6.1.0", "tslib": "^2.3.0", "uuid": "^8.3.2", "winston": "^3.3.3", "winston-daily-rotate-file": "^4.5.5", - "ws": "^7.5.1" + "ws": "^7.5.3" }, "optionalDependencies": { "bufferutil": "^4.0.3", @@ -73,35 +75,37 @@ "devDependencies": { "@istanbuljs/nyc-config-typescript": "^1.0.1", "@rollup/plugin-json": "^4.1.0", - "@types/mocha": "^8.2.2", - "@types/mochawesome": "^6.2.0", - "@types/node": "^14.17.4", - "@types/uuid": "^8.3.0", - "@types/ws": "^7.4.5", - "@typescript-eslint/eslint-plugin": "^4.28.1", - "@typescript-eslint/parser": "^4.28.1", + "@types/mocha": "^8.2.3", + "@types/mochawesome": "^6.2.1", + "@types/node": "^14.17.5", + "@types/tar": "^4.0.5", + "@types/uuid": "^8.3.1", + "@types/ws": "^7.4.6", + "@typescript-eslint/eslint-plugin": "^4.28.2", + "@typescript-eslint/parser": "^4.28.2", "auto-changelog": "^2.3.0", "clinic": "^9.0.0", "cross-env": "^7.0.3", - "eslint": "^7.29.0", + "eslint": "^7.30.0", "eslint-plugin-import": "^2.23.4", - "eslint-plugin-jsdoc": "^35.4.1", + "eslint-plugin-jsdoc": "^35.4.3", "eslint-plugin-node": "^11.1.0", "expect": "^27.0.6", "mbt": "^1.2.1", - "mocha": "^9.0.1", + "mocha": "^9.0.2", "mochawesome": "^6.2.2", "npm-check": "^5.9.2", "nyc": "^15.1.0", "release-it": "^14.10.0", - "rollup": "^2.52.3", + "robohydra": "^0.6.9", + "rollup": "^2.53.0", "rollup-plugin-analyzer": "^4.0.0", "rollup-plugin-copy": "^3.4.0", "rollup-plugin-delete": "^2.0.0", "rollup-plugin-istanbul": "^3.0.0", "rollup-plugin-terser": "^7.0.2", "rollup-plugin-typescript2": "^0.30.0", - "ts-node": "^10.0.0", - "typescript": "^4.3.4" + "ts-node": "^10.1.0", + "typescript": "^4.3.5" } } diff --git a/rollup.config.js b/rollup.config.js index 46683b3b..00f0d3cd 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -20,7 +20,7 @@ export default { preserveModulesRoot: 'src', ...!isDevelopmentBuild && { plugins: [terser({ numWorkers: 2 })] } }, - external: ['crypto', 'perf_hooks', 'fs', 'path', 'poolifier', 'uuid', 'ws', 'winston-daily-rotate-file', 'winston/lib/winston/transports', 'winston', 'worker_threads'], + external: ['basic-ftp', 'crypto', 'perf_hooks', 'fs', 'path', 'poolifier', 'tar', 'url', 'uuid', 'ws', 'winston-daily-rotate-file', 'winston/lib/winston/transports', 'winston', 'worker_threads'], plugins: [ json(), typescript({ diff --git a/src/assets/configs-aws b/src/assets/configs-aws index 6281db13..2dc38e36 160000 --- a/src/assets/configs-aws +++ b/src/assets/configs-aws @@ -1 +1 @@ -Subproject commit 6281db138c29805f3695bf751b40917a306721e7 +Subproject commit 2dc38e36a569dc1266e48d85e7e87ed0d3f18528 diff --git a/src/charging-station/ChargingStation.ts b/src/charging-station/ChargingStation.ts index 71de426c..8e307a9e 100644 --- a/src/charging-station/ChargingStation.ts +++ b/src/charging-station/ChargingStation.ts @@ -228,7 +228,10 @@ export default class ChargingStation { } const sampledValueTemplates: SampledValueTemplate[] = this.getConnector(connectorId).MeterValues; for (let index = 0; !Utils.isEmptyArray(sampledValueTemplates) && index < sampledValueTemplates.length; index++) { - if (phase && sampledValueTemplates[index]?.phase === phase && sampledValueTemplates[index]?.measurand === measurand + if (!Constants.SUPPORTED_MEASURANDS.includes(sampledValueTemplates[index]?.measurand)) { + logger.warn(`${this.logPrefix()} Unsupported MeterValues measurand ${measurand} ${phase ? `on phase ${phase} ` : ''}in template on connectorId ${connectorId}`); + continue; + } else if (phase && sampledValueTemplates[index]?.phase === phase && sampledValueTemplates[index]?.measurand === measurand && this.getConfigurationKey(StandardParametersKey.MeterValuesSampledData).value.includes(measurand)) { return sampledValueTemplates[index]; } else if (!phase && !sampledValueTemplates[index].phase && sampledValueTemplates[index]?.measurand === measurand @@ -547,6 +550,13 @@ export default class ChargingStation { } // OCPP parameters this.initOCPPParameters(); + if (this.stationInfo.autoRegister) { + this.bootNotificationResponse = { + currentTime: new Date().toISOString(), + interval: this.getHeartbeatInterval() / 1000, + status: RegistrationStatus.ACCEPTED + }; + } this.stationInfo.powerDivider = this.getPowerDivider(); if (this.getEnableStatistics()) { this.performanceStatistics = new PerformanceStatistics(this.stationInfo.chargingStationId); @@ -643,8 +653,13 @@ export default class ChargingStation { let requestPayload: Record; let errMsg: string; try { - // Parse the message - [messageType, messageId, commandName, commandPayload, errorDetails] = JSON.parse(messageEvent.toString()) as IncomingRequest; + const request = JSON.parse(messageEvent.toString()) as IncomingRequest; + if (Utils.isIterable(request)) { + // Parse the message + [messageType, messageId, commandName, commandPayload, errorDetails] = request; + } else { + throw new Error('Incoming request is not iterable'); + } // Check the Type of message switch (messageType) { // Incoming Message @@ -692,7 +707,7 @@ export default class ChargingStation { } } catch (error) { // Log - logger.error('%s Incoming message %j processing error %j on request content type %j', this.logPrefix(), messageEvent, error, this.requests[messageId]); + logger.error('%s Incoming request message %j processing error %j on content type %j', this.logPrefix(), messageEvent, error, this.requests[messageId]); // Send error messageType !== MessageType.CALL_ERROR_MESSAGE && await this.ocppRequestService.sendError(messageId, error, commandName); } @@ -926,6 +941,8 @@ export default class ChargingStation { if (HeartBeatInterval) { return Utils.convertToInt(HeartBeatInterval.value) * 1000; } + !this.stationInfo.autoRegister && logger.warn(`${this.logPrefix()} Heartbeat interval configuration key not set, using default value: ${Constants.DEFAULT_HEARTBEAT_INTERVAL}`); + return Constants.DEFAULT_HEARTBEAT_INTERVAL; } private stopHeartbeat(): void { diff --git a/src/charging-station/ocpp/1.6/OCCP16IncomingRequestService.ts b/src/charging-station/ocpp/1.6/OCCP16IncomingRequestService.ts index e806051a..98f165a6 100644 --- a/src/charging-station/ocpp/1.6/OCCP16IncomingRequestService.ts +++ b/src/charging-station/ocpp/1.6/OCCP16IncomingRequestService.ts @@ -1,19 +1,27 @@ -import { ChangeAvailabilityRequest, ChangeConfigurationRequest, ClearChargingProfileRequest, GetConfigurationRequest, OCPP16AvailabilityType, OCPP16IncomingRequestCommand, RemoteStartTransactionRequest, RemoteStopTransactionRequest, ResetRequest, SetChargingProfileRequest, UnlockConnectorRequest } from '../../../types/ocpp/1.6/Requests'; -import { ChangeAvailabilityResponse, ChangeConfigurationResponse, ClearChargingProfileResponse, GetConfigurationResponse, SetChargingProfileResponse, UnlockConnectorResponse } from '../../../types/ocpp/1.6/Responses'; +import * as url from 'url'; + +import { ChangeAvailabilityRequest, ChangeConfigurationRequest, ClearChargingProfileRequest, GetConfigurationRequest, GetDiagnosticsRequest, OCPP16AvailabilityType, OCPP16IncomingRequestCommand, RemoteStartTransactionRequest, RemoteStopTransactionRequest, ResetRequest, SetChargingProfileRequest, UnlockConnectorRequest } from '../../../types/ocpp/1.6/Requests'; +import { ChangeAvailabilityResponse, ChangeConfigurationResponse, ClearChargingProfileResponse, GetConfigurationResponse, GetDiagnosticsResponse, SetChargingProfileResponse, UnlockConnectorResponse } from '../../../types/ocpp/1.6/Responses'; import { ChargingProfilePurposeType, OCPP16ChargingProfile } from '../../../types/ocpp/1.6/ChargingProfile'; +import { Client, FTPResponse } from 'basic-ftp'; import { OCPP16AuthorizationStatus, OCPP16StopTransactionReason } from '../../../types/ocpp/1.6/Transaction'; import Constants from '../../../utils/Constants'; import { DefaultResponse } from '../../../types/ocpp/Responses'; import { ErrorType } from '../../../types/ocpp/ErrorType'; +import { IncomingRequestCommand } from '../../../types/ocpp/Requests'; import { MessageType } from '../../../types/ocpp/MessageType'; import { OCPP16ChargePointStatus } from '../../../types/ocpp/1.6/ChargePointStatus'; +import { OCPP16DiagnosticsStatus } from '../../../types/ocpp/1.6/DiagnosticsStatus'; import { OCPP16StandardParametersKey } from '../../../types/ocpp/1.6/Configuration'; import { OCPPConfigurationKey } from '../../../types/ocpp/Configuration'; import OCPPError from '../../OcppError'; import OCPPIncomingRequestService from '../OCPPIncomingRequestService'; import Utils from '../../../utils/Utils'; +import fs from 'fs'; import logger from '../../../utils/Logger'; +import path from 'path'; +import tar from 'tar'; export default class OCPP16IncomingRequestService extends OCPPIncomingRequestService { public async handleRequest(messageId: string, commandName: OCPP16IncomingRequestCommand, commandPayload: Record): Promise { @@ -340,4 +348,53 @@ export default class OCPP16IncomingRequestService extends OCPPIncomingRequestSer logger.info(this.chargingStation.logPrefix() + ' Trying to remote stop a non existing transaction ' + transactionId.toString()); return Constants.OCPP_RESPONSE_REJECTED; } + + private async handleRequestGetDiagnostics(commandPayload: GetDiagnosticsRequest): Promise { + logger.debug(this.chargingStation.logPrefix() + ' ' + IncomingRequestCommand.GET_DIAGNOSTICS + ' request received: %j', commandPayload); + const uri = new url.URL(commandPayload.location); + if (uri.protocol.startsWith('ftp:')) { + let ftpClient: Client; + try { + const logFiles = fs.readdirSync(path.resolve(__dirname, '../../../../')).filter((file) => file.endsWith('.log')).map((file) => path.join('./', file)); + const diagnosticsArchive = this.chargingStation.stationInfo.chargingStationId + '_logs.tar.gz'; + tar.create({ gzip: true }, logFiles).pipe(fs.createWriteStream(diagnosticsArchive)); + ftpClient = new Client(); + const accessResponse = await ftpClient.access({ + host: uri.host, + ...(uri.port !== '') && { port: Utils.convertToInt(uri.port) }, + ...(uri.username !== '') && { user: uri.username }, + ...(uri.password !== '') && { password: uri.password }, + }); + let uploadResponse: FTPResponse; + if (accessResponse.code === 220) { + // eslint-disable-next-line @typescript-eslint/no-misused-promises + ftpClient.trackProgress(async (info) => { + logger.info(`${this.chargingStation.logPrefix()} ${info.bytes / 1024} bytes transferred from diagnostics archive ${info.name}`); + await this.chargingStation.ocppRequestService.sendDiagnosticsStatusNotification(OCPP16DiagnosticsStatus.Uploading); + }); + uploadResponse = await ftpClient.uploadFrom(path.join(path.resolve(__dirname, '../../../../'), diagnosticsArchive), uri.pathname + diagnosticsArchive); + if (uploadResponse.code === 226) { + await this.chargingStation.ocppRequestService.sendDiagnosticsStatusNotification(OCPP16DiagnosticsStatus.Uploaded); + if (ftpClient) { + ftpClient.close(); + } + return { fileName: diagnosticsArchive }; + } + throw Error(`Diagnostics transfer failed with error code ${accessResponse.code.toString()}${uploadResponse?.code && '|' + uploadResponse?.code.toString()}`); + } + throw Error(`Diagnostics transfer failed with error code ${accessResponse.code.toString()}${uploadResponse?.code && '|' + uploadResponse?.code.toString()}`); + } catch (error) { + await this.chargingStation.ocppRequestService.sendDiagnosticsStatusNotification(OCPP16DiagnosticsStatus.UploadFailed); + this.handleIncomingRequestError(IncomingRequestCommand.GET_DIAGNOSTICS, error); + if (ftpClient) { + ftpClient.close(); + } + return Constants.OCPP_RESPONSE_EMPTY; + } + } else { + logger.error(`${this.chargingStation.logPrefix()} Unsupported protocol ${uri.protocol} to transfer the diagnostic logs archive`); + await this.chargingStation.ocppRequestService.sendDiagnosticsStatusNotification(OCPP16DiagnosticsStatus.UploadFailed); + return Constants.OCPP_RESPONSE_EMPTY; + } + } } diff --git a/src/charging-station/ocpp/1.6/OCPP16RequestService.ts b/src/charging-station/ocpp/1.6/OCPP16RequestService.ts index 74bc1fbf..4b7186ce 100644 --- a/src/charging-station/ocpp/1.6/OCPP16RequestService.ts +++ b/src/charging-station/ocpp/1.6/OCPP16RequestService.ts @@ -1,7 +1,7 @@ import { ACElectricUtils, DCElectricUtils } from '../../../utils/ElectricUtils'; import { AuthorizeRequest, OCPP16AuthorizeResponse, OCPP16StartTransactionResponse, OCPP16StopTransactionReason, OCPP16StopTransactionResponse, StartTransactionRequest, StopTransactionRequest } from '../../../types/ocpp/1.6/Transaction'; import { CurrentType, Voltage } from '../../../types/ChargingStationTemplate'; -import { HeartbeatRequest, OCPP16BootNotificationRequest, OCPP16IncomingRequestCommand, OCPP16RequestCommand, StatusNotificationRequest } from '../../../types/ocpp/1.6/Requests'; +import { DiagnosticsStatusNotificationRequest, HeartbeatRequest, OCPP16BootNotificationRequest, OCPP16IncomingRequestCommand, OCPP16RequestCommand, StatusNotificationRequest } from '../../../types/ocpp/1.6/Requests'; import { MeterValueUnit, MeterValuesRequest, OCPP16MeterValue, OCPP16MeterValueMeasurand, OCPP16MeterValuePhase } from '../../../types/ocpp/1.6/MeterValues'; import Constants from '../../../utils/Constants'; @@ -11,6 +11,7 @@ import { MessageType } from '../../../types/ocpp/MessageType'; import { OCPP16BootNotificationResponse } from '../../../types/ocpp/1.6/Responses'; import { OCPP16ChargePointErrorCode } from '../../../types/ocpp/1.6/ChargePointErrorCode'; import { OCPP16ChargePointStatus } from '../../../types/ocpp/1.6/ChargePointStatus'; +import { OCPP16DiagnosticsStatus } from '../../../types/ocpp/1.6/DiagnosticsStatus'; import { OCPP16ServiceUtils } from './OCPP16ServiceUtils'; import OCPPError from '../../OcppError'; import OCPPRequestService from '../OCPPRequestService'; @@ -354,6 +355,13 @@ export default class OCPP16RequestService extends OCPPRequestService { await this.sendMessage(Utils.generateUUID(), payload, MessageType.CALL_MESSAGE, OCPP16RequestCommand.METER_VALUES); } + public async sendDiagnosticsStatusNotification(diagnosticsStatus: OCPP16DiagnosticsStatus): Promise { + const payload: DiagnosticsStatusNotificationRequest = { + status: diagnosticsStatus + }; + await this.sendMessage(Utils.generateUUID(), payload, MessageType.CALL_MESSAGE, OCPP16RequestCommand.DIAGNOSTICS_STATUS_NOTIFICATION); + } + public async sendError(messageId: string, error: OCPPError, commandName: OCPP16RequestCommand | OCPP16IncomingRequestCommand): Promise { // Send error return this.sendMessage(messageId, error, MessageType.CALL_ERROR_MESSAGE, commandName); diff --git a/src/charging-station/ocpp/OCPPIncomingRequestService.ts b/src/charging-station/ocpp/OCPPIncomingRequestService.ts index 897127b6..9980e5d8 100644 --- a/src/charging-station/ocpp/OCPPIncomingRequestService.ts +++ b/src/charging-station/ocpp/OCPPIncomingRequestService.ts @@ -1,5 +1,6 @@ import ChargingStation from '../ChargingStation'; import { IncomingRequestCommand } from '../../types/ocpp/Requests'; +import logger from '../../utils/Logger'; export default abstract class OCPPIncomingRequestService { protected chargingStation: ChargingStation; @@ -8,5 +9,10 @@ export default abstract class OCPPIncomingRequestService { this.chargingStation = chargingStation; } + public handleIncomingRequestError(commandName: IncomingRequestCommand, error: Error): void { + logger.error(this.chargingStation.logPrefix() + ' Incoming request command ' + commandName + ' error: %j', error); + throw error; + } + public abstract handleRequest(messageId: string, commandName: IncomingRequestCommand, commandPayload: Record): Promise; } diff --git a/src/charging-station/ocpp/OCPPRequestService.ts b/src/charging-station/ocpp/OCPPRequestService.ts index 2b00ccb9..81682699 100644 --- a/src/charging-station/ocpp/OCPPRequestService.ts +++ b/src/charging-station/ocpp/OCPPRequestService.ts @@ -1,5 +1,5 @@ import { AuthorizeResponse, StartTransactionResponse, StopTransactionReason, StopTransactionResponse } from '../../types/ocpp/Transaction'; -import { IncomingRequestCommand, RequestCommand } from '../../types/ocpp/Requests'; +import { DiagnosticsStatus, IncomingRequestCommand, RequestCommand } from '../../types/ocpp/Requests'; import { BootNotificationResponse } from '../../types/ocpp/Responses'; import { ChargePointErrorCode } from '../../types/ocpp/ChargePointErrorCode'; @@ -104,7 +104,7 @@ export default abstract class OCPPRequestService { } public handleRequestError(commandName: RequestCommand, error: Error): void { - logger.error(this.chargingStation.logPrefix() + ' Send ' + commandName + ' error: %j', error); + logger.error(this.chargingStation.logPrefix() + ' Request command ' + commandName + ' error: %j', error); throw error; } @@ -117,5 +117,6 @@ export default abstract class OCPPRequestService { public abstract sendMeterValues(connectorId: number, transactionId: number, interval: number, self: OCPPRequestService): Promise; public abstract sendTransactionBeginMeterValues(connectorId: number, transactionId: number, beginMeterValue: MeterValue): Promise; public abstract sendTransactionEndMeterValues(connectorId: number, transactionId: number, endMeterValue: MeterValue): Promise; + public abstract sendDiagnosticsStatusNotification(diagnosticsStatus: DiagnosticsStatus): Promise; public abstract sendError(messageId: string, error: OCPPError, commandName: RequestCommand | IncomingRequestCommand): Promise; } diff --git a/src/types/ChargingStationTemplate.ts b/src/types/ChargingStationTemplate.ts index c65e94c6..0136ab32 100644 --- a/src/types/ChargingStationTemplate.ts +++ b/src/types/ChargingStationTemplate.ts @@ -54,6 +54,7 @@ export default interface ChargingStationTemplate { useConnectorId0?: boolean; randomConnectors?: boolean; resetTime?: number; + autoRegister: boolean; autoReconnectMaxRetries?: number; reconnectExponentialDelay?: boolean; registrationMaxRetries?: number; diff --git a/src/types/ocpp/1.6/DiagnosticsStatus.ts b/src/types/ocpp/1.6/DiagnosticsStatus.ts new file mode 100644 index 00000000..c9feccea --- /dev/null +++ b/src/types/ocpp/1.6/DiagnosticsStatus.ts @@ -0,0 +1,6 @@ +export enum OCPP16DiagnosticsStatus { + Idle = 'Idle', + Uploaded = 'Uploaded', + UploadFailed = 'UploadFailed', + Uploading = 'Uploading' +} diff --git a/src/types/ocpp/1.6/Requests.ts b/src/types/ocpp/1.6/Requests.ts index 9ed48049..873d41a0 100644 --- a/src/types/ocpp/1.6/Requests.ts +++ b/src/types/ocpp/1.6/Requests.ts @@ -2,6 +2,7 @@ import { ChargingProfilePurposeType, OCPP16ChargingProfile } from './ChargingPro import { OCPP16ChargePointErrorCode } from './ChargePointErrorCode'; import { OCPP16ChargePointStatus } from './ChargePointStatus'; +import { OCPP16DiagnosticsStatus } from './DiagnosticsStatus'; import { OCPP16StandardParametersKey } from './Configuration'; export enum OCPP16RequestCommand { @@ -12,7 +13,8 @@ export enum OCPP16RequestCommand { AUTHORIZE = 'Authorize', START_TRANSACTION = 'StartTransaction', STOP_TRANSACTION = 'StopTransaction', - METER_VALUES = 'MeterValues' + METER_VALUES = 'MeterValues', + DIAGNOSTICS_STATUS_NOTIFICATION= 'DiagnosticsStatusNotification' } export enum OCPP16IncomingRequestCommand { @@ -25,7 +27,8 @@ export enum OCPP16IncomingRequestCommand { SET_CHARGING_PROFILE = 'SetChargingProfile', CLEAR_CHARGING_PROFILE = 'ClearChargingProfile', REMOTE_START_TRANSACTION = 'RemoteStartTransaction', - REMOTE_STOP_TRANSACTION = 'RemoteStopTransaction' + REMOTE_STOP_TRANSACTION = 'RemoteStopTransaction', + GET_DIAGNOSTICS = 'GetDiagnostics' } // eslint-disable-next-line @typescript-eslint/no-empty-interface @@ -106,3 +109,15 @@ export interface ClearChargingProfileRequest { chargingProfilePurpose?: ChargingProfilePurposeType; stackLevel?: number; } + +export interface GetDiagnosticsRequest { + location: string; + retries?: number; + retryInterval?: number; + startTime?: Date; + stopTime?: Date; +} + +export interface DiagnosticsStatusNotificationRequest { + status: OCPP16DiagnosticsStatus +} diff --git a/src/types/ocpp/1.6/Responses.ts b/src/types/ocpp/1.6/Responses.ts index 317926f3..68df3e91 100644 --- a/src/types/ocpp/1.6/Responses.ts +++ b/src/types/ocpp/1.6/Responses.ts @@ -73,3 +73,10 @@ export enum OCPP16ClearChargingProfileStatus { export interface ClearChargingProfileResponse { status: OCPP16ClearChargingProfileStatus; } + +export interface GetDiagnosticsResponse { + fileName?: string; +} + +// eslint-disable-next-line @typescript-eslint/no-empty-interface +export interface DiagnosticsStatusNotificationResponse {} diff --git a/src/types/ocpp/Requests.ts b/src/types/ocpp/Requests.ts index aeb6828c..82c7d213 100644 --- a/src/types/ocpp/Requests.ts +++ b/src/types/ocpp/Requests.ts @@ -1,6 +1,7 @@ import { OCPP16AvailabilityType, OCPP16BootNotificationRequest, OCPP16IncomingRequestCommand, OCPP16RequestCommand } from './1.6/Requests'; import { MessageType } from './MessageType'; +import { OCPP16DiagnosticsStatus } from './1.6/DiagnosticsStatus'; import OCPPError from '../../charging-station/OcppError'; export default interface Requests { @@ -27,6 +28,12 @@ export const IncomingRequestCommand = { ...OCPP16IncomingRequestCommand }; +export type DiagnosticsStatus = OCPP16DiagnosticsStatus; + +export const DiagnosticsStatus = { + ...OCPP16DiagnosticsStatus +}; + export type Request = [(payload: Record | string, requestPayload: Record) => void, (error: OCPPError) => void, Record]; export type IncomingRequest = [MessageType, string, IncomingRequestCommand, Record, Record]; diff --git a/src/utils/Constants.ts b/src/utils/Constants.ts index 350170aa..9327b988 100644 --- a/src/utils/Constants.ts +++ b/src/utils/Constants.ts @@ -6,6 +6,7 @@ export default class Constants { static readonly ENTITY_CHARGING_STATION = 'ChargingStation'; static readonly ENTITY_AUTOMATIC_TRANSACTION_GENERATOR = 'AutomaticTransactionGenerator'; + static readonly OCPP_RESPONSE_EMPTY = Object.freeze({}); static readonly OCPP_RESPONSE_ACCEPTED = Object.freeze({ status: DefaultStatus.ACCEPTED }); static readonly OCPP_RESPONSE_REJECTED = Object.freeze({ status: DefaultStatus.REJECTED }); static readonly OCPP_CONFIGURATION_RESPONSE_ACCEPTED = Object.freeze({ status: ConfigurationStatus.ACCEPTED }); @@ -25,7 +26,7 @@ export default class Constants { static readonly OCPP_AVAILABILITY_RESPONSE_SCHEDULED = Object.freeze({ status: AvailabilityStatus.SCHEDULED }); static readonly OCPP_DEFAULT_BOOT_NOTIFICATION_INTERVAL = 60000; // Ms - static readonly OCPP_ERROR_TIMEOUT = 60000; // 60 sec + static readonly OCPP_ERROR_TIMEOUT = 60000; // Ms static readonly CHARGING_STATION_DEFAULT_RESET_TIME = 60000; // Ms static readonly CHARGING_STATION_ATG_WAIT_TIME = 2000; // Ms @@ -41,6 +42,8 @@ export default class Constants { static readonly DEFAULT_CONNECTION_TIMEOUT = 30; + static readonly DEFAULT_HEARTBEAT_INTERVAL = 60000; // Ms + static readonly SUPPORTED_MEASURANDS = Object.freeze([MeterValueMeasurand.STATE_OF_CHARGE, MeterValueMeasurand.VOLTAGE, MeterValueMeasurand.POWER_ACTIVE_IMPORT, MeterValueMeasurand.CURRENT_IMPORT, MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER]); diff --git a/test/robohydra/config.json b/test/robohydra/config.json new file mode 100644 index 00000000..71e532fd --- /dev/null +++ b/test/robohydra/config.json @@ -0,0 +1,9 @@ +{ + "pluginLoadPaths": [ + "test/robohydra/plugins" + ], + "plugins": [ + "logger", + "wsServer" + ] +} diff --git a/test/robohydra/messages.txt b/test/robohydra/messages.txt new file mode 100644 index 00000000..b71191b0 --- /dev/null +++ b/test/robohydra/messages.txt @@ -0,0 +1,2 @@ +GetDiagnostics: + curl -d '[2,"123456789","GetDiagnostics",{"location":"ftp://localhost"}]' -H "Content-Type: application/json" -X POST http://localhost:3000/message diff --git a/test/robohydra/plugins/wsServer/index.js b/test/robohydra/plugins/wsServer/index.js new file mode 100644 index 00000000..d4ab6b8d --- /dev/null +++ b/test/robohydra/plugins/wsServer/index.js @@ -0,0 +1,59 @@ +const RoboHydraHead = require('robohydra').heads.RoboHydraHead; +const RoboHydraWebSocketHead = require('robohydra').heads.RoboHydraWebSocketHead; +const RoboHydraWebSocketHeadProxy = require('robohydra').heads.RoboHydraWebSocketHeadProxy; + +exports.getBodyParts = function(conf) { + let wsSocket; + return { + heads: [ + new RoboHydraHead({ + name: 'message', + path: '/message', + method: 'POST', + handler: function(req, res) { + const msg = JSON.stringify(req.body); + if (wsSocket) { + wsSocket.send(msg); + res.send('Message sent'); + } else { + res.send('Cannot send message, no opened websocket found'); + } + } + }), + + new RoboHydraHead({ + name: 'close', + path: '/close', + method: 'GET', + handler: function(req, res) { + if (wsSocket) { + wsSocket.close(); + res.send('Websocket closed'); + } else { + res.send('Cannot close websocket, no opened websocket found'); + } + } + }), + + new RoboHydraWebSocketHeadProxy({ + name: 'proxy', + mountPath: '/proxy', + proxyTo: 'ws://server.example.com', + preProcessor: function(data) { + console.log('From the client: ' + data); + }, + postProcessor: function(data) { + console.log('From the server: ' + data); + } + }), + + new RoboHydraWebSocketHead({ + name: 'WS Server', + path: '/.*', + handler: function(req, socket) { + wsSocket = socket; + } + }) + ] + }; +};