qaggaz
Logger: homeassistant.setup Source: setup.py:278 First occurred: 11:37:21 PM (1 occurrence) Last logged: 11:37:21 PM Setup failed for custom integration 'chirp': Requirements for chirp not found: ['dukpy==0.5.0'].
#10 · closed · 7 comments
Logger: homeassistant.setup Source: setup.py:278 First occurred: 11:37:21 PM (1 occurrence) Last logged: 11:37:21 PM Setup failed for custom integration 'chirp': Requirements for chirp not found: ['dukpy==0.5.0'].
Logger: homeassistant.util.package Source: util/package.py:187 First occurred: 11:37:16 PM (3 occurrences) Last logged: 11:37:21 PM Unable to install package dukpy==0.5.0: × Failed to build `dukpy==0.5.0` ├─▶ The build backend returned an error ╰─▶ Call to `setuptools.build_meta:__legacy__.build_wheel` failed (exit status: 1) [stdout] running bdist_wheel running build running build_py creating build/lib.linux-x86_64-cpython-314/dukpy copying dukpy/tsc.py -> build/lib.linux-x86_64-cpython-314/dukpy copying dukpy/run.py -> build/lib.linux-x86_64-cpython-314/dukpy copying dukpy/nodelike.py -> build/lib.linux-x86_64-cpython-314/dukpy copying dukpy/module_loader.py -> build/lib.linux-x86_64-cpython-314/dukpy copying dukpy/lessc.py -> build/lib.linux-x86_64-cpython-314/dukpy copying dukpy/install.py -> build/lib.linux-x86_64-cpython-314/dukpy copying dukpy/evaljs.py -> build/lib.linux-x86_64-cpython-314/dukpy copying dukpy/coffee.py -> build/lib.linux-x86_64-cpython-314/dukpy copying dukpy/babel.py -> build/lib.linux-x86_64-cpython-314/dukpy copying dukpy/__init__.py -> build/lib.linux-x86_64-cpython-314/dukpy creating build/lib.linux-x86_64-cpython-314/dukpy/webassets copying dukpy/webassets/typescriptfilter.py -> build/lib.linux-x86_64-cpython-314/dukpy/webassets copying dukpy/webassets/lessfilter.py -> build/lib.linux-x86_64-cpython-314/dukpy/webassets copying dukpy/webassets/jsxfilter.py -> build/lib.linux-x86_64-cpython-314/dukpy/webassets copying dukpy/webassets/babelfilter.py -> build/lib.linux-x86_64-cpython-314/dukpy/webassets copying dukpy/webassets/__init__.py -> build/lib.linux-x86_64-cpython-314/dukpy/webassets creating build/lib.linux-x86_64-cpython-314/dukpy/jscore copying dukpy/jscore/url.js -> build/lib.linux-x86_64-cpython-314/dukpy/jscore copying dukpy/jscore/querystring.js -> build/lib.linux-x86_64-cpython-314/dukpy/jscore copying dukpy/jscore/punycode.js -> build/lib.linux-x86_64-cpython-314/dukpy/jscore copying dukpy/jscore/path.js -> build/lib.linux-x86_64-cpython-314/dukpy/jscore copying dukpy/jscore/fs.js -> build/lib.linux-x86_64-cpython-314/dukpy/jscore creating build/lib.linux-x86_64-cpython-314/dukpy/jsmodules copying dukpy/jsmodules/typescriptServices.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules copying dukpy/jsmodules/semver.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules copying dukpy/jsmodules/coffeescript.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules copying dukpy/jsmodules/babel-6.26.0.min.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules creating build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/react copying dukpy/jsmodules/react/react.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/react copying dukpy/jsmodules/react/react-dom-server.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/react creating build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less-node copying dukpy/jsmodules/less/less-node/url-file-manager.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less-node copying dukpy/jsmodules/less/less-node/plugin-loader.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less-node copying dukpy/jsmodules/less/less-node/lessc-helper.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less-node copying dukpy/jsmodules/less/less-node/index.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less-node copying dukpy/jsmodules/less/less-node/image-size.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less-node copying dukpy/jsmodules/less/less-node/fs.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less-node copying dukpy/jsmodules/less/less-node/file-manager.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less-node copying dukpy/jsmodules/less/less-node/environment.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less-node creating build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less copying dukpy/jsmodules/less/less/utils.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less copying dukpy/jsmodules/less/less/transform-tree.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less copying dukpy/jsmodules/less/less/source-map-output.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less copying dukpy/jsmodules/less/less/source-map-builder.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less copying dukpy/jsmodules/less/less/render.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less copying dukpy/jsmodules/less/less/plugin-manager.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less copying dukpy/jsmodules/less/less/parse.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less copying dukpy/jsmodules/less/less/parse-tree.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less copying dukpy/jsmodules/less/less/logger.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less copying dukpy/jsmodules/less/less/less-error.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less copying dukpy/jsmodules/less/less/index.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less copying dukpy/jsmodules/less/less/import-manager.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less copying dukpy/jsmodules/less/less/contexts.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less creating build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/visitors copying dukpy/jsmodules/less/less/visitors/visitor.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/visitors copying dukpy/jsmodules/less/less/visitors/to-css-visitor.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/visitors copying dukpy/jsmodules/less/less/visitors/set-tree-visibility-visitor.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/visitors copying dukpy/jsmodules/less/less/visitors/join-selector-visitor.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/visitors copying dukpy/jsmodules/less/less/visitors/index.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/visitors copying dukpy/jsmodules/less/less/visitors/import-visitor.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/visitors copying dukpy/jsmodules/less/less/visitors/import-sequencer.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/visitors copying dukpy/jsmodules/less/less/visitors/extend-visitor.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/visitors creating build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/tree copying dukpy/jsmodules/less/less/tree/variable.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/tree copying dukpy/jsmodules/less/less/tree/value.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/tree copying dukpy/jsmodules/less/less/tree/url.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/tree copying dukpy/jsmodules/less/less/tree/unit.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/tree copying dukpy/jsmodules/less/less/tree/unicode-descriptor.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/tree copying dukpy/jsmodules/less/less/tree/selector.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/tree copying dukpy/jsmodules/less/less/tree/ruleset.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/tree copying dukpy/jsmodules/less/less/tree/ruleset-call.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/tree copying dukpy/jsmodules/less/less/tree/rule.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/tree copying dukpy/jsmodules/less/less/tree/quoted.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/tree copying dukpy/jsmodules/less/less/tree/paren.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/tree copying dukpy/jsmodules/less/less/tree/operation.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/tree copying dukpy/jsmodules/less/less/tree/node.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/tree copying dukpy/jsmodules/less/less/tree/negative.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/tree copying dukpy/jsmodules/less/less/tree/mixin-definition.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/tree copying dukpy/jsmodules/less/less/tree/mixin-call.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/tree copying dukpy/jsmodules/less/less/tree/media.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/tree copying dukpy/jsmodules/less/less/tree/keyword.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/tree copying dukpy/jsmodules/less/less/tree/js-eval-node.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/tree copying dukpy/jsmodules/less/less/tree/javascript.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/tree copying dukpy/jsmodules/less/less/tree/index.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/tree copying dukpy/jsmodules/less/less/tree/import.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/tree copying dukpy/jsmodules/less/less/tree/extend.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/tree copying dukpy/jsmodules/less/less/tree/expression.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/tree copying dukpy/jsmodules/less/less/tree/element.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/tree copying dukpy/jsmodules/less/less/tree/directive.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/tree copying dukpy/jsmodules/less/less/tree/dimension.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/tree copying dukpy/jsmodules/less/less/tree/detached-ruleset.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/tree copying dukpy/jsmodules/less/less/tree/debug-info.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/tree copying dukpy/jsmodules/less/less/tree/condition.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/tree copying dukpy/jsmodules/less/less/tree/comment.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/tree copying dukpy/jsmodules/less/less/tree/combinator.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/tree copying dukpy/jsmodules/less/less/tree/color.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/tree copying dukpy/jsmodules/less/less/tree/call.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/tree copying dukpy/jsmodules/less/less/tree/attribute.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/tree copying dukpy/jsmodules/less/less/tree/assignment.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/tree copying dukpy/jsmodules/less/less/tree/anonymous.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/tree copying dukpy/jsmodules/less/less/tree/alpha.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/tree creating build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/plugins copying dukpy/jsmodules/less/less/plugins/function-importer.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/plugins creating build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/parser copying dukpy/jsmodules/less/less/parser/parser.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/parser copying dukpy/jsmodules/less/less/parser/parser-input.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/parser copying dukpy/jsmodules/less/less/parser/chunker.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/parser creating build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/functions copying dukpy/jsmodules/less/less/functions/types.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/functions copying dukpy/jsmodules/less/less/functions/svg.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/functions copying dukpy/jsmodules/less/less/functions/string.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/functions copying dukpy/jsmodules/less/less/functions/number.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/functions copying dukpy/jsmodules/less/less/functions/math.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/functions copying dukpy/jsmodules/less/less/functions/math-helper.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/functions copying dukpy/jsmodules/less/less/functions/index.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/functions copying dukpy/jsmodules/less/less/functions/function-registry.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/functions copying dukpy/jsmodules/less/less/functions/function-caller.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/functions copying dukpy/jsmodules/less/less/functions/default.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/functions copying dukpy/jsmodules/less/less/functions/data-uri.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/functions copying dukpy/jsmodules/less/less/functions/color.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/functions copying dukpy/jsmodules/less/less/functions/color-blending.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/functions creating build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/environment copying dukpy/jsmodules/less/less/environment/file-manager-api.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/environment copying dukpy/jsmodules/less/less/environment/environment.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/environment copying dukpy/jsmodules/less/less/environment/environment-api.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/environment copying dukpy/jsmodules/less/less/environment/abstract-file-manager.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/environment creating build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/data copying dukpy/jsmodules/less/less/data/unit-conversions.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/data copying dukpy/jsmodules/less/less/data/index.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/data copying dukpy/jsmodules/less/less/data/colors.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/data running build_ext building 'dukpy._dukpy' extension creating build/temp.linux-x86_64-cpython-314/src creating build/temp.linux-x86_64-cpython-314/src/duktape gcc -fno-strict-overflow -Wsign-compare -DNDEBUG -g -O3 -Wall -fno-semantic-interposition -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-free -DTHREAD_STACK_SIZE=0x200000 -fPIC -DDUK_OPT_NONSTD_REGEXP_DOLLAR_ESCAPE=1 -DDUK_OPT_OCTAL_SUPPORT=1 -I./src/duktape -I/tmp/.tmpF8PQFI/builds-v0/.tmp7Rfzaq/include -I/usr/local/include/python3.14 -c src/_support.c -o build/temp.linux-x86_64-cpython-314/src/_support.o [stderr] /tmp/.tmpF8PQFI/builds-v0/.tmp7Rfzaq/lib/python3.14/site-packages/setuptools/dist.py:765: SetuptoolsDeprecationWarning: License classifiers are deprecated. !! ******************************************************************************** Please consider removing the following classifiers in favor of a SPDX license expression: License :: OSI Approved :: MIT License See https://packaging.python.org/en/latest/guides/writing-pyproject-toml/#license for details. ******************************************************************************** !! self._finalize_license_expression() error: command 'gcc' failed: No such file or directory hint: This usually indicates a problem with the package or the build environment. Unable to install package dukpy==0.5.0: × Failed to build `dukpy==0.5.0` ├─▶ The build backend returned an error ╰─▶ Call to `setuptools.build_meta:__legacy__.build_wheel` failed (exit status: 1) [stdout] running bdist_wheel running build running build_py creating build/lib.linux-x86_64-cpython-314/dukpy copying dukpy/tsc.py -> build/lib.linux-x86_64-cpython-314/dukpy copying dukpy/run.py -> build/lib.linux-x86_64-cpython-314/dukpy copying dukpy/nodelike.py -> build/lib.linux-x86_64-cpython-314/dukpy copying dukpy/module_loader.py -> build/lib.linux-x86_64-cpython-314/dukpy copying dukpy/lessc.py -> build/lib.linux-x86_64-cpython-314/dukpy copying dukpy/install.py -> build/lib.linux-x86_64-cpython-314/dukpy copying dukpy/evaljs.py -> build/lib.linux-x86_64-cpython-314/dukpy copying dukpy/coffee.py -> build/lib.linux-x86_64-cpython-314/dukpy copying dukpy/babel.py -> build/lib.linux-x86_64-cpython-314/dukpy copying dukpy/__init__.py -> build/lib.linux-x86_64-cpython-314/dukpy creating build/lib.linux-x86_64-cpython-314/dukpy/webassets copying dukpy/webassets/typescriptfilter.py -> build/lib.linux-x86_64-cpython-314/dukpy/webassets copying dukpy/webassets/lessfilter.py -> build/lib.linux-x86_64-cpython-314/dukpy/webassets copying dukpy/webassets/jsxfilter.py -> build/lib.linux-x86_64-cpython-314/dukpy/webassets copying dukpy/webassets/babelfilter.py -> build/lib.linux-x86_64-cpython-314/dukpy/webassets copying dukpy/webassets/__init__.py -> build/lib.linux-x86_64-cpython-314/dukpy/webassets creating build/lib.linux-x86_64-cpython-314/dukpy/jscore copying dukpy/jscore/url.js -> build/lib.linux-x86_64-cpython-314/dukpy/jscore copying dukpy/jscore/querystring.js -> build/lib.linux-x86_64-cpython-314/dukpy/jscore copying dukpy/jscore/punycode.js -> build/lib.linux-x86_64-cpython-314/dukpy/jscore copying dukpy/jscore/path.js -> build/lib.linux-x86_64-cpython-314/dukpy/jscore copying dukpy/jscore/fs.js -> build/lib.linux-x86_64-cpython-314/dukpy/jscore creating build/lib.linux-x86_64-cpython-314/dukpy/jsmodules copying dukpy/jsmodules/typescriptServices.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules copying dukpy/jsmodules/semver.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules copying dukpy/jsmodules/coffeescript.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules copying dukpy/jsmodules/babel-6.26.0.min.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules creating build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/react copying dukpy/jsmodules/react/react.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/react copying dukpy/jsmodules/react/react-dom-server.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/react creating build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less-node copying dukpy/jsmodules/less/less-node/url-file-manager.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less-node copying dukpy/jsmodules/less/less-node/plugin-loader.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less-node copying dukpy/jsmodules/less/less-node/lessc-helper.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less-node copying dukpy/jsmodules/less/less-node/index.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less-node copying dukpy/jsmodules/less/less-node/image-size.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less-node copying dukpy/jsmodules/less/less-node/fs.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less-node copying dukpy/jsmodules/less/less-node/file-manager.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less-node copying dukpy/jsmodules/less/less-node/environment.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less-node creating build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less copying dukpy/jsmodules/less/less/utils.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less copying dukpy/jsmodules/less/less/transform-tree.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less copying dukpy/jsmodules/less/less/source-map-output.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less copying dukpy/jsmodules/less/less/source-map-builder.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less copying dukpy/jsmodules/less/less/render.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less copying dukpy/jsmodules/less/less/plugin-manager.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less copying dukpy/jsmodules/less/less/parse.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less copying dukpy/jsmodules/less/less/parse-tree.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less copying dukpy/jsmodules/less/less/logger.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less copying dukpy/jsmodules/less/less/less-error.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less copying dukpy/jsmodules/less/less/index.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less copying dukpy/jsmodules/less/less/import-manager.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less copying dukpy/jsmodules/less/less/contexts.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less creating build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/visitors copying dukpy/jsmodules/less/less/visitors/visitor.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/visitors copying dukpy/jsmodules/less/less/visitors/to-css-visitor.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/visitors copying dukpy/jsmodules/less/less/visitors/set-tree-visibility-visitor.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/visitors copying dukpy/jsmodules/less/less/visitors/join-selector-visitor.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/visitors copying dukpy/jsmodules/less/less/visitors/index.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/visitors copying dukpy/jsmodules/less/less/visitors/import-visitor.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/visitors copying dukpy/jsmodules/less/less/visitors/import-sequencer.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/visitors copying dukpy/jsmodules/less/less/visitors/extend-visitor.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/visitors creating build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/tree copying dukpy/jsmodules/less/less/tree/variable.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/tree copying dukpy/jsmodules/less/less/tree/value.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/tree copying dukpy/jsmodules/less/less/tree/url.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/tree copying dukpy/jsmodules/less/less/tree/unit.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/tree copying dukpy/jsmodules/less/less/tree/unicode-descriptor.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/tree copying dukpy/jsmodules/less/less/tree/selector.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/tree copying dukpy/jsmodules/less/less/tree/ruleset.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/tree copying dukpy/jsmodules/less/less/tree/ruleset-call.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/tree copying dukpy/jsmodules/less/less/tree/rule.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/tree copying dukpy/jsmodules/less/less/tree/quoted.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/tree copying dukpy/jsmodules/less/less/tree/paren.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/tree copying dukpy/jsmodules/less/less/tree/operation.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/tree copying dukpy/jsmodules/less/less/tree/node.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/tree copying dukpy/jsmodules/less/less/tree/negative.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/tree copying dukpy/jsmodules/less/less/tree/mixin-definition.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/tree copying dukpy/jsmodules/less/less/tree/mixin-call.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/tree copying dukpy/jsmodules/less/less/tree/media.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/tree copying dukpy/jsmodules/less/less/tree/keyword.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/tree copying dukpy/jsmodules/less/less/tree/js-eval-node.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/tree copying dukpy/jsmodules/less/less/tree/javascript.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/tree copying dukpy/jsmodules/less/less/tree/index.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/tree copying dukpy/jsmodules/less/less/tree/import.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/tree copying dukpy/jsmodules/less/less/tree/extend.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/tree copying dukpy/jsmodules/less/less/tree/expression.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/tree copying dukpy/jsmodules/less/less/tree/element.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/tree copying dukpy/jsmodules/less/less/tree/directive.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/tree copying dukpy/jsmodules/less/less/tree/dimension.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/tree copying dukpy/jsmodules/less/less/tree/detached-ruleset.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/tree copying dukpy/jsmodules/less/less/tree/debug-info.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/tree copying dukpy/jsmodules/less/less/tree/condition.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/tree copying dukpy/jsmodules/less/less/tree/comment.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/tree copying dukpy/jsmodules/less/less/tree/combinator.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/tree copying dukpy/jsmodules/less/less/tree/color.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/tree copying dukpy/jsmodules/less/less/tree/call.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/tree copying dukpy/jsmodules/less/less/tree/attribute.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/tree copying dukpy/jsmodules/less/less/tree/assignment.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/tree copying dukpy/jsmodules/less/less/tree/anonymous.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/tree copying dukpy/jsmodules/less/less/tree/alpha.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/tree creating build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/plugins copying dukpy/jsmodules/less/less/plugins/function-importer.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/plugins creating build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/parser copying dukpy/jsmodules/less/less/parser/parser.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/parser copying dukpy/jsmodules/less/less/parser/parser-input.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/parser copying dukpy/jsmodules/less/less/parser/chunker.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/parser creating build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/functions copying dukpy/jsmodules/less/less/functions/types.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/functions copying dukpy/jsmodules/less/less/functions/svg.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/functions copying dukpy/jsmodules/less/less/functions/string.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/functions copying dukpy/jsmodules/less/less/functions/number.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/functions copying dukpy/jsmodules/less/less/functions/math.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/functions copying dukpy/jsmodules/less/less/functions/math-helper.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/functions copying dukpy/jsmodules/less/less/functions/index.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/functions copying dukpy/jsmodules/less/less/functions/function-registry.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/functions copying dukpy/jsmodules/less/less/functions/function-caller.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/functions copying dukpy/jsmodules/less/less/functions/default.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/functions copying dukpy/jsmodules/less/less/functions/data-uri.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/functions copying dukpy/jsmodules/less/less/functions/color.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/functions copying dukpy/jsmodules/less/less/functions/color-blending.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/functions creating build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/environment copying dukpy/jsmodules/less/less/environment/file-manager-api.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/environment copying dukpy/jsmodules/less/less/environment/environment.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/environment copying dukpy/jsmodules/less/less/environment/environment-api.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/environment copying dukpy/jsmodules/less/less/environment/abstract-file-manager.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/environment creating build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/data copying dukpy/jsmodules/less/less/data/unit-conversions.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/data copying dukpy/jsmodules/less/less/data/index.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/data copying dukpy/jsmodules/less/less/data/colors.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/data running build_ext building 'dukpy._dukpy' extension creating build/temp.linux-x86_64-cpython-314/src creating build/temp.linux-x86_64-cpython-314/src/duktape gcc -fno-strict-overflow -Wsign-compare -DNDEBUG -g -O3 -Wall -fno-semantic-interposition -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-free -DTHREAD_STACK_SIZE=0x200000 -fPIC -DDUK_OPT_NONSTD_REGEXP_DOLLAR_ESCAPE=1 -DDUK_OPT_OCTAL_SUPPORT=1 -I./src/duktape -I/tmp/.tmp8c1JRX/builds-v0/.tmpiP93cA/include -I/usr/local/include/python3.14 -c src/_support.c -o build/temp.linux-x86_64-cpython-314/src/_support.o [stderr] /tmp/.tmp8c1JRX/builds-v0/.tmpiP93cA/lib/python3.14/site-packages/setuptools/dist.py:765: SetuptoolsDeprecationWarning: License classifiers are deprecated. !! ******************************************************************************** Please consider removing the following classifiers in favor of a SPDX license expression: License :: OSI Approved :: MIT License See https://packaging.python.org/en/latest/guides/writing-pyproject-toml/#license for details. ******************************************************************************** !! self._finalize_license_expression() error: command 'gcc' failed: No such file or directory hint: This usually indicates a problem with the package or the build environment. Unable to install package dukpy==0.5.0: × Failed to build `dukpy==0.5.0` ├─▶ The build backend returned an error ╰─▶ Call to `setuptools.build_meta:__legacy__.build_wheel` failed (exit status: 1) [stdout] running bdist_wheel running build running build_py creating build/lib.linux-x86_64-cpython-314/dukpy copying dukpy/tsc.py -> build/lib.linux-x86_64-cpython-314/dukpy copying dukpy/run.py -> build/lib.linux-x86_64-cpython-314/dukpy copying dukpy/nodelike.py -> build/lib.linux-x86_64-cpython-314/dukpy copying dukpy/module_loader.py -> build/lib.linux-x86_64-cpython-314/dukpy copying dukpy/lessc.py -> build/lib.linux-x86_64-cpython-314/dukpy copying dukpy/install.py -> build/lib.linux-x86_64-cpython-314/dukpy copying dukpy/evaljs.py -> build/lib.linux-x86_64-cpython-314/dukpy copying dukpy/coffee.py -> build/lib.linux-x86_64-cpython-314/dukpy copying dukpy/babel.py -> build/lib.linux-x86_64-cpython-314/dukpy copying dukpy/__init__.py -> build/lib.linux-x86_64-cpython-314/dukpy creating build/lib.linux-x86_64-cpython-314/dukpy/webassets copying dukpy/webassets/typescriptfilter.py -> build/lib.linux-x86_64-cpython-314/dukpy/webassets copying dukpy/webassets/lessfilter.py -> build/lib.linux-x86_64-cpython-314/dukpy/webassets copying dukpy/webassets/jsxfilter.py -> build/lib.linux-x86_64-cpython-314/dukpy/webassets copying dukpy/webassets/babelfilter.py -> build/lib.linux-x86_64-cpython-314/dukpy/webassets copying dukpy/webassets/__init__.py -> build/lib.linux-x86_64-cpython-314/dukpy/webassets creating build/lib.linux-x86_64-cpython-314/dukpy/jscore copying dukpy/jscore/url.js -> build/lib.linux-x86_64-cpython-314/dukpy/jscore copying dukpy/jscore/querystring.js -> build/lib.linux-x86_64-cpython-314/dukpy/jscore copying dukpy/jscore/punycode.js -> build/lib.linux-x86_64-cpython-314/dukpy/jscore copying dukpy/jscore/path.js -> build/lib.linux-x86_64-cpython-314/dukpy/jscore copying dukpy/jscore/fs.js -> build/lib.linux-x86_64-cpython-314/dukpy/jscore creating build/lib.linux-x86_64-cpython-314/dukpy/jsmodules copying dukpy/jsmodules/typescriptServices.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules copying dukpy/jsmodules/semver.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules copying dukpy/jsmodules/coffeescript.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules copying dukpy/jsmodules/babel-6.26.0.min.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules creating build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/react copying dukpy/jsmodules/react/react.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/react copying dukpy/jsmodules/react/react-dom-server.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/react creating build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less-node copying dukpy/jsmodules/less/less-node/url-file-manager.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less-node copying dukpy/jsmodules/less/less-node/plugin-loader.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less-node copying dukpy/jsmodules/less/less-node/lessc-helper.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less-node copying dukpy/jsmodules/less/less-node/index.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less-node copying dukpy/jsmodules/less/less-node/image-size.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less-node copying dukpy/jsmodules/less/less-node/fs.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less-node copying dukpy/jsmodules/less/less-node/file-manager.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less-node copying dukpy/jsmodules/less/less-node/environment.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less-node creating build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less copying dukpy/jsmodules/less/less/utils.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less copying dukpy/jsmodules/less/less/transform-tree.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less copying dukpy/jsmodules/less/less/source-map-output.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less copying dukpy/jsmodules/less/less/source-map-builder.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less copying dukpy/jsmodules/less/less/render.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less copying dukpy/jsmodules/less/less/plugin-manager.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less copying dukpy/jsmodules/less/less/parse.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less copying dukpy/jsmodules/less/less/parse-tree.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less copying dukpy/jsmodules/less/less/logger.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less copying dukpy/jsmodules/less/less/less-error.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less copying dukpy/jsmodules/less/less/index.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less copying dukpy/jsmodules/less/less/import-manager.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less copying dukpy/jsmodules/less/less/contexts.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less creating build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/visitors copying dukpy/jsmodules/less/less/visitors/visitor.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/visitors copying dukpy/jsmodules/less/less/visitors/to-css-visitor.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/visitors copying dukpy/jsmodules/less/less/visitors/set-tree-visibility-visitor.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/visitors copying dukpy/jsmodules/less/less/visitors/join-selector-visitor.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/visitors copying dukpy/jsmodules/less/less/visitors/index.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/visitors copying dukpy/jsmodules/less/less/visitors/import-visitor.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/visitors copying dukpy/jsmodules/less/less/visitors/import-sequencer.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/visitors copying dukpy/jsmodules/less/less/visitors/extend-visitor.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/visitors creating build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/tree copying dukpy/jsmodules/less/less/tree/variable.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/tree copying dukpy/jsmodules/less/less/tree/value.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/tree copying dukpy/jsmodules/less/less/tree/url.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/tree copying dukpy/jsmodules/less/less/tree/unit.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/tree copying dukpy/jsmodules/less/less/tree/unicode-descriptor.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/tree copying dukpy/jsmodules/less/less/tree/selector.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/tree copying dukpy/jsmodules/less/less/tree/ruleset.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/tree copying dukpy/jsmodules/less/less/tree/ruleset-call.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/tree copying dukpy/jsmodules/less/less/tree/rule.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/tree copying dukpy/jsmodules/less/less/tree/quoted.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/tree copying dukpy/jsmodules/less/less/tree/paren.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/tree copying dukpy/jsmodules/less/less/tree/operation.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/tree copying dukpy/jsmodules/less/less/tree/node.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/tree copying dukpy/jsmodules/less/less/tree/negative.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/tree copying dukpy/jsmodules/less/less/tree/mixin-definition.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/tree copying dukpy/jsmodules/less/less/tree/mixin-call.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/tree copying dukpy/jsmodules/less/less/tree/media.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/tree copying dukpy/jsmodules/less/less/tree/keyword.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/tree copying dukpy/jsmodules/less/less/tree/js-eval-node.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/tree copying dukpy/jsmodules/less/less/tree/javascript.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/tree copying dukpy/jsmodules/less/less/tree/index.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/tree copying dukpy/jsmodules/less/less/tree/import.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/tree copying dukpy/jsmodules/less/less/tree/extend.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/tree copying dukpy/jsmodules/less/less/tree/expression.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/tree copying dukpy/jsmodules/less/less/tree/element.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/tree copying dukpy/jsmodules/less/less/tree/directive.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/tree copying dukpy/jsmodules/less/less/tree/dimension.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/tree copying dukpy/jsmodules/less/less/tree/detached-ruleset.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/tree copying dukpy/jsmodules/less/less/tree/debug-info.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/tree copying dukpy/jsmodules/less/less/tree/condition.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/tree copying dukpy/jsmodules/less/less/tree/comment.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/tree copying dukpy/jsmodules/less/less/tree/combinator.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/tree copying dukpy/jsmodules/less/less/tree/color.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/tree copying dukpy/jsmodules/less/less/tree/call.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/tree copying dukpy/jsmodules/less/less/tree/attribute.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/tree copying dukpy/jsmodules/less/less/tree/assignment.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/tree copying dukpy/jsmodules/less/less/tree/anonymous.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/tree copying dukpy/jsmodules/less/less/tree/alpha.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/tree creating build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/plugins copying dukpy/jsmodules/less/less/plugins/function-importer.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/plugins creating build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/parser copying dukpy/jsmodules/less/less/parser/parser.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/parser copying dukpy/jsmodules/less/less/parser/parser-input.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/parser copying dukpy/jsmodules/less/less/parser/chunker.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/parser creating build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/functions copying dukpy/jsmodules/less/less/functions/types.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/functions copying dukpy/jsmodules/less/less/functions/svg.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/functions copying dukpy/jsmodules/less/less/functions/string.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/functions copying dukpy/jsmodules/less/less/functions/number.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/functions copying dukpy/jsmodules/less/less/functions/math.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/functions copying dukpy/jsmodules/less/less/functions/math-helper.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/functions copying dukpy/jsmodules/less/less/functions/index.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/functions copying dukpy/jsmodules/less/less/functions/function-registry.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/functions copying dukpy/jsmodules/less/less/functions/function-caller.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/functions copying dukpy/jsmodules/less/less/functions/default.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/functions copying dukpy/jsmodules/less/less/functions/data-uri.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/functions copying dukpy/jsmodules/less/less/functions/color.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/functions copying dukpy/jsmodules/less/less/functions/color-blending.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/functions creating build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/environment copying dukpy/jsmodules/less/less/environment/file-manager-api.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/environment copying dukpy/jsmodules/less/less/environment/environment.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/environment copying dukpy/jsmodules/less/less/environment/environment-api.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/environment copying dukpy/jsmodules/less/less/environment/abstract-file-manager.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/environment creating build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/data copying dukpy/jsmodules/less/less/data/unit-conversions.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/data copying dukpy/jsmodules/less/less/data/index.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/data copying dukpy/jsmodules/less/less/data/colors.js -> build/lib.linux-x86_64-cpython-314/dukpy/jsmodules/less/less/data running build_ext building 'dukpy._dukpy' extension creating build/temp.linux-x86_64-cpython-314/src creating build/temp.linux-x86_64-cpython-314/src/duktape gcc -fno-strict-overflow -Wsign-compare -DNDEBUG -g -O3 -Wall -fno-semantic-interposition -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-free -DTHREAD_STACK_SIZE=0x200000 -fPIC -DDUK_OPT_NONSTD_REGEXP_DOLLAR_ESCAPE=1 -DDUK_OPT_OCTAL_SUPPORT=1 -I./src/duktape -I/tmp/.tmpUVGNoK/builds-v0/.tmptQCx47/include -I/usr/local/include/python3.14 -c src/_support.c -o build/temp.linux-x86_64-cpython-314/src/_support.o [stderr] /tmp/.tmpUVGNoK/builds-v0/.tmptQCx47/lib/python3.14/site-packages/setuptools/dist.py:765: SetuptoolsDeprecationWarning: License classifiers are deprecated. !! ******************************************************************************** Please consider removing the following classifiers in favor of a SPDX license expression: License :: OSI Approved :: MIT License See https://packaging.python.org/en/latest/guides/writing-pyproject-toml/#license for details. ******************************************************************************** !! self._finalize_license_expression() error: command 'gcc' failed: No such file or directory hint: This usually indicates a problem with the package or the build environment.
Fix (dukpy==0.5.0->dukpy==0.5.1) is checked in, will test today
version 1.1.26 looks OK
Looks good to me as well! Thanks for the quick fix. I have some ha autodisovery configs that I can contribute (Milesight EM410-RDL radar level sensor and a Milesight smart button) if you are interested. Closing this issue as it is resolved.
I you could share configuration files it would be great - will add them to container version git repo - there are some files already
Here here are the three that I have been testing: 1) Milesight EM410-RDL Radar Level Sensor 2) Milesight WS101 Smart Button 3) A reworked WS523 smart plug codec, that includes both uplink and downlink functions and exposes an outage binary sensor for dying gasp. 4) A very hacky jinja macro template for home assistant to convert the level (in mm) returned from the EM410-RDL (in tank mode) to volume in gallons for a cylindrical tank mounted horizontally. Note that this requires both the tank height to be configured in the EM410 as well as passed as a parameter to this macro. On Thu, Mar 5, 2026 at 12:09 PM modrisb ***@***.***> wrote: > *modrisb* left a comment (modrisb/chirp#10) > <https://github.com/modrisb/chirp/issues/10#issuecomment-4007805296> > > I you could share configuration files it would be great - will add them to > container version git repo - there are some files already > > — > Reply to this email directly, view it on GitHub > <https://github.com/modrisb/chirp/issues/10#issuecomment-4007805296>, or > unsubscribe > <https://github.com/notifications/unsubscribe-auth/ALE2V3GQHA7BGQKMFGFNYGT4PHUJLAVCNFSM6AAAAACWHXV7P6VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHM2DAMBXHAYDKMRZGY> > . > You are receiving this because you modified the open/close state.Message > ID: ***@***.***> >
Sorry, github stripped the file attachements, so here they are (all four files): ## Milesite EM410-RDL Radar Level Sensor ``` /** * Payload Decoder * * Copyright 2025 Milesight IoT * * @product EM410-RDL */ var RAW_VALUE = 0x00; /* eslint no-redeclare: "off" */ /* eslint-disable */ // Chirpstack v4 function decodeUplink(input) { var decoded = milesightDeviceDecode(input.bytes); return { data: decoded }; } // Chirpstack v3 function Decode(fPort, bytes) { return milesightDeviceDecode(bytes); } // The Things Network function Decoder(bytes, port) { return milesightDeviceDecode(bytes); } /* eslint-enable */ function milesightDeviceDecode(bytes) { var decoded = {}; for (var i = 0; i < bytes.length; ) { var channel_id = bytes[i++]; var channel_type = bytes[i++]; // IPSO VERSION if (channel_id === 0xff && channel_type === 0x01) { decoded.ipso_version = readProtocolVersion(bytes[i]); i += 1; } // HARDWARE VERSION else if (channel_id === 0xff && channel_type === 0x09) { decoded.hardware_version = readHardwareVersion(bytes.slice(i, i + 2)); i += 2; } // FIRMWARE VERSION else if (channel_id === 0xff && channel_type === 0x0a) { decoded.firmware_version = readFirmwareVersion(bytes.slice(i, i + 2)); i += 2; } // TSL VERSION else if (channel_id === 0xff && channel_type === 0xff) { decoded.tsl_version = readTslVersion(bytes.slice(i, i + 2)); i += 2; } // SERIAL NUMBER else if (channel_id === 0xff && channel_type === 0x16) { decoded.sn = readSerialNumber(bytes.slice(i, i + 8)); i += 8; } // LORAWAN CLASS TYPE else if (channel_id === 0xff && channel_type === 0x0f) { decoded.lorawan_class = readLoRaWANClass(bytes[i]); i += 1; } // RESET EVENT else if (channel_id === 0xff && channel_type === 0xfe) { decoded.reset_event = readResetEvent(1); i += 1; } // DEVICE STATUS else if (channel_id === 0xff && channel_type === 0x0b) { decoded.device_status = readOnOffStatus(1); i += 1; } // BATTERY else if (channel_id === 0x01 && channel_type === 0x75) { decoded.battery = readUInt8(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 = readInt16LE(bytes.slice(i, i + 2)); i += 2; } // POSITION else if (channel_id === 0x05 && channel_type === 0x00) { decoded.position = readPositionStatus(bytes[i]); i += 1; } // RADAR SIGNAL STRENGTH else if (channel_id === 0x06 && channel_type === 0xc7) { decoded.radar_signal_rssi = readInt16LE(bytes.slice(i, i + 2)) / 100; i += 2; } // DISTANCE ALARM else if (channel_id === 0x84 && channel_type === 0x82) { var data = {}; data.distance = readInt16LE(bytes.slice(i, i + 2)); data.distance_alarm = readDistanceAlarm(bytes[i + 2]); i += 3; decoded.distance = data.distance; decoded.event = decoded.event || []; decoded.event.push(data); } // DISTANCE MUTATION ALARM else if (channel_id === 0x94 && channel_type === 0x82) { var data = {}; data.distance = readInt16LE(bytes.slice(i, i + 2)); data.distance_mutation = readInt16LE(bytes.slice(i + 2, i + 4)); data.distance_alarm = readDistanceAlarm(bytes[i + 4]); i += 5; decoded.distance = data.distance; decoded.event = decoded.event || []; decoded.event.push(data); } // DISTANCE EXCEPTION ALARM else if (channel_id === 0xb4 && channel_type === 0x82) { var distance_raw_data = readUInt16LE(bytes.slice(i, i + 2)); var distance_value = readInt16LE(bytes.slice(i, i + 2)); var distance_exception = readDistanceException(bytes[i + 2]); i += 3; var data = {}; if (distance_raw_data === 0xfffd || distance_raw_data === 0xffff) { // IGNORE NO TARGET AND SENSOR EXCEPTION } else { data.distance = distance_value; } data.distance_exception = distance_exception; decoded.event = decoded.event || []; decoded.event.push(data); } // HISTORY else if (channel_id === 0x20 && channel_type === 0xce) { var timestamp = readUInt32LE(bytes.slice(i, i + 4)); var distance_raw_data = readUInt16LE(bytes.slice(i + 4, i + 6)); var distance_value = readInt16LE(bytes.slice(i + 4, i + 6)); var temperature_raw_data = readUInt16LE(bytes.slice(i + 6, i + 8)); var temperature_value = readInt16LE(bytes.slice(i + 6, i + 8)) / 10; var mutation = readInt16LE(bytes.slice(i + 8, i + 10)); var event_value = readUInt8(bytes[i + 10]); i += 11; var data = {}; data.timestamp = timestamp; if (distance_raw_data === 0xfffd) { data.distance_sensor_status = "no target"; } else if (distance_raw_data === 0xffff) { data.distance_sensor_status = "sensor exception"; } else if (distance_raw_data === 0xfffe) { data.distance_sensor_status = "disabled"; } else { data.distance = distance_value; } if (temperature_raw_data === 0xfffe) { data.temperature_sensor_status = "disabled"; } else if (temperature_raw_data === 0xffff) { data.temperature_sensor_status = "sensor exception"; } else { data.temperature = temperature_value; } var event = readHistoryEvent(event_value); if (event.length > 0) { data.event = event; } if (event.indexOf("mutation alarm") !== -1) { data.distance_mutation = mutation; } decoded.history = decoded.history || []; decoded.history.push(data); } // DOWNLINK RESPONSE else if (channel_id === 0xfe || channel_id === 0xff) { var result = handle_downlink_response(channel_type, bytes, i); decoded = Object.assign(decoded, result.data); i = result.offset; } // DOWNLINK RESPONSE else if (channel_id === 0xf8 || channel_id === 0xf9) { var result = handle_downlink_response_ext(channel_id, channel_type, bytes, i); decoded = Object.assign(decoded, result.data); i = result.offset; } else { break; } } return decoded; } // 0xFE function handle_downlink_response(channel_type, bytes, offset) { var decoded = {}; switch (channel_type) { case 0x06: var data = readUInt8(bytes[offset]); var min = readInt16LE(bytes.slice(offset + 1, offset + 3)); var max = readInt16LE(bytes.slice(offset + 3, offset + 5)); // skip 4 bytes (reserved) offset += 9; var condition_type = data & 0x07; var id = (data >>> 3) & 0x07; var alarm_release_enable = (data >>> 7) & 0x01; if (id === 1) { decoded.distance_alarm_config = {}; decoded.distance_alarm_config.enable = readEnableStatus(condition_type === 0 ? 0 : 1); decoded.distance_alarm_config.condition = readConditionType(condition_type); decoded.distance_alarm_config.alarm_release_enable = readEnableStatus(alarm_release_enable); decoded.distance_alarm_config.threshold_min = min; decoded.distance_alarm_config.threshold_max = max; } else if (id === 2) { decoded.distance_mutation_alarm_config = {}; decoded.distance_mutation_alarm_config.enable = readEnableStatus(condition_type === 0 ? 0 : 1); decoded.distance_mutation_alarm_config.alarm_release_enable = readEnableStatus(alarm_release_enable); decoded.distance_mutation_alarm_config.mutation = max; } else if (id === 3) { decoded.tank_mode_distance_alarm_config = {}; decoded.tank_mode_distance_alarm_config.enable = readEnableStatus(condition_type === 0 ? 0 : 1); decoded.tank_mode_distance_alarm_config.condition = readConditionType(condition_type); decoded.tank_mode_distance_alarm_config.alarm_release_enable = readEnableStatus(alarm_release_enable); decoded.tank_mode_distance_alarm_config.threshold_min = min; decoded.tank_mode_distance_alarm_config.threshold_max = max; } else if (id === 4) { decoded.tank_mode_distance_mutation_alarm_config = {}; decoded.tank_mode_distance_mutation_alarm_config.enable = readEnableStatus(condition_type === 0 ? 0 : 1); decoded.tank_mode_distance_mutation_alarm_config.alarm_release_enable = readEnableStatus(alarm_release_enable); decoded.tank_mode_distance_mutation_alarm_config.mutation = max; } break; case 0x10: decoded.reboot = readYesNoStatus(1); offset += 1; break; case 0x1b: decoded.distance_range = {}; decoded.distance_range.mode = readDistanceMode(readUInt8(bytes[offset])); // skip 2 bytes (reserved) decoded.distance_range.max = readUInt16LE(bytes.slice(offset + 3, offset + 5)); offset += 5; break; case 0x1c: decoded.recollection_config = {}; decoded.recollection_config.counts = readUInt8(bytes[offset]); decoded.recollection_config.interval = readUInt8(bytes[offset + 1]); offset += 2; break; case 0x27: decoded.clear_history = readYesNoStatus(1); offset += 1; break; case 0x28: decoded.report_status = readYesNoStatus(1); offset += 1; break; case 0x2a: var calibrate_type = readUInt8(bytes[offset]); offset += 1; switch (calibrate_type) { case 0: decoded.radar_calibration = readYesNoStatus(1); break; case 1: decoded.radar_blind_calibration = readYesNoStatus(1); break; } break; case 0x3e: decoded.tilt_distance_link = readEnableStatus(readUInt8(bytes[offset])); offset += 1; break; case 0x4a: decoded.sync_time = readYesNoStatus(1); offset += 1; break; case 0x68: decoded.history_enable = readEnableStatus(readUInt8(bytes[offset])); offset += 1; break; case 0x69: decoded.retransmit_enable = readEnableStatus(readUInt8(bytes[offset])); offset += 1; break; case 0x6a: var interval_type = readUInt8(bytes[offset]); switch (interval_type) { case 0: decoded.retransmit_interval = readUInt16LE(bytes.slice(offset + 1, offset + 3)); break; case 1: decoded.resend_interval = readUInt16LE(bytes.slice(offset + 1, offset + 3)); break; } offset += 3; break; case 0x8e: // ignore the first byte decoded.report_interval = readUInt16LE(bytes.slice(offset + 1, offset + 3)); offset += 3; break; case 0xab: decoded.distance_calibration_settings = {}; decoded.distance_calibration_settings.enable = readEnableStatus(readUInt8(bytes[offset])); decoded.distance_calibration_settings.calibration_value = readInt16LE(bytes.slice(offset + 1, offset + 3)); offset += 3; break; case 0xbd: decoded.time_zone = readTimeZone(readInt16LE(bytes.slice(offset, offset + 2))); offset += 2; break; case 0xf2: decoded.alarm_counts = readUInt16LE(bytes.slice(offset, offset + 2)); offset += 2; break; default: throw new Error("unknown downlink response"); } return { data: decoded, offset: offset }; } // 0xF8 function handle_downlink_response_ext(code, channel_type, bytes, offset) { var decoded = {}; switch (channel_type) { case 0x12: decoded.distance_mode = readDistanceMode(readUInt8(bytes[offset])); offset += 1; break; case 0x13: decoded.blind_detection_enable = readEnableStatus(readUInt8(bytes[offset])); offset += 1; break; case 0x14: decoded.signal_quality = readInt16LE(bytes.slice(offset, offset + 2)); offset += 2; break; case 0x15: decoded.distance_threshold_sensitive = readInt16LE(bytes.slice(offset, offset + 2)) / 10; offset += 2; break; case 0x16: decoded.peak_sorting = readPeakSortingAlgorithm(readUInt8(bytes[offset])); offset += 1; break; case 0x0d: decoded.retransmit_config = {}; decoded.retransmit_config.enable = readEnableStatus(readUInt8(bytes[offset])); decoded.retransmit_config.retransmit_interval = readUInt16LE(bytes.slice(offset + 1, offset + 3)); offset += 3; break; case 0x39: decoded.collection_interval = readUInt16LE(bytes.slice(offset, offset + 2)); offset += 2; break; default: throw new Error("unknown downlink response"); } if (hasResultFlag(code)) { var result_value = readUInt8(bytes[offset]); offset += 1; if (result_value !== 0) { var request = decoded; decoded = {}; decoded.device_response_result = {}; decoded.device_response_result.channel_type = channel_type; decoded.device_response_result.result = readResultStatus(result_value); decoded.device_response_result.request = request; } } return { data: decoded, offset: offset }; } function hasResultFlag(code) { return code === 0xf8; } function readResultStatus(status) { var status_map = { 0: "success", 1: "forbidden", 2: "invalid parameter" }; return getValue(status_map, status); } function readProtocolVersion(bytes) { var major = (bytes & 0xf0) >> 4; var minor = bytes & 0x0f; return "v" + major + "." + minor; } function readHardwareVersion(bytes) { var major = (bytes[0] & 0xff).toString(16); var minor = (bytes[1] & 0xff) >> 4; return "v" + major + "." + minor; } function readFirmwareVersion(bytes) { var major = (bytes[0] & 0xff).toString(16); var minor = (bytes[1] & 0xff).toString(16); return "v" + major + "." + minor; } function readTslVersion(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(""); } function readLoRaWANClass(type) { var class_map = { 0: "Class A", 1: "Class B", 2: "Class C", 3: "Class CtoB", }; return getValue(class_map, type); } function readResetEvent(status) { var status_map = { 0: "normal", 1: "reset" }; return getValue(status_map, status); } function readOnOffStatus(status) { var status_map = { 0: "off", 1: "on" }; return getValue(status_map, status); } function readEnableStatus(status) { var status_map = { 0: "disable", 1: "enable" }; return getValue(status_map, status); } function readYesNoStatus(status) { var status_map = { 0: "no", 1: "yes" }; return getValue(status_map, status); } function readPositionStatus(status) { var status_map = { 0: "normal", 1: "tilt" }; return getValue(status_map, status); } function readDistanceMode(status) { var status_map = { 0: "general", 1: "rainwater", 2: "wastewater", 3: "tank" }; return getValue(status_map, status); } function readPeakSortingAlgorithm(status) { var status_map = { 0: "closest", 1: "strongest" }; return getValue(status_map, status); } function readTimeZone(time_zone) { var timezone_map = { "-720": "UTC-12", "-660": "UTC-11", "-600": "UTC-10", "-570": "UTC-9:30", "-540": "UTC-9", "-480": "UTC-8", "-420": "UTC-7", "-360": "UTC-6", "-300": "UTC-5", "-240": "UTC-4", "-210": "UTC-3:30", "-180": "UTC-3", "-120": "UTC-2", "-60": "UTC-1", 0: "UTC", 60: "UTC+1", 120: "UTC+2", 180: "UTC+3", 210: "UTC+3:30", 240: "UTC+4", 270: "UTC+4:30", 300: "UTC+5", 330: "UTC+5:30", 345: "UTC+5:45", 360: "UTC+6", 390: "UTC+6:30", 420: "UTC+7", 480: "UTC+8", 540: "UTC+9", 570: "UTC+9:30", 600: "UTC+10", 630: "UTC+10:30", 660: "UTC+11", 720: "UTC+12", 765: "UTC+12:45", 780: "UTC+13", 840: "UTC+14" }; return getValue(timezone_map, time_zone); } function readDistanceAlarm(status) { var status_map = { 0: "threshold alarm release", 1: "threshold alarm", 2: "mutation alarm", }; return getValue(status_map, status); } function readDistanceException(status) { var status_map = { 0: "blind spot alarm release", 1: "blind spot alarm", 2: "no target", 3: "sensor exception", }; return getValue(status_map, status); } function readHistoryEvent(status) { var event = []; if (((status >>> 0) & 0x01) === 0x01) { event.push("threshold alarm"); } if (((status >>> 1) & 0x01) === 0x01) { event.push("threshold alarm release"); } if (((status >>> 2) & 0x01) === 0x01) { event.push("blind spot alarm"); } if (((status >>> 3) & 0x01) === 0x01) { event.push("blind spot alarm release"); } if (((status >>> 4) & 0x01) === 0x01) { event.push("mutation alarm"); } if (((status >>> 5) & 0x01) === 0x01) { event.push("tilt alarm"); } return event; } function readConditionType(condition) { var condition_map = { 0: "disable", 1: "below", 2: "above", 3: "between", 4: "outside", 5: "mutation" }; return getValue(condition_map, condition); } /* eslint-disable */ function readUInt8(bytes) { return bytes & 0xff; } function readInt8(bytes) { var ref = readUInt8(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; } function getValue(map, key) { if (RAW_VALUE) return key; var value = map[key]; if (!value) value = "unknown"; return value; } //if (!Object.assign) { Object.defineProperty(Object, "assign", { enumerable: false, configurable: true, writable: true, value: function (target) { "use strict"; if (target == null) { throw new TypeError("Cannot convert first argument to object"); } var to = Object(target); for (var i = 1; i < arguments.length; i++) { var nextSource = arguments[i]; if (nextSource == null) { continue; } nextSource = Object(nextSource); var keysArray = Object.keys(Object(nextSource)); for (var nextIndex = 0, len = keysArray.length; nextIndex < len; nextIndex++) { var nextKey = keysArray[nextIndex]; var desc = Object.getOwnPropertyDescriptor(nextSource, nextKey); if (desc !== undefined && desc.enumerable) { // concat array if (Array.isArray(to[nextKey]) && Array.isArray(nextSource[nextKey])) { to[nextKey] = to[nextKey].concat(nextSource[nextKey]); } else { to[nextKey] = nextSource[nextKey]; } } } } return to; }, }); //} // function getHaDeviceInfo() { return { device: { manufacturer: "Milesight IoT Co., Ltd", model: "EM410-RDL" }, entities: { distance:{ entity_conf: { value_template: "{{ (value_json.object.distance | float) }}", state_class: "measurement", device_class: "distance", unit_of_measurement: "mm" } }, radar_signal_rssi:{ entity_conf: { value_template: "{{ (value_json.object.radar_signal_rssi | float) }}", entity_category: "diagnostic", device_class: "signal_strength", unit_of_measurement: "dBm", } }, battery:{ entity_conf: { value_template: "{{ value_json.object.battery | float }}", entity_category: "diagnostic", device_class: "battery", unit_of_measurement: "%", } }, rssi:{ entity_conf: { value_template: "{{ value_json.rxInfo[-1].rssi | int }}", entity_category: "diagnostic", device_class: "signal_strength", unit_of_measurement: "dBm", } } } }; } ``` ## Milesight WS101 Smart Button ``` /** * Payload Decoder * * Copyright 2025 Milesight IoT * * @product WS101 */ var RAW_VALUE = 0x00; /* eslint no-redeclare: "off" */ /* eslint-disable */ // Chirpstack v4 function decodeUplink(input) { var decoded = milesightDeviceDecode(input.bytes); return { data: decoded }; } /* eslint-enable */ function milesightDeviceDecode(bytes) { var decoded = {}; for (var i = 0; i < bytes.length;) { var channel_id = bytes[i++]; var channel_type = bytes[i++]; // IPSO VERSION if (channel_id === 0xff && channel_type === 0x01) { decoded.ipso_version = readProtocolVersion(bytes[i]); i += 1; } // HARDWARE VERSION else if (channel_id === 0xff && channel_type === 0x09) { decoded.hardware_version = readHardwareVersion(bytes.slice(i, i + 2)); i += 2; } // FIRMWARE VERSION else if (channel_id === 0xff && channel_type === 0x0a) { decoded.firmware_version = readFirmwareVersion(bytes.slice(i, i + 2)); i += 2; } // TSL VERSION else if (channel_id === 0xff && channel_type === 0xff) { decoded.tsl_version = readTslVersion(bytes.slice(i, i + 2)); i += 2; } // SERIAL NUMBER else if (channel_id === 0xff && channel_type === 0x08) { decoded.sn = readSerialNumber(bytes.slice(i, i + 6)); i += 6; } // LORAWAN CLASS TYPE else if (channel_id === 0xff && channel_type === 0x0f) { decoded.lorawan_class = readLoRaWANClass(bytes[i]); i += 1; } // RESET EVENT else if (channel_id === 0xff && channel_type === 0xfe) { decoded.reset_event = readResetEvent(1); i += 1; } // DEVICE STATUS else if (channel_id === 0xff && channel_type === 0x0b) { decoded.device_status = readDeviceStatus(1); i += 1; } // BATTERY else if (channel_id === 0x01 && channel_type === 0x75) { decoded.battery = readUInt8(bytes[i]); i += 1; } // PRESS STATE else if (channel_id === 0xff && channel_type === 0x2e) { decoded.button_event = {}; decoded.button_event.status = readButtonEvent(bytes[i]); decoded.button_event.msgid = getRandomIntInclusive(100000, 999999); i += 1; } // DOWNLINK RESPONSE else if (channel_id === 0xfe || channel_id === 0xff) { var result = handle_downlink_response(channel_type, bytes, i); decoded = Object.assign(decoded, result.data); i = result.offset; } else { break; } } return decoded; } function handle_downlink_response(channel_type, bytes, offset) { var decoded = {}; switch (channel_type) { case 0x03: decoded.reporting_interval = readUInt16LE(bytes.slice(offset, offset + 2)); offset += 2; break; case 0x10: decoded.reboot = readYesNoStatus(1); offset += 1; break; case 0x28: decoded.query_device_status = readYesNoStatus(1); offset += 1; break; case 0x2f: decoded.led_indicator_enable = readEnableStatus(bytes[offset]); offset += 1; break; case 0x3e: decoded.buzzer_enable = readEnableStatus(bytes[offset]); offset += 1; break; case 0x74: decoded.double_click_enable = readEnableStatus(bytes[offset]); offset += 1; break; default: throw new Error("unknown downlink response"); } return { data: decoded, offset: offset }; } function readProtocolVersion(bytes) { var major = (bytes & 0xf0) >> 4; var minor = bytes & 0x0f; return "v" + major + "." + minor; } function readHardwareVersion(bytes) { var major = (bytes[0] & 0xff).toString(16); var minor = (bytes[1] & 0xff) >> 4; return "v" + major + "." + minor; } function readFirmwareVersion(bytes) { var major = (bytes[0] & 0xff).toString(16); var minor = (bytes[1] & 0xff).toString(16); return "v" + major + "." + minor; } function readTslVersion(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(""); } function readLoRaWANClass(type) { var class_map = { 0: "Class A", 1: "Class B", 2: "Class C", 3: "Class CtoB", }; return getValue(class_map, type); } function readResetEvent(status) { var status_map = { 0: "normal", 1: "reset" }; return getValue(status_map, status); } function readDeviceStatus(status) { var status_map = { 0: "off", 1: "on" }; return getValue(status_map, status); } function readButtonEvent(status) { var status_map = { 1: "short press", 2: "long press", 3: "double press" }; return getValue(status_map, status); } function readEnableStatus(status) { var status_map = { 0: "disable", 1: "enable" }; return getValue(status_map, status); } function readYesNoStatus(status) { var status_map = { 0: "no", 1: "yes" }; return getValue(status_map, status); } function getRandomIntInclusive(min, max) { min = Math.ceil(min); max = Math.floor(max); return Math.floor(Math.random() * (max - min + 1)) + min; } /* eslint-disable */ function readUInt8(bytes) { return bytes & 0xff; } function readInt8(bytes) { var ref = readUInt8(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 getValue(map, key) { if (RAW_VALUE) return key; var value = map[key]; if (!value) value = "unknown"; return value; } //if (!Object.assign) { Object.defineProperty(Object, "assign", { enumerable: false, configurable: true, writable: true, value: function (target) { "use strict"; if (target == null) { throw new TypeError("Cannot convert first argument to object"); } var to = Object(target); for (var i = 1; i < arguments.length; i++) { var nextSource = arguments[i]; if (nextSource == null) { continue; } nextSource = Object(nextSource); var keysArray = Object.keys(Object(nextSource)); for (var nextIndex = 0, len = keysArray.length; nextIndex < len; nextIndex++) { var nextKey = keysArray[nextIndex]; var desc = Object.getOwnPropertyDescriptor(nextSource, nextKey); if (desc !== undefined && desc.enumerable) { // concat array if (Array.isArray(to[nextKey]) && Array.isArray(nextSource[nextKey])) { to[nextKey] = to[nextKey].concat(nextSource[nextKey]); } else { to[nextKey] = nextSource[nextKey]; } } } } return to; }, }); //} // function getHaDeviceInfo() { return { device: { manufacturer: "Milesight IoT Co., Ltd", model: "WS101" }, entities: { state:{ integration: "event", entity_conf: { value_template: "{ \"event_type\": \"{{ value_json.object.button_event.status }}\" }", event_types: ["short press", "double press", "long press"], device_class: "button" } }, battery:{ entity_conf: { value_template: "{{ value_json.object.battery | float }}", entity_category: "diagnostic", device_class: "battery", unit_of_measurement: "%", } }, rssi:{ entity_conf: { value_template: "{{ value_json.rxInfo[-1].rssi | int }}", entity_category: "diagnostic", device_class: "signal_strength", unit_of_measurement: "dBm", } } } }; } ``` ## Milesight WS523 smart plug ### including working uplink and downlink functions, and a binary dying gasp outage sensor ``` /** * Payload Decoder * * Copyright 2025 Milesight IoT * * @product WS52x */ var RAW_VALUE = 0x00; /* eslint no-redeclare: "off" */ /* eslint-disable */ // Chirpstack v4 function decodeUplink(input) { var decoded = milesightDeviceDecode(input.bytes); return { data: decoded }; } /* eslint-enable */ function milesightDeviceDecode(bytes) { var decoded = {}; decoded.outage = "off"; for (var i = 0; i < bytes.length;) { var channel_id = bytes[i++]; var channel_type = bytes[i++]; // IPSO VERSION if (channel_id === 0xff && channel_type === 0x01) { decoded.ipso_version = readProtocolVersion(bytes[i]); i += 1; } // HARDWARE VERSION else if (channel_id === 0xff && channel_type === 0x09) { decoded.hardware_version = readHardwareVersion(bytes.slice(i, i + 2)); i += 2; } // FIRMWARE VERSION else if (channel_id === 0xff && channel_type === 0x0a) { decoded.firmware_version = readFirmwareVersion(bytes.slice(i, i + 2)); i += 2; } // TSL VERSION else if (channel_id === 0xff && channel_type === 0xff) { decoded.tsl_version = readTslVersion(bytes.slice(i, i + 2)); i += 2; } // SERIAL NUMBER else if (channel_id === 0xff && channel_type === 0x16) { decoded.sn = readSerialNumber(bytes.slice(i, i + 8)); i += 8; } // LORAWAN CLASS TYPE else if (channel_id === 0xff && channel_type === 0x0f) { decoded.lorawan_class = readLoRaWANClass(bytes[i]); i += 1; } // RESET EVENT else if (channel_id === 0xff && channel_type === 0xfe) { decoded.reset_event = readResetEvent(1); i += 1; } // DEVICE STATUS else if (channel_id === 0xff && channel_type === 0x0b) { decoded.device_status = readDeviceStatus(1); i += 1; } // VOLTAGE else 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 = readUInt8(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; } // CURRENT else if (channel_id === 0x07 && channel_type == 0xc9) { decoded.current = readUInt16LE(bytes.slice(i, i + 2)); i += 2; } // SOCKET STATUS else if (channel_id === 0x08 && channel_type == 0x70) { var data = bytes[i++]; decoded.socket_status = readSocketStatus(data & 0x01); } // *-- OUTAGE --* else if (channel_id === 0xff && channel_type === 0x3f) { var data = bytes[i++]; decoded.outage = "on"; } // DOWNLINK RESPONSE else if (channel_id === 0xfe || channel_id === 0xff) { var result = handle_downlink_response(channel_type, bytes, i); decoded = Object.assign(decoded, result.data); i = result.offset; } // Clear OUTAGE if it is not set else { break; } } return decoded; } function handle_downlink_response(channel_type, bytes, offset) { var decoded = {}; switch (channel_type) { case 0x03: decoded.report_interval = readUInt16LE(bytes.slice(offset, offset + 2)); offset += 2; break; case 0x10: decoded.reboot = readYesNoStatus(1); offset += 1; break; case 0x28: decoded.report_status = readYesNoStatus(1); offset += 1; break; case 0x22: // skip first byte decoded.delay_time = readUInt16LE(bytes.slice(offset + 1, offset + 3)); decoded.socket_status = readOnOffStatus(bytes[offset + 3] & 0x0F); offset += 4; break; case 0x23: decoded.cancel_delay_task = readUInt8(bytes[offset]); // skip next byte offset += 2; break; case 0x24: decoded.current_alarm_config = {}; decoded.current_alarm_config.enable = readEnableStatus(bytes[offset]); decoded.current_alarm_config.threshold = readUInt8(bytes[offset + 1]); offset += 2; break; case 0x25: var child_lock_data = readUInt16LE(bytes.slice(offset, offset + 2)); decoded.child_lock_config = {}; decoded.child_lock_config.enable = readEnableStatus((child_lock_data >>> 15) & 0x01); decoded.child_lock_config.lock_time = child_lock_data & 0x7fff; offset += 2; break; case 0x26: decoded.power_consumption_enable = readEnableStatus(bytes[offset]); offset += 1; break; case 0x27: decoded.reset_power_consumption = readYesNoStatus(1); offset += 1; break; case 0x2c: decoded.report_attribute = readYesNoStatus(1); offset += 1; break; case 0x2f: decoded.led_indicator_enable = readEnableStatus(bytes[offset]); offset += 1; break; case 0x30: decoded.over_current_protection = {}; decoded.over_current_protection.enable = readEnableStatus(bytes[offset]); decoded.over_current_protection.trip_current = readUInt8(bytes[offset + 1]); offset += 2; break; default: throw new Error("unknown downlink response"); } return { data: decoded, offset: offset }; } function readProtocolVersion(bytes) { var major = (bytes & 0xf0) >> 4; var minor = bytes & 0x0f; return "v" + major + "." + minor; } function readHardwareVersion(bytes) { var major = (bytes[0] & 0xff).toString(16); var minor = (bytes[1] & 0xff) >> 4; return "v" + major + "." + minor; } function readFirmwareVersion(bytes) { var major = (bytes[0] & 0xff).toString(16); var minor = (bytes[1] & 0xff).toString(16); return "v" + major + "." + minor; } function readTslVersion(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(""); } function readLoRaWANClass(type) { var class_map = { 0: "Class A", 1: "Class B", 2: "Class C", 3: "Class CtoB", }; return getValue(class_map, type); } function readResetEvent(status) { var status_map = { 0: "normal", 1: "reset" }; return getValue(status_map, status); } function readDeviceStatus(status) { var status_map = { 0: "off", 1: "on" }; return getValue(status_map, status); } function readSocketStatus(status) { var on_off_map = { 0: "off", 1: "on" }; return getValue(on_off_map, status); } function readEnableStatus(status) { var status_map = { 0: "disable", 1: "enable" }; return getValue(status_map, status); } function readYesNoStatus(status) { var yes_no_map = { 0: "no", 1: "yes" }; return getValue(yes_no_map, status); } function readOnOffStatus(status) { var on_off_map = { 0: "off", 1: "on" }; return getValue(on_off_map, status); } /* eslint-disable */ function readUInt8(bytes) { return bytes & 0xff; } function readInt8(bytes) { var ref = readUInt8(bytes); return ref > 0x7f ? ref - 0x100 : ref; } 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 getValue(map, key) { if (RAW_VALUE) return key; var value = map[key]; if (!value) value = "unknown"; return value; } //if (!Object.assign) { Object.defineProperty(Object, "assign", { enumerable: false, configurable: true, writable: true, value: function (target) { "use strict"; if (target == null) { throw new TypeError("Cannot convert first argument to object"); } var to = Object(target); for (var i = 1; i < arguments.length; i++) { var nextSource = arguments[i]; if (nextSource == null) { continue; } nextSource = Object(nextSource); var keysArray = Object.keys(Object(nextSource)); for (var nextIndex = 0, len = keysArray.length; nextIndex < len; nextIndex++) { var nextKey = keysArray[nextIndex]; var desc = Object.getOwnPropertyDescriptor(nextSource, nextKey); if (desc !== undefined && desc.enumerable) { // concat array if (Array.isArray(to[nextKey]) && Array.isArray(nextSource[nextKey])) { to[nextKey] = to[nextKey].concat(nextSource[nextKey]); } else { to[nextKey] = nextSource[nextKey]; } } } } return to; }, }); //} /** * Payload Encoder * * Copyright 2025 Milesight IoT * * @product WS52x */ var RAW_VALUE = 0x00; /* eslint no-redeclare: "off" */ /* eslint-disable */ // Chirpstack v4 function encodeDownlink(input) { var encoded = milesightDeviceEncode(input.data); return { bytes: encoded }; } /* eslint-enable */ function milesightDeviceEncode(payload) { var encoded = []; if ("reboot" in payload) { encoded = encoded.concat(reboot(payload.reboot)); } if ("report_status" in payload) { encoded = encoded.concat(reportStatus(payload.report_status)); } if ("report_attribute" in payload) { encoded = encoded.concat(reportAttribute(payload.report_attribute)); } if ("report_interval" in payload) { encoded = encoded.concat(setReportInterval(payload.report_interval)); } if ("socket_status" in payload) { if ("delay_time" in payload) { encoded = encoded.concat(socketStatusWithDelay(payload.socket_status, payload.delay_time)); } else { encoded = encoded.concat(socketStatus(payload.socket_status)); } } if ("cancel_delay_task" in payload) { encoded = encoded.concat(cancelDelayTask(payload.cancel_delay_task)); } if ("over_current_protection" in payload) { encoded = encoded.concat(setOverCurrentProtection(payload.over_current_protection)); } if ("current_alarm_config" in payload) { encoded = encoded.concat(setCurrentAlarmConfig(payload.current_alarm_config)); } if ("child_lock_config" in payload) { encoded = encoded.concat(setChildLock(payload.child_lock_config)); } if ("power_consumption_enable" in payload) { encoded = encoded.concat(powerConsumptionEnable(payload.power_consumption_enable)); } if ("reset_power_consumption" in payload) { encoded = encoded.concat(resetPowerConsumption(payload.reset_power_consumption)); } if ("led_indicator_enable" in payload) { encoded = encoded.concat(setLedEnable(payload.led_indicator_enable)); } return encoded; } /** * reboot device * @param {number} reboot values: (0: no, 1: yes) * @example { "reboot": 1 } */ function reboot(reboot) { var yes_no_map = { 0: "no", 1: "yes" }; var yes_no_values = getValues(yes_no_map); if (yes_no_values.indexOf(reboot) === -1) { throw new Error("reboot must be one of " + yes_no_values.join(", ")); } if (getValueEnc(yes_no_map, reboot) === 0) { return []; } return [0xff, 0x10, 0xff]; } /** * report status * @param {number} report_status values: (0: no, 1: yes) * @example { "report_status": 1 } */ function reportStatus(report_status) { var yes_no_map = { 0: "no", 1: "yes" }; var yes_no_values = getValues(yes_no_map); if (yes_no_values.indexOf(report_status) === -1) { throw new Error("report_status must be one of " + yes_no_values.join(", ")); } if (getValueEnc(yes_no_map, report_status) === 0) { return []; } return [0xff, 0x28, 0xff]; } /** * report attribute * @param {number} report_attribute values: (0: no, 1: yes) * @example { "report_attribute": 1 } */ function reportAttribute(report_attribute) { var yes_no_map = { 0: "no", 1: "yes" }; var yes_no_values = getValues(yes_no_map); if (yes_no_values.indexOf(report_attribute) === -1) { throw new Error("report_attribute must be one of " + yes_no_values.join(", ")); } if (getValueEnc(yes_no_map, report_attribute) === 0) { return []; } return [0xff, 0x2c, 0xff]; } /** * set socket status * @param {string} socket_status values: (0: off, 1: on) * @example { "socket_status": 0 } */ function socketStatus(socket_status) { var on_off_map = { 0: "off", 1: "on" }; var on_off_values = getValues(on_off_map); if (on_off_values.indexOf(socket_status) === -1) { throw new Error("socket_status must be one of " + on_off_values.join(", ")); } var buffer = new Buffer(4); buffer.writeUInt8(0x08); buffer.writeUInt8(getValueEnc(on_off_map, socket_status)); buffer.writeUInt16LE(0xffff); return buffer.toBytes(); } /** * control socket status with delay * @param {number} socket_status values: (0: off, 1: on) * @param {number} delay_time unit: second, range: [0, 65535] * @example { "socket_status": 1, "delay_time": 10 } */ function socketStatusWithDelay(socket_status, delay_time) { var on_off_map = { 0: "off", 1: "on" }; var on_off_values = getValues(on_off_map); if (on_off_values.indexOf(socket_status) === -1) { throw new Error("socket_status must be one of " + on_off_values.join(", ")); } if (typeof delay_time !== "number") { throw new Error("delay_time must be a number"); } if (delay_time < 0 || delay_time > 65535) { throw new Error("delay_time must be in the range [0, 65535]"); } var data = (0x01 << 4) | getValueEnc(on_off_map, socket_status); var buffer = new Buffer(6); buffer.writeUInt8(0xff); buffer.writeUInt8(0x22); buffer.writeUInt8(0x00); buffer.writeUInt16LE(delay_time); buffer.writeUInt8(data); return buffer.toBytes(); } /** * cancel delay task * @param {number} cancel_delay_task task_id * @example { "cancel_delay_task": 1 } */ function cancelDelayTask(cancel_delay_task) { if (typeof cancel_delay_task !== "number") { throw new Error("cancel_delay_task must be a number"); } var buffer = new Buffer(4); buffer.writeUInt8(0xff); buffer.writeUInt8(0x23); buffer.writeUInt8(cancel_delay_task); buffer.writeUInt8(0xff); return buffer.toBytes(); } /** * update report interval * @param {number} report_interval uint: second * @example payload: { "report_interval": 600 } */ function setReportInterval(report_interval) { if (typeof report_interval !== "number") { throw new Error("report_interval must be a number"); } if (report_interval < 1) { throw new Error("report_interval must be greater than 1"); } var buffer = new Buffer(4); buffer.writeUInt8(0xff); buffer.writeUInt8(0x03); buffer.writeUInt16LE(report_interval); return buffer.toBytes(); } /** * set over_current protection configuration * @param {object} over_current_protection * @param {number} over_current_protection.enable values: (0: disable, 1: enable) * @param {number} over_current_protection.trip_current unit: A * @example { "over_current_protection": { "enable": 1, "trip_current": 10 } } */ function setOverCurrentProtection(over_current_protection) { var enable = over_current_protection.enable; var trip_current = over_current_protection.trip_current; var enable_map = { 0: "disable", 1: "enable" }; var enable_values = getValues(enable_map); if (enable_values.indexOf(enable) === -1) { throw new Error("over_current_protection.enable must be one of " + enable_values.join(", ")); } if (typeof trip_current !== "number") { throw new Error("over_current_protection.trip_current must be a number"); } var buffer = new Buffer(4); buffer.writeUInt8(0xff); buffer.writeUInt8(0x30); buffer.writeUInt8(getValueEnc(enable_map, enable)); buffer.writeUInt8(trip_current); return buffer.toBytes(); } /** * set current alarm configuration * @param {object} current_alarm_config * @param {number} current_alarm_config.enable values: (0: disable, 1: enable) * @param {number} current_alarm_config.threshold unit: A * @example { "current_alarm_config": { "enable": 1, "threshold": 10 } } */ function setCurrentAlarmConfig(current_alarm_config) { var enable = current_alarm_config.enable; var threshold = current_alarm_config.threshold; var enable_map = { 0: "disable", 1: "enable" }; var enable_values = getValues(enable_map); if (enable_values.indexOf(enable) === -1) { throw new Error("current_alarm_config.enable must be one of " + enable_values.join(", ")); } if (typeof threshold !== "number") { throw new Error("current_alarm_config.threshold must be a number"); } var buffer = new Buffer(4); buffer.writeUInt8(0xff); buffer.writeUInt8(0x24); buffer.writeUInt8(getValueEnc(enable_map, enable)); buffer.writeUInt8(threshold); return buffer.toBytes(); } /** * set child lock configuration * @param {object} child_lock_config * @param {number} child_lock_config.enable values: (0: disable, 1: enable) * @param {number} child_lock_config.lock_time unit: min * @example { "child_lock_config": { "enable": 1, "lock_time": 10 } } */ function setChildLock(child_lock_config) { var enable = child_lock_config.enable; var lock_time = child_lock_config.lock_time; var enable_map = { 0: "disable", 1: "enable" }; var enable_values = getValues(enable_map); if (enable_values.indexOf(enable) === -1) { throw new Error("child_lock_config.enable must be one of " + enable_values.join(", ")); } if (typeof lock_time !== "number") { throw new Error("child_lock_config.lock_time must be a number"); } var data = (getValueEnc(enable_map, enable) << 15) + lock_time; var buffer = new Buffer(4); buffer.writeUInt8(0xff); buffer.writeUInt8(0x25); buffer.writeUInt16LE(data); return buffer.toBytes(); } /** * set statistics enable configuration * @param {number} power_consumption_enable values: (0: disable, 1: enable) * @example { "power_consumption_enable": 1 } */ function powerConsumptionEnable(power_consumption_enable) { var enable_map = { 0: "disable", 1: "enable" }; var enable_values = getValues(enable_map); if (enable_values.indexOf(power_consumption_enable) === -1) { throw new Error("power_consumption_enable must be one of " + enable_values.join(", ")); } var buffer = new Buffer(3); buffer.writeUInt8(0xff); buffer.writeUInt8(0x26); buffer.writeUInt8(getValueEnc(enable_map, power_consumption_enable)); return buffer.toBytes(); } /** * reset power consumption * @param {number} reset_power_consumption values: (0: no, 1: yes) * @example { "reset_power_consumption": 1 } */ function resetPowerConsumption(reset_power_consumption) { var yes_no_map = { 0: "no", 1: "yes" }; var yes_no_values = getValues(yes_no_map); if (yes_no_values.indexOf(reset_power_consumption) === -1) { throw new Error("reset_power_consumption must be one of " + yes_no_values.join(", ")); } if (getValueEnc(yes_no_map, reset_power_consumption) === 0) { return []; } return [0xff, 0x27, 0xff]; } /** * set led enable configuration * @param {number} led_indicator_enable values: (0: disable, 1: enable) * @example { "led_indicator_enable": 1 } */ function setLedEnable(led_indicator_enable) { var enable_map = { 0: "disable", 1: "enable" }; var enable_values = getValues(enable_map); if (enable_values.indexOf(led_indicator_enable) === -1) { throw new Error("led_indicator_enable must be one of " + enable_values.join(", ")); } var buffer = new Buffer(3); buffer.writeUInt8(0xff); buffer.writeUInt8(0x2f); buffer.writeUInt8(getValueEnc(enable_map, led_indicator_enable)); return buffer.toBytes(); } function getValues(map) { var values = []; for (var key in map) { values.push(RAW_VALUE ? parseInt(key) : map[key]); } return values; } function getValueEnc(map, value) { if (RAW_VALUE) return value; for (var key in map) { if (map[key] === value) { return parseInt(key); } } throw new Error("not match in " + JSON.stringify(map)); } function Buffer(size) { this.buffer = new Array(size); this.offset = 0; for (var i = 0; i < size; i++) { this.buffer[i] = 0; } } Buffer.prototype._write = function (value, byteLength, isLittleEndian) { var offset = 0; for (var index = 0; index < byteLength; index++) { offset = isLittleEndian ? index << 3 : (byteLength - 1 - index) << 3; this.buffer[this.offset + index] = (value >> offset) & 0xff; } }; Buffer.prototype.writeUInt8 = function (value) { this._write(value, 1, 1); this.offset += 1; }; Buffer.prototype.writeInt8 = function (value) { this._write(value < 0 ? value + 0x100 : value, 1, 1); this.offset += 1; }; Buffer.prototype.writeUInt16LE = function (value) { this._write(value, 2, 1); this.offset += 2; }; Buffer.prototype.writeInt16LE = function (value) { this._write(value < 0 ? value + 0x10000 : value, 2, 1); this.offset += 2; }; Buffer.prototype.writeUInt32LE = function (value) { this._write(value, 4, 1); this.offset += 4; }; Buffer.prototype.writeInt32LE = function (value) { this._write(value < 0 ? value + 0x100000000 : value, 4, 1); this.offset += 4; }; Buffer.prototype.toBytes = function () { return this.buffer; }; // HA function getHaDeviceInfo() { return { device: { manufacturer: "Milesight IoT Co., Ltd", model: "WS52x" }, entities: { current: { entity_conf: { value_template: "{{ (value_json.object.current | float) / 1000 }}", entity_category: "diagnostic", state_class: "measurement", device_class: "current", unit_of_measurement: "A" } }, factor: { entity_conf: { value_template: "{{ (value_json.object.power_factor | float) / 100 }}", entity_category: "diagnostic", state_class: "measurement", device_class: "power_factor" } }, power: { entity_conf: { value_template: "{{ value_json.object.active_power | float }}", state_class: "measurement", device_class: "power", unit_of_measurement: "W" } }, voltage: { entity_conf: { value_template: "{{ value_json.object.voltage | float }}", entity_category: "diagnostic", state_class: "measurement", device_class: "voltage", unit_of_measurement: "V" } }, outage: { integration: "binary_sensor", entity_conf: { state: "{{ value_json.object.outage }}", entity_category: "diagnostic" } }, power_sum: { entity_conf: { value_template: "{{ (value_json.object.power_consumption | float) / 1000 }}", state_class: "total_increasing", device_class: "energy", unit_of_measurement: "kWh" } }, state: { integration: "switch", entity_conf: { value_template: "{{ value_json.object.socket_status }}", command_topic: "{command_topic}", state_on: "on", state_off: "off", payload_off: '{"dev_eui":"{dev_eui}", "confirmed":true, "fPort":85, "object": { "socket_status" : "off" }}', payload_on: '{"dev_eui":"{dev_eui}", "confirmed":true, "fPort":85, "object": { "socket_status" : "on" }}' } }, rssi: { entity_conf: { value_template: "{{ value_json.rxInfo[-1].rssi | int }}", entity_category: "diagnostic", device_class: "signal_strength", unit_of_measurement: "dBm" } } } }; } ``` ## A very hacky jinja macro template for home assistant ### convert the level (in mm) returned from the EM410-RDL (in tank mode) to volume in gallons for a cylindrical tank mounted horizontally. _Note that this requires both the tank height to be configured in the EM410 as well as passed as a parameter to this macro._ ``` {%- macro horizontal_cylinder_gal(h_mm, tank_height_in, total_v) -%} {%- set r = tank_height_in / 2 -%} {%- set h = ([0,(h_mm / 25.4), tank_height_in] | sort)[1] -%} {%- set acos_val = acos((r - h) / r) -%} {%- set area_seg = (r**2 * acos_val) - ((r - h) * (2 * r * h - h**2)**0.5) -%} {%- set total_area = pi * r**2 -%} {{ (total_v * (area_seg / total_area)) | round(2) }} {%- endmacro -%} ```