diff --git a/.Makefile.swp b/.Makefile.swp new file mode 100644 index 0000000000..7e57b2e034 Binary files /dev/null and b/.Makefile.swp differ diff --git a/package-lock.json b/package-lock.json index c74d15161b..4c567ab190 100644 --- a/package-lock.json +++ b/package-lock.json @@ -21,7 +21,7 @@ }, "devDependencies": { "ajv": "^6.12.6", - "ajv-cli": "^0.6.0", + "ajv-cli": "^5.0.0", "prettier": "^2.6.2" } }, @@ -42,29 +42,75 @@ } }, "node_modules/ajv-cli": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/ajv-cli/-/ajv-cli-0.6.0.tgz", - "integrity": "sha512-85CnFX7Nft+UvmAi1fHNnqrtOiSL8KW/o4hS096AVT1P+45SAe5YO242pn9+rqC9F1UKyeFioCG52jKXTOI2FA==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ajv-cli/-/ajv-cli-5.0.0.tgz", + "integrity": "sha512-LY4m6dUv44HTyhV+u2z5uX4EhPYTM38Iv1jdgDJJJCyOOuqB8KtZEGjPZ2T+sh5ZIJrXUfgErYx/j3gLd3+PlQ==", "dev": true, "dependencies": { - "ajv": "^3.8.0", - "glob": "^7.0.3", + "ajv": "^8.0.0", + "fast-json-patch": "^2.0.0", + "glob": "^7.1.0", + "js-yaml": "^3.14.0", + "json-schema-migrate": "^2.0.0", + "json5": "^2.1.3", "minimist": "^1.2.0" }, "bin": { - "ajv": "index.js" + "ajv": "dist/index.js" + }, + "peerDependencies": { + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "ts-node": { + "optional": true + } } }, "node_modules/ajv-cli/node_modules/ajv": { - "version": "3.8.10", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-3.8.10.tgz", - "integrity": "sha512-h74deHfbgeB8TuWq6UQxP4fwsCbo9T+pvWofl4pEdZzI6lMSSFAWZr3PsNXHjSFABCj49j6fgbzUTHWIrMdHMw==", + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-cli/node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/ajv-cli/node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", "dev": true, "dependencies": { - "co": "^4.6.0", - "json-stable-stringify": "^1.0.1" + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" } }, + "node_modules/ajv-cli/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + }, "node_modules/ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", @@ -118,16 +164,6 @@ "wrap-ansi": "^7.0.0" } }, - "node_modules/co": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", - "dev": true, - "engines": { - "iojs": ">= 1.0.0", - "node": ">= 0.12.0" - } - }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -163,12 +199,43 @@ "node": ">=6" } }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true, + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", "dev": true }, + "node_modules/fast-json-patch": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/fast-json-patch/-/fast-json-patch-2.2.1.tgz", + "integrity": "sha512-4j5uBaTnsYAV5ebkidvxiLUYOwjQ+JSFljeqfTxCrH9bDmlCQaOJFS84oDJ2rAXZq2yskmk3ORfoP9DCwqFNig==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^2.0.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/fast-json-patch/node_modules/fast-deep-equal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", + "integrity": "sha512-bCK/2Z4zLidyB4ReuIsvALH6w31YfAQDmXMqMx6FyfHqvBxtjC0eRumeSu4Bs3XtXwpyIywtSTrVT99BxY1f9w==", + "dev": true + }, "node_modules/fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", @@ -276,31 +343,53 @@ "js-yaml": "bin/js-yaml.js" } }, - "node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true + "node_modules/json-schema-migrate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/json-schema-migrate/-/json-schema-migrate-2.0.0.tgz", + "integrity": "sha512-r38SVTtojDRp4eD6WsCqiE0eNDt4v1WalBXb9cyZYw9ai5cGtBwzRNWjHzJl38w6TxFkXAIA7h+fyX3tnrAFhQ==", + "dev": true, + "dependencies": { + "ajv": "^8.0.0" + } }, - "node_modules/json-stable-stringify": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.2.tgz", - "integrity": "sha512-eunSSaEnxV12z+Z73y/j5N37/In40GK4GmsSy+tEHJMxknvqnA7/djeYtAgW0GsWHUfg+847WJjKaEylk2y09g==", + "node_modules/json-schema-migrate/node_modules/ajv": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", "dev": true, "dependencies": { - "jsonify": "^0.0.1" + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/jsonify": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.1.tgz", - "integrity": "sha512-2/Ki0GcmuqSrgFyelQq9M05y7PS0mEwuIzrf3f1fPqkVDVRvZrPZtVSMHxdgo8Aq0sxAOb/cr2aqqA3LeWHVPg==", + "node_modules/json-schema-migrate/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" } }, "node_modules/lodash.isequal": { @@ -420,6 +509,21 @@ "node": ">=0.10.0" } }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "dev": true + }, "node_modules/string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", @@ -536,25 +640,56 @@ } }, "ajv-cli": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/ajv-cli/-/ajv-cli-0.6.0.tgz", - "integrity": "sha512-85CnFX7Nft+UvmAi1fHNnqrtOiSL8KW/o4hS096AVT1P+45SAe5YO242pn9+rqC9F1UKyeFioCG52jKXTOI2FA==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ajv-cli/-/ajv-cli-5.0.0.tgz", + "integrity": "sha512-LY4m6dUv44HTyhV+u2z5uX4EhPYTM38Iv1jdgDJJJCyOOuqB8KtZEGjPZ2T+sh5ZIJrXUfgErYx/j3gLd3+PlQ==", "dev": true, "requires": { - "ajv": "^3.8.0", - "glob": "^7.0.3", + "ajv": "^8.0.0", + "fast-json-patch": "^2.0.0", + "glob": "^7.1.0", + "js-yaml": "^3.14.0", + "json-schema-migrate": "^2.0.0", + "json5": "^2.1.3", "minimist": "^1.2.0" }, "dependencies": { "ajv": { - "version": "3.8.10", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-3.8.10.tgz", - "integrity": "sha512-h74deHfbgeB8TuWq6UQxP4fwsCbo9T+pvWofl4pEdZzI6lMSSFAWZr3PsNXHjSFABCj49j6fgbzUTHWIrMdHMw==", + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + } + }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", "dev": true, "requires": { - "co": "^4.6.0", - "json-stable-stringify": "^1.0.1" + "sprintf-js": "~1.0.2" } + }, + "js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true } } }, @@ -602,12 +737,6 @@ "wrap-ansi": "^7.0.0" } }, - "co": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", - "dev": true - }, "color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -637,12 +766,35 @@ "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==" }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true + }, "fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", "dev": true }, + "fast-json-patch": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/fast-json-patch/-/fast-json-patch-2.2.1.tgz", + "integrity": "sha512-4j5uBaTnsYAV5ebkidvxiLUYOwjQ+JSFljeqfTxCrH9bDmlCQaOJFS84oDJ2rAXZq2yskmk3ORfoP9DCwqFNig==", + "dev": true, + "requires": { + "fast-deep-equal": "^2.0.1" + }, + "dependencies": { + "fast-deep-equal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", + "integrity": "sha512-bCK/2Z4zLidyB4ReuIsvALH6w31YfAQDmXMqMx6FyfHqvBxtjC0eRumeSu4Bs3XtXwpyIywtSTrVT99BxY1f9w==", + "dev": true + } + } + }, "fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", @@ -723,25 +875,45 @@ "argparse": "^2.0.1" } }, + "json-schema-migrate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/json-schema-migrate/-/json-schema-migrate-2.0.0.tgz", + "integrity": "sha512-r38SVTtojDRp4eD6WsCqiE0eNDt4v1WalBXb9cyZYw9ai5cGtBwzRNWjHzJl38w6TxFkXAIA7h+fyX3tnrAFhQ==", + "dev": true, + "requires": { + "ajv": "^8.0.0" + }, + "dependencies": { + "ajv": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + } + }, + "json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + } + } + }, "json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", "dev": true }, - "json-stable-stringify": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.2.tgz", - "integrity": "sha512-eunSSaEnxV12z+Z73y/j5N37/In40GK4GmsSy+tEHJMxknvqnA7/djeYtAgW0GsWHUfg+847WJjKaEylk2y09g==", - "dev": true, - "requires": { - "jsonify": "^0.0.1" - } - }, - "jsonify": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.1.tgz", - "integrity": "sha512-2/Ki0GcmuqSrgFyelQq9M05y7PS0mEwuIzrf3f1fPqkVDVRvZrPZtVSMHxdgo8Aq0sxAOb/cr2aqqA3LeWHVPg==", + "json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", "dev": true }, "lodash.isequal": { @@ -828,6 +1000,18 @@ "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=" }, + "require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "dev": true + }, "string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", diff --git a/package.json b/package.json index d3440cfb7c..e68a5ae44c 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,7 @@ "homepage": "https://github.com/TheThingsNetwork/lorawan-devices#readme", "devDependencies": { "ajv": "^6.12.6", - "ajv-cli": "^0.6.0", + "ajv-cli": "^5.0.0", "prettier": "^2.6.2" }, "dependencies": { diff --git a/vendor/milesight-iot/am103-codec.yaml b/vendor/milesight-iot/am103-codec.yaml new file mode 100644 index 0000000000..890bd1cdb5 --- /dev/null +++ b/vendor/milesight-iot/am103-codec.yaml @@ -0,0 +1,14 @@ +# Uplink decoder decodes binary data uplink into a JSON object +uplinkDecoder: + fileName: am103.js + examples: + - description: Ambience Monitoring Sensors (example 1) - Milesight IoT + input: + fPort: 85 + bytes: [0x01, 0x75, 0x5C, 0x03, 0x67, 0x34, 0x01, 0x04, 0x68, 0x65, 0x07, 0x7D, 0xE7, 0x04] + output: + data: + battery: 92 + temperature: 30.8 + humidity: 50.5 + co2: 1255 diff --git a/vendor/milesight-iot/am103.js b/vendor/milesight-iot/am103.js new file mode 100644 index 0000000000..12047cc0fd --- /dev/null +++ b/vendor/milesight-iot/am103.js @@ -0,0 +1,92 @@ + +function decodeUplink(input) { + var res = Decoder(input.bytes, input.fPort); + if (res.error) { + return { + errors: [res.error], + }; + } + return { + data: res, + }; +} + +/** + * Payload Decoder for The Things Network + * + * Copyright 2021 Milesight IoT + * + * @product AM104 / AM107 + */ +function Decoder(bytes, port) { + var decoded = {}; + + for (var i = 0; i < bytes.length;) { + var channel_id = bytes[i++]; + var channel_type = bytes[i++]; + // BATTERY + if (channel_id === 0x01 && channel_type === 0x75) { + decoded.battery = bytes[i]; + i += 1; + } + // TEMPERATURE + else if (channel_id === 0x03 && channel_type === 0x67) { + // ℃ + decoded.temperature = readInt16LE(bytes.slice(i, i + 2)) / 10; + i += 2; + + // ℉ + // decoded.temperature = readInt16LE(bytes.slice(i, i + 2)) / 10 * 1.8 + 32; + // i +=2; + } + // HUMIDITY + else if (channel_id === 0x04 && channel_type === 0x68) { + decoded.humidity = bytes[i] / 2; + i += 1; + } + // PIR + else if (channel_id === 0x05 && channel_type === 0x6A) { + decoded.activity = readUInt16LE(bytes.slice(i, i + 2)); + i += 2; + } + // LIGHT + else if (channel_id === 0x06 && channel_type === 0x65) { + decoded.illumination = readUInt16LE(bytes.slice(i, i + 2)); + decoded.infrared_and_visible = readUInt16LE(bytes.slice(i + 2, i + 4)); + decoded.infrared = readUInt16LE(bytes.slice(i + 4, i + 6)); + i += 6; + } + // CO2 + else if (channel_id === 0x07 && channel_type === 0x7D) { + decoded.co2 = readUInt16LE(bytes.slice(i, i + 2)); + i += 2; + } + // TVOC + else if (channel_id === 0x08 && channel_type === 0x7D) { + decoded.tvoc = readUInt16LE(bytes.slice(i, i + 2)); + i += 2; + } + // PRESSURE + else if (channel_id === 0x09 && channel_type === 0x73) { + decoded.pressure = readUInt16LE(bytes.slice(i, i + 2)) / 10; + i += 2; + } else { + break; + } + } + + return decoded; +} + +/* ****************************************** +* bytes to number +********************************************/ +function readUInt16LE(bytes) { + var value = (bytes[1] << 8) + bytes[0]; + return value & 0xffff; +} + +function readInt16LE(bytes) { + var ref = readUInt16LE(bytes); + return ref > 0x7fff ? ref - 0x10000 : ref; +} diff --git a/vendor/milesight-iot/am103.png b/vendor/milesight-iot/am103.png new file mode 100644 index 0000000000..0a5972d35a Binary files /dev/null and b/vendor/milesight-iot/am103.png differ diff --git a/vendor/milesight-iot/am103.yaml b/vendor/milesight-iot/am103.yaml new file mode 100644 index 0000000000..54efbd4ef1 --- /dev/null +++ b/vendor/milesight-iot/am103.yaml @@ -0,0 +1,116 @@ +name: Milesight AM103-LoRaWAN Indoor Air Quality Sensor (3 in 1) +description: Milesight AM103 is a compact indoor ambience monitoring sensor that supports long-lasting battery life, wall-mounted installation, and visual display via an E-ink screen. Meanwhile, AM103L is a more economical model without E-ink screen to meet your various needs. Their built-in NFC lead to easy batch installation. The clean and modern design of AM103 and AM103L is ideal for offices, classrooms, libraries, hospitals, etc. + +hardwareVersions: + - version: '1.x' + numeric: 1 + +firmwareVersions: + - version: '1.x' + numeric: 1 + hardwareVersions: + - '1.x' + + profiles: + EU863-870: + id: profile-eu868 + lorawanCertified: true + codec: am103-codec + US902-928: + id: profile-us915 + lorawanCertified: true + codec: am103-codec + AU915-928: + id: profile-au915 + lorawanCertified: true + codec: am103-codec + AS923: + id: profile-as923 + lorawanCertified: true + codec: am103-codec + CN470-510: + id: profile-cn470 + lorawanCertified: true + codec: am103-codec + KR920-923: + id: profile-kr920 + lorawanCertified: true + codec: am103-codec + IN865-867: + id: profile-in865 + lorawanCertified: true + codec: am103-codec + RU864-870: + id: profile-ru864 + lorawanCertified: true + codec: am103-codec + +sensors: + - battery + - temperature + - humidity + - co2 + +dimensions: + width: 20.5 + length: 68 + height: 65 + +battery: + replaceable: true + type: ER14505 + +operatingConditions: + temperature: + min: -20 + max: 60 + + relativeHumidity: + min: 0 + max: 0.95 + +ipCode: IP30 + +keyProvisioning: + - custom + - join server +keySecurity: none +productURL: https://www.milesight-iot.com/lorawan/sensor/am103/?utm_source=platform&utm_medium=web&utm_campaign=milesight +dataSheetURL: https://resource.milesight-iot.com/milesight/document/am100-series-datasheet-en.pdf +resellerURLs: + - name: 'iot.sales@milesight.com' + region: + - United States + - European Union + - Canada + url: https://www.alibaba.com/product-detail/AM103-AM103L-Temperature-and-Humidity-Sensor_1600552633106.html?spm=a2700.galleryofferlist.normal_offer.d_title.40bd4794jPiLIT + +photos: + main: am103.png + +compliances: + safety: + - body: IEC + norm: EN + standard: 62368-1 + radioEquipment: + - body: ETSI + norm: EN + standard: 300 220-1 + version: 3.1.1 + - body: ETSI + norm: EN + standard: 300 220-2 + version: 2.2.1 + - body: ETSI + norm: EN + standard: 301 489-1 + version: 2.2.3 + - body: ETSI + norm: EN + standard: 301 489-3 + version: 2.1.1 + - body: ETSI + norm: EN + standard: 300 330 + version: 2.1.1 diff --git a/vendor/milesight-iot/am103l-codec.yaml b/vendor/milesight-iot/am103l-codec.yaml new file mode 100644 index 0000000000..95132fa62e --- /dev/null +++ b/vendor/milesight-iot/am103l-codec.yaml @@ -0,0 +1,14 @@ +# Uplink decoder decodes binary data uplink into a JSON object +uplinkDecoder: + fileName: am103l.js + examples: + - description: Ambience Monitoring Sensors (example 1) - Milesight IoT + input: + fPort: 85 + bytes: [0x01, 0x75, 0x5C, 0x03, 0x67, 0x34, 0x01, 0x04, 0x68, 0x65, 0x07, 0x7D, 0xE7, 0x04] + output: + data: + battery: 92 + temperature: 30.8 + humidity: 50.5 + co2: 1255 diff --git a/vendor/milesight-iot/am103l.js b/vendor/milesight-iot/am103l.js new file mode 100644 index 0000000000..12047cc0fd --- /dev/null +++ b/vendor/milesight-iot/am103l.js @@ -0,0 +1,92 @@ + +function decodeUplink(input) { + var res = Decoder(input.bytes, input.fPort); + if (res.error) { + return { + errors: [res.error], + }; + } + return { + data: res, + }; +} + +/** + * Payload Decoder for The Things Network + * + * Copyright 2021 Milesight IoT + * + * @product AM104 / AM107 + */ +function Decoder(bytes, port) { + var decoded = {}; + + for (var i = 0; i < bytes.length;) { + var channel_id = bytes[i++]; + var channel_type = bytes[i++]; + // BATTERY + if (channel_id === 0x01 && channel_type === 0x75) { + decoded.battery = bytes[i]; + i += 1; + } + // TEMPERATURE + else if (channel_id === 0x03 && channel_type === 0x67) { + // ℃ + decoded.temperature = readInt16LE(bytes.slice(i, i + 2)) / 10; + i += 2; + + // ℉ + // decoded.temperature = readInt16LE(bytes.slice(i, i + 2)) / 10 * 1.8 + 32; + // i +=2; + } + // HUMIDITY + else if (channel_id === 0x04 && channel_type === 0x68) { + decoded.humidity = bytes[i] / 2; + i += 1; + } + // PIR + else if (channel_id === 0x05 && channel_type === 0x6A) { + decoded.activity = readUInt16LE(bytes.slice(i, i + 2)); + i += 2; + } + // LIGHT + else if (channel_id === 0x06 && channel_type === 0x65) { + decoded.illumination = readUInt16LE(bytes.slice(i, i + 2)); + decoded.infrared_and_visible = readUInt16LE(bytes.slice(i + 2, i + 4)); + decoded.infrared = readUInt16LE(bytes.slice(i + 4, i + 6)); + i += 6; + } + // CO2 + else if (channel_id === 0x07 && channel_type === 0x7D) { + decoded.co2 = readUInt16LE(bytes.slice(i, i + 2)); + i += 2; + } + // TVOC + else if (channel_id === 0x08 && channel_type === 0x7D) { + decoded.tvoc = readUInt16LE(bytes.slice(i, i + 2)); + i += 2; + } + // PRESSURE + else if (channel_id === 0x09 && channel_type === 0x73) { + decoded.pressure = readUInt16LE(bytes.slice(i, i + 2)) / 10; + i += 2; + } else { + break; + } + } + + return decoded; +} + +/* ****************************************** +* bytes to number +********************************************/ +function readUInt16LE(bytes) { + var value = (bytes[1] << 8) + bytes[0]; + return value & 0xffff; +} + +function readInt16LE(bytes) { + var ref = readUInt16LE(bytes); + return ref > 0x7fff ? ref - 0x10000 : ref; +} diff --git a/vendor/milesight-iot/am103l.png b/vendor/milesight-iot/am103l.png new file mode 100644 index 0000000000..0a5972d35a Binary files /dev/null and b/vendor/milesight-iot/am103l.png differ diff --git a/vendor/milesight-iot/am103l.yaml b/vendor/milesight-iot/am103l.yaml new file mode 100644 index 0000000000..d89dfda4eb --- /dev/null +++ b/vendor/milesight-iot/am103l.yaml @@ -0,0 +1,116 @@ +name: Milesight AM103-LoRaWAN Indoor Air Quality Sensor (3 in 1) +description: Milesight AM103 is a compact indoor ambience monitoring sensor that supports long-lasting battery life, wall-mounted installation, and visual display via an E-ink screen. Meanwhile, AM103L is a more economical model without E-ink screen to meet your various needs. Their built-in NFC lead to easy batch installation. The clean and modern design of AM103 and AM103L is ideal for offices, classrooms, libraries, hospitals, etc. + +hardwareVersions: + - version: '1.x' + numeric: 1 + +firmwareVersions: + - version: '1.x' + numeric: 1 + hardwareVersions: + - '1.x' + + profiles: + EU863-870: + id: profile-eu868 + lorawanCertified: true + codec: am103l-codec + US902-928: + id: profile-us915 + lorawanCertified: true + codec: am103l-codec + AU915-928: + id: profile-au915 + lorawanCertified: true + codec: am103l-codec + AS923: + id: profile-as923 + lorawanCertified: true + codec: am103l-codec + CN470-510: + id: profile-cn470 + lorawanCertified: true + codec: am103l-codec + KR920-923: + id: profile-kr920 + lorawanCertified: true + codec: am103l-codec + IN865-867: + id: profile-in865 + lorawanCertified: true + codec: am103l-codec + RU864-870: + id: profile-ru864 + lorawanCertified: true + codec: am103l-codec + +sensors: + - battery + - temperature + - humidity + - co2 + +dimensions: + width: 20.5 + length: 68 + height: 65 + +battery: + replaceable: true + type: ER14505 + +operatingConditions: + temperature: + min: -20 + max: 60 + + relativeHumidity: + min: 0 + max: 0.95 + +ipCode: IP30 + +keyProvisioning: + - custom + - join server +keySecurity: none +productURL: https://www.milesight-iot.com/lorawan/sensor/am103/?utm_source=platform&utm_medium=web&utm_campaign=milesight +dataSheetURL: https://resource.milesight-iot.com/milesight/document/am100-series-datasheet-en.pdf +resellerURLs: + - name: 'iot.sales@milesight.com' + region: + - United States + - European Union + - Canada + url: https://www.alibaba.com/product-detail/AM103-AM103L-Temperature-and-Humidity-Sensor_1600552633106.html?spm=a2700.galleryofferlist.normal_offer.d_title.40bd4794jPiLIT + +photos: + main: am103l.png + +compliances: + safety: + - body: IEC + norm: EN + standard: 62368-1 + radioEquipment: + - body: ETSI + norm: EN + standard: 300 220-1 + version: 3.1.1 + - body: ETSI + norm: EN + standard: 300 220-2 + version: 2.2.1 + - body: ETSI + norm: EN + standard: 301 489-1 + version: 2.2.3 + - body: ETSI + norm: EN + standard: 301 489-3 + version: 2.1.1 + - body: ETSI + norm: EN + standard: 300 330 + version: 2.1.1 diff --git a/vendor/milesight-iot/am104-codec.yaml b/vendor/milesight-iot/am104-codec.yaml new file mode 100644 index 0000000000..9597ce9089 --- /dev/null +++ b/vendor/milesight-iot/am104-codec.yaml @@ -0,0 +1,23 @@ +# Uplink decoder decodes binary data uplink into a JSON object +uplinkDecoder: + fileName: am104.js + examples: + - description: Ambience Monitoring Sensors (example 1) - Milesight IoT + input: + fPort: 85 + bytes: [0x01, 0x75, 0x5C, 0x03, 0x67, 0x34, 0x01, 0x04, 0x68, 0x65, 0x05, 0x6A, 0x49, 0x00] + output: + data: + battery: 92 + temperature: 30.8 + humidity: 50.5 + activity: 73 + - description: Ambience Monitoring Sensors (example 2) - Milesgiht IoT + input: + fPort: 85 + bytes: [0x06, 0x65, 0x1C, 0x00, 0x79, 0x00, 0x14, 0x00] + output: + data: + illumination: 28 + infrared: 20 + infrared_and_visible: 121 diff --git a/vendor/milesight-iot/am104.js b/vendor/milesight-iot/am104.js new file mode 100644 index 0000000000..d7bc36483d --- /dev/null +++ b/vendor/milesight-iot/am104.js @@ -0,0 +1,75 @@ + +function decodeUplink(input) { + var res = Decoder(input.bytes, input.fPort); + if (res.error) { + return { + errors: [res.error], + }; + } + return { + data: res, + }; +} + +/** + * Payload Decoder for The Things Network + * + * Copyright 2021 Milesight IoT + * + * @product AM104 / AM107 + */ +function Decoder(bytes, port) { + var decoded = {}; + + for (var i = 0; i < bytes.length;) { + var channel_id = bytes[i++]; + var channel_type = bytes[i++]; + // BATTERY + if (channel_id === 0x01 && channel_type === 0x75) { + decoded.battery = bytes[i]; + i += 1; + } + // TEMPERATURE + else if (channel_id === 0x03 && channel_type === 0x67) { + // ℃ + decoded.temperature = readInt16LE(bytes.slice(i, i + 2)) / 10; + i += 2; + + // ℉ + // decoded.temperature = readInt16LE(bytes.slice(i, i + 2)) / 10 * 1.8 + 32; + // i +=2; + } + // HUMIDITY + else if (channel_id === 0x04 && channel_type === 0x68) { + decoded.humidity = bytes[i] / 2; + i += 1; + } + // PIR + else if (channel_id === 0x05 && channel_type === 0x6A) { + decoded.activity = readUInt16LE(bytes.slice(i, i + 2)); + i += 2; + } + // LIGHT + else if (channel_id === 0x06 && channel_type === 0x65) { + decoded.illumination = readUInt16LE(bytes.slice(i, i + 2)); + decoded.infrared_and_visible = readUInt16LE(bytes.slice(i + 2, i + 4)); + decoded.infrared = readUInt16LE(bytes.slice(i + 4, i + 6)); + i += 6; + } + } + + return decoded; +} + +/* ****************************************** +* bytes to number +********************************************/ +function readUInt16LE(bytes) { + var value = (bytes[1] << 8) + bytes[0]; + return value & 0xffff; +} + +function readInt16LE(bytes) { + var ref = readUInt16LE(bytes); + return ref > 0x7fff ? ref - 0x10000 : ref; +} diff --git a/vendor/milesight-iot/am104.png b/vendor/milesight-iot/am104.png new file mode 100644 index 0000000000..24dca133bf Binary files /dev/null and b/vendor/milesight-iot/am104.png differ diff --git a/vendor/milesight-iot/am104.yaml b/vendor/milesight-iot/am104.yaml new file mode 100644 index 0000000000..51b629c8e8 --- /dev/null +++ b/vendor/milesight-iot/am104.yaml @@ -0,0 +1,161 @@ +name: Milesight AM104 - LoRaWAN® Indoor Air Quality Sensor (4 in 1) +description: Milesight AM104 is a compact indoor ambience monitoring sensor that supports long-lasting battery life, wall-mounted installation, and visual display via an E-ink screen. It's equipped with NFC and can easily be configured via a smartphone or PC software. Its clean and modern design is ideal for offices, classrooms, libraries, hospitals, etc. + +hardwareVersions: + - version: '1.x' + numeric: 1 + - version: '2.x' + numeric: 2 + +firmwareVersions: + - version: '1.x' + numeric: 1 + hardwareVersions: + - '1.x' + + profiles: + EU863-870: + id: profile-eu868 + lorawanCertified: true + codec: am104-codec + US902-928: + id: profile-us915 + lorawanCertified: true + codec: am104-codec + AU915-928: + id: profile-au915 + lorawanCertified: true + codec: am104-codec + AS923: + id: profile-as923 + lorawanCertified: true + codec: am104-codec + CN470-510: + id: profile-cn470 + lorawanCertified: true + codec: am104-codec + KR920-923: + id: profile-kr920 + lorawanCertified: true + codec: am104-codec + IN865-867: + id: profile-in865 + lorawanCertified: true + codec: am104-codec + RU864-870: + id: profile-ru864 + lorawanCertified: true + codec: am104-codec + + - version: '1.x' + numeric: 2 + hardwareVersions: + - '2.x' + + profiles: + EU863-870: + id: profile-eu868 + lorawanCertified: true + codec: am104-codec + US902-928: + id: profile-us915 + lorawanCertified: true + codec: am104-codec + AU915-928: + id: profile-au915 + lorawanCertified: true + codec: am104-codec + AS923: + id: profile-as923 + lorawanCertified: true + codec: am104-codec + CN470-510: + id: profile-cn470 + lorawanCertified: true + codec: am104-codec + KR920-923: + id: profile-kr920 + lorawanCertified: true + codec: am104-codec + IN865-867: + id: profile-in865 + lorawanCertified: true + codec: am104-codec + RU864-870: + id: profile-ru864 + lorawanCertified: true + codec: am104-codec + +sensors: + - battery + - temperature + - humidity + - pir + - light + +dimensions: + width: 21.2 + length: 105 + height: 70.4 + +battery: + replaceable: true + type: AA + +operatingConditions: + temperature: + min: 0 + max: 45 + + relativeHumidity: + min: 0 + max: 1.00 + +ipCode: IP30 + +keyProvisioning: + - custom + - join server +keySecurity: none +productURL: https://www.milesight-iot.com/lorawan/sensor/am100/?utm_source=ttn-device-repository&utm_medium=web&utm_campaign=Milesight +dataSheetURL: https://resource.milesight-iot.com/milesight/document/am100-series-datasheet-en.pdf +resellerURLs: + - name: 'iot.sales@milesight.com' + region: + - United States + - European Union + - Canada + url: https://www.alibaba.com/product-detail/Milesight-AM104-LoRaWAN-Sensor-for-Indoor_62478849987.html?spm=a2747.manage.0.0.45e671d2wIYq59&utm_source=ttn-device-repository&utm_medium=web&utm_campaign=Milesight + +photos: + main: am104.png + +videos: + main: https://www.youtube.com/watch?v=lu90qeIkjC0&ab_channel=MilesightIoT + +compliances: + safety: + - body: IEC + norm: EN + standard: 62368-1 + radioEquipment: + - body: ETSI + norm: EN + standard: 300 220-1 + version: 3.1.1 + - body: ETSI + norm: EN + standard: 300 220-2 + version: 2.2.1 + - body: ETSI + norm: EN + standard: 301 489-1 + version: 2.2.3 + - body: ETSI + norm: EN + standard: 301 489-3 + version: 2.1.1 + - body: ETSI + norm: EN + standard: 300 330 + version: 2.1.1 diff --git a/vendor/milesight-iot/am107.js b/vendor/milesight-iot/am107.js index 7643f56e70..12047cc0fd 100644 --- a/vendor/milesight-iot/am107.js +++ b/vendor/milesight-iot/am107.js @@ -22,57 +22,57 @@ function Decoder(bytes, port) { var decoded = {}; for (var i = 0; i < bytes.length;) { - var channel_id = bytes[i++]; - var channel_type = bytes[i++]; - // BATTERY - if (channel_id === 0x01 && channel_type === 0x75) { - decoded.battery = bytes[i]; - i += 1; - } - // TEMPERATURE - else if (channel_id === 0x03 && channel_type === 0x67) { - // ℃ - decoded.temperature = readInt16LE(bytes.slice(i, i + 2)) / 10; - i += 2; + var channel_id = bytes[i++]; + var channel_type = bytes[i++]; + // BATTERY + if (channel_id === 0x01 && channel_type === 0x75) { + decoded.battery = bytes[i]; + i += 1; + } + // TEMPERATURE + else if (channel_id === 0x03 && channel_type === 0x67) { + // ℃ + decoded.temperature = readInt16LE(bytes.slice(i, i + 2)) / 10; + i += 2; - // ℉ - // decoded.temperature = readInt16LE(bytes.slice(i, i + 2)) / 10 * 1.8 + 32; - // i +=2; - } - // HUMIDITY - else if (channel_id === 0x04 && channel_type === 0x68) { - decoded.humidity = bytes[i] / 2; - i += 1; - } - // PIR - else if (channel_id === 0x05 && channel_type === 0x6A) { - decoded.activity = readUInt16LE(bytes.slice(i, i + 2)); - i += 2; - } - // LIGHT - else if (channel_id === 0x06 && channel_type === 0x65) { - decoded.illumination = readUInt16LE(bytes.slice(i, i + 2)); - decoded.infrared_and_visible = readUInt16LE(bytes.slice(i + 2, i + 4)); - decoded.infrared = readUInt16LE(bytes.slice(i + 4, i + 6)); - i += 6; - } - // CO2 - else if (channel_id === 0x07 && channel_type === 0x7D) { - decoded.co2 = readUInt16LE(bytes.slice(i, i + 2)); - i += 2; - } - // TVOC - else if (channel_id === 0x08 && channel_type === 0x7D) { - decoded.tvoc = readUInt16LE(bytes.slice(i, i + 2)); - i += 2; - } - // PRESSURE - else if (channel_id === 0x09 && channel_type === 0x73) { - decoded.pressure = readUInt16LE(bytes.slice(i, i + 2)) / 10; - i += 2; - } else { - break; - } + // ℉ + // decoded.temperature = readInt16LE(bytes.slice(i, i + 2)) / 10 * 1.8 + 32; + // i +=2; + } + // HUMIDITY + else if (channel_id === 0x04 && channel_type === 0x68) { + decoded.humidity = bytes[i] / 2; + i += 1; + } + // PIR + else if (channel_id === 0x05 && channel_type === 0x6A) { + decoded.activity = readUInt16LE(bytes.slice(i, i + 2)); + i += 2; + } + // LIGHT + else if (channel_id === 0x06 && channel_type === 0x65) { + decoded.illumination = readUInt16LE(bytes.slice(i, i + 2)); + decoded.infrared_and_visible = readUInt16LE(bytes.slice(i + 2, i + 4)); + decoded.infrared = readUInt16LE(bytes.slice(i + 4, i + 6)); + i += 6; + } + // CO2 + else if (channel_id === 0x07 && channel_type === 0x7D) { + decoded.co2 = readUInt16LE(bytes.slice(i, i + 2)); + i += 2; + } + // TVOC + else if (channel_id === 0x08 && channel_type === 0x7D) { + decoded.tvoc = readUInt16LE(bytes.slice(i, i + 2)); + i += 2; + } + // PRESSURE + else if (channel_id === 0x09 && channel_type === 0x73) { + decoded.pressure = readUInt16LE(bytes.slice(i, i + 2)) / 10; + i += 2; + } else { + break; + } } return decoded; diff --git a/vendor/milesight-iot/am307-codec.yaml b/vendor/milesight-iot/am307-codec.yaml new file mode 100644 index 0000000000..add0896d7e --- /dev/null +++ b/vendor/milesight-iot/am307-codec.yaml @@ -0,0 +1,22 @@ +# Uplink decoder decodes binary data uplink into a JSON object +uplinkDecoder: + fileName: am307l.js + examples: + - description: Ambience Monitoring Sensors (example 1) - Milesight IoT + input: + fPort: 85 + bytes: [0x01, 0x75, 0x5C, 0x03, 0x67, 0x34, 0x01, 0x04, 0x68, 0x65, 0x05, 0x6A, 0x49, 0x00] + output: + data: + battery: 92 + temperature: 30.8 + humidity: 50.5 + - description: Ambience Monitoring Sensors (example 2) - Milesgiht IoT + input: + fPort: 85 + bytes: [0x07, 0x7D, 0xE7, 0x04, 0x08, 0x7D, 0x07, 0x00, 0x09, 0x73, 0x3F, 0x27] + output: + data: + co2: 1255 + tvoc: 7 + pressure: 1004.7 diff --git a/vendor/milesight-iot/am307.js b/vendor/milesight-iot/am307.js new file mode 100644 index 0000000000..385f9d7fe2 --- /dev/null +++ b/vendor/milesight-iot/am307.js @@ -0,0 +1,113 @@ +function decodeUplink(input) { + var res = Decoder(input.bytes, input.fPort); + if (res.error) { + return { + errors: [res.error], + }; + } + return { + data: res, + }; +} +/** + * Payload Decoder for The Things Network + * + * Copyright 2021 Milesight IoT + * + * @product AM307 / AM319 + */ +function Decoder(bytes, port) { + var decoded = {}; + + for (var i = 0; i < bytes.length;) { + var channel_id = bytes[i++]; + var channel_type = bytes[i++]; + // BATTERY + if (channel_id === 0x01 && channel_type === 0x75) { + decoded.battery = bytes[i]; + i += 1; + } + // TEMPERATURE + else if (channel_id === 0x03 && channel_type === 0x67) { + // ℃ + decoded.temperature = readInt16LE(bytes.slice(i, i + 2)) / 10; + i += 2; + + // ℉ + // decoded.temperature = readInt16LE(bytes.slice(i, i + 2)) / 10 * 1.8 + 32; + // i +=2; + } + // HUMIDITY + else if (channel_id === 0x04 && channel_type === 0x68) { + decoded.humidity = bytes[i] / 2; + i += 1; + } + // PIR + else if (channel_id === 0x05 && channel_type === 0x00) { + decoded.pir = bytes[i] === 1 ? "trigger" : "idle"; + i += 1; + } + // LIGHT + else if (channel_id === 0x06 && channel_type === 0xCB) { + decoded.light_level = bytes[i]; + i += 1; + } + // CO2 + else if (channel_id === 0x07 && channel_type === 0x7D) { + decoded.co2 = readUInt16LE(bytes.slice(i, i + 2)); + i += 2; + } + // TVOC + else if (channel_id === 0x08 && channel_type === 0x7D) { + decoded.tvoc = readUInt16LE(bytes.slice(i, i + 2)); + i += 2; + } + // PRESSURE + else if (channel_id === 0x09 && channel_type === 0x73) { + decoded.pressure = readUInt16LE(bytes.slice(i, i + 2)) / 10; + i += 2; + } + // HCHO + else if (channel_id === 0x0A && channel_type === 0x7D) { + decoded.hcho = readUInt16LE(bytes.slice(i, i + 2)) / 100; + i += 2; + } + // PM2.5 + else if (channel_id === 0x0B && channel_type === 0x7D) { + decoded.pm2_5 = readUInt16LE(bytes.slice(i, i + 2)); + i += 2; + } + // PM10 + else if (channel_id === 0x0C && channel_type === 0x7D) { + decoded.pm10 = readUInt16LE(bytes.slice(i, i + 2)); + i += 2; + } + // O3 + else if (channel_id === 0x0D && channel_type === 0x7D) { + decoded.o3 = readUInt16LE(bytes.slice(i, i + 2)) / 100; + i += 2; + } + // BEEP + else if (channel_id === 0x0E && channel_type === 0x01) { + decoded.beep = bytes[i] === 1 ? "yes" : "no"; + i += 1; + } else { + break; + } + } + + return decoded; +} + +/* ****************************************** + * bytes to number + ********************************************/ +function readUInt16LE(bytes) { + var value = (bytes[1] << 8) + bytes[0]; + return value & 0xffff; +} + +function readInt16LE(bytes) { + var ref = readUInt16LE(bytes); + return ref > 0x7fff ? ref - 0x10000 : ref; +} \ No newline at end of file diff --git a/vendor/milesight-iot/am307.png b/vendor/milesight-iot/am307.png new file mode 100644 index 0000000000..c2391bf85e Binary files /dev/null and b/vendor/milesight-iot/am307.png differ diff --git a/vendor/milesight-iot/am307.yaml b/vendor/milesight-iot/am307.yaml new file mode 100644 index 0000000000..779e66b32d --- /dev/null +++ b/vendor/milesight-iot/am307.yaml @@ -0,0 +1,98 @@ +name: Milesight AM307-LoRaWAN Indoor Air Quality Sensor (7 in 1) +description: Milesight AM307 collects various indoor ambience conditions through 7 built-in sensors and delivers the data to the mobile App and its 4.2-inch E-ink screen. It supports batteries or DC power supply and can be easily equipped via NFC. It features a tri-color LED indicator, anti-theft design, and emoticon indication. AM307 is widely used for offices, stores, classrooms, hospitals, etc. + +hardwareVersions: + - version: '1.x' + numeric: 1 + +firmwareVersions: + - version: '1.x' + numeric: 1 + hardwareVersions: + - '1.x' + + profiles: + EU863-870: + id: profile-eu868 + lorawanCertified: true + codec: am307-codec + US902-928: + id: profile-us915 + lorawanCertified: true + codec: am307-codec + AU915-928: + id: profile-au915 + lorawanCertified: true + codec: am307-codec + AS923: + id: profile-as923 + lorawanCertified: true + codec: am307-codec + CN470-510: + id: profile-cn470 + lorawanCertified: true + codec: am307-codec + KR920-923: + id: profile-kr920 + lorawanCertified: true + codec: am307-codec + IN865-867: + id: profile-in865 + lorawanCertified: true + codec: am307-codec + RU864-870: + id: profile-ru864 + lorawanCertified: true + codec: am307-codec + +sensors: + - battery + - temperature + - humidity + - co2 + - tvoc + - pressure + - pir + - light + +dimensions: + width: 22 + length: 100.8 + height: 114 + +battery: + replaceable: true + type: ER14505 + +operatingConditions: + temperature: + min: -20 + max: 60 + + relativeHumidity: + min: 0.1 + max: 0.9 + +ipCode: IP30 + +keyProvisioning: + - custom + - join server +keySecurity: none +productURL: https://www.milesight-iot.com/lorawan/sensor/am300/?utm_source=platform&utm_medium=web&utm_campaign=milesight +dataSheetURL: https://resource.milesight-iot.com/milesight/document/am300-series-datasheet-en.pdf +resellerURLs: + - name: 'iot.sales@milesight.com' + region: + - United States + - European Union + - Canada + url: https://www.alibaba.com/product-detail/AM307-LoRaWan-sensor-Indoor-Air-Quality_1600553894002.html?spm=a2700.galleryofferlist.normal_offer.d_title.1a66757a2WXnF8 + +photos: + main: am307.png + other: + - am307.png + +videos: + main: https://youtu.be/ax-kQnPY3PA diff --git a/vendor/milesight-iot/am307l-codec.yaml b/vendor/milesight-iot/am307l-codec.yaml new file mode 100644 index 0000000000..add0896d7e --- /dev/null +++ b/vendor/milesight-iot/am307l-codec.yaml @@ -0,0 +1,22 @@ +# Uplink decoder decodes binary data uplink into a JSON object +uplinkDecoder: + fileName: am307l.js + examples: + - description: Ambience Monitoring Sensors (example 1) - Milesight IoT + input: + fPort: 85 + bytes: [0x01, 0x75, 0x5C, 0x03, 0x67, 0x34, 0x01, 0x04, 0x68, 0x65, 0x05, 0x6A, 0x49, 0x00] + output: + data: + battery: 92 + temperature: 30.8 + humidity: 50.5 + - description: Ambience Monitoring Sensors (example 2) - Milesgiht IoT + input: + fPort: 85 + bytes: [0x07, 0x7D, 0xE7, 0x04, 0x08, 0x7D, 0x07, 0x00, 0x09, 0x73, 0x3F, 0x27] + output: + data: + co2: 1255 + tvoc: 7 + pressure: 1004.7 diff --git a/vendor/milesight-iot/am307l.js b/vendor/milesight-iot/am307l.js new file mode 100644 index 0000000000..385f9d7fe2 --- /dev/null +++ b/vendor/milesight-iot/am307l.js @@ -0,0 +1,113 @@ +function decodeUplink(input) { + var res = Decoder(input.bytes, input.fPort); + if (res.error) { + return { + errors: [res.error], + }; + } + return { + data: res, + }; +} +/** + * Payload Decoder for The Things Network + * + * Copyright 2021 Milesight IoT + * + * @product AM307 / AM319 + */ +function Decoder(bytes, port) { + var decoded = {}; + + for (var i = 0; i < bytes.length;) { + var channel_id = bytes[i++]; + var channel_type = bytes[i++]; + // BATTERY + if (channel_id === 0x01 && channel_type === 0x75) { + decoded.battery = bytes[i]; + i += 1; + } + // TEMPERATURE + else if (channel_id === 0x03 && channel_type === 0x67) { + // ℃ + decoded.temperature = readInt16LE(bytes.slice(i, i + 2)) / 10; + i += 2; + + // ℉ + // decoded.temperature = readInt16LE(bytes.slice(i, i + 2)) / 10 * 1.8 + 32; + // i +=2; + } + // HUMIDITY + else if (channel_id === 0x04 && channel_type === 0x68) { + decoded.humidity = bytes[i] / 2; + i += 1; + } + // PIR + else if (channel_id === 0x05 && channel_type === 0x00) { + decoded.pir = bytes[i] === 1 ? "trigger" : "idle"; + i += 1; + } + // LIGHT + else if (channel_id === 0x06 && channel_type === 0xCB) { + decoded.light_level = bytes[i]; + i += 1; + } + // CO2 + else if (channel_id === 0x07 && channel_type === 0x7D) { + decoded.co2 = readUInt16LE(bytes.slice(i, i + 2)); + i += 2; + } + // TVOC + else if (channel_id === 0x08 && channel_type === 0x7D) { + decoded.tvoc = readUInt16LE(bytes.slice(i, i + 2)); + i += 2; + } + // PRESSURE + else if (channel_id === 0x09 && channel_type === 0x73) { + decoded.pressure = readUInt16LE(bytes.slice(i, i + 2)) / 10; + i += 2; + } + // HCHO + else if (channel_id === 0x0A && channel_type === 0x7D) { + decoded.hcho = readUInt16LE(bytes.slice(i, i + 2)) / 100; + i += 2; + } + // PM2.5 + else if (channel_id === 0x0B && channel_type === 0x7D) { + decoded.pm2_5 = readUInt16LE(bytes.slice(i, i + 2)); + i += 2; + } + // PM10 + else if (channel_id === 0x0C && channel_type === 0x7D) { + decoded.pm10 = readUInt16LE(bytes.slice(i, i + 2)); + i += 2; + } + // O3 + else if (channel_id === 0x0D && channel_type === 0x7D) { + decoded.o3 = readUInt16LE(bytes.slice(i, i + 2)) / 100; + i += 2; + } + // BEEP + else if (channel_id === 0x0E && channel_type === 0x01) { + decoded.beep = bytes[i] === 1 ? "yes" : "no"; + i += 1; + } else { + break; + } + } + + return decoded; +} + +/* ****************************************** + * bytes to number + ********************************************/ +function readUInt16LE(bytes) { + var value = (bytes[1] << 8) + bytes[0]; + return value & 0xffff; +} + +function readInt16LE(bytes) { + var ref = readUInt16LE(bytes); + return ref > 0x7fff ? ref - 0x10000 : ref; +} \ No newline at end of file diff --git a/vendor/milesight-iot/am307l.png b/vendor/milesight-iot/am307l.png new file mode 100644 index 0000000000..3dd4aac59d Binary files /dev/null and b/vendor/milesight-iot/am307l.png differ diff --git a/vendor/milesight-iot/am307l.yaml b/vendor/milesight-iot/am307l.yaml new file mode 100644 index 0000000000..54f71401ca --- /dev/null +++ b/vendor/milesight-iot/am307l.yaml @@ -0,0 +1,98 @@ +name: Milesight am307l-LoRaWAN Indoor Air Quality Sensor (7 in 1) +description: Milesight am307l collects various indoor ambience conditions through 7 built-in sensors and delivers the data to the mobile App and its 4.2-inch E-ink screen. It supports batteries or DC power supply and can be easily equipped via NFC. It features a tri-color LED indicator, anti-theft design, and emoticon indication. am307l is widely used for offices, stores, classrooms, hospitals, etc. + +hardwareVersions: + - version: '1.x' + numeric: 1 + +firmwareVersions: + - version: '1.x' + numeric: 1 + hardwareVersions: + - '1.x' + + profiles: + EU863-870: + id: profile-eu868 + lorawanCertified: true + codec: am307l-codec + US902-928: + id: profile-us915 + lorawanCertified: true + codec: am307l-codec + AU915-928: + id: profile-au915 + lorawanCertified: true + codec: am307l-codec + AS923: + id: profile-as923 + lorawanCertified: true + codec: am307l-codec + CN470-510: + id: profile-cn470 + lorawanCertified: true + codec: am307l-codec + KR920-923: + id: profile-kr920 + lorawanCertified: true + codec: am307l-codec + IN865-867: + id: profile-in865 + lorawanCertified: true + codec: am307l-codec + RU864-870: + id: profile-ru864 + lorawanCertified: true + codec: am307l-codec + +sensors: + - battery + - temperature + - humidity + - co2 + - tvoc + - pressure + - pir + - light + +dimensions: + width: 22 + length: 100.8 + height: 114 + +battery: + replaceable: true + type: ER14505 + +operatingConditions: + temperature: + min: -20 + max: 60 + + relativeHumidity: + min: 0.1 + max: 0.9 + +ipCode: IP30 + +keyProvisioning: + - custom + - join server +keySecurity: none +productURL: https://www.milesight-iot.com/lorawan/sensor/am300/?utm_source=platform&utm_medium=web&utm_campaign=milesight +dataSheetURL: https://resource.milesight-iot.com/milesight/document/am300-series-datasheet-en.pdf +resellerURLs: + - name: 'iot.sales@milesight.com' + region: + - United States + - European Union + - Canada + url: https://www.alibaba.com/product-detail/AM307-LoRaWan-sensor-Indoor-Air-Quality_1600553894002.html?spm=a2700.galleryofferlist.normal_offer.d_title.1a66757a2WXnF8 + +photos: + main: am307l.png + other: + - am307l.png + +videos: + main: https://youtu.be/ax-kQnPY3PA diff --git a/vendor/milesight-iot/am308-codec.yaml b/vendor/milesight-iot/am308-codec.yaml new file mode 100644 index 0000000000..61c0e9a46b --- /dev/null +++ b/vendor/milesight-iot/am308-codec.yaml @@ -0,0 +1,24 @@ +# Uplink decoder decodes binary data uplink into a JSON object +uplinkDecoder: + fileName: am308.js + examples: + - description: Ambience Monitoring Sensors (example 1) - Milesight IoT + input: + fPort: 85 + bytes: [0x01, 0x75, 0x5C, 0x03, 0x67, 0x34, 0x01, 0x04, 0x68, 0x65, 0x05, 0x6A, 0x49, 0x00] + output: + data: + battery: 92 + temperature: 30.8 + humidity: 50.5 + - description: Ambience Monitoring Sensors (example 2) - Milesgiht IoT + input: + fPort: 85 + bytes: [0x07, 0x7D, 0xE7, 0x04, 0x08, 0x7D, 0x07, 0x00, 0x09, 0x73, 0x3F, 0x27, 0x0B, 0x7D, 0x20, 0x00, 0x0C, 0x7D, 0x30, 0x00] + output: + data: + co2: 1255 + tvoc: 0.07 + pressure: 1004.7 + pm2_5: 32 + pm10: 48 diff --git a/vendor/milesight-iot/am308.js b/vendor/milesight-iot/am308.js new file mode 100644 index 0000000000..cefe947078 --- /dev/null +++ b/vendor/milesight-iot/am308.js @@ -0,0 +1,208 @@ +function decodeUplink(input) { + var res = Decoder(input.bytes, input.fPort); + if (res.error) { + return { + errors: [res.error], + }; + } + return { + data: res, + }; +} +/** + * Payload Decoder for The Things Network + * + * Copyright 2023 Milesight IoT + * + * @product AM307(v2) / AM308(v2) / AM319(v2) + */ +function Decoder(bytes, port) { + return milesight(bytes); +} + +function milesight(bytes) { + var decoded = {}; + + for (var i = 0; i < bytes.length;) { + var channel_id = bytes[i++]; + var channel_type = bytes[i++]; + // BATTERY + if (channel_id === 0x01 && channel_type === 0x75) { + decoded.battery = bytes[i]; + i += 1; + } + // TEMPERATURE + else if (channel_id === 0x03 && channel_type === 0x67) { + // ℃ + decoded.temperature = readInt16LE(bytes.slice(i, i + 2)) / 10; + i += 2; + + // ℉ + // decoded.temperature = readInt16LE(bytes.slice(i, i + 2)) / 10 * 1.8 + 32; + // i +=2; + } + // HUMIDITY + else if (channel_id === 0x04 && channel_type === 0x68) { + decoded.humidity = bytes[i] / 2; + i += 1; + } + // PIR + else if (channel_id === 0x05 && channel_type === 0x00) { + decoded.pir = bytes[i] === 1 ? "trigger" : "idle"; + i += 1; + } + // LIGHT + else if (channel_id === 0x06 && channel_type === 0xcb) { + decoded.light_level = bytes[i]; + i += 1; + } + // CO2 + else if (channel_id === 0x07 && channel_type === 0x7d) { + decoded.co2 = readUInt16LE(bytes.slice(i, i + 2)); + i += 2; + } + // TVOC (iaq) + else if (channel_id === 0x08 && channel_type === 0x7d) { + decoded.tvoc = readUInt16LE(bytes.slice(i, i + 2)) / 100; + i += 2; + } + // TVOC (ug/m3) + else if (channel_id === 0x08 && channel_type === 0xe6) { + decoded.tvoc = readUInt16LE(bytes.slice(i, i + 2)); + i += 2; + } + // PRESSURE + else if (channel_id === 0x09 && channel_type === 0x73) { + decoded.pressure = readUInt16LE(bytes.slice(i, i + 2)) / 10; + i += 2; + } + // HCHO + else if (channel_id === 0x0a && channel_type === 0x7d) { + decoded.hcho = readUInt16LE(bytes.slice(i, i + 2)) / 100; + i += 2; + } + // PM2.5 + else if (channel_id === 0x0b && channel_type === 0x7d) { + decoded.pm2_5 = readUInt16LE(bytes.slice(i, i + 2)); + i += 2; + } + // PM10 + else if (channel_id === 0x0c && channel_type === 0x7d) { + decoded.pm10 = readUInt16LE(bytes.slice(i, i + 2)); + i += 2; + } + // O3 + else if (channel_id === 0x0d && channel_type === 0x7d) { + decoded.o3 = readUInt16LE(bytes.slice(i, i + 2)) / 100; + i += 2; + } + // BEEP + else if (channel_id === 0x0e && channel_type === 0x01) { + decoded.beep = bytes[i] === 1 ? "yes" : "no"; + i += 1; + } + // HISTORY DATA (AM307) + else if (channel_id === 0x20 && channel_type === 0xce) { + var data = {}; + data.timestamp = readUInt32LE(bytes.slice(i, i + 4)); + data.temperature = readInt16LE(bytes.slice(i + 4, i + 6)) / 10; + data.humidity = readUInt16LE(bytes.slice(i + 6, i + 8)) / 2; + data.pir = bytes[i + 8] === 1 ? "trigger" : "idle"; + data.light_level = bytes[i + 9]; + data.co2 = readUInt16LE(bytes.slice(i + 10, i + 12)); + // unit: iaq + data.tvoc = readUInt16LE(bytes.slice(i + 12, i + 14)) / 100; + data.pressure = readUInt16LE(bytes.slice(i + 14, i + 16)) / 10; + i += 16; + + decoded.history = decoded.history || []; + decoded.history.push(data); + } + // HISTORY DATA (AM308) + else if (channel_id === 0x20 && channel_type === 0xce) { + var data = {}; + data.timestamp = readUInt32LE(bytes.slice(i, i + 4)); + data.temperature = readInt16LE(bytes.slice(i + 4, i + 6)) / 10; + data.humidity = readUInt16LE(bytes.slice(i + 6, i + 8)) / 2; + data.pir = bytes[i + 8] === 1 ? "trigger" : "idle"; + data.light_level = bytes[i + 9]; + data.co2 = readUInt16LE(bytes.slice(i + 10, i + 12)); + // unit: iaq + data.tvoc = readUInt16LE(bytes.slice(i + 12, i + 14)) / 100; + data.pressure = readUInt16LE(bytes.slice(i + 14, i + 16)) / 10; + data.pm2_5 = readUInt16LE(bytes.slice(i + 16, i + 18)); + data.pm10 = readUInt16LE(bytes.slice(i + 18, i + 20)); + i += 20; + + decoded.history = decoded.history || []; + decoded.history.push(data); + } + // HISTORY DATA (AM319 CH2O) + else if (channel_id === 0x20 && channel_type === 0xce) { + var data = {}; + data.timestamp = readUInt32LE(bytes.slice(i, i + 4)); + data.temperature = readInt16LE(bytes.slice(i + 4, i + 6)) / 10; + data.humidity = readUInt16LE(bytes.slice(i + 6, i + 8)) / 2; + data.pir = bytes[i + 8] === 1 ? "trigger" : "idle"; + data.light_level = bytes[i + 9]; + data.co2 = readUInt16LE(bytes.slice(i + 10, i + 12)); + // unit: iaq + data.tvoc = readUInt16LE(bytes.slice(i + 12, i + 14)) / 100; + data.pressure = readUInt16LE(bytes.slice(i + 14, i + 16)) / 10; + data.pm2_5 = readUInt16LE(bytes.slice(i + 16, i + 18)); + data.pm10 = readUInt16LE(bytes.slice(i + 18, i + 20)); + data.hcho = readUInt16LE(bytes.slice(i + 20, i + 22)) / 100; + i += 22; + + decoded.history = decoded.history || []; + decoded.history.push(data); + } + // HISTORY DATA (AM319 O3) + else if (channel_id === 0x20 && channel_type === 0xce) { + var data = {}; + data.timestamp = readUInt32LE(bytes.slice(i, i + 4)); + data.temperature = readInt16LE(bytes.slice(i + 4, i + 6)) / 10; + data.humidity = readUInt16LE(bytes.slice(i + 6, i + 8)) / 2; + data.pir = bytes[i + 8] === 1 ? "trigger" : "idle"; + data.light_level = bytes[i + 9]; + data.co2 = readUInt16LE(bytes.slice(i + 10, i + 12)); + // unit: iaq + data.tvoc = readUInt16LE(bytes.slice(i + 12, i + 14)) / 100; + data.pressure = readUInt16LE(bytes.slice(i + 14, i + 16)) / 10; + data.pm2_5 = readUInt16LE(bytes.slice(i + 16, i + 18)); + data.pm10 = readUInt16LE(bytes.slice(i + 18, i + 20)); + data.o3 = readUInt16LE(bytes.slice(i + 20, i + 22)) / 100; + i += 22; + + decoded.history = decoded.history || []; + decoded.history.push(data); + } else { + break; + } + } + + return decoded; +} + +/* ****************************************** + * bytes to number + ********************************************/ +function readUInt16LE(bytes) { + var value = (bytes[1] << 8) + bytes[0]; + return value & 0xffff; +} + +function readInt16LE(bytes) { + var ref = readUInt16LE(bytes); + return ref > 0x7fff ? ref - 0x10000 : ref; +} + +function readUInt32LE(bytes) { + var value = (bytes[3] << 24) + (bytes[2] << 16) + (bytes[1] << 8) + bytes[0]; + return (value & 0xffffffff) >>> 0; +} + +function readInt32LE(bytes) { + var ref = readUInt32LE(bytes); + return ref > 0x7fffffff ? ref - 0x100000000 : ref; +} diff --git a/vendor/milesight-iot/am308.png b/vendor/milesight-iot/am308.png new file mode 100644 index 0000000000..c2391bf85e Binary files /dev/null and b/vendor/milesight-iot/am308.png differ diff --git a/vendor/milesight-iot/am308.yaml b/vendor/milesight-iot/am308.yaml new file mode 100644 index 0000000000..9111f61566 --- /dev/null +++ b/vendor/milesight-iot/am308.yaml @@ -0,0 +1,99 @@ +name: Milesight AM308-LoRaWAN Indoor Air Quality Sensor (7 in 1) +description: Milesight AM308 collects various indoor ambience conditions through 7 built-in sensors and delivers the data to the mobile App and its 4.2-inch E-ink screen. It supports batteries or DC power supply and can be easily equipped via NFC. It features a tri-color LED indicator, anti-theft design, and emoticon indication. am308 is widely used for offices, stores, classrooms, hospitals, etc. + +hardwareVersions: + - version: '1.x' + numeric: 1 + +firmwareVersions: + - version: '1.x' + numeric: 1 + hardwareVersions: + - '1.x' + + profiles: + EU863-870: + id: profile-eu868 + lorawanCertified: true + codec: am308-codec + US902-928: + id: profile-us915 + lorawanCertified: true + codec: am308-codec + AU915-928: + id: profile-au915 + lorawanCertified: true + codec: am308-codec + AS923: + id: profile-as923 + lorawanCertified: true + codec: am308-codec + CN470-510: + id: profile-cn470 + lorawanCertified: true + codec: am308-codec + KR920-923: + id: profile-kr920 + lorawanCertified: true + codec: am308-codec + IN865-867: + id: profile-in865 + lorawanCertified: true + codec: am308-codec + RU864-870: + id: profile-ru864 + lorawanCertified: true + codec: am308-codec + +sensors: + - battery + - temperature + - humidity + - co2 + - tvoc + - pressure + - pir + - light + - pm2.5 + - pm10 + +dimensions: + width: 22 + length: 100.8 + height: 114 + +battery: + replaceable: true + type: ER14505 + +operatingConditions: + temperature: + min: -20 + max: 60 + + relativeHumidity: + min: 0.1 + max: 0.9 + +ipCode: IP30 + +keyProvisioning: + - custom + - join server +keySecurity: none +productURL: https://www.milesight-iot.com/lorawan/sensor/am300/?utm_source=platform&utm_medium=web&utm_campaign=milesight +dataSheetURL: https://resource.milesight-iot.com/milesight/document/am300-series-datasheet-en.pdf +resellerURLs: + - name: 'iot.sales@milesight.com' + region: + - United States + - European Union + - Canada + +photos: + main: am308.png + other: + - am308.png + +videos: + main: https://youtu.be/ax-kQnPY3PA diff --git a/vendor/milesight-iot/am308l-codec.yaml b/vendor/milesight-iot/am308l-codec.yaml new file mode 100644 index 0000000000..aad6f73ab0 --- /dev/null +++ b/vendor/milesight-iot/am308l-codec.yaml @@ -0,0 +1,24 @@ +# Uplink decoder decodes binary data uplink into a JSON object +uplinkDecoder: + fileName: am308l.js + examples: + - description: Ambience Monitoring Sensors (example 1) - Milesight IoT + input: + fPort: 85 + bytes: [0x01, 0x75, 0x5C, 0x03, 0x67, 0x34, 0x01, 0x04, 0x68, 0x65, 0x05, 0x6A, 0x49, 0x00] + output: + data: + battery: 92 + temperature: 30.8 + humidity: 50.5 + - description: Ambience Monitoring Sensors (example 2) - Milesgiht IoT + input: + fPort: 85 + bytes: [0x07, 0x7D, 0xE7, 0x04, 0x08, 0x7D, 0x07, 0x00, 0x09, 0x73, 0x3F, 0x27, 0x0B, 0x7D, 0x20, 0x00, 0x0C, 0x7D, 0x30, 0x00] + output: + data: + co2: 1255 + tvoc: 0.07 + pressure: 1004.7 + pm2_5: 32 + pm10: 48 diff --git a/vendor/milesight-iot/am308l.js b/vendor/milesight-iot/am308l.js new file mode 100644 index 0000000000..cefe947078 --- /dev/null +++ b/vendor/milesight-iot/am308l.js @@ -0,0 +1,208 @@ +function decodeUplink(input) { + var res = Decoder(input.bytes, input.fPort); + if (res.error) { + return { + errors: [res.error], + }; + } + return { + data: res, + }; +} +/** + * Payload Decoder for The Things Network + * + * Copyright 2023 Milesight IoT + * + * @product AM307(v2) / AM308(v2) / AM319(v2) + */ +function Decoder(bytes, port) { + return milesight(bytes); +} + +function milesight(bytes) { + var decoded = {}; + + for (var i = 0; i < bytes.length;) { + var channel_id = bytes[i++]; + var channel_type = bytes[i++]; + // BATTERY + if (channel_id === 0x01 && channel_type === 0x75) { + decoded.battery = bytes[i]; + i += 1; + } + // TEMPERATURE + else if (channel_id === 0x03 && channel_type === 0x67) { + // ℃ + decoded.temperature = readInt16LE(bytes.slice(i, i + 2)) / 10; + i += 2; + + // ℉ + // decoded.temperature = readInt16LE(bytes.slice(i, i + 2)) / 10 * 1.8 + 32; + // i +=2; + } + // HUMIDITY + else if (channel_id === 0x04 && channel_type === 0x68) { + decoded.humidity = bytes[i] / 2; + i += 1; + } + // PIR + else if (channel_id === 0x05 && channel_type === 0x00) { + decoded.pir = bytes[i] === 1 ? "trigger" : "idle"; + i += 1; + } + // LIGHT + else if (channel_id === 0x06 && channel_type === 0xcb) { + decoded.light_level = bytes[i]; + i += 1; + } + // CO2 + else if (channel_id === 0x07 && channel_type === 0x7d) { + decoded.co2 = readUInt16LE(bytes.slice(i, i + 2)); + i += 2; + } + // TVOC (iaq) + else if (channel_id === 0x08 && channel_type === 0x7d) { + decoded.tvoc = readUInt16LE(bytes.slice(i, i + 2)) / 100; + i += 2; + } + // TVOC (ug/m3) + else if (channel_id === 0x08 && channel_type === 0xe6) { + decoded.tvoc = readUInt16LE(bytes.slice(i, i + 2)); + i += 2; + } + // PRESSURE + else if (channel_id === 0x09 && channel_type === 0x73) { + decoded.pressure = readUInt16LE(bytes.slice(i, i + 2)) / 10; + i += 2; + } + // HCHO + else if (channel_id === 0x0a && channel_type === 0x7d) { + decoded.hcho = readUInt16LE(bytes.slice(i, i + 2)) / 100; + i += 2; + } + // PM2.5 + else if (channel_id === 0x0b && channel_type === 0x7d) { + decoded.pm2_5 = readUInt16LE(bytes.slice(i, i + 2)); + i += 2; + } + // PM10 + else if (channel_id === 0x0c && channel_type === 0x7d) { + decoded.pm10 = readUInt16LE(bytes.slice(i, i + 2)); + i += 2; + } + // O3 + else if (channel_id === 0x0d && channel_type === 0x7d) { + decoded.o3 = readUInt16LE(bytes.slice(i, i + 2)) / 100; + i += 2; + } + // BEEP + else if (channel_id === 0x0e && channel_type === 0x01) { + decoded.beep = bytes[i] === 1 ? "yes" : "no"; + i += 1; + } + // HISTORY DATA (AM307) + else if (channel_id === 0x20 && channel_type === 0xce) { + var data = {}; + data.timestamp = readUInt32LE(bytes.slice(i, i + 4)); + data.temperature = readInt16LE(bytes.slice(i + 4, i + 6)) / 10; + data.humidity = readUInt16LE(bytes.slice(i + 6, i + 8)) / 2; + data.pir = bytes[i + 8] === 1 ? "trigger" : "idle"; + data.light_level = bytes[i + 9]; + data.co2 = readUInt16LE(bytes.slice(i + 10, i + 12)); + // unit: iaq + data.tvoc = readUInt16LE(bytes.slice(i + 12, i + 14)) / 100; + data.pressure = readUInt16LE(bytes.slice(i + 14, i + 16)) / 10; + i += 16; + + decoded.history = decoded.history || []; + decoded.history.push(data); + } + // HISTORY DATA (AM308) + else if (channel_id === 0x20 && channel_type === 0xce) { + var data = {}; + data.timestamp = readUInt32LE(bytes.slice(i, i + 4)); + data.temperature = readInt16LE(bytes.slice(i + 4, i + 6)) / 10; + data.humidity = readUInt16LE(bytes.slice(i + 6, i + 8)) / 2; + data.pir = bytes[i + 8] === 1 ? "trigger" : "idle"; + data.light_level = bytes[i + 9]; + data.co2 = readUInt16LE(bytes.slice(i + 10, i + 12)); + // unit: iaq + data.tvoc = readUInt16LE(bytes.slice(i + 12, i + 14)) / 100; + data.pressure = readUInt16LE(bytes.slice(i + 14, i + 16)) / 10; + data.pm2_5 = readUInt16LE(bytes.slice(i + 16, i + 18)); + data.pm10 = readUInt16LE(bytes.slice(i + 18, i + 20)); + i += 20; + + decoded.history = decoded.history || []; + decoded.history.push(data); + } + // HISTORY DATA (AM319 CH2O) + else if (channel_id === 0x20 && channel_type === 0xce) { + var data = {}; + data.timestamp = readUInt32LE(bytes.slice(i, i + 4)); + data.temperature = readInt16LE(bytes.slice(i + 4, i + 6)) / 10; + data.humidity = readUInt16LE(bytes.slice(i + 6, i + 8)) / 2; + data.pir = bytes[i + 8] === 1 ? "trigger" : "idle"; + data.light_level = bytes[i + 9]; + data.co2 = readUInt16LE(bytes.slice(i + 10, i + 12)); + // unit: iaq + data.tvoc = readUInt16LE(bytes.slice(i + 12, i + 14)) / 100; + data.pressure = readUInt16LE(bytes.slice(i + 14, i + 16)) / 10; + data.pm2_5 = readUInt16LE(bytes.slice(i + 16, i + 18)); + data.pm10 = readUInt16LE(bytes.slice(i + 18, i + 20)); + data.hcho = readUInt16LE(bytes.slice(i + 20, i + 22)) / 100; + i += 22; + + decoded.history = decoded.history || []; + decoded.history.push(data); + } + // HISTORY DATA (AM319 O3) + else if (channel_id === 0x20 && channel_type === 0xce) { + var data = {}; + data.timestamp = readUInt32LE(bytes.slice(i, i + 4)); + data.temperature = readInt16LE(bytes.slice(i + 4, i + 6)) / 10; + data.humidity = readUInt16LE(bytes.slice(i + 6, i + 8)) / 2; + data.pir = bytes[i + 8] === 1 ? "trigger" : "idle"; + data.light_level = bytes[i + 9]; + data.co2 = readUInt16LE(bytes.slice(i + 10, i + 12)); + // unit: iaq + data.tvoc = readUInt16LE(bytes.slice(i + 12, i + 14)) / 100; + data.pressure = readUInt16LE(bytes.slice(i + 14, i + 16)) / 10; + data.pm2_5 = readUInt16LE(bytes.slice(i + 16, i + 18)); + data.pm10 = readUInt16LE(bytes.slice(i + 18, i + 20)); + data.o3 = readUInt16LE(bytes.slice(i + 20, i + 22)) / 100; + i += 22; + + decoded.history = decoded.history || []; + decoded.history.push(data); + } else { + break; + } + } + + return decoded; +} + +/* ****************************************** + * bytes to number + ********************************************/ +function readUInt16LE(bytes) { + var value = (bytes[1] << 8) + bytes[0]; + return value & 0xffff; +} + +function readInt16LE(bytes) { + var ref = readUInt16LE(bytes); + return ref > 0x7fff ? ref - 0x10000 : ref; +} + +function readUInt32LE(bytes) { + var value = (bytes[3] << 24) + (bytes[2] << 16) + (bytes[1] << 8) + bytes[0]; + return (value & 0xffffffff) >>> 0; +} + +function readInt32LE(bytes) { + var ref = readUInt32LE(bytes); + return ref > 0x7fffffff ? ref - 0x100000000 : ref; +} diff --git a/vendor/milesight-iot/am308l.png b/vendor/milesight-iot/am308l.png new file mode 100644 index 0000000000..3dd4aac59d Binary files /dev/null and b/vendor/milesight-iot/am308l.png differ diff --git a/vendor/milesight-iot/am308l.yaml b/vendor/milesight-iot/am308l.yaml new file mode 100644 index 0000000000..231163d399 --- /dev/null +++ b/vendor/milesight-iot/am308l.yaml @@ -0,0 +1,99 @@ +name: Milesight AM308-LoRaWAN Indoor Air Quality Sensor (7 in 1) +description: Milesight AM308 collects various indoor ambience conditions through 7 built-in sensors and delivers the data to the mobile App and its 4.2-inch E-ink screen. It supports batteries or DC power supply and can be easily equipped via NFC. It features a tri-color LED indicator, anti-theft design, and emoticon indication. am308 is widely used for offices, stores, classrooms, hospitals, etc. + +hardwareVersions: + - version: '1.x' + numeric: 1 + +firmwareVersions: + - version: '1.x' + numeric: 1 + hardwareVersions: + - '1.x' + + profiles: + EU863-870: + id: profile-eu868 + lorawanCertified: true + codec: am308l-codec + US902-928: + id: profile-us915 + lorawanCertified: true + codec: am308l-codec + AU915-928: + id: profile-au915 + lorawanCertified: true + codec: am308l-codec + AS923: + id: profile-as923 + lorawanCertified: true + codec: am308l-codec + CN470-510: + id: profile-cn470 + lorawanCertified: true + codec: am308l-codec + KR920-923: + id: profile-kr920 + lorawanCertified: true + codec: am308l-codec + IN865-867: + id: profile-in865 + lorawanCertified: true + codec: am308l-codec + RU864-870: + id: profile-ru864 + lorawanCertified: true + codec: am308l-codec + +sensors: + - battery + - temperature + - humidity + - co2 + - tvoc + - pressure + - pir + - light + - pm2.5 + - pm10 + +dimensions: + width: 22 + length: 100.8 + height: 114 + +battery: + replaceable: true + type: ER14505 + +operatingConditions: + temperature: + min: -20 + max: 60 + + relativeHumidity: + min: 0.1 + max: 0.9 + +ipCode: IP30 + +keyProvisioning: + - custom + - join server +keySecurity: none +productURL: https://www.milesight-iot.com/lorawan/sensor/am300/?utm_source=platform&utm_medium=web&utm_campaign=milesight +dataSheetURL: https://resource.milesight-iot.com/milesight/document/am300-series-datasheet-en.pdf +resellerURLs: + - name: 'iot.sales@milesight.com' + region: + - United States + - European Union + - Canada + +photos: + main: am308l.png + other: + - am308l.png + +videos: + main: https://youtu.be/ax-kQnPY3PA diff --git a/vendor/milesight-iot/am319-codec.yaml b/vendor/milesight-iot/am319-codec.yaml new file mode 100644 index 0000000000..9f1d76831f --- /dev/null +++ b/vendor/milesight-iot/am319-codec.yaml @@ -0,0 +1,60 @@ +# Uplink decoder decodes binary data uplink into a JSON object +uplinkDecoder: + fileName: am319.js + + examples: + - description: Ambience Monitoring Sensors (example 1) - Milesight IoT + input: + fPort: 85 + bytes: + [ + 0x03, + 0x67, + 0x34, + 0x01, + 0x04, + 0x68, + 0x65, + 0x05, + 0x00, + 0x01, + 0x06, + 0xCB, + 0x02, + 0x07, + 0x7D, + 0xA8, + 0x03, + 0x08, + 0x7D, + 0x25, + 0x00, + 0x09, + 0x73, + 0x66, + 0x27, + 0x0A, + 0x7D, + 0x04, + 0x00, + 0x0B, + 0x7D, + 0x20, + 0x00, + 0x0C, + 0x7D, + 0x30, + 0x00, + ] + output: + data: + temperature: 30.8 + humidity: 50.5 + activity: 'trigger' + light_level: 2 + co2: 936 + tvoc: 37 + pressure: 1008.6 + hcho: 0.04 + pm2.5: 32 + pm10: 48 diff --git a/vendor/milesight-iot/am319.js b/vendor/milesight-iot/am319.js new file mode 100644 index 0000000000..d2595fa562 --- /dev/null +++ b/vendor/milesight-iot/am319.js @@ -0,0 +1,113 @@ +function decodeUplink(input) { + var res = Decoder(input.bytes, input.fPort); + if (res.error) { + return { + errors: [res.error], + }; + } + return { + data: res, + }; +} +/** + * Payload Decoder for The Things Network + * + * Copyright 2021 Milesight IoT + * + * @product AM307 / AM319 + */ +function Decoder(bytes, port) { + var decoded = {}; + + for (var i = 0; i < bytes.length;) { + var channel_id = bytes[i++]; + var channel_type = bytes[i++]; + // BATTERY + if (channel_id === 0x01 && channel_type === 0x75) { + decoded.battery = bytes[i]; + i += 1; + } + // TEMPERATURE + else if (channel_id === 0x03 && channel_type === 0x67) { + // ℃ + decoded.temperature = readInt16LE(bytes.slice(i, i + 2)) / 10; + i += 2; + + // ℉ + // decoded.temperature = readInt16LE(bytes.slice(i, i + 2)) / 10 * 1.8 + 32; + // i +=2; + } + // HUMIDITY + else if (channel_id === 0x04 && channel_type === 0x68) { + decoded.humidity = bytes[i] / 2; + i += 1; + } + // ACTIVITY + else if (channel_id === 0x05 && channel_type === 0x00) { + decoded.activity = bytes[i] === 1 ? "trigger" : "idle"; + i += 1; + } + // LIGHT + else if (channel_id === 0x06 && channel_type === 0xCB) { + decoded.light_level = bytes[i]; + i += 1; + } + // CO2 + else if (channel_id === 0x07 && channel_type === 0x7D) { + decoded.co2 = readUInt16LE(bytes.slice(i, i + 2)); + i += 2; + } + // TVOC + else if (channel_id === 0x08 && channel_type === 0x7D) { + decoded.tvoc = readUInt16LE(bytes.slice(i, i + 2)); + i += 2; + } + // PRESSURE + else if (channel_id === 0x09 && channel_type === 0x73) { + decoded.pressure = readUInt16LE(bytes.slice(i, i + 2)) / 10; + i += 2; + } + // HCHO + else if (channel_id === 0x0A && channel_type === 0x7D) { + decoded.hcho = readUInt16LE(bytes.slice(i, i + 2)) / 100; + i += 2; + } + // PM2.5 + else if (channel_id === 0x0B && channel_type === 0x7D) { + decoded["pm2.5"] = readUInt16LE(bytes.slice(i, i + 2)); + i += 2; + } + // PM10 + else if (channel_id === 0x0C && channel_type === 0x7D) { + decoded.pm10 = readUInt16LE(bytes.slice(i, i + 2)); + i += 2; + } + // O3 + else if (channel_id === 0x0D && channel_type === 0x7D) { + decoded.o3 = readUInt16LE(bytes.slice(i, i + 2)) / 100; + i += 2; + } + // BEEP + else if (channel_id === 0x0E && channel_type === 0x01) { + decoded.beep = bytes[i] === 1 ? "yes" : "no"; + i += 1; + } else { + break; + } + } + + return decoded; +} + +/* ****************************************** + * bytes to number + ********************************************/ +function readUInt16LE(bytes) { + var value = (bytes[1] << 8) + bytes[0]; + return value & 0xffff; +} + +function readInt16LE(bytes) { + var ref = readUInt16LE(bytes); + return ref > 0x7fff ? ref - 0x10000 : ref; +} \ No newline at end of file diff --git a/vendor/milesight-iot/am319.png b/vendor/milesight-iot/am319.png new file mode 100644 index 0000000000..2ec183c6a6 Binary files /dev/null and b/vendor/milesight-iot/am319.png differ diff --git a/vendor/milesight-iot/am319.yaml b/vendor/milesight-iot/am319.yaml new file mode 100644 index 0000000000..19e9f551bb --- /dev/null +++ b/vendor/milesight-iot/am319.yaml @@ -0,0 +1,97 @@ +name: Milesight AM319-LoRaWAN Indoor Air Quality Sensor (9 in 1) +description: Milesight AM309 collects various indoor ambience conditions through 9 built-in sensors and delivers the data to the mobile App and its 4.2-inch E-ink screen. It supports batteries or DC power supply and can be easily equipped via NFC. It features a tri-color LED indicator, anti-theft design, and emoticon indication. AM307 is widely used for offices, stores, classrooms, hospitals, etc. + +hardwareVersions: + - version: '1.x' + numeric: 1 + +firmwareVersions: + - version: '1.x' + numeric: 1 + hardwareVersions: + - '1.x' + + profiles: + EU863-870: + id: profile-eu868 + lorawanCertified: true + codec: am319-codec + US902-928: + id: profile-us915 + lorawanCertified: true + codec: am319-codec + AU915-928: + id: profile-au915 + lorawanCertified: true + codec: am319-codec + AS923: + id: profile-as923 + lorawanCertified: true + codec: am319-codec + CN470-510: + id: profile-cn470 + lorawanCertified: true + codec: am319-codec + KR920-923: + id: profile-kr920 + lorawanCertified: true + codec: am319-codec + IN865-867: + id: profile-in865 + lorawanCertified: true + codec: am319-codec + RU864-870: + id: profile-ru864 + lorawanCertified: true + codec: am319-codec + +sensors: + - temperature + - humidity + - co2 + - tvoc + - pressure + - pir + - light + - pm2.5 + - pm10 + # hcho + - o3 + +dimensions: + width: 22 + length: 100.8 + height: 114 + +operatingConditions: + temperature: + min: -20 + max: 60 + + relativeHumidity: + min: 0.1 + max: 0.9 + +ipCode: IP30 + +keyProvisioning: + - custom + - join server +keySecurity: none +productURL: https://www.milesight-iot.com/lorawan/sensor/am300/?utm_source=platform&utm_medium=web&utm_campaign=milesight +dataSheetURL: https://resource.milesight-iot.com/milesight/document/am300-series-datasheet-en.pdf +resellerURLs: + - name: 'iot.sales@milesight.com' + region: + - United States + - European Union + - Canada + url: https://www.alibaba.com/product-detail/Milesight-AM319-LoRaWAN-Sensor-indoor-ambience_1600336362534.html?spm=a2700.galleryofferlist.normal_offer.d_title.c54f1672nliIa5 + +photos: + main: am319.png + other: + - am319.png + +videos: + main: https://youtu.be/ax-kQnPY3PA diff --git a/vendor/milesight-iot/am319l-codec.yaml b/vendor/milesight-iot/am319l-codec.yaml new file mode 100644 index 0000000000..bbfb7ea861 --- /dev/null +++ b/vendor/milesight-iot/am319l-codec.yaml @@ -0,0 +1,60 @@ +# Uplink decoder decodes binary data uplink into a JSON object +uplinkDecoder: + fileName: am319l.js + + examples: + - description: Ambience Monitoring Sensors (example 1) - Milesight IoT + input: + fPort: 85 + bytes: + [ + 0x03, + 0x67, + 0x34, + 0x01, + 0x04, + 0x68, + 0x65, + 0x05, + 0x00, + 0x01, + 0x06, + 0xCB, + 0x02, + 0x07, + 0x7D, + 0xA8, + 0x03, + 0x08, + 0x7D, + 0x25, + 0x00, + 0x09, + 0x73, + 0x66, + 0x27, + 0x0A, + 0x7D, + 0x04, + 0x00, + 0x0B, + 0x7D, + 0x20, + 0x00, + 0x0C, + 0x7D, + 0x30, + 0x00, + ] + output: + data: + temperature: 30.8 + humidity: 50.5 + activity: 'trigger' + light_level: 2 + co2: 936 + tvoc: 37 + pressure: 1008.6 + hcho: 0.04 + pm2.5: 32 + pm10: 48 diff --git a/vendor/milesight-iot/am319l.js b/vendor/milesight-iot/am319l.js new file mode 100644 index 0000000000..d2595fa562 --- /dev/null +++ b/vendor/milesight-iot/am319l.js @@ -0,0 +1,113 @@ +function decodeUplink(input) { + var res = Decoder(input.bytes, input.fPort); + if (res.error) { + return { + errors: [res.error], + }; + } + return { + data: res, + }; +} +/** + * Payload Decoder for The Things Network + * + * Copyright 2021 Milesight IoT + * + * @product AM307 / AM319 + */ +function Decoder(bytes, port) { + var decoded = {}; + + for (var i = 0; i < bytes.length;) { + var channel_id = bytes[i++]; + var channel_type = bytes[i++]; + // BATTERY + if (channel_id === 0x01 && channel_type === 0x75) { + decoded.battery = bytes[i]; + i += 1; + } + // TEMPERATURE + else if (channel_id === 0x03 && channel_type === 0x67) { + // ℃ + decoded.temperature = readInt16LE(bytes.slice(i, i + 2)) / 10; + i += 2; + + // ℉ + // decoded.temperature = readInt16LE(bytes.slice(i, i + 2)) / 10 * 1.8 + 32; + // i +=2; + } + // HUMIDITY + else if (channel_id === 0x04 && channel_type === 0x68) { + decoded.humidity = bytes[i] / 2; + i += 1; + } + // ACTIVITY + else if (channel_id === 0x05 && channel_type === 0x00) { + decoded.activity = bytes[i] === 1 ? "trigger" : "idle"; + i += 1; + } + // LIGHT + else if (channel_id === 0x06 && channel_type === 0xCB) { + decoded.light_level = bytes[i]; + i += 1; + } + // CO2 + else if (channel_id === 0x07 && channel_type === 0x7D) { + decoded.co2 = readUInt16LE(bytes.slice(i, i + 2)); + i += 2; + } + // TVOC + else if (channel_id === 0x08 && channel_type === 0x7D) { + decoded.tvoc = readUInt16LE(bytes.slice(i, i + 2)); + i += 2; + } + // PRESSURE + else if (channel_id === 0x09 && channel_type === 0x73) { + decoded.pressure = readUInt16LE(bytes.slice(i, i + 2)) / 10; + i += 2; + } + // HCHO + else if (channel_id === 0x0A && channel_type === 0x7D) { + decoded.hcho = readUInt16LE(bytes.slice(i, i + 2)) / 100; + i += 2; + } + // PM2.5 + else if (channel_id === 0x0B && channel_type === 0x7D) { + decoded["pm2.5"] = readUInt16LE(bytes.slice(i, i + 2)); + i += 2; + } + // PM10 + else if (channel_id === 0x0C && channel_type === 0x7D) { + decoded.pm10 = readUInt16LE(bytes.slice(i, i + 2)); + i += 2; + } + // O3 + else if (channel_id === 0x0D && channel_type === 0x7D) { + decoded.o3 = readUInt16LE(bytes.slice(i, i + 2)) / 100; + i += 2; + } + // BEEP + else if (channel_id === 0x0E && channel_type === 0x01) { + decoded.beep = bytes[i] === 1 ? "yes" : "no"; + i += 1; + } else { + break; + } + } + + return decoded; +} + +/* ****************************************** + * bytes to number + ********************************************/ +function readUInt16LE(bytes) { + var value = (bytes[1] << 8) + bytes[0]; + return value & 0xffff; +} + +function readInt16LE(bytes) { + var ref = readUInt16LE(bytes); + return ref > 0x7fff ? ref - 0x10000 : ref; +} \ No newline at end of file diff --git a/vendor/milesight-iot/am319l.png b/vendor/milesight-iot/am319l.png new file mode 100644 index 0000000000..3dd4aac59d Binary files /dev/null and b/vendor/milesight-iot/am319l.png differ diff --git a/vendor/milesight-iot/am319l.yaml b/vendor/milesight-iot/am319l.yaml new file mode 100644 index 0000000000..496398c22b --- /dev/null +++ b/vendor/milesight-iot/am319l.yaml @@ -0,0 +1,97 @@ +name: Milesight AM319-LoRaWAN Indoor Air Quality Sensor (9 in 1) +description: Milesight AM309 collects various indoor ambience conditionsam308 through 9 built-in sensors and delivers the data to the mobile App and its 4.2-inch E-ink screen. It supports batteries or DC power supply and can be easily equipped via NFC. It features a tri-color LED indicator, anti-theft design, and emoticon indication. AM307 is widely used for offices, stores, classrooms, hospitals, etc. + +hardwareVersions: + - version: '1.x' + numeric: 1 + +firmwareVersions: + - version: '1.x' + numeric: 1 + hardwareVersions: + - '1.x' + + profiles: + EU863-870: + id: profile-eu868 + lorawanCertified: true + codec: am319l-codec + US902-928: + id: profile-us915 + lorawanCertified: true + codec: am319l-codec + AU915-928: + id: profile-au915 + lorawanCertified: true + codec: am319l-codec + AS923: + id: profile-as923 + lorawanCertified: true + codec: am319l-codec + CN470-510: + id: profile-cn470 + lorawanCertified: true + codec: am319l-codec + KR920-923: + id: profile-kr920 + lorawanCertified: true + codec: am319l-codec + IN865-867: + id: profile-in865 + lorawanCertified: true + codec: am319l-codec + RU864-870: + id: profile-ru864 + lorawanCertified: true + codec: am319l-codec + +sensors: + - temperature + - humidity + - co2 + - tvoc + - pressure + - pir + - light + - pm2.5 + - pm10 + # hcho + - o3 + +dimensions: + width: 22 + length: 100.8 + height: 114 + +operatingConditions: + temperature: + min: -20 + max: 60 + + relativeHumidity: + min: 0.1 + max: 0.9 + +ipCode: IP30 + +keyProvisioning: + - custom + - join server +keySecurity: none +productURL: https://www.milesight-iot.com/lorawan/sensor/am300/?utm_source=platform&utm_medium=web&utm_campaign=milesight +dataSheetURL: https://resource.milesight-iot.com/milesight/document/am300-series-datasheet-en.pdf +resellerURLs: + - name: 'iot.sales@milesight.com' + region: + - United States + - European Union + - Canada + url: https://www.alibaba.com/product-detail/Milesight-AM319-LoRaWAN-Sensor-indoor-ambience_1600336362534.html?spm=a2700.galleryofferlist.normal_offer.d_title.c54f1672nliIa5 + +photos: + main: am319l.png + other: + - am319l.png + +videos: + main: https://youtu.be/ax-kQnPY3PA diff --git a/vendor/milesight-iot/em300-di-codec.yaml b/vendor/milesight-iot/em300-di-codec.yaml new file mode 100644 index 0000000000..c8e2929b2e --- /dev/null +++ b/vendor/milesight-iot/em300-di-codec.yaml @@ -0,0 +1,15 @@ +# Uplink decoder decodes binary data uplink into a JSON object (optional) +# For documentation on writing encoders and decoders, see: https://thethingsstack.io/integrations/payload-formatters/javascript/ +uplinkDecoder: + fileName: em300-di.js + + examples: + - description: LoRaWAN® Pulse Counter - Milesight IoT + input: + fPort: 85 + bytes: [0x01, 0x75, 0x5C, 0x05, 0xc8, 0x00, 0x01, 0x00, 0x00] + + output: + data: + battery: 92 + pulse: 256 diff --git a/vendor/milesight-iot/em300-di.js b/vendor/milesight-iot/em300-di.js new file mode 100644 index 0000000000..a87813d2cc --- /dev/null +++ b/vendor/milesight-iot/em300-di.js @@ -0,0 +1,103 @@ +function decodeUplink(input) { + var res = Decoder(input.bytes, input.fPort); + if (res.error) { + return { + errors: [res.error], + }; + } + return { + data: res, + }; +} + +/** + * Payload Decoder for The Things Network + * + * Copyright 2023 Milesight IoT + * + * @product EM300-DI + */ +function Decoder(bytes, port) { + return milesight(bytes); +} + +function milesight(bytes) { + var decoded = {}; + + for (var i = 0; i < bytes.length;) { + var channel_id = bytes[i++]; + var channel_type = bytes[i++]; + + // BATTERY + if (channel_id === 0x01 && channel_type === 0x75) { + decoded.battery = bytes[i]; + i += 1; + } + // TEMPERATURE + else if (channel_id === 0x03 && channel_type === 0x67) { + // ℃ + decoded.temperature = readInt16LE(bytes.slice(i, i + 2)) / 10; + i += 2; + + // ℉ + // decoded.temperature = readInt16LE(bytes.slice(i, i + 2)) / 10 * 1.8 + 32; + // i +=2; + } + // HUMIDITY + else if (channel_id === 0x04 && channel_type === 0x68) { + decoded.humidity = bytes[i] / 2; + i += 1; + } + // GPIO + else if (channel_id === 0x05 && channel_type === 0x00) { + decoded.gpio = bytes[i]; + i += 1; + } + // PULSE COUNTER + else if (channel_id === 0x05 && channel_type === 0xc8) { + decoded.pulse = readUInt32LE(bytes.slice(i, i + 4)); + i += 4; + } + // HISTROY + else if (channel_id === 0x20 && channel_type === 0xce) { + // maybe not historical raw data + if (bytes.slice(i).length < 12) break; + + var point = {}; + point.timestamp = readUInt32LE(bytes.slice(i, i + 4)); + point.temperature = readInt16LE(bytes.slice(i + 4, i + 6)) / 10; + point.humidity = bytes[i + 6] / 2; + var mode = bytes[i + 7]; + if (mode === 1) { + point.gpio = bytes[i + 8]; + } else if (mode === 2) { + point.pulse = readUInt32LE(bytes.slice(i + 9, i + 13)); + } + decoded.history = decoded.history || []; + decoded.history.push(point); + i += 13; + } else { + break; + } + } + + return decoded; +} + +/* ****************************************** + * bytes to number + ********************************************/ +function readUInt16LE(bytes) { + var value = (bytes[1] << 8) + bytes[0]; + return value & 0xffff; +} + +function readInt16LE(bytes) { + var ref = readUInt16LE(bytes); + return ref > 0x7fff ? ref - 0x10000 : ref; +} + +function readUInt32LE(bytes) { + var value = (bytes[3] << 24) + (bytes[2] << 16) + (bytes[1] << 8) + bytes[0]; + return (value & 0xffffffff) >>> 0; +} diff --git a/vendor/milesight-iot/em300-di.png b/vendor/milesight-iot/em300-di.png new file mode 100644 index 0000000000..cc4e212867 Binary files /dev/null and b/vendor/milesight-iot/em300-di.png differ diff --git a/vendor/milesight-iot/em300-di.yaml b/vendor/milesight-iot/em300-di.yaml new file mode 100644 index 0000000000..224b82c8cd --- /dev/null +++ b/vendor/milesight-iot/em300-di.yaml @@ -0,0 +1,85 @@ +name: EM300-DI +description: EM300-DI LoRaWAN® Pulse Counter is used to remotely read metering data from water meters. It turns existing traditional water meters into smart meters via LoRaWAN® network which further enables easier management and increases the efficiency of water use. + +hardwareVersions: + - version: 'V2.2' + numeric: 1 + +firmwareVersions: + - version: '1.15' + numeric: 1 + hardwareVersions: + - 'V2.2' + + profiles: + EU863-870: + id: profile-eu868 + codec: em300-di-codec + US902-928: + id: profile-us915 + codec: em300-di-codec + AU915-928: + id: profile-au915 + codec: em300-di-codec + AS923: + id: profile-as923 + codec: em300-di-codec + CN470-510: + id: profile-cn470 + codec: em300-di-codec + KR920-923: + id: profile-kr920 + codec: em300-di-codec + IN865-867: + id: profile-in865 + codec: em300-di-codec + RU864-870: + id: profile-ru864 + codec: em300-di-codec + +sensors: + - battery + - pulse count +# 4-20 ma, accelerometer, altitude, analog input, auxiliary, barometer, battery, button, bvoc, co, co2, conductivity, +# current, digital input, dissolved oxygen, distance, dust, energy, gps, gyroscope, h2s, humidity, iaq, level, light, +# lightning, link, magnetometer, moisture, motion, no, no2, o3, particulate matter, ph, pir, pm2.5, pm10, potentiometer, +# power, precipitation, pressure, proximity, pulse count, pulse frequency, radar, rainfall, rssi, smart valve, snr, so2, +# solar radiation, sound, strain, surface temperature, temperature, tilt, time, tvoc, uv, vapor pressure, velocity, +# vibration, voltage, water potential, water, weight, wifi ssid, wind direction, wind speed. + +dimensions: + width: 27 + length: 88 + height: 87 + +battery: + replaceable: true + type: ER18505 Li-SoCl2 battery + +operatingConditions: + temperature: + min: -30 + max: 70 + + relativeHumidity: + min: 0 + max: 1.00 + +ipCode: IP67 + +keyProvisioning: + - custom + - join server +keySecurity: none +productURL: https://www.milesight-iot.com/products/lorawan-sensor/em300-di/ +dataSheetURL: https://resource.milesight-iot.com/milesight/document/em300-di-datasheet-en.pdf +resellerURLs: + - name: 'iot.sales@milesight.com' + region: + - United States + - European Union + - Canada + url: https://www.milesight-iot.com/contact-us/ + +photos: + main: em300-di.png diff --git a/vendor/milesight-iot/em300-mcs.js b/vendor/milesight-iot/em300-mcs.js index 6a8a09868e..26da8b5f14 100644 --- a/vendor/milesight-iot/em300-mcs.js +++ b/vendor/milesight-iot/em300-mcs.js @@ -1,6 +1,6 @@ function Decoder(bytes, port) { var decoded = {}; - + for (var i = 0; i < bytes.length;) { var channel_id = bytes[i++]; var channel_type = bytes[i++]; diff --git a/vendor/milesight-iot/em300-mld-codec.yaml b/vendor/milesight-iot/em300-mld-codec.yaml new file mode 100644 index 0000000000..66ed40e182 --- /dev/null +++ b/vendor/milesight-iot/em300-mld-codec.yaml @@ -0,0 +1,22 @@ +# Uplink decoder decodes binary data uplink into a JSON object (optional) +# For documentation on writing encoders and decoders, see: https://thethingsstack.io/integrations/payload-formatters/javascript/ +uplinkDecoder: + fileName: em300-mld.js + examples: + - description: LoRaWAN leak sensor that incorporatesaflexible printed membrane - Milesight IoT + input: + fPort: 85 + bytes: [0x01, 0x75, 0x5C, 0x05, 0x00, 0x00] + output: + data: + battery: 92 + leakage_status: normal + + - description: LoRaWAN leak sensor that incorporatesaflexible printed membrane - Milesight IoT + input: + fPort: 85 + bytes: [0x01, 0x75, 0x5C, 0x05, 0x00, 0x01] + output: + data: + battery: 92 + leakage_status: leak diff --git a/vendor/milesight-iot/em300-mld.js b/vendor/milesight-iot/em300-mld.js new file mode 100644 index 0000000000..b6095f8e38 --- /dev/null +++ b/vendor/milesight-iot/em300-mld.js @@ -0,0 +1,73 @@ +function decodeUplink(input) { + var res = Decoder(input.bytes, input.fPort); + if (res.error) { + return { + errors: [res.error], + }; + } + return { + data: res, + }; +} + +/** + * Payload Decoder for The Things Network + * + * Copyright 2023 Milesight IoT + * + * @product EM300-MLD + */ +function Decoder(bytes, port) { + return milesight(bytes); +} + +function milesight(bytes) { + var decoded = {}; + + for (var i = 0; i < bytes.length;) { + var channel_id = bytes[i++]; + var channel_type = bytes[i++]; + // BATTERY + if (channel_id === 0x01 && channel_type === 0x75) { + decoded.battery = bytes[i]; + i += 1; + } + // LEAKAGE STATUS + else if (channel_id === 0x05 && channel_type === 0x00) { + decoded.leakage_status = bytes[i] === 0 ? "normal" : "leak"; + i += 1; + } + // TEMPERATURE, HUMIDITY & LEAKAGE STATUS HISTROY + else if (channel_id === 0x20 && channel_type === 0xce) { + var point = {}; + point.timestamp = readUInt32LE(bytes.slice(i, i + 4)); + point.leakage_status = bytes[i + 7] === 0 ? "normal" : "leak"; + + decoded.history = decoded.history || []; + decoded.history.push(point); + i += 8; + } else { + break; + } + } + + return decoded; +} + +/* ****************************************** + * bytes to number + ********************************************/ +function readUInt16LE(bytes) { + var value = (bytes[1] << 8) + bytes[0]; + return value & 0xffff; +} + +function readInt16LE(bytes) { + var ref = readUInt16LE(bytes); + return ref > 0x7fff ? ref - 0x10000 : ref; +} + +function readUInt32LE(bytes) { + var value = (bytes[3] << 24) + (bytes[2] << 16) + (bytes[1] << 8) + bytes[0]; + return (value & 0xffffffff) >>> 0; +} diff --git a/vendor/milesight-iot/em300-mld.png b/vendor/milesight-iot/em300-mld.png new file mode 100644 index 0000000000..e1651e519e Binary files /dev/null and b/vendor/milesight-iot/em300-mld.png differ diff --git a/vendor/milesight-iot/em300-mld.yaml b/vendor/milesight-iot/em300-mld.yaml new file mode 100644 index 0000000000..017da51542 --- /dev/null +++ b/vendor/milesight-iot/em300-mld.yaml @@ -0,0 +1,101 @@ +name: em300-mld +description: The EM300-MLD is an innovative LoRaWAN leak sensor that incorporatesaflexible printed membrane + +hardwareVersions: + - version: 'V3.0' + numeric: 1 + +firmwareVersions: + - version: '1.07' + numeric: 1 + hardwareVersions: + - 'V3.0' + + profiles: + EU863-870: + id: profile-eu868 + codec: em300-mld-codec + US902-928: + id: profile-us915 + codec: em300-mld-codec + AU915-928: + id: profile-au915 + codec: em300-mld-codec + AS923: + id: profile-as923 + codec: em300-mld-codec + CN470-510: + id: profile-cn470 + codec: em300-mld-codec + KR920-923: + id: profile-kr920 + codec: em300-mld-codec + IN865-867: + id: profile-in865 + codec: em300-mld-codec + RU864-870: + id: profile-ru864 + codec: em300-mld-codec + +sensors: + - battery + - water + +# 4-20 ma, accelerometer, altitude, analog input, auxiliary, barometer, battery, button, bvoc, co, co2, conductivity, +# current, digital input, dissolved oxygen, distance, dust, energy, gps, gyroscope, h2s, humidity, iaq, level, light, +# lightning, link, magnetometer, moisture, motion, no, no2, o3, particulate matter, ph, pir, pm2.5, pm10, potentiometer, +# power, precipitation, pressure, proximity, pulse count, pulse frequency, radar, rainfall, rssi, smart valve, snr, so2, +# solar radiation, sound, strain, surface temperature, temperature, tilt, time, tvoc, uv, vapor pressure, velocity, +# vibration, voltage, water potential, water, weight, wifi ssid, wind direction, wind speed. + +dimensions: + width: 105.6 + length: 85.3 + height: 27 + +battery: + replaceable: true + type: ER18505 Li-SoCl2 battery + +operatingConditions: + temperature: + min: -30 + max: 70 + + relativeHumidity: + min: 0 + max: 0.95 + +ipCode: IP67 + +keyProvisioning: + - custom + - join server +keySecurity: none +productURL: https://www.milesight.com/iot/product/lorawan-sensor/em300-mld +dataSheetURL: https://resource.milesight.com/milesight/iot/document/em300-mld-datasheet-en.pdf +resellerURLs: + - name: 'iot.sales@milesight.com' + region: + - United States + - European Union + - Canada + url: https://www.milesight-iot.com/contact-us/ + +photos: + main: em300-mld.png + +compliances: + safety: + - body: IEC + norm: EN + standard: 62368-1 + radioEquipment: + - body: ETSI + norm: EN + standard: 301 489-1 + version: 2.2.0 + - body: ETSI + norm: EN + standard: 301 489-3 + version: 2.1.0 diff --git a/vendor/milesight-iot/em300-sld-codec.yaml b/vendor/milesight-iot/em300-sld-codec.yaml new file mode 100644 index 0000000000..435b1bcffe --- /dev/null +++ b/vendor/milesight-iot/em300-sld-codec.yaml @@ -0,0 +1,19 @@ +# Uplink decoder decodes binary data uplink into a JSON object (optional) +# For documentation on writing encoders and decoders, see: https://thethingsstack.io/integrations/payload-formatters/javascript/ +uplinkDecoder: + fileName: em300-sld.js + examples: + - description: Spot Leakage Detection Sensor (example 1) - Milesgiht IoT + input: + fPort: 85 + bytes: [0x05, 0x00, 0x00] + output: + data: + water: normal + - description: Spot Leakage Detection Sensor (example 2) - Milesgiht IoT + input: + fPort: 85 + bytes: [0x05, 0x00, 0x01] + output: + data: + water: leak diff --git a/vendor/milesight-iot/em300-sld.js b/vendor/milesight-iot/em300-sld.js new file mode 100644 index 0000000000..82edaf9bbd --- /dev/null +++ b/vendor/milesight-iot/em300-sld.js @@ -0,0 +1,68 @@ +function decodeUplink(input) { + var res = Decoder(input.bytes, input.fPort); + if (res.error) { + return { + errors: [res.error], + }; + } + return { + data: res, + }; +} +/** + * Payload Decoder for The Things Network + * + * Copyright 2021 Milesight IoT + * + * @product EM300-SLD / EM300-ZLD + */ +function Decoder(bytes, port) { + var decoded = {}; + + for (var i = 0; i < bytes.length;) { + var channel_id = bytes[i++]; + var channel_type = bytes[i++]; + // BATTERY + if (channel_id === 0x01 && channel_type === 0x75) { + decoded.battery = bytes[i]; + i += 1; + } + // TEMPERATURE + else if (channel_id === 0x03 && channel_type === 0x67) { + // ℃ + decoded.temperature = readInt16LE(bytes.slice(i, i + 2)) / 10; + i += 2; + + // ℉ + // decoded.temperature = readInt16LE(bytes.slice(i, i + 2)) / 10 * 1.8 + 32; + // i +=2; + } + // HUMIDITY + else if (channel_id === 0x04 && channel_type === 0x68) { + decoded.humidity = bytes[i] / 2; + i += 1; + } + // WATER LEAK + else if (channel_id === 0x05 && channel_type === 0x00) { + decoded.water = (bytes[i] === 0) ? 'normal' : 'leak'; + i += 1; + } else { + break; + } + } + + return decoded; +} + +/* ****************************************** + * bytes to number + ********************************************/ +function readUInt16LE(bytes) { + var value = (bytes[1] << 8) + bytes[0]; + return value & 0xffff; +} + +function readInt16LE(bytes) { + var ref = readUInt16LE(bytes); + return ref > 0x7fff ? ref - 0x10000 : ref; +} \ No newline at end of file diff --git a/vendor/milesight-iot/em300-sld.png b/vendor/milesight-iot/em300-sld.png new file mode 100644 index 0000000000..6d691fd08c Binary files /dev/null and b/vendor/milesight-iot/em300-sld.png differ diff --git a/vendor/milesight-iot/em300-sld.yaml b/vendor/milesight-iot/em300-sld.yaml new file mode 100644 index 0000000000..59f3d7eb9c --- /dev/null +++ b/vendor/milesight-iot/em300-sld.yaml @@ -0,0 +1,114 @@ +name: Mileisght EM300-SLD Spot Leak Detection +description: Milesight EM300-SLD can detect the presence of liquids with a small, high-precision water probe. Besides, EM300-SLD integrates temperature and humidity sensors. It features a long battery life of up to 5 years, an IP67 UV-resistant and waterproof enclosure, and can be easily configured via NFC. Combining with Milesight LoRaWAN® gateway and Milesight IoT Cloud solution, users can manage all sensor data remotely and visually and receive alarms via mobile APP. + +hardwareVersions: + - version: '2.x' + numeric: 1 + - version: '3.x' + numeric: 2 + +firmwareVersions: + - version: '1.x' + numeric: 1 + hardwareVersions: + - '2.x' + + profiles: + EU863-870: + id: profile-eu868 + codec: em300-sld-codec + US902-928: + id: profile-us915 + codec: em300-sld-codec + AU915-928: + id: profile-au915 + codec: em300-sld-codec + AS923: + id: profile-as923 + codec: em300-sld-codec + CN470-510: + id: profile-cn470 + codec: em300-sld-codec + KR920-923: + id: profile-kr920 + codec: em300-sld-codec + IN865-867: + id: profile-in865 + codec: em300-sld-codec + RU864-870: + id: profile-ru864 + codec: em300-sld-codec + + - version: '1.x' + numeric: 2 + hardwareVersions: + - '3.x' + + profiles: + EU863-870: + id: profile-eu868 + codec: em300-sld-codec + US902-928: + id: profile-us915 + codec: em300-sld-codec + AU915-928: + id: profile-au915 + codec: em300-sld-codec + AS923: + id: profile-as923 + codec: em300-sld-codec + CN470-510: + id: profile-cn470 + codec: em300-sld-codec + KR920-923: + id: profile-kr920 + codec: em300-sld-codec + IN865-867: + id: profile-in865 + codec: em300-sld-codec + RU864-870: + id: profile-ru864 + codec: em300-sld-codec + +sensors: + - battery + - temperature + - humidity + - water + +dimensions: + width: 85.3 + length: 27 + height: 105.6 + +battery: + replaceable: true + type: ER18505 Li-SoCl2 battery + +operatingConditions: + temperature: + min: -30 + max: 70 + + relativeHumidity: + min: 0 + max: 1.00 + +ipCode: IP67 + +keyProvisioning: + - custom + - join server +keySecurity: none +productURL: https://www.milesight-iot.com/lorawan/sensor/em300-sldzld/?utm_source=platform&utm_medium=web&utm_campaign=milesight +dataSheetURL: https://resource.milesight-iot.com/milesight/document/em300-sld-datasheet-en.pdf +resellerURLs: + - name: 'iot.sales@milesight.com' + region: + - United States + - European Union + - Canada + url: https://www.alibaba.com/product-detail/EM300-SLD-Standard-Leak-Detection-LoRa_1600200005425.html?spm=a2700.galleryofferlist.normal_offer.d_title.e08998a2B03eI6 + +photos: + main: em300-sld.png diff --git a/vendor/milesight-iot/em300-th.js b/vendor/milesight-iot/em300-th.js index 5d9cedc2fe..33ae310161 100644 --- a/vendor/milesight-iot/em300-th.js +++ b/vendor/milesight-iot/em300-th.js @@ -37,7 +37,7 @@ function Decoder(bytes, port) { } - + else { diff --git a/vendor/milesight-iot/em300-zld-codec.yaml b/vendor/milesight-iot/em300-zld-codec.yaml new file mode 100644 index 0000000000..ad7f0b2060 --- /dev/null +++ b/vendor/milesight-iot/em300-zld-codec.yaml @@ -0,0 +1,19 @@ +# Uplink decoder decodes binary data uplink into a JSON object (optional) +# For documentation on writing encoders and decoders, see: https://thethingsstack.io/integrations/payload-formatters/javascript/ +uplinkDecoder: + fileName: em300-zld.js + examples: + - description: Zone Leakage Detection Sensor (example 1) - Milesgiht IoT + input: + fPort: 85 + bytes: [0x05, 0x00, 0x00] + output: + data: + water: normal + - description: Zone Leakage Detection Sensor (example 2) - Milesgiht IoT + input: + fPort: 85 + bytes: [0x05, 0x00, 0x01] + output: + data: + water: leak diff --git a/vendor/milesight-iot/em300-zld.js b/vendor/milesight-iot/em300-zld.js new file mode 100644 index 0000000000..82edaf9bbd --- /dev/null +++ b/vendor/milesight-iot/em300-zld.js @@ -0,0 +1,68 @@ +function decodeUplink(input) { + var res = Decoder(input.bytes, input.fPort); + if (res.error) { + return { + errors: [res.error], + }; + } + return { + data: res, + }; +} +/** + * Payload Decoder for The Things Network + * + * Copyright 2021 Milesight IoT + * + * @product EM300-SLD / EM300-ZLD + */ +function Decoder(bytes, port) { + var decoded = {}; + + for (var i = 0; i < bytes.length;) { + var channel_id = bytes[i++]; + var channel_type = bytes[i++]; + // BATTERY + if (channel_id === 0x01 && channel_type === 0x75) { + decoded.battery = bytes[i]; + i += 1; + } + // TEMPERATURE + else if (channel_id === 0x03 && channel_type === 0x67) { + // ℃ + decoded.temperature = readInt16LE(bytes.slice(i, i + 2)) / 10; + i += 2; + + // ℉ + // decoded.temperature = readInt16LE(bytes.slice(i, i + 2)) / 10 * 1.8 + 32; + // i +=2; + } + // HUMIDITY + else if (channel_id === 0x04 && channel_type === 0x68) { + decoded.humidity = bytes[i] / 2; + i += 1; + } + // WATER LEAK + else if (channel_id === 0x05 && channel_type === 0x00) { + decoded.water = (bytes[i] === 0) ? 'normal' : 'leak'; + i += 1; + } else { + break; + } + } + + return decoded; +} + +/* ****************************************** + * bytes to number + ********************************************/ +function readUInt16LE(bytes) { + var value = (bytes[1] << 8) + bytes[0]; + return value & 0xffff; +} + +function readInt16LE(bytes) { + var ref = readUInt16LE(bytes); + return ref > 0x7fff ? ref - 0x10000 : ref; +} \ No newline at end of file diff --git a/vendor/milesight-iot/em300-zld.png b/vendor/milesight-iot/em300-zld.png new file mode 100644 index 0000000000..f608aaeadf Binary files /dev/null and b/vendor/milesight-iot/em300-zld.png differ diff --git a/vendor/milesight-iot/em300-zld.yaml b/vendor/milesight-iot/em300-zld.yaml new file mode 100644 index 0000000000..fc26c00a21 --- /dev/null +++ b/vendor/milesight-iot/em300-zld.yaml @@ -0,0 +1,114 @@ +name: Milesight EM300-ZLD Zone Leak Detection +description: Milesight EM300-ZLD can detect a large area presence of water by a long cable with high precision. Besides, EM300-ZLD integrates temperature and humidity sensors. It features a long battery life of up to 5 years, an IP67 UV-resistant and waterproof enclosure, and can be easily configured via NFC. Combining with Milesight LoRaWAN® gateway and Milesight IoT Cloud solution, users can manage all sensor data remotely and visually and receive alarms via mobile APP. + +hardwareVersions: + - version: '2.x' + numeric: 1 + - version: '3.x' + numeric: 2 + +firmwareVersions: + - version: '1.x' + numeric: 1 + hardwareVersions: + - '2.x' + + profiles: + EU863-870: + id: profile-eu868 + codec: em300-zld-codec + US902-928: + id: profile-us915 + codec: em300-zld-codec + AU915-928: + id: profile-au915 + codec: em300-zld-codec + AS923: + id: profile-as923 + codec: em300-zld-codec + CN470-510: + id: profile-cn470 + codec: em300-zld-codec + KR920-923: + id: profile-kr920 + codec: em300-zld-codec + IN865-867: + id: profile-in865 + codec: em300-zld-codec + RU864-870: + id: profile-ru864 + codec: em300-zld-codec + + - version: '1.x' + numeric: 2 + hardwareVersions: + - '3.x' + + profiles: + EU863-870: + id: profile-eu868 + codec: em300-sld-codec + US902-928: + id: profile-us915 + codec: em300-sld-codec + AU915-928: + id: profile-au915 + codec: em300-sld-codec + AS923: + id: profile-as923 + codec: em300-sld-codec + CN470-510: + id: profile-cn470 + codec: em300-sld-codec + KR920-923: + id: profile-kr920 + codec: em300-sld-codec + IN865-867: + id: profile-in865 + codec: em300-sld-codec + RU864-870: + id: profile-ru864 + codec: em300-sld-codec + +sensors: + - battery + - temperature + - humidity + - water + +dimensions: + width: 85.3 + length: 27 + height: 105.6 + +battery: + replaceable: true + type: ER18505 + +operatingConditions: + temperature: + min: -30 + max: 70 + + relativeHumidity: + min: 0 + max: 1.00 + +ipCode: IP67 + +keyProvisioning: + - custom + - join server +keySecurity: none +productURL: https://www.milesight-iot.com/lorawan/sensor/em300-sldzld/?utm_source=platform&utm_medium=web&utm_campaign=milesight +dataSheetURL: https://resource.milesight-iot.com/milesight/document/em300-zld-datasheet-en.pdf +resellerURLs: + - name: 'iot.sales@milesight.com' + region: + - United States + - European Union + - Canada + url: https://www.alibaba.com/product-detail/EM300-ZLD-Standard-Leak-Detection-LoRa_1600200045246.html?spm=a2700.galleryofferlist.normal_offer.d_title.21b92633X3bAoK&s=p + +photos: + main: em300-zld.png diff --git a/vendor/milesight-iot/em310-tilt-codec.yaml b/vendor/milesight-iot/em310-tilt-codec.yaml new file mode 100644 index 0000000000..725e2688f1 --- /dev/null +++ b/vendor/milesight-iot/em310-tilt-codec.yaml @@ -0,0 +1,4 @@ +# Uplink decoder decodes binary data uplink into a JSON object (optional) +# For documentation on writing encoders and decoders, see: https://thethingsstack.io/integrations/payload-formatters/javascript/ +uplinkDecoder: + fileName: em310-tilt.js diff --git a/vendor/milesight-iot/em310-tilt.js b/vendor/milesight-iot/em310-tilt.js new file mode 100644 index 0000000000..76fd24a2ae --- /dev/null +++ b/vendor/milesight-iot/em310-tilt.js @@ -0,0 +1,63 @@ +function decodeUplink(input) { + var res = Decoder(input.bytes, input.fPort); + if (res.error) { + return { + errors: [res.error], + }; + } + return { + data: res, + }; +} +/** + * Payload Decoder for The Things Network + * + * Copyright 2023 Milesight IoT + * + * @product EM310-TILT + */ +function Decoder(bytes, port) { + return milesight(bytes); +} + +function milesight(bytes) { + var decoded = {}; + + for (var i = 0; i < bytes.length;) { + var channel_id = bytes[i++]; + var channel_type = bytes[i++]; + + // BATTERY + if (channel_id === 0x01 && channel_type === 0x75) { + decoded.battery = bytes[i]; + i += 1; + } + // ANGLE + else if (channel_id === 0x03 && channel_type === 0xcf) { + decoded.angle_x = readInt16LE(bytes.slice(i, i + 2)) / 100; + decoded.angle_y = readInt16LE(bytes.slice(i + 2, i + 4)) / 100; + decoded.angle_z = readInt16LE(bytes.slice(i + 4, i + 6)) / 100; + decoded.threshold_x = (bytes[i + 6] & 1) === 1 ? "trigger" : "normal"; + decoded.threshold_y = ((bytes[i + 6] >> 1) & 1) === 1 ? "trigger" : "normal"; + decoded.threshold_z = ((bytes[i + 6] >> 2) & 1) === 1 ? "trigger" : "normal"; + i += 7; + } else { + break; + } + } + + return decoded; +} + +/* ****************************************** + * bytes to number + ********************************************/ +function readUInt16LE(bytes) { + var value = (bytes[1] << 8) + bytes[0]; + return value & 0xffff; +} + +function readInt16LE(bytes) { + var ref = readUInt16LE(bytes); + return ref > 0x7fff ? ref - 0x10000 : ref; +} diff --git a/vendor/milesight-iot/em310-tilt.png b/vendor/milesight-iot/em310-tilt.png new file mode 100644 index 0000000000..810c52701b Binary files /dev/null and b/vendor/milesight-iot/em310-tilt.png differ diff --git a/vendor/milesight-iot/em310-tilt.yaml b/vendor/milesight-iot/em310-tilt.yaml new file mode 100644 index 0000000000..430b6c7da8 --- /dev/null +++ b/vendor/milesight-iot/em310-tilt.yaml @@ -0,0 +1,101 @@ +name: Tilt Sensor +description: Milesight EM310 LoRaWAN® tilt sensor makes only the settings of a relative initial surface and angle threshold are needed, and the X, Y, Z tilt angles can be leveraged to know object status accurately in real time, straightforward and effortless. + +hardwareVersions: + - version: 'V1.0' + numeric: 1 + +firmwareVersions: + - version: '1.02' + numeric: 1 + hardwareVersions: + - 'V1.0' + + profiles: + EU863-870: + id: profile-eu868 + codec: em310-tilt-codec + US902-928: + id: profile-us915 + codec: em310-tilt-codec + AU915-928: + id: profile-au915 + codec: em310-tilt-codec + AS923: + id: profile-as923 + codec: em310-tilt-codec + CN470-510: + id: profile-cn470 + codec: em310-tilt-codec + KR920-923: + id: profile-kr920 + codec: em310-tilt-codec + IN865-867: + id: profile-in865 + codec: em310-tilt-codec + RU864-870: + id: profile-ru864 + codec: em310-tilt-codec + +sensors: + - battery + - tilt + +# 4-20 ma, accelerometer, altitude, analog input, auxiliary, barometer, battery, button, bvoc, co, co2, conductivity, +# current, digital input, dissolved oxygen, distance, dust, energy, gps, gyroscope, h2s, humidity, iaq, level, light, +# lightning, link, magnetometer, moisture, motion, no, no2, o3, particulate matter, ph, pir, pm2.5, pm10, potentiometer, +# power, precipitation, pressure, proximity, pulse count, pulse frequency, radar, rainfall, rssi, smart valve, snr, so2, +# solar radiation, sound, strain, surface temperature, temperature, tilt, time, tvoc, uv, vapor pressure, velocity, +# vibration, voltage, water potential, water, weight, wifi ssid, wind direction, wind speed. + +dimensions: + width: 111 + length: 62 + height: 33 + +battery: + replaceable: true + type: ER17505 Li-SoCl2 battery *2 + +operatingConditions: + temperature: + min: -20 + max: 60 + + relativeHumidity: + min: 0 + max: 0.95 + +ipCode: IP67 + +keyProvisioning: + - custom + - join server +keySecurity: none +productURL: https://www.milesight-iot.com/lorawan/sensor/em310-tilt/ +dataSheetURL: https://resource.milesight-iot.com/milesight/document/em310-tilt-datasheet-en.pdf +resellerURLs: + - name: 'iot.sales@milesight.com' + region: + - United States + - European Union + - Canada + url: https://www.milesight-iot.com/contact-us/ + +photos: + main: em310-tilt.png + +compliances: + safety: + - body: IEC + norm: EN + standard: 62368-1 + radioEquipment: + - body: ETSI + norm: EN + standard: 301 489-1 + version: 2.2.0 + - body: ETSI + norm: EN + standard: 301 489-3 + version: 2.1.0 diff --git a/vendor/milesight-iot/em310-udl-codec.yaml b/vendor/milesight-iot/em310-udl-codec.yaml new file mode 100644 index 0000000000..c898930124 --- /dev/null +++ b/vendor/milesight-iot/em310-udl-codec.yaml @@ -0,0 +1,14 @@ +# Uplink decoder decodes binary data uplink into a JSON object (optional) +# For documentation on writing encoders and decoders, see: https://thethingsstack.io/integrations/payload-formatters/javascript/ +uplinkDecoder: + fileName: em310-udl.js + examples: + - description: Ultrasonic Distance/Level Sensor (example 1) - Milesgiht IoT + input: + fPort: 85 + bytes: [0x01, 0x75, 0x5C, 0x03, 0x82, 0x44, 0x08, 0x04, 0x00, 0x01] + output: + data: + battery: 92 + distance: 2116 + tilt: 'tilt' diff --git a/vendor/milesight-iot/em310-udl.js b/vendor/milesight-iot/em310-udl.js new file mode 100644 index 0000000000..e1a3794a60 --- /dev/null +++ b/vendor/milesight-iot/em310-udl.js @@ -0,0 +1,58 @@ +function decodeUplink(input) { + var res = Decoder(input.bytes, input.fPort); + if (res.error) { + return { + errors: [res.error], + }; + } + return { + data: res, + }; +} +/** + * Payload Decoder for The Things Network + * + * Copyright 2021 Milesight IoT + * + * @product EM310-UDL + */ +function Decoder(bytes, port) { + var decoded = {}; + + for (var i = 0; i < bytes.length;) { + var channel_id = bytes[i++]; + var channel_type = bytes[i++]; + // BATTERY + if (channel_id === 0x01 && channel_type === 0x75) { + decoded.battery = bytes[i]; + i += 1; + } + // DISTANCE + else if (channel_id === 0x03 && channel_type === 0x82) { + decoded.distance = readUInt16LE(bytes.slice(i, i + 2)); + i += 2; + } + // TILT + else if (channel_id === 0x04 && channel_type === 0x00) { + decoded.tilt = bytes[i] === 0 ? "normal" : "tilt"; + i += 1; + } else { + break; + } + } + + return decoded; +} + +/* ****************************************** + * bytes to number + ********************************************/ +function readUInt16LE(bytes) { + var value = (bytes[1] << 8) + bytes[0]; + return value & 0xffff; +} + +function readInt16LE(bytes) { + var ref = readUInt16LE(bytes); + return ref > 0x7fff ? ref - 0x10000 : ref; +} \ No newline at end of file diff --git a/vendor/milesight-iot/em310-udl.png b/vendor/milesight-iot/em310-udl.png new file mode 100644 index 0000000000..d09c174f2a Binary files /dev/null and b/vendor/milesight-iot/em310-udl.png differ diff --git a/vendor/milesight-iot/em310-udl.yaml b/vendor/milesight-iot/em310-udl.yaml new file mode 100644 index 0000000000..2bbcf6f86e --- /dev/null +++ b/vendor/milesight-iot/em310-udl.yaml @@ -0,0 +1,80 @@ +name: Milesigt EM310-UDL Ultrasonic Distance Sensor +description: Milesight EM310-UDL is an ultrasonic sensor featuring a short blind zone and Wide Measuring Range. Besides, EM310-UDL equips with a 3-axis accelerometer to detect the status of the container cover. Compliant with Milesight LoRaWAN® gateway and Milesight IoT Cloud solution, users can know the container status and fill-in level in real-time via browser or mobile App remotely. It's widely used in waste management, manhole cover monitoring, parking lot monitoring, etc. + +hardwareVersions: + - version: '1.x' + numeric: 1 + +firmwareVersions: + - version: '1.x' + numeric: 1 + hardwareVersions: + - '1.x' + + profiles: + EU863-870: + id: profile-eu868 + codec: em310-udl-codec + US902-928: + id: profile-us915 + codec: em310-udl-codec + AU915-928: + id: profile-au915 + codec: em310-udl-codec + AS923: + id: profile-as923 + codec: em310-udl-codec + CN470-510: + id: profile-cn470 + codec: em310-udl-codec + KR920-923: + id: profile-kr920 + codec: em310-udl-codec + IN865-867: + id: profile-in865 + codec: em310-udl-codec + RU864-870: + id: profile-ru864 + codec: em310-udl-codec + +sensors: + - battery + - distance + # position + +dimensions: + width: 62 + length: 40 + height: 111 + +battery: + replaceable: true + type: ER17505 + +operatingConditions: + temperature: + min: -15 + max: 60 + + relativeHumidity: + min: 0 + max: 0.9 + +ipCode: IP67 + +keyProvisioning: + - custom + - join server +keySecurity: none +productURL: https://www.milesight-iot.com/lorawan/sensor/em310-udl/?utm_source=platform&utm_medium=web&utm_campaign=milesight +dataSheetURL: https://resource.milesight-iot.com/milesight/document/em310-udl-datasheet-en.pdf +resellerURLs: + - name: 'iot.sales@milesight.com' + region: + - United States + - European Union + - Canada + url: https://www.alibaba.com/product-detail/Milesight-EM310-UDL-LoRaWAN-Ultrasonic-Distance_1600350016037.html?spm=a2700.galleryofferlist.normal_offer.d_title.be403298QsPdeI + +photos: + main: em310-udl.png diff --git a/vendor/milesight-iot/em320-th-codec.yaml b/vendor/milesight-iot/em320-th-codec.yaml new file mode 100644 index 0000000000..c5fb2d8161 --- /dev/null +++ b/vendor/milesight-iot/em320-th-codec.yaml @@ -0,0 +1,16 @@ +# Uplink decoder decodes binary data uplink into a JSON object (optional) +# For documentation on writing encoders and decoders, see: https://thethingsstack.io/integrations/payload-formatters/javascript/ +uplinkDecoder: + fileName: em320-th.js + + examples: + - description: Temperature & Humidity Sensor - Milesight IoT + input: + fPort: 85 + bytes: [0x01, 0x75, 0x5C, 0x03, 0x67, 0x34, 0x01, 0x04, 0x68, 0x65] + + output: + data: + battery: 92 + humidity: 50.5 + temperature: 30.8 diff --git a/vendor/milesight-iot/em320-th.js b/vendor/milesight-iot/em320-th.js new file mode 100644 index 0000000000..2650bf8b99 --- /dev/null +++ b/vendor/milesight-iot/em320-th.js @@ -0,0 +1,83 @@ +function decodeUplink(input) { + var res = Decoder(input.bytes, input.fPort); + if (res.error) { + return { + errors: [res.error], + }; + } + return { + data: res, + }; +} +/** + * Payload Decoder for The Things Network + * + * Copyright 2023 Milesight IoT + * + * @product EM320-TH + */ +function Decoder(bytes, port) { + return milesight(bytes); +} + +function milesight(bytes) { + var decoded = {}; + + for (var i = 0; i < bytes.length;) { + var channel_id = bytes[i++]; + var channel_type = bytes[i++]; + + // BATTERY + if (channel_id === 0x01 && channel_type === 0x75) { + decoded.battery = bytes[i]; + i += 1; + } + // TEMPERATURE + else if (channel_id === 0x03 && channel_type === 0x67) { + // ℃ + decoded.temperature = readInt16LE(bytes.slice(i, i + 2)) / 10; + i += 2; + + // ℉ + // decoded.temperature = readInt16LE(bytes.slice(i, i + 2)) / 10 * 1.8 + 32; + // i +=2; + } + // HUMIDITY + else if (channel_id === 0x04 && channel_type === 0x68) { + decoded.humidity = bytes[i] / 2; + i += 1; + } + // TEMPERATURE & HUMIDITY HISTROY + else if (channel_id === 0x20 && channel_type === 0xce) { + var point = {}; + point.timestamp = readUInt32LE(bytes.slice(i, i + 4)); + point.temperature = readInt16LE(bytes.slice(i + 4, i + 6)) / 10; + point.humidity = bytes[i + 6] / 2; + decoded.history = decoded.history || []; + decoded.history.push(point); + i += 7; + } else { + break; + } + } + + return decoded; +} + +/* ****************************************** + * bytes to number + ********************************************/ +function readUInt16LE(bytes) { + var value = (bytes[1] << 8) + bytes[0]; + return value & 0xffff; +} + +function readInt16LE(bytes) { + var ref = readUInt16LE(bytes); + return ref > 0x7fff ? ref - 0x10000 : ref; +} + +function readUInt32LE(bytes) { + var value = (bytes[3] << 24) + (bytes[2] << 16) + (bytes[1] << 8) + bytes[0]; + return (value & 0xffffffff) >>> 0; +} diff --git a/vendor/milesight-iot/em320-th.png b/vendor/milesight-iot/em320-th.png new file mode 100644 index 0000000000..a41cf7bc13 Binary files /dev/null and b/vendor/milesight-iot/em320-th.png differ diff --git a/vendor/milesight-iot/em320-th.yaml b/vendor/milesight-iot/em320-th.yaml new file mode 100644 index 0000000000..1ae4929ade --- /dev/null +++ b/vendor/milesight-iot/em320-th.yaml @@ -0,0 +1,102 @@ +name: Temperature & Humidity Sensor +description: EM320-TH is a LoRaWAN®-based device for precise temperature and humidity monitoring. + +hardwareVersions: + - version: 'V1.0' + numeric: 1 + +firmwareVersions: + - version: '1.02' + numeric: 1 + hardwareVersions: + - 'V1.0' + + profiles: + EU863-870: + id: profile-eu868 + codec: em320-th-codec + US902-928: + id: profile-us915 + codec: em320-th-codec + AU915-928: + id: profile-au915 + codec: em320-th-codec + AS923: + id: profile-as923 + codec: em320-th-codec + CN470-510: + id: profile-cn470 + codec: em320-th-codec + KR920-923: + id: profile-kr920 + codec: em320-th-codec + IN865-867: + id: profile-in865 + codec: em320-th-codec + RU864-870: + id: profile-ru864 + codec: em320-th-codec + +sensors: + - battery + - temperature + - humidity + +# 4-20 ma, accelerometer, altitude, analog input, auxiliary, barometer, battery, button, bvoc, co, co2, conductivity, +# current, digital input, dissolved oxygen, distance, dust, energy, gps, gyroscope, h2s, humidity, iaq, level, light, +# lightning, link, magnetometer, moisture, motion, no, no2, o3, particulate matter, ph, pir, pm2.5, pm10, potentiometer, +# power, precipitation, pressure, proximity, pulse count, pulse frequency, radar, rainfall, rssi, smart valve, snr, so2, +# solar radiation, sound, strain, surface temperature, temperature, tilt, time, tvoc, uv, vapor pressure, velocity, +# vibration, voltage, water potential, water, weight, wifi ssid, wind direction, wind speed. + +dimensions: + width: 18 + length: 58 + height: 85 + +battery: + replaceable: true + type: ER14505 Li-SoCl2 battery*2 + +operatingConditions: + temperature: + min: -30 + max: 60 + + relativeHumidity: + min: 0 + max: 0.95 + +ipCode: IP67 + +keyProvisioning: + - custom + - join server +keySecurity: none +productURL: https://www.milesight-iot.com/products/lorawan-sensor/em320-th/ +dataSheetURL: https://resource.milesight-iot.com/milesight/document/em320-th-datasheet-en.pdf +resellerURLs: + - name: 'iot.sales@milesight.com' + region: + - United States + - European Union + - Canada + url: https://www.milesight-iot.com/contact-us/ + +photos: + main: em320-th.png + +compliances: + safety: + - body: IEC + norm: EN + standard: 62368-1 + radioEquipment: + - body: ETSI + norm: EN + standard: 301 489-1 + version: 2.2.0 + - body: ETSI + norm: EN + standard: 301 489-3 + version: 2.1.0 diff --git a/vendor/milesight-iot/em320-tilt-codec.yaml b/vendor/milesight-iot/em320-tilt-codec.yaml new file mode 100644 index 0000000000..af650b0d83 --- /dev/null +++ b/vendor/milesight-iot/em320-tilt-codec.yaml @@ -0,0 +1,20 @@ +# Uplink decoder decodes binary data uplink into a JSON object (optional) +# For documentation on writing encoders and decoders, see: https://thethingsstack.io/integrations/payload-formatters/javascript/ +uplinkDecoder: + fileName: em320-tilt.js + + examples: + - description: Temperature & Humidity Sensor - Milesight IoT + input: + fPort: 85 + bytes: [0x01, 0x75, 0x5C, 0x03, 0xD4, 0x00, 0x00, 0x01, 0x00, 0x50, 0x46] + + output: + data: + battery: 92 + angle_x: 0 + angle_y: 0 + angle_z: 90 + threshold_x: normal + threshold_y: trigger + threshold_z: normal diff --git a/vendor/milesight-iot/em320-tilt.js b/vendor/milesight-iot/em320-tilt.js new file mode 100644 index 0000000000..476924a681 --- /dev/null +++ b/vendor/milesight-iot/em320-tilt.js @@ -0,0 +1,63 @@ +function decodeUplink(input) { + var res = Decoder(input.bytes, input.fPort); + if (res.error) { + return { + errors: [res.error], + }; + } + return { + data: res, + }; +} +/** + * Payload Decoder for The Things Network + * + * Copyright 2023 Milesight IoT + * + * @product EM320-TILT + */ +function Decoder(bytes, port) { + return milesight(bytes); +} + +function milesight(bytes) { + var decoded = {}; + + for (var i = 0; i < bytes.length;) { + var channel_id = bytes[i++]; + var channel_type = bytes[i++]; + + // BATTERY + if (channel_id === 0x01 && channel_type === 0x75) { + decoded.battery = bytes[i]; + i += 1; + } + // ANGLE + else if (channel_id === 0x03 && channel_type === 0xd4) { + decoded.angle_x = (readInt16LE(bytes.slice(i, i + 2)) >> 1) / 100; + decoded.angle_y = (readInt16LE(bytes.slice(i + 2, i + 4)) >> 1) / 100; + decoded.angle_z = (readInt16LE(bytes.slice(i + 4, i + 6)) >> 1) / 100; + decoded.threshold_x = (bytes[i] & 0x01) === 0x01 ? "trigger" : "normal"; + decoded.threshold_y = (bytes[i + 2] & 0x01) === 0x01 ? "trigger" : "normal"; + decoded.threshold_z = (bytes[i + 4] & 0x01) === 0x01 ? "trigger" : "normal"; + i += 6; + } else { + break; + } + } + + return decoded; +} + +/* ****************************************** + * bytes to number + ********************************************/ +function readUInt16LE(bytes) { + var value = (bytes[1] << 8) + bytes[0]; + return value & 0xffff; +} + +function readInt16LE(bytes) { + var ref = readUInt16LE(bytes); + return ref > 0x7fff ? ref - 0x10000 : ref; +} diff --git a/vendor/milesight-iot/em320-tilt.png b/vendor/milesight-iot/em320-tilt.png new file mode 100644 index 0000000000..49a453069d Binary files /dev/null and b/vendor/milesight-iot/em320-tilt.png differ diff --git a/vendor/milesight-iot/em320-tilt.yaml b/vendor/milesight-iot/em320-tilt.yaml new file mode 100644 index 0000000000..825e82016f --- /dev/null +++ b/vendor/milesight-iot/em320-tilt.yaml @@ -0,0 +1,102 @@ +name: Tilt Sensor +description: EM320-TILT is an LoRaWAN® tilt sensor mainly for angle measurementand asset movement detection + +hardwareVersions: + - version: 'V1.0' + numeric: 1 + +firmwareVersions: + - version: '1.02' + numeric: 1 + hardwareVersions: + - 'V1.0' + + profiles: + EU863-870: + id: profile-eu868 + codec: em320-tilt-codec + US902-928: + id: profile-us915 + codec: em320-tilt-codec + AU915-928: + id: profile-au915 + codec: em320-tilt-codec + AS923: + id: profile-as923 + codec: em320-tilt-codec + CN470-510: + id: profile-cn470 + codec: em320-tilt-codec + KR920-923: + id: profile-kr920 + codec: em320-tilt-codec + IN865-867: + id: profile-in865 + codec: em320-tilt-codec + RU864-870: + id: profile-ru864 + codec: em320-tilt-codec + +sensors: + - battery + - tilt + - accelerometer + +# 4-20 ma, accelerometer, altitude, analog input, auxiliary, barometer, battery, button, bvoc, co, co2, conductivity, +# current, digital input, dissolved oxygen, distance, dust, energy, gps, gyroscope, h2s, humidity, iaq, level, light, +# lightning, link, magnetometer, moisture, motion, no, no2, o3, particulate matter, ph, pir, pm2.5, pm10, potentiometer, +# power, precipitation, pressure, proximity, pulse count, pulse frequency, radar, rainfall, rssi, smart valve, snr, so2, +# solar radiation, sound, strain, surface temperature, temperature, tilt, time, tvoc, uv, vapor pressure, velocity, +# vibration, voltage, water potential, water, weight, wifi ssid, wind direction, wind speed. + +dimensions: + width: 18 + length: 58 + height: 85 + +battery: + replaceable: true + type: ER14505 Li-SoCl2 battery*2 + +operatingConditions: + temperature: + min: -30 + max: 60 + + relativeHumidity: + min: 0 + max: 0.95 + +ipCode: IP67 + +keyProvisioning: + - custom + - join server +keySecurity: none +productURL: https://www.milesight-iot.com/products/lorawan-sensor/em320-tilt/ +dataSheetURL: https://resource.milesight-iot.com/milesight/document/em320-tilt-datasheet-en.pdf +resellerURLs: + - name: 'iot.sales@milesight.com' + region: + - United States + - European Union + - Canada + url: https://www.milesight-iot.com/contact-us/ + +photos: + main: em320-tilt.png + +compliances: + safety: + - body: IEC + norm: EN + standard: 62368-1 + radioEquipment: + - body: ETSI + norm: EN + standard: 301 489-1 + version: 2.2.0 + - body: ETSI + norm: EN + standard: 301 489-3 + version: 2.1.0 diff --git a/vendor/milesight-iot/em400-mud-codec.yaml b/vendor/milesight-iot/em400-mud-codec.yaml new file mode 100644 index 0000000000..a5142f0693 --- /dev/null +++ b/vendor/milesight-iot/em400-mud-codec.yaml @@ -0,0 +1,17 @@ +# Uplink decoder decodes binary data uplink into a JSON object (optional) +# For documentation on writing encoders and decoders, see: https://thethingsstack.io/integrations/payload-formatters/javascript/ +uplinkDecoder: + fileName: em400-mud.js + + examples: + - description: Multifunctional Ultrasonic Distance Sensor - Milesight IoT + input: + fPort: 85 + bytes: [0x01, 0x75, 0x5C, 0x03, 0x67, 0x01, 0x01, 0x04, 0x82, 0x44, 0x08, 0x05, 0x00, 0x01] + + output: + data: + battery: 92 + temperature: 25.7 + distance: 2116 + position: tilt diff --git a/vendor/milesight-iot/em400-mud.js b/vendor/milesight-iot/em400-mud.js new file mode 100644 index 0000000000..f8821738a3 --- /dev/null +++ b/vendor/milesight-iot/em400-mud.js @@ -0,0 +1,79 @@ +function decodeUplink(input) { + var res = Decoder(input.bytes, input.fPort); + if (res.error) { + return { + errors: [res.error], + }; + } + return { + data: res, + }; +} +/** + * Payload Decoder for The Things Network + * + * Copyright 2023 Milesight IoT + * + * @product EM400-MUD + */ +function Decoder(bytes, port) { + return milesight(bytes); +} + +function milesight(bytes) { + var decoded = {}; + + for (var i = 0; i < bytes.length;) { + var channel_id = bytes[i++]; + var channel_type = bytes[i++]; + // BATTERY + if (channel_id === 0x01 && channel_type === 0x75) { + decoded.battery = bytes[i]; + i += 1; + } + // TEMPERATURE + else if (channel_id === 0x03 && channel_type === 0x67) { + decoded.temperature = readInt16LE(bytes.slice(i, i + 2)) / 10; + i += 2; + } + // DISTANCE + else if (channel_id === 0x04 && channel_type === 0x82) { + decoded.distance = readUInt16LE(bytes.slice(i, i + 2)); + i += 2; + } + // POSITION + else if (channel_id === 0x05 && channel_type === 0x00) { + decoded.position = bytes[i] === 0 ? "normal" : "tilt"; + i += 1; + } + // TEMPERATURE WITH ABNORMAL + else if (channel_id === 0x83 && channel_type === 0x67) { + decoded.temperature = readInt16LE(bytes.slice(i, i + 2)) / 10; + decoded.temperature_abnormal = bytes[i + 2] == 0 ? false : true; + i += 3; + } + // DISTANCE WITH ALARMING + else if (channel_id === 0x84 && channel_type === 0x82) { + decoded.distance = readUInt16LE(bytes.slice(i, i + 2)); + decoded.distance_alarming = bytes[i + 2] == 0 ? false : true; + i += 3; + } else { + break; + } + } + + return decoded; +} + +/* ****************************************** + * bytes to number + ********************************************/ +function readUInt16LE(bytes) { + var value = (bytes[1] << 8) + bytes[0]; + return value & 0xffff; +} + +function readInt16LE(bytes) { + var ref = readUInt16LE(bytes); + return ref > 0x7fff ? ref - 0x10000 : ref; +} diff --git a/vendor/milesight-iot/em400-mud.png b/vendor/milesight-iot/em400-mud.png new file mode 100644 index 0000000000..132c7975e7 Binary files /dev/null and b/vendor/milesight-iot/em400-mud.png differ diff --git a/vendor/milesight-iot/em400-mud.yaml b/vendor/milesight-iot/em400-mud.yaml new file mode 100644 index 0000000000..fe7fe90936 --- /dev/null +++ b/vendor/milesight-iot/em400-mud.yaml @@ -0,0 +1,105 @@ +name: Multifunctional Ultrasonic Distance Sensor +description: EM400-MUD is a multifunctional ultrasonic distance sensor designedto detect small-range areas and small blind spots. + +hardwareVersions: + - version: 'V1.0' + numeric: 1 + +firmwareVersions: + - version: '1.01' + numeric: 1 + hardwareVersions: + - 'V1.0' + + profiles: + EU863-870: + id: profile-eu868 + codec: em400-mud-codec + US902-928: + id: profile-us915 + codec: em400-mud-codec + AU915-928: + id: profile-au915 + codec: em400-mud-codec + AS923: + id: profile-as923 + codec: em400-mud-codec + CN470-510: + id: profile-cn470 + codec: em400-mud-codec + KR920-923: + id: profile-kr920 + codec: em400-mud-codec + IN865-867: + id: profile-in865 + codec: em400-mud-codec + RU864-870: + id: profile-ru864 + codec: em400-mud-codec + +sensors: + - battery + - temperature + - accelerometer + - distance + +# 4-20 ma, accelerometer, altitude, analog input, auxiliary, barometer, battery, button, bvoc, co, co2, conductivity, +# current, digital input, dissolved oxygen, distance, dust, energy, gps, gyroscope, h2s, humidity, iaq, level, light, +# lightning, link, magnetometer, moisture, motion, no, no2, o3, particulate matter, ph, pir, pm2.5, pm10, potentiometer, +# power, precipitation, pressure, proximity, pulse count, pulse frequency, radar, rainfall, rssi, smart valve, snr, so2, +# solar radiation, sound, strain, surface temperature, temperature, tilt, time, tvoc, uv, vapor pressure, velocity, +# vibration, voltage, water potential, water, weight, wifi ssid, wind direction, wind speed. +additionalRadios: + - cellular + +dimensions: + width: 32.5 + length: 65 + height: 118 + +battery: + replaceable: true + type: ER26500 Li-SoCl2 battery*2 + +operatingConditions: + temperature: + min: -30 + max: 70 + + relativeHumidity: + min: 0 + max: 0.95 + +ipCode: IP67 + +keyProvisioning: + - custom + - join server +keySecurity: none +productURL: https://www.milesight-iot.com/products/lorawan-sensor/em400-mud/ +dataSheetURL: https://resource.milesight.com/milesight/iot/document/em400-mud-datasheet-en.pdf +resellerURLs: + - name: 'iot.sales@milesight.com' + region: + - United States + - European Union + - Canada + url: https://www.milesight-iot.com/contact-us/ + +photos: + main: em400-mud.png + +compliances: + safety: + - body: IEC + norm: EN + standard: 62368-1 + radioEquipment: + - body: ETSI + norm: EN + standard: 301 489-1 + version: 2.2.0 + - body: ETSI + norm: EN + standard: 301 489-3 + version: 2.1.0 diff --git a/vendor/milesight-iot/em400-tld-codec.yaml b/vendor/milesight-iot/em400-tld-codec.yaml new file mode 100644 index 0000000000..021d4659e5 --- /dev/null +++ b/vendor/milesight-iot/em400-tld-codec.yaml @@ -0,0 +1,17 @@ +# Uplink decoder decodes binary data uplink into a JSON object (optional) +# For documentation on writing encoders and decoders, see: https://thethingsstack.io/integrations/payload-formatters/javascript/ +uplinkDecoder: + fileName: em400-tld.js + + examples: + - description: ToF Laser Distance Sensor - Milesight IoT + input: + fPort: 85 + bytes: [0x01, 0x75, 0x5C, 0x03, 0x67, 0x01, 0x01, 0x04, 0x82, 0x44, 0x08, 0x05, 0x00, 0x01] + + output: + data: + battery: 92 + temperature: 25.7 + distance: 2116 + position: tilt diff --git a/vendor/milesight-iot/em400-tld.js b/vendor/milesight-iot/em400-tld.js new file mode 100644 index 0000000000..efe1847f68 --- /dev/null +++ b/vendor/milesight-iot/em400-tld.js @@ -0,0 +1,79 @@ +function decodeUplink(input) { + var res = Decoder(input.bytes, input.fPort); + if (res.error) { + return { + errors: [res.error], + }; + } + return { + data: res, + }; +} +/** + * Payload Decoder for The Things Network + * + * Copyright 2023 Milesight IoT + * + * @product EM400-TLD + */ +function Decoder(bytes, port) { + return milesight(bytes); +} + +function milesight(bytes) { + var decoded = {}; + + for (var i = 0; i < bytes.length; ) { + var channel_id = bytes[i++]; + var channel_type = bytes[i++]; + // BATTERY + if (channel_id === 0x01 && channel_type === 0x75) { + decoded.battery = bytes[i]; + i += 1; + } + // TEMPERATURE + else if (channel_id === 0x03 && channel_type === 0x67) { + decoded.temperature = readInt16LE(bytes.slice(i, i + 2)) / 10; + i += 2; + } + // DISTANCE + else if (channel_id === 0x04 && channel_type === 0x82) { + decoded.distance = readUInt16LE(bytes.slice(i, i + 2)); + i += 2; + } + // POSITION + else if (channel_id === 0x05 && channel_type === 0x00) { + decoded.position = bytes[i] === 0 ? "normal" : "tilt"; + i += 1; + } + // TEMPERATURE WITH ABNORMAL + else if (channel_id === 0x83 && channel_type === 0x67) { + decoded.temperature = readInt16LE(bytes.slice(i, i + 2)) / 10; + decoded.temperature_abnormal = bytes[i + 2] == 0 ? false : true; + i += 3; + } + // DISTANCE WITH ALARMING + else if (channel_id === 0x84 && channel_type === 0x82) { + decoded.distance = readUInt16LE(bytes.slice(i, i + 2)); + decoded.distance_alarming = bytes[i + 2] == 0 ? false : true; + i += 3; + } else { + break; + } + } + + return decoded; +} + +/* ****************************************** + * bytes to number + ********************************************/ +function readUInt16LE(bytes) { + var value = (bytes[1] << 8) + bytes[0]; + return value & 0xffff; +} + +function readInt16LE(bytes) { + var ref = readUInt16LE(bytes); + return ref > 0x7fff ? ref - 0x10000 : ref; +} diff --git a/vendor/milesight-iot/em400-tld.png b/vendor/milesight-iot/em400-tld.png new file mode 100644 index 0000000000..10f6064182 Binary files /dev/null and b/vendor/milesight-iot/em400-tld.png differ diff --git a/vendor/milesight-iot/em400-tld.yaml b/vendor/milesight-iot/em400-tld.yaml new file mode 100644 index 0000000000..f56a2cc04e --- /dev/null +++ b/vendor/milesight-iot/em400-tld.yaml @@ -0,0 +1,105 @@ +name: ToF Laser Distance Sensor +description: EM400-TLD is a distance sensor based on ToF (timeof flight), whichis mainly used for detecting the fill level and positionstatus. + +hardwareVersions: + - version: 'V1.0' + numeric: 1 + +firmwareVersions: + - version: '1.01' + numeric: 1 + hardwareVersions: + - 'V1.0' + + profiles: + EU863-870: + id: profile-eu868 + codec: em400-tld-codec + US902-928: + id: profile-us915 + codec: em400-tld-codec + AU915-928: + id: profile-au915 + codec: em400-tld-codec + AS923: + id: profile-as923 + codec: em400-tld-codec + CN470-510: + id: profile-cn470 + codec: em400-tld-codec + KR920-923: + id: profile-kr920 + codec: em400-tld-codec + IN865-867: + id: profile-in865 + codec: em400-tld-codec + RU864-870: + id: profile-ru864 + codec: em400-tld-codec + +sensors: + - battery + - temperature + - accelerometer + - distance + +# 4-20 ma, accelerometer, altitude, analog input, auxiliary, barometer, battery, button, bvoc, co, co2, conductivity, +# current, digital input, dissolved oxygen, distance, dust, energy, gps, gyroscope, h2s, humidity, iaq, level, light, +# lightning, link, magnetometer, moisture, motion, no, no2, o3, particulate matter, ph, pir, pm2.5, pm10, potentiometer, +# power, precipitation, pressure, proximity, pulse count, pulse frequency, radar, rainfall, rssi, smart valve, snr, so2, +# solar radiation, sound, strain, surface temperature, temperature, tilt, time, tvoc, uv, vapor pressure, velocity, +# vibration, voltage, water potential, water, weight, wifi ssid, wind direction, wind speed. +additionalRadios: + - cellular + +dimensions: + width: 30 + length: 65 + height: 118 + +battery: + replaceable: true + type: ER26500 Li-SoCl2 battery*2 + +operatingConditions: + temperature: + min: -30 + max: 70 + + relativeHumidity: + min: 0 + max: 0.95 + +ipCode: IP67 + +keyProvisioning: + - custom + - join server +keySecurity: none +productURL: https://www.milesight-iot.com/products/lorawan-sensor/em400-tld/ +dataSheetURL: https://resource.milesight.com/milesight/iot/document/em400-tld-datasheet-en.pdf +resellerURLs: + - name: 'iot.sales@milesight.com' + region: + - United States + - European Union + - Canada + url: https://www.milesight-iot.com/contact-us/ + +photos: + main: em400-tld.png + +compliances: + safety: + - body: IEC + norm: EN + standard: 62368-1 + radioEquipment: + - body: ETSI + norm: EN + standard: 301 489-1 + version: 2.2.0 + - body: ETSI + norm: EN + standard: 301 489-3 + version: 2.1.0 diff --git a/vendor/milesight-iot/em400-udl-codec.yaml b/vendor/milesight-iot/em400-udl-codec.yaml new file mode 100644 index 0000000000..021d4659e5 --- /dev/null +++ b/vendor/milesight-iot/em400-udl-codec.yaml @@ -0,0 +1,17 @@ +# Uplink decoder decodes binary data uplink into a JSON object (optional) +# For documentation on writing encoders and decoders, see: https://thethingsstack.io/integrations/payload-formatters/javascript/ +uplinkDecoder: + fileName: em400-tld.js + + examples: + - description: ToF Laser Distance Sensor - Milesight IoT + input: + fPort: 85 + bytes: [0x01, 0x75, 0x5C, 0x03, 0x67, 0x01, 0x01, 0x04, 0x82, 0x44, 0x08, 0x05, 0x00, 0x01] + + output: + data: + battery: 92 + temperature: 25.7 + distance: 2116 + position: tilt diff --git a/vendor/milesight-iot/em400-udl.js b/vendor/milesight-iot/em400-udl.js new file mode 100644 index 0000000000..efe1847f68 --- /dev/null +++ b/vendor/milesight-iot/em400-udl.js @@ -0,0 +1,79 @@ +function decodeUplink(input) { + var res = Decoder(input.bytes, input.fPort); + if (res.error) { + return { + errors: [res.error], + }; + } + return { + data: res, + }; +} +/** + * Payload Decoder for The Things Network + * + * Copyright 2023 Milesight IoT + * + * @product EM400-TLD + */ +function Decoder(bytes, port) { + return milesight(bytes); +} + +function milesight(bytes) { + var decoded = {}; + + for (var i = 0; i < bytes.length; ) { + var channel_id = bytes[i++]; + var channel_type = bytes[i++]; + // BATTERY + if (channel_id === 0x01 && channel_type === 0x75) { + decoded.battery = bytes[i]; + i += 1; + } + // TEMPERATURE + else if (channel_id === 0x03 && channel_type === 0x67) { + decoded.temperature = readInt16LE(bytes.slice(i, i + 2)) / 10; + i += 2; + } + // DISTANCE + else if (channel_id === 0x04 && channel_type === 0x82) { + decoded.distance = readUInt16LE(bytes.slice(i, i + 2)); + i += 2; + } + // POSITION + else if (channel_id === 0x05 && channel_type === 0x00) { + decoded.position = bytes[i] === 0 ? "normal" : "tilt"; + i += 1; + } + // TEMPERATURE WITH ABNORMAL + else if (channel_id === 0x83 && channel_type === 0x67) { + decoded.temperature = readInt16LE(bytes.slice(i, i + 2)) / 10; + decoded.temperature_abnormal = bytes[i + 2] == 0 ? false : true; + i += 3; + } + // DISTANCE WITH ALARMING + else if (channel_id === 0x84 && channel_type === 0x82) { + decoded.distance = readUInt16LE(bytes.slice(i, i + 2)); + decoded.distance_alarming = bytes[i + 2] == 0 ? false : true; + i += 3; + } else { + break; + } + } + + return decoded; +} + +/* ****************************************** + * bytes to number + ********************************************/ +function readUInt16LE(bytes) { + var value = (bytes[1] << 8) + bytes[0]; + return value & 0xffff; +} + +function readInt16LE(bytes) { + var ref = readUInt16LE(bytes); + return ref > 0x7fff ? ref - 0x10000 : ref; +} diff --git a/vendor/milesight-iot/em400-udl.png b/vendor/milesight-iot/em400-udl.png new file mode 100644 index 0000000000..5b0b486fc0 Binary files /dev/null and b/vendor/milesight-iot/em400-udl.png differ diff --git a/vendor/milesight-iot/em400-udl.yaml b/vendor/milesight-iot/em400-udl.yaml new file mode 100644 index 0000000000..d3103c76b7 --- /dev/null +++ b/vendor/milesight-iot/em400-udl.yaml @@ -0,0 +1,106 @@ +name: Ultrasonic Distance Sensor +description: EM400-UDL is a non-contact ultrasonic distancesensordesigned for outdoor applications such as monitoringwaterlevel, fill level of tanks and silos, presence of objects, orsnowlevel + +hardwareVersions: + - version: 'V1.0' + numeric: 1 + +firmwareVersions: + - version: '1.01' + numeric: 1 + hardwareVersions: + - 'V1.0' + + profiles: + EU863-870: + id: profile-eu868 + codec: em400-udl-codec + US902-928: + id: profile-us915 + codec: em400-udl-codec + AU915-928: + id: profile-au915 + codec: em400-udl-codec + AS923: + id: profile-as923 + codec: em400-udl-codec + CN470-510: + id: profile-cn470 + codec: em400-udl-codec + KR920-923: + id: profile-kr920 + codec: em400-udl-codec + IN865-867: + id: profile-in865 + codec: em400-udl-codec + RU864-870: + id: profile-ru864 + codec: em400-udl-codec + +sensors: + - battery + - temperature + - accelerometer + - distance + +# 4-20 ma, accelerometer, altitude, analog input, auxiliary, barometer, battery, button, bvoc, co, co2, conductivity, +# current, digital input, dissolved oxygen, distance, dust, energy, gps, gyroscope, h2s, humidity, iaq, level, light, +# lightning, link, magnetometer, moisture, motion, no, no2, o3, particulate matter, ph, pir, pm2.5, pm10, potentiometer, +# power, precipitation, pressure, proximity, pulse count, pulse frequency, radar, rainfall, rssi, smart valve, snr, so2, +# solar radiation, sound, strain, surface temperature, temperature, tilt, time, tvoc, uv, vapor pressure, velocity, +# vibration, voltage, water potential, water, weight, wifi ssid, wind direction, wind speed. + +additionalRadios: + - cellular + +dimensions: + width: 80 + length: 65 + height: 118 + +battery: + replaceable: true + type: ER26500 Li-SoCl2 battery*2 + +operatingConditions: + temperature: + min: -30 + max: 70 + + relativeHumidity: + min: 0 + max: 0.95 + +ipCode: IP67 + +keyProvisioning: + - custom + - join server +keySecurity: none +productURL: https://www.milesight-iot.com/products/lorawan-sensor/em400-udl/ +dataSheetURL: https://resource.milesight.com/milesight/iot/document/em400-udl-datasheet-en.pdf +resellerURLs: + - name: 'iot.sales@milesight.com' + region: + - United States + - European Union + - Canada + url: https://www.milesight-iot.com/contact-us/ + +photos: + main: em400-udl.png + +compliances: + safety: + - body: IEC + norm: EN + standard: 62368-1 + radioEquipment: + - body: ETSI + norm: EN + standard: 301 489-1 + version: 2.2.0 + - body: ETSI + norm: EN + standard: 301 489-3 + version: 2.1.0 diff --git a/vendor/milesight-iot/em500-co2.js b/vendor/milesight-iot/em500-co2.js index 420edabebe..0a78e96356 100644 --- a/vendor/milesight-iot/em500-co2.js +++ b/vendor/milesight-iot/em500-co2.js @@ -39,7 +39,7 @@ function Decoder(bytes, port) { // PRESSURE else if (channel_id === 0x06 && channel_type === 0x73) { - decoded.pressure = readInt16LE(bytes.slice(i, i + 2))/10; + decoded.pressure = readInt16LE(bytes.slice(i, i + 2)) / 10; i += 2; } else { break; diff --git a/vendor/milesight-iot/em500-co2.png b/vendor/milesight-iot/em500-co2.png new file mode 100644 index 0000000000..b3c863e1f0 Binary files /dev/null and b/vendor/milesight-iot/em500-co2.png differ diff --git a/vendor/milesight-iot/em500-lgt-codec.yaml b/vendor/milesight-iot/em500-lgt-codec.yaml new file mode 100644 index 0000000000..b2d2a27c5b --- /dev/null +++ b/vendor/milesight-iot/em500-lgt-codec.yaml @@ -0,0 +1,21 @@ +# Uplink decoder decodes binary data uplink into a JSON object (optional) +# For documentation on writing encoders and decoders, see: https://thethingsstack.io/integrations/payload-formatters/javascript/ +uplinkDecoder: + fileName: em500-lgt.js + examples: + - description: Light Sensors (example 1) - Milesight IoT + input: + fPort: 85 + bytes: [0x01, 0x75, 0x5C, 0x03, 0x94, 0x50, 0x00, 0x00, 0x00] + output: + data: + battery: 92 + light: 80 + - description: Light Sensors (example 2) - Milesight IoT + input: + fPort: 85 + bytes: [0x01, 0x75, 0x64, 0x03, 0x94, 0x50, 0x00, 0x00, 0x00] + output: + data: + battery: 100 + light: 80 diff --git a/vendor/milesight-iot/em500-lgt.js b/vendor/milesight-iot/em500-lgt.js new file mode 100644 index 0000000000..71d0823a22 --- /dev/null +++ b/vendor/milesight-iot/em500-lgt.js @@ -0,0 +1,61 @@ +function decodeUplink(input) { + var res = Decoder(input.bytes, input.fPort); + if (res.error) { + return { + errors: [res.error], + }; + } + return { + data: res, + }; +} +/** + * Payload Decoder for The Things Network + * + * Copyright 2021 Milesight IoT + * + * @product EM500-LGT + */ +function Decoder(bytes, port) { + var decoded = {}; + + for (var i = 0; i < bytes.length;) { + var channel_id = bytes[i++]; + var channel_type = bytes[i++]; + // BATTERY + if (channel_id === 0x01 && channel_type === 0x75) { + decoded.battery = bytes[i]; + i += 1; + } + // LIGHT + else if (channel_id === 0x03 && channel_type === 0x94) { + decoded.light = readUInt32LE(bytes.slice(i, i + 4)); + i += 4; + } + } + + return decoded; +} + +/* ****************************************** + * bytes to number + ********************************************/ +function readUInt16LE(bytes) { + var value = (bytes[1] << 8) + bytes[0]; + return value & 0xffff; +} + +function readInt16LE(bytes) { + var ref = readUInt16LE(bytes); + return ref > 0x7fff ? ref - 0x10000 : ref; +} + +function readUInt32LE(bytes) { + var value = (bytes[3] << 24) + (bytes[2] << 16) + (bytes[1] << 8) + bytes[0]; + return (value & 0xFFFFFFFF); +} + +function readInt32LE(bytes) { + var ref = readUInt32LE(bytes); + return (ref > 0x7FFFFFFF) ? ref - 0x100000000 : ref; +} \ No newline at end of file diff --git a/vendor/milesight-iot/em500-lgt.png b/vendor/milesight-iot/em500-lgt.png new file mode 100644 index 0000000000..905d8433de Binary files /dev/null and b/vendor/milesight-iot/em500-lgt.png differ diff --git a/vendor/milesight-iot/em500-lgt.yaml b/vendor/milesight-iot/em500-lgt.yaml new file mode 100644 index 0000000000..1f97fc51fb --- /dev/null +++ b/vendor/milesight-iot/em500-lgt.yaml @@ -0,0 +1,87 @@ +name: Milesight EM500-LGT Light Sensor +description: Milesight EM500-UDL is an outdoor environment monitoring sensor for measuring light in harsh environments. EM500-LGT features a long-lasting battery life of up to 10 years, an IP67 UV-resistant and waterproof enclosure, and can be easily configured via NFC. It is widely used for outdoor applications like smart agriculture, urban lighting, etc. + +hardwareVersions: + - version: 'V1.x' + numeric: 1 + +firmwareVersions: + - version: '2.x' + numeric: 1 + hardwareVersions: + - 'V1.x' + + profiles: + EU863-870: + id: profile-eu868 + lorawanCertified: true + codec: em500-lgt-codec + US902-928: + id: profile-us915 + lorawanCertified: true + codec: em500-lgt-codec + AU915-928: + id: profile-au915 + lorawanCertified: true + codec: em500-lgt-codec + AS923: + id: profile-as923 + lorawanCertified: true + codec: em500-lgt-codec + CN470-510: + id: profile-cn470 + lorawanCertified: true + codec: em500-lgt-codec + KR920-923: + id: profile-kr920 + lorawanCertified: true + codec: em500-lgt-codec + IN865-867: + id: profile-in865 + lorawanCertified: true + codec: em500-lgt-codec + RU864-870: + id: profile-ru864 + lorawanCertified: true + codec: em500-lgt-codec + +sensors: + - battery + - light + +dimensions: + width: 71 + length: 69.5 + height: 105.4 + +battery: + replaceable: true + type: ER34615 + +operatingConditions: + temperature: + min: -30 + max: 60 + + relativeHumidity: + min: 0 + max: 1.00 + +ipCode: IP66 + +keyProvisioning: + - custom + - join server +keySecurity: none +productURL: https://www.milesight-iot.com/lorawan/sensor/em500-series/?utm_source=platform&utm_medium=web&utm_campaign=milesight +dataSheetURL: https://resource.milesight-iot.com/milesight/document/em500-lgt-datasheet-en.pdf +resellerURLs: + - name: 'iot.sales@milesight.com' + region: + - United States + - European Union + - Canada + url: https://www.alibaba.com/product-detail/EM500-LGT-lighting-sensor-accurate-detect_1600547241262.html?spm=a2700.shop_plser.41413.20.691d1a83CtfBqy + +photos: + main: em500-lgt.png diff --git a/vendor/milesight-iot/em500-pp-codec.yaml b/vendor/milesight-iot/em500-pp-codec.yaml new file mode 100644 index 0000000000..de45e5187f --- /dev/null +++ b/vendor/milesight-iot/em500-pp-codec.yaml @@ -0,0 +1,21 @@ +# Uplink decoder decodes binary data uplink into a JSON object (optional) +# For documentation on writing encoders and decoders, see: https://thethingsstack.io/integrations/payload-formatters/javascript/ +uplinkDecoder: + fileName: em500-pp.js + examples: + - description: Pipe Pressure Sensors (example 1) - Milesight IoT + input: + fPort: 85 + bytes: [0x01, 0x75, 0x5C, 0x03, 0x7b, 0x0a, 0x00] + output: + data: + battery: 92 + pressure: 10 + - description: Pipe Pressure Sensors (example 2) - Milesight IoT + input: + fPort: 85 + bytes: [0x01, 0x75, 0x64, 0x03, 0x7b, 0x0a, 0x00] + output: + data: + battery: 100 + pressure: 10 diff --git a/vendor/milesight-iot/em500-pp.js b/vendor/milesight-iot/em500-pp.js new file mode 100644 index 0000000000..c1abb2db26 --- /dev/null +++ b/vendor/milesight-iot/em500-pp.js @@ -0,0 +1,53 @@ +function decodeUplink(input) { + var res = Decoder(input.bytes, input.fPort); + if (res.error) { + return { + errors: [res.error], + }; + } + return { + data: res, + }; +} +/** + * Payload Decoder for The Things Network + * + * Copyright 2021 Milesight IoT + * + * @product EM500-PP + */ +function Decoder(bytes, port) { + var decoded = {}; + + for (var i = 0; i < bytes.length;) { + var channel_id = bytes[i++]; + var channel_type = bytes[i++]; + // BATTERY + if (channel_id === 0x01 && channel_type === 0x75) { + decoded.battery = bytes[i]; + i += 1; + } + // PRESSURE + else if (channel_id === 0x03 && channel_type === 0x7B) { + decoded.pressure = readInt16LE(bytes.slice(i, i + 2)); + i += 2; + } else { + break; + } + } + + return decoded; +} + +/* ****************************************** + * bytes to number + ********************************************/ +function readUInt16LE(bytes) { + var value = (bytes[1] << 8) + bytes[0]; + return value & 0xffff; +} + +function readInt16LE(bytes) { + var ref = readUInt16LE(bytes); + return ref > 0x7fff ? ref - 0x10000 : ref; +} \ No newline at end of file diff --git a/vendor/milesight-iot/em500-pp.png b/vendor/milesight-iot/em500-pp.png new file mode 100644 index 0000000000..c1e20b62e6 Binary files /dev/null and b/vendor/milesight-iot/em500-pp.png differ diff --git a/vendor/milesight-iot/em500-pp.yaml b/vendor/milesight-iot/em500-pp.yaml new file mode 100644 index 0000000000..7f77b755db --- /dev/null +++ b/vendor/milesight-iot/em500-pp.yaml @@ -0,0 +1,87 @@ +name: Milesight EM500-PP Pipe Pressure Sensor +description: Milesight EM500-PP is an outdoor environment monitoring sensor for measuring pipe pressure in harsh environments. EM500-PP features a long-lasting battery life of up to 10 years, an IP67 UV-resistant and waterproof enclosure, and can be easily configured via NFC. It is widely used for applications like smart buildings, pipeline and tank systems monitoring, etc. + +hardwareVersions: + - version: 'V1.x' + numeric: 1 + +firmwareVersions: + - version: '2.x' + numeric: 1 + hardwareVersions: + - 'V1.x' + + profiles: + EU863-870: + id: profile-eu868 + lorawanCertified: true + codec: em500-pp-codec + US902-928: + id: profile-us915 + lorawanCertified: true + codec: em500-pp-codec + AU915-928: + id: profile-au915 + lorawanCertified: true + codec: em500-pp-codec + AS923: + id: profile-as923 + lorawanCertified: true + codec: em500-pp-codec + CN470-510: + id: profile-cn470 + lorawanCertified: true + codec: em500-pp-codec + KR920-923: + id: profile-kr920 + lorawanCertified: true + codec: em500-pp-codec + IN865-867: + id: profile-in865 + lorawanCertified: true + codec: em500-pp-codec + RU864-870: + id: profile-ru864 + lorawanCertified: true + codec: em500-pp-codec + +sensors: + - battery + - pressure + +dimensions: + width: 71 + length: 69.5 + height: 105.4 + +battery: + replaceable: true + type: ER34615 + +operatingConditions: + temperature: + min: -30 + max: 70 + + relativeHumidity: + min: 0 + max: 1.00 + +ipCode: IP66 + +keyProvisioning: + - custom + - join server +keySecurity: none +productURL: https://www.milesight-iot.com/lorawan/sensor/em500-series/?utm_source=platform&utm_medium=web&utm_campaign=milesight +dataSheetURL: https://resource.milesight-iot.com/milesight/document/em500-pp-datasheet-en.pdf +resellerURLs: + - name: 'iot.sales@milesight.com' + region: + - United States + - European Union + - Canada + url: https://www.alibaba.com/product-detail/EM500-PP-pressure-no-leakage-danger_1600546180517.html?spm=a2700.shop_plser.41413.16.15946fcaep3egI + +photos: + main: em500-pp.png diff --git a/vendor/milesight-iot/em500-pt100-codec.yaml b/vendor/milesight-iot/em500-pt100-codec.yaml new file mode 100644 index 0000000000..5dc58bfc3b --- /dev/null +++ b/vendor/milesight-iot/em500-pt100-codec.yaml @@ -0,0 +1,13 @@ +# Uplink decoder decodes binary data uplink into a JSON object (optional) +# For documentation on writing encoders and decoders, see: https://thethingsstack.io/integrations/payload-formatters/javascript/ +uplinkDecoder: + fileName: em500-pt100.js + examples: + - description: PT100 Temperature Sensors (example 1) - Milesight IoT + input: + fPort: 85 + bytes: [0x01, 0x75, 0x5C, 0x03, 0x67, 0x19, 0x01] + output: + data: + battery: 92 + temperature: 28.1 diff --git a/vendor/milesight-iot/em500-pt100.js b/vendor/milesight-iot/em500-pt100.js new file mode 100644 index 0000000000..08c93227a5 --- /dev/null +++ b/vendor/milesight-iot/em500-pt100.js @@ -0,0 +1,58 @@ +function decodeUplink(input) { + var res = Decoder(input.bytes, input.fPort); + if (res.error) { + return { + errors: [res.error], + }; + } + return { + data: res, + }; +} +/** + * Payload Decoder for The Things Network + * + * Copyright 2021 Milesight IoT + * + * @product EM500-PT100 + */ +function Decoder(bytes, port) { + var decoded = {}; + + for (var i = 0; i < bytes.length;) { + var channel_id = bytes[i++]; + var channel_type = bytes[i++]; + // BATTERY + if (channel_id === 0x01 && channel_type === 0x75) { + decoded.battery = bytes[i]; + i += 1; + } + // TEMPERATURE + else if (channel_id === 0x03 && channel_type === 0x67) { + // ℃ + decoded.temperature = readInt16LE(bytes.slice(i, i + 2)) / 10; + i += 2; + + // ℉ + // decoded.temperature = readInt16LE(bytes.slice(i, i + 2)) / 10 * 1.8 + 32; + // i +=2; + } else { + break; + } + } + + return decoded; +} + +/* ****************************************** + * bytes to number + ********************************************/ +function readUInt16LE(bytes) { + var value = (bytes[1] << 8) + bytes[0]; + return value & 0xffff; +} + +function readInt16LE(bytes) { + var ref = readUInt16LE(bytes); + return ref > 0x7fff ? ref - 0x10000 : ref; +} \ No newline at end of file diff --git a/vendor/milesight-iot/em500-pt100.png b/vendor/milesight-iot/em500-pt100.png new file mode 100644 index 0000000000..2cc6ad244c Binary files /dev/null and b/vendor/milesight-iot/em500-pt100.png differ diff --git a/vendor/milesight-iot/em500-pt100.yaml b/vendor/milesight-iot/em500-pt100.yaml new file mode 100644 index 0000000000..6f1330a63d --- /dev/null +++ b/vendor/milesight-iot/em500-pt100.yaml @@ -0,0 +1,87 @@ +name: Milesight EM500-PT100 Industrial Temperature Sensor +description: Milesight EM500-PT100 resistance temperature sensor is designed for measuring a wide range of temperatures in harsh environments. EM500-PT100 features a long-lasting battery life of up to 10 years, an IP67 UV-resistant and waterproof enclosure, and can be easily configured via NFC. It offers a corrosion resistance cable and multiple probe options. EM500-PT100 is widely used for temperature monitoring applications like industrial machines, ovens, pipes, etc. + +hardwareVersions: + - version: 'V1.x' + numeric: 1 + +firmwareVersions: + - version: '2.x' + numeric: 1 + hardwareVersions: + - 'V1.x' + + profiles: + EU863-870: + id: profile-eu868 + lorawanCertified: true + codec: em500-pt100-codec + US902-928: + id: profile-us915 + lorawanCertified: true + codec: em500-pt100-codec + AU915-928: + id: profile-au915 + lorawanCertified: true + codec: em500-pt100-codec + AS923: + id: profile-as923 + lorawanCertified: true + codec: em500-pt100-codec + CN470-510: + id: profile-cn470 + lorawanCertified: true + codec: em500-pt100-codec + KR920-923: + id: profile-kr920 + lorawanCertified: true + codec: em500-pt100-codec + IN865-867: + id: profile-in865 + lorawanCertified: true + codec: em500-pt100-codec + RU864-870: + id: profile-ru864 + lorawanCertified: true + codec: em500-pt100-codec + +sensors: + - battery + - temperature + +dimensions: + width: 71 + length: 69.5 + height: 105.4 + +battery: + replaceable: true + type: ER34615 + +operatingConditions: + temperature: + min: -30 + max: 70 + + relativeHumidity: + min: 0 + max: 1.00 + +ipCode: IP66 + +keyProvisioning: + - custom + - join server +keySecurity: none +productURL: https://www.milesight-iot.com/lorawan/sensor/em500-series/?utm_source=platform&utm_medium=web&utm_campaign=milesight +dataSheetURL: https://resource.milesight-iot.com/milesight/document/em500-pt100-datasheet-en.pdf +resellerURLs: + - name: 'iot.sales@milesight.com' + region: + - United States + - European Union + - Canada + url: https://www.alibaba.com/product-detail/EM500-PT100-LoRaWan-PT100-temperature-sensor_1600059025633.html?spm=a2700.details.0.0.25eb4624m9AFpX + +photos: + main: em500-pt100.png diff --git a/vendor/milesight-iot/em500-smt-codec.yaml b/vendor/milesight-iot/em500-smt-codec.yaml new file mode 100644 index 0000000000..c235440e4a --- /dev/null +++ b/vendor/milesight-iot/em500-smt-codec.yaml @@ -0,0 +1,13 @@ +# Uplink decoder decodes binary data uplink into a JSON object (optional) +# For documentation on writing encoders and decoders, see: https://thethingsstack.io/integrations/payload-formatters/javascript/ +uplinkDecoder: + fileName: em500-smt.js + example: + - description: Soil Moisture Sensor (example 1) - Milesight IoT + input: + fPort: 85 + bytes: [0x01, 0x75, 0x64, 0x04, 0x68, 0x71] + output: + data: + battery: 100 + humidity: 56.5 diff --git a/vendor/milesight-iot/em500-smt.js b/vendor/milesight-iot/em500-smt.js new file mode 100644 index 0000000000..c8ae10091c --- /dev/null +++ b/vendor/milesight-iot/em500-smt.js @@ -0,0 +1,58 @@ +function decodeUplink(input) { + var res = Decoder(input.bytes, input.fPort); + if (res.error) { + return { + errors: [res.error], + }; + } + return { + data: res, + }; +} +/** + * Payload Decoder for The Things Network + * + * Copyright 2021 Milesight IoT + * + * @product EM500-SMTC + */ +function Decoder(bytes, port) { + var decoded = {}; + + for (var i = 0; i < bytes.length;) { + var channel_id = bytes[i++]; + var channel_type = bytes[i++]; + // BATTERY + if (channel_id === 0x01 && channel_type === 0x75) { + decoded.battery = bytes[i]; + i += 1; + } + // HUMIDITY + else if (channel_id === 0x04 && channel_type === 0x68) { + decoded.humidity = bytes[i] / 2; + i += 2; + } + else if (channel_id === 0x04 && channel_type === 0xCA) { + decoded.humidity = bytes[i] / 2; + i += 2; + } + else { + break; + } + } + + return decoded; +} + +/* ****************************************** + * bytes to number + ********************************************/ +function readUInt16LE(bytes) { + var value = (bytes[1] << 8) + bytes[0]; + return value & 0xffff; +} + +function readInt16LE(bytes) { + var ref = readUInt16LE(bytes); + return ref > 0x7fff ? ref - 0x10000 : ref; +} \ No newline at end of file diff --git a/vendor/milesight-iot/em500-smt.png b/vendor/milesight-iot/em500-smt.png new file mode 100644 index 0000000000..befd9162d7 Binary files /dev/null and b/vendor/milesight-iot/em500-smt.png differ diff --git a/vendor/milesight-iot/em500-smt.yaml b/vendor/milesight-iot/em500-smt.yaml new file mode 100644 index 0000000000..8bbc963978 --- /dev/null +++ b/vendor/milesight-iot/em500-smt.yaml @@ -0,0 +1,88 @@ +name: Milesight EM500-SWL Submersible Water Level +description: Milesight EM500-SWL is designed for measuring liquid levels in harsh environments. M500-SWL features a long-lasting battery life of up to 10 years, an IP67 UV-resistant and waterproof enclosure, and can be easily configured via NFC. It offers a stainless probe with corrosion resistance and a customizable measuring range up to 200m. EM500-SWL is widely used for applications like tank level monitoring, river level monitoring, etc. + +hardwareVersions: + - version: 'V1.x' + numeric: 1 + +firmwareVersions: + - version: '2.x' + numeric: 1 + hardwareVersions: + - 'V1.x' + + profiles: + EU863-870: + id: profile-eu868 + lorawanCertified: true + codec: em500-smt-codec + US902-928: + id: profile-us915 + lorawanCertified: true + codec: em500-smt-codec + AU915-928: + id: profile-au915 + lorawanCertified: true + codec: em500-smt-codec + AS923: + id: profile-as923 + lorawanCertified: true + codec: em500-smt-codec + CN470-510: + id: profile-cn470 + lorawanCertified: true + codec: em500-smt-codec + KR920-923: + id: profile-kr920 + lorawanCertified: true + codec: em500-smt-codec + IN865-867: + id: profile-in865 + lorawanCertified: true + codec: em500-smt-codec + RU864-870: + id: profile-ru864 + lorawanCertified: true + codec: em500-smt-codec + +sensors: + - battery + - temperature + - moisture + +dimensions: + width: 71 + length: 69.5 + height: 105.4 + +battery: + replaceable: true + type: ER34615 + +operatingConditions: + temperature: + min: -30 + max: 70 + + relativeHumidity: + min: 0 + max: 1.00 + +ipCode: IP67 + +keyProvisioning: + - custom + - join server +keySecurity: none +productURL: https://www.milesight-iot.com/lorawan/sensor/em500-series/?utm_source=platform&utm_medium=web&utm_campaign=milesight +dataSheetURL: https://resource.milesight-iot.com/milesight/document/em500-smt-datasheet-en.pdf +resellerURLs: + - name: 'iot.sales@milesight.com' + region: + - United States + - European Union + - Canada + url: https://www.alibaba.com/product-detail/EM500-SWL-Series-Submersible-Water-Level_62482085244.html?spm=a2700.shop_plser.41413.30.7fdf1a83ENIQ1v + +photos: + main: em500-smt.png diff --git a/vendor/milesight-iot/em500-smtc-codec.yaml b/vendor/milesight-iot/em500-smtc-codec.yaml new file mode 100644 index 0000000000..7265a7d368 --- /dev/null +++ b/vendor/milesight-iot/em500-smtc-codec.yaml @@ -0,0 +1,14 @@ +# Uplink decoder decodes binary data uplink into a JSON object (optional) +# For documentation on writing encoders and decoders, see: https://thethingsstack.io/integrations/payload-formatters/javascript/ +uplinkDecoder: + fileName: em500-smtc.js + examples: + - description: Soil Moisture, Temperature, Electrical Conductivity Sensor (example 1) - Milesight IoT + input: + fPort: 85 + bytes: [0x01, 0x75, 0x5C, 0x03, 0x67, 0x34, 0x01, 0x04, 0x68, 0x65, 0x05, 0x7f, 0xf0, 0x00] + output: + data: + battery: 92 + temperature: 30.8 + humidity: 50.5 diff --git a/vendor/milesight-iot/em500-smtc.js b/vendor/milesight-iot/em500-smtc.js new file mode 100644 index 0000000000..67b6e7dc6a --- /dev/null +++ b/vendor/milesight-iot/em500-smtc.js @@ -0,0 +1,73 @@ +function decodeUplink(input) { + var res = Decoder(input.bytes, input.fPort); + if (res.error) { + return { + errors: [res.error], + }; + } + return { + data: res, + }; +} + +/** +* Payload Decoder for The Things Network +* +* Copyright 2021 Milesight IoT +* +* @product EM500-SMTC +*/ +function Decoder(bytes, port) { + var decoded = {}; + + for (var i = 0; i < bytes.length;) { + var channel_id = bytes[i++]; + var channel_type = bytes[i++]; + // BATTERY + if (channel_id === 0x01 && channel_type === 0x75) { + decoded.battery = bytes[i]; + i += 1; + } + // TEMPERATURE + else if (channel_id === 0x03 && channel_type === 0x67) { + // ℃ + decoded.temperature = readInt16LE(bytes.slice(i, i + 2)) / 10; + i += 2; + + // ℉ + // decoded.temperature = readInt16LE(bytes.slice(i, i + 2)) / 10 * 1.8 + 32; + // i +=2; + } + // HUMIDITY + else if (channel_id === 0x04 && channel_type === 0x68) { + decoded.humidity = bytes[i] / 2; + i += 2; + } + else if (channel_id === 0x04 && channel_type === 0xCA) { + decoded.humidity = bytes[i] / 2; + i += 2; + } + // CONDUCTIVITY + else if (channel_id === 0x05 && channel_type === 0x7F) { + decoded.conductivity = readUInt16LE(bytes.slice(i, i + 2)); + i += 2; + } else { + break; + } + } + + return decoded; +} + +/* ****************************************** + * bytes to number + ********************************************/ +function readUInt16LE(bytes) { + var value = (bytes[1] << 8) + bytes[0]; + return value & 0xffff; +} + +function readInt16LE(bytes) { + var ref = readUInt16LE(bytes); + return ref > 0x7fff ? ref - 0x10000 : ref; +} \ No newline at end of file diff --git a/vendor/milesight-iot/em500-smtc.png b/vendor/milesight-iot/em500-smtc.png new file mode 100644 index 0000000000..61fb51cccf Binary files /dev/null and b/vendor/milesight-iot/em500-smtc.png differ diff --git a/vendor/milesight-iot/em500-smtc.yaml b/vendor/milesight-iot/em500-smtc.yaml new file mode 100644 index 0000000000..0cb6bf02e5 --- /dev/null +++ b/vendor/milesight-iot/em500-smtc.yaml @@ -0,0 +1,89 @@ +name: Milesight EM500-SMTC Soil Moisture, Temperature and Electrical Conductivity Sensor +description: Milesight EM500-SMTC is designed for measuring soil moisture, temperature, and electrical conductivity with high precision in harsh environments. EM500-SMTC features a long-lasting battery life of up to 10 years and can be easily configured via NFC. It offers a corrosion resistance probe and an IP67 UV-resistant and waterproof enclosure. EM500-SMTC is widely used for outdoor applications like smart agriculture, smart horticulture, etc. + +hardwareVersions: + - version: 'V1.x' + numeric: 1 + +firmwareVersions: + - version: '2.x' + numeric: 1 + hardwareVersions: + - 'V1.x' + + profiles: + EU863-870: + id: profile-eu868 + lorawanCertified: true + codec: em500-smtc-codec + US902-928: + id: profile-us915 + lorawanCertified: true + codec: em500-smtc-codec + AU915-928: + id: profile-au915 + lorawanCertified: true + codec: em500-smtc-codec + AS923: + id: profile-as923 + lorawanCertified: true + codec: em500-smtc-codec + CN470-510: + id: profile-cn470 + lorawanCertified: true + codec: em500-smtc-codec + KR920-923: + id: profile-kr920 + lorawanCertified: true + codec: em500-smtc-codec + IN865-867: + id: profile-in865 + lorawanCertified: true + codec: em500-smtc-codec + RU864-870: + id: profile-ru864 + lorawanCertified: true + codec: em500-smtc-codec + +sensors: + - battery + - temperature + - moisture + - conductivity + +dimensions: + width: 71 + length: 69.5 + height: 105.4 + +battery: + replaceable: true + type: ER34615 + +operatingConditions: + temperature: + min: -30 + max: 70 + + relativeHumidity: + min: 0 + max: 1.00 + +ipCode: IP67 + +keyProvisioning: + - custom + - join server +keySecurity: none +productURL: https://www.milesight-iot.com/lorawan/sensor/em500-series/?utm_source=platform&utm_medium=web&utm_campaign=milesight +dataSheetURL: https://resource.milesight-iot.com/milesight/document/em500-smtc-datasheet-en.pdf +resellerURLs: + - name: 'iot.sales@milesight.com' + region: + - United States + - European Union + - Canada + url: https://www.alibaba.com/product-detail/LoRaWan-sensor-EM500-SMT-MEC-for_1600094905982.html?spm=a2700.details.0.0.25eb4624m9AFpX + +photos: + main: em500-smtc.png diff --git a/vendor/milesight-iot/em500-swl-codec.yaml b/vendor/milesight-iot/em500-swl-codec.yaml new file mode 100644 index 0000000000..eb4e5f357f --- /dev/null +++ b/vendor/milesight-iot/em500-swl-codec.yaml @@ -0,0 +1,13 @@ +# Uplink decoder decodes binary data uplink into a JSON object (optional) +# For documentation on writing encoders and decoders, see: https://thethingsstack.io/integrations/payload-formatters/javascript/ +uplinkDecoder: + fileName: em500-swl.js + examples: + - description: Submersible Water Lever Sensor (example 1) - Milesight IoT + input: + fPort: 85 + bytes: [0x01, 0x75, 0x5C, 0x03, 0x77, 0x02, 0x00] + output: + data: + battery: 92 + distance: 2 diff --git a/vendor/milesight-iot/em500-swl.js b/vendor/milesight-iot/em500-swl.js new file mode 100644 index 0000000000..c94d83a9b6 --- /dev/null +++ b/vendor/milesight-iot/em500-swl.js @@ -0,0 +1,53 @@ +function decodeUplink(input) { + var res = Decoder(input.bytes, input.fPort); + if (res.error) { + return { + errors: [res.error], + }; + } + return { + data: res, + }; +} +/** + * Payload Decoder for The Things Network + * + * Copyright 2021 Milesight IoT + * + * @product EM500-SWL + */ +function Decoder(bytes, port) { + var decoded = {}; + + for (var i = 0; i < bytes.length;) { + var channel_id = bytes[i++]; + var channel_type = bytes[i++]; + // BATTERY + if (channel_id === 0x01 && channel_type === 0x75) { + decoded.battery = bytes[i]; + i += 1; + } + // WATER LEVEL + else if (channel_id === 0x03 && channel_type === 0x77) { + decoded.distance = readUInt16LE(bytes.slice(i, i + 2)); + i += 2; + } else { + break; + } + } + + return decoded; +} + +/* ****************************************** + * bytes to number + ********************************************/ +function readUInt16LE(bytes) { + var value = (bytes[1] << 8) + bytes[0]; + return value & 0xffff; +} + +function readInt16LE(bytes) { + var ref = readUInt16LE(bytes); + return ref > 0x7fff ? ref - 0x10000 : ref; +} \ No newline at end of file diff --git a/vendor/milesight-iot/em500-swl.png b/vendor/milesight-iot/em500-swl.png new file mode 100644 index 0000000000..638c7a7730 Binary files /dev/null and b/vendor/milesight-iot/em500-swl.png differ diff --git a/vendor/milesight-iot/em500-swl.yaml b/vendor/milesight-iot/em500-swl.yaml new file mode 100644 index 0000000000..0f46c91990 --- /dev/null +++ b/vendor/milesight-iot/em500-swl.yaml @@ -0,0 +1,87 @@ +name: Milesight EM500-SWL Submersible Water Level +description: Milesight EM500-SWL is designed for measuring liquid levels in harsh environments. M500-SWL features a long-lasting battery life of up to 10 years, an IP67 UV-resistant and waterproof enclosure, and can be easily configured via NFC. It offers a stainless probe with corrosion resistance and a customizable measuring range up to 200m. EM500-SWL is widely used for applications like tank level monitoring, river level monitoring, etc. + +hardwareVersions: + - version: 'V1.x' + numeric: 1 + +firmwareVersions: + - version: '2.x' + numeric: 1 + hardwareVersions: + - 'V1.x' + + profiles: + EU863-870: + id: profile-eu868 + lorawanCertified: true + codec: em500-swl-codec + US902-928: + id: profile-us915 + lorawanCertified: true + codec: em500-swl-codec + AU915-928: + id: profile-au915 + lorawanCertified: true + codec: em500-swl-codec + AS923: + id: profile-as923 + lorawanCertified: true + codec: em500-swl-codec + CN470-510: + id: profile-cn470 + lorawanCertified: true + codec: em500-swl-codec + KR920-923: + id: profile-kr920 + lorawanCertified: true + codec: em500-swl-codec + IN865-867: + id: profile-in865 + lorawanCertified: true + codec: em500-swl-codec + RU864-870: + id: profile-ru864 + lorawanCertified: true + codec: em500-swl-codec + +sensors: + - battery + - distance + +dimensions: + width: 71 + length: 69.5 + height: 105.4 + +battery: + replaceable: true + type: ER34615 + +operatingConditions: + temperature: + min: -30 + max: 65 + + relativeHumidity: + min: 0 + max: 1.00 + +ipCode: IP67 + +keyProvisioning: + - custom + - join server +keySecurity: none +productURL: https://www.milesight-iot.com/lorawan/sensor/em500-series/?utm_source=platform&utm_medium=web&utm_campaign=milesight +dataSheetURL: https://resource.milesight-iot.com/milesight/document/em500-swl-datasheet-en.pdf +resellerURLs: + - name: 'iot.sales@milesight.com' + region: + - United States + - European Union + - Canada + url: https://www.alibaba.com/product-detail/EM500-SWL-Series-Submersible-Water-Level_62482085244.html?spm=a2700.shop_plser.41413.30.7fdf1a83ENIQ1v + +photos: + main: em500-swl.png diff --git a/vendor/milesight-iot/em500-udl.js b/vendor/milesight-iot/em500-udl.js index 087248a4c5..2276d41563 100644 --- a/vendor/milesight-iot/em500-udl.js +++ b/vendor/milesight-iot/em500-udl.js @@ -18,37 +18,37 @@ * } */ function Decoder(bytes, port) { - var decoded = {}; + var decoded = {}; - for (var i = 0; i < bytes.length; ) { - var channel_id = bytes[i++]; - var channel_type = bytes[i++]; - // BATTERY - if (channel_id === 0x01 && channel_type === 0x75) { - decoded.battery = bytes[i]; - i += 1; - } - // DISTANCE - else if (channel_id === 0x03 && channel_type === 0x82) { - decoded.distance = readInt16LE(bytes.slice(i, i + 2))/1000; - i += 2; - } else { - break; - } + for (var i = 0; i < bytes.length;) { + var channel_id = bytes[i++]; + var channel_type = bytes[i++]; + // BATTERY + if (channel_id === 0x01 && channel_type === 0x75) { + decoded.battery = bytes[i]; + i += 1; + } + // DISTANCE + else if (channel_id === 0x03 && channel_type === 0x82) { + decoded.distance = readInt16LE(bytes.slice(i, i + 2)) / 1000; + i += 2; + } else { + break; } - - return decoded; } - /******************************************* - * bytes to number - ********************************************/ - function readUInt16LE(bytes) { - var value = (bytes[1] << 8) + bytes[0]; - return value & 0xffff; - } + return decoded; +} + +/******************************************* + * bytes to number + ********************************************/ +function readUInt16LE(bytes) { + var value = (bytes[1] << 8) + bytes[0]; + return value & 0xffff; +} - function readInt16LE(bytes) { - var ref = readUInt16LE(bytes); - return ref > 0x7fff ? ref - 0x10000 : ref; - } \ No newline at end of file +function readInt16LE(bytes) { + var ref = readUInt16LE(bytes); + return ref > 0x7fff ? ref - 0x10000 : ref; +} \ No newline at end of file diff --git a/vendor/milesight-iot/em500-udl.png b/vendor/milesight-iot/em500-udl.png new file mode 100644 index 0000000000..9391675892 Binary files /dev/null and b/vendor/milesight-iot/em500-udl.png differ diff --git a/vendor/milesight-iot/gs101-codec.yaml b/vendor/milesight-iot/gs101-codec.yaml new file mode 100644 index 0000000000..f249d01ed5 --- /dev/null +++ b/vendor/milesight-iot/gs101-codec.yaml @@ -0,0 +1,4 @@ +# Uplink decoder decodes binary data uplink into a JSON object (optional) +# For documentation on writing encoders and decoders, see: https://thethingsstack.io/integrations/payload-formatters/javascript/ +uplinkDecoder: + fileName: gs101.js diff --git a/vendor/milesight-iot/gs101.js b/vendor/milesight-iot/gs101.js new file mode 100644 index 0000000000..a260337f8c --- /dev/null +++ b/vendor/milesight-iot/gs101.js @@ -0,0 +1,92 @@ +function decodeUplink(input) { + var res = Decoder(input.bytes, input.fPort); + if (res.error) { + return { + errors: [res.error], + }; + } + return { + data: res, + }; +} +/** + * Payload Decoder for The Things Network + * + * Copyright 2023 Milesight IoT + * + * @product GS101 + */ +function Decoder(bytes, port) { + return milesight(bytes); +} + +function milesight(bytes) { + var decoded = {}; + + for (var i = 0; i < bytes.length; ) { + var channel_id = bytes[i++]; + var channel_type = bytes[i++]; + //gas status + if (channel_id === 0x05 && channel_type === 0x8e) { + decoded.state = bytes[i] === 0 ? "normal" : "abnormal"; + i += 1; + } + //vale + else if (channel_id === 0x06 && channel_type === 0x01) { + decoded.valve = bytes[i] === 0 ? "close" : "open"; + i += 1; + } + //relay + else if (channel_id === 0x07 && channel_type === 0x01) { + decoded.relay = bytes[i] === 0 ? "close" : "open"; + i += 1; + } + //remained life time for the sensor + else if (channel_id === 0x08 && channel_type === 0x90) { + decoded.life_remain = readUInt32LE(bytes.slice(i, i + 4)) + "s"; + i += 4; + } + //alarm info + else if (channel_id === 0xff && channel_type === 0x3f) { + var alarm_type = bytes[i]; + switch (alarm_type) { + case 0: + decoded.alarm = "power down"; + i += 1; + break; + case 1: + decoded.alarm = "power on"; + i += 1; + break; + case 2: + decoded.alarm = "sensor failure"; + i += 1; + break; + case 3: + decoded.alarm = "sensor recover"; + i += 1; + break; + case 4: + decoded.alarm = "sensor about to fail"; + i += 1; + break; + case 5: + decoded.alarm = "sensor failed"; + i += 1; + break; + } + } else { + break; + } + } + + return decoded; +} + +/* ****************************************** + * bytes to number + ********************************************/ +function readUInt32LE(bytes) { + var value = (bytes[3] << 24) + (bytes[2] << 16) + (bytes[1] << 8) + bytes[0]; + return (value & 0xffffffff) >>> 0; +} diff --git a/vendor/milesight-iot/gs101.png b/vendor/milesight-iot/gs101.png new file mode 100644 index 0000000000..f74ce96ea0 Binary files /dev/null and b/vendor/milesight-iot/gs101.png differ diff --git a/vendor/milesight-iot/gs101.yaml b/vendor/milesight-iot/gs101.yaml new file mode 100644 index 0000000000..0cdf814826 --- /dev/null +++ b/vendor/milesight-iot/gs101.yaml @@ -0,0 +1,97 @@ +name: LoRaWAN Gas Detector +description: GS101 is a LoRaWAN ® residential gas detector to detect thenatural gas leak and send alarms. +hardwareVersions: + - version: 'V1.0' + numeric: 1 + +firmwareVersions: + - version: '1.01' + numeric: 1 + hardwareVersions: + - 'V1.0' + + profiles: + EU863-870: + id: profile-eu868 + codec: gs101-codec + US902-928: + id: profile-us915 + codec: gs101-codec + AU915-928: + id: profile-au915 + codec: gs101-codec + AS923: + id: profile-as923 + codec: gs101-codec + CN470-510: + id: profile-cn470 + codec: gs101-codec + KR920-923: + id: profile-kr920 + codec: gs101-codec + IN865-867: + id: profile-in865 + codec: gs101-codec + RU864-870: + id: profile-ru864 + codec: gs101-codec + +sensors: + - battery + - iaq + - smart valve + +# 4-20 ma, accelerometer, altitude, analog input, auxiliary, barometer, battery, button, bvoc, co, co2, conductivity, +# current, digital input, dissolved oxygen, distance, dust, energy, gps, gyroscope, h2s, humidity, iaq, level, light, +# lightning, link, magnetometer, moisture, motion, no, no2, o3, particulate matter, ph, pir, pm2.5, pm10, potentiometer, +# power, precipitation, pressure, proximity, pulse count, pulse frequency, radar, rainfall, rssi, smart valve, snr, so2, +# solar radiation, sound, strain, surface temperature, temperature, tilt, time, tvoc, uv, vapor pressure, velocity, +# vibration, voltage, water potential, water, weight, wifi ssid, wind direction, wind speed. + +dimensions: + width: 80 + length: 65 + height: 118 + +operatingConditions: + temperature: + min: -30 + max: 70 + + relativeHumidity: + min: 0 + max: 0.95 + +ipCode: IP30 + +keyProvisioning: + - custom + - join server +keySecurity: none +productURL: https://www.milesight-iot.com/products/lorawan-sensor/gs101/ +dataSheetURL: https://resource.milesight.com/milesight/iot/document/gs101-datasheet-en.pdf +resellerURLs: + - name: 'iot.sales@milesight.com' + region: + - United States + - European Union + - Canada + url: https://www.milesight-iot.com/contact-us/ + +photos: + main: gs101.png + +compliances: + safety: + - body: IEC + norm: EN + standard: 62368-1 + radioEquipment: + - body: ETSI + norm: EN + standard: 301 489-1 + version: 2.2.0 + - body: ETSI + norm: EN + standard: 301 489-3 + version: 2.1.0 diff --git a/vendor/milesight-iot/gs301-codec.yaml b/vendor/milesight-iot/gs301-codec.yaml new file mode 100644 index 0000000000..0a0f679947 --- /dev/null +++ b/vendor/milesight-iot/gs301-codec.yaml @@ -0,0 +1,17 @@ +# Uplink decoder decodes binary data uplink into a JSON object (optional) +# For documentation on writing encoders and decoders, see: https://thethingsstack.io/integrations/payload-formatters/javascript/ +uplinkDecoder: + fileName: gs301.js + examples: + - description: LoRaWAN Bathroom Odor Detector - Milesight IoT + input: + fPort: 85 + bytes: [0x01, 0x75, 0x64, 0x02, 0x67, 0x1C, 0x01, 0x03, 0x68, 0x64, 0x04, 0x7D, 0x00, 0x00, 0x05, 0x7D, 0x01, 0x00] + + output: + data: + battery: 100 + temperature: 28.4 + humidity: 50 + nh3: 0 + h2s: 0.01 diff --git a/vendor/milesight-iot/gs301.js b/vendor/milesight-iot/gs301.js new file mode 100644 index 0000000000..f2f2e99f6f --- /dev/null +++ b/vendor/milesight-iot/gs301.js @@ -0,0 +1,77 @@ +function decodeUplink(input) { + var res = Decoder(input.bytes, input.fPort); + if (res.error) { + return { + errors: [res.error], + }; + } + return { + data: res, + }; +} +/** + * Payload Decoder for The Things Network + * + * Copyright 2023 Milesight IoT + * + * @product GS301 + */ +function Decoder(bytes, port) { + return milesight(bytes); +} + +function milesight(bytes) { + var decoded = {}; + + for (var i = 0; i < bytes.length; ) { + var channel_id = bytes[i++]; + var channel_type = bytes[i++]; + // BATTERY + if (channel_id === 0x01 && channel_type === 0x75) { + decoded.battery = bytes[i]; + i += 1; + } + // TEMPERATURE + else if (channel_id === 0x02 && channel_type === 0x67) { + // ℃ + decoded.temperature = readInt16LE(bytes.slice(i, i + 2)) / 10; + i += 2; + + // ℉ + // decoded.temperature = readInt16LE(bytes.slice(i, i + 2)) / 10 * 1.8 + 32; + // i +=2; + } + // HUMIDITY + else if (channel_id === 0x03 && channel_type === 0x68) { + decoded.humidity = bytes[i] / 2; + i += 1; + } + // NH3 + else if (channel_id === 0x04 && channel_type === 0x7d) { + decoded.nh3 = readUInt16LE(bytes.slice(i, i + 2)) / 100; + i += 2; + } + // H2S + else if (channel_id === 0x05 && channel_type === 0x7d) { + decoded.h2s = readUInt16LE(bytes.slice(i, i + 2)) / 100; + i += 2; + } else { + break; + } + } + + return decoded; +} + +/* ****************************************** + * bytes to number + ********************************************/ +function readUInt16LE(bytes) { + var value = (bytes[1] << 8) + bytes[0]; + return value & 0xffff; +} + +function readInt16LE(bytes) { + var ref = readUInt16LE(bytes); + return ref > 0x7fff ? ref - 0x10000 : ref; +} diff --git a/vendor/milesight-iot/gs301.png b/vendor/milesight-iot/gs301.png new file mode 100644 index 0000000000..8a7e3d2146 Binary files /dev/null and b/vendor/milesight-iot/gs301.png differ diff --git a/vendor/milesight-iot/gs301.yaml b/vendor/milesight-iot/gs301.yaml new file mode 100644 index 0000000000..22f07c5d01 --- /dev/null +++ b/vendor/milesight-iot/gs301.yaml @@ -0,0 +1,103 @@ +name: LoRaWAN Bathroom Odor Detector +description: GS301 is a 4-in-1 LoRaWAN® bathroomodor detector todetectammonia (NH3) and hydrogen sulfide (H2S) gas, GS301 is also able to detect temperature and humidity to fully aware of the environment of bathrooms + +hardwareVersions: + - version: 'V1.0' + numeric: 1 + +firmwareVersions: + - version: '1.01' + numeric: 1 + hardwareVersions: + - 'V1.0' + + profiles: + EU863-870: + id: profile-eu868 + codec: gs301-codec + US902-928: + id: profile-us915 + codec: gs301-codec + AU915-928: + id: profile-au915 + codec: gs301-codec + AS923: + id: profile-as923 + codec: gs301-codec + CN470-510: + id: profile-cn470 + codec: gs301-codec + KR920-923: + id: profile-kr920 + codec: gs301-codec + IN865-867: + id: profile-in865 + codec: gs301-codec + RU864-870: + id: profile-ru864 + codec: gs301-codec + +sensors: + - battery + - iaq + - temperature + - humidity + +# 4-20 ma, accelerometer, altitude, analog input, auxiliary, barometer, battery, button, bvoc, co, co2, conductivity, +# current, digital input, dissolved oxygen, distance, dust, energy, gps, gyroscope, h2s, humidity, iaq, level, light, +# lightning, link, magnetometer, moisture, motion, no, no2, o3, particulate matter, ph, pir, pm2.5, pm10, potentiometer, +# power, precipitation, pressure, proximity, pulse count, pulse frequency, radar, rainfall, rssi, smart valve, snr, so2, +# solar radiation, sound, strain, surface temperature, temperature, tilt, time, tvoc, uv, vapor pressure, velocity, +# vibration, voltage, water potential, water, weight, wifi ssid, wind direction, wind speed. + +dimensions: + width: 32.5 + length: 85 + height: 120 + +battery: + replaceable: true + type: ER18050 Li-SoCl2 battery*4 + +operatingConditions: + temperature: + min: -40 + max: 55 + + relativeHumidity: + min: 0 + max: 0.95 + +ipCode: IP30 + +keyProvisioning: + - custom + - join server +keySecurity: none +productURL: https://www.milesight-iot.com/products/lorawan-sensor/gs301/ +dataSheetURL: https://resource.milesight.com/milesight/iot/document/gs301-datasheet-en.pdf +resellerURLs: + - name: 'iot.sales@milesight.com' + region: + - United States + - European Union + - Canada + url: https://www.milesight-iot.com/contact-us/ + +photos: + main: gs301.png + +compliances: + safety: + - body: IEC + norm: EN + standard: 62368-1 + radioEquipment: + - body: ETSI + norm: EN + standard: 301 489-1 + version: 2.2.0 + - body: ETSI + norm: EN + standard: 301 489-3 + version: 2.1.0 diff --git a/vendor/milesight-iot/index.yaml b/vendor/milesight-iot/index.yaml index 7b342dc040..404a740917 100644 --- a/vendor/milesight-iot/index.yaml +++ b/vendor/milesight-iot/index.yaml @@ -7,3 +7,58 @@ endDevices: - em300-mcs - em500-co2 - em500-udl + - am103 + - am103l + - am104 + - am307 + - am319 + - em300-sld + - em300-zld + - em310-udl + - em500-lgt + - em500-pp + - em500-pt100 + - em500-smt + - em500-smtc + - em500-swl + - uc1114 + - uc1122 + - uc1152 + - uc100 + - uc300 + - uc50x + - uc51x + - vs121 + - ws50x + - ws52x + - ws101 + - ws136 + - ws156 + - ws202 + - ws301 + - ws558 + - am307l + - am308 + - am308l + - am319l + - em300-di + - em300-mld + - em310-tilt + - em320-th + - em320-tilt + - em400-mud + - em400-tld + - em400-udl + - gs101 + - gs301 + - ts101 + - vs133 + - vs330 + - vs340 + - ws201 + - ws203 + - ws302 + - ws303 + - wts305 + - wts505 + - wts506 diff --git a/vendor/milesight-iot/profile-us923.yaml b/vendor/milesight-iot/profile-us923.yaml new file mode 100644 index 0000000000..97d00b9a14 --- /dev/null +++ b/vendor/milesight-iot/profile-us923.yaml @@ -0,0 +1,8 @@ +vendorProfileID: 601 +macVersion: 1.1 +regionalParametersVersion: RP001-1.1-RevB +supportsJoin: true +maxEIRP: 20 +supports32bitFCnt: true +supportsClassB: false +supportsClassC: false diff --git a/vendor/milesight-iot/ts101-codec.yaml b/vendor/milesight-iot/ts101-codec.yaml new file mode 100644 index 0000000000..7ef93c4421 --- /dev/null +++ b/vendor/milesight-iot/ts101-codec.yaml @@ -0,0 +1,14 @@ +# Uplink decoder decodes binary data uplink into a JSON object (optional) +# For documentation on writing encoders and decoders, see: https://thethingsstack.io/integrations/payload-formatters/javascript/ +uplinkDecoder: + fileName: ts101.js + examples: + - description: LoRaWAN Insertion Temperature Sensor - Milesight IoT + input: + fPort: 85 + bytes: [0x01, 0x75, 0x64, 0x03, 0x67, 0x07, 0x01] + + output: + data: + battery: 100 + temperature: 26.3 diff --git a/vendor/milesight-iot/ts101.js b/vendor/milesight-iot/ts101.js new file mode 100644 index 0000000000..a48b3fa6c1 --- /dev/null +++ b/vendor/milesight-iot/ts101.js @@ -0,0 +1,96 @@ +function decodeUplink(input) { + var res = Decoder(input.bytes, input.fPort); + if (res.error) { + return { + errors: [res.error], + }; + } + return { + data: res, + }; +} +/** + * Payload Decoder for The Things Network + * + * Copyright 2023 Milesight IoT + * + * @product TS101 + */ +function Decoder(bytes, port) { + return milesight(bytes); +} + +function milesight(bytes) { + var decoded = {}; + + for (var i = 0; i < bytes.length; ) { + var channel_id = bytes[i++]; + var channel_type = bytes[i++]; + // battery + if (channel_id === 0x01 && channel_type === 0x75) { + decoded.battery = bytes[i]; + i += 1; + } + // temperature + else if (channel_id === 0x03 && channel_type === 0x67) { + decoded.temperature = readInt16LE(bytes.slice(i, i + 2)) / 10; + i += 2; + } + // temperature threshold alert + else if (channel_id === 0x83 && channel_type === 0x67) { + decoded.temperature = readInt16LE(bytes.slice(i, i + 2)) / 10; + decoded.temperature_alert = readAlertType(bytes[i + 2]); + i += 3; + } + // temperature mutation alert + else if (channel_id === 0x93 && channel_type === 0xd7) { + decoded.temperature = readInt16LE(bytes.slice(i, i + 2)) / 10; + decoded.temperature_change = readInt16LE(bytes.slice(i + 2, i + 4)) / 100; + decoded.temperature_alert = readAlertType(bytes[i + 4]); + i += 5; + } + // temperature history + else if (channel_id === 0x20 && channel_type === 0xce) { + if (decoded.history == undefined) { + decoded.history = []; + } + var item = {}; + item.timestamp = readUInt32LE(bytes.slice(i, i + 4)); + item.temperature = readInt16LE(bytes.slice(i + 4, i + 6)) / 10; + decoded.history.push(item); + i += 6; + } else { + break; + } + } + + return decoded; +} + +function readUInt16LE(bytes) { + var value = (bytes[1] << 8) + bytes[0]; + return value & 0xffff; +} + +function readInt16LE(bytes) { + var ref = readUInt16LE(bytes); + return ref > 0x7fff ? ref - 0x10000 : ref; +} + +function readUInt32LE(bytes) { + var value = (bytes[3] << 24) + (bytes[2] << 16) + (bytes[1] << 8) + bytes[0]; + return (value & 0xffffffff) >>> 0; +} + +function readAlertType(type) { + switch (type) { + case 0: + return "normal"; + case 1: + return "threshold"; + case 2: + return "mutation"; + default: + return "unkown"; + } +} diff --git a/vendor/milesight-iot/ts101.png b/vendor/milesight-iot/ts101.png new file mode 100644 index 0000000000..49cf8101fe Binary files /dev/null and b/vendor/milesight-iot/ts101.png differ diff --git a/vendor/milesight-iot/ts101.yaml b/vendor/milesight-iot/ts101.yaml new file mode 100644 index 0000000000..3b32406a35 --- /dev/null +++ b/vendor/milesight-iot/ts101.yaml @@ -0,0 +1,101 @@ +name: LoRaWAN Insertion Temperature Sensor +description: Milesight TS101 is an all-in-one insertion temperature sensor withanintegrated transmitter. It is equipped with an advanced measuringunitthatprovides a wide temperature measuring range. + +hardwareVersions: + - version: 'V1.0' + numeric: 1 + +firmwareVersions: + - version: '1.01' + numeric: 1 + hardwareVersions: + - 'V1.0' + + profiles: + EU863-870: + id: profile-eu868 + codec: ts101-codec + US902-928: + id: profile-us915 + codec: ts101-codec + AU915-928: + id: profile-au915 + codec: ts101-codec + AS923: + id: profile-as923 + codec: ts101-codec + CN470-510: + id: profile-cn470 + codec: ts101-codec + KR920-923: + id: profile-kr920 + codec: ts101-codec + IN865-867: + id: profile-in865 + codec: ts101-codec + RU864-870: + id: profile-ru864 + codec: ts101-codec + +sensors: + - battery + - temperature + +# 4-20 ma, accelerometer, altitude, analog input, auxiliary, barometer, battery, button, bvoc, co, co2, conductivity, +# current, digital input, dissolved oxygen, distance, dust, energy, gps, gyroscope, h2s, humidity, iaq, level, light, +# lightning, link, magnetometer, moisture, motion, no, no2, o3, particulate matter, ph, pir, pm2.5, pm10, potentiometer, +# power, precipitation, pressure, proximity, pulse count, pulse frequency, radar, rainfall, rssi, smart valve, snr, so2, +# solar radiation, sound, strain, surface temperature, temperature, tilt, time, tvoc, uv, vapor pressure, velocity, +# vibration, voltage, water potential, water, weight, wifi ssid, wind direction, wind speed. + +dimensions: + width: 26 + length: 92 + height: 92 + +battery: + replaceable: true + type: ER18505 Li-SoCl2 battery + +operatingConditions: + temperature: + min: -30 + max: 70 + + relativeHumidity: + min: 0 + max: 0.95 + +ipCode: IP67 + +keyProvisioning: + - custom + - join server +keySecurity: none +productURL: https://www.milesight.com/iot/product/lorawan-sensor/ts101 +dataSheetURL: https://resource.milesight.com/milesight/iot/document/ts101-datasheet-en.pdf +resellerURLs: + - name: 'iot.sales@milesight.com' + region: + - United States + - European Union + - Canada + url: https://www.milesight-iot.com/contact-us/ + +photos: + main: ts101.png + +compliances: + safety: + - body: IEC + norm: EN + standard: 62368-1 + radioEquipment: + - body: ETSI + norm: EN + standard: 301 489-1 + version: 2.2.0 + - body: ETSI + norm: EN + standard: 301 489-3 + version: 2.1.0 diff --git a/vendor/milesight-iot/uc100-codec.yaml b/vendor/milesight-iot/uc100-codec.yaml new file mode 100644 index 0000000000..c12066bbed --- /dev/null +++ b/vendor/milesight-iot/uc100-codec.yaml @@ -0,0 +1,11 @@ +# Uplink decoder decodes binary data uplink into a JSON object +uplinkDecoder: + fileName: uc100.js + examples: + - description: LoRa Controllers (example 1) - Milesgiht IoT + input: + fPort: 85 + bytes: [0xff, 0x19, 0x07, 0x02, 0x03, 0x15, 0x00] + output: + data: + chn8: 21 diff --git a/vendor/milesight-iot/uc100.js b/vendor/milesight-iot/uc100.js new file mode 100644 index 0000000000..234765d976 --- /dev/null +++ b/vendor/milesight-iot/uc100.js @@ -0,0 +1,168 @@ +function decodeUplink(input) { + var res = Decoder(input.bytes, input.fPort); + if (res.error) { + return { + errors: [res.error], + }; + } + return { + data: res, + }; +} + +/** + * Payload Decoder for The Things Network + * + * Copyright 2022 Milesight IoT + * + * @product UC100 series + */ +function Decoder(bytes, port) { + var decoded = {}; + for (i = 0; i < bytes.length;) { + var channel_id = bytes[i++]; + var channel_type = bytes[i++]; + + // POWER STATE + if (channel_id === 0xff && channel_type === 0x0b) { + decoded.power = "on"; + i += 1; + } + // IPSO VERSION + else if (channel_id === 0xff && channel_type === 0x01) { + decoded.ipso_version = readProtocolVersion(bytes[i]); + i += 1; + } + // PRODUCT SERIAL NUMBER + else if (channel_id === 0xff && channel_type === 0x16) { + decoded.sn = readSerialNumber(bytes.slice(i, i + 8)); + i += 8; + } + // HARDWARE VERSION + else if (channel_id === 0xff && channel_type === 0x09) { + decoded.hardware_version = readHardwareVersion(bytes.slice(i, i + 2)); + i += 2; + } + // SOFTWARE VERSION + else if (channel_id === 0xff && channel_type === 0x0a) { + decoded.software_version = readSoftwareVersion(bytes.slice(i, i + 2)); + i += 2; + } + // METRICS DATA REPORT + else if (channel_id === 0xff && channel_type === 0x19) { + var modbus_chn_id = bytes[i++] + 1; + var data_length = bytes[i++]; + var data_type = bytes[i++]; + var chn = "chn" + modbus_chn_id; + switch (data_type) { + case 0: + decoded[chn] = bytes[i] ? "on" : "off"; + i += 1; + break; + case 1: + decoded[chn] = bytes[i]; + i += 1; + break; + case 2: + case 3: + decoded[chn] = readUInt16LE(bytes.slice(i, i + 2)); + i += 2; + break; + case 4: + case 6: + case 8: + case 9: + case 10: + case 11: + decoded[chn] = readUInt32LE(bytes.slice(i, i + 4)); + i += 4; + break; + case 5: + case 7: + decoded[chn] = readFloatLE(bytes.slice(i, i + 4)); + i += 4; + break; + } + } + // MODBUS READ ERROR + else if (channel_id === 0xff && channel_type === 0x15) { + + var modbus_chn_id = bytes[i] + 1; + var channel_name = "channel_" + modbus_chn_id + "_error"; + decoded[channel_name] = true; + i += 1; + } else { + break; + } + } + return decoded; +} + +/* ****************************************** + * bytes to number + ********************************************/ +function readUInt8LE(bytes) { + return bytes & 0xff; +} + +function readInt8LE(bytes) { + var ref = readUInt8LE(bytes); + return ref > 0x7f ? ref - 0x100 : ref; +} + +function readUInt16LE(bytes) { + var value = (bytes[1] << 8) + bytes[0]; + return value & 0xffff; +} + +function readInt16LE(bytes) { + var ref = readUInt16LE(bytes); + return ref > 0x7fff ? ref - 0x10000 : ref; +} + +function readUInt32LE(bytes) { + var value = (bytes[3] << 24) + (bytes[2] << 16) + (bytes[1] << 8) + bytes[0]; + return value & 0xffffffff; +} + +function readInt32LE(bytes) { + var ref = readUInt32LE(bytes); + return ref > 0x7fffffff ? ref - 0x100000000 : ref; +} + +function readFloatLE(bytes) { + // JavaScript bitwise operators yield a 32 bits integer, not a float. + // Assume LSB (least significant byte first). + var bits = (bytes[3] << 24) | (bytes[2] << 16) | (bytes[1] << 8) | bytes[0]; + var sign = bits >>> 31 === 0 ? 1.0 : -1.0; + var e = (bits >>> 23) & 0xff; + var m = e === 0 ? (bits & 0x7fffff) << 1 : (bits & 0x7fffff) | 0x800000; + var f = sign * m * Math.pow(2, e - 150); + return f; +} + +function readProtocolVersion(bytes) { + var major = (bytes & 0xf0) >> 4; + var minor = bytes & 0x0f; + return "v" + major + "." + minor; +} + +function readHardwareVersion(bytes) { + var major = bytes[0] & 0xff; + var minor = (bytes[1] & 0xff) >> 4; + return "v" + major + "." + minor; +} + +function readSoftwareVersion(bytes) { + var major = bytes[0] & 0xff; + var minor = bytes[1] & 0xff; + return "v" + major + "." + minor; +} + +function readSerialNumber(bytes) { + var temp = []; + for (var idx = 0; idx < bytes.length; idx++) { + temp.push(("0" + (bytes[idx] & 0xff).toString(16)).slice(-2)); + } + return temp.join(""); +} \ No newline at end of file diff --git a/vendor/milesight-iot/uc100.png b/vendor/milesight-iot/uc100.png new file mode 100644 index 0000000000..7d775ec690 Binary files /dev/null and b/vendor/milesight-iot/uc100.png differ diff --git a/vendor/milesight-iot/uc100.yaml b/vendor/milesight-iot/uc100.yaml new file mode 100644 index 0000000000..347755e5fc --- /dev/null +++ b/vendor/milesight-iot/uc100.yaml @@ -0,0 +1,78 @@ +name: Milesight UC100 Series IoT Controller +description: UC100 is an IoT controller used for remote control and data acquisition from Modbus RS485 devices via LoRaWAN® networks. It can read up to 16 Modbus RTU devices and support Modbus transparent transmission between server and RS485 devices as a Modbus to LoRaWAN® converter. Besides, UC100 supports multiple trigger conditions and actions which can work autonomously even when the network dropped. Combining with Milesight IoT Cloud solution, it can monitor and control remote assets via web server or mobile App easily. UC100 is widely used in indoor applications like smart metering, smart cities, building automation, etc. + +hardwareVersions: + - version: 'V1.0' + numeric: 1 + +firmwareVersions: + - version: '1.x' + numeric: 1 + hardwareVersions: + - 'V1.0' + + profiles: + EU863-870: + id: profile-eu868 + codec: uc100-codec + US902-928: + id: profile-us915 + codec: uc100-codec + AU915-928: + id: profile-au915 + codec: uc100-codec + AS923: + id: profile-as923 + codec: uc100-codec + CN470-510: + id: profile-cn470 + codec: uc100-codec + KR920-923: + id: profile-kr920 + codec: uc100-codec + IN865-867: + id: profile-in865 + codec: uc100-codec + RU864-870: + id: profile-ru864 + codec: uc100-codec + +#sensors: +# modbus channels + +bridgeInterfaces: + - modbus + - rs-485 + +dimensions: + width: 70 + length: 45 + height: 13 + +operatingConditions: + temperature: + min: -20 + max: 60 + + relativeHumidity: + min: 0 + max: 0.95 + +ipCode: IP30 + +keyProvisioning: + - custom + - join server +keySecurity: none +productURL: https://www.milesight-iot.com/controller/uc100-iot-lorawan-controller/ +dataSheetURL: https://resource.milesight-iot.com/milesight/document/uc100-datasheet-en.pdf +resellerURLs: + - name: 'iot.sales@milesight.com' + region: + - United States + - European Union + - Canada + url: https://www.alibaba.com/product-detail/Milesight-UC100-IoT-Controller_1600114835889.html?spm=a2700.galleryofferlist.normal_offer.d_title.1b6e5b85Uvb080 + +photos: + main: uc100.png diff --git a/vendor/milesight-iot/uc1114-codec.yaml b/vendor/milesight-iot/uc1114-codec.yaml new file mode 100644 index 0000000000..d76dfd79dc --- /dev/null +++ b/vendor/milesight-iot/uc1114-codec.yaml @@ -0,0 +1,18 @@ +# Uplink decoder decodes binary data uplink into a JSON object +uplinkDecoder: + fileName: uc1114.js + examples: + - description: Remote I/O Controllers (example 1) - Milesight IoT + input: + fPort: 85 + bytes: [0x01, 0x00, 0x01] + output: + data: + digital_input_1: on + - description: Remote I/O Controllers (example 2) - Milesgiht IoT + input: + fPort: 85 + bytes: [0x02, 0xc8, 0x3c, 0x00, 0x00, 0x00] + output: + data: + digital_input_2: on diff --git a/vendor/milesight-iot/uc1114.js b/vendor/milesight-iot/uc1114.js new file mode 100644 index 0000000000..c089a4d3f4 --- /dev/null +++ b/vendor/milesight-iot/uc1114.js @@ -0,0 +1,102 @@ +function decodeUplink(input) { + var res = Decoder(input.bytes, input.fPort); + if (res.error) { + return { + errors: [res.error], + }; + } + return { + data: res, + }; +} +/** + * Payload Decoder for The Things Network + * + * Copyright 2021 Milesight IoT + * + * @product UC11 series + */ +function Decoder(bytes, port) { + var decoded = {}; + + for (i = 0; i < bytes.length;) { + var channel_id = bytes[i++]; + var channel_type = bytes[i++]; + + // Digital Input 1 + if (channel_id === 0x01 && channel_type !== 0x00) { + decoded.digital_input_1 = bytes[i] === 0 ? "off" : "on"; + i += 1; + } + // Digital Input 2 + else if (channel_id === 0x02 && channel_type !== 0x00) { + decoded.digital_input_2 = bytes[i] === 0 ? "off" : "on"; + i += 1; + } + // Pulse Counter 1 + else if (channel_id === 0x01 && channel_type === 0xc8) { + decoded.pulse_count_1 = readUInt32LE(bytes.slice(i, i + 4)); + i += 4; + } + // Pulse Counter 1 + else if (channel_id === 0x02 && channel_type === 0xc8) { + decoded.pulse_count_2 = readUInt32LE(bytes.slice(i, i + 4)); + i += 4; + } + // Digital Output 1 + else if (channel_id === 0x09) { + decoded.digital_output_1 = bytes[i] === 0 ? "off" : "on"; + i += 1; + } + // Digital Output 2 + else if (channel_id === 0x0a) { + decoded.digital_output_2 = bytes[i] === 0 ? "off" : "on"; + i += 1; + } + } + + return decoded; +} + +/* ****************************************** + * bytes to number + ********************************************/ +function readUInt8LE(bytes) { + return (bytes & 0xFF); +} + +function readInt8LE(bytes) { + var ref = readUInt8LE(bytes); + return (ref > 0x7F) ? ref - 0x100 : ref; +} + +function readUInt16LE(bytes) { + var value = (bytes[1] << 8) + bytes[0]; + return (value & 0xFFFF); +} + +function readInt16LE(bytes) { + var ref = readUInt16LE(bytes); + return (ref > 0x7FFF) ? ref - 0x10000 : ref; +} + +function readUInt32LE(bytes) { + var value = (bytes[3] << 24) + (bytes[2] << 16) + (bytes[1] << 8) + bytes[0]; + return (value & 0xFFFFFFFF); +} + +function readInt32LE(bytes) { + var ref = readUInt32LE(bytes); + return (ref > 0x7FFFFFFF) ? ref - 0x100000000 : ref; +} + +function readFloatLE(bytes) { + // JavaScript bitwise operators yield a 32 bits integer, not a float. + // Assume LSB (least significant byte first). + var bits = bytes[3] << 24 | bytes[2] << 16 | bytes[1] << 8 | bytes[0]; + var sign = (bits >>> 31 === 0) ? 1.0 : -1.0; + var e = bits >>> 23 & 0xff; + var m = (e === 0) ? (bits & 0x7fffff) << 1 : (bits & 0x7fffff) | 0x800000; + var f = sign * m * Math.pow(2, e - 150); + return f; +} diff --git a/vendor/milesight-iot/uc1114.png b/vendor/milesight-iot/uc1114.png new file mode 100644 index 0000000000..5ee85e5a20 Binary files /dev/null and b/vendor/milesight-iot/uc1114.png differ diff --git a/vendor/milesight-iot/uc1114.yaml b/vendor/milesight-iot/uc1114.yaml new file mode 100644 index 0000000000..f1d54f105b --- /dev/null +++ b/vendor/milesight-iot/uc1114.yaml @@ -0,0 +1,66 @@ +name: UC1114 +description: LoRa Controller + +hardwareVersions: + - version: 'V3.x' + numeric: 1 + +firmwareVersions: + - version: '3.09' + numeric: 1 + hardwareVersions: + - 'V3.x' + + profiles: + EU863-870: + id: profile-eu868 + codec: uc1114-codec + US902-928: + id: profile-us915 + codec: uc1114-codec + AU915-928: + id: profile-au915 + codec: uc1114-codec + AS923: + id: profile-as923 + codec: uc1114-codec + CN470-510: + id: profile-cn470 + codec: uc1114-codec + KR920-923: + id: profile-kr920 + codec: uc1114-codec + IN865-867: + id: profile-in865 + codec: uc1114-codec + RU864-870: + id: profile-ru864 + codec: uc1114-codec + +sensors: + - digital input + - pulse count + +dimensions: + width: 24 + length: 79 + height: 60 + +operatingConditions: + temperature: + min: -40 + max: 70 + + relativeHumidity: + min: 0 + max: 0.95 + +ipCode: IP30 + +keyProvisioning: + - custom + - join server +keySecurity: none + +photos: + main: uc1114.png diff --git a/vendor/milesight-iot/uc1122-codec.yaml b/vendor/milesight-iot/uc1122-codec.yaml new file mode 100644 index 0000000000..f2c124a2cb --- /dev/null +++ b/vendor/milesight-iot/uc1122-codec.yaml @@ -0,0 +1,22 @@ +# Uplink decoder decodes binary data uplink into a JSON object +uplinkDecoder: + fileName: uc1122.js + examples: + - description: Remote I/O Controllers (example 1) - Milesight IoT + input: + fPort: 85 + bytes: [0x01, 0x00, 0x01] + output: + data: + digital_input: on + - description: Remote I/O Controllers (example 2) - Milesgiht IoT + input: + fPort: 85 + bytes: [0x11, 0x02, 0x0D, 0x00, 0x0A, 0x00, 0x0F, 0x00, 0x0B, 0x00] + output: + data: + analog_input_1: + avg: 0.11 + cur: 0.13 + min: 0.10 + max: 0.15 diff --git a/vendor/milesight-iot/uc1122.js b/vendor/milesight-iot/uc1122.js new file mode 100644 index 0000000000..9aced59aa3 --- /dev/null +++ b/vendor/milesight-iot/uc1122.js @@ -0,0 +1,102 @@ +function decodeUplink(input) { + var res = Decoder(input.bytes, input.fPort); + if (res.error) { + return { + errors: [res.error], + }; + } + return { + data: res, + }; +} +/** + * Payload Decoder for The Things Network + * + * Copyright 2021 Milesight IoT + * + * @product UC11 series + */ +function Decoder(bytes, port) { + var decoded = {}; + + for (i = 0; i < bytes.length;) { + var channel_id = bytes[i++]; + var channel_type = bytes[i++]; + + // Digital Input 1 + if (channel_id === 0x01 && channel_type !== 0xc8) { + decoded.digital_input = bytes[i] === 0 ? "off" : "on"; + i += 1; + } + // Digital Output 1 + else if (channel_id === 0x09) { + decoded.digital_output = bytes[i] === 0 ? "off" : "on"; + i += 1; + } + // ADC 1 + else if (channel_id === 0x11) { + decoded.analog_input_1 = {}; + decoded.analog_input_1.cur = readInt16LE(bytes.slice(i, i + 2)) / 100; + decoded.analog_input_1.min = readInt16LE(bytes.slice(i + 2, i + 4)) / 100; + decoded.analog_input_1.max = readInt16LE(bytes.slice(i + 4, i + 6)) / 100; + decoded.analog_input_1.avg = readInt16LE(bytes.slice(i + 6, i + 8)) / 100; + i += 8; + continue; + } + // ADC 2 + else if (channel_id === 0x12) { + decoded.analog_input_2 = {}; + decoded.analog_input_2.cur = readInt16LE(bytes.slice(i, i + 2)) / 100; + decoded.analog_input_2.min = readInt16LE(bytes.slice(i + 2, i + 4)) / 100; + decoded.analog_input_2.max = readInt16LE(bytes.slice(i + 4, i + 6)) / 100; + decoded.analog_input_2.avg = readInt16LE(bytes.slice(i + 6, i + 8)) / 100; + i += 8; + continue; + } + } + + return decoded; +} + +/* ****************************************** + * bytes to number + ********************************************/ +function readUInt8LE(bytes) { + return (bytes & 0xFF); +} + +function readInt8LE(bytes) { + var ref = readUInt8LE(bytes); + return (ref > 0x7F) ? ref - 0x100 : ref; +} + +function readUInt16LE(bytes) { + var value = (bytes[1] << 8) + bytes[0]; + return (value & 0xFFFF); +} + +function readInt16LE(bytes) { + var ref = readUInt16LE(bytes); + return (ref > 0x7FFF) ? ref - 0x10000 : ref; +} + +function readUInt32LE(bytes) { + var value = (bytes[3] << 24) + (bytes[2] << 16) + (bytes[1] << 8) + bytes[0]; + return (value & 0xFFFFFFFF); +} + +function readInt32LE(bytes) { + var ref = readUInt32LE(bytes); + return (ref > 0x7FFFFFFF) ? ref - 0x100000000 : ref; +} + +function readFloatLE(bytes) { + // JavaScript bitwise operators yield a 32 bits integer, not a float. + // Assume LSB (least significant byte first). + var bits = bytes[3] << 24 | bytes[2] << 16 | bytes[1] << 8 | bytes[0]; + var sign = (bits >>> 31 === 0) ? 1.0 : -1.0; + var e = bits >>> 23 & 0xff; + var m = (e === 0) ? (bits & 0x7fffff) << 1 : (bits & 0x7fffff) | 0x800000; + var f = sign * m * Math.pow(2, e - 150); + return f; +} diff --git a/vendor/milesight-iot/uc1122.png b/vendor/milesight-iot/uc1122.png new file mode 100644 index 0000000000..5ee85e5a20 Binary files /dev/null and b/vendor/milesight-iot/uc1122.png differ diff --git a/vendor/milesight-iot/uc1122.yaml b/vendor/milesight-iot/uc1122.yaml new file mode 100644 index 0000000000..809ed67228 --- /dev/null +++ b/vendor/milesight-iot/uc1122.yaml @@ -0,0 +1,79 @@ +name: UC1122 +description: LoRa Controller + +hardwareVersions: + - version: 'V3.x' + numeric: 1 + +firmwareVersions: + - version: '3.09' + numeric: 1 + hardwareVersions: + - 'V3.x' + + profiles: + EU863-870: + id: profile-eu868 + codec: uc1122-codec + US902-928: + id: profile-us915 + codec: uc1122-codec + AU915-928: + id: profile-au915 + codec: uc1122-codec + AS923: + id: profile-as923 + codec: uc1122-codec + CN470-510: + id: profile-cn470 + codec: uc1122-codec + KR920-923: + id: profile-kr920 + codec: uc1122-codec + IN865-867: + id: profile-in865 + codec: uc1122-codec + RU864-870: + id: profile-ru864 + codec: uc1122-codec + +sensors: + - digital input + - analog input + # cur + # min + # max + # avg + # analog input 2 + # cur + # min + # max + # avg + # digital output + +bridgeInterfaces: + - analog + +dimensions: + width: 24 + length: 79 + height: 60 + +operatingConditions: + temperature: + min: -40 + max: 70 + + relativeHumidity: + min: 0 + max: 0.95 + +ipCode: IP30 + +keyProvisioning: + - custom + - join server +keySecurity: none + +photos: + main: uc1122.png diff --git a/vendor/milesight-iot/uc1152-codec.yaml b/vendor/milesight-iot/uc1152-codec.yaml new file mode 100644 index 0000000000..d886cc4b27 --- /dev/null +++ b/vendor/milesight-iot/uc1152-codec.yaml @@ -0,0 +1,18 @@ +# Uplink decoder decodes binary data uplink into a JSON object +uplinkDecoder: + fileName: uc1152.js + examples: + - description: Remote I/O Controllers (example 1) - Milesight IoT + input: + fPort: 85 + bytes: [0x09, 0x01, 0x01] + output: + data: + digital_output: on + - description: Remote I/O Controllers (example 2) - Milesgiht IoT + input: + fPort: 85 + bytes: [0xFF, 0x0E, 0x19, 0x13, 0x04, 0x00] + output: + data: + channels: [{ index: 1, reading: 4 }] diff --git a/vendor/milesight-iot/uc1152.js b/vendor/milesight-iot/uc1152.js new file mode 100644 index 0000000000..cbc8d9c75c --- /dev/null +++ b/vendor/milesight-iot/uc1152.js @@ -0,0 +1,127 @@ +function decodeUplink(input) { + var res = Decoder(input.bytes, input.fPort); + if (res.error) { + return { + errors: [res.error], + }; + } + return { + data: res, + }; +} +/** + * Payload Decoder for The Things Network + * + * Copyright 2021 Milesight IoT + * + * @product UC11 series + */ +function Decoder(bytes, port) { + var decoded = {}; + + for (i = 0; i < bytes.length;) { + var channel_id = bytes[i++]; + var channel_type = bytes[i++]; + + // Digital Input 1 + if (channel_id === 0x01 && channel_type !== 0xc8) { + decoded.digital_input = bytes[i] === 0 ? "off" : "on"; + i += 1; + } + // Digital Output 1 + else if (channel_id === 0x09) { + decoded.digital_output = bytes[i] === 0 ? "off" : "on"; + i += 1; + } + // MODBUS + else if (channel_id === 0xFF && channel_type === 0x0E) { + var modbus_chn_id = bytes[i++]; + var package_type = bytes[i++]; + var data_type = package_type & 7; + var date_length = package_type >> 3; + var chn = modbus_chn_id - 0x18; + decoded.channels = []; + var channel = {}; + switch (data_type) { + case 0: + channel['index'] = chn; + channel['reading'] = bytes[i] ? "on" : "off"; + decoded.channels.push(channel); + i += 1; + break; + case 1: + channel['index'] = chn; + channel['reading'] = bytes[i]; + decoded.channels.push(channel); + i += 1; + break; + case 2: + case 3: + channel['index'] = chn; + channel['reading'] = readUInt16LE(bytes.slice(i, i + 2)); + decoded.channels.push(channel); + i += 2; + break; + case 4: + case 6: + channel['index'] = chn; + channel['reading'] = readUInt32LE(bytes.slice(i, i + 4)); + decoded.channels.push(channel); + i += 4; + break; + case 5: + case 7: + channel['index'] = chn; + channel['reading'] = readFloatLE(bytes.slice(i, i + 4)); + decoded.channels.push(channel); + i += 4; + break; + } + } + } + + return decoded; +} + +/* ****************************************** + * bytes to number + ********************************************/ +function readUInt8LE(bytes) { + return (bytes & 0xFF); +} + +function readInt8LE(bytes) { + var ref = readUInt8LE(bytes); + return (ref > 0x7F) ? ref - 0x100 : ref; +} + +function readUInt16LE(bytes) { + var value = (bytes[1] << 8) + bytes[0]; + return (value & 0xFFFF); +} + +function readInt16LE(bytes) { + var ref = readUInt16LE(bytes); + return (ref > 0x7FFF) ? ref - 0x10000 : ref; +} + +function readUInt32LE(bytes) { + var value = (bytes[3] << 24) + (bytes[2] << 16) + (bytes[1] << 8) + bytes[0]; + return (value & 0xFFFFFFFF); +} + +function readInt32LE(bytes) { + var ref = readUInt32LE(bytes); + return (ref > 0x7FFFFFFF) ? ref - 0x100000000 : ref; +} + +function readFloatLE(bytes) { + // JavaScript bitwise operators yield a 32 bits integer, not a float. + // Assume LSB (least significant byte first). + var bits = bytes[3] << 24 | bytes[2] << 16 | bytes[1] << 8 | bytes[0]; + var sign = (bits >>> 31 === 0) ? 1.0 : -1.0; + var e = bits >>> 23 & 0xff; + var m = (e === 0) ? (bits & 0x7fffff) << 1 : (bits & 0x7fffff) | 0x800000; + var f = sign * m * Math.pow(2, e - 150); + return f; +} diff --git a/vendor/milesight-iot/uc1152.png b/vendor/milesight-iot/uc1152.png new file mode 100644 index 0000000000..5ee85e5a20 Binary files /dev/null and b/vendor/milesight-iot/uc1152.png differ diff --git a/vendor/milesight-iot/uc1152.yaml b/vendor/milesight-iot/uc1152.yaml new file mode 100644 index 0000000000..9948f566cf --- /dev/null +++ b/vendor/milesight-iot/uc1152.yaml @@ -0,0 +1,74 @@ +name: UC1152 +description: LoRa Controller + +hardwareVersions: + - version: 'V3.x' + numeric: 1 + +firmwareVersions: + - version: '3.x' + numeric: 1 + hardwareVersions: + - 'V3.x' + + profiles: + EU863-870: + id: profile-eu868 + codec: uc1152-codec + US902-928: + id: profile-us915 + codec: uc1152-codec + AU915-928: + id: profile-au915 + codec: uc1152-codec + AS923: + id: profile-as923 + codec: uc1152-codec + CN470-510: + id: profile-cn470 + codec: uc1152-codec + KR920-923: + id: profile-kr920 + codec: uc1152-codec + IN865-867: + id: profile-in865 + codec: uc1152-codec + RU864-870: + id: profile-ru864 + codec: uc1152-codec + +sensors: + - digital input + # digital output + # modbus + # index + # reading + +bridgeInterfaces: + - modbus + - rs-485 + # rs-232 + +dimensions: + width: 24 + length: 79 + height: 60 + +operatingConditions: + temperature: + min: -40 + max: 70 + + relativeHumidity: + min: 0 + max: 0.95 + +ipCode: IP30 + +keyProvisioning: + - custom + - join server +keySecurity: none + +photos: + main: uc1152.png diff --git a/vendor/milesight-iot/uc300-codec.yaml b/vendor/milesight-iot/uc300-codec.yaml new file mode 100644 index 0000000000..7ebdeba8f0 --- /dev/null +++ b/vendor/milesight-iot/uc300-codec.yaml @@ -0,0 +1,23 @@ +# Uplink decoder decodes binary data uplink into a JSON object +uplinkDecoder: + fileName: uc300.js + examples: + - description: LoRa Controllers (example 1) - Milesight IoT + input: + fPort: 85 + bytes: [0x03, 0xC8, 0x16, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x05, 0x00, 0x00, 0x06, 0x00, 0x01, 0x07, 0x01, 0x00, 0x08, 0x01, 0x01] + output: + data: + digital_input_2: off + digital_input_3: off + digital_input_4: on + digital_output_1: off + digital_output_2: on + pulse_count_1: 22 + - description: LoRa Controllers (example 2) - Milesgiht IoT + input: + fPort: 85 + bytes: [0xff, 0x19, 0x07, 0x02, 0x03, 0x15, 0x00] + output: + data: + modbus_channels: [{ index: 8, reading: 5379 }] diff --git a/vendor/milesight-iot/uc300.js b/vendor/milesight-iot/uc300.js new file mode 100644 index 0000000000..8883634754 --- /dev/null +++ b/vendor/milesight-iot/uc300.js @@ -0,0 +1,195 @@ +function decodeUplink(input) { + var res = Decoder(input.bytes, input.fPort); + if (res.error) { + return { + errors: [res.error], + }; + } + return { + data: res, + }; +} +/** + * Payload Decoder for The Things Network + * + * Copyright 2022 Milesight IoT + * + * @product UC300 series + */ + +function Decoder(bytes, fport) { + var decoded = {}; + + for (i = 0; i < bytes.length;) { + var channel_id = bytes[i++]; + var channel_type = bytes[i++]; + + // Digital Input + if (channel_id === 0x03 && channel_type === 0x00) { + decoded.digital_input_1 = bytes[i] === 0 ? "off" : "on"; + i += 1; + } + else if (channel_id === 0x04 && channel_type === 0x00) { + decoded.digital_input_2 = bytes[i] === 0 ? "off" : "on"; + i += 1; + } + else if (channel_id === 0x05 && channel_type === 0x00) { + decoded.digital_input_3 = bytes[i] === 0 ? "off" : "on"; + i += 1; + } + else if (channel_id === 0x06 && channel_type === 0x00) { + decoded.digital_input_4 = bytes[i] === 0 ? "off" : "on"; + i += 1; + } + // Digital Output + else if (channel_id === 0x07 && channel_type === 0x01) { + decoded.digital_output_1 = bytes[i] === 0 ? "off" : "on"; + i += 1; + } + else if (channel_id === 0x08 && channel_type === 0x01) { + decoded.digital_output_2 = bytes[i] === 0 ? "off" : "on"; + i += 1; + } + // Digital Input as Counter + else if (channel_id === 0x03 && channel_type === 0xc8) { + decoded.pulse_count_1 = readUInt32LE(bytes.slice(i, i + 4)); + i += 4; + } + else if (channel_id === 0x04 && channel_type === 0xc8) { + decoded.pulse_count_2 = readUInt32LE(bytes.slice(i, i + 4)); + i += 4; + } + else if (channel_id === 0x05 && channel_type === 0xc8) { + decoded.pulse_count_3 = readUInt32LE(bytes.slice(i, i + 4)); + i += 4; + } + else if (channel_id === 0x06 && channel_type === 0xc8) { + decoded.pulse_count_4 = readUInt32LE(bytes.slice(i, i + 4)); + i += 4; + } + // PT100 + else if (channel_id === 0x09 && channel_type === 0x67) { + decoded.pt100_1 = readInt16LE(bytes.slice(i, i + 2)) / 10; + i += 2; + } + else if (channel_id === 0x0a && channel_type === 0x67) { + decoded.pt100_2 = readInt16LE(bytes.slice(i, i + 2)) / 10; + i += 2; + } + // ADC CHANNEL + else if (channel_id === 0x0b && channel_type === 0x02) { + decoded.analog_input_adc_1 = readUInt32LE(bytes.slice(i, i + 2)) / 100; + i += 4; + continue; + } + else if (channel_id === 0x0c && channel_type === 0x02) { + decoded.analog_input_adc_2 = readUInt32LE(bytes.slice(i, i + 2)) / 100; + i += 4; + continue; + } + // ADC CHANNEL for voltage + else if (channel_id === 0x0d && channel_type === 0x02) { + decoded.analog_input_adv_1 = readUInt32LE(bytes.slice(i, i + 2)) / 100; + i += 4; + continue; + } + else if (channel_id === 0x0e && channel_type === 0x02) { + decoded.analog_input_adv_2 = readUInt32LE(bytes.slice(i, i + 2)) / 100; + i += 4; + continue; + } + // MODBUS + else if (channel_id === 0xff && channel_type === 0x19) { + var modbus_chn_id = bytes[i++] + 1; + var package_type = bytes[i++]; + var data_type = package_type & 7; + var data_length = package_type >> 3; + decoded.modbus_channels = []; + var perchannel = {}; + switch (data_type) { + case 0: + perchannel['index'] = modbus_chn_id; + perchannel['reading'] = bytes[i] ? "on" : "off"; + decoded.modbus_channels.push(perchannel); + i += 1; + break; + case 1: + perchannel['index'] = modbus_chn_id; + perchannel['reading'] = bytes[i]; + decoded.modbus_channels.push(perchannel); + i += 1; + break; + case 2: + case 3: + perchannel['index'] = modbus_chn_id; + perchannel['reading'] = readUInt16LE(bytes.slice(i, i + 2)); + decoded.modbus_channels.push(perchannel); + i += 2; + break; + case 4: + case 6: + case 8: + case 9: + case 10: + case 11: + perchannel['index'] = modbus_chn_id; + perchannel['reading'] = readUInt32LE(bytes.slice(i, i + 4)); + decoded.modbus_channels.push(perchannel); + i += 4; + break; + case 5: + case 7: + perchannel['index'] = modbus_chn_id; + perchannel['reading'] = readFloatLE(bytes.slice(i, i + 4)); + decoded.modbus_channels.push(perchannel); + i += 4; + break; + } + } + } + + return decoded; +} + +/* ****************************************** + * bytes to number + ********************************************/ +function readUInt8LE(bytes) { + return bytes & 0xff; +} + +function readInt8LE(bytes) { + var ref = readUInt8LE(bytes); + return ref > 0x7f ? ref - 0x100 : ref; +} + +function readUInt16LE(bytes) { + var value = (bytes[1] << 8) + bytes[0]; + return value & 0xffff; +} + +function readInt16LE(bytes) { + var ref = readUInt16LE(bytes); + return ref > 0x7fff ? ref - 0x10000 : ref; +} + +function readUInt32LE(bytes) { + var value = (bytes[3] << 24) + (bytes[2] << 16) + (bytes[1] << 8) + bytes[0]; + return value & 0xffffffff; +} + +function readInt32LE(bytes) { + var ref = readUInt32LE(bytes); + return ref > 0x7fffffff ? ref - 0x100000000 : ref; +} + +function readFloatLE(bytes) { + // JavaScript bitwise operators yield a 32 bits integer, not a float. + // Assume LSB (least significant byte first). + var bits = (bytes[3] << 24) | (bytes[2] << 16) | (bytes[1] << 8) | bytes[0]; + var sign = bits >>> 31 === 0 ? 1.0 : -1.0; + var e = (bits >>> 23) & 0xff; + var m = e === 0 ? (bits & 0x7fffff) << 1 : (bits & 0x7fffff) | 0x800000; + var f = sign * m * Math.pow(2, e - 150); + return f; +} \ No newline at end of file diff --git a/vendor/milesight-iot/uc300.png b/vendor/milesight-iot/uc300.png new file mode 100644 index 0000000000..51028ab109 Binary files /dev/null and b/vendor/milesight-iot/uc300.png differ diff --git a/vendor/milesight-iot/uc300.yaml b/vendor/milesight-iot/uc300.yaml new file mode 100644 index 0000000000..5306c66a1a --- /dev/null +++ b/vendor/milesight-iot/uc300.yaml @@ -0,0 +1,87 @@ +name: Milesight UC300 Series IoT Controller +description: Milesight UC300 series is an IoT controller used for remote control and data acquisition from diverse devices. It contains multiple I/O interfaces including analog input, digital input, relay output, serial port, PT100 RTD input, which support remote device data transmission via LoRaWAN®. Besides, UC300 series supports multiple trigger conditions and actions which can work autonomously even when the network dropped. Adopting industrial design and IP30 metal case, UC300 is widely used in indoor applications like smart factory, building automation, etc. + +hardwareVersions: + - version: 'V1.0' + numeric: 1 + +firmwareVersions: + - version: '1.x' + numeric: 1 + hardwareVersions: + - 'V1.0' + + profiles: + EU863-870: + id: profile-eu868 + codec: uc300-codec + US902-928: + id: profile-us915 + codec: uc300-codec + AU915-928: + id: profile-au915 + codec: uc300-codec + AS923: + id: profile-as923 + codec: uc300-codec + CN470-510: + id: profile-cn470 + codec: uc300-codec + KR920-923: + id: profile-kr920 + codec: uc300-codec + IN865-867: + id: profile-in865 + codec: uc300-codec + RU864-870: + id: profile-ru864 + codec: uc300-codec + +sensors: + - digital input + - pulse count + # digital input + - analog input + # pt100 + # modbus channels + # index + # reading + +bridgeInterfaces: + - modbus + - rs-485 + # rs-232 + - analog + +dimensions: + width: 70 + length: 22 + height: 93 + +operatingConditions: + temperature: + min: -20 + max: 60 + + relativeHumidity: + min: 0 + max: 0.95 + +ipCode: IP30 + +keyProvisioning: + - custom + - join server +keySecurity: none +productURL: https://www.milesight-iot.com/controller/uc300/?utm_source=platform&utm_medium=web&utm_campaign=milesight +dataSheetURL: https://resource.milesight-iot.com/milesight/document/uc300-datasheet-en.pdf +resellerURLs: + - name: 'iot.sales@milesight.com' + region: + - United States + - European Union + - Canada + url: https://www.alibaba.com/product-detail/Milesight-UC300-IoT-Controller-LoRaWAN_1600473886091.html?spm=a2700.shop_plser.41413.14.4514352d23IFp0 + +photos: + main: uc300.png diff --git a/vendor/milesight-iot/uc50x-codec.yaml b/vendor/milesight-iot/uc50x-codec.yaml new file mode 100644 index 0000000000..9eedc36771 --- /dev/null +++ b/vendor/milesight-iot/uc50x-codec.yaml @@ -0,0 +1,18 @@ +# Uplink decoder decodes binary data uplink into a JSON object +uplinkDecoder: + fileName: uc50x.js + examples: + - description: LoRa Controllers (example 1) - Milesight IoT + input: + fPort: 85 + bytes: [0x04, 0x01, 0x01] + output: + data: + gpio_2: on + - description: LoRa Controllers (example 2) - Milesgiht IoT + input: + fPort: 85 + bytes: [0xFF, 0x0E, 0x19, 0x13, 0x04, 0x00] + output: + data: + modbus_channels: [{ index: 19, reading: 4 }] diff --git a/vendor/milesight-iot/uc50x.js b/vendor/milesight-iot/uc50x.js new file mode 100644 index 0000000000..cfb9983551 --- /dev/null +++ b/vendor/milesight-iot/uc50x.js @@ -0,0 +1,161 @@ +function decodeUplink(input) { + var res = Decoder(input.bytes, input.fPort); + if (res.error) { + return { + errors: [res.error], + }; + } + return { + data: res, + }; +} +/** + * Payload Decoder for The Things Network + * + * Copyright 2020 Milesight IoT + * + * @product UC500 series + */ +function Decoder(bytes, port) { + var decoded = {}; + + for (i = 0; i < bytes.length;) { + var channel_id = bytes[i++]; + var channel_type = bytes[i++]; + + // BATTERY + if (channel_id === 0x01 && channel_type === 0x75) { + decoded.battery = bytes[i]; + i += 1; + } + // GPIO1 + else if (channel_id === 0x03 && channel_type !== 0xC8) { + decoded.gpio_1 = bytes[i] === 0 ? "off" : "on"; + i += 1; + } + // GPIO2 + else if (channel_id === 0x04 && channel_type !== 0xC8) { + decoded.gpio_2 = bytes[i] === 0 ? "off" : "on"; + i += 1; + } + // PULSE COUNTER 1 + else if (channel_id === 0x03 && channel_type === 0xc8) { + decoded.pulse_count_1 = readUInt32LE(bytes.slice(i, i + 4)); + i += 4; + } + // PULSE COUNTER 2 + else if (channel_id === 0x04 && channel_type === 0xc8) { + decoded.pulse_count_2 = readUInt32LE(bytes.slice(i, i + 4)); + i += 4; + } + // ADC 1 + else if (channel_id === 0x05) { + decoded.analog_input_1 = {}; + decoded.analog_input_1_cur = readInt16LE(bytes.slice(i, i + 2)) / 100; + decoded.analog_input_1_min = readInt16LE(bytes.slice(i + 2, i + 4)) / 100; + decoded.analog_input_1_max = readInt16LE(bytes.slice(i + 4, i + 6)) / 100; + decoded.analog_input_1_avg = readInt16LE(bytes.slice(i + 6, i + 8)) / 100; + i += 8; + continue; + } + // ADC 2 + else if (channel_id === 0x06) { + decoded.analog_input_2 = {}; + decoded.analog_input_2_cur = readInt16LE(bytes.slice(i, i + 2)) / 100; + decoded.analog_input_2_min = readInt16LE(bytes.slice(i + 2, i + 4)) / 100; + decoded.analog_input_2_max = readInt16LE(bytes.slice(i + 4, i + 6)) / 100; + decoded.analog_input_2_avg = readInt16LE(bytes.slice(i + 6, i + 8)) / 100; + i += 8; + continue; + } + // MODBUS + else if (channel_id === 0xFF && channel_type === 0x0E) { + var modbus_chn_id = bytes[i++] - 6; + var package_type = bytes[i++]; + var data_type = package_type & 7; + var date_length = package_type >> 3; + decoded.modbus_channels = []; + var perchannel = {}; + switch (data_type) { + case 0: + perchannel['index'] = modbus_chn_id; + perchannel['reading'] = bytes[i] ? "on" : "off"; + decoded.modbus_channels.push(perchannel); + i += 1; + break; + case 1: + perchannel['index'] = modbus_chn_id; + perchannel['reading'] = bytes[i]; + decoded.modbus_channels.push(perchannel); + i += 1; + break; + case 2: + case 3: + perchannel['index'] = modbus_chn_id; + perchannel['reading'] = readUInt16LE(bytes.slice(i, i + 2)); + decoded.modbus_channels.push(perchannel); + i += 2; + break; + case 4: + case 6: + perchannel['index'] = modbus_chn_id; + perchannel['reading'] = readUInt32LE(bytes.slice(i, i + 4)); + decoded.modbus_channels.push(perchannel); + i += 4; + break; + case 5: + case 7: + perchannel['index'] = modbus_chn_id; + perchannel['reading'] = readFloatLE(bytes.slice(i, i + 4)); + decoded.modbus_channels.push(perchannel); + i += 4; + break; + } + } + } + + return decoded; +} + +/* ****************************************** + * bytes to number + ********************************************/ +function readUInt8LE(bytes) { + return (bytes & 0xFF); +} + +function readInt8LE(bytes) { + var ref = readUInt8LE(bytes); + return (ref > 0x7F) ? ref - 0x100 : ref; +} + +function readUInt16LE(bytes) { + var value = (bytes[1] << 8) + bytes[0]; + return (value & 0xFFFF); +} + +function readInt16LE(bytes) { + var ref = readUInt16LE(bytes); + return (ref > 0x7FFF) ? ref - 0x10000 : ref; +} + +function readUInt32LE(bytes) { + var value = (bytes[3] << 24) + (bytes[2] << 16) + (bytes[1] << 8) + bytes[0]; + return (value & 0xFFFFFFFF); +} + +function readInt32LE(bytes) { + var ref = readUInt32LE(bytes); + return (ref > 0x7FFFFFFF) ? ref - 0x100000000 : ref; +} + +function readFloatLE(bytes) { + // JavaScript bitwise operators yield a 32 bits integer, not a float. + // Assume LSB (least significant byte first). + var bits = bytes[3] << 24 | bytes[2] << 16 | bytes[1] << 8 | bytes[0]; + var sign = (bits >>> 31 === 0) ? 1.0 : -1.0; + var e = bits >>> 23 & 0xff; + var m = (e === 0) ? (bits & 0x7fffff) << 1 : (bits & 0x7fffff) | 0x800000; + var f = sign * m * Math.pow(2, e - 150); + return f; +} diff --git a/vendor/milesight-iot/uc50x.png b/vendor/milesight-iot/uc50x.png new file mode 100644 index 0000000000..1ce7cfcb35 Binary files /dev/null and b/vendor/milesight-iot/uc50x.png differ diff --git a/vendor/milesight-iot/uc50x.yaml b/vendor/milesight-iot/uc50x.yaml new file mode 100644 index 0000000000..e412008b21 --- /dev/null +++ b/vendor/milesight-iot/uc50x.yaml @@ -0,0 +1,90 @@ +name: Milesight UC50x Series LoRaWAN® Controller +description: Milesight UC50x series is a LoRaWAN® controller used for data acquisition from various sensors and equipments. It contains different I/O interfaces such as analog input, digital input, digital output, serial port and so on, which simplify the deployment and replacement of LoRaWAN® networks. For outdoor applications, it provides flexible power like built-in solar panel or high-capacity battery and is equipped with an IP67-rated enclosure and M12 connectors to protect itself from water and dust in harsh environments. + +hardwareVersions: + - version: '1.x' + numeric: 1 + - version: '2.x' + numeric: 2 + +firmwareVersions: + - version: '1.x' + numeric: 1 + hardwareVersions: + - '1.x' + - '2.x' + + profiles: + EU863-870: + id: profile-eu868 + codec: uc50x-codec + US902-928: + id: profile-us915 + codec: uc50x-codec + AU915-928: + id: profile-au915 + codec: uc50x-codec + AS923: + id: profile-as923 + codec: uc50x-codec + CN470-510: + id: profile-cn470 + codec: uc50x-codec + KR920-923: + id: profile-kr920 + codec: uc50x-codec + IN865-867: + id: profile-in865 + codec: uc50x-codec + RU864-870: + id: profile-ru864 + codec: uc50x-codec + +sensors: + - digital input + - pulse count + # digital input + - analog input + # digital output + # modbus channels + # index + # reading + +bridgeInterfaces: + - modbus + - rs-485 + # rs-232 + - analog + +dimensions: + width: 116 + length: 45.5 + height: 116 + +operatingConditions: + temperature: + min: -20 + max: 60 + + relativeHumidity: + min: 0 + max: 0.95 + +ipCode: IP67 + +keyProvisioning: + - custom + - join server +keySecurity: none +productURL: https://www.milesight-iot.com/lorawan/controller/uc500/ +dataSheetURL: https://resource.milesight-iot.com/milesight/document/uc50x-series-datasheet-en.pdf +resellerURLs: + - name: 'iot.sales@milesight.com' + region: + - United States + - European Union + - Canada + url: https://www.milesight-iot.com/contact-us/ + +photos: + main: uc50x.png diff --git a/vendor/milesight-iot/uc51x-codec.yaml b/vendor/milesight-iot/uc51x-codec.yaml new file mode 100644 index 0000000000..d745a306a3 --- /dev/null +++ b/vendor/milesight-iot/uc51x-codec.yaml @@ -0,0 +1,11 @@ +# Uplink decoder decodes binary data uplink into a JSON object +uplinkDecoder: + fileName: uc51x.js + examples: + - description: Solenoid Valve Controller (example 1) - Milesight IoT + input: + fPort: 85 + bytes: [0x03, 0x01, 0x01] + output: + data: + valve_1: on diff --git a/vendor/milesight-iot/uc51x.js b/vendor/milesight-iot/uc51x.js new file mode 100644 index 0000000000..2fdb9440a8 --- /dev/null +++ b/vendor/milesight-iot/uc51x.js @@ -0,0 +1,70 @@ +function decodeUplink(input) { + var res = Decoder(input.bytes, input.fPort); + if (res.error) { + return { + errors: [res.error], + }; + } + return { + data: res, + }; +} +/** + * Payload Decoder for The Things Network + * + * Copyright 2021 Milesight IoT + * + * @product UC51x Series + */ +function Decoder(bytes, port) { + var decoded = {}; + + for (var i = 0; i < bytes.length;) { + var channel_id = bytes[i++]; + var channel_type = bytes[i++]; + + // BATTERY + if (channel_id === 0x01 && channel_type === 0x75) { + decoded.battery = bytes[i]; + i += 1; + } + // VALVE 1 + else if (channel_id === 0x03 && channel_type == 0x01) { + decoded.valve_1 = bytes[i] === 0 ? "off" : "on"; + i += 1; + } + // VALVE 2 + else if (channel_id === 0x05 && channel_type == 0x01) { + decoded.valve_2 = bytes[i] === 0 ? "off" : "on"; + i += 1; + } + // VALVE 1 Pulse + else if (channel_id === 0x04 && channel_type === 0xc8) { + decoded.valve_1_pulse = readUInt32LE(bytes.slice(i, i + 4)); + i += 4; + } + // VALVE 2 Pulse + else if (channel_id === 0x06 && channel_type === 0xc8) { + decoded.valve_2_pulse = readUInt32LE(bytes.slice(i, i + 4)); + i += 4; + } else { + break; + } + } + + return decoded; +} + +/* ****************************************** + * bytes to number + ********************************************/ +function readUInt32LE(bytes) { + var value = + (bytes[3] << 24) + (bytes[2] << 16) + (bytes[1] << 8) + bytes[0]; + return value & 0xffffffff; +} + +function readInt32LE(bytes) { + var ref = readUInt32LE(bytes); + return ref > 0x7fffffff ? ref - 0x100000000 : ref; +} diff --git a/vendor/milesight-iot/uc51x.png b/vendor/milesight-iot/uc51x.png new file mode 100644 index 0000000000..8bb1b14bde Binary files /dev/null and b/vendor/milesight-iot/uc51x.png differ diff --git a/vendor/milesight-iot/uc51x.yaml b/vendor/milesight-iot/uc51x.yaml new file mode 100644 index 0000000000..9901be1ca7 --- /dev/null +++ b/vendor/milesight-iot/uc51x.yaml @@ -0,0 +1,82 @@ +name: Milesight UC51x Series LoRaWAN® Solenoid Valve Controller +description: Milesight UC51x series is a device used to remotely control DC latching solenoids of the valve. It contains 2 solenoid interfaces and 2 GPIO interfaces, which can be easily controlled locally or remotely. Besides ultra-low-power LoRaWAN® technology, UC51x series also provides built-in solar pannel and high-capacity battery power supply for long-term operation. For outdoor applications, it equips with IP67-rated enclosure and M12 connectors to protect from water and dust under harsh environments. + +hardwareVersions: + - version: '1.x' + numeric: 1 + - version: '2.x' + numeric: 2 + +firmwareVersions: + - version: '1.x' + numeric: 1 + hardwareVersions: + - '1.x' + - '2.x' + + profiles: + EU863-870: + id: profile-eu868 + codec: uc51x-codec + US902-928: + id: profile-us915 + codec: uc51x-codec + AU915-928: + id: profile-au915 + codec: uc51x-codec + AS923: + id: profile-as923 + codec: uc51x-codec + CN470-510: + id: profile-cn470 + codec: uc51x-codec + KR920-923: + id: profile-kr920 + codec: uc51x-codec + IN865-867: + id: profile-in865 + codec: uc51x-codec + RU864-870: + id: profile-ru864 + codec: uc51x-codec + +sensors: + - battery + - smart valve + # valve 1 + # valve 1 count + # valve 2 + # valve 2 count + +dimensions: + width: 116 + length: 45.5 + height: 116 + +operatingConditions: + temperature: + min: -20 + max: 60 + + relativeHumidity: + min: 0 + max: 0.95 + +ipCode: IP67 + +keyProvisioning: + - custom + - join server +keySecurity: none +productURL: https://www.milesight-iot.com/lorawan/controller/uc51x/?utm_source=platform&utm_medium=web&utm_campaign=milesight +dataSheetURL: https://resource.milesight-iot.com/milesight/document/uc51x-series-datasheet-en.pdf +resellerURLs: + - name: 'iot.sales@milesight.com' + region: + - United States + - European Union + - Canada + url: https://www.alibaba.com/product-detail/IoT-UC51X-LoRaWAN-Solenoid-Valve-Controller_1600474066257.html?spm=a2700.shop_plser.41413.12.7e258267c3wg4h + +photos: + main: uc51x.png diff --git a/vendor/milesight-iot/vs121-codec.yaml b/vendor/milesight-iot/vs121-codec.yaml new file mode 100644 index 0000000000..dc7c451b00 --- /dev/null +++ b/vendor/milesight-iot/vs121-codec.yaml @@ -0,0 +1,13 @@ +# Uplink decoder decodes binary data uplink into a JSON object +uplinkDecoder: + fileName: vs121.js + examples: + - description: AI Workplace Sensor (example 1) - Milesight IoT + input: + fPort: 85 + bytes: [0x04, 0xC9, 0x03, 0x03, 0x00, 0x02] + output: + data: + people_counter_all: 3 + region_count: 3 + regions: [{ 'count': 1, 'index': 0 }, { 'count': 1, 'index': 1 }, { 'count': 0, 'index': 2 }] diff --git a/vendor/milesight-iot/vs121.js b/vendor/milesight-iot/vs121.js new file mode 100644 index 0000000000..6f3f7b0788 --- /dev/null +++ b/vendor/milesight-iot/vs121.js @@ -0,0 +1,68 @@ +function decodeUplink(input) { + var res = Decoder(input.bytes, input.fPort); + if (res.error) { + return { + errors: [res.error], + }; + } + return { + data: res, + }; +} +/** + * Payload Decoder for The Things Network + * + * Copyright 2020 Milesight IoT + * + * @product VS121 + */ +function Decoder(bytes, port) { + var decoded = {}; + + for (i = 0; i < bytes.length;) { + var channel_id = bytes[i++]; + var channel_type = bytes[i++]; + + // PEOPLE COUNTER + if (channel_id === 0x04 && channel_type === 0xc9) { + decoded.people_counter_all = bytes[i]; + decoded.region_count = bytes[i + 1]; + decoded.regions = []; + var region = readUInt16BE(bytes.slice(i + 2, i + 4)); + for (var idx = 0; idx < decoded.region_count; idx++) { + var block = {}; + block['index'] = idx; + block['count'] = (region > idx) & 1; + decoded.regions.push(block); + } + i += 4; + } else { + break; + } + } + return decoded; +} + +// bytes to number +function readUInt16BE(bytes) { + var value = (bytes[0] << 8) + bytes[1]; + return value & 0xffff; +} + +// bytes to version +function readVersion(bytes) { + var temp = []; + for (var idx = 0; idx < bytes.length; idx++) { + temp.push((bytes[idx] & 0xff).toString(10)); + } + return temp.join("."); +} + +// bytes to string +function readString(bytes) { + var temp = []; + for (var idx = 0; idx < bytes.length; idx++) { + temp.push(("0" + (bytes[idx] & 0xff).toString(16)).slice(-2)); + } + return temp.join(""); +} diff --git a/vendor/milesight-iot/vs121.png b/vendor/milesight-iot/vs121.png new file mode 100644 index 0000000000..a78dd5a2b8 Binary files /dev/null and b/vendor/milesight-iot/vs121.png differ diff --git a/vendor/milesight-iot/vs121.yaml b/vendor/milesight-iot/vs121.yaml new file mode 100644 index 0000000000..2f7093f1b2 --- /dev/null +++ b/vendor/milesight-iot/vs121.yaml @@ -0,0 +1,75 @@ +name: Milesight VS121 AI Workplace Occupancy Sensor +description: Milesight VS121, based on Artificial Intelligence (AI) technology, is an AI workplace sensor designed to monitor occupancy & utilization in modern workspace, which can reach up to 95% recognition rate. With the ability to sense from up to more than 78 m2, few sensors are needed to cover the same area, decreasing the deploy costs for users. Milesight VS121 sensors are equipped with Wi-Fi for easy configuration without any configuration tools. + +hardwareVersions: + - version: 'V1.x' + numeric: 1 + +firmwareVersions: + - version: '1.x' + numeric: 1 + hardwareVersions: + - 'V1.x' + + profiles: + EU863-870: + id: profile-eu868 + codec: vs121-codec + US902-928: + id: profile-us915 + codec: vs121-codec + AU915-928: + id: profile-au915 + codec: vs121-codec + AS923: + id: profile-as923 + codec: vs121-codec + CN470-510: + id: profile-cn470 + codec: vs121-codec + KR920-923: + id: profile-kr920 + codec: vs121-codec + IN865-867: + id: profile-in865 + codec: vs121-codec + RU864-870: + id: profile-ru864 + codec: vs121-codec + +#sensors: +# people_counter_all +# region_count + +dimensions: + width: 50 + length: 23.8 + height: 50 + +operatingConditions: + temperature: + min: -5 + max: 55 + + relativeHumidity: + min: 0 + max: 0.95 + +ipCode: IP30 + +keyProvisioning: + - custom + - join server +keySecurity: none +productURL: https://www.milesight-iot.com/lorawan/sensor/vs121/?utm_source=platform&utm_medium=web&utm_campaign=milesight +dataSheetURL: https://resource.milesight-iot.com/milesight/document/vs121-datasheet-en.pdf +resellerURLs: + - name: 'iot.sales@milesight.com' + region: + - United States + - European Union + - Canada + url: https://www.alibaba.com/product-detail/Milesight-VS121-LoRaWAN-AI-Workplace-Sensor_1600323708781.html?spm=a2700.galleryofferlist.normal_offer.d_title.4dbd6596x5KHxg + +photos: + main: vs121.png diff --git a/vendor/milesight-iot/vs133-codec.yaml b/vendor/milesight-iot/vs133-codec.yaml new file mode 100644 index 0000000000..8e394dfa2e --- /dev/null +++ b/vendor/milesight-iot/vs133-codec.yaml @@ -0,0 +1,60 @@ +# Uplink decoder decodes binary data uplink into a JSON object (optional) +# For documentation on writing encoders and decoders, see: https://thethingsstack.io/integrations/payload-formatters/javascript/ +uplinkDecoder: + fileName: vs133.js + examples: + - description: LoRaWAN Insertion Temperature Sensor - Milesight IoT + input: + fPort: 85 + bytes: + [ + 0x03, + 0xd2, + 0x48, + 0x00, + 0x00, + 0x00, + 0x04, + 0xd2, + 0xc8, + 0x00, + 0x00, + 0x00, + 0x06, + 0xd2, + 0x00, + 0x00, + 0x00, + 0x00, + 0x07, + 0xd2, + 0x00, + 0x00, + 0x00, + 0x00, + 0x05, + 0xcc, + 0x00, + 0x00, + 0x00, + 0x00, + 0x08, + 0xcc, + 0x00, + 0x00, + 0x00, + 0x00, + ] + + output: + data: + line_1: + total_in: 72 + total_out: 200 + period_in: 0 + period_out: 0 + line_2: + total_in: 0 + total_out: 0 + period_in: 0 + period_out: 0 diff --git a/vendor/milesight-iot/vs133.js b/vendor/milesight-iot/vs133.js new file mode 100644 index 0000000000..9b02d81ef7 --- /dev/null +++ b/vendor/milesight-iot/vs133.js @@ -0,0 +1,85 @@ +function decodeUplink(input) { + var res = Decoder(input.bytes, input.fPort); + if (res.error) { + return { + errors: [res.error], + }; + } + return { + data: res, + }; +} +/** + * Payload Decoder for The Things Network + * + * Copyright 2023 Milesight IoT + * + * @product VS133 + */ +function Decoder(bytes, port) { + return milesight(bytes); +} + +total_in_chns = [0x03, 0x06, 0x09, 0x0c]; +total_out_chns = [0x04, 0x07, 0x0a, 0x0d]; +period_chns = [0x05, 0x08, 0x0b, 0x0e]; + +function milesight(bytes) { + var decoded = {}; + + for (var i = 0; i < bytes.length; ) { + var channel_id = bytes[i++]; + var channel_type = bytes[i++]; + + // LINE TOTAL IN + if (includes(total_in_chns, channel_id) && channel_type === 0xd2) { + var channel_in_name = "line_" + ((channel_id - total_in_chns[0]) / 3 + 1); + decoded[channel_in_name] = decoded[channel_in_name] || {}; + decoded[channel_in_name].total_in = readUInt32LE(bytes.slice(i, i + 4)); + i += 4; + } + // LINE TOTAL OUT + else if (includes(total_out_chns, channel_id) && channel_type === 0xd2) { + var channel_out_name = "line_" + ((channel_id - total_out_chns[0]) / 3 + 1); + decoded[channel_out_name] = decoded[channel_out_name] || {}; + decoded[channel_out_name].total_out = readUInt32LE(bytes.slice(i, i + 4)); + i += 4; + } + // LINE PERIOD + else if (includes(period_chns, channel_id) && channel_type === 0xcc) { + var channel_period_name = "line_" + ((channel_id - period_chns[0]) / 3 + 1); + decoded[channel_period_name] = decoded[channel_period_name] || {}; + decoded[channel_period_name].period_in = readUInt16LE(bytes.slice(i, i + 2)); + decoded[channel_period_name].period_out = readUInt16LE(bytes.slice(i + 2, i + 4)); + i += 4; + } else { + break; + } + } + + return decoded; +} + +function readUInt8LE(bytes) { + return bytes & 0xff; +} + +function readUInt16LE(bytes) { + var value = (bytes[1] << 8) + bytes[0]; + return value & 0xffff; +} + +function readUInt32LE(bytes) { + var value = (bytes[3] << 24) + (bytes[2] << 16) + (bytes[1] << 8) + bytes[0]; + return (value & 0xffffffff) >>> 0; +} + +function includes(datas, value) { + var size = datas.length; + for (var i = 0; i < size; i++) { + if (datas[i] == value) { + return true; + } + } + return false; +} diff --git a/vendor/milesight-iot/vs133.png b/vendor/milesight-iot/vs133.png new file mode 100644 index 0000000000..4bca46549d Binary files /dev/null and b/vendor/milesight-iot/vs133.png differ diff --git a/vendor/milesight-iot/vs133.yaml b/vendor/milesight-iot/vs133.yaml new file mode 100644 index 0000000000..6fb54c9c5a --- /dev/null +++ b/vendor/milesight-iot/vs133.yaml @@ -0,0 +1,96 @@ +name: AI ToF People Counting Sensor +description: VS133 is a sensor that uses second-generation ToF technology to accuratelycount people with an excellent privacy protection + +hardwareVersions: + - version: 'V1.0' + numeric: 1 + +firmwareVersions: + - version: 'v133.1.0.x' + numeric: 1 + hardwareVersions: + - 'V1.0' + + profiles: + EU863-870: + id: profile-eu868 + codec: vs133-codec + US902-928: + id: profile-us915 + codec: vs133-codec + AU915-928: + id: profile-au915 + codec: vs133-codec + AS923: + id: profile-as923 + codec: vs133-codec + CN470-510: + id: profile-cn470 + codec: vs133-codec + KR920-923: + id: profile-kr920 + codec: vs133-codec + IN865-867: + id: profile-in865 + codec: vs133-codec + RU864-870: + id: profile-ru864 + codec: vs133-codec + +sensors: + - motion + +# 4-20 ma, accelerometer, altitude, analog input, auxiliary, barometer, battery, button, bvoc, co, co2, conductivity, +# current, digital input, dissolved oxygen, distance, dust, energy, gps, gyroscope, h2s, humidity, iaq, level, light, +# lightning, link, magnetometer, moisture, motion, no, no2, o3, particulate matter, ph, pir, pm2.5, pm10, potentiometer, +# power, precipitation, pressure, proximity, pulse count, pulse frequency, radar, rainfall, rssi, smart valve, snr, so2, +# solar radiation, sound, strain, surface temperature, temperature, tilt, time, tvoc, uv, vapor pressure, velocity, +# vibration, voltage, water potential, water, weight, wifi ssid, wind direction, wind speed. + +dimensions: + width: 26 + length: 180 + height: 72 + +operatingConditions: + temperature: + min: -20 + max: 50 + + relativeHumidity: + min: 0 + max: 0.95 + +ipCode: IP40 + +keyProvisioning: + - custom + - join server +keySecurity: none +productURL: https://www.milesight.com/iot/product/lorawan-sensor/vs133 +dataSheetURL: https://resource.milesight.com/milesight/iot/document/vs133-datasheet-en.pdf +resellerURLs: + - name: 'iot.sales@milesight.com' + region: + - United States + - European Union + - Canada + url: https://www.milesight-iot.com/contact-us/ + +photos: + main: vs133.png + +compliances: + safety: + - body: IEC + norm: EN + standard: 62368-1 + radioEquipment: + - body: ETSI + norm: EN + standard: 301 489-1 + version: 2.2.0 + - body: ETSI + norm: EN + standard: 301 489-3 + version: 2.1.0 diff --git a/vendor/milesight-iot/vs330-codec.yaml b/vendor/milesight-iot/vs330-codec.yaml new file mode 100644 index 0000000000..4a916115d1 --- /dev/null +++ b/vendor/milesight-iot/vs330-codec.yaml @@ -0,0 +1,16 @@ +# Uplink decoder decodes binary data uplink into a JSON object (optional) +# For documentation on writing encoders and decoders, see: https://thethingsstack.io/integrations/payload-formatters/javascript/ +uplinkDecoder: + fileName: vs330.js + examples: + - description: LoRaWAN Bathroom Occupancy Sensor - Milesight IoT + input: + fPort: 85 + bytes: [0x01, 0x75, 0x62, 0x02, 0x82, 0x0F, 0x00, 0x03, 0x8E, 0x01, 0x04, 0x8E, 0x01] + + output: + data: + battery: 98 + distance: 15 + occupancy: occupied + calibration: success diff --git a/vendor/milesight-iot/vs330.js b/vendor/milesight-iot/vs330.js new file mode 100644 index 0000000000..2f132f7c6f --- /dev/null +++ b/vendor/milesight-iot/vs330.js @@ -0,0 +1,61 @@ +function decodeUplink(input) { + var res = Decoder(input.bytes, input.fPort); + if (res.error) { + return { + errors: [res.error], + }; + } + return { + data: res, + }; +} +/** + * Payload Decoder for The Things Network + * + * Copyright 2023 Milesight IoT + * + * @product VS330 + */ +function Decoder(bytes, port) { + return milesight(bytes); +} + +function milesight(bytes) { + var decoded = {}; + + for (i = 0; i < bytes.length; ) { + var channel_id = bytes[i++]; + var channel_type = bytes[i++]; + + // BATTERY + if (channel_id === 0x01 && channel_type === 0x75) { + decoded.battery = bytes[i]; + i += 1; + } + // DISTANCE + else if (channel_id === 0x02 && channel_type === 0x82) { + decoded.distance = readUInt16LE(bytes.slice(i, i + 2)); + i += 2; + } + // OCCUPANCY + else if (channel_id === 0x03 && channel_type === 0x8e) { + decoded.occupancy = bytes[i] === 0 ? "vacant" : "occupied"; + i += 1; + } + // CALIBRATION + else if (channel_id === 0x04 && channel_type === 0x8e) { + decoded.calibration = bytes[i] === 0 ? "failed" : "success"; + i += 1; + } else { + break; + } + } + + return decoded; +} + +// bytes to number +function readUInt16LE(bytes) { + var value = (bytes[1] << 8) + bytes[0]; + return value & 0xffff; +} diff --git a/vendor/milesight-iot/vs330.png b/vendor/milesight-iot/vs330.png new file mode 100644 index 0000000000..d484ce63cd Binary files /dev/null and b/vendor/milesight-iot/vs330.png differ diff --git a/vendor/milesight-iot/vs330.yaml b/vendor/milesight-iot/vs330.yaml new file mode 100644 index 0000000000..985e378a8f --- /dev/null +++ b/vendor/milesight-iot/vs330.yaml @@ -0,0 +1,101 @@ +name: LoRaWAN Bathroom Occupancy Sensor +description: VS330 is a LoRaWAN® bathroom occupancy sensor providingacost-effectivesolution for monitoring the occupancy status of the bathroomsandthecubiclesof a public toilet in different scenarios + +hardwareVersions: + - version: 'V1.0' + numeric: 1 + +firmwareVersions: + - version: '1.0x' + numeric: 1 + hardwareVersions: + - 'V1.0' + + profiles: + EU863-870: + id: profile-eu868 + codec: vs330-codec + US902-928: + id: profile-us915 + codec: vs330-codec + AU915-928: + id: profile-au915 + codec: vs330-codec + AS923: + id: profile-as923 + codec: vs330-codec + CN470-510: + id: profile-cn470 + codec: vs330-codec + KR920-923: + id: profile-kr920 + codec: vs330-codec + IN865-867: + id: profile-in865 + codec: vs330-codec + RU864-870: + id: profile-ru864 + codec: vs330-codec + +sensors: + - motion + - pir + +# 4-20 ma, accelerometer, altitude, analog input, auxiliary, barometer, battery, button, bvoc, co, co2, conductivity, +# current, digital input, dissolved oxygen, distance, dust, energy, gps, gyroscope, h2s, humidity, iaq, level, light, +# lightning, link, magnetometer, moisture, motion, no, no2, o3, particulate matter, ph, pir, pm2.5, pm10, potentiometer, +# power, precipitation, pressure, proximity, pulse count, pulse frequency, radar, rainfall, rssi, smart valve, snr, so2, +# solar radiation, sound, strain, surface temperature, temperature, tilt, time, tvoc, uv, vapor pressure, velocity, +# vibration, voltage, water potential, water, weight, wifi ssid, wind direction, wind speed. + +dimensions: + width: 24 + length: 100 + height: 100 + +battery: + replaceable: true + type: ER18505 Li-SOCl2 battery *3 + +operatingConditions: + temperature: + min: -20 + max: 60 + + relativeHumidity: + min: 0 + max: 0.95 + +ipCode: IP30 + +keyProvisioning: + - custom + - join server +keySecurity: none +productURL: https://www.milesight.com/iot/product/lorawan-sensor/vs330 +dataSheetURL: https://resource.milesight.com/milesight/iot/document/vs330-datasheet-en.pdf +resellerURLs: + - name: 'iot.sales@milesight.com' + region: + - United States + - European Union + - Canada + url: https://www.milesight-iot.com/contact-us/ + +photos: + main: vs330.png + +compliances: + safety: + - body: IEC + norm: EN + standard: 62368-1 + radioEquipment: + - body: ETSI + norm: EN + standard: 301 489-1 + version: 2.2.0 + - body: ETSI + norm: EN + standard: 301 489-3 + version: 2.1.0 diff --git a/vendor/milesight-iot/vs340-codec.yaml b/vendor/milesight-iot/vs340-codec.yaml new file mode 100644 index 0000000000..60a4bda4f1 --- /dev/null +++ b/vendor/milesight-iot/vs340-codec.yaml @@ -0,0 +1,14 @@ +# Uplink decoder decodes binary data uplink into a JSON object (optional) +# For documentation on writing encoders and decoders, see: https://thethingsstack.io/integrations/payload-formatters/javascript/ +uplinkDecoder: + fileName: vs340.js + examples: + - description: Desk&Seat Occupancy Sensor - Milesight IoT + input: + fPort: 85 + bytes: [0x01, 0x75, 0x64, 0x03, 0x00, 0x01] + + output: + data: + battery: 100 + occupancy: occupied diff --git a/vendor/milesight-iot/vs340.js b/vendor/milesight-iot/vs340.js new file mode 100644 index 0000000000..aa4df53ee3 --- /dev/null +++ b/vendor/milesight-iot/vs340.js @@ -0,0 +1,44 @@ +function decodeUplink(input) { + var res = Decoder(input.bytes, input.fPort); + if (res.error) { + return { + errors: [res.error], + }; + } + return { + data: res, + }; +} +/** + * Payload Decoder for The Things Network + * + * Copyright 2023 Milesight IoT + * + * @product VS340 / VS341 + */ +function Decoder(bytes, port) { + return milesight(bytes); +} + +function milesight(bytes) { + var decoded = {}; + + for (var i = 0; i < bytes.length; ) { + var channel_id = bytes[i++]; + var channel_type = bytes[i++]; + // BATTERY + if (channel_id === 0x01 && channel_type === 0x75) { + decoded.battery = bytes[i]; + i += 1; + } + // OCCUPANCY + else if (channel_id === 0x03 && channel_type === 0x00) { + decoded.occupancy = bytes[i] === 0 ? "vacant" : "occupied"; + i += 1; + } else { + break; + } + } + + return decoded; +} diff --git a/vendor/milesight-iot/vs340.png b/vendor/milesight-iot/vs340.png new file mode 100644 index 0000000000..9739057acc Binary files /dev/null and b/vendor/milesight-iot/vs340.png differ diff --git a/vendor/milesight-iot/vs340.yaml b/vendor/milesight-iot/vs340.yaml new file mode 100644 index 0000000000..fe636537ba --- /dev/null +++ b/vendor/milesight-iot/vs340.yaml @@ -0,0 +1,101 @@ +name: Desk&Seat Occupancy Sensor +description: VS34x is an occupancy sensor designed to detect whether desksorseats in a workspace are occupied, allowing for better managementand optimization of space usage. + +hardwareVersions: + - version: 'V1.0' + numeric: 1 + +firmwareVersions: + - version: '1.0x' + numeric: 1 + hardwareVersions: + - 'V1.0' + + profiles: + EU863-870: + id: profile-eu868 + codec: vs340-codec + US902-928: + id: profile-us915 + codec: vs340-codec + AU915-928: + id: profile-au915 + codec: vs340-codec + AS923: + id: profile-as923 + codec: vs340-codec + CN470-510: + id: profile-cn470 + codec: vs340-codec + KR920-923: + id: profile-kr920 + codec: vs340-codec + IN865-867: + id: profile-in865 + codec: vs340-codec + RU864-870: + id: profile-ru864 + codec: vs340-codec + +sensors: + - pir + - motion + +# 4-20 ma, accelerometer, altitude, analog input, auxiliary, barometer, battery, button, bvoc, co, co2, conductivity, +# current, digital input, dissolved oxygen, distance, dust, energy, gps, gyroscope, h2s, humidity, iaq, level, light, +# lightning, link, magnetometer, moisture, motion, no, no2, o3, particulate matter, ph, pir, pm2.5, pm10, potentiometer, +# power, precipitation, pressure, proximity, pulse count, pulse frequency, radar, rainfall, rssi, smart valve, snr, so2, +# solar radiation, sound, strain, surface temperature, temperature, tilt, time, tvoc, uv, vapor pressure, velocity, +# vibration, voltage, water potential, water, weight, wifi ssid, wind direction, wind speed. + +dimensions: + width: 26 + length: 73 + height: 73 + +battery: + replaceable: true + type: ER18505 Li-SOCl2 battery + +operatingConditions: + temperature: + min: -20 + max: 60 + + relativeHumidity: + min: 0 + max: 0.95 + +ipCode: IP30 + +keyProvisioning: + - custom + - join server +keySecurity: none +productURL: https://www.milesight.com/iot/product/lorawan-sensor/vs34x +dataSheetURL: https://resource.milesight.com/milesight/iot/document/vs34x-datasheet-v1.0.pdf +resellerURLs: + - name: 'iot.sales@milesight.com' + region: + - United States + - European Union + - Canada + url: https://www.milesight-iot.com/contact-us/ + +photos: + main: vs340.png + +compliances: + safety: + - body: IEC + norm: EN + standard: 62368-1 + radioEquipment: + - body: ETSI + norm: EN + standard: 301 489-1 + version: 2.2.0 + - body: ETSI + norm: EN + standard: 301 489-3 + version: 2.1.0 diff --git a/vendor/milesight-iot/vs341-codec.yaml b/vendor/milesight-iot/vs341-codec.yaml new file mode 100644 index 0000000000..e7cf3ea405 --- /dev/null +++ b/vendor/milesight-iot/vs341-codec.yaml @@ -0,0 +1,14 @@ +# Uplink decoder decodes binary data uplink into a JSON object (optional) +# For documentation on writing encoders and decoders, see: https://thethingsstack.io/integrations/payload-formatters/javascript/ +uplinkDecoder: + fileName: vs341.js + examples: + - description: Desk&Seat Occupancy Sensor - Milesight IoT + input: + fPort: 85 + bytes: [0x01, 0x75, 0x64, 0x03, 0x00, 0x01] + + output: + data: + battery: 100 + occupancy: occupied diff --git a/vendor/milesight-iot/vs341.js b/vendor/milesight-iot/vs341.js new file mode 100644 index 0000000000..aa4df53ee3 --- /dev/null +++ b/vendor/milesight-iot/vs341.js @@ -0,0 +1,44 @@ +function decodeUplink(input) { + var res = Decoder(input.bytes, input.fPort); + if (res.error) { + return { + errors: [res.error], + }; + } + return { + data: res, + }; +} +/** + * Payload Decoder for The Things Network + * + * Copyright 2023 Milesight IoT + * + * @product VS340 / VS341 + */ +function Decoder(bytes, port) { + return milesight(bytes); +} + +function milesight(bytes) { + var decoded = {}; + + for (var i = 0; i < bytes.length; ) { + var channel_id = bytes[i++]; + var channel_type = bytes[i++]; + // BATTERY + if (channel_id === 0x01 && channel_type === 0x75) { + decoded.battery = bytes[i]; + i += 1; + } + // OCCUPANCY + else if (channel_id === 0x03 && channel_type === 0x00) { + decoded.occupancy = bytes[i] === 0 ? "vacant" : "occupied"; + i += 1; + } else { + break; + } + } + + return decoded; +} diff --git a/vendor/milesight-iot/vs341.png b/vendor/milesight-iot/vs341.png new file mode 100644 index 0000000000..c52a6a5b6a Binary files /dev/null and b/vendor/milesight-iot/vs341.png differ diff --git a/vendor/milesight-iot/vs341.yaml b/vendor/milesight-iot/vs341.yaml new file mode 100644 index 0000000000..fe636537ba --- /dev/null +++ b/vendor/milesight-iot/vs341.yaml @@ -0,0 +1,101 @@ +name: Desk&Seat Occupancy Sensor +description: VS34x is an occupancy sensor designed to detect whether desksorseats in a workspace are occupied, allowing for better managementand optimization of space usage. + +hardwareVersions: + - version: 'V1.0' + numeric: 1 + +firmwareVersions: + - version: '1.0x' + numeric: 1 + hardwareVersions: + - 'V1.0' + + profiles: + EU863-870: + id: profile-eu868 + codec: vs340-codec + US902-928: + id: profile-us915 + codec: vs340-codec + AU915-928: + id: profile-au915 + codec: vs340-codec + AS923: + id: profile-as923 + codec: vs340-codec + CN470-510: + id: profile-cn470 + codec: vs340-codec + KR920-923: + id: profile-kr920 + codec: vs340-codec + IN865-867: + id: profile-in865 + codec: vs340-codec + RU864-870: + id: profile-ru864 + codec: vs340-codec + +sensors: + - pir + - motion + +# 4-20 ma, accelerometer, altitude, analog input, auxiliary, barometer, battery, button, bvoc, co, co2, conductivity, +# current, digital input, dissolved oxygen, distance, dust, energy, gps, gyroscope, h2s, humidity, iaq, level, light, +# lightning, link, magnetometer, moisture, motion, no, no2, o3, particulate matter, ph, pir, pm2.5, pm10, potentiometer, +# power, precipitation, pressure, proximity, pulse count, pulse frequency, radar, rainfall, rssi, smart valve, snr, so2, +# solar radiation, sound, strain, surface temperature, temperature, tilt, time, tvoc, uv, vapor pressure, velocity, +# vibration, voltage, water potential, water, weight, wifi ssid, wind direction, wind speed. + +dimensions: + width: 26 + length: 73 + height: 73 + +battery: + replaceable: true + type: ER18505 Li-SOCl2 battery + +operatingConditions: + temperature: + min: -20 + max: 60 + + relativeHumidity: + min: 0 + max: 0.95 + +ipCode: IP30 + +keyProvisioning: + - custom + - join server +keySecurity: none +productURL: https://www.milesight.com/iot/product/lorawan-sensor/vs34x +dataSheetURL: https://resource.milesight.com/milesight/iot/document/vs34x-datasheet-v1.0.pdf +resellerURLs: + - name: 'iot.sales@milesight.com' + region: + - United States + - European Union + - Canada + url: https://www.milesight-iot.com/contact-us/ + +photos: + main: vs340.png + +compliances: + safety: + - body: IEC + norm: EN + standard: 62368-1 + radioEquipment: + - body: ETSI + norm: EN + standard: 301 489-1 + version: 2.2.0 + - body: ETSI + norm: EN + standard: 301 489-3 + version: 2.1.0 diff --git a/vendor/milesight-iot/ws101-codec.yaml b/vendor/milesight-iot/ws101-codec.yaml new file mode 100644 index 0000000000..7995066ef9 --- /dev/null +++ b/vendor/milesight-iot/ws101-codec.yaml @@ -0,0 +1,11 @@ +# Uplink decoder decodes binary data uplink into a JSON object +uplinkDecoder: + fileName: ws101.js + examples: + - description: Smart Button (example 1) - Milesight IoT + input: + fPort: 85 + bytes: [0xFF, 0x2E, 0x01] + output: + data: + button: short diff --git a/vendor/milesight-iot/ws101.js b/vendor/milesight-iot/ws101.js new file mode 100644 index 0000000000..79f6d7c2ea --- /dev/null +++ b/vendor/milesight-iot/ws101.js @@ -0,0 +1,52 @@ +function decodeUplink(input) { + var res = Decoder(input.bytes, input.fPort); + if (res.error) { + return { + errors: [res.error], + }; + } + return { + data: res, + }; +} +/** + * Payload Decoder for The Things Network + * + * Copyright 2021 Milesight IoT + * + * @product WS101 + */ +function Decoder(bytes, port) { + var decoded = {}; + + for (var i = 0; i < bytes.length;) { + var channel_id = bytes[i++]; + var channel_type = bytes[i++]; + // BATTERY + if (channel_id === 0x01 && channel_type === 0x75) { + decoded.battery = bytes[i]; + i += 1; + } + // PRESS STATE + else if (channel_id === 0xff && channel_type === 0x2e) { + switch (bytes[i]) { + case 1: + decoded.button = "short"; + break; + case 2: + decoded.button = "long"; + break; + case 3: + decoded.button = "double"; + break; + default: + console.log("unsupported"); + } + i += 1; + } else { + break; + } + } + + return decoded; +} diff --git a/vendor/milesight-iot/ws101.png b/vendor/milesight-iot/ws101.png new file mode 100644 index 0000000000..942c26a047 Binary files /dev/null and b/vendor/milesight-iot/ws101.png differ diff --git a/vendor/milesight-iot/ws101.yaml b/vendor/milesight-iot/ws101.yaml new file mode 100644 index 0000000000..f7579c5d86 --- /dev/null +++ b/vendor/milesight-iot/ws101.yaml @@ -0,0 +1,83 @@ +name: Milesight WS101 Smart Button +description: Milesight WS101 is a LoRaWAN®-based smart button for wireless controls, triggers and alarms. WS101 supports multiple press actions, all of which can be defined by the user to control devices or trigger scenes. Besides, Milesight also provides a red button that is primarily used to send SOS alarms. WS101 can be widely used in smart homes, smart offices, hotels, schools, etc. + +hardwareVersions: + - version: 'V1.x' + numeric: 1 + +firmwareVersions: + - version: '1.x' + numeric: 1 + hardwareVersions: + - 'V1.x' + + profiles: + EU863-870: + id: profile-eu868 + lorawanCertified: true + codec: ws101-codec + US902-928: + id: profile-us915 + lorawanCertified: true + codec: ws101-codec + AU915-928: + id: profile-au915 + lorawanCertified: true + codec: ws101-codec + AS923: + id: profile-as923 + lorawanCertified: true + codec: ws101-codec + CN470-510: + id: profile-cn470 + lorawanCertified: true + codec: ws101-codec + KR920-923: + id: profile-kr920 + lorawanCertified: true + codec: ws101-codec + IN865-867: + id: profile-in865 + lorawanCertified: true + codec: ws101-codec + RU864-870: + id: profile-ru864 + lorawanCertified: true + codec: ws101-codec + +sensors: + - button + - battery + +dimensions: + width: 50 + length: 18 + height: 50 + +operatingConditions: + temperature: + min: -30 + max: 60 + + relativeHumidity: + min: 0 + max: 0.9 + +ipCode: IP30 + +keyProvisioning: + - custom + - join server +keySecurity: none +productURL: https://www.milesight-iot.com/lorawan/button/ws101/?utm_source=platform&utm_medium=web&utm_campaign=milesight +dataSheetURL: https://resource.milesight-iot.com/milesight/document/ws101-datasheet-en.pdf +resellerURLs: + - name: 'iot.sales@milesight.com' + region: + - United States + - European Union + - Canada + url: https://www.alibaba.com/product-detail/Milesight-IoT-WS101-LoRaWAN-Smart-Button_1600565527448.html?spm=a2700.shop_plser.41413.14.60d3353fOwN2AL + +photos: + main: ws101.png diff --git a/vendor/milesight-iot/ws136-codec.yaml b/vendor/milesight-iot/ws136-codec.yaml new file mode 100644 index 0000000000..dbaee1df06 --- /dev/null +++ b/vendor/milesight-iot/ws136-codec.yaml @@ -0,0 +1,11 @@ +# Uplink decoder decodes binary data uplink into a JSON object +uplinkDecoder: + fileName: ws136.js + examples: + - description: Smart Scene Panel (example 1) - Milesight IoT + input: + fPort: 85 + bytes: [0xFF, 0x34, 0x01] + output: + data: + button: 1 diff --git a/vendor/milesight-iot/ws136.js b/vendor/milesight-iot/ws136.js new file mode 100644 index 0000000000..a06037e69f --- /dev/null +++ b/vendor/milesight-iot/ws136.js @@ -0,0 +1,44 @@ +function decodeUplink(input) { + var res = Decoder(input.bytes, input.fPort); + if (res.error) { + return { + errors: [res.error], + }; + } + return { + data: res, + }; +} +/** + * Payload Decoder for The Things Network + * + * Copyright 2022 Milesight IoT + * + * @product WS136 / WS156 + */ +function Decoder(bytes, port) { + var decoded = {}; + + for (var i = 0; i < bytes.length;) { + var channel_id = bytes[i++]; + var channel_type = bytes[i++]; + // BATTERY + if (channel_id === 0x01 && channel_type === 0x75) { + decoded.battery = bytes[i]; + i += 1; + } + // PRESS STATE + else if (channel_id === 0xff && channel_type === 0x34) { + var id = bytes[i]; + var command = [bytes[i + 2], bytes[i + 1]]; + // decoded[`button_${id}`] = "trigger"; + decoded.button = id; + // decoded[`button_${id}_command`] = command; + i += 3; + } else { + break; + } + } + + return decoded; +} \ No newline at end of file diff --git a/vendor/milesight-iot/ws136.png b/vendor/milesight-iot/ws136.png new file mode 100644 index 0000000000..6464fa2a29 Binary files /dev/null and b/vendor/milesight-iot/ws136.png differ diff --git a/vendor/milesight-iot/ws136.yaml b/vendor/milesight-iot/ws136.yaml new file mode 100644 index 0000000000..625462f419 --- /dev/null +++ b/vendor/milesight-iot/ws136.yaml @@ -0,0 +1,83 @@ +name: Milesight WS136/WS156-Smart Scene Panel +description: Milesight WS136 & WS156 LoRaWAN® Smart Scene Panel gives a multi button control panel that can simply activate different pre-defined scenes with one-press. Without any additional cable, WS136 & WS156 can be easily installed anywhere and used to control devices via LoRaWAN® or Milesight LoRa D2D communication protocol. Besides, It's equipped a user-defined E-ink screen to suit different scenes. + +hardwareVersions: + - version: 'V1.x' + numeric: 1 + +firmwareVersions: + - version: '1.x' + numeric: 1 + hardwareVersions: + - 'V1.x' + + profiles: + EU863-870: + id: profile-eu868 + lorawanCertified: true + codec: ws136-codec + US902-928: + id: profile-us915 + lorawanCertified: true + codec: ws136-codec + AU915-928: + id: profile-au915 + lorawanCertified: true + codec: ws136-codec + AS923: + id: profile-as923 + lorawanCertified: true + codec: ws136-codec + CN470-510: + id: profile-cn470 + lorawanCertified: true + codec: ws136-codec + KR920-923: + id: profile-kr920 + lorawanCertified: true + codec: ws136-codec + IN865-867: + id: profile-in865 + lorawanCertified: true + codec: ws136-codec + RU864-870: + id: profile-ru864 + lorawanCertified: true + codec: ws136-codec + +sensors: + - button + - battery + +dimensions: + width: 86 + length: 14 + height: 86 + +operatingConditions: + temperature: + min: -10 + max: 50 + + relativeHumidity: + min: 0 + max: 0.9 + +ipCode: IP30 + +keyProvisioning: + - custom + - join server +keySecurity: none +productURL: https://www.milesight-iot.com/lorawan/button/ws136_ws156/?utm_source=platform&utm_medium=web&utm_campaign=milesight +dataSheetURL: https://resource.milesight-iot.com/milesight/document/ws136_ws156-datasheet-en.pdf +resellerURLs: + - name: 'iot.sales@milesight.com' + region: + - United States + - European Union + - Canada + url: https://www.alibaba.com/product-detail/Milesight-IoT-ws136_ws156-LoRaWAN-Smart-Button_1600565527448.html?spm=a2700.shop_plser.41413.14.60d3353fOwN2AL + +photos: + main: ws136.png diff --git a/vendor/milesight-iot/ws156-codec.yaml b/vendor/milesight-iot/ws156-codec.yaml new file mode 100644 index 0000000000..b220529451 --- /dev/null +++ b/vendor/milesight-iot/ws156-codec.yaml @@ -0,0 +1,11 @@ +# Uplink decoder decodes binary data uplink into a JSON object +uplinkDecoder: + fileName: ws156.js + examples: + - description: Smart Scene Panel (example 1) - Milesight IoT + input: + fPort: 85 + bytes: [0xFF, 0x34, 0x01] + output: + data: + button: 1 diff --git a/vendor/milesight-iot/ws156.js b/vendor/milesight-iot/ws156.js new file mode 100644 index 0000000000..a06037e69f --- /dev/null +++ b/vendor/milesight-iot/ws156.js @@ -0,0 +1,44 @@ +function decodeUplink(input) { + var res = Decoder(input.bytes, input.fPort); + if (res.error) { + return { + errors: [res.error], + }; + } + return { + data: res, + }; +} +/** + * Payload Decoder for The Things Network + * + * Copyright 2022 Milesight IoT + * + * @product WS136 / WS156 + */ +function Decoder(bytes, port) { + var decoded = {}; + + for (var i = 0; i < bytes.length;) { + var channel_id = bytes[i++]; + var channel_type = bytes[i++]; + // BATTERY + if (channel_id === 0x01 && channel_type === 0x75) { + decoded.battery = bytes[i]; + i += 1; + } + // PRESS STATE + else if (channel_id === 0xff && channel_type === 0x34) { + var id = bytes[i]; + var command = [bytes[i + 2], bytes[i + 1]]; + // decoded[`button_${id}`] = "trigger"; + decoded.button = id; + // decoded[`button_${id}_command`] = command; + i += 3; + } else { + break; + } + } + + return decoded; +} \ No newline at end of file diff --git a/vendor/milesight-iot/ws156.png b/vendor/milesight-iot/ws156.png new file mode 100644 index 0000000000..6464fa2a29 Binary files /dev/null and b/vendor/milesight-iot/ws156.png differ diff --git a/vendor/milesight-iot/ws156.yaml b/vendor/milesight-iot/ws156.yaml new file mode 100644 index 0000000000..96c30ea7eb --- /dev/null +++ b/vendor/milesight-iot/ws156.yaml @@ -0,0 +1,83 @@ +name: Milesight WS136/WS156-Smart Scene Panel +description: Milesight WS136 & WS156 LoRaWAN® Smart Scene Panel gives a multi button control panel that can simply activate different pre-defined scenes with one-press. Without any additional cable, WS136 & WS156 can be easily installed anywhere and used to control devices via LoRaWAN® or Milesight LoRa D2D communication protocol. Besides, It's equipped a user-defined E-ink screen to suit different scenes. + +hardwareVersions: + - version: 'V1.x' + numeric: 1 + +firmwareVersions: + - version: '1.x' + numeric: 1 + hardwareVersions: + - 'V1.x' + + profiles: + EU863-870: + id: profile-eu868 + lorawanCertified: true + codec: ws156-codec + US902-928: + id: profile-us915 + lorawanCertified: true + codec: ws156-codec + AU915-928: + id: profile-au915 + lorawanCertified: true + codec: ws156-codec + AS923: + id: profile-as923 + lorawanCertified: true + codec: ws156-codec + CN470-510: + id: profile-cn470 + lorawanCertified: true + codec: ws156-codec + KR920-923: + id: profile-kr920 + lorawanCertified: true + codec: ws156-codec + IN865-867: + id: profile-in865 + lorawanCertified: true + codec: ws156-codec + RU864-870: + id: profile-ru864 + lorawanCertified: true + codec: ws156-codec + +sensors: + - button + - battery + +dimensions: + width: 86 + length: 14 + height: 86 + +operatingConditions: + temperature: + min: -10 + max: 50 + + relativeHumidity: + min: 0 + max: 0.9 + +ipCode: IP30 + +keyProvisioning: + - custom + - join server +keySecurity: none +productURL: https://www.milesight-iot.com/lorawan/button/ws136_ws156/?utm_source=platform&utm_medium=web&utm_campaign=milesight +dataSheetURL: https://resource.milesight-iot.com/milesight/document/ws136_ws156-datasheet-en.pdf +resellerURLs: + - name: 'iot.sales@milesight.com' + region: + - United States + - European Union + - Canada + url: https://www.alibaba.com/product-detail/Milesight-IoT-ws136_ws156-LoRaWAN-Smart-Button_1600565527448.html?spm=a2700.shop_plser.41413.14.60d3353fOwN2AL + +photos: + main: ws156.png diff --git a/vendor/milesight-iot/ws201-codec.yaml b/vendor/milesight-iot/ws201-codec.yaml new file mode 100644 index 0000000000..17d2703d08 --- /dev/null +++ b/vendor/milesight-iot/ws201-codec.yaml @@ -0,0 +1,15 @@ +# Uplink decoder decodes binary data uplink into a JSON object (optional) +# For documentation on writing encoders and decoders, see: https://thethingsstack.io/integrations/payload-formatters/javascript/ +uplinkDecoder: + fileName: ws201.js + examples: + - description: Smart Fill Level Monitor Sensor - Milesight IoT + input: + fPort: 85 + bytes: [0x01, 0x75, 0x64, 0x03, 0x82, 0x3E, 0x00, 0x04, 0xD6, 0x45] + + output: + data: + battery: 100 + distance: 62 + remaining: 69 diff --git a/vendor/milesight-iot/ws201.js b/vendor/milesight-iot/ws201.js new file mode 100644 index 0000000000..4c8a534878 --- /dev/null +++ b/vendor/milesight-iot/ws201.js @@ -0,0 +1,57 @@ +function decodeUplink(input) { + var res = Decoder(input.bytes, input.fPort); + if (res.error) { + return { + errors: [res.error], + }; + } + return { + data: res, + }; +} +/** + * Payload Decoder for The Things Network + * + * Copyright 2023 Milesight IoT + * + * @product WS201 + */ +function Decoder(bytes, port) { + return milesight(bytes); +} + +function milesight(bytes) { + var decoded = {}; + + for (var i = 0; i < bytes.length; ) { + var channel_id = bytes[i++]; + var channel_type = bytes[i++]; + // BATTERY + if (channel_id === 0x01 && channel_type === 0x75) { + decoded.battery = bytes[i]; + i += 1; + } + // DISTANCE + else if (channel_id === 0x03 && channel_type === 0x82) { + decoded.distance = readUInt16LE(bytes.slice(i, i + 2)); + i += 2; + } + // REMAINING AMOUNT + else if (channel_id === 0x04 && channel_type === 0xd6) { + decoded.remaining = bytes[i]; + i += 1; + } else { + break; + } + } + + return decoded; +} + +/* ****************************************** + * bytes to number + ********************************************/ +function readUInt16LE(bytes) { + var value = (bytes[1] << 8) + bytes[0]; + return value & 0xffff; +} diff --git a/vendor/milesight-iot/ws201.png b/vendor/milesight-iot/ws201.png new file mode 100644 index 0000000000..9476a4bfc8 Binary files /dev/null and b/vendor/milesight-iot/ws201.png differ diff --git a/vendor/milesight-iot/ws201.yaml b/vendor/milesight-iot/ws201.yaml new file mode 100644 index 0000000000..b7054d4bec --- /dev/null +++ b/vendor/milesight-iot/ws201.yaml @@ -0,0 +1,101 @@ +name: Smart Fill Level Monitor Sensor +description: WS201 is a wireless fill-level monitoring sensor that securely monitors a small container’s fill level especially tissue boxes using ToF + +hardwareVersions: + - version: 'V1.0' + numeric: 1 + +firmwareVersions: + - version: '1.0x' + numeric: 1 + hardwareVersions: + - 'V1.0' + + profiles: + EU863-870: + id: profile-eu868 + codec: ws201-codec + US902-928: + id: profile-us915 + codec: ws201-codec + AU915-928: + id: profile-au915 + codec: ws201-codec + AS923: + id: profile-as923 + codec: ws201-codec + CN470-510: + id: profile-cn470 + codec: ws201-codec + KR920-923: + id: profile-kr920 + codec: ws201-codec + IN865-867: + id: profile-in865 + codec: ws201-codec + RU864-870: + id: profile-ru864 + codec: ws201-codec + +sensors: + - level + - distance + +# 4-20 ma, accelerometer, altitude, analog input, auxiliary, barometer, battery, button, bvoc, co, co2, conductivity, +# current, digital input, dissolved oxygen, distance, dust, energy, gps, gyroscope, h2s, humidity, iaq, level, light, +# lightning, link, magnetometer, moisture, motion, no, no2, o3, particulate matter, ph, pir, pm2.5, pm10, potentiometer, +# power, precipitation, pressure, proximity, pulse count, pulse frequency, radar, rainfall, rssi, smart valve, snr, so2, +# solar radiation, sound, strain, surface temperature, temperature, tilt, time, tvoc, uv, vapor pressure, velocity, +# vibration, voltage, water potential, water, weight, wifi ssid, wind direction, wind speed. + +dimensions: + width: 12 + length: 38 + height: 66 + +battery: + replaceable: true + type: CR2450 Lithium Battery + +operatingConditions: + temperature: + min: -10 + max: 60 + + relativeHumidity: + min: 0 + max: 0.95 + +ipCode: IP30 + +keyProvisioning: + - custom + - join server +keySecurity: none +productURL: https://www.milesight.com/iot/product/lorawan-sensor/ws201 +dataSheetURL: https://resource.milesight.com/milesight/iot/document/ws201-datasheet-en.pdf +resellerURLs: + - name: 'iot.sales@milesight.com' + region: + - United States + - European Union + - Canada + url: https://www.milesight-iot.com/contact-us/ + +photos: + main: ws201.png + +compliances: + safety: + - body: IEC + norm: EN + standard: 62368-1 + radioEquipment: + - body: ETSI + norm: EN + standard: 301 489-1 + version: 2.2.0 + - body: ETSI + norm: EN + standard: 301 489-3 + version: 2.1.0 diff --git a/vendor/milesight-iot/ws202-codec.yaml b/vendor/milesight-iot/ws202-codec.yaml new file mode 100644 index 0000000000..6a6f2ae718 --- /dev/null +++ b/vendor/milesight-iot/ws202-codec.yaml @@ -0,0 +1,18 @@ +# Uplink decoder decodes binary data uplink into a JSON object +uplinkDecoder: + fileName: ws202.js + examples: + - description: PIR Sensors (example 1) - Milesight IoT + input: + fPort: 85 + bytes: [0x03, 0x00, 0x01] + output: + data: + pir: trigger + - description: PIR Sensors (example 2) - Milesgiht IoT + input: + fPort: 85 + bytes: [0x04, 0x00, 0x00] + output: + data: + light: dark diff --git a/vendor/milesight-iot/ws202.js b/vendor/milesight-iot/ws202.js new file mode 100644 index 0000000000..a546e78a94 --- /dev/null +++ b/vendor/milesight-iot/ws202.js @@ -0,0 +1,45 @@ +function decodeUplink(input) { + var res = Decoder(input.bytes, input.fPort); + if (res.error) { + return { + errors: [res.error], + }; + } + return { + data: res, + }; +} +/** + * Payload Decoder for The Things Network + * + * Copyright 2021 Milesight IoT + * + * @product WS101 + */ +function Decoder(bytes, port) { + var decoded = {}; + + for (var i = 0; i < bytes.length;) { + var channel_id = bytes[i++]; + var channel_type = bytes[i++]; + // BATTERY + if (channel_id === 0x01 && channel_type === 0x75) { + decoded.battery = bytes[i]; + i += 1; + } + // PIR + else if (channel_id === 0x03 && channel_type === 0x00) { + decoded.pir = bytes[i] === 0 ? "normal" : "trigger"; + i += 1; + } + // LIGHT + else if (channel_id === 0x04 && channel_type === 0x00) { + decoded.light = bytes[i] === 0 ? "dark" : "light"; + i += 1; + } else { + break; + } + } + + return decoded; +} \ No newline at end of file diff --git a/vendor/milesight-iot/ws202.png b/vendor/milesight-iot/ws202.png new file mode 100644 index 0000000000..51e0e0aa2d Binary files /dev/null and b/vendor/milesight-iot/ws202.png differ diff --git a/vendor/milesight-iot/ws202.yaml b/vendor/milesight-iot/ws202.yaml new file mode 100644 index 0000000000..3bb89919a7 --- /dev/null +++ b/vendor/milesight-iot/ws202.yaml @@ -0,0 +1,84 @@ +name: Milesight WS202 PIR & Light Sensor +description: Milesight WS202 is a LoRa PIR sensor based on passive infrared technology to detect a motion or occupancy. WS202 can detect whether there is movement within the range of 6-8 m and send the changes via LoRaWAN® network. Besides, WS202 equips with light sensor which can link PIR detection results to trigger scenes. With compact size and powered battery, WS202 is easy to install everywhere. + +hardwareVersions: + - version: 'V1.x' + numeric: 1 + +firmwareVersions: + - version: '1.x' + numeric: 1 + hardwareVersions: + - 'V1.x' + + profiles: + EU863-870: + id: profile-eu868 + lorawanCertified: true + codec: ws202-codec + US902-928: + id: profile-us915 + lorawanCertified: true + codec: ws202-codec + AU915-928: + id: profile-au915 + lorawanCertified: true + codec: ws202-codec + AS923: + id: profile-as923 + lorawanCertified: true + codec: ws202-codec + CN470-510: + id: profile-cn470 + lorawanCertified: true + codec: ws202-codec + KR920-923: + id: profile-kr920 + lorawanCertified: true + codec: ws202-codec + IN865-867: + id: profile-in865 + lorawanCertified: true + codec: ws202-codec + RU864-870: + id: profile-ru864 + lorawanCertified: true + codec: ws202-codec + +sensors: + - battery + - pir + - light + +dimensions: + width: 50 + length: 23.8 + height: 50 + +operatingConditions: + temperature: + min: -30 + max: 60 + + relativeHumidity: + min: 0 + max: 0.9 + +ipCode: IP30 + +keyProvisioning: + - custom + - join server +keySecurity: none +productURL: https://www.milesight-iot.com/lorawan/sensor/ws202/?utm_source=platform&utm_medium=web&utm_campaign=milesight +dataSheetURL: https://resource.milesight-iot.com/milesight/document/ws202-datasheet-en.pdf +resellerURLs: + - name: 'iot.sales@milesight.com' + region: + - United States + - European Union + - Canada + url: https://www.alibaba.com/product-detail/Milesight-LoRaWAN-PIR-Light-Sensor-WS202_1600565502532.html?spm=a2700.shop_plser.41413.12.48633c61KeZU12 + +photos: + main: ws202.png diff --git a/vendor/milesight-iot/ws203-codec.yaml b/vendor/milesight-iot/ws203-codec.yaml new file mode 100644 index 0000000000..c168c093d6 --- /dev/null +++ b/vendor/milesight-iot/ws203-codec.yaml @@ -0,0 +1,16 @@ +# Uplink decoder decodes binary data uplink into a JSON object (optional) +# For documentation on writing encoders and decoders, see: https://thethingsstack.io/integrations/payload-formatters/javascript/ +uplinkDecoder: + fileName: ws203.js + examples: + - description: Motion&TH Sensor - Milesight IoT + input: + fPort: 85 + bytes: [0x01, 0x75, 0x64, 0x03, 0x67, 0x34, 0x01, 0x04, 0x68, 0x65, 0x05, 0x00, 0x00] + + output: + data: + battery: 100 + humidity: 50.5 + occupancy: vacant + temperature: 30.8 diff --git a/vendor/milesight-iot/ws203.js b/vendor/milesight-iot/ws203.js new file mode 100644 index 0000000000..f56c40d4f2 --- /dev/null +++ b/vendor/milesight-iot/ws203.js @@ -0,0 +1,108 @@ +function decodeUplink(input) { + var res = Decoder(input.bytes, input.fPort); + if (res.error) { + return { + errors: [res.error], + }; + } + return { + data: res, + }; +} +/** + * Payload Decoder for The Things Network + * + * Copyright 2023 Milesight IoT + * + * @product WS203 + */ +function Decoder(bytes, port) { + return milesight(bytes); +} + +function milesight(bytes) { + var decoded = {}; + + for (var i = 0; i < bytes.length; ) { + var channel_id = bytes[i++]; + var channel_type = bytes[i++]; + // BATTERY + if (channel_id === 0x01 && channel_type === 0x75) { + decoded.battery = bytes[i]; + i += 1; + } + // TEMPERATURE + else if (channel_id === 0x03 && channel_type === 0x67) { + // ℃ + decoded.temperature = readInt16LE(bytes.slice(i, i + 2)) / 10; + i += 2; + + // ℉ + // decoded.temperature = readInt16LE(bytes.slice(i, i + 2)) / 10 * 1.8 + 32; + // i +=2; + } + // HUMIDITY + else if (channel_id === 0x04 && channel_type === 0x68) { + decoded.humidity = bytes[i] / 2; + i += 1; + } + // OCCUPANCY + else if (channel_id === 0x05 && channel_type === 0x00) { + decoded.occupancy = bytes[i] === 0 ? "vacant" : "occupied"; + i += 1; + } + // TEMPERATURE WITH ABNORMAL + else if (channel_id === 0x83 && channel_type === 0x67) { + decoded.temperature = readInt16LE(bytes.slice(i, i + 2)) / 10; + decoded.temperature_abnormal = bytes[i + 2] === 0 ? "normal" : "abnormal"; + i += 3; + } + // HISTORICAL DATA + else if (channel_id === 0x20 && channel_type === 0xce) { + var data = {}; + data.timestamp = readUInt32LE(bytes.slice(i, i + 4)); + var report_type = bytes[i + 4]; + data.report_type = ["temperature resume", "temperature threshold", "pir idle", "pir occupancy", "period"][report_type & 0x07]; + data.occupancy = bytes[i + 5] === 0 ? "vacant" : "occupied"; + data.temperature = readInt16LE(bytes.slice(i + 6, i + 8)) / 10; + data.humidity = bytes[i + 8] / 2; + i += 9; + + decoded.history = decoded.history || []; + decoded.history.push(data); + } else { + break; + } + } + + return decoded; +} + +function readUInt8LE(bytes) { + return bytes & 0xff; +} + +function readInt8LE(bytes) { + var ref = readUInt8LE(bytes); + return ref > 0x7f ? ref - 0x100 : ref; +} + +function readUInt16LE(bytes) { + var value = (bytes[1] << 8) + bytes[0]; + return value & 0xffff; +} + +function readInt16LE(bytes) { + var ref = readUInt16LE(bytes); + return ref > 0x7fff ? ref - 0x10000 : ref; +} + +function readUInt32LE(bytes) { + var value = (bytes[3] << 24) + (bytes[2] << 16) + (bytes[1] << 8) + bytes[0]; + return (value & 0xffffffff) >>> 0; +} + +function readInt32LE(bytes) { + var ref = readUInt32LE(bytes); + return ref > 0x7fffffff ? ref - 0x100000000 : ref; +} diff --git a/vendor/milesight-iot/ws203.png b/vendor/milesight-iot/ws203.png new file mode 100644 index 0000000000..b94f247864 Binary files /dev/null and b/vendor/milesight-iot/ws203.png differ diff --git a/vendor/milesight-iot/ws203.yaml b/vendor/milesight-iot/ws203.yaml new file mode 100644 index 0000000000..388a656ff7 --- /dev/null +++ b/vendor/milesight-iot/ws203.yaml @@ -0,0 +1,104 @@ +name: Motion&TH Sensor +description: Milesight WS203 is an environmental monitoring devicethat combines motion and temperature/humidity (TH) sensors. + +hardwareVersions: + - version: 'V1.0' + numeric: 1 + +firmwareVersions: + - version: '1.0x' + numeric: 1 + hardwareVersions: + - 'V1.0' + + profiles: + EU863-870: + id: profile-eu868 + codec: ws203-codec + US902-928: + id: profile-us915 + codec: ws203-codec + AU915-928: + id: profile-au915 + codec: ws203-codec + AS923: + id: profile-as923 + codec: ws203-codec + CN470-510: + id: profile-cn470 + codec: ws203-codec + KR920-923: + id: profile-kr920 + codec: ws203-codec + IN865-867: + id: profile-in865 + codec: ws203-codec + RU864-870: + id: profile-ru864 + codec: ws203-codec + +sensors: + - battery + - temperature + - humidity + - pir + - motion + +# 4-20 ma, accelerometer, altitude, analog input, auxiliary, barometer, battery, button, bvoc, co, co2, conductivity, +# current, digital input, dissolved oxygen, distance, dust, energy, gps, gyroscope, h2s, humidity, iaq, level, light, +# lightning, link, magnetometer, moisture, motion, no, no2, o3, particulate matter, ph, pir, pm2.5, pm10, potentiometer, +# power, precipitation, pressure, proximity, pulse count, pulse frequency, radar, rainfall, rssi, smart valve, snr, so2, +# solar radiation, sound, strain, surface temperature, temperature, tilt, time, tvoc, uv, vapor pressure, velocity, +# vibration, voltage, water potential, water, weight, wifi ssid, wind direction, wind speed. + +dimensions: + width: 26 + length: 73 + height: 73 + +battery: + replaceable: true + type: ER18505 Li-SOCl2 Battery + +operatingConditions: + temperature: + min: -20 + max: 60 + + relativeHumidity: + min: 0 + max: 0.95 + +ipCode: IP30 + +keyProvisioning: + - custom + - join server +keySecurity: none +productURL: https://www.milesight.com/iot/product/lorawan-sensor/ws203 +dataSheetURL: https://resource.milesight.com/milesight/iot/document/ws203-datasheet-v1.0.pdf +resellerURLs: + - name: 'iot.sales@milesight.com' + region: + - United States + - European Union + - Canada + url: https://www.milesight-iot.com/contact-us/ + +photos: + main: ws203.png + +compliances: + safety: + - body: IEC + norm: EN + standard: 62368-1 + radioEquipment: + - body: ETSI + norm: EN + standard: 301 489-1 + version: 2.2.0 + - body: ETSI + norm: EN + standard: 301 489-3 + version: 2.1.0 diff --git a/vendor/milesight-iot/ws301-codec.yaml b/vendor/milesight-iot/ws301-codec.yaml new file mode 100644 index 0000000000..92a11f78af --- /dev/null +++ b/vendor/milesight-iot/ws301-codec.yaml @@ -0,0 +1,18 @@ +# Uplink decoder decodes binary data uplink into a JSON object +uplinkDecoder: + fileName: ws301.js + examples: + - description: Magnetic Contact Switch (example 1) - Milesight IoT + input: + fPort: 85 + bytes: [0x03, 0x00, 0x01] + output: + data: + door: open + - description: Magnetic Contact Switch (example 2) - Milesgiht IoT + input: + fPort: 85 + bytes: [0x04, 0x00, 0x01] + output: + data: + install: no diff --git a/vendor/milesight-iot/ws301.js b/vendor/milesight-iot/ws301.js new file mode 100644 index 0000000000..f98a16c516 --- /dev/null +++ b/vendor/milesight-iot/ws301.js @@ -0,0 +1,45 @@ +function decodeUplink(input) { + var res = Decoder(input.bytes, input.fPort); + if (res.error) { + return { + errors: [res.error], + }; + } + return { + data: res, + }; +} +/** + * Payload Decoder for The Things Network + * + * Copyright 2021 Milesight IoT + * + * @product WS301 + */ +function Decoder(bytes, port) { + var decoded = {}; + + for (var i = 0; i < bytes.length;) { + var channel_id = bytes[i++]; + var channel_type = bytes[i++]; + // BATTERY + if (channel_id === 0x01 && channel_type === 0x75) { + decoded.battery = bytes[i]; + i += 1; + } + // DOOR / WINDOW STATE + else if (channel_id === 0x03 && channel_type === 0x00) { + decoded.door = bytes[i] === 0 ? "close" : "open"; + i += 1; + } + // + else if (channel_id === 0x04 && channel_type === 0x00) { + decoded.install = bytes[i] === 0 ? "yes" : "no"; + i += 1; + } else { + break; + } + } + + return decoded; +} diff --git a/vendor/milesight-iot/ws301.png b/vendor/milesight-iot/ws301.png new file mode 100644 index 0000000000..36fa5049d1 Binary files /dev/null and b/vendor/milesight-iot/ws301.png differ diff --git a/vendor/milesight-iot/ws301.yaml b/vendor/milesight-iot/ws301.yaml new file mode 100644 index 0000000000..8c2fc6cdc1 --- /dev/null +++ b/vendor/milesight-iot/ws301.yaml @@ -0,0 +1,84 @@ +name: Milesight WS301-Wireless Magnetic Contact Switch +description: Milesight WS301 can be mounted on any doors or windows to detect an opening or closing event. It adds physical security monitoring to your location by warning of intrusion or unauthorized entry. Besides, it provides more than 4 years service life without battery replacement. Compliant with Milesight LoRaWAN® gateway and Milesight IoT Cloud solution, WS301 will surely monitor the real-time open/close status and receive alarms via mobile App. + +hardwareVersions: + - version: 'V1.x' + numeric: 1 + +firmwareVersions: + - version: '1.x' + numeric: 1 + hardwareVersions: + - 'V1.x' + + profiles: + EU863-870: + id: profile-eu868 + lorawanCertified: true + codec: ws301-codec + US902-928: + id: profile-us915 + lorawanCertified: true + codec: ws301-codec + AU915-928: + id: profile-au915 + lorawanCertified: true + codec: ws301-codec + AS923: + id: profile-as923 + lorawanCertified: true + codec: ws301-codec + CN470-510: + id: profile-cn470 + lorawanCertified: true + codec: ws301-codec + KR920-923: + id: profile-kr920 + lorawanCertified: true + codec: ws301-codec + IN865-867: + id: profile-in865 + lorawanCertified: true + codec: ws301-codec + RU864-870: + id: profile-ru864 + lorawanCertified: true + codec: ws301-codec + +sensors: + - battery + # door + # install + +dimensions: + width: 31 + length: 18 + height: 50.5 + +operatingConditions: + temperature: + min: -40 + max: 70 + + relativeHumidity: + min: 0 + max: 0.95 + +ipCode: IP30 + +keyProvisioning: + - custom + - join server +keySecurity: none +productURL: https://www.milesight-iot.com/lorawan/sensor/ws301/?utm_source=platform&utm_medium=web&utm_campaign=milesight +dataSheetURL: https://resource.milesight-iot.com/milesight/document/ws301-datasheet-en.pdf +resellerURLs: + - name: 'iot.sales@milesight.com' + region: + - United States + - European Union + - Canada + url: https://www.alibaba.com/product-detail/WS301-LoRaWAN-Wire-Free-Magnetic-Contact_1600289951732.html?spm=a2700.details.0.0.69242108TatuBJ + +photos: + main: ws301.png diff --git a/vendor/milesight-iot/ws302-codec.yaml b/vendor/milesight-iot/ws302-codec.yaml new file mode 100644 index 0000000000..a83a11ca7a --- /dev/null +++ b/vendor/milesight-iot/ws302-codec.yaml @@ -0,0 +1,4 @@ +# Uplink decoder decodes binary data uplink into a JSON object (optional) +# For documentation on writing encoders and decoders, see: https://thethingsstack.io/integrations/payload-formatters/javascript/ +uplinkDecoder: + fileName: ws302.js diff --git a/vendor/milesight-iot/ws302.js b/vendor/milesight-iot/ws302.js new file mode 100644 index 0000000000..449e81aa44 --- /dev/null +++ b/vendor/milesight-iot/ws302.js @@ -0,0 +1,112 @@ +function decodeUplink(input) { + var res = Decoder(input.bytes, input.fPort); + if (res.error) { + return { + errors: [res.error], + }; + } + return { + data: res, + }; +} +/** + * Payload Decoder for The Things Network + * + * Copyright 2023 Milesight IoT + * + * @product WS302 + */ +function Decoder(bytes, port) { + return milesight(bytes); +} + +function milesight(bytes) { + var decoded = {}; + + for (var i = 0; i < bytes.length; ) { + var channel_id = bytes[i++]; + var channel_type = bytes[i++]; + + // BATTERY + if (channel_id === 0x01 && channel_type === 0x75) { + decoded.battery = bytes[i]; + i += 1; + } + // SOUND + else if (channel_id === 0x05 && channel_type === 0x5b) { + decoded.freq_weight = readFrequecyWeightType(bytes[i]); + decoded.time_weight = readTimeWeightType(bytes[i]); + decoded.la = readUInt16LE(bytes.slice(i + 1, i + 3)) / 10; + decoded.laeq = readUInt16LE(bytes.slice(i + 3, i + 5)) / 10; + decoded.lamax = readUInt16LE(bytes.slice(i + 5, i + 7)) / 10; + i += 7; + } + // LoRaWAN Class Type + else if (channel_id === 0xff && channel_type === 0x0f) { + switch (bytes[i]) { + case 0: + decoded.class_type = "class-a"; + break; + case 1: + decoded.class_type = "class-b"; + break; + case 2: + decoded.class_type = "class-c"; + break; + } + i += 1; + } else { + break; + } + } + + return decoded; +} + +function readFrequecyWeightType(bytes) { + var type = ""; + + var bits = bytes & 0x03; + switch (bits) { + case 0: + type = "Z"; + break; + case 1: + type = "A"; + break; + case 2: + type = "C"; + break; + } + + return type; +} + +function readTimeWeightType(bytes) { + var type = ""; + + var bits = (bytes[0] >> 2) & 0x03; + switch (bits) { + case 0: + type = "impulse"; + break; + case 1: + type = "fast"; + break; + case 2: + type = "slow"; + break; + } + + return type; +} + +function readUInt16LE(bytes) { + var value = (bytes[1] << 8) + bytes[0]; + return value & 0xffff; +} + +function readInt16LE(bytes) { + var ref = readUInt16LE(bytes); + return ref > 0x7fff ? ref - 0x10000 : ref; +} diff --git a/vendor/milesight-iot/ws302.png b/vendor/milesight-iot/ws302.png new file mode 100644 index 0000000000..1f44aea749 Binary files /dev/null and b/vendor/milesight-iot/ws302.png differ diff --git a/vendor/milesight-iot/ws302.yaml b/vendor/milesight-iot/ws302.yaml new file mode 100644 index 0000000000..73d6b31edd --- /dev/null +++ b/vendor/milesight-iot/ws302.yaml @@ -0,0 +1,101 @@ +name: Sound Level Sensor +description: WS302 is a LoRa sound level sensor with integrated microphone. WS302 can not only measure a wide range of noise levels + +hardwareVersions: + - version: 'V1.0' + numeric: 1 + +firmwareVersions: + - version: '1.0x' + numeric: 1 + hardwareVersions: + - 'V1.0' + + profiles: + EU863-870: + id: profile-eu868 + codec: ws302-codec + US902-928: + id: profile-us915 + codec: ws302-codec + AU915-928: + id: profile-au915 + codec: ws302-codec + AS923: + id: profile-as923 + codec: ws302-codec + CN470-510: + id: profile-cn470 + codec: ws302-codec + KR920-923: + id: profile-kr920 + codec: ws302-codec + IN865-867: + id: profile-in865 + codec: ws302-codec + RU864-870: + id: profile-ru864 + codec: ws302-codec + +sensors: + - battery + - sound + +# 4-20 ma, accelerometer, altitude, analog input, auxiliary, barometer, battery, button, bvoc, co, co2, conductivity, +# current, digital input, dissolved oxygen, distance, dust, energy, gps, gyroscope, h2s, humidity, iaq, level, light, +# lightning, link, magnetometer, moisture, motion, no, no2, o3, particulate matter, ph, pir, pm2.5, pm10, potentiometer, +# power, precipitation, pressure, proximity, pulse count, pulse frequency, radar, rainfall, rssi, smart valve, snr, so2, +# solar radiation, sound, strain, surface temperature, temperature, tilt, time, tvoc, uv, vapor pressure, velocity, +# vibration, voltage, water potential, water, weight, wifi ssid, wind direction, wind speed. + +dimensions: + width: 20.5 + length: 68 + height: 65 + +battery: + replaceable: true + type: ER14505 Li-SOCl2 *2 + +operatingConditions: + temperature: + min: -20 + max: 60 + + relativeHumidity: + min: 0 + max: 0.95 + +ipCode: IP30 + +keyProvisioning: + - custom + - join server +keySecurity: none +productURL: https://www.milesight.com/iot/product/lorawan-sensor/ws302 +dataSheetURL: https://resource.milesight.com/milesight/iot/document/ws302-datasheet-en.pdf +resellerURLs: + - name: 'iot.sales@milesight.com' + region: + - United States + - European Union + - Canada + url: https://www.milesight-iot.com/contact-us/ + +photos: + main: ws302.png + +compliances: + safety: + - body: IEC + norm: EN + standard: 62368-1 + radioEquipment: + - body: ETSI + norm: EN + standard: 301 489-1 + version: 2.2.0 + - body: ETSI + norm: EN + standard: 301 489-3 + version: 2.1.0 diff --git a/vendor/milesight-iot/ws303-codec.yaml b/vendor/milesight-iot/ws303-codec.yaml new file mode 100644 index 0000000000..ef52a4ce9a --- /dev/null +++ b/vendor/milesight-iot/ws303-codec.yaml @@ -0,0 +1,14 @@ +# Uplink decoder decodes binary data uplink into a JSON object (optional) +# For documentation on writing encoders and decoders, see: https://thethingsstack.io/integrations/payload-formatters/javascript/ +uplinkDecoder: + fileName: ws303.js + examples: + - description: Mini Leak Detection Sensor - Milesight IoT + input: + fPort: 85 + bytes: [0x01, 0x75, 0x64, 0x03, 0x00, 0x01] + + output: + data: + battery: 100 + leak_status: leak diff --git a/vendor/milesight-iot/ws303.js b/vendor/milesight-iot/ws303.js new file mode 100644 index 0000000000..f30c1ce04b --- /dev/null +++ b/vendor/milesight-iot/ws303.js @@ -0,0 +1,44 @@ +function decodeUplink(input) { + var res = Decoder(input.bytes, input.fPort); + if (res.error) { + return { + errors: [res.error], + }; + } + return { + data: res, + }; +} +/** + * Payload Decoder for The Things Network + * + * Copyright 2023 Milesight IoT + * + * @product WS303 + */ +function Decoder(bytes, port) { + return milesight(bytes); +} + +function milesight(bytes) { + var decoded = {}; + + for (var i = 0; i < bytes.length; ) { + var channel_id = bytes[i++]; + var channel_type = bytes[i++]; + // BATTERY + if (channel_id === 0x01 && channel_type === 0x75) { + decoded.battery = bytes[i]; + i += 1; + } + // WATER LEAK + else if (channel_id === 0x03 && channel_type === 0x00) { + decoded.leak_status = (bytes[i] === 0) ? 'no leak' : 'leak'; + i += 1; + } else { + break; + } + } + + return decoded; +} \ No newline at end of file diff --git a/vendor/milesight-iot/ws303.png b/vendor/milesight-iot/ws303.png new file mode 100644 index 0000000000..b7656e0972 Binary files /dev/null and b/vendor/milesight-iot/ws303.png differ diff --git a/vendor/milesight-iot/ws303.yaml b/vendor/milesight-iot/ws303.yaml new file mode 100644 index 0000000000..17f8472091 --- /dev/null +++ b/vendor/milesight-iot/ws303.yaml @@ -0,0 +1,101 @@ +name: Mini Leak Detection Sensor +description: WS303 is a tiny and mighty leakage detection sensor for detecting presence of water leaks and transmitting an alarm using LoRaWAN® technology + +hardwareVersions: + - version: 'V1.0' + numeric: 1 + +firmwareVersions: + - version: '1.0x' + numeric: 1 + hardwareVersions: + - 'V1.0' + + profiles: + EU863-870: + id: profile-eu868 + codec: ws303-codec + US902-928: + id: profile-us915 + codec: ws303-codec + AU915-928: + id: profile-au915 + codec: ws303-codec + AS923: + id: profile-as923 + codec: ws303-codec + CN470-510: + id: profile-cn470 + codec: ws303-codec + KR920-923: + id: profile-kr920 + codec: ws303-codec + IN865-867: + id: profile-in865 + codec: ws303-codec + RU864-870: + id: profile-ru864 + codec: ws303-codec + +sensors: + - battery + - water + +# 4-20 ma, accelerometer, altitude, analog input, auxiliary, barometer, battery, button, bvoc, co, co2, conductivity, +# current, digital input, dissolved oxygen, distance, dust, energy, gps, gyroscope, h2s, humidity, iaq, level, light, +# lightning, link, magnetometer, moisture, motion, no, no2, o3, particulate matter, ph, pir, pm2.5, pm10, potentiometer, +# power, precipitation, pressure, proximity, pulse count, pulse frequency, radar, rainfall, rssi, smart valve, snr, so2, +# solar radiation, sound, strain, surface temperature, temperature, tilt, time, tvoc, uv, vapor pressure, velocity, +# vibration, voltage, water potential, water, weight, wifi ssid, wind direction, wind speed. + +dimensions: + width: 14 + length: 63 + height: 63 + +battery: + replaceable: true + type: CR2450 Lithium Battery + +operatingConditions: + temperature: + min: -10 + max: 60 + + relativeHumidity: + min: 0 + max: 0.95 + +ipCode: IP67 + +keyProvisioning: + - custom + - join server +keySecurity: none +productURL: https://www.milesight.com/iot/product/lorawan-sensor/ws303 +dataSheetURL: https://resource.milesight.com/milesight/iot/document/ws303-datasheet-en.pdf +resellerURLs: + - name: 'iot.sales@milesight.com' + region: + - United States + - European Union + - Canada + url: https://www.milesight-iot.com/contact-us/ + +photos: + main: ws303.png + +compliances: + safety: + - body: IEC + norm: EN + standard: 62368-1 + radioEquipment: + - body: ETSI + norm: EN + standard: 301 489-1 + version: 2.2.0 + - body: ETSI + norm: EN + standard: 301 489-3 + version: 2.1.0 diff --git a/vendor/milesight-iot/ws50x-codec.yaml b/vendor/milesight-iot/ws50x-codec.yaml new file mode 100644 index 0000000000..793acff163 --- /dev/null +++ b/vendor/milesight-iot/ws50x-codec.yaml @@ -0,0 +1,16 @@ +# Uplink decoder decodes binary data uplink into a JSON object +uplinkDecoder: + fileName: ws50x.js + examples: + - description: Wall Switch (example 1) - Milesight IoT + input: + fPort: 85 + bytes: [0xFF, 0x29, 0x31] + output: + data: + switch_1: open + switch_2: close + switch_3: close + switch_1_change: yes + switch_2_change: yes + switch_3_change: no diff --git a/vendor/milesight-iot/ws50x.js b/vendor/milesight-iot/ws50x.js new file mode 100644 index 0000000000..8c1a969349 --- /dev/null +++ b/vendor/milesight-iot/ws50x.js @@ -0,0 +1,59 @@ +function decodeUplink(input) { + var res = Decoder(input.bytes, input.fPort); + if (res.error) { + return { + errors: [res.error], + }; + } + return { + data: res, + }; +} +/** + * Payload Decoder for The Things Network + * + * Copyright 2021 Milesight IoT + * + * @product WS50x + */ +function Decoder(bytes, port) { + var decoded = {}; + + for (var i = 0; i < bytes.length;) { + var channel_id = bytes[i++]; + var channel_type = bytes[i++]; + + // SWITCH STATE + if (channel_id === 0xff && channel_type === 0x29) { + // TTN unsupport binary (0b00000001 --> 1) + // payload (0 0 0 0 0 0 0 0) + // Switch 3 2 1 3 2 1 + // ------- ------- + // bit mask change state + decoded.switch_1 = (bytes[i] & 1) == 1 ? "open" : "close"; + decoded.switch_1_change = ((bytes[i] >> 4) & 1) == 1 ? "yes" : "no"; + + decoded.switch_2 = ((bytes[i] >> 1) & 1) == 1 ? "open" : "close"; + decoded.switch_2_change = ((bytes[i] >> 5) & 1) == 1 ? "yes" : "no"; + + decoded.switch_3 = ((bytes[i] >> 2) & 1) == 1 ? "open" : "close"; + decoded.switch_3_change = ((bytes[i] >> 6) & 1) == 1 ? "yes" : "no"; + i += 1; + } else { + break; + } + } + + return decoded; +} + +/* +{ + "switch_1": "open|close", + "switch_2": "open|close", + "switch_3": "open|close", + "switch_1_change": "yes|no", + "switch_2_change": "yes|no", + "switch_3_change": "yes|no" +} +*/ diff --git a/vendor/milesight-iot/ws50x.png b/vendor/milesight-iot/ws50x.png new file mode 100644 index 0000000000..edfb5bd9f9 Binary files /dev/null and b/vendor/milesight-iot/ws50x.png differ diff --git a/vendor/milesight-iot/ws50x.yaml b/vendor/milesight-iot/ws50x.yaml new file mode 100644 index 0000000000..6059e1940d --- /dev/null +++ b/vendor/milesight-iot/ws50x.yaml @@ -0,0 +1,87 @@ +name: Milesight WS50x Wall Switch +description: Milesight WS50x is a smart LoRaWAN® wall switch for the local and remote control of lights and electrical appliances. It adopts two standard sizes for most of international wall switch types, which can replace the traditional wall switches directly. Compliant with Milesight LoRaWAN® gateway and Milesight IoT Cloud solution, WS50x can be monitored and controlled via webpage or mobile App remotely and triggered by other Milesight sensors. + +hardwareVersions: + - version: 'V1.x' + numeric: 1 + +firmwareVersions: + - version: '1.x' + numeric: 1 + hardwareVersions: + - 'V1.x' + + profiles: + EU863-870: + id: profile-eu868 + lorawanCertified: true + codec: ws50x-codec + US902-928: + id: profile-us915 + lorawanCertified: true + codec: ws50x-codec + AU915-928: + id: profile-au915 + lorawanCertified: true + codec: ws50x-codec + AS923: + id: profile-as923 + lorawanCertified: true + codec: ws50x-codec + CN470-510: + id: profile-cn470 + lorawanCertified: true + codec: ws50x-codec + KR920-923: + id: profile-kr920 + lorawanCertified: true + codec: ws50x-codec + IN865-867: + id: profile-in865 + lorawanCertified: true + codec: ws50x-codec + RU864-870: + id: profile-ru864 + lorawanCertified: true + codec: ws50x-codec + +#sensors: +# switch_1 +# switch_2 +# switch_3 +# switch_1_change +# switch_2_change +# switch_3_change + +dimensions: + width: 86 + length: 40 + height: 86 + +operatingConditions: + temperature: + min: -20 + max: 60 + + relativeHumidity: + min: 0 + max: 0.95 + +ipCode: IP30 + +keyProvisioning: + - custom + - join server +keySecurity: none +productURL: https://www.milesight-iot.com/lorawan/switch/ws50x/?utm_source=platform&utm_medium=web&utm_campaign=milesight +dataSheetURL: https://resource.milesight-iot.com/milesight/document/ws50x-datasheet-en.pdf +resellerURLs: + - name: 'iot.sales@milesight.com' + region: + - United States + - European Union + - Canada + url: https://www.alibaba.com/product-detail/WS50X-Milesight-IoT-Smart-Wall-Switch_62245253567.html?spm=a2700.shop_plser.41413.12.72b2826fcNleAh + +photos: + main: ws50x.png diff --git a/vendor/milesight-iot/ws52x-codec.yaml b/vendor/milesight-iot/ws52x-codec.yaml new file mode 100644 index 0000000000..ada1ad2d0a --- /dev/null +++ b/vendor/milesight-iot/ws52x-codec.yaml @@ -0,0 +1,27 @@ +# Uplink decoder decodes binary data uplink into a JSON object +uplinkDecoder: + fileName: ws52x.js + examples: + - description: Portable Socket (example 1) - Milesight IoT + input: + fPort: 85 + bytes: [0x03, 0x74, 0xED, 0x08] + output: + data: + voltage: 228.5 + + - description: Portable Socket (example 2) - Milesight IoT + input: + fPort: 85 + bytes: [0x06, 0x83, 0x56, 0x04, 0x00, 0x00] + output: + data: + energy: 1110 + + - description: Portable Socket (example 3) - Milesight IoT + input: + fPort: 85 + bytes: [0x08, 0x70, 0x01] + output: + data: + button: open diff --git a/vendor/milesight-iot/ws52x.js b/vendor/milesight-iot/ws52x.js new file mode 100644 index 0000000000..e1f43a4042 --- /dev/null +++ b/vendor/milesight-iot/ws52x.js @@ -0,0 +1,70 @@ +function decodeUplink(input) { + var res = Decoder(input.bytes, input.fPort); + if (res.error) { + return { + errors: [res.error], + }; + } + return { + data: res, + }; +} +/** + * Payload Decoder for The Things Network + * + * Copyright 2021 Milesight IoT + * + * @product WS52x + */ +function Decoder(bytes, port) { + var decoded = {}; + + for (var i = 0; i < bytes.length;) { + var channel_id = bytes[i++]; + var channel_type = bytes[i++]; + + // VOLTAGE + if (channel_id === 0x03 && channel_type === 0x74) { + decoded.voltage = readUInt16LE(bytes.slice(i, i + 2)) / 10; + i += 2; + } + // POWER FACTOR + else if (channel_id === 0x05 && channel_type === 0x81) { + decoded.power = bytes[i]; + i += 1; + } + // ENERGY SUM + else if (channel_id === 0x06 && channel_type == 0x83) { + decoded.energy = readUInt32LE(bytes.slice(i, i + 4)); + i += 4; + } + // CURRENT + else if (channel_id === 0x07 && channel_type == 0xc9) { + decoded.current = readUInt16LE(bytes.slice(i, i + 2)); + i += 2; + } + // STATE + else if (channel_id === 0x08 && channel_type == 0x70) { + decoded.button = bytes[i] == 1 ? "open" : "close"; + i += 1; + } else { + break; + } + } + + return decoded; +} + +/* ****************************************** + * bytes to number + ********************************************/ +function readUInt16LE(bytes) { + var value = (bytes[1] << 8) + bytes[0]; + return value & 0xffff; +} + +function readUInt32LE(bytes) { + var value = + (bytes[3] << 24) + (bytes[2] << 16) + (bytes[1] << 8) + bytes[0]; + return value & 0xffffffff; +} diff --git a/vendor/milesight-iot/ws52x.png b/vendor/milesight-iot/ws52x.png new file mode 100644 index 0000000000..83e8279543 Binary files /dev/null and b/vendor/milesight-iot/ws52x.png differ diff --git a/vendor/milesight-iot/ws52x.yaml b/vendor/milesight-iot/ws52x.yaml new file mode 100644 index 0000000000..4ed5e40a3c --- /dev/null +++ b/vendor/milesight-iot/ws52x.yaml @@ -0,0 +1,86 @@ +name: Milesight WS52x Portable Socket +description: Milesight WS52x is a LoRaWAN® smart portable socket for the monitoring and control of electrical appliances. Adopting most of international socket types, WS52x can be used for turning on or off the electrical devices locally or remotely and measuring power consumption data plugged on it and even sending overcurrent alarms. WS52x can be widely used for wireless control of indoor lights, fans, heaters, machines, etc. + +hardwareVersions: + - version: 'V1.x' + numeric: 1 + +firmwareVersions: + - version: '1.x' + numeric: 1 + hardwareVersions: + - 'V1.x' + + profiles: + EU863-870: + id: profile-eu868 + lorawanCertified: true + codec: ws52x-codec + US902-928: + id: profile-us915 + lorawanCertified: true + codec: ws52x-codec + AU915-928: + id: profile-au915 + lorawanCertified: true + codec: ws52x-codec + AS923: + id: profile-as923 + lorawanCertified: true + codec: ws52x-codec + CN470-510: + id: profile-cn470 + lorawanCertified: true + codec: ws52x-codec + KR920-923: + id: profile-kr920 + lorawanCertified: true + codec: ws52x-codec + IN865-867: + id: profile-in865 + lorawanCertified: true + codec: ws52x-codec + RU864-870: + id: profile-ru864 + lorawanCertified: true + codec: ws52x-codec + +sensors: + - voltage + - button + - current + - energy + - power + +dimensions: + width: 62.3 + length: 34.6 + height: 110 + +operatingConditions: + temperature: + min: -20 + max: 60 + + relativeHumidity: + min: 0.1 + max: 0.9 + +ipCode: IP30 + +keyProvisioning: + - custom + - join server +keySecurity: none +productURL: https://www.milesight-iot.com/lorawan/socket/ws52x/?utm_source=platform&utm_medium=web&utm_campaign=milesight +dataSheetURL: https://resource.milesight-iot.com/milesight/document/ws52x-datasheet-en.pdf +resellerURLs: + - name: 'iot.sales@milesight.com' + region: + - United States + - European Union + - Canada + url: https://www.alibaba.com/product-detail/Milesight-WS52X-LoRaWAN-Portable-Socket-IoT_1600473971778.html?spm=a2700.shop_plser.41413.16.187980325KqcOX + +photos: + main: ws52x.png diff --git a/vendor/milesight-iot/ws558-codec.yaml b/vendor/milesight-iot/ws558-codec.yaml new file mode 100644 index 0000000000..fa48053e11 --- /dev/null +++ b/vendor/milesight-iot/ws558-codec.yaml @@ -0,0 +1,19 @@ +# Uplink decoder decodes binary data uplink into a JSON object +uplinkDecoder: + fileName: ws558.js + examples: + - description: Light Controller (example 1) - Milesight IoT + input: + fPort: 85 + bytes: [0x03, 0x74, 0xB2, 0x08] + output: + data: + voltage: 222.6 + + - description: Light Controller (example 2) - Milesight IoT + input: + fPort: 85 + bytes: [0x06, 0x83, 0x56, 0x04, 0x00, 0x00] + output: + data: + power_consumption: 1110 diff --git a/vendor/milesight-iot/ws558.js b/vendor/milesight-iot/ws558.js new file mode 100644 index 0000000000..fa014fcf62 --- /dev/null +++ b/vendor/milesight-iot/ws558.js @@ -0,0 +1,101 @@ +function decodeUplink(input) { + var res = Decoder(input.bytes, input.fPort); + if (res.error) { + return { + errors: [res.error], + }; + } + return { + data: res, + }; +} + +/** + * Payload Decoder for The Things Network + * + * Copyright 2021 Milesight IoT + * + * @product WS558 + */ +function Decoder(bytes, port) { + var decoded = {}; + + for (var i = 0; i < bytes.length;) { + var channel_id = bytes[i++]; + var channel_type = bytes[i++]; + // VOLTAGE + if (channel_id === 0x03 && channel_type === 0x74) { + decoded.voltage = readUInt16LE(bytes.slice(i, i + 2)) / 10; + i += 2; + } + // ACTIVE POWER + else if (channel_id === 0x04 && channel_type === 0x80) { + decoded.active_power = readUInt32LE(bytes.slice(i, i + 4)); + i += 4; + } + // POWER FACTOR + else if (channel_id === 0x05 && channel_type === 0x81) { + decoded.power_factor = bytes[i]; + i += 1; + } + // POWER CONSUMPTION + else if (channel_id === 0x06 && channel_type === 0x83) { + decoded.power_consumption = readUInt32LE(bytes.slice(i, i + 4)); + i += 4; + } + // TOTAL CURRENT + else if (channel_id === 0x07 && channel_type === 0xC9) { + decoded.total_current = readUInt16LE(bytes.slice(i, i + 2)); + i += 2; + } + // SWITCH STATUS + else if (channel_id === 0x08 && channel_type === 0x31) { + var switchFlags = bytes[i + 1]; + + // output all switch status + for (var idx = 0; idx < 8; idx++) { + var switchTag = "switch_" + (idx + 1); + decoded[switchTag] = (switchFlags >> idx) & 1 === 1 ? "on" : "off"; + } + + i += 2; + } else { + break; + } + } + + return decoded; +} + +/* ****************************************** + * bytes to number + ********************************************/ +function readUInt8LE(bytes) { + return (bytes & 0xFF); +} + +function readInt8LE(bytes) { + var ref = readUInt8LE(bytes); + return (ref > 0x7F) ? ref - 0x100 : ref; +} + +function readUInt16LE(bytes) { + var value = (bytes[1] << 8) + bytes[0]; + return (value & 0xFFFF); +} + +function readInt16LE(bytes) { + var ref = readUInt16LE(bytes); + return (ref > 0x7FFF) ? ref - 0x10000 : ref; +} + + +function readUInt32LE(bytes) { + var value = (bytes[3] << 24) + (bytes[2] << 16) + (bytes[1] << 8) + bytes[0]; + return (value & 0xFFFFFFFF); +} + +function readInt32LE(bytes) { + var ref = readUInt32LE(bytes); + return (ref > 0x7FFFFFFF) ? ref - 0x100000000 : ref; +} \ No newline at end of file diff --git a/vendor/milesight-iot/ws558.png b/vendor/milesight-iot/ws558.png new file mode 100644 index 0000000000..80f412c1f8 Binary files /dev/null and b/vendor/milesight-iot/ws558.png differ diff --git a/vendor/milesight-iot/ws558.yaml b/vendor/milesight-iot/ws558.yaml new file mode 100644 index 0000000000..69f9bd10c0 --- /dev/null +++ b/vendor/milesight-iot/ws558.yaml @@ -0,0 +1,87 @@ +name: Milesight WS558 Smart Light Controller +description: WS558 is a LoRaWAN® Smart Light Controller for monitoring and controlling lights locally or remotely. With 2 circuit types and 8 switches, it fits different rooms without the need of re-wiring,reducing the renovation costs. Compliant with Milesight LoRaWAN® gateway and Milesight IoT Cloud solution, WS558 can be monitored and controlled via webpage or mobile App remotely and triggered by other Milesight sensors. Besides, WS558 supports Milesight D2D communication protocol, which can set up connection quickly and be controlled without gateway. WS558 can be widely used for wireless control of indoor lights, fans, heaters, machines, etc. + +hardwareVersions: + - version: 'V1.x' + numeric: 1 + +firmwareVersions: + - version: '1.x' + numeric: 1 + hardwareVersions: + - 'V1.x' + + profiles: + EU863-870: + id: profile-eu868 + lorawanCertified: true + codec: ws558-codec + US902-928: + id: profile-us915 + lorawanCertified: true + codec: ws558-codec + AU915-928: + id: profile-au915 + lorawanCertified: true + codec: ws558-codec + AS923: + id: profile-as923 + lorawanCertified: true + codec: ws558-codec + CN470-510: + id: profile-cn470 + lorawanCertified: true + codec: ws558-codec + KR920-923: + id: profile-kr920 + lorawanCertified: true + codec: ws558-codec + IN865-867: + id: profile-in865 + lorawanCertified: true + codec: ws558-codec + RU864-870: + id: profile-ru864 + lorawanCertified: true + codec: ws558-codec + +sensors: + - voltage + - power + # power_factor + # power_consumption + - current + # switch + +dimensions: + width: 145 + length: 90 + height: 40 + +operatingConditions: + temperature: + min: -20 + max: 60 + + relativeHumidity: + min: 0 + max: 0.95 + +ipCode: IP30 + +keyProvisioning: + - custom + - join server +keySecurity: none +productURL: https://www.milesight-iot.com/lorawan/light-controller/ws558/ +dataSheetURL: https://resource.milesight-iot.com/milesight/document/ws558-datasheet-en.pdf +resellerURLs: + - name: 'iot.sales@milesight.com' + region: + - United States + - European Union + - Canada + url: https://www.alibaba.com/product-detail/WS558-Smart-Light-Controller-for-Smart_1600618429042.html?spm=a2700.galleryofferlist.normal_offer.d_title.fe2d260adByt5w + +photos: + main: ws558.png diff --git a/vendor/milesight-iot/wts305-codec.yaml b/vendor/milesight-iot/wts305-codec.yaml new file mode 100644 index 0000000000..14f6ed49f9 --- /dev/null +++ b/vendor/milesight-iot/wts305-codec.yaml @@ -0,0 +1,18 @@ +# Uplink decoder decodes binary data uplink into a JSON object (optional) +# For documentation on writing encoders and decoders, see: https://thethingsstack.io/integrations/payload-formatters/javascript/ +uplinkDecoder: + fileName: wts305.js + examples: + - description: Weather Station - Milesight IoT + input: + fPort: 85 + bytes: [0x01, 0x75, 0x64, 0x03, 0x67, 0x10, 0x01, 0x04, 0x68, 0x71, 0x05, 0x84, 0x00, 0x01, 0x06, 0x73, 0xaa, 0x27, 0x07, 0x92, 0x92, 0x01] + + output: + data: + battery: 100 + humidity: 56.5 + pressure: 1015.4 + temperature: 27.2 + wind_direction: 25.6 + wind_speed: 40.2 diff --git a/vendor/milesight-iot/wts305.js b/vendor/milesight-iot/wts305.js new file mode 100644 index 0000000000..b1a1a5d402 --- /dev/null +++ b/vendor/milesight-iot/wts305.js @@ -0,0 +1,88 @@ +function decodeUplink(input) { + var res = Decoder(input.bytes, input.fPort); + if (res.error) { + return { + errors: [res.error], + }; + } + return { + data: res, + }; +} +/** + * Payload Decoder for The Things Network + * + * Copyright 2023 Milesight IoT + * + * @product WTS305 / WTS506 + */ +function Decoder(bytes, port) { + return milesight(bytes); +} + +function milesight(bytes) { + var decoded = {}; + + for (var i = 0; i < bytes.length; ) { + var channel_id = bytes[i++]; + var channel_type = bytes[i++]; + // BATTERY + if (channel_id === 0x01 && channel_type === 0x75) { + decoded.battery = bytes[i]; + i += 1; + } + // TEMPERATURE + else if (channel_id === 0x03 && channel_type === 0x67) { + // ℃ + decoded.temperature = readInt16LE(bytes.slice(i, i + 2)) / 10; + i += 2; + + // ℉ + // decoded.temperature = readInt16LE(bytes.slice(i, i + 2)) / 10 * 1.8 + 32; + // i +=2; + } + // HUMIDITY + else if (channel_id === 0x04 && channel_type === 0x68) { + decoded.humidity = bytes[i] / 2; + i += 1; + } + // Wind Direction, unit degree + else if (channel_id === 0x05 && channel_type === 0x84) { + decoded.wind_direction = readInt16LE(bytes.slice(i, i + 2)) / 10; + i += 2; + } + // Barometric Pressure, unit hPa + else if (channel_id === 0x06 && channel_type === 0x73) { + decoded.pressure = readUInt16LE(bytes.slice(i, i + 2)) / 10; + i += 2; + } + // Wind Speed, unit m/s + else if (channel_id === 0x07 && channel_type === 0x92) { + decoded.wind_speed = readUInt16LE(bytes.slice(i, i + 2)) / 10; + i += 2; + } + // rainfall_total, unit mm, Frame counter to define whether device enters the new rainfall accumulation phase, it will plus 1 every upload, range: 0~255 + else if (channel_id === 0x08 && channel_type === 0x77) { + decoded.rainfall_total = readUInt16LE(bytes.slice(i, i + 2)) / 100; + decoded.rainfall_counter = bytes[i + 2]; + i += 3; + } else { + break; + } + } + + return decoded; +} + +/* ****************************************** + * bytes to number + ********************************************/ +function readUInt16LE(bytes) { + var value = (bytes[1] << 8) + bytes[0]; + return value & 0xffff; +} + +function readInt16LE(bytes) { + var ref = readUInt16LE(bytes); + return ref > 0x7fff ? ref - 0x10000 : ref; +} diff --git a/vendor/milesight-iot/wts305.png b/vendor/milesight-iot/wts305.png new file mode 100644 index 0000000000..200d79f6d7 Binary files /dev/null and b/vendor/milesight-iot/wts305.png differ diff --git a/vendor/milesight-iot/wts305.yaml b/vendor/milesight-iot/wts305.yaml new file mode 100644 index 0000000000..f97e96b9a6 --- /dev/null +++ b/vendor/milesight-iot/wts305.yaml @@ -0,0 +1,105 @@ +name: Weather Station +description: WTS Series are an all-in-one LoRaWAN® weather monitoring system for various atmospheric conditions, such as temperature, humidity, wind speed, wind direction, barometric pressure and rainfall + +hardwareVersions: + - version: 'V2.0/V3.0' + numeric: 1 + +firmwareVersions: + - version: '1.0x' + numeric: 1 + hardwareVersions: + - 'V2.0/V3.0' + + profiles: + EU863-870: + id: profile-eu868 + codec: wts305-codec + US902-928: + id: profile-us915 + codec: wts305-codec + AU915-928: + id: profile-au915 + codec: wts305-codec + AS923: + id: profile-as923 + codec: wts305-codec + CN470-510: + id: profile-cn470 + codec: wts305-codec + KR920-923: + id: profile-kr920 + codec: wts305-codec + IN865-867: + id: profile-in865 + codec: wts305-codec + RU864-870: + id: profile-ru864 + codec: wts305-codec + +sensors: + - battery + - temperature + - humidity + - wind direction + - wind speed + - pressure + +# 4-20 ma, accelerometer, altitude, analog input, auxiliary, barometer, battery, button, bvoc, co, co2, conductivity, +# current, digital input, dissolved oxygen, distance, dust, energy, gps, gyroscope, h2s, humidity, iaq, level, light, +# lightning, link, magnetometer, moisture, motion, no, no2, o3, particulate matter, ph, pir, pm2.5, pm10, potentiometer, +# power, precipitation, pressure, proximity, pulse count, pulse frequency, radar, rainfall, rssi, smart valve, snr, so2, +# solar radiation, sound, strain, surface temperature, temperature, tilt, time, tvoc, uv, vapor pressure, velocity, +# vibration, voltage, water potential, water, weight, wifi ssid, wind direction, wind speed. + +dimensions: + width: 50 + length: 140 + height: 248 + +battery: + replaceable: true + type: Solar powered (15 W, 1A) with 2 × 2550 mAh chargeable batteries backup + +operatingConditions: + temperature: + min: -20 + max: 60 + + relativeHumidity: + min: 0 + max: 0.95 + +ipCode: IP67 + +keyProvisioning: + - custom + - join server +keySecurity: none +productURL: https://www.milesight-iot.com/lorawan/wts305-wts50x/ +dataSheetURL: https://resource.milesight-iot.com/milesight/document/wts-series-datasheet-en.pdf +resellerURLs: + - name: 'iot.sales@milesight.com' + region: + - United States + - European Union + - Canada + url: https://www.milesight-iot.com/contact-us/ + +photos: + main: wts305.png + +compliances: + safety: + - body: IEC + norm: EN + standard: 62368-1 + radioEquipment: + - body: ETSI + norm: EN + standard: 301 489-1 + version: 2.2.0 + - body: ETSI + norm: EN + standard: 301 489-3 + version: 2.1.0 diff --git a/vendor/milesight-iot/wts505-codec.yaml b/vendor/milesight-iot/wts505-codec.yaml new file mode 100644 index 0000000000..2caa3841de --- /dev/null +++ b/vendor/milesight-iot/wts505-codec.yaml @@ -0,0 +1,18 @@ +# Uplink decoder decodes binary data uplink into a JSON object (optional) +# For documentation on writing encoders and decoders, see: https://thethingsstack.io/integrations/payload-formatters/javascript/ +uplinkDecoder: + fileName: wts505.js + examples: + - description: Weather Station - Milesight IoT + input: + fPort: 85 + bytes: [0x01, 0x75, 0x64, 0x03, 0x67, 0x10, 0x01, 0x04, 0x68, 0x71, 0x05, 0x84, 0x00, 0x01, 0x06, 0x73, 0xaa, 0x27, 0x07, 0x92, 0x92, 0x01] + + output: + data: + battery: 100 + humidity: 56.5 + pressure: 1015.4 + temperature: 27.2 + wind_direction: 25.6 + wind_speed: 40.2 diff --git a/vendor/milesight-iot/wts505.js b/vendor/milesight-iot/wts505.js new file mode 100644 index 0000000000..b1a1a5d402 --- /dev/null +++ b/vendor/milesight-iot/wts505.js @@ -0,0 +1,88 @@ +function decodeUplink(input) { + var res = Decoder(input.bytes, input.fPort); + if (res.error) { + return { + errors: [res.error], + }; + } + return { + data: res, + }; +} +/** + * Payload Decoder for The Things Network + * + * Copyright 2023 Milesight IoT + * + * @product WTS305 / WTS506 + */ +function Decoder(bytes, port) { + return milesight(bytes); +} + +function milesight(bytes) { + var decoded = {}; + + for (var i = 0; i < bytes.length; ) { + var channel_id = bytes[i++]; + var channel_type = bytes[i++]; + // BATTERY + if (channel_id === 0x01 && channel_type === 0x75) { + decoded.battery = bytes[i]; + i += 1; + } + // TEMPERATURE + else if (channel_id === 0x03 && channel_type === 0x67) { + // ℃ + decoded.temperature = readInt16LE(bytes.slice(i, i + 2)) / 10; + i += 2; + + // ℉ + // decoded.temperature = readInt16LE(bytes.slice(i, i + 2)) / 10 * 1.8 + 32; + // i +=2; + } + // HUMIDITY + else if (channel_id === 0x04 && channel_type === 0x68) { + decoded.humidity = bytes[i] / 2; + i += 1; + } + // Wind Direction, unit degree + else if (channel_id === 0x05 && channel_type === 0x84) { + decoded.wind_direction = readInt16LE(bytes.slice(i, i + 2)) / 10; + i += 2; + } + // Barometric Pressure, unit hPa + else if (channel_id === 0x06 && channel_type === 0x73) { + decoded.pressure = readUInt16LE(bytes.slice(i, i + 2)) / 10; + i += 2; + } + // Wind Speed, unit m/s + else if (channel_id === 0x07 && channel_type === 0x92) { + decoded.wind_speed = readUInt16LE(bytes.slice(i, i + 2)) / 10; + i += 2; + } + // rainfall_total, unit mm, Frame counter to define whether device enters the new rainfall accumulation phase, it will plus 1 every upload, range: 0~255 + else if (channel_id === 0x08 && channel_type === 0x77) { + decoded.rainfall_total = readUInt16LE(bytes.slice(i, i + 2)) / 100; + decoded.rainfall_counter = bytes[i + 2]; + i += 3; + } else { + break; + } + } + + return decoded; +} + +/* ****************************************** + * bytes to number + ********************************************/ +function readUInt16LE(bytes) { + var value = (bytes[1] << 8) + bytes[0]; + return value & 0xffff; +} + +function readInt16LE(bytes) { + var ref = readUInt16LE(bytes); + return ref > 0x7fff ? ref - 0x10000 : ref; +} diff --git a/vendor/milesight-iot/wts505.png b/vendor/milesight-iot/wts505.png new file mode 100644 index 0000000000..133353018c Binary files /dev/null and b/vendor/milesight-iot/wts505.png differ diff --git a/vendor/milesight-iot/wts505.yaml b/vendor/milesight-iot/wts505.yaml new file mode 100644 index 0000000000..28580882c6 --- /dev/null +++ b/vendor/milesight-iot/wts505.yaml @@ -0,0 +1,105 @@ +name: Weather Station +description: WTS Series are an all-in-one LoRaWAN® weather monitoring system for various atmospheric conditions, such as temperature, humidity, wind speed, wind direction, barometric pressure and rainfall + +hardwareVersions: + - version: 'V2.0/V3.0' + numeric: 1 + +firmwareVersions: + - version: '1.0x' + numeric: 1 + hardwareVersions: + - 'V2.0/V3.0' + + profiles: + EU863-870: + id: profile-eu868 + codec: wts505-codec + US902-928: + id: profile-us915 + codec: wts505-codec + AU915-928: + id: profile-au915 + codec: wts505-codec + AS923: + id: profile-as923 + codec: wts505-codec + CN470-510: + id: profile-cn470 + codec: wts505-codec + KR920-923: + id: profile-kr920 + codec: wts505-codec + IN865-867: + id: profile-in865 + codec: wts505-codec + RU864-870: + id: profile-ru864 + codec: wts505-codec + +sensors: + - battery + - temperature + - humidity + - wind direction + - wind speed + - pressure + +# 4-20 ma, accelerometer, altitude, analog input, auxiliary, barometer, battery, button, bvoc, co, co2, conductivity, +# current, digital input, dissolved oxygen, distance, dust, energy, gps, gyroscope, h2s, humidity, iaq, level, light, +# lightning, link, magnetometer, moisture, motion, no, no2, o3, particulate matter, ph, pir, pm2.5, pm10, potentiometer, +# power, precipitation, pressure, proximity, pulse count, pulse frequency, radar, rainfall, rssi, smart valve, snr, so2, +# solar radiation, sound, strain, surface temperature, temperature, tilt, time, tvoc, uv, vapor pressure, velocity, +# vibration, voltage, water potential, water, weight, wifi ssid, wind direction, wind speed. + +dimensions: + width: 50 + length: 140 + height: 248 + +battery: + replaceable: true + type: Solar powered (15 W, 1A) with 2 × 2550 mAh chargeable batteries backup + +operatingConditions: + temperature: + min: -20 + max: 60 + + relativeHumidity: + min: 0 + max: 0.95 + +ipCode: IP67 + +keyProvisioning: + - custom + - join server +keySecurity: none +productURL: https://www.milesight-iot.com/lorawan/wts305-wts50x/ +dataSheetURL: https://resource.milesight-iot.com/milesight/document/wts-series-datasheet-en.pdf +resellerURLs: + - name: 'iot.sales@milesight.com' + region: + - United States + - European Union + - Canada + url: https://www.milesight-iot.com/contact-us/ + +photos: + main: wts505.png + +compliances: + safety: + - body: IEC + norm: EN + standard: 62368-1 + radioEquipment: + - body: ETSI + norm: EN + standard: 301 489-1 + version: 2.2.0 + - body: ETSI + norm: EN + standard: 301 489-3 + version: 2.1.0 diff --git a/vendor/milesight-iot/wts506-codec.yaml b/vendor/milesight-iot/wts506-codec.yaml new file mode 100644 index 0000000000..242d096159 --- /dev/null +++ b/vendor/milesight-iot/wts506-codec.yaml @@ -0,0 +1,20 @@ +# Uplink decoder decodes binary data uplink into a JSON object (optional) +# For documentation on writing encoders and decoders, see: https://thethingsstack.io/integrations/payload-formatters/javascript/ +uplinkDecoder: + fileName: wts506.js + examples: + - description: Weather Station - Milesight IoT + input: + fPort: 85 + bytes: [0x01, 0x75, 0x64, 0x03, 0x67, 0x10, 0x01, 0x04, 0x68, 0x71, 0x05, 0x84, 0x00, 0x01, 0x06, 0x73, 0xaa, 0x27, 0x07, 0x92, 0x92, 0x01, 0x08, 0x77, 0xc4, 0x13, 0x25] + + output: + data: + battery: 100 + humidity: 56.5 + pressure: 1015.4 + temperature: 27.2 + wind_direction: 25.6 + wind_speed: 40.2 + rainfall_counter: 37 + rainfall_total: 50.6 diff --git a/vendor/milesight-iot/wts506.js b/vendor/milesight-iot/wts506.js new file mode 100644 index 0000000000..b1a1a5d402 --- /dev/null +++ b/vendor/milesight-iot/wts506.js @@ -0,0 +1,88 @@ +function decodeUplink(input) { + var res = Decoder(input.bytes, input.fPort); + if (res.error) { + return { + errors: [res.error], + }; + } + return { + data: res, + }; +} +/** + * Payload Decoder for The Things Network + * + * Copyright 2023 Milesight IoT + * + * @product WTS305 / WTS506 + */ +function Decoder(bytes, port) { + return milesight(bytes); +} + +function milesight(bytes) { + var decoded = {}; + + for (var i = 0; i < bytes.length; ) { + var channel_id = bytes[i++]; + var channel_type = bytes[i++]; + // BATTERY + if (channel_id === 0x01 && channel_type === 0x75) { + decoded.battery = bytes[i]; + i += 1; + } + // TEMPERATURE + else if (channel_id === 0x03 && channel_type === 0x67) { + // ℃ + decoded.temperature = readInt16LE(bytes.slice(i, i + 2)) / 10; + i += 2; + + // ℉ + // decoded.temperature = readInt16LE(bytes.slice(i, i + 2)) / 10 * 1.8 + 32; + // i +=2; + } + // HUMIDITY + else if (channel_id === 0x04 && channel_type === 0x68) { + decoded.humidity = bytes[i] / 2; + i += 1; + } + // Wind Direction, unit degree + else if (channel_id === 0x05 && channel_type === 0x84) { + decoded.wind_direction = readInt16LE(bytes.slice(i, i + 2)) / 10; + i += 2; + } + // Barometric Pressure, unit hPa + else if (channel_id === 0x06 && channel_type === 0x73) { + decoded.pressure = readUInt16LE(bytes.slice(i, i + 2)) / 10; + i += 2; + } + // Wind Speed, unit m/s + else if (channel_id === 0x07 && channel_type === 0x92) { + decoded.wind_speed = readUInt16LE(bytes.slice(i, i + 2)) / 10; + i += 2; + } + // rainfall_total, unit mm, Frame counter to define whether device enters the new rainfall accumulation phase, it will plus 1 every upload, range: 0~255 + else if (channel_id === 0x08 && channel_type === 0x77) { + decoded.rainfall_total = readUInt16LE(bytes.slice(i, i + 2)) / 100; + decoded.rainfall_counter = bytes[i + 2]; + i += 3; + } else { + break; + } + } + + return decoded; +} + +/* ****************************************** + * bytes to number + ********************************************/ +function readUInt16LE(bytes) { + var value = (bytes[1] << 8) + bytes[0]; + return value & 0xffff; +} + +function readInt16LE(bytes) { + var ref = readUInt16LE(bytes); + return ref > 0x7fff ? ref - 0x10000 : ref; +} diff --git a/vendor/milesight-iot/wts506.png b/vendor/milesight-iot/wts506.png new file mode 100644 index 0000000000..133353018c Binary files /dev/null and b/vendor/milesight-iot/wts506.png differ diff --git a/vendor/milesight-iot/wts506.yaml b/vendor/milesight-iot/wts506.yaml new file mode 100644 index 0000000000..a03c97f57b --- /dev/null +++ b/vendor/milesight-iot/wts506.yaml @@ -0,0 +1,106 @@ +name: Weather Station +description: WTS Series are an all-in-one LoRaWAN® weather monitoring system for various atmospheric conditions, such as temperature, humidity, wind speed, wind direction, barometric pressure and rainfall + +hardwareVersions: + - version: 'V2.0/V3.0' + numeric: 1 + +firmwareVersions: + - version: '1.0x' + numeric: 1 + hardwareVersions: + - 'V2.0/V3.0' + + profiles: + EU863-870: + id: profile-eu868 + codec: wts506-codec + US902-928: + id: profile-us915 + codec: wts506-codec + AU915-928: + id: profile-au915 + codec: wts506-codec + AS923: + id: profile-as923 + codec: wts506-codec + CN470-510: + id: profile-cn470 + codec: wts506-codec + KR920-923: + id: profile-kr920 + codec: wts506-codec + IN865-867: + id: profile-in865 + codec: wts506-codec + RU864-870: + id: profile-ru864 + codec: wts506-codec + +sensors: + - battery + - temperature + - humidity + - wind direction + - wind speed + - pressure + - rainfall + +# 4-20 ma, accelerometer, altitude, analog input, auxiliary, barometer, battery, button, bvoc, co, co2, conductivity, +# current, digital input, dissolved oxygen, distance, dust, energy, gps, gyroscope, h2s, humidity, iaq, level, light, +# lightning, link, magnetometer, moisture, motion, no, no2, o3, particulate matter, ph, pir, pm2.5, pm10, potentiometer, +# power, precipitation, pressure, proximity, pulse count, pulse frequency, radar, rainfall, rssi, smart valve, snr, so2, +# solar radiation, sound, strain, surface temperature, temperature, tilt, time, tvoc, uv, vapor pressure, velocity, +# vibration, voltage, water potential, water, weight, wifi ssid, wind direction, wind speed. + +dimensions: + width: 50 + length: 140 + height: 248 + +battery: + replaceable: true + type: Solar powered (15 W, 1A) with 2 × 2550 mAh chargeable batteries backup + +operatingConditions: + temperature: + min: -20 + max: 60 + + relativeHumidity: + min: 0 + max: 0.95 + +ipCode: IP67 + +keyProvisioning: + - custom + - join server +keySecurity: none +productURL: https://www.milesight-iot.com/lorawan/wts305-wts50x/ +dataSheetURL: https://resource.milesight-iot.com/milesight/document/wts-series-datasheet-en.pdf +resellerURLs: + - name: 'iot.sales@milesight.com' + region: + - United States + - European Union + - Canada + url: https://www.milesight-iot.com/contact-us/ + +photos: + main: wts506.png + +compliances: + safety: + - body: IEC + norm: EN + standard: 62368-1 + radioEquipment: + - body: ETSI + norm: EN + standard: 301 489-1 + version: 2.2.0 + - body: ETSI + norm: EN + standard: 301 489-3 + version: 2.1.0