From 6ba46560f383142235af2adce3f61ab70af6d203 Mon Sep 17 00:00:00 2001 From: Karel Vanroye Date: Fri, 19 May 2023 12:01:00 -0700 Subject: [PATCH 001/112] Initial commit for python package --- .github/workflows/python-publish.yml | 31 +++++ i2c-stick-py/CONTRIBUTING.md | 17 +++ i2c-stick-py/LICENSE | 13 +++ i2c-stick-py/NOTICE | 5 + i2c-stick-py/README.md | 7 ++ i2c-stick-py/melexis/i2c_stick/I2CStick.py | 70 ++++++++++++ i2c-stick-py/melexis/i2c_stick/MemoryFile.py | 112 +++++++++++++++++++ i2c-stick-py/melexis/i2c_stick/__init__.py | 8 ++ i2c-stick-py/setup.cfg | 3 + i2c-stick-py/setup.py | 51 +++++++++ 10 files changed, 317 insertions(+) create mode 100644 .github/workflows/python-publish.yml create mode 100644 i2c-stick-py/CONTRIBUTING.md create mode 100644 i2c-stick-py/LICENSE create mode 100644 i2c-stick-py/NOTICE create mode 100644 i2c-stick-py/README.md create mode 100644 i2c-stick-py/melexis/i2c_stick/I2CStick.py create mode 100644 i2c-stick-py/melexis/i2c_stick/MemoryFile.py create mode 100644 i2c-stick-py/melexis/i2c_stick/__init__.py create mode 100644 i2c-stick-py/setup.cfg create mode 100644 i2c-stick-py/setup.py diff --git a/.github/workflows/python-publish.yml b/.github/workflows/python-publish.yml new file mode 100644 index 0000000..ebdc414 --- /dev/null +++ b/.github/workflows/python-publish.yml @@ -0,0 +1,31 @@ +# This workflows will upload a Python Package using Twine when a release is created +# For more information see: https://help.github.com/en/actions/language-and-framework-guides/using-python-with-github-actions#publishing-to-package-registries + +name: Upload Python Package + +on: + release: + types: [created] + +jobs: + deploy: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + - name: Set up Python + uses: actions/setup-python@v2 + with: + python-version: '3.x' + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install setuptools wheel twine + - name: Build and publish + env: + TWINE_USERNAME: ${{ secrets.PYPI_USERNAME }} + TWINE_PASSWORD: ${{ secrets.PYPI_PASSWORD }} + run: | + python setup.py sdist bdist_wheel + twine upload dist/* diff --git a/i2c-stick-py/CONTRIBUTING.md b/i2c-stick-py/CONTRIBUTING.md new file mode 100644 index 0000000..0a90a45 --- /dev/null +++ b/i2c-stick-py/CONTRIBUTING.md @@ -0,0 +1,17 @@ +# Contribution guide +Anyone is more than welcome to contribute to the development, no matter of your prorgamming skill level. It is reviewers obligation to help bring your contribution to our desired quality level and you should do your best to help reviewer understand your decisions. Standard GitHub flow is used https://guides.github.com/introduction/flow/ to start Pull Requests, which are then merged. We also prefer to make a Work In Progress Merge request once you starting your work just in case someone else is not working on the same issue. + +# Getting started +There should always be few issues opened for new features, otherwise you are also more than welcome to create some on your own suggestions. The help wanted label indicates that it is easy enough task for anyone to start, so go and pick up the feature you feel most excited by and start implementing it. + +## Quality of contribution +All new contributions need to be properly tested. We are not targeting some coverage percentage, but rather focus on regression testing to confirm expected functionality and border cases. This will help us keep existing features even after years of constant development and it helps fixing regression bugs. + +## Documentation +Basic documentation is expected, but every bit of detail you can include will help in the future. It might look obvious, but it will also help person reviewing the code to correctly understand the intended functionality, so that he can focus more on implementation aspect. + +## Code review +Anyone is more than welcome to check open Pull requests and make a code review. Everyone benefits from fresh eyes looking at new features or bug fixes and it also improves coding skills of all included. Remember to act politely. Since some people might not be frequent contributors to various repositories, do not intimidate them, but rather help them improve. We are all learning. + +# Reporting issues or requesting a new feature +Please open a new Issue if you have any problems with the usage plugin. We will be happy to fix them as soon as possible. If you want some feature to be included, but do not know where to start, you should also open an Issue with label enhancement request and we can implement it when we have time if it fits in our view. diff --git a/i2c-stick-py/LICENSE b/i2c-stick-py/LICENSE new file mode 100644 index 0000000..784d536 --- /dev/null +++ b/i2c-stick-py/LICENSE @@ -0,0 +1,13 @@ + Copyright 2020 Melexis + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/i2c-stick-py/NOTICE b/i2c-stick-py/NOTICE new file mode 100644 index 0000000..4fd89ae --- /dev/null +++ b/i2c-stick-py/NOTICE @@ -0,0 +1,5 @@ +Copyright Melexis N.V. + +This product includes software developed at Melexis N.V. (https://www.melexis.com). + +Melexis N.V. has provided this code according to LICENSE file attached to repository diff --git a/i2c-stick-py/README.md b/i2c-stick-py/README.md new file mode 100644 index 0000000..c21ac64 --- /dev/null +++ b/i2c-stick-py/README.md @@ -0,0 +1,7 @@ +# melexis-i2c-stick-py + +Python interface for I2C Stick, it runs on the host computer to communicate with the I2C Stick over the UART. + +## Getting started. + +todo... \ No newline at end of file diff --git a/i2c-stick-py/melexis/i2c_stick/I2CStick.py b/i2c-stick-py/melexis/i2c_stick/I2CStick.py new file mode 100644 index 0000000..165fbfa --- /dev/null +++ b/i2c-stick-py/melexis/i2c_stick/I2CStick.py @@ -0,0 +1,70 @@ +import serial +import time + +class I2CStick: + ser = None + def __init__(self, port): + self.open(port) + + def open(self, port): + self.ser = serial.Serial(port, 921600, timeout=5) + self.ser.write(b'!') + time.sleep(0.2) + self.ser.flushInput() + self.ser.flushOutput() + time.sleep(0.1) + + def close(self): + if self.ser is not None: + self.ser.close() + self.ser = None + + def mv(self, sa): + self.ser.write('mv:{:02X}'.format(sa).encode()+ b'\n') + line = self.ser.readline().decode('utf-8').rstrip() # read a '\n' terminated line + values = line.split(":")[-1] + return [float(value) for value in values.split(",")] + + def read_continuous_message(self): + line = self.ser.readline().decode('utf-8').rstrip() # read a '\n' terminated line + if line.startswith("@"): + values = line.split(":") + if values[2] == 'mv': + mv_list = [float(v) for v in values[-1].split(",")] + return {'sa': int(values[-3], 16), 'time': int(values[-2]), 'drv': int(values[1], 16), 'mv': mv_list} + return None + + def stop_continuous_mode(self): + self.ser.write(b'!') + time.sleep(0.1) + self.ser.flushInput() + self.ser.flushOutput() + time.sleep(0.1) + + def trigger_continuous_mode(self): + self.ser.write(b'!') + time.sleep(0.1) + self.ser.flushInput() + self.ser.flushOutput() + self.ser.write(b';') + self.ser.readline().decode('utf-8').rstrip() # read a '\n' terminated line + + def set_pwm(self, pin, pwm): + self.ser.write(bytes('pwm:{}:{}\n'.format(pin, pwm), 'utf-8')) + return self.ser.readline().decode('utf-8').rstrip() # read a '\n' terminated line + + def run_cmd(self, cmd): + self.ser.write(bytes(cmd+"\n", 'utf-8')) + return self.ser.readline().decode('utf-8').rstrip() # read a '\n' terminated line + + +if (__name__ == '__main__'): + mis = I2CStick("COM154") + print(mis.mv(0x3A)) + mis.trigger_continuous_mode() + print(mis.read_continuous_message()) + print(mis.read_continuous_message()) + print(mis.read_continuous_message()) + print(mis.read_continuous_message()) + print(mis.read_continuous_message()) + mis.stop_continuous_mode() diff --git a/i2c-stick-py/melexis/i2c_stick/MemoryFile.py b/i2c-stick-py/melexis/i2c_stick/MemoryFile.py new file mode 100644 index 0000000..9e54258 --- /dev/null +++ b/i2c-stick-py/melexis/i2c_stick/MemoryFile.py @@ -0,0 +1,112 @@ +import bincopy +import struct + +# goal is to extend the functionality and update the default creation parameter of a BinFile object. + +class MemoryFile(bincopy.BinFile): + def __init__(self, filenames=None, overwrite=True, header_encoding='utf-8'): + super().__init__(filenames=filenames, overwrite=overwrite, header_encoding=header_encoding) + + + @staticmethod + def read_evb_bin_file(evb_bin_file, at_address=0x2400): + # EVB BIN file format is little-endian, while bin_copy; the hex file package expects big-endian! + # so here we do the trick with unpack/pack! + with open(evb_bin_file, mode='rb') as file: # b is important -> binary + fileContent = file.read() + + fmt_in = "<{:d}H".format (int(len(fileContent)/2)) + fmt_out = ">{:d}H".format (int(len(fileContent)/2)) + data = list(struct.unpack(fmt_in, fileContent)) + bin_data = struct.pack(fmt_out, *data) + + bin_file = MemoryFile() + bin_file.add_binary(bin_data, address=at_address, overwrite=True) + return bin_file + + + def add_32(self, address, int_data): + if type(int_data) is list: + byte_array = struct.pack('>{}L'.format(len(int_data)), *int_data) + else: + byte_array = struct.pack('>L', int_data) + # silly mistake for 90632 in the eeprom map... LWORD is before HWORD + for i in range(0, len(byte_array), 4): + self.add_binary(byte_array[i+2:i+4], address=address, overwrite=True) + self.add_binary(byte_array[i+0:i+2], address=address+1, overwrite=True) + # + # for new design use this: + # self.add_binary(byte_array, address=address, overwrite=True) + + + def add_32s(self, address, int_data): + if type(int_data) is list: + byte_array = struct.pack('>{}l'.format(len(int_data)), *int_data) + else: + byte_array = struct.pack('>l', int_data) + # silly mistake for 90632 in the eeprom map... LWORD is before HWORD + for i in range(0, len(byte_array), 4): + self.add_binary(byte_array[i+2:i+4], address=address, overwrite=True) + self.add_binary(byte_array[i+0:i+2], address=address+1, overwrite=True) + # + # for new design use this: + # self.add_binary(byte_array, address=address, overwrite=True) + + + def add_16(self, address, int_data): + if type(int_data) is list: + byte_array = struct.pack('>{}H'.format(len(int_data)), *int_data) + else: + byte_array = struct.pack('>H', int_data) + self.add_binary(byte_array, address=address, overwrite=True) + + + def add_16s(self, address, int_data): + if type(int_data) is list: + byte_array = struct.pack('>{}h'.format(len(int_data)), *int_data) + else: + byte_array = struct.pack('>h', int_data) + self.add_binary(byte_array, address=address, overwrite=True) + + + def write_evb_bin_file(self, evb_bin_file_name = "evb90632.bin"): + if evb_bin_file_name is None: + return None + + if not evb_bin_file_name.endswith('.bin'): + evb_bin_file_name += '.bin' + + bin_data_in = self.as_binary() + fmt_in = ">{:d}H".format (int(len(bin_data_in)/2)) + fmt_out = "<{:d}H".format (int(len(bin_data_in)/2)) + + data = list(struct.unpack(fmt_in, bin_data_in)) + bin_data = struct.pack(fmt_out, *data) + + with open(evb_bin_file_name, "wb") as out_file: + out_file.write(bin_data) + + return evb_bin_file_name + + + def write_hex_file(self, hex_file_name = "evb90632.hex"): + if hex_file_name is None: + return self.as_ihex() + + if not hex_file_name.endswith('.hex'): + hex_file_name += '.hex' + + with open(hex_file_name, "w") as out_file: + out_file.write(self.as_ihex()) + + return hex_file_name + + + def get_address_data_pairs(self): + pairs = [] + for seg in self.segments: + for addr in range(int((seg.maximum_address-seg.minimum_address) / seg._word_size_bytes)): + addr += int(seg.minimum_address / seg._word_size_bytes) + pairs.append ((addr, self[addr])) + return pairs + diff --git a/i2c-stick-py/melexis/i2c_stick/__init__.py b/i2c-stick-py/melexis/i2c_stick/__init__.py new file mode 100644 index 0000000..0e67645 --- /dev/null +++ b/i2c-stick-py/melexis/i2c_stick/__init__.py @@ -0,0 +1,8 @@ + +# __all__ = ['.I2CStick.I2CStick'] + +# __all__ = ['.I2CStick.I2CStick', ".MemoryFile.MemoryFile"] + +from .I2CStick import I2CStick +from .MemoryFile import MemoryFile + diff --git a/i2c-stick-py/setup.cfg b/i2c-stick-py/setup.cfg new file mode 100644 index 0000000..d85a638 --- /dev/null +++ b/i2c-stick-py/setup.cfg @@ -0,0 +1,3 @@ +# Inside of setup.cfg +[metadata] +description-file = README.md diff --git a/i2c-stick-py/setup.py b/i2c-stick-py/setup.py new file mode 100644 index 0000000..79bfab3 --- /dev/null +++ b/i2c-stick-py/setup.py @@ -0,0 +1,51 @@ +from setuptools import setup +import sys +import platform +from setuptools import find_namespace_packages + + +version='0.1.0' + +requires = ['bincopy>=17.14.5', + 'pyserial>=3.5', + ] + +with open("README.md", "r") as fh: + long_description = fh.read() + +# This is a `native namespace package` +# +# See more info here: +# https://packaging.python.org/en/latest/guides/packaging-namespace-packages/#native-namespace-packages +# + +setup( + name='melexis-i2c-stick', + version=version, + description='Python package for I2C Stick', + long_description=long_description, + long_description_content_type="text/markdown", + license='Apache License, Version 2.0', + install_requires=requires, + url = 'https://github.com/melexis/i2c-stick', # Provide either the link to your github or to your website + download_url = 'https://github.com/melexis/i2c-stick/archive/melexis-i2c-stick-py-V'+version+'.tar.gz', + packages=find_namespace_packages(include=['mynamespace.*']), + classifiers=[ + # complete classifier list: http://pypi.python.org/pypi?%3Aaction=list_classifiers + 'Development Status :: 5 - Production/Stable', + 'Intended Audience :: Developers', + 'License :: OSI Approved :: Apache Software License', + 'Operating System :: Microsoft :: Windows', + 'Operating System :: POSIX', + 'Programming Language :: Python', + 'Programming Language :: Python :: 3', + 'Programming Language :: Python :: 3.4', + 'Programming Language :: Python :: 3.5', + 'Programming Language :: Python :: 3.6', + 'Programming Language :: Python :: 3.7', + 'Programming Language :: Python :: 3.8', + 'Programming Language :: Python :: 3.9', + 'Programming Language :: Python :: 3.10', + 'Topic :: Utilities', + ], +) From 00780600367b49cc2f2ff2c39012b3fce96ba1b6 Mon Sep 17 00:00:00 2001 From: Karel Vanroye Date: Fri, 19 May 2023 12:03:14 -0700 Subject: [PATCH 002/112] Initial commit for python package --- .github/workflows/python-publish.yml | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/.github/workflows/python-publish.yml b/.github/workflows/python-publish.yml index ebdc414..7fc7ace 100644 --- a/.github/workflows/python-publish.yml +++ b/.github/workflows/python-publish.yml @@ -3,9 +3,20 @@ name: Upload Python Package +# on: +# release: +# types: [created] + + on: - release: - types: [created] + # Runs on pushes targeting the default branch + push: + branches: ["main"] + + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + + jobs: deploy: From 1156badbd622400add428840ac80175c889617dc Mon Sep 17 00:00:00 2001 From: Karel Vanroye Date: Fri, 19 May 2023 12:06:58 -0700 Subject: [PATCH 003/112] workflow #1 --- .github/workflows/python-publish.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/python-publish.yml b/.github/workflows/python-publish.yml index 7fc7ace..35602c7 100644 --- a/.github/workflows/python-publish.yml +++ b/.github/workflows/python-publish.yml @@ -38,5 +38,6 @@ jobs: TWINE_USERNAME: ${{ secrets.PYPI_USERNAME }} TWINE_PASSWORD: ${{ secrets.PYPI_PASSWORD }} run: | + find -type f python setup.py sdist bdist_wheel twine upload dist/* From 90fed439c5fa7ab9c73accc6a57199be660f022e Mon Sep 17 00:00:00 2001 From: Karel Vanroye Date: Fri, 19 May 2023 12:08:45 -0700 Subject: [PATCH 004/112] workflow #2 --- .github/workflows/python-publish.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/python-publish.yml b/.github/workflows/python-publish.yml index 35602c7..3d9094d 100644 --- a/.github/workflows/python-publish.yml +++ b/.github/workflows/python-publish.yml @@ -39,5 +39,7 @@ jobs: TWINE_PASSWORD: ${{ secrets.PYPI_PASSWORD }} run: | find -type f + cd i2c-stick-py + pwd python setup.py sdist bdist_wheel twine upload dist/* From 130aed99c468b40b061ea68a96174a4f5a769999 Mon Sep 17 00:00:00 2001 From: Karel Vanroye Date: Fri, 19 May 2023 12:16:29 -0700 Subject: [PATCH 005/112] workflow #3 --- .github/workflows/python-publish.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/python-publish.yml b/.github/workflows/python-publish.yml index 3d9094d..9572d0e 100644 --- a/.github/workflows/python-publish.yml +++ b/.github/workflows/python-publish.yml @@ -38,8 +38,6 @@ jobs: TWINE_USERNAME: ${{ secrets.PYPI_USERNAME }} TWINE_PASSWORD: ${{ secrets.PYPI_PASSWORD }} run: | - find -type f cd i2c-stick-py - pwd python setup.py sdist bdist_wheel twine upload dist/* From 90c3ff4f7b51625042fbdb40c5652f13e345329e Mon Sep 17 00:00:00 2001 From: Karel Vanroye Date: Fri, 19 May 2023 12:17:31 -0700 Subject: [PATCH 006/112] workflow #4 --- i2c-stick-py/setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i2c-stick-py/setup.py b/i2c-stick-py/setup.py index 79bfab3..54c5e29 100644 --- a/i2c-stick-py/setup.py +++ b/i2c-stick-py/setup.py @@ -4,7 +4,7 @@ from setuptools import find_namespace_packages -version='0.1.0' +version='0.1.1' requires = ['bincopy>=17.14.5', 'pyserial>=3.5', From 21d302ee847f01652a86345c73cbc3488c5c4f49 Mon Sep 17 00:00:00 2001 From: Karel Vanroye Date: Fri, 19 May 2023 12:26:09 -0700 Subject: [PATCH 007/112] workflow #5 --- .github/workflows/python-publish.yml | 19 +++++++++---------- i2c-stick-py/setup.py | 1 - 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/.github/workflows/python-publish.yml b/.github/workflows/python-publish.yml index 9572d0e..eacab5c 100644 --- a/.github/workflows/python-publish.yml +++ b/.github/workflows/python-publish.yml @@ -3,19 +3,18 @@ name: Upload Python Package -# on: -# release: -# types: [created] - - on: - # Runs on pushes targeting the default branch - push: - branches: ["main"] + release: + types: [created] - # Allows you to run this workflow manually from the Actions tab - workflow_dispatch: +# on: +# # Runs on pushes targeting the default branch +# push: +# branches: ["main"] + +# # Allows you to run this workflow manually from the Actions tab +# workflow_dispatch: jobs: diff --git a/i2c-stick-py/setup.py b/i2c-stick-py/setup.py index 54c5e29..910a49f 100644 --- a/i2c-stick-py/setup.py +++ b/i2c-stick-py/setup.py @@ -28,7 +28,6 @@ license='Apache License, Version 2.0', install_requires=requires, url = 'https://github.com/melexis/i2c-stick', # Provide either the link to your github or to your website - download_url = 'https://github.com/melexis/i2c-stick/archive/melexis-i2c-stick-py-V'+version+'.tar.gz', packages=find_namespace_packages(include=['mynamespace.*']), classifiers=[ # complete classifier list: http://pypi.python.org/pypi?%3Aaction=list_classifiers From dd3f29b4b408b1edaff3fb92a702bf5e613eb061 Mon Sep 17 00:00:00 2001 From: Karel Vanroye Date: Fri, 19 May 2023 14:47:30 -0700 Subject: [PATCH 008/112] workflow #7 --- i2c-stick-py/.gitignore | 8 ++++++++ i2c-stick-py/setup.py | 3 ++- 2 files changed, 10 insertions(+), 1 deletion(-) create mode 100644 i2c-stick-py/.gitignore diff --git a/i2c-stick-py/.gitignore b/i2c-stick-py/.gitignore new file mode 100644 index 0000000..d539c79 --- /dev/null +++ b/i2c-stick-py/.gitignore @@ -0,0 +1,8 @@ +*.pyc +.cache +__pycache__/ +.idea +*env +*bak +*~ +*.egg-info \ No newline at end of file diff --git a/i2c-stick-py/setup.py b/i2c-stick-py/setup.py index 910a49f..76caa54 100644 --- a/i2c-stick-py/setup.py +++ b/i2c-stick-py/setup.py @@ -4,7 +4,7 @@ from setuptools import find_namespace_packages -version='0.1.1' +version='0.1.2' requires = ['bincopy>=17.14.5', 'pyserial>=3.5', @@ -47,4 +47,5 @@ 'Programming Language :: Python :: 3.10', 'Topic :: Utilities', ], + zip_safe=False, ) From 519e0979225f97047ff6549e8102f6615db2f31f Mon Sep 17 00:00:00 2001 From: Karel Vanroye Date: Fri, 19 May 2023 15:38:37 -0700 Subject: [PATCH 009/112] workflow #8 --- .github/workflows/python-publish.yml | 2 +- i2c-stick-py/MANIFEST.in | 4 +++ i2c-stick-py/pyproject.toml | 48 ++++++++++++++++++++++++++ i2c-stick-py/requirements.txt | 18 ++++++++++ i2c-stick-py/setup.cfg | 3 -- i2c-stick-py/setup.py | 51 ---------------------------- 6 files changed, 71 insertions(+), 55 deletions(-) create mode 100644 i2c-stick-py/MANIFEST.in create mode 100644 i2c-stick-py/pyproject.toml create mode 100644 i2c-stick-py/requirements.txt delete mode 100644 i2c-stick-py/setup.cfg delete mode 100644 i2c-stick-py/setup.py diff --git a/.github/workflows/python-publish.yml b/.github/workflows/python-publish.yml index eacab5c..160882d 100644 --- a/.github/workflows/python-publish.yml +++ b/.github/workflows/python-publish.yml @@ -38,5 +38,5 @@ jobs: TWINE_PASSWORD: ${{ secrets.PYPI_PASSWORD }} run: | cd i2c-stick-py - python setup.py sdist bdist_wheel + python -m build twine upload dist/* diff --git a/i2c-stick-py/MANIFEST.in b/i2c-stick-py/MANIFEST.in new file mode 100644 index 0000000..9b4c5b5 --- /dev/null +++ b/i2c-stick-py/MANIFEST.in @@ -0,0 +1,4 @@ +# MANIFEST.in + +include *.toml +include CONTRIBUTING.md diff --git a/i2c-stick-py/pyproject.toml b/i2c-stick-py/pyproject.toml new file mode 100644 index 0000000..d5b6a55 --- /dev/null +++ b/i2c-stick-py/pyproject.toml @@ -0,0 +1,48 @@ +# pyproject.toml + +[build-system] +requires = ["setuptools>=63.2.0", "wheel"] +build-backend = "setuptools.build_meta" + +[project] +name = "melexis-i2c-stick" +version = "0.1.4" +description = "Melexis I2C Stick, python interface" +readme = "README.md" +authors = [{ name = "Karel Vanroye", email = "kva@melexis.com" }] +license = { file = "LICENSE" } +classifiers = [ + "License :: OSI Approved :: Apache Software License", + "Programming Language :: Python", + "Programming Language :: Python :: 3", +] +keywords = ["Melexis", "I2C", "sensors", "demo"] +dependencies = [ + 'bincopy>=17.14.5', + 'pyserial>=3.5', +] +requires-python = ">=3.9" + +[project.optional-dependencies] +dev = [] + +[project.urls] +Homepage = "https://github.com/melexis/i2c-stick" + +# [project.scripts] +# melexis_i2c_stick = "melexis.i2c_stick.__main__:main" + + +[tool.bumpver] +current_version = "0.1.4" +version_pattern = "MAJOR.MINOR.PATCH[PYTAGNUM]" +commit_message = "bump version {old_version} -> {new_version}" +commit = false +tag = false +push = false + +[tool.bumpver.file_patterns] +"pyproject.toml" = [ + 'version = "{version}"', +] + diff --git a/i2c-stick-py/requirements.txt b/i2c-stick-py/requirements.txt new file mode 100644 index 0000000..2af993f --- /dev/null +++ b/i2c-stick-py/requirements.txt @@ -0,0 +1,18 @@ +# +# This file is autogenerated by pip-compile with Python 3.10 +# by the following command: +# +# pip-compile +# +argparse-addons==0.12.0 + # via bincopy +bincopy==17.14.5 + # via melexis-i2c-stick (pyproject.toml) +humanfriendly==10.0 + # via bincopy +pyelftools==0.29 + # via bincopy +pyreadline3==3.4.1 + # via humanfriendly +pyserial==3.5 + # via melexis-i2c-stick (pyproject.toml) diff --git a/i2c-stick-py/setup.cfg b/i2c-stick-py/setup.cfg deleted file mode 100644 index d85a638..0000000 --- a/i2c-stick-py/setup.cfg +++ /dev/null @@ -1,3 +0,0 @@ -# Inside of setup.cfg -[metadata] -description-file = README.md diff --git a/i2c-stick-py/setup.py b/i2c-stick-py/setup.py deleted file mode 100644 index 76caa54..0000000 --- a/i2c-stick-py/setup.py +++ /dev/null @@ -1,51 +0,0 @@ -from setuptools import setup -import sys -import platform -from setuptools import find_namespace_packages - - -version='0.1.2' - -requires = ['bincopy>=17.14.5', - 'pyserial>=3.5', - ] - -with open("README.md", "r") as fh: - long_description = fh.read() - -# This is a `native namespace package` -# -# See more info here: -# https://packaging.python.org/en/latest/guides/packaging-namespace-packages/#native-namespace-packages -# - -setup( - name='melexis-i2c-stick', - version=version, - description='Python package for I2C Stick', - long_description=long_description, - long_description_content_type="text/markdown", - license='Apache License, Version 2.0', - install_requires=requires, - url = 'https://github.com/melexis/i2c-stick', # Provide either the link to your github or to your website - packages=find_namespace_packages(include=['mynamespace.*']), - classifiers=[ - # complete classifier list: http://pypi.python.org/pypi?%3Aaction=list_classifiers - 'Development Status :: 5 - Production/Stable', - 'Intended Audience :: Developers', - 'License :: OSI Approved :: Apache Software License', - 'Operating System :: Microsoft :: Windows', - 'Operating System :: POSIX', - 'Programming Language :: Python', - 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.4', - 'Programming Language :: Python :: 3.5', - 'Programming Language :: Python :: 3.6', - 'Programming Language :: Python :: 3.7', - 'Programming Language :: Python :: 3.8', - 'Programming Language :: Python :: 3.9', - 'Programming Language :: Python :: 3.10', - 'Topic :: Utilities', - ], - zip_safe=False, -) From 421d8a74a3c578208b21e8c5615e204e7a925497 Mon Sep 17 00:00:00 2001 From: Karel Vanroye Date: Fri, 19 May 2023 15:40:47 -0700 Subject: [PATCH 010/112] workflow #9 --- .github/workflows/python-publish.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/python-publish.yml b/.github/workflows/python-publish.yml index 160882d..99cf524 100644 --- a/.github/workflows/python-publish.yml +++ b/.github/workflows/python-publish.yml @@ -31,7 +31,7 @@ jobs: - name: Install dependencies run: | python -m pip install --upgrade pip - pip install setuptools wheel twine + pip install pip-tools twine - name: Build and publish env: TWINE_USERNAME: ${{ secrets.PYPI_USERNAME }} From 50cb174eefae53080a99b4f586f96f99b08a6b15 Mon Sep 17 00:00:00 2001 From: Karel Vanroye Date: Fri, 19 May 2023 15:48:31 -0700 Subject: [PATCH 011/112] workflow #10 --- i2c-stick-py/LICENSE | 2 +- i2c-stick-py/pyproject.toml | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/i2c-stick-py/LICENSE b/i2c-stick-py/LICENSE index 784d536..7b05b13 100644 --- a/i2c-stick-py/LICENSE +++ b/i2c-stick-py/LICENSE @@ -1,4 +1,4 @@ - Copyright 2020 Melexis + Copyright 2023 Melexis Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/i2c-stick-py/pyproject.toml b/i2c-stick-py/pyproject.toml index d5b6a55..a15aff1 100644 --- a/i2c-stick-py/pyproject.toml +++ b/i2c-stick-py/pyproject.toml @@ -1,5 +1,7 @@ # pyproject.toml +# Learn more about package building configurations: https://realpython.com/pypi-publish-python-package/ + [build-system] requires = ["setuptools>=63.2.0", "wheel"] build-backend = "setuptools.build_meta" From 80aaf6c1d81a77623eac52128bc580e331420b4b Mon Sep 17 00:00:00 2001 From: Karel Vanroye Date: Fri, 19 May 2023 16:25:24 -0700 Subject: [PATCH 012/112] workflow #11 --- i2c-stick-py/pyproject.toml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/i2c-stick-py/pyproject.toml b/i2c-stick-py/pyproject.toml index a15aff1..e2eeb80 100644 --- a/i2c-stick-py/pyproject.toml +++ b/i2c-stick-py/pyproject.toml @@ -8,7 +8,7 @@ build-backend = "setuptools.build_meta" [project] name = "melexis-i2c-stick" -version = "0.1.4" +version = "0.1.5" description = "Melexis I2C Stick, python interface" readme = "README.md" authors = [{ name = "Karel Vanroye", email = "kva@melexis.com" }] @@ -23,7 +23,7 @@ dependencies = [ 'bincopy>=17.14.5', 'pyserial>=3.5', ] -requires-python = ">=3.9" +requires-python = ">=3.3" [project.optional-dependencies] dev = [] @@ -36,7 +36,7 @@ Homepage = "https://github.com/melexis/i2c-stick" [tool.bumpver] -current_version = "0.1.4" +current_version = "0.1.5" version_pattern = "MAJOR.MINOR.PATCH[PYTAGNUM]" commit_message = "bump version {old_version} -> {new_version}" commit = false From 18af4dade8d75fd5adcebd8494fe66c85e8d2450 Mon Sep 17 00:00:00 2001 From: Karel Vanroye Date: Tue, 23 May 2023 15:00:04 -0700 Subject: [PATCH 013/112] patch "fv" command end of line in return + update doc + add several commands to the I2CStick class --- doc/03_serial_interface_commands.md | 16 +- i2c-stick-arduino/i2c_stick_cmd.cpp | 2 +- i2c-stick-arduino/i2c_stick_fw_config.h | 2 +- i2c-stick-py/README.md | 3 +- i2c-stick-py/melexis/i2c_stick/I2CStick.py | 170 ++++++++++++++++++- i2c-stick-py/melexis/i2c_stick/MemoryFile.py | 73 +++++--- i2c-stick-py/melexis/i2c_stick/__main__.py | 7 + i2c-stick-py/pyproject.toml | 8 +- 8 files changed, 238 insertions(+), 43 deletions(-) create mode 100644 i2c-stick-py/melexis/i2c_stick/__main__.py diff --git a/doc/03_serial_interface_commands.md b/doc/03_serial_interface_commands.md index 2e37868..e740a44 100644 --- a/doc/03_serial_interface_commands.md +++ b/doc/03_serial_interface_commands.md @@ -299,10 +299,10 @@ Meaning: The sensor at slave address 3A has new data. Read the memory content of the selected sensor. Format: `mr::
` + `LF` -or -Format: `mr:` + `sa` + `:
` + `LF` -or -Format: `mr:` + `sa` + `:
,` + `LF` +or +Format: `mr:` + `sa` + `:
` + `LF` +or +Format: `mr:` + `sa` + `:
,` + `LF` Note: `
` and `` are in hex format with 4 characters (always) @@ -318,10 +318,10 @@ receive: `mr:3A:2400,10,01,0003,DATA,EF4A,3480` + `LF` Write the memory content of the selected sensor. Format: `mw::
,` + `LF` -or -Format: `mr:` + `sa` + `:
,` + `LF` -or -Format: `mr:` + `sa` + `:
,,,..` + `LF` +or +Format: `mr:` + `sa` + `:
,` + `LF` +or +Format: `mr:` + `sa` + `:
,,,..` + `LF` Note: `
` and `` are in hex format with 4 characters (always) diff --git a/i2c-stick-arduino/i2c_stick_cmd.cpp b/i2c-stick-arduino/i2c_stick_cmd.cpp index d9ba3bb..c76a81f 100644 --- a/i2c-stick-arduino/i2c_stick_cmd.cpp +++ b/i2c-stick-arduino/i2c_stick_cmd.cpp @@ -299,7 +299,7 @@ handle_cmd(uint8_t channel_mask, const char *cmd) if (!strncmp(this_cmd, cmd, strlen(this_cmd))) { char buf[16]; memset(buf, 0, sizeof(buf)); - send_answer_chunk(channel_mask, "fv:" FW_VERSION, 0); + send_answer_chunk(channel_mask, "fv:" FW_VERSION, 1); return NULL; } diff --git a/i2c-stick-arduino/i2c_stick_fw_config.h b/i2c-stick-arduino/i2c_stick_fw_config.h index 2090a55..edf88c8 100644 --- a/i2c-stick-arduino/i2c_stick_fw_config.h +++ b/i2c-stick-arduino/i2c_stick_fw_config.h @@ -4,7 +4,7 @@ // FW Configuration // **************** -#define FW_VERSION "V1.3.0" +#define FW_VERSION "V1.3.1" // enable/disable modules diff --git a/i2c-stick-py/README.md b/i2c-stick-py/README.md index c21ac64..0716553 100644 --- a/i2c-stick-py/README.md +++ b/i2c-stick-py/README.md @@ -1,7 +1,8 @@ -# melexis-i2c-stick-py +# melexis-i2c-stick Python interface for I2C Stick, it runs on the host computer to communicate with the I2C Stick over the UART. + ## Getting started. todo... \ No newline at end of file diff --git a/i2c-stick-py/melexis/i2c_stick/I2CStick.py b/i2c-stick-py/melexis/i2c_stick/I2CStick.py index 165fbfa..2a5fc54 100644 --- a/i2c-stick-py/melexis/i2c_stick/I2CStick.py +++ b/i2c-stick-py/melexis/i2c_stick/I2CStick.py @@ -49,14 +49,176 @@ def trigger_continuous_mode(self): self.ser.write(b';') self.ser.readline().decode('utf-8').rstrip() # read a '\n' terminated line - def set_pwm(self, pin, pwm): - self.ser.write(bytes('pwm:{}:{}\n'.format(pin, pwm), 'utf-8')) - return self.ser.readline().decode('utf-8').rstrip() # read a '\n' terminated line - def run_cmd(self, cmd): self.ser.write(bytes(cmd+"\n", 'utf-8')) return self.ser.readline().decode('utf-8').rstrip() # read a '\n' terminated line + def pwm(self, pin, pwm): + a = self.run_cmd("pwm:{}:{}".format(pin, pwm)) + return a + + def sn(self, sa): + a = self.run_cmd("sn:{:02X}".format(sa)) + a = a.split(":") + if a[0] != "sn": + return None + if a[1] != "{:02X}".format(sa): + return None + return a[2] + + + def mr(self, sa, address, count): + a = self.run_cmd("mr:{:02X}:{:04X},{:04X}".format(sa, address, count)) + a = a.split(":") + if a[0] != "mr": + return None + if a[1] != "{:02X}".format(sa): + return None + (addr, bits_in_data, address_increments, address_count, d, data) = a[2].split(',', 5) + if int(addr, 16) != address: + return None + if d != 'DATA': + return None + addr = int(addr, 16) + bits_in_data = int(bits_in_data, 16) + address_increments = int(address_increments, 16) + address_count = int(address_count, 16) + bytes_per_address = int(bits_in_data / 8 / address_increments) + result = {} + result['sa'] = sa + result['address'] = addr + result['bits_in_data'] = bits_in_data + result['address_increments'] = address_increments + result['address_count'] = address_count + result['bytes_per_address'] = bytes_per_address + result['data'] = [int(x, 16) for x in data.split(',')] + + return result + + + def mw(self, sa, address, data): + if type(data) == list: + data_str = ",".join(["{:04X}".format(x) for x in data]) + else: + data_str = "{:04X}".format(data) + a = self.run_cmd("mw:{:02X}:{:04X},{}".format(sa, address, data_str)) + a = a.split(":") + if a[0] != "mw": + return None + if a[1] != "{:02X}".format(sa): + return None + return a[2] + + + def mv(self, sa): + a = self.run_cmd("mv:{:02X}".format(sa)) + a = a.split(":") + if a[0] != "mv": + return None + if a[1] != "{:02X}".format(sa): + return None + result = {} + result['time_ms'] = int(a[2]) + result['values'] = [float(x) for x in a[3].split(',')] + return result + + def mlx(self): + result = [] + timeout_old = self.ser.timeout + self.ser.timeout = 0.25 + + a = self.run_cmd("mlx") + t = 0 + while t < 0.1: + a = a.split(":") + if a[0] != "mlx": + self.ser.timeout = timeout_old + return None + result.append(a[1]) + start = time.time() + a = self.ser.readline().decode('utf-8').rstrip() # read a '\n' terminated line + t = time.time() - start + + self.ser.timeout = timeout_old + + return result + + + def fv(self): + a = self.run_cmd("fv") + a = a.split(":") + if a[0] != "fv": + return None + return a[1] + + + def bi(self): + a = self.run_cmd("bi") + a = a.split(":") + if a[0] != "bi": + return None + return a[1] + + + def ls(self): + result = [] + timeout_old = self.ser.timeout + self.ser.timeout = 0.25 + + a = self.run_cmd("ls") + t = 0 + while t < 0.1: + a = a.split(":") + if a[0] == "ls": + if len(a) < 3: + result.append(a[1]) + else: + item = {} + item['sa'] = int(a[1], 16) + a = a[2].split(',') + item['drv'] = int(a[0], 16) + item['raw'] = int(a[1], 16) + item['disabled'] = int(a[2], 16) + item['product'] = a[3] + result.append(item) + start = time.time() + a = self.ser.readline().decode('utf-8').rstrip() # read a '\n' terminated line + t = time.time() - start + + self.ser.timeout = timeout_old + + return result + + + def scan(self): + result = [] + timeout_old = self.ser.timeout + self.ser.timeout = 0.25 + + a = self.run_cmd("scan") + t = 0 + while t < 0.1: + a = a.split(":") + if a[0] == "scan": + if len(a) < 3: + result.append(a[1]) + else: + item = {} + item['sa'] = int(a[1], 16) + a = a[2].split(',') + item['drv'] = int(a[0], 16) + item['raw'] = int(a[1], 16) + item['disabled'] = int(a[2], 16) + item['product'] = a[3] + result.append(item) + start = time.time() + a = self.ser.readline().decode('utf-8').rstrip() # read a '\n' terminated line + t = time.time() - start + + self.ser.timeout = timeout_old + + return result + if (__name__ == '__main__'): mis = I2CStick("COM154") diff --git a/i2c-stick-py/melexis/i2c_stick/MemoryFile.py b/i2c-stick-py/melexis/i2c_stick/MemoryFile.py index 9e54258..83628eb 100644 --- a/i2c-stick-py/melexis/i2c_stick/MemoryFile.py +++ b/i2c-stick-py/melexis/i2c_stick/MemoryFile.py @@ -4,14 +4,23 @@ # goal is to extend the functionality and update the default creation parameter of a BinFile object. class MemoryFile(bincopy.BinFile): - def __init__(self, filenames=None, overwrite=True, header_encoding='utf-8'): + def __init__(self, filenames=None, overwrite=True, header_encoding='utf-8', bytes_per_address=2): super().__init__(filenames=filenames, overwrite=overwrite, header_encoding=header_encoding) + ''' + note this parameter 'bytes_per_address' is not the same as the bincopy's 'word_size_bits'. + That parameter ('word_size_bits') would create hex files which are not readable by all other tools out there to read a hex file. + Instead, here we internally use an address which links one address to one single byte. + So for many melexis products this means the address you find in the hex-file is double of the actual address to be used when writing. + bytes_per_address aims to ease that process, however when using other libraries to parse the hexfiles, one have to understand that the address requires to be divided by two. + ''' + self.bytes_per_address = bytes_per_address @staticmethod - def read_evb_bin_file(evb_bin_file, at_address=0x2400): - # EVB BIN file format is little-endian, while bin_copy; the hex file package expects big-endian! + def read_evb90614_32_40_41_bin_file(evb_bin_file, at_address): + # EVB90614, EVB90632, EVB90640-41 BIN file format is little-endian, while bin_copy; the hex file package expects big-endian! # so here we do the trick with unpack/pack! + self.bytes_per_address = 2 # force 2 bytes per address for MLX90632! with open(evb_bin_file, mode='rb') as file: # b is important -> binary fileContent = file.read() @@ -21,36 +30,46 @@ def read_evb_bin_file(evb_bin_file, at_address=0x2400): bin_data = struct.pack(fmt_out, *data) bin_file = MemoryFile() - bin_file.add_binary(bin_data, address=at_address, overwrite=True) + bin_file.add_binary(bin_data, address=at_address*self.bytes_per_address, overwrite=True) return bin_file def add_32(self, address, int_data): + if type(int_data) is list: + byte_array = struct.pack('>{}L'.format(len(int_data)), *int_data) + else: + byte_array = struct.pack('>L', int_data) + self.add_binary(byte_array, address=address, overwrite=True) + + + def add_32s(self, address, int_data): + if type(int_data) is list: + byte_array = struct.pack('>{}l'.format(len(int_data)), *int_data) + else: + byte_array = struct.pack('>l', int_data) + self.add_binary(byte_array, address=address, overwrite=True) + + + def add_32_swapped(self, address, int_data): if type(int_data) is list: byte_array = struct.pack('>{}L'.format(len(int_data)), *int_data) else: byte_array = struct.pack('>L', int_data) # silly mistake for 90632 in the eeprom map... LWORD is before HWORD for i in range(0, len(byte_array), 4): - self.add_binary(byte_array[i+2:i+4], address=address, overwrite=True) - self.add_binary(byte_array[i+0:i+2], address=address+1, overwrite=True) - # - # for new design use this: - # self.add_binary(byte_array, address=address, overwrite=True) + self.add_binary(byte_array[i+2:i+4], address=address*self.bytes_per_address, overwrite=True) + self.add_binary(byte_array[i+0:i+2], address=(address+1)*self.bytes_per_address, overwrite=True) - def add_32s(self, address, int_data): + def add_32s_swapped(self, address, int_data): if type(int_data) is list: byte_array = struct.pack('>{}l'.format(len(int_data)), *int_data) else: byte_array = struct.pack('>l', int_data) # silly mistake for 90632 in the eeprom map... LWORD is before HWORD for i in range(0, len(byte_array), 4): - self.add_binary(byte_array[i+2:i+4], address=address, overwrite=True) - self.add_binary(byte_array[i+0:i+2], address=address+1, overwrite=True) - # - # for new design use this: - # self.add_binary(byte_array, address=address, overwrite=True) + self.add_binary(byte_array[i+2:i+4], address=address*self.bytes_per_address, overwrite=True) + self.add_binary(byte_array[i+0:i+2], address=(address+1)*self.bytes_per_address, overwrite=True) def add_16(self, address, int_data): @@ -58,7 +77,7 @@ def add_16(self, address, int_data): byte_array = struct.pack('>{}H'.format(len(int_data)), *int_data) else: byte_array = struct.pack('>H', int_data) - self.add_binary(byte_array, address=address, overwrite=True) + self.add_binary(byte_array, address=address*self.bytes_per_address, overwrite=True) def add_16s(self, address, int_data): @@ -66,17 +85,19 @@ def add_16s(self, address, int_data): byte_array = struct.pack('>{}h'.format(len(int_data)), *int_data) else: byte_array = struct.pack('>h', int_data) - self.add_binary(byte_array, address=address, overwrite=True) + self.add_binary(byte_array, address=address*self.bytes_per_address, overwrite=True) - def write_evb_bin_file(self, evb_bin_file_name = "evb90632.bin"): + def write_evb90614_32_40_41_bin_file(self, address, count, evb_bin_file_name = "evb.bin"): if evb_bin_file_name is None: return None if not evb_bin_file_name.endswith('.bin'): evb_bin_file_name += '.bin' - bin_data_in = self.as_binary() + bin_data_in = self[address*self.bytes_per_address:(address+count)*self.bytes_per_address].as_binary() + if len(bin_data_in) < (count*self.bytes_per_address): + bin_data_in.append(bytearray([255])*((count*self.bytes_per_address)-len(bin_data_in))) fmt_in = ">{:d}H".format (int(len(bin_data_in)/2)) fmt_out = "<{:d}H".format (int(len(bin_data_in)/2)) @@ -89,7 +110,7 @@ def write_evb_bin_file(self, evb_bin_file_name = "evb90632.bin"): return evb_bin_file_name - def write_hex_file(self, hex_file_name = "evb90632.hex"): + def write_hex_file(self, hex_file_name = "memory_file.hex"): if hex_file_name is None: return self.as_ihex() @@ -105,8 +126,12 @@ def write_hex_file(self, hex_file_name = "evb90632.hex"): def get_address_data_pairs(self): pairs = [] for seg in self.segments: - for addr in range(int((seg.maximum_address-seg.minimum_address) / seg._word_size_bytes)): - addr += int(seg.minimum_address / seg._word_size_bytes) - pairs.append ((addr, self[addr])) + for addr in range(0, int((seg.maximum_address-seg.minimum_address) / seg._word_size_bytes), self.bytes_per_address): + addr += int(seg.minimum_address / seg._word_size_bytes) + data = 0 + for i in range(self.bytes_per_address): + data <<= 8 + data += (int(self[addr+i])) + + pairs.append ((int(addr/self.bytes_per_address), data)) return pairs - diff --git a/i2c-stick-py/melexis/i2c_stick/__main__.py b/i2c-stick-py/melexis/i2c_stick/__main__.py new file mode 100644 index 0000000..a0534b3 --- /dev/null +++ b/i2c-stick-py/melexis/i2c_stick/__main__.py @@ -0,0 +1,7 @@ +def main(): + print ("Melexis I2C Stick") + print ("here comes the command line interface program") + + +if __name__ == '__main__': + main() diff --git a/i2c-stick-py/pyproject.toml b/i2c-stick-py/pyproject.toml index e2eeb80..cd970bd 100644 --- a/i2c-stick-py/pyproject.toml +++ b/i2c-stick-py/pyproject.toml @@ -8,7 +8,7 @@ build-backend = "setuptools.build_meta" [project] name = "melexis-i2c-stick" -version = "0.1.5" +version = "0.2.0" description = "Melexis I2C Stick, python interface" readme = "README.md" authors = [{ name = "Karel Vanroye", email = "kva@melexis.com" }] @@ -31,12 +31,12 @@ dev = [] [project.urls] Homepage = "https://github.com/melexis/i2c-stick" -# [project.scripts] -# melexis_i2c_stick = "melexis.i2c_stick.__main__:main" +[project.scripts] +melexis_i2c_stick = "melexis.i2c_stick.__main__:main" [tool.bumpver] -current_version = "0.1.5" +current_version = "0.2.0" version_pattern = "MAJOR.MINOR.PATCH[PYTAGNUM]" commit_message = "bump version {old_version} -> {new_version}" commit = false From b912ee0523bbf82b53f34deff37d521ea6017a8c Mon Sep 17 00:00:00 2001 From: Karel Vanroye Date: Wed, 24 May 2023 08:46:20 -0700 Subject: [PATCH 014/112] update doc + python: adding commands to I2CStick class --- doc/03_serial_interface_commands.md | 49 +++++++ i2c-stick-py/melexis/i2c_stick/I2CStick.py | 152 +++++++++++++++++---- i2c-stick-py/pyproject.toml | 4 +- 3 files changed, 175 insertions(+), 30 deletions(-) diff --git a/doc/03_serial_interface_commands.md b/doc/03_serial_interface_commands.md index e740a44..ac24b74 100644 --- a/doc/03_serial_interface_commands.md +++ b/doc/03_serial_interface_commands.md @@ -120,6 +120,55 @@ Meaning: read at register address 3004h from slave address 3A(hex, 7 bit), 2 byt The first byte is 0x5A, the 2nd is 0x69. +### `ch` - get Configure Host command + +Get the configuration of the host: +- the format of the communication +- the I2C frequency +- which drivers there are provided by the firmware +- The slave address assosiations with the drivers + +Send: `ch` + `LF` + +Receive: `ch:=[()]` + `LF` + +Receive example: +``` +ch:FORMAT=0(DEC) +ch:I2C_FREQ=0(100kHz) +ch:SA_DRV=5A,01,MLX90614 +ch:SA_DRV=3E,01,MLX90614 +ch:SA_DRV=33,02,MLX90640 +ch:SA_DRV=33,03,MLX90641 +ch:SA_DRV=3A,04,MLX90632 +ch:DRV=01,MLX90614 +ch:DRV=02,MLX90640 +ch:DRV=03,MLX90641 +ch:DRV=04,MLX90632 +``` + +### `+ch` - set Configure Host command + +Set the configuration of the host: +- the format of the communication +- the I2C frequency +- which drivers there are provided by the firmware +- The slave address assosiations with the drivers + +Send: `+ch:=|` + `LF` + +Receive: `+ch: []` + `LF` + +Send example: +``` ++ch:FORMAT=DEC +``` + +Receive example: +``` ++ch:OK [host-register] +``` + ### `scan` - Scan I2C bus command Scan the I2C bus and look at which slave address returns an diff --git a/i2c-stick-py/melexis/i2c_stick/I2CStick.py b/i2c-stick-py/melexis/i2c_stick/I2CStick.py index 2a5fc54..026ad5d 100644 --- a/i2c-stick-py/melexis/i2c_stick/I2CStick.py +++ b/i2c-stick-py/melexis/i2c_stick/I2CStick.py @@ -14,17 +14,63 @@ def open(self, port): self.ser.flushOutput() time.sleep(0.1) + def close(self): if self.ser is not None: self.ser.close() self.ser = None + + def run_cmd(self, cmd): + self.ser.write(bytes(cmd+"\n", 'utf-8')) + return self.ser.readline().decode('utf-8').rstrip() # read a '\n' terminated line + + + def mlx(self): + result = [] + timeout_old = self.ser.timeout + self.ser.timeout = 0.25 + + a = self.run_cmd("mlx") + t = 0 + while t < 0.1: + a = a.split(":") + if a[0] != "mlx": + self.ser.timeout = timeout_old + return None + result.append(a[1]) + start = time.time() + a = self.ser.readline().decode('utf-8').rstrip() # read a '\n' terminated line + t = time.time() - start + + self.ser.timeout = timeout_old + + return result + + + def fv(self): + a = self.run_cmd("fv") + a = a.split(":") + if a[0] != "fv": + return None + return a[1] + + + def bi(self): + a = self.run_cmd("bi") + a = a.split(":") + if a[0] != "bi": + return None + return a[1] + + def mv(self, sa): self.ser.write('mv:{:02X}'.format(sa).encode()+ b'\n') line = self.ser.readline().decode('utf-8').rstrip() # read a '\n' terminated line values = line.split(":")[-1] return [float(value) for value in values.split(",")] - + + def read_continuous_message(self): line = self.ser.readline().decode('utf-8').rstrip() # read a '\n' terminated line if line.startswith("@"): @@ -34,6 +80,7 @@ def read_continuous_message(self): return {'sa': int(values[-3], 16), 'time': int(values[-2]), 'drv': int(values[1], 16), 'mv': mv_list} return None + def stop_continuous_mode(self): self.ser.write(b'!') time.sleep(0.1) @@ -41,6 +88,7 @@ def stop_continuous_mode(self): self.ser.flushOutput() time.sleep(0.1) + def trigger_continuous_mode(self): self.ser.write(b'!') time.sleep(0.1) @@ -49,14 +97,12 @@ def trigger_continuous_mode(self): self.ser.write(b';') self.ser.readline().decode('utf-8').rstrip() # read a '\n' terminated line - def run_cmd(self, cmd): - self.ser.write(bytes(cmd+"\n", 'utf-8')) - return self.ser.readline().decode('utf-8').rstrip() # read a '\n' terminated line def pwm(self, pin, pwm): a = self.run_cmd("pwm:{}:{}".format(pin, pwm)) return a + def sn(self, sa): a = self.run_cmd("sn:{:02X}".format(sa)) a = a.split(":") @@ -122,42 +168,60 @@ def mv(self, sa): result['values'] = [float(x) for x in a[3].split(',')] return result - def mlx(self): - result = [] - timeout_old = self.ser.timeout - self.ser.timeout = 0.25 - a = self.run_cmd("mlx") - t = 0 - while t < 0.1: - a = a.split(":") - if a[0] != "mlx": - self.ser.timeout = timeout_old - return None - result.append(a[1]) - start = time.time() - a = self.ser.readline().decode('utf-8').rstrip() # read a '\n' terminated line - t = time.time() - start + def nd(self, sa): + a = self.run_cmd("nd:{:02X}".format(sa)) + a = a.split(":") + if a[0] != "nd": + return None + if a[1] != "{:02X}".format(sa): + return None + if a[2] == "FAIL": + return "FAIL:" + a[3] + return int(a[2]) - self.ser.timeout = timeout_old + def raw(self, sa): + a = self.run_cmd("raw:{:02X}".format(sa)) + a = a.split(":") + if a[0] != "raw": + return None + if a[1] != "{:02X}".format(sa): + return None + if a[2] == "FAIL": + return "FAIL:" + a[3] + result = {} + result['values'] = [int(x, 16) for x in a[2].split(',')] return result - def fv(self): - a = self.run_cmd("fv") + def raw(self, sa): + a = self.run_cmd("raw:{:02X}".format(sa)) a = a.split(":") - if a[0] != "fv": + if a[0] != "raw": return None - return a[1] + if a[1] != "{:02X}".format(sa): + return None + if a[2] == "FAIL": + return "FAIL:" + a[3] + result = {} + result['values'] = [int(x, 16) for x in a[2].split(',')] + return result - def bi(self): - a = self.run_cmd("bi") + def dis(self, sa, disable=1): + a = self.run_cmd("dis:{:02X}:{}".format(sa,disable)) a = a.split(":") - if a[0] != "bi": + if a[0] != "dis": return None - return a[1] + if a[1] != "{:02X}".format(sa): + return None + if a[2] == "FAIL": + return "FAIL:" + a[3] + result = {} + result['status'] = a[3] + result['disabled'] = int(a[2]) + return result def ls(self): @@ -220,6 +284,38 @@ def scan(self): return result + def cs(self, sa): + result = {} + timeout_old = self.ser.timeout + self.ser.timeout = 0.25 + + a = self.run_cmd("cs:{:02X}".format(sa)) + t = 0 + while t < 0.1: + a = a.split(":") + if a[0] != "cs": + self.ser.timeout = timeout_old + return None + if a[1] != "{:02X}".format(sa): + self.ser.timeout = timeout_old + return None + if a[2] == "RO": + if 'RO' not in result.keys(): + result['read_only'] = {} + a = a[3].split("=") + result['read_only'][a[0]] = a[1] + else: + a = a[2].split("=") + result[a[0]] = a[1] + start = time.time() + a = self.ser.readline().decode('utf-8').rstrip() # read a '\n' terminated line + t = time.time() - start + + self.ser.timeout = timeout_old + + return result + + if (__name__ == '__main__'): mis = I2CStick("COM154") print(mis.mv(0x3A)) diff --git a/i2c-stick-py/pyproject.toml b/i2c-stick-py/pyproject.toml index cd970bd..232b497 100644 --- a/i2c-stick-py/pyproject.toml +++ b/i2c-stick-py/pyproject.toml @@ -8,7 +8,7 @@ build-backend = "setuptools.build_meta" [project] name = "melexis-i2c-stick" -version = "0.2.0" +version = "0.2.1" description = "Melexis I2C Stick, python interface" readme = "README.md" authors = [{ name = "Karel Vanroye", email = "kva@melexis.com" }] @@ -36,7 +36,7 @@ melexis_i2c_stick = "melexis.i2c_stick.__main__:main" [tool.bumpver] -current_version = "0.2.0" +current_version = "0.2.1" version_pattern = "MAJOR.MINOR.PATCH[PYTAGNUM]" commit_message = "bump version {old_version} -> {new_version}" commit = false From eae88cf1069485f4245861841f755ea7bf6a8d6a Mon Sep 17 00:00:00 2001 From: Karel Vanroye Date: Wed, 24 May 2023 10:13:41 -0700 Subject: [PATCH 015/112] firmware: streamline value(description) format and command in response --- i2c-stick-arduino/i2c_stick_cmd.cpp | 8 ++++---- i2c-stick-arduino/i2c_stick_fw_config.h | 2 +- i2c-stick-arduino/mlx90614_cmd.cpp | 6 +++--- i2c-stick-arduino/mlx90632_cmd.cpp | 10 ++++++---- i2c-stick-arduino/mlx90640_cmd.cpp | 24 +++++++++++++++++------- i2c-stick-arduino/mlx90641_cmd.cpp | 6 +++--- 6 files changed, 34 insertions(+), 22 deletions(-) diff --git a/i2c-stick-arduino/i2c_stick_cmd.cpp b/i2c-stick-arduino/i2c_stick_cmd.cpp index c76a81f..ac72961 100644 --- a/i2c-stick-arduino/i2c_stick_cmd.cpp +++ b/i2c-stick-arduino/i2c_stick_cmd.cpp @@ -1525,7 +1525,7 @@ cmd_ch(uint8_t channel_mask, const char *input) default: value = "Unknown"; } - sprintf(buf, "%s(%d)", value, fmt); + sprintf(buf, "%d(%s)", fmt, value); send_answer_chunk(channel_mask, buf, 1); send_answer_chunk(channel_mask, "ch:I2C_FREQ=", 0); @@ -1553,7 +1553,7 @@ cmd_ch(uint8_t channel_mask, const char *input) default: value = "Unknown"; } - sprintf(buf, "%s(%d)", value, freq); + sprintf(buf, "%d(%s)", freq, value); send_answer_chunk(channel_mask, buf, 1); for (uint16_t spot=1; spot:` + `LF` Receive example: `i2c:3A:R:FF:OK` + `LF` -Meaning: +Meaning: Send: read from slave address 3A(hex, 7 bit), 1 byte. Receive: First byte is FF hex. diff --git a/i2c-stick-py/melexis/i2c_stick/I2CStick.py b/i2c-stick-py/melexis/i2c_stick/I2CStick.py index 026ad5d..0ec8d4a 100644 --- a/i2c-stick-py/melexis/i2c_stick/I2CStick.py +++ b/i2c-stick-py/melexis/i2c_stick/I2CStick.py @@ -8,7 +8,7 @@ def __init__(self, port): def open(self, port): self.ser = serial.Serial(port, 921600, timeout=5) - self.ser.write(b'!') + self.ser.write(b'!') time.sleep(0.2) self.ser.flushInput() self.ser.flushOutput() @@ -21,6 +21,33 @@ def close(self): self.ser = None + def read_continuous_message(self): + line = self.ser.readline().decode('utf-8').rstrip() # read a '\n' terminated line + if line.startswith("@"): + values = line.split(":") + if values[2] == 'mv': + mv_list = [float(v) for v in values[-1].split(",")] + return {'sa': int(values[-3], 16), 'time': int(values[-2]), 'drv': int(values[1], 16), 'mv': mv_list} + return None + + + def stop_continuous_mode(self): + self.ser.write(b'!') + time.sleep(0.1) + self.ser.flushInput() + self.ser.flushOutput() + time.sleep(0.1) + + + def trigger_continuous_mode(self): + self.ser.write(b'!') + time.sleep(0.1) + self.ser.flushInput() + self.ser.flushOutput() + self.ser.write(b';') + self.ser.readline().decode('utf-8').rstrip() # read a '\n' terminated line + + def run_cmd(self, cmd): self.ser.write(bytes(cmd+"\n", 'utf-8')) return self.ser.readline().decode('utf-8').rstrip() # read a '\n' terminated line @@ -64,176 +91,36 @@ def bi(self): return a[1] - def mv(self, sa): - self.ser.write('mv:{:02X}'.format(sa).encode()+ b'\n') - line = self.ser.readline().decode('utf-8').rstrip() # read a '\n' terminated line - values = line.split(":")[-1] - return [float(value) for value in values.split(",")] - - - def read_continuous_message(self): - line = self.ser.readline().decode('utf-8').rstrip() # read a '\n' terminated line - if line.startswith("@"): - values = line.split(":") - if values[2] == 'mv': - mv_list = [float(v) for v in values[-1].split(",")] - return {'sa': int(values[-3], 16), 'time': int(values[-2]), 'drv': int(values[1], 16), 'mv': mv_list} + def i2c_read(self, sa): return None - def stop_continuous_mode(self): - self.ser.write(b'!') - time.sleep(0.1) - self.ser.flushInput() - self.ser.flushOutput() - time.sleep(0.1) - - - def trigger_continuous_mode(self): - self.ser.write(b'!') - time.sleep(0.1) - self.ser.flushInput() - self.ser.flushOutput() - self.ser.write(b';') - self.ser.readline().decode('utf-8').rstrip() # read a '\n' terminated line - - - def pwm(self, pin, pwm): - a = self.run_cmd("pwm:{}:{}".format(pin, pwm)) - return a - - - def sn(self, sa): - a = self.run_cmd("sn:{:02X}".format(sa)) - a = a.split(":") - if a[0] != "sn": - return None - if a[1] != "{:02X}".format(sa): - return None - return a[2] - - - def mr(self, sa, address, count): - a = self.run_cmd("mr:{:02X}:{:04X},{:04X}".format(sa, address, count)) - a = a.split(":") - if a[0] != "mr": - return None - if a[1] != "{:02X}".format(sa): - return None - (addr, bits_in_data, address_increments, address_count, d, data) = a[2].split(',', 5) - if int(addr, 16) != address: - return None - if d != 'DATA': - return None - addr = int(addr, 16) - bits_in_data = int(bits_in_data, 16) - address_increments = int(address_increments, 16) - address_count = int(address_count, 16) - bytes_per_address = int(bits_in_data / 8 / address_increments) - result = {} - result['sa'] = sa - result['address'] = addr - result['bits_in_data'] = bits_in_data - result['address_increments'] = address_increments - result['address_count'] = address_count - result['bytes_per_address'] = bytes_per_address - result['data'] = [int(x, 16) for x in data.split(',')] - - return result - - - def mw(self, sa, address, data): - if type(data) == list: - data_str = ",".join(["{:04X}".format(x) for x in data]) - else: - data_str = "{:04X}".format(data) - a = self.run_cmd("mw:{:02X}:{:04X},{}".format(sa, address, data_str)) - a = a.split(":") - if a[0] != "mw": - return None - if a[1] != "{:02X}".format(sa): - return None - return a[2] - - - def mv(self, sa): - a = self.run_cmd("mv:{:02X}".format(sa)) - a = a.split(":") - if a[0] != "mv": - return None - if a[1] != "{:02X}".format(sa): - return None - result = {} - result['time_ms'] = int(a[2]) - result['values'] = [float(x) for x in a[3].split(',')] - return result - - - def nd(self, sa): - a = self.run_cmd("nd:{:02X}".format(sa)) - a = a.split(":") - if a[0] != "nd": - return None - if a[1] != "{:02X}".format(sa): - return None - if a[2] == "FAIL": - return "FAIL:" + a[3] - return int(a[2]) + def i2c_write(self, sa): + return None - def raw(self, sa): - a = self.run_cmd("raw:{:02X}".format(sa)) - a = a.split(":") - if a[0] != "raw": - return None - if a[1] != "{:02X}".format(sa): - return None - if a[2] == "FAIL": - return "FAIL:" + a[3] - result = {} - result['values'] = [int(x, 16) for x in a[2].split(',')] - return result + def i2c_addressed_read(self, sa): + return None - def raw(self, sa): - a = self.run_cmd("raw:{:02X}".format(sa)) - a = a.split(":") - if a[0] != "raw": - return None - if a[1] != "{:02X}".format(sa): - return None - if a[2] == "FAIL": - return "FAIL:" + a[3] - result = {} - result['values'] = [int(x, 16) for x in a[2].split(',')] - return result + def ch(self): + return None - def dis(self, sa, disable=1): - a = self.run_cmd("dis:{:02X}:{}".format(sa,disable)) - a = a.split(":") - if a[0] != "dis": - return None - if a[1] != "{:02X}".format(sa): - return None - if a[2] == "FAIL": - return "FAIL:" + a[3] - result = {} - result['status'] = a[3] - result['disabled'] = int(a[2]) - return result + def ch_write(self): + return None - def ls(self): + def scan(self): result = [] timeout_old = self.ser.timeout self.ser.timeout = 0.25 - a = self.run_cmd("ls") + a = self.run_cmd("scan") t = 0 while t < 0.1: a = a.split(":") - if a[0] == "ls": + if a[0] == "scan": if len(a) < 3: result.append(a[1]) else: @@ -254,16 +141,16 @@ def ls(self): return result - def scan(self): + def ls(self): result = [] timeout_old = self.ser.timeout self.ser.timeout = 0.25 - a = self.run_cmd("scan") + a = self.run_cmd("ls") t = 0 while t < 0.1: a = a.split(":") - if a[0] == "scan": + if a[0] == "ls": if len(a) < 3: result.append(a[1]) else: @@ -284,6 +171,38 @@ def scan(self): return result + def dis(self, sa, disable=1): + a = self.run_cmd("dis:{:02X}:{}".format(sa,disable)) + a = a.split(":") + if a[0] != "dis": + return None + if a[1] != "{:02X}".format(sa): + return None + if a[2] == "FAIL": + return "FAIL:" + a[3] + result = {} + result['status'] = a[3] + result['disabled'] = int(a[2]) + return result + + + def mv(self, sa): + self.ser.write('mv:{:02X}'.format(sa).encode()+ b'\n') + line = self.ser.readline().decode('utf-8').rstrip() # read a '\n' terminated line + values = line.split(":")[-1] + return [float(value) for value in values.split(",")] + + + def sn(self, sa): + a = self.run_cmd("sn:{:02X}".format(sa)) + a = a.split(":") + if a[0] != "sn": + return None + if a[1] != "{:02X}".format(sa): + return None + return a[2] + + def cs(self, sa): result = {} timeout_old = self.ser.timeout @@ -316,6 +235,99 @@ def cs(self, sa): return result + def cs_write(self, sa): + return None + + + def nd(self, sa): + a = self.run_cmd("nd:{:02X}".format(sa)) + a = a.split(":") + if a[0] != "nd": + return None + if a[1] != "{:02X}".format(sa): + return None + if a[2] == "FAIL": + return "FAIL:" + a[3] + return int(a[2]) + + + def mr(self, sa, address, count): + a = self.run_cmd("mr:{:02X}:{:04X},{:04X}".format(sa, address, count)) + a = a.split(":") + if a[0] != "mr": + return None + if a[1] != "{:02X}".format(sa): + return None + (addr, bits_in_data, address_increments, address_count, d, data) = a[2].split(',', 5) + if int(addr, 16) != address: + return None + if d != 'DATA': + return None + addr = int(addr, 16) + bits_in_data = int(bits_in_data, 16) + address_increments = int(address_increments, 16) + address_count = int(address_count, 16) + bytes_per_address = int(bits_in_data / 8 / address_increments) + result = {} + result['sa'] = sa + result['address'] = addr + result['bits_in_data'] = bits_in_data + result['address_increments'] = address_increments + result['address_count'] = address_count + result['bytes_per_address'] = bytes_per_address + result['data'] = [int(x, 16) for x in data.split(',')] + + return result + + + def mw(self, sa, address, data): + if type(data) == list: + data_str = ",".join(["{:04X}".format(x) for x in data]) + else: + data_str = "{:04X}".format(data) + a = self.run_cmd("mw:{:02X}:{:04X},{}".format(sa, address, data_str)) + a = a.split(":") + if a[0] != "mw": + return None + if a[1] != "{:02X}".format(sa): + return None + return a[2] + + + def mv(self, sa): + a = self.run_cmd("mv:{:02X}".format(sa)) + a = a.split(":") + if a[0] != "mv": + return None + if a[1] != "{:02X}".format(sa): + return None + result = {} + result['time_ms'] = int(a[2]) + result['values'] = [float(x) for x in a[3].split(',')] + return result + + + def raw(self, sa): + a = self.run_cmd("raw:{:02X}".format(sa)) + a = a.split(":") + if a[0] != "raw": + return None + if a[1] != "{:02X}".format(sa): + return None + if a[2] == "FAIL": + return "FAIL:" + a[3] + result = {} + result['values'] = [int(x, 16) for x in a[2].split(',')] + return result + + + def pwm(self, pin, pwm): + a = self.run_cmd("pwm:{}:{}".format(pin, pwm)) + return a + + + + if (__name__ == '__main__'): mis = I2CStick("COM154") print(mis.mv(0x3A)) From 7073b542f78974de98824ab0f5a4000173ec0913 Mon Sep 17 00:00:00 2001 From: Karel Vanroye Date: Wed, 24 May 2023 13:24:45 -0700 Subject: [PATCH 017/112] python: add ch function --- i2c-stick-py/melexis/i2c_stick/I2CStick.py | 45 +++++++++++++++++++++- i2c-stick-py/pyproject.toml | 4 +- 2 files changed, 46 insertions(+), 3 deletions(-) diff --git a/i2c-stick-py/melexis/i2c_stick/I2CStick.py b/i2c-stick-py/melexis/i2c_stick/I2CStick.py index 0ec8d4a..4da50bd 100644 --- a/i2c-stick-py/melexis/i2c_stick/I2CStick.py +++ b/i2c-stick-py/melexis/i2c_stick/I2CStick.py @@ -1,5 +1,6 @@ import serial import time +import re class I2CStick: ser = None @@ -104,7 +105,49 @@ def i2c_addressed_read(self, sa): def ch(self): - return None + result = {} + timeout_old = self.ser.timeout + self.ser.timeout = 0.25 + + a = self.run_cmd("ch") + t = 0 + while t < 0.1: + a = a.split(":") + if a[0] != "ch": + self.ser.timeout = timeout_old + return None + else: + # regex ==> https://regex101.com/r/ltml2J/1 + regex = r"(?P\S+)=(?P[^\s\(\)]+)(?:\((?P\S+)\))?" + r = re.match(regex, a[1]) + item = r.groupdict() + key = item['key'] + if key not in result.keys(): + result[key] = [] + item.pop('key') + if key == "SA_DRV": + new_item = {} + sa, drv, product = item['value'].split(',') + new_item['SA'] = int(sa, 16) + new_item['DRV'] = int(drv, 16) + new_item['product'] = product + result[key].append(new_item) + elif key == "DRV": + new_item = {} + drv, product = item['value'].split(',') + new_item['DRV'] = int(drv, 16) + new_item['product'] = product + result[key].append(new_item) + else: + result[key].append(item) + + start = time.time() + a = self.ser.readline().decode('utf-8').rstrip() # read a '\n' terminated line + t = time.time() - start + + self.ser.timeout = timeout_old + + return result def ch_write(self): diff --git a/i2c-stick-py/pyproject.toml b/i2c-stick-py/pyproject.toml index 232b497..2830581 100644 --- a/i2c-stick-py/pyproject.toml +++ b/i2c-stick-py/pyproject.toml @@ -8,7 +8,7 @@ build-backend = "setuptools.build_meta" [project] name = "melexis-i2c-stick" -version = "0.2.1" +version = "0.3.0" description = "Melexis I2C Stick, python interface" readme = "README.md" authors = [{ name = "Karel Vanroye", email = "kva@melexis.com" }] @@ -36,7 +36,7 @@ melexis_i2c_stick = "melexis.i2c_stick.__main__:main" [tool.bumpver] -current_version = "0.2.1" +current_version = "0.3.0" version_pattern = "MAJOR.MINOR.PATCH[PYTAGNUM]" commit_message = "bump version {old_version} -> {new_version}" commit = false From a8b52e743137b582ebafa975097316003069cb12 Mon Sep 17 00:00:00 2001 From: Karel Vanroye Date: Wed, 24 May 2023 13:48:33 -0700 Subject: [PATCH 018/112] fix: use decimal notation in cs command --- i2c-stick-arduino/i2c_stick_dispatcher.cpp.jinja2 | 2 +- i2c-stick-arduino/mlx90632_cmd.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/i2c-stick-arduino/i2c_stick_dispatcher.cpp.jinja2 b/i2c-stick-arduino/i2c_stick_dispatcher.cpp.jinja2 index 7c48527..909c2d0 100644 --- a/i2c-stick-arduino/i2c_stick_dispatcher.cpp.jinja2 +++ b/i2c-stick-arduino/i2c_stick_dispatcher.cpp.jinja2 @@ -163,7 +163,7 @@ cmd_cs(uint8_t sa, uint8_t channel_mask, const char *input) uint8_to_hex(buf, sa); send_answer_chunk(channel_mask, buf, 0); send_answer_chunk(channel_mask, ":RAW=", 0); - uint8_to_hex(buf, raw); + itoa(raw, buf, 10); send_answer_chunk(channel_mask, buf, 1); switch(drv) diff --git a/i2c-stick-arduino/mlx90632_cmd.cpp b/i2c-stick-arduino/mlx90632_cmd.cpp index 70ebe89..f6947db 100644 --- a/i2c-stick-arduino/mlx90632_cmd.cpp +++ b/i2c-stick-arduino/mlx90632_cmd.cpp @@ -228,7 +228,7 @@ cmd_90632_cs(uint8_t sa, uint8_t channel_mask, const char *input) uint8_to_hex(buf, sa); send_answer_chunk(channel_mask, buf, 0); send_answer_chunk(channel_mask, ":RR=", 0); - uint8_to_hex(buf, rr); + itoa(rr, buf, 10); send_answer_chunk(channel_mask, buf, 1); send_answer_chunk(channel_mask, "cs:", 0); From b2257155ed3432e9df7de844a512d93f919a1c0e Mon Sep 17 00:00:00 2001 From: Karel Vanroye Date: Wed, 24 May 2023 14:45:55 -0700 Subject: [PATCH 019/112] python add cs command --- i2c-stick-py/melexis/i2c_stick/I2CStick.py | 44 ++++++++++++++++++++-- 1 file changed, 41 insertions(+), 3 deletions(-) diff --git a/i2c-stick-py/melexis/i2c_stick/I2CStick.py b/i2c-stick-py/melexis/i2c_stick/I2CStick.py index 4da50bd..4d874d4 100644 --- a/i2c-stick-py/melexis/i2c_stick/I2CStick.py +++ b/i2c-stick-py/melexis/i2c_stick/I2CStick.py @@ -262,13 +262,51 @@ def cs(self, sa): self.ser.timeout = timeout_old return None if a[2] == "RO": - if 'RO' not in result.keys(): + if 'read_only' not in result.keys(): result['read_only'] = {} a = a[3].split("=") - result['read_only'][a[0]] = a[1] + value = a[1].split(",") + for i, v in enumerate(value): + regex = r"(?P[^\s\(\)]+)(?:\((?P\S+)\))?" + new_value = re.match(regex, v).groupdict() + if (new_value['value'][:1].isdigit() or new_value['value'][:1] == '-') & (a[0] != 'SA'): + try: + new_value['value'] = int(new_value['value']) + except: + try: + new_value['value'] = float(new_value['value']) + except: + None + None + if new_value['description'] is not None: + value[i] = new_value + else: + value[i] = new_value['value'] + if (len(value) == 1): + value = value[0] + result['read_only'][a[0]] = value else: a = a[2].split("=") - result[a[0]] = a[1] + value = a[1].split(",") + for i, v in enumerate(value): + regex = r"(?P[^\s\(\)]+)(?:\((?P\S+)\))?" + new_value = re.match(regex, v).groupdict() + if (new_value['value'][:1].isdigit() or new_value['value'][:1] == '-') & (a[0] != 'SA'): + try: + new_value['value'] = int(new_value['value']) + except: + try: + new_value['value'] = float(new_value['value']) + except: + None + None + if new_value['description'] is not None: + value[i] = new_value + else: + value[i] = new_value['value'] + if (len(value) == 1): + value = value[0] + result[a[0]] = value start = time.time() a = self.ser.readline().decode('utf-8').rstrip() # read a '\n' terminated line t = time.time() - start From d52f92cad055bc9850cb79b2d148b55bb3e0f839 Mon Sep 17 00:00:00 2001 From: Karel Vanroye Date: Tue, 30 May 2023 14:50:36 -0700 Subject: [PATCH 020/112] * FW: add timestamp on raw command * FW: 90632 add MEAS_SELECT/COUNT configuration * PY: add cs_write command --- i2c-stick-arduino/i2c_stick_cmd.cpp | 4 + i2c-stick-arduino/i2c_stick_fw_config.h | 8 +- i2c-stick-arduino/mlx90632_advanced.h | 4 +- i2c-stick-arduino/mlx90632_api.cpp | 3 + i2c-stick-arduino/mlx90632_cmd.cpp | 123 ++++++++++++++++++--- i2c-stick-py/melexis/i2c_stick/I2CStick.py | 18 ++- 6 files changed, 135 insertions(+), 25 deletions(-) diff --git a/i2c-stick-arduino/i2c_stick_cmd.cpp b/i2c-stick-arduino/i2c_stick_cmd.cpp index ac72961..e946567 100644 --- a/i2c-stick-arduino/i2c_stick_cmd.cpp +++ b/i2c-stick-arduino/i2c_stick_cmd.cpp @@ -1108,6 +1108,10 @@ handle_cmd_raw(uint8_t sa, uint8_t channel_mask) send_answer_chunk(channel_mask, "FAIL: no device driver assigned", 1); return; } + uint32_t time_stamp = hal_get_millis(); // update timestamp when data is available. + uint32_to_dec(buf, time_stamp, 8); + send_answer_chunk(channel_mask, buf, 0); + send_answer_chunk(channel_mask, ":", 0); if (error_message != NULL) { diff --git a/i2c-stick-arduino/i2c_stick_fw_config.h b/i2c-stick-arduino/i2c_stick_fw_config.h index 1b9e5d2..bd9a7b1 100644 --- a/i2c-stick-arduino/i2c_stick_fw_config.h +++ b/i2c-stick-arduino/i2c_stick_fw_config.h @@ -4,17 +4,11 @@ // FW Configuration // **************** -#define FW_VERSION "V1.3.2" +#define FW_VERSION "V1.3.3" // enable/disable modules // ====================== -#define DEVICE_PT100_ADS122C_ENABLE -//#undef DEVICE_PT100_ADS122C_ENABLE - -//#define DEVICE_MLX90640_TEST_ENABLE -//#undef DEVICE_MLX90640_TEST_ENABLE - //#define BUFFER_COMMAND_ENABLE #undef BUFFER_COMMAND_ENABLE diff --git a/i2c-stick-arduino/mlx90632_advanced.h b/i2c-stick-arduino/mlx90632_advanced.h index 34b8f41..6fcd7b9 100644 --- a/i2c-stick-arduino/mlx90632_advanced.h +++ b/i2c-stick-arduino/mlx90632_advanced.h @@ -163,6 +163,7 @@ extern "C" { #define MLX90632_EE_Ha 0x2481 /**< Ha customer calibration value register 16bit */ #define MLX90632_EE_Hb 0x2482 /**< Hb customer calibration value register 16bit */ +#define MLX90632_EE_MEAS_BASE 0x24E0 /* Register addresses - volatile */ #define MLX90632_REG_I2C_ADDR 0x3000 /**< Chip I2C address register */ @@ -229,7 +230,8 @@ struct Mlx90632Device struct Mlx90632AdcData adc_data_; struct Mlx90632CalibData calib_data_; uint8_t slave_address_; - + uint8_t meas_select_; + uint8_t meas_count_; }; diff --git a/i2c-stick-arduino/mlx90632_api.cpp b/i2c-stick-arduino/mlx90632_api.cpp index f2dd90f..8b104b0 100644 --- a/i2c-stick-arduino/mlx90632_api.cpp +++ b/i2c-stick-arduino/mlx90632_api.cpp @@ -254,6 +254,9 @@ _mlx90632_initialize(struct Mlx90632Device *mlx, uint8_t i2c_slave_address) { mlx->slave_address_ = i2c_slave_address; memset(&mlx->adc_data_, 0, sizeof(mlx->adc_data_)); + mlx->meas_select_ = 0; + mlx->meas_count_ = 3; + if (_mlx90632_soft_reset(mlx) < 0) { return -2; diff --git a/i2c-stick-arduino/mlx90632_cmd.cpp b/i2c-stick-arduino/mlx90632_cmd.cpp index f6947db..7e614a9 100644 --- a/i2c-stick-arduino/mlx90632_cmd.cpp +++ b/i2c-stick-arduino/mlx90632_cmd.cpp @@ -151,9 +151,16 @@ cmd_90632_nd(uint8_t sa, uint8_t *nd, char const **error_message) if (reg_status & MLX90632_STATUS_NEW_DATA) // new data bit is set! { - if (mlx->adc_data_.RAM_6_ == 0) /* first time */ + if (mlx->meas_select_ < 3) // only in normal application mode! { - if (cycle_pos == 2) // check we have a full dataset! + if (mlx->adc_data_.RAM_6_ == 0) /* first time */ + { + if (cycle_pos == 2) // check we have a full dataset! + { + mlx->adc_data_.RAM_6_ = 1; // incase there is no 'MV' there is no update, keep nd=1 in that case... + *nd = 1; + } + } else { *nd = 1; } @@ -269,6 +276,20 @@ cmd_90632_cs(uint8_t sa, uint8_t channel_mask, const char *input) send_answer_chunk(channel_mask, buf, 0); send_answer_chunk(channel_mask, p, 1); + send_answer_chunk(channel_mask, "cs:", 0); + uint8_to_hex(buf, sa); + send_answer_chunk(channel_mask, buf, 0); + send_answer_chunk(channel_mask, ":MEAS_SELECT=", 0); + itoa(mlx->meas_select_, buf, 10); + send_answer_chunk(channel_mask, buf, 1); + + send_answer_chunk(channel_mask, "cs:", 0); + uint8_to_hex(buf, sa); + send_answer_chunk(channel_mask, buf, 0); + send_answer_chunk(channel_mask, ":MEAS_COUNT=", 0); + itoa(mlx->meas_count_, buf, 10); + send_answer_chunk(channel_mask, buf, 1); + send_answer_chunk(channel_mask, "cs:", 0); uint8_to_hex(buf, sa); send_answer_chunk(channel_mask, buf, 0); @@ -488,6 +509,69 @@ cmd_90632_cs_write(uint8_t sa, uint8_t channel_mask, const char *input) return; } + var_name = "MEAS_SELECT="; + if (!strncmp(var_name, input, strlen(var_name))) + { + int16_t meas_select = atoi(input+strlen(var_name)); + send_answer_chunk(channel_mask, "+cs:", 0); + uint8_to_hex(buf, sa); + send_answer_chunk(channel_mask, buf, 0); + if ((meas_select >= 0) && (meas_select <= 31)) + { + // update REG_CONTROL value with meas_select + uint16_t reg_control; + _mlx90632_i2c_read(mlx->slave_address_, MLX90632_REG_CONTROL, ®_control); + reg_control &= ~0x01F0; /* Set meas_select bits to zero */ + reg_control |= (meas_select << 4); /* Set needed meas_select bits to one */ + _mlx90632_i2c_write(mlx->slave_address_, MLX90632_REG_CONTROL, reg_control); + + // update the host register + mlx->meas_select_ = meas_select; + mlx->meas_count_ = 0; // next time raw-command is run, it will auto-count the amount! + + // reset the new_data bits... + { + uint16_t reg_status; + _mlx90632_i2c_read(mlx->slave_address_, MLX90632_REG_STATUS, ®_status); + reg_status &= ~(MLX90632_STATUS_NEW_DATA | MLX90632_STATUS_EOC); + _mlx90632_i2c_write(mlx->slave_address_, MLX90632_REG_STATUS, reg_status); + } + + /* HALT & go back to previous mode in order to 'activate' the new MEAS_SELECT value */ + { + MLX90632_Reg_Mode mode; + _mlx90632_reg_read_mode(mlx, &mode); + _mlx90632_reg_write_mode(mlx, MLX90632_REG_MODE_HALT); + _mlx90632_reg_write_mode(mlx, mode); + } + + // report answer back to the command. + send_answer_chunk(channel_mask, ":MEAS_SELECT=OK [host&mlx-register]", 1); + } else + { + send_answer_chunk(channel_mask, ":MEAS_SELECT=FAIL; outbound", 1); + } + return; + } + + var_name = "MEAS_COUNT="; + if (!strncmp(var_name, input, strlen(var_name))) + { + int16_t meas_count = atoi(input+strlen(var_name)); + send_answer_chunk(channel_mask, "+cs:", 0); + uint8_to_hex(buf, sa); + send_answer_chunk(channel_mask, buf, 0); + if ((meas_count >= 0) && (meas_count <= 31)) + { + mlx->meas_count_ = meas_count; + send_answer_chunk(channel_mask, ":MEAS_COUNT=OK [host-register]", 1); + } else + { + send_answer_chunk(channel_mask, ":MEAS_COUNT=FAIL; outbound", 1); + } + return; + } + var_name = "SA="; if (!strncmp(var_name, input, strlen(var_name))) { @@ -728,27 +812,38 @@ cmd_90632_raw(uint8_t sa, uint16_t *raw_list, uint16_t *raw_count, char const ** _mlx90632_initialize(mlx, sa); } - if (*raw_count < 6) + if (mlx->meas_count_ == 0) + { // undefined length of the meas; let's count... + uint16_t meas; + for (uint8_t i = mlx->meas_select_; i<32; i++) + { + _mlx90632_i2c_read_block(mlx->slave_address_, MLX90632_EE_MEAS_BASE + i, &meas, 1); + if (meas == 0xFFFF) + break; + mlx->meas_count_++; + } + } + + if (*raw_count < (1 + (3 * mlx->meas_count_))) { *raw_count = 0; // input buffer not long enough, report nothing. *error_message = MLX90632_ERROR_BUFFER_TOO_SMALL; return; } - *raw_count = 6; + *raw_count = 1 + (3 * mlx->meas_count_); - int16_t e = _mlx90632_read_adc(mlx); - if (e != 0) + /* reset bit NEW_DATA and EOC */ + uint16_t cycle_pos = 0; { - *raw_count = 0; - *error_message = MLX90632_ERROR_COMMUNICATION; - return; + uint16_t reg_status; + if (_mlx90632_i2c_read(mlx->slave_address_, MLX90632_REG_STATUS, ®_status) < 0) return; + reg_status &= ~(MLX90632_STATUS_NEW_DATA | MLX90632_STATUS_EOC); + if (_mlx90632_i2c_write(mlx->slave_address_, MLX90632_REG_STATUS, reg_status) < 0) return; + cycle_pos = (reg_status & MLX90632_STATUS_CYCLE_POSITION) >> 2; } - uint16_t *pointer = (uint16_t *)&mlx->adc_data_; - for (int16_t i=0; i<6; i++) - { - raw_list[i] = pointer[i]; - } + raw_list[0] = cycle_pos; + if (_mlx90632_i2c_read_block(mlx->slave_address_, MLX90632_ADDR_RAM + 3 * mlx->meas_select_, &raw_list[1], 3 * mlx->meas_count_)) return; } diff --git a/i2c-stick-py/melexis/i2c_stick/I2CStick.py b/i2c-stick-py/melexis/i2c_stick/I2CStick.py index 4d874d4..c896246 100644 --- a/i2c-stick-py/melexis/i2c_stick/I2CStick.py +++ b/i2c-stick-py/melexis/i2c_stick/I2CStick.py @@ -316,8 +316,18 @@ def cs(self, sa): return result - def cs_write(self, sa): - return None + def cs_write(self, sa, item, value): + a = self.run_cmd("+cs:{:02X}:{}={}".format(sa, item, value)) + a = a.split(":") + # +cs:3A:MEAS_SELECT=OK [host&mlx-register]' + # '+cs:3A:FAIL; unknown variable' + if a[0] != "+cs": + return None + if a[1] != "{:02X}".format(sa): + return None + if a[2].startswith("FAIL"): + return a[2] + return a[2] def nd(self, sa): @@ -398,7 +408,9 @@ def raw(self, sa): if a[2] == "FAIL": return "FAIL:" + a[3] result = {} - result['values'] = [int(x, 16) for x in a[2].split(',')] + result = {} + result['time_ms'] = int(a[2]) + result['values'] = [int(x, 16) for x in a[3].split(',')] return result From 292f6b12b550e9edfa3df5492ec38ba44a0c6b32 Mon Sep 17 00:00:00 2001 From: Karel Vanroye Date: Tue, 30 May 2023 14:51:41 -0700 Subject: [PATCH 021/112] PY: patch version --- i2c-stick-py/pyproject.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/i2c-stick-py/pyproject.toml b/i2c-stick-py/pyproject.toml index 2830581..1ef6fa6 100644 --- a/i2c-stick-py/pyproject.toml +++ b/i2c-stick-py/pyproject.toml @@ -8,7 +8,7 @@ build-backend = "setuptools.build_meta" [project] name = "melexis-i2c-stick" -version = "0.3.0" +version = "0.3.1" description = "Melexis I2C Stick, python interface" readme = "README.md" authors = [{ name = "Karel Vanroye", email = "kva@melexis.com" }] @@ -36,7 +36,7 @@ melexis_i2c_stick = "melexis.i2c_stick.__main__:main" [tool.bumpver] -current_version = "0.3.0" +current_version = "0.3.1" version_pattern = "MAJOR.MINOR.PATCH[PYTAGNUM]" commit_message = "bump version {old_version} -> {new_version}" commit = false From 0fbd4e271910e2a8f674ac25db0b83cfdb0e44cf Mon Sep 17 00:00:00 2001 From: Karel Vanroye Date: Tue, 30 May 2023 15:38:12 -0700 Subject: [PATCH 022/112] * PY: singed raw data --- i2c-stick-py/melexis/i2c_stick/I2CStick.py | 1 + i2c-stick-py/pyproject.toml | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/i2c-stick-py/melexis/i2c_stick/I2CStick.py b/i2c-stick-py/melexis/i2c_stick/I2CStick.py index c896246..76e0d1b 100644 --- a/i2c-stick-py/melexis/i2c_stick/I2CStick.py +++ b/i2c-stick-py/melexis/i2c_stick/I2CStick.py @@ -411,6 +411,7 @@ def raw(self, sa): result = {} result['time_ms'] = int(a[2]) result['values'] = [int(x, 16) for x in a[3].split(',')] + result['values'] = [x if x < 2**15 else x - 2**16 for x in result['values']] return result diff --git a/i2c-stick-py/pyproject.toml b/i2c-stick-py/pyproject.toml index 1ef6fa6..53eb854 100644 --- a/i2c-stick-py/pyproject.toml +++ b/i2c-stick-py/pyproject.toml @@ -8,7 +8,7 @@ build-backend = "setuptools.build_meta" [project] name = "melexis-i2c-stick" -version = "0.3.1" +version = "0.3.2" description = "Melexis I2C Stick, python interface" readme = "README.md" authors = [{ name = "Karel Vanroye", email = "kva@melexis.com" }] @@ -36,7 +36,7 @@ melexis_i2c_stick = "melexis.i2c_stick.__main__:main" [tool.bumpver] -current_version = "0.3.1" +current_version = "0.3.2" version_pattern = "MAJOR.MINOR.PATCH[PYTAGNUM]" commit_message = "bump version {old_version} -> {new_version}" commit = false From 83fd6b976c1f625297a9c8f3176d92dd80f1fa25 Mon Sep 17 00:00:00 2001 From: Karel Vanroye Date: Wed, 31 May 2023 14:02:53 -0700 Subject: [PATCH 023/112] * FW: Fix extern C compilation issue --- i2c-stick-arduino/i2c_stick_arduino.h | 9 +++++---- i2c-stick-arduino/i2c_stick_fw_config.h | 2 +- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/i2c-stick-arduino/i2c_stick_arduino.h b/i2c-stick-arduino/i2c_stick_arduino.h index cad4825..01982ce 100644 --- a/i2c-stick-arduino/i2c_stick_arduino.h +++ b/i2c-stick-arduino/i2c_stick_arduino.h @@ -51,6 +51,11 @@ extern "C" { #endif +#ifdef __cplusplus +} +#endif + + // Configure QWIIC I2C Bus: // ************************ // By default use Wire @@ -73,8 +78,4 @@ extern "C" { #endif -#ifdef __cplusplus -} -#endif - #endif // __I2C_STICK_HAL_ARDUINO_H__ diff --git a/i2c-stick-arduino/i2c_stick_fw_config.h b/i2c-stick-arduino/i2c_stick_fw_config.h index bd9a7b1..984d8ee 100644 --- a/i2c-stick-arduino/i2c_stick_fw_config.h +++ b/i2c-stick-arduino/i2c_stick_fw_config.h @@ -4,7 +4,7 @@ // FW Configuration // **************** -#define FW_VERSION "V1.3.3" +#define FW_VERSION "V1.3.4" // enable/disable modules From 2764bf384c5443a81019748bf574d0b15d62bf23 Mon Sep 17 00:00:00 2001 From: Karel Vanroye Date: Wed, 31 May 2023 14:42:47 -0700 Subject: [PATCH 024/112] * FW: 90632 remove MEAS_COUNT config * FW: 90632 raw emit only last updated values * PY: update readme --- i2c-stick-arduino/i2c_stick_fw_config.h | 2 +- i2c-stick-arduino/mlx90632_advanced.h | 1 - i2c-stick-arduino/mlx90632_api.cpp | 1 - i2c-stick-arduino/mlx90632_cmd.cpp | 44 ++----------------------- i2c-stick-py/README.md | 4 +-- 5 files changed, 6 insertions(+), 46 deletions(-) diff --git a/i2c-stick-arduino/i2c_stick_fw_config.h b/i2c-stick-arduino/i2c_stick_fw_config.h index 984d8ee..e1f255b 100644 --- a/i2c-stick-arduino/i2c_stick_fw_config.h +++ b/i2c-stick-arduino/i2c_stick_fw_config.h @@ -4,7 +4,7 @@ // FW Configuration // **************** -#define FW_VERSION "V1.3.4" +#define FW_VERSION "V1.3.5" // enable/disable modules diff --git a/i2c-stick-arduino/mlx90632_advanced.h b/i2c-stick-arduino/mlx90632_advanced.h index 6fcd7b9..9035ba4 100644 --- a/i2c-stick-arduino/mlx90632_advanced.h +++ b/i2c-stick-arduino/mlx90632_advanced.h @@ -231,7 +231,6 @@ struct Mlx90632Device struct Mlx90632CalibData calib_data_; uint8_t slave_address_; uint8_t meas_select_; - uint8_t meas_count_; }; diff --git a/i2c-stick-arduino/mlx90632_api.cpp b/i2c-stick-arduino/mlx90632_api.cpp index 8b104b0..a9600cd 100644 --- a/i2c-stick-arduino/mlx90632_api.cpp +++ b/i2c-stick-arduino/mlx90632_api.cpp @@ -255,7 +255,6 @@ _mlx90632_initialize(struct Mlx90632Device *mlx, uint8_t i2c_slave_address) mlx->slave_address_ = i2c_slave_address; memset(&mlx->adc_data_, 0, sizeof(mlx->adc_data_)); mlx->meas_select_ = 0; - mlx->meas_count_ = 3; if (_mlx90632_soft_reset(mlx) < 0) { diff --git a/i2c-stick-arduino/mlx90632_cmd.cpp b/i2c-stick-arduino/mlx90632_cmd.cpp index 7e614a9..3eeacc3 100644 --- a/i2c-stick-arduino/mlx90632_cmd.cpp +++ b/i2c-stick-arduino/mlx90632_cmd.cpp @@ -283,13 +283,6 @@ cmd_90632_cs(uint8_t sa, uint8_t channel_mask, const char *input) itoa(mlx->meas_select_, buf, 10); send_answer_chunk(channel_mask, buf, 1); - send_answer_chunk(channel_mask, "cs:", 0); - uint8_to_hex(buf, sa); - send_answer_chunk(channel_mask, buf, 0); - send_answer_chunk(channel_mask, ":MEAS_COUNT=", 0); - itoa(mlx->meas_count_, buf, 10); - send_answer_chunk(channel_mask, buf, 1); - send_answer_chunk(channel_mask, "cs:", 0); uint8_to_hex(buf, sa); send_answer_chunk(channel_mask, buf, 0); @@ -527,7 +520,6 @@ cmd_90632_cs_write(uint8_t sa, uint8_t channel_mask, const char *input) // update the host register mlx->meas_select_ = meas_select; - mlx->meas_count_ = 0; // next time raw-command is run, it will auto-count the amount! // reset the new_data bits... { @@ -554,24 +546,6 @@ cmd_90632_cs_write(uint8_t sa, uint8_t channel_mask, const char *input) return; } - var_name = "MEAS_COUNT="; - if (!strncmp(var_name, input, strlen(var_name))) - { - int16_t meas_count = atoi(input+strlen(var_name)); - send_answer_chunk(channel_mask, "+cs:", 0); - uint8_to_hex(buf, sa); - send_answer_chunk(channel_mask, buf, 0); - if ((meas_count >= 0) && (meas_count <= 31)) - { - mlx->meas_count_ = meas_count; - send_answer_chunk(channel_mask, ":MEAS_COUNT=OK [host-register]", 1); - } else - { - send_answer_chunk(channel_mask, ":MEAS_COUNT=FAIL; outbound", 1); - } - return; - } - var_name = "SA="; if (!strncmp(var_name, input, strlen(var_name))) { @@ -812,25 +786,13 @@ cmd_90632_raw(uint8_t sa, uint16_t *raw_list, uint16_t *raw_count, char const ** _mlx90632_initialize(mlx, sa); } - if (mlx->meas_count_ == 0) - { // undefined length of the meas; let's count... - uint16_t meas; - for (uint8_t i = mlx->meas_select_; i<32; i++) - { - _mlx90632_i2c_read_block(mlx->slave_address_, MLX90632_EE_MEAS_BASE + i, &meas, 1); - if (meas == 0xFFFF) - break; - mlx->meas_count_++; - } - } - - if (*raw_count < (1 + (3 * mlx->meas_count_))) + if (*raw_count < (1 + 3)) { *raw_count = 0; // input buffer not long enough, report nothing. *error_message = MLX90632_ERROR_BUFFER_TOO_SMALL; return; } - *raw_count = 1 + (3 * mlx->meas_count_); + *raw_count = 1 + 3; /* reset bit NEW_DATA and EOC */ uint16_t cycle_pos = 0; @@ -843,7 +805,7 @@ cmd_90632_raw(uint8_t sa, uint16_t *raw_list, uint16_t *raw_count, char const ** } raw_list[0] = cycle_pos; - if (_mlx90632_i2c_read_block(mlx->slave_address_, MLX90632_ADDR_RAM + 3 * mlx->meas_select_, &raw_list[1], 3 * mlx->meas_count_)) return; + if (_mlx90632_i2c_read_block(mlx->slave_address_, MLX90632_ADDR_RAM + 3 * cycle_pos, &raw_list[1], 3)) return; } diff --git a/i2c-stick-py/README.md b/i2c-stick-py/README.md index 0716553..4501277 100644 --- a/i2c-stick-py/README.md +++ b/i2c-stick-py/README.md @@ -1,8 +1,8 @@ # melexis-i2c-stick -Python interface for I2C Stick, it runs on the host computer to communicate with the I2C Stick over the UART. +Python interface for I2C Stick, it runs on the host computer to communicate with the I2C Stick over the USB-UART port. ## Getting started. -todo... \ No newline at end of file +https://www.melexis.com/i2c-stick From 08e43d838dbce976fc4e1e16e712d9227b9daa3b Mon Sep 17 00:00:00 2001 From: Karel Vanroye Date: Tue, 3 Oct 2023 17:01:25 -0700 Subject: [PATCH 025/112] add txt file support + bump bincopy version to 18 --- i2c-stick-py/melexis/i2c_stick/MemoryFile.py | 46 ++++++++++++++++---- i2c-stick-py/pyproject.toml | 8 +++- i2c-stick-py/requirements.txt | 20 +-------- 3 files changed, 46 insertions(+), 28 deletions(-) diff --git a/i2c-stick-py/melexis/i2c_stick/MemoryFile.py b/i2c-stick-py/melexis/i2c_stick/MemoryFile.py index 83628eb..2813b7e 100644 --- a/i2c-stick-py/melexis/i2c_stick/MemoryFile.py +++ b/i2c-stick-py/melexis/i2c_stick/MemoryFile.py @@ -16,8 +16,24 @@ def __init__(self, filenames=None, overwrite=True, header_encoding='utf-8', byte self.bytes_per_address = bytes_per_address - @staticmethod - def read_evb90614_32_40_41_bin_file(evb_bin_file, at_address): + def read_evb90614_32_40_41_txt_file(self, txt_file, at_address): + # EVB90614, EVB90632, EVB90640-41 BIN file format is little-endian, while bin_copy; the hex file package expects big-endian! + # so here we do the trick with unpack/pack! + self.bytes_per_address = 2 # force 2 bytes per address for MLX90632! + with open(txt_file, mode='r') as file: + fileContent = file.read() + + fc = fileContent.split("\n") + fc.remove("") + data = [int(x) for x in fc] + + bin_data = struct.pack(fmt_out, *data) + + self.add_binary(bin_data, address=at_address*self.bytes_per_address, overwrite=True) + return txt_file + + + def read_evb90614_32_40_41_bin_file(self, evb_bin_file, at_address): # EVB90614, EVB90632, EVB90640-41 BIN file format is little-endian, while bin_copy; the hex file package expects big-endian! # so here we do the trick with unpack/pack! self.bytes_per_address = 2 # force 2 bytes per address for MLX90632! @@ -29,9 +45,8 @@ def read_evb90614_32_40_41_bin_file(evb_bin_file, at_address): data = list(struct.unpack(fmt_in, fileContent)) bin_data = struct.pack(fmt_out, *data) - bin_file = MemoryFile() - bin_file.add_binary(bin_data, address=at_address*self.bytes_per_address, overwrite=True) - return bin_file + self.add_binary(bin_data, address=at_address*self.bytes_per_address, overwrite=True) + return evb_bin_file def add_32(self, address, int_data): @@ -95,7 +110,7 @@ def write_evb90614_32_40_41_bin_file(self, address, count, evb_bin_file_name = " if not evb_bin_file_name.endswith('.bin'): evb_bin_file_name += '.bin' - bin_data_in = self[address*self.bytes_per_address:(address+count)*self.bytes_per_address].as_binary() + bin_data_in = self[address*self.bytes_per_address:(address+count)*self.bytes_per_address] if len(bin_data_in) < (count*self.bytes_per_address): bin_data_in.append(bytearray([255])*((count*self.bytes_per_address)-len(bin_data_in))) fmt_in = ">{:d}H".format (int(len(bin_data_in)/2)) @@ -110,6 +125,21 @@ def write_evb90614_32_40_41_bin_file(self, address, count, evb_bin_file_name = " return evb_bin_file_name + def write_evb90614_32_40_41_txt_file(self, address, count, txt_file_name = "memory.txt"): + if txt_file_name is None: + return None + + if not txt_file_name.endswith('.txt'): + txt_file_name += '.txt' + + data = self[address*self.bytes_per_address:(address+count)*self.bytes_per_address] + + with open(txt_file_name, "w") as out_file: + out_file.write("\n".join(data)) + + return txt_file_name + + def write_hex_file(self, hex_file_name = "memory_file.hex"): if hex_file_name is None: return self.as_ihex() @@ -126,8 +156,8 @@ def write_hex_file(self, hex_file_name = "memory_file.hex"): def get_address_data_pairs(self): pairs = [] for seg in self.segments: - for addr in range(0, int((seg.maximum_address-seg.minimum_address) / seg._word_size_bytes), self.bytes_per_address): - addr += int(seg.minimum_address / seg._word_size_bytes) + for addr in range(0, int((seg.maximum_address-seg.minimum_address) / seg.word_size_bytes), self.bytes_per_address): + addr += int(seg.minimum_address / seg.word_size_bytes) data = 0 for i in range(self.bytes_per_address): data <<= 8 diff --git a/i2c-stick-py/pyproject.toml b/i2c-stick-py/pyproject.toml index 53eb854..29aa045 100644 --- a/i2c-stick-py/pyproject.toml +++ b/i2c-stick-py/pyproject.toml @@ -8,7 +8,7 @@ build-backend = "setuptools.build_meta" [project] name = "melexis-i2c-stick" -version = "0.3.2" +version = "0.4.0" description = "Melexis I2C Stick, python interface" readme = "README.md" authors = [{ name = "Karel Vanroye", email = "kva@melexis.com" }] @@ -24,6 +24,10 @@ dependencies = [ 'pyserial>=3.5', ] requires-python = ">=3.3" +dynamic = ["dependencies"] + +[tool.setuptools.dynamic] +dependencies = {file = ["requirements.txt"]} [project.optional-dependencies] dev = [] @@ -36,7 +40,7 @@ melexis_i2c_stick = "melexis.i2c_stick.__main__:main" [tool.bumpver] -current_version = "0.3.2" +current_version = "0.4.0" version_pattern = "MAJOR.MINOR.PATCH[PYTAGNUM]" commit_message = "bump version {old_version} -> {new_version}" commit = false diff --git a/i2c-stick-py/requirements.txt b/i2c-stick-py/requirements.txt index 2af993f..9e10e0f 100644 --- a/i2c-stick-py/requirements.txt +++ b/i2c-stick-py/requirements.txt @@ -1,18 +1,2 @@ -# -# This file is autogenerated by pip-compile with Python 3.10 -# by the following command: -# -# pip-compile -# -argparse-addons==0.12.0 - # via bincopy -bincopy==17.14.5 - # via melexis-i2c-stick (pyproject.toml) -humanfriendly==10.0 - # via bincopy -pyelftools==0.29 - # via bincopy -pyreadline3==3.4.1 - # via humanfriendly -pyserial==3.5 - # via melexis-i2c-stick (pyproject.toml) +bincopy>=18 +pyserial>=3.5 From 20db14a78289f9b6d22f270c441ac25d5c2e9b7d Mon Sep 17 00:00:00 2001 From: Karel Vanroye Date: Tue, 3 Oct 2023 17:10:58 -0700 Subject: [PATCH 026/112] update config file --- i2c-stick-py/pyproject.toml | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/i2c-stick-py/pyproject.toml b/i2c-stick-py/pyproject.toml index 29aa045..ca949ba 100644 --- a/i2c-stick-py/pyproject.toml +++ b/i2c-stick-py/pyproject.toml @@ -20,14 +20,10 @@ classifiers = [ ] keywords = ["Melexis", "I2C", "sensors", "demo"] dependencies = [ - 'bincopy>=17.14.5', + 'bincopy>=18', 'pyserial>=3.5', ] requires-python = ">=3.3" -dynamic = ["dependencies"] - -[tool.setuptools.dynamic] -dependencies = {file = ["requirements.txt"]} [project.optional-dependencies] dev = [] From c0c22557c4534c30340fbb3048a2fc86eaddb41f Mon Sep 17 00:00:00 2001 From: Karel Vanroye Date: Tue, 3 Oct 2023 17:43:07 -0700 Subject: [PATCH 027/112] fix minor issues --- i2c-stick-py/melexis/i2c_stick/MemoryFile.py | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/i2c-stick-py/melexis/i2c_stick/MemoryFile.py b/i2c-stick-py/melexis/i2c_stick/MemoryFile.py index 2813b7e..3b37fb0 100644 --- a/i2c-stick-py/melexis/i2c_stick/MemoryFile.py +++ b/i2c-stick-py/melexis/i2c_stick/MemoryFile.py @@ -16,17 +16,19 @@ def __init__(self, filenames=None, overwrite=True, header_encoding='utf-8', byte self.bytes_per_address = bytes_per_address - def read_evb90614_32_40_41_txt_file(self, txt_file, at_address): + def read_txt_file(self, txt_file, at_address): # EVB90614, EVB90632, EVB90640-41 BIN file format is little-endian, while bin_copy; the hex file package expects big-endian! # so here we do the trick with unpack/pack! self.bytes_per_address = 2 # force 2 bytes per address for MLX90632! with open(txt_file, mode='r') as file: fileContent = file.read() + fileContent.replace("\r", "") fc = fileContent.split("\n") fc.remove("") data = [int(x) for x in fc] + fmt_out = ">{:d}H".format (len(fc)) bin_data = struct.pack(fmt_out, *data) self.add_binary(bin_data, address=at_address*self.bytes_per_address, overwrite=True) @@ -125,17 +127,22 @@ def write_evb90614_32_40_41_bin_file(self, address, count, evb_bin_file_name = " return evb_bin_file_name - def write_evb90614_32_40_41_txt_file(self, address, count, txt_file_name = "memory.txt"): + def write_txt_file(self, address, count, txt_file_name = "memory.txt"): if txt_file_name is None: return None if not txt_file_name.endswith('.txt'): txt_file_name += '.txt' - data = self[address*self.bytes_per_address:(address+count)*self.bytes_per_address] + bin_data_in = self[address*self.bytes_per_address:(address+count)*self.bytes_per_address] + if len(bin_data_in) < (count*self.bytes_per_address): + bin_data_in.append(bytearray([255])*((count*self.bytes_per_address)-len(bin_data_in))) + fmt_in = ">{:d}H".format (int(len(bin_data_in)/2)) + + data = [str(x) for x in list(struct.unpack(fmt_in, bin_data_in))] with open(txt_file_name, "w") as out_file: - out_file.write("\n".join(data)) + out_file.write("\n".join(data) + "\n") return txt_file_name From e9cc151415d3c91f1d967ad16713bf284fb6166b Mon Sep 17 00:00:00 2001 From: Karel Vanroye Date: Tue, 3 Oct 2023 17:43:49 -0700 Subject: [PATCH 028/112] fix minor issues --- i2c-stick-py/pyproject.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/i2c-stick-py/pyproject.toml b/i2c-stick-py/pyproject.toml index ca949ba..14406be 100644 --- a/i2c-stick-py/pyproject.toml +++ b/i2c-stick-py/pyproject.toml @@ -8,7 +8,7 @@ build-backend = "setuptools.build_meta" [project] name = "melexis-i2c-stick" -version = "0.4.0" +version = "0.4.1" description = "Melexis I2C Stick, python interface" readme = "README.md" authors = [{ name = "Karel Vanroye", email = "kva@melexis.com" }] @@ -36,7 +36,7 @@ melexis_i2c_stick = "melexis.i2c_stick.__main__:main" [tool.bumpver] -current_version = "0.4.0" +current_version = "0.4.1" version_pattern = "MAJOR.MINOR.PATCH[PYTAGNUM]" commit_message = "bump version {old_version} -> {new_version}" commit = false From 250295608b3b07efa46aa5f9bdc050d74bdbd28c Mon Sep 17 00:00:00 2001 From: Karel Vanroye Date: Wed, 11 Oct 2023 10:15:48 -0700 Subject: [PATCH 029/112] adding automation tools + discover 90614 which are in PWM mode during an I2C-scan command --- .gitignore | 1 + i2c-stick-arduino/.gitignore | 9 +- i2c-stick-arduino/context.yaml | 50 +- i2c-stick-arduino/dodo.py | 429 ++++++++++++++++ i2c-stick-arduino/driver_cmd.cpp.jinja2 | 457 +++++++++++++++++ i2c-stick-arduino/driver_cmd.h.jinja2 | 36 ++ i2c-stick-arduino/firmware_list.md.jinja2 | 3 + i2c-stick-arduino/i2c-stick-arduino.ino | 22 + i2c-stick-arduino/i2c_stick.h | 1 - i2c-stick-arduino/i2c_stick_cmd.cpp | 5 + i2c-stick-arduino/i2c_stick_dispatcher.cpp | 451 ++++++++++++++++- .../i2c_stick_dispatcher.cpp.jinja2 | 2 +- i2c-stick-arduino/i2c_stick_dispatcher.h | 45 +- .../i2c_stick_dispatcher.h.jinja2 | 2 +- i2c-stick-arduino/i2c_stick_hal.h | 5 + i2c-stick-arduino/mailmerge.py | 25 +- i2c-stick-arduino/mlx90614_cmd.h | 1 - i2c-stick-arduino/mlx90621_api.cpp | 474 ++++++++++++++++++ i2c-stick-arduino/mlx90621_api.h | 54 ++ i2c-stick-arduino/mlx90621_cmd.cpp | 457 +++++++++++++++++ i2c-stick-arduino/mlx90621_cmd.h | 36 ++ i2c-stick-arduino/mlx90621_i2c_driver.cpp | 180 +++++++ i2c-stick-arduino/mlx90621_i2c_driver.h | 27 + i2c-stick-arduino/requirements.txt | 7 + 24 files changed, 2737 insertions(+), 42 deletions(-) create mode 100644 i2c-stick-arduino/dodo.py create mode 100644 i2c-stick-arduino/driver_cmd.cpp.jinja2 create mode 100644 i2c-stick-arduino/driver_cmd.h.jinja2 create mode 100644 i2c-stick-arduino/firmware_list.md.jinja2 create mode 100644 i2c-stick-arduino/mlx90621_api.cpp create mode 100644 i2c-stick-arduino/mlx90621_api.h create mode 100644 i2c-stick-arduino/mlx90621_cmd.cpp create mode 100644 i2c-stick-arduino/mlx90621_cmd.h create mode 100644 i2c-stick-arduino/mlx90621_i2c_driver.cpp create mode 100644 i2c-stick-arduino/mlx90621_i2c_driver.h create mode 100644 i2c-stick-arduino/requirements.txt diff --git a/.gitignore b/.gitignore index 2bb41a9..cc674d2 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,4 @@ web-interface/*.html !web-interface/assets/**/*.min.js !web-interface/assets/**/*.min.css web-interface/melexis-bulma.css +.idea \ No newline at end of file diff --git a/i2c-stick-arduino/.gitignore b/i2c-stick-arduino/.gitignore index 7664704..c0d991c 100644 --- a/i2c-stick-arduino/.gitignore +++ b/i2c-stick-arduino/.gitignore @@ -1 +1,8 @@ -*.bak \ No newline at end of file +*.bak +.doit.db* +__pycache__ +package +driver_cmd.h +driver_cmd.cpp +firmware_list.md +tools diff --git a/i2c-stick-arduino/context.yaml b/i2c-stick-arduino/context.yaml index 496d81d..a87cb3a 100644 --- a/i2c-stick-arduino/context.yaml +++ b/i2c-stick-arduino/context.yaml @@ -1,18 +1,34 @@ - +board_manager: + additional-urls: + - https://github.com/earlephilhower/arduino-pico/releases/download/global/package_rp2040_index.json + boards: + - rp2040:rp2040 +boards: +- fqbn: rp2040:rp2040:adafruit_trinkeyrp2040qt + name: Adafruit Trinkey RP2040 QT + nick: i2c-stick + platform: rp2040:rp2040 + url: https://www.adafruit.com/product/5056 + USB_PID: 0x8109 + USB_VID: 0x239A drivers: - - id: 1 - name: MLX90614 - scr_name: mlx90614 - function_id: '90614' - - id: 2 - name: MLX90640 - scr_name: mlx90640 - function_id: '90640' - - id: 3 - name: MLX90641 - scr_name: mlx90641 - function_id: '90641' - - id: 4 - name: MLX90632 - scr_name: mlx90632 - function_id: '90632' \ No newline at end of file +- function_id: '90614' + id: 1 + name: MLX90614 + scr_name: mlx90614 +- function_id: '90640' + id: 2 + name: MLX90640 + scr_name: mlx90640 +- function_id: '90641' + id: 3 + name: MLX90641 + scr_name: mlx90641 +- function_id: '90632' + id: 4 + name: MLX90632 + scr_name: mlx90632 +- function_id: '90621' + id: 5 + name: MLX90621 + scr_name: mlx90621 diff --git a/i2c-stick-arduino/dodo.py b/i2c-stick-arduino/dodo.py new file mode 100644 index 0000000..d02acc2 --- /dev/null +++ b/i2c-stick-arduino/dodo.py @@ -0,0 +1,429 @@ +# todo: +# [ ] create package / website within this dodo.py file. +# [ ] align version number of firmware and the python package. (make them one and the same!) +import sys +import subprocess + +CONTEXT_FILE = "context.yaml" + +DOIT_CONFIG = {'action_string_formatting': 'both', + 'default_tasks': ['arduino-compile:i2c-stick', 'cleaner'], + } +PIP_USER = " --user " +if sys.prefix != sys.base_prefix: # check if we are in a virtual environment + PIP_USER = "" + +try: + import doit +except (Exception,) as e: + print("installing python packages from requirements.txt") + t = subprocess.check_output('pip install {} -r requirements.txt'.format(PIP_USER), text=True) + print(t) + print("\n\nPlease run this script again") + print("Note: instead of 'python dodo.py', now you can use 'doit'") + print("Note: use 'doit list' for a list of commands.") + exit(1) + +import shutil +import os +import yaml +import jinja2 +import yamlinclude +from glob import glob +from pathlib import Path +import serial.tools.list_ports +from doit.action import CmdAction +import platform + +with open(CONTEXT_FILE) as f: + context = yaml.load(f, Loader=yaml.FullLoader) + +arduino_add_url = " ".join(["--additional-urls {}".format(x) for x in context['board_manager']['additional-urls']]) + +ARDUINO_CLI = os.path.join('tools', 'arduino-cli'+Path(sys.executable).suffix) + + +def str_presenter(dumper, data): + if len(data.splitlines()) > 1: # check for multiline string + return dumper.represent_scalar('tag:yaml.org,2002:str', data, style='|') + return dumper.represent_scalar('tag:yaml.org,2002:str', data) + + +yaml.add_representer(str, str_presenter) + + +def remove(path): + """ param could either be relative or absolute. """ + for p in glob(path): + if os.path.isfile(p) or os.path.islink(p): + os.remove(p) # remove the file + elif os.path.isdir(p): + shutil.rmtree(p) # remove dir and all contains + else: + raise ValueError("path {} is not a file or dir.".format(p)) + + +def task_cleaner(): + """ Clean the entire repository for a git commit & be ready to re-compile the entire project!""" + def do_clean(): + patterns = ["build", + "package", + "*~", + "*.bak"] + for pattern in patterns: + try: + remove(pattern) + except Exception as err: + print(str(err)) + + # reset the automatically generated files... + txt = """ +// this file is automatically generated: +// please edit 'context.yaml', and then: +// run the doit command `python dodo.py generate` or `doit generate`. + +#error "This file is automatically generated; please run `python dodo.py source` or `doit source` from command line" +""" + with open("i2c_stick_dispatcher.cpp", "w") as text_file: + text_file.write(txt) + with open("i2c_stick_dispatcher.h", "w") as text_file: + text_file.write(txt) + from doit.doit_cmd import DoitMain + DoitMain().run(["forget", "generate:i2c_stick_dispatcher.h"]) + DoitMain().run(["forget", "generate:i2c_stick_dispatcher.cpp"]) + + return { + "actions": None, + "clean": [do_clean], + } + + +def task_pip(): + """Install required python packages using pip""" + for rqt_file in ['requirements.txt']: + yield { + 'name': rqt_file, + 'actions': ["pip install {} -r {}".format(PIP_USER, rqt_file)], + 'file_dep': [rqt_file], + } + + +def task_arduino_install_cli(): + """Arduino: Install the arduino-cli tool""" + def do_install(task): + if not Path("tools").is_dir(): + os.mkdir('tools') + system = platform.system().lower() + os_dict = { + 'linux': 'Linux', + 'windows': 'Windows', + 'darwin': 'macOS', + } + bits = '32bit' + if sys.maxsize > 2**32: + bits = '64bit' + zip_suffix = 'tar.gz' + if system == 'windows': + zip_suffix = 'zip' + + url = "https://downloads.arduino.cc/arduino-cli/arduino-cli_latest_{}_{}.{}".format(os_dict[system], bits, zip_suffix) + print("downloading:", url) + import io + import zipfile + from contextlib import closing + import requests + + r = requests.get(url) + with closing(r), zipfile.ZipFile(io.BytesIO(r.content)) as archive: + for member in archive.infolist(): + if member.filename == Path(task.targets[0]).name: + print("file: {}".format(member.filename)) + with open(task.targets[0], "wb") as file: + file.write(archive.read(member)) + + return + + return { + 'basename': 'arduino-install-cli', + 'actions': [(do_install, )], + 'verbosity': 2, + 'file_dep': ['requirements.txt'], + 'targets': [ARDUINO_CLI], + } + + +def task_package(): + """Create the ZIP package file""" + + def do_package(): + shutil.copy('firmware_list.md', 'build') + # remove("package") + # os.mkdir("package") + # dst = os.path.join("package", "ktc_trial") + # os.mkdir(dst) + # shutil.copy(os.path.join("dist", 'ktc_trial.exe'), dst) + # shutil.copy("ktc_trial.yml", dst) + # shutil.make_archive("ktc_trial", 'zip', "package") + return + + return { + 'actions': [do_package], + # 'targets': ['ktc_trial.zip'], + 'clean': True, + # 'file_dep': ['ktc_trial.yml', os.path.join("dist", 'ktc_trial.exe')], + 'task_dep': ['arduino-compile', 'generate:firmware_list.md'], + } + + +def task_arduino_update_boards(): + """Arduino: get a fresh copy of the board index""" + return { + 'basename': 'arduino-update-boards', + 'actions': ["{} {} core update-index".format(ARDUINO_CLI, arduino_add_url), + ], + 'file_dep': [CONTEXT_FILE], + 'task_dep': ['arduino-install-cli'], + } + + +def task_arduino_install_board(): + """Arduino: install the board tool-chain""" + for board in context['board_manager']['boards']: + yield { + 'basename': 'arduino-install-board', + 'name': board, + 'actions': ["{} {} core install {}".format(ARDUINO_CLI, arduino_add_url, board), + ], + 'task_dep': ['arduino-install-cli', 'arduino-update-boards'], + 'file_dep': [CONTEXT_FILE], + } + + +def task_arduino_install_libs(): + """Arduino: install the specific libraries""" + return { + 'basename': 'arduino-install-libs', + "actions": None, + 'task_dep': ['arduino-install-cli'], + } + + +def task_arduino_compile(): + """Arduino: Compile the sources into a UF2 file (and bin-file)""" + working_directory = Path('.') + headers = list(working_directory.glob('*.h')) + cpp_files = list(working_directory.glob('*.cpp')) + for board in context['boards']: + yield { + 'basename': 'arduino-compile', + 'name': board['nick'], + 'actions': ["{} compile --fqbn {} i2c-stick-arduino.ino -e --clean".format(ARDUINO_CLI, board['fqbn']), + ], + 'task_dep': ['arduino-install-cli', + 'arduino-install-board:'+board['platform'], + 'arduino-install-libs', + 'generate:i2c_stick_dispatcher.h', + 'generate:i2c_stick_dispatcher.cpp', + ], + 'file_dep': [CONTEXT_FILE, + 'i2c-stick-arduino.ino', + 'i2c_stick_dispatcher.h', + 'i2c_stick_dispatcher.cpp'] + headers + cpp_files, + 'targets': ['build/{}/i2c-stick-arduino.ino.uf2'.format(board['fqbn'].replace(":", "."))], + } + + +def task_arduino_upload(): + """Arduino: Upload to the target board""" + def do_upload(board_cfg, port): + if port == 'auto': + filtered_ports = [] + pid = None + vid = None + if 'USB_VID' in board_cfg: + vid = board_cfg['USB_VID'] + if 'USB_PID' in board_cfg: + pid = board_cfg['USB_PID'] + for p in serial.tools.list_ports.comports(include_links=False): + if vid is None: + if pid is None: + filtered_ports.append(p) + continue + + if vid is None: + if p.pid == pid: + filtered_ports.append(p) + continue + if pid is None: + if p.vid == vid: + filtered_ports.append(p) + continue + + if p.vid == vid: + if p.pid == pid: + filtered_ports.append(p) + port = filtered_ports[0].name + return "{} upload --fqbn {} i2c-stick-arduino.ino --port {}".format(ARDUINO_CLI, board_cfg['fqbn'], port) + + for board in context['boards']: + yield { + 'basename': 'arduino-upload', + 'name': board['nick'], + 'params': [ + {'name': 'port', + 'short': 'p', + 'long': 'port', + 'type': str, + 'default': 'auto', + }, + ], + 'actions': [CmdAction((do_upload, [board], {})), + ], + 'task_dep': ['arduino-install-cli', + 'arduino-compile', + ], + 'file_dep': [CONTEXT_FILE], + 'uptodate': [False], # force to run the task always + 'verbosity': 2, + } + + +def task_generate(): + """Generate file using context.yaml and jinja2 template files""" + def do_generate(template, output): + this_dir = os.path.dirname(os.path.abspath(__file__)) + yamlinclude.YamlIncludeConstructor.add_to_loader_class(loader_class=yaml.FullLoader, base_dir=this_dir) + loader = jinja2.FileSystemLoader(this_dir) + + env = jinja2.Environment( + loader=loader, + autoescape=jinja2.select_autoescape() + ) + + t = env.get_template(template) + + with open(output, 'w') as output_f: + output_f.write(t.render(context)) + + working_directory = Path('.') + for jinja2_file in working_directory.glob('*.jinja2'): + if jinja2_file.with_suffix('').with_suffix('').name.endswith('driver_cmd'): + continue + output_file = jinja2_file.with_suffix('') + yield { + 'name': output_file.name, + 'actions': [(do_generate, [jinja2_file.name, output_file.name])], + 'file_dep': [jinja2_file.name], + 'task_dep': ['pip:requirements.txt'], + 'targets': [output_file.name], + } + + +def task_add_driver(): + """Add a templated entry for a new sensor to the framework""" + def do_generate(template, output, data): + this_dir = os.path.dirname(os.path.abspath(__file__)) + yamlinclude.YamlIncludeConstructor.add_to_loader_class(loader_class=yaml.FullLoader, base_dir=this_dir) + loader = jinja2.FileSystemLoader(this_dir) + + env = jinja2.Environment( + loader=loader, + autoescape=jinja2.select_autoescape() + ) + + t = env.get_template(template) + print("output:", output) + with open(output, 'w') as output_f: + output_f.write(t.render(data)) + output_f.write("\n") + + def do_add_driver(driver, src_name, function_id, sa_list): + if driver is None: + print("Please provide parameters about the drivers") + print("Run 'doit info add-driver' for more information") + return + if src_name is None: + src_name = driver.lower() + if function_id is None: + if src_name.startswith('mlx'): + function_id = src_name[3:] + if function_id is None: + print("Please provide parameters about the drivers") + print("Run 'doit info add-driver' for more information") + return + if len(sa_list) == 0: + print("Please provide parameters about the drivers") + print("Run 'doit info add-driver' for more information") + return + + driver_data = { 'driver': { + 'name': driver, + 'src_name': src_name, + 'function_id': function_id, + 'sa_list': sa_list, + }, + } + + driver_ids = [x['id'] for x in context['drivers']] + for drv in context['drivers']: + if drv['name'] == driver: + print("ERROR: Driver '{}' already exists; edit the file 'context.yaml' manually to resolve this issue".format(driver)) + return + + do_generate("driver_cmd.h.jinja2", "{}_cmd.h".format(src_name), driver_data) + do_generate("driver_cmd.cpp.jinja2", "{}_cmd.cpp".format(src_name), driver_data) + # now update the context.yaml file! + + context['drivers'].append({ + 'id': max(driver_ids)+1, + 'name': driver, + 'scr_name': src_name, + 'function_id': function_id, + }) + with open(CONTEXT_FILE, 'w') as output_f: + output_f.write(yaml.dump(context)) + output_f.write("\n") + + # and finally re-generate the dispatcher for the newly added driver. + from doit.doit_cmd import DoitMain + DoitMain().run(["--always", "generate:i2c_stick_dispatcher.h"]) + DoitMain().run(["--always", "generate:i2c_stick_dispatcher.cpp"]) + + return { + 'basename': 'add-driver', + 'actions': [(do_add_driver,)], + 'file_dep': ['driver_cmd.h.jinja2'], + 'params': [ + {'name': 'driver', + 'short': 'd', + 'long': 'driver', + 'type': str, + 'default': None, + }, + {'name': 'src_name', + 'short': 's', + 'long': 'src_name', + 'type': str, + 'default': None, + }, + {'name': 'function_id', + 'short': 'f', + 'long': 'function_id', + 'type': str, + 'default': None, + }, + {'name': 'sa_list', + 'short': 'a', + 'long': 'sa', + 'type': list, + 'default': [], + }, + ], + 'uptodate': [False], # make to run the task always + 'verbosity': 2, + } + + +if __name__ == '__main__': + import doit + doit.run(globals()) diff --git a/i2c-stick-arduino/driver_cmd.cpp.jinja2 b/i2c-stick-arduino/driver_cmd.cpp.jinja2 new file mode 100644 index 0000000..a24ab39 --- /dev/null +++ b/i2c-stick-arduino/driver_cmd.cpp.jinja2 @@ -0,0 +1,457 @@ +#include "{{driver.src_name}}_cmd.h" +#include "i2c_stick.h" +#include "i2c_stick_cmd.h" +#include "i2c_stick_dispatcher.h" +#include "i2c_stick_hal.h" + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef MAX_{{driver.name}}_SLAVES +#define MAX_{{driver.name}}_SLAVES 8 +#endif // MAX_{{driver.name}}_SLAVES + +#define {{driver.name}}_ERROR_BUFFER_TOO_SMALL "Buffer too small" +#define {{driver.name}}_ERROR_COMMUNICATION "Communication error" +#define {{driver.name}}_ERROR_NO_FREE_HANDLE "No free handle; pls recompile firmware with higher 'MAX_{{driver.name}}_SLAVES'" +#define {{driver.name}}_ERROR_OUT_OF_RANGE "Out of range" + + +static {{driver.name}}_t *g_{{driver.name|lower}}_list[MAX_{{driver.name}}_SLAVES]; + + +{{driver.name}}_t * +cmd_{{driver.function_id}}_get_handle(uint8_t sa) +{ + if (sa >= 128) + { + return NULL; + } + + for (uint8_t i=0; islave_address_ & 0x7F) == sa) + { // found! + return g_{{driver.name|lower}}_list[i]; + } + } + + // not found => try to find a handle with slave address zero (not yet initialized)! + for (uint8_t i=0; islave_address_ == 0) + { // found! + return g_{{driver.name|lower}}_list[i]; + } + } + + // not found => use first free spot! + uint8_t i=0; + for (; islave_address_ = 0x80 | sa; + return g_{{driver.name|lower}}_list[i]; + } + } + + return NULL; // no free spot available +} + + +static void +delete_handle(uint8_t sa) +{ + for (uint8_t i=0; islave_address_ & 0x7F) == sa) + { // found! + memset(g_{{driver.name|lower}}_list[i], 0, sizeof({{driver.name}}_t)); + free(g_{{driver.name|lower}}_list[i]); + g_{{driver.name|lower}}_list[i] = NULL; + } + } +} + + +int16_t +cmd_{{driver.function_id}}_register_driver() +{ + int16_t r = 0; +{% for sa in driver.sa_list %} + r = i2c_stick_register_driver({{sa}}, DRV_{{driver.name}}_ID); + if (r < 0) return r; +{% endfor %} + return 1; +} + + +void +cmd_{{driver.function_id}}_init(uint8_t sa) +{ + {{driver.name}}_t *mlx = cmd_{{driver.function_id}}_get_handle(sa); + if (mlx == NULL) + { + return; + } + // init functions goes here + + // turn off bit7, to indicate other routines this slave has been init + mlx->slave_address_ &= 0x7F; +} + + +void +cmd_{{driver.function_id}}_tear_down(uint8_t sa) +{ // nothing special to do, just release all associated memory + delete_handle(sa); +} + + +void +cmd_{{driver.function_id}}_mv(uint8_t sa, float *mv_list, uint16_t *mv_count, char const **error_message) +{ + {{driver.name}}_t *mlx = cmd_{{driver.function_id}}_get_handle(sa); + if (mlx == NULL) + { + *mv_count = 0; + *error_message = {{driver.name}}_ERROR_NO_FREE_HANDLE; + return; + } + if (mlx->slave_address_ & 0x80) + { + cmd_{{driver.function_id}}_init(sa); + } + + if (*mv_count <= 2) // check Measurement Value buffer length + { + *mv_count = 0; + *error_message = {{driver.name}}_ERROR_BUFFER_TOO_SMALL; + return; + } + *mv_count = 2; + + // todo: + // + // get the measurement values from the sensor + // +} + + +void +cmd_{{driver.function_id}}_raw(uint8_t sa, uint16_t *raw_list, uint16_t *raw_count, char const **error_message) +{ + {{driver.name}}_t *mlx = cmd_{{driver.function_id}}_get_handle(sa); + if (mlx == NULL) + { + *raw_count = 0; + *error_message = {{driver.name}}_ERROR_NO_FREE_HANDLE; + return; + } + if (mlx->slave_address_ & 0x80) + { + cmd_{{driver.function_id}}_init(sa); + } + + if (*raw_count < 3) // check Raw Value buffer length + { + *raw_count = 0; // input buffer not long enough, report nothing. + *error_message = {{driver.name}}_ERROR_BUFFER_TOO_SMALL; + return; + } + *raw_count = 3; + + // todo: + // + // get the raw values from the sensor + // +} + + +void +cmd_{{driver.function_id}}_nd(uint8_t sa, uint8_t *nd, char const **error_message) +{ + {{driver.name}}_t *mlx = cmd_{{driver.function_id}}_get_handle(sa); + if (mlx == NULL) + { + *error_message = {{driver.name}}_ERROR_NO_FREE_HANDLE; + return; + } + if (mlx->slave_address_ & 0x80) + { + cmd_{{driver.function_id}}_init(sa); + } + + // todo: + // + // read the status from the sensor and check if new data is available (ND=New Data). + // + } + + +void +cmd_{{driver.function_id}}_sn(uint8_t sa, uint16_t *sn_list, uint16_t *sn_count, char const **error_message) +{ + {{driver.name}}_t *mlx = cmd_{{driver.function_id}}_get_handle(sa); + if (mlx == NULL) + { + *sn_count = 0; + *error_message = {{driver.name}}_ERROR_NO_FREE_HANDLE; + return; + } + if (mlx->slave_address_ & 0x80) + { + cmd_{{driver.function_id}}_init(sa); + } + + if (*sn_count < 4) // check the Serial Number buffer length + { + *sn_count = 0; // input buffer not long enough, report nothing. + *error_message = {{driver.name}}_ERROR_BUFFER_TOO_SMALL; + return; + } + *sn_count = 4; + + // todo: + // + // read the serial number from the sensor. + // +} + + +void +cmd_{{driver.function_id}}_cs(uint8_t sa, uint8_t channel_mask, const char *input) +{ + {{driver.name}}_t *mlx = cmd_{{driver.function_id}}_get_handle(sa); + if (mlx == NULL) + { + return; + } + if (mlx->slave_address_ & 0x80) + { + cmd_{{driver.function_id}}_init(sa); + } + + // todo: + // + // read the CS(Configuration of the Slave) from the sensor. + // + + char buf[16]; memset(buf, 0, sizeof(buf)); + send_answer_chunk(channel_mask, "cs:", 0); + uint8_to_hex(buf, sa); + send_answer_chunk(channel_mask, buf, 0); + send_answer_chunk(channel_mask, ":SA=", 0); + uint8_to_hex(buf, sa); + send_answer_chunk(channel_mask, buf, 1); + + + // todo: + // + // Send the answer back in the format + // "cs::=" + // + + + // todo: + // + // Send the configuration of the MV header, unit and resolution back to the terminal(not to sensor!) + // + + // send_answer_chunk(channel_mask, "cs:", 0); + // uint8_to_hex(buf, sa); + // send_answer_chunk(channel_mask, buf, 0); + // send_answer_chunk(channel_mask, ":RO:MV_HEADER=TA,TO", 1); + + // send_answer_chunk(channel_mask, "cs:", 0); + // uint8_to_hex(buf, sa); + // send_answer_chunk(channel_mask, buf, 0); + // send_answer_chunk(channel_mask, ":RO:MV_UNIT=DegC,DegC", 1); + + // send_answer_chunk(channel_mask, "cs:", 0); + // uint8_to_hex(buf, sa); + // send_answer_chunk(channel_mask, buf, 0); + // send_answer_chunk(channel_mask, ":RO:MV_RES=" xstr(MLX90614_LSB_C) "," xstr(MLX90614_LSB_C), 1); +} + + +void +cmd_{{driver.function_id}}_cs_write(uint8_t sa, uint8_t channel_mask, const char *input) +{ + char buf[16]; memset(buf, 0, sizeof(buf)); + {{driver.name}}_t *mlx = cmd_{{driver.function_id}}_get_handle(sa); + if (mlx == NULL) + { + return; + } + if (mlx->slave_address_ & 0x80) + { + cmd_{{driver.function_id}}_init(sa); + } + + + // + // todo: + // + // write the configuration of the slave to the sensor and report to the channel the status. + // + // Please get inspired from other drivers like MLX90614. + // + // Also if SA can be re-programmed, please add the correct sequence here, see also MLX90614 or MLX90632 for an extensive example. + // + + // finally we have a catch all to inform the user that they asked something unknown. + send_answer_chunk(channel_mask, "+cs:", 0); + uint8_to_hex(buf, sa); + send_answer_chunk(channel_mask, buf, 0); + send_answer_chunk(channel_mask, ":FAIL; unknown variable", 1); +} + + +void +cmd_{{driver.function_id}}_mr(uint8_t sa, uint16_t *mem_data, uint16_t mem_start_address, uint16_t mem_count, uint8_t *bit_per_address, uint8_t *address_increments, char const **error_message) +{ + {{driver.name}}_t *mlx = cmd_{{driver.function_id}}_get_handle(sa); + if (mlx == NULL) + { + *bit_per_address = 0; + *address_increments = 0; + *error_message = {{driver.name}}_ERROR_NO_FREE_HANDLE; + return; + } + if (mlx->slave_address_ & 0x80) + { + cmd_{{driver.function_id}}_init(sa); + } + + // indicate 16 bit at each single address: + *bit_per_address = 16; + *address_increments = 1; + + if ((mem_start_address + mem_count) > 0x00FF) + { + *bit_per_address = 0; + *address_increments = 0; + *error_message = {{driver.name}}_ERROR_OUT_OF_RANGE; + return; + } + + for (uint16_t i=0; islave_address_ & 0x80) + { + cmd_{{driver.function_id}}_init(sa); + } + + *bit_per_address = 16; + *address_increments = 1; + + if ((mem_start_address + mem_count) > 0x00FF) + { + *bit_per_address = 0; + *address_increments = 0; + *error_message = {{driver.name}}_ERROR_OUT_OF_RANGE; + return; + } + + for (uint16_t i=0; i slave address is actually a {{driver.name}}! + // often times this can be done by reading some specific values from the ROM or EEPROM, + // and verify the values are as expected. + // + + // remember there is no communication initiated yet... + + // in this ecample below for MLX90614 we check if the EEPROM reads the slave address at address 0x2E... + +// MLX90614_SMBusInit(); +// if (MLX90614_SMBusRead(sa, 0x2E, &value) < 0) + { + *error_message = {{driver.name}}_ERROR_COMMUNICATION; + *is_ok = 0; + return; + } + if (value & 0x007F != sa) + { + *is_ok = 0; + } +} + + +#ifdef __cplusplus +} +#endif diff --git a/i2c-stick-arduino/driver_cmd.h.jinja2 b/i2c-stick-arduino/driver_cmd.h.jinja2 new file mode 100644 index 0000000..035e517 --- /dev/null +++ b/i2c-stick-arduino/driver_cmd.h.jinja2 @@ -0,0 +1,36 @@ +#ifndef _{{driver.name}}_CMD_ +#define _{{driver.name}}_CMD_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct {{driver.name}}_t +{ + uint8_t slave_address_; + // local caching of sensor values whenever needed; + // stored along with , such that multiple sensors can be supported. +}; + + +int16_t cmd_{{driver.function_id}}_register_driver(); + +void cmd_{{driver.function_id}}_mv(uint8_t sa, float *mv_list, uint16_t *mv_count, char const **error_message); +void cmd_{{driver.function_id}}_raw(uint8_t sa, uint16_t *raw_list, uint16_t *raw_count, char const **error_message); +void cmd_{{driver.function_id}}_nd(uint8_t sa, uint8_t *nd, char const **error_message); +void cmd_{{driver.function_id}}_sn(uint8_t sa, uint16_t *sn_list, uint16_t *sn_count, char const **error_message); +void cmd_{{driver.function_id}}_cs(uint8_t sa, uint8_t channel_mask, const char *input); +void cmd_{{driver.function_id}}_cs_write(uint8_t sa, uint8_t channel_mask, const char *input); +void cmd_{{driver.function_id}}_mr(uint8_t sa, uint16_t *mem_data, uint16_t mem_start_address, uint16_t mem_count, uint8_t *bit_per_address, uint8_t *address_increments, char const **error_message); +void cmd_{{driver.function_id}}_mw(uint8_t sa, uint16_t *mem_data, uint16_t mem_start_address, uint16_t mem_count, uint8_t *bit_per_address, uint8_t *address_increments, char const **error_message); +void cmd_{{driver.function_id}}_is(uint8_t sa, uint8_t *is_ok, char const **error_message); + +void cmd_{{driver.function_id}}_tear_down(uint8_t sa); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/i2c-stick-arduino/firmware_list.md.jinja2 b/i2c-stick-arduino/firmware_list.md.jinja2 new file mode 100644 index 0000000..c907cc9 --- /dev/null +++ b/i2c-stick-arduino/firmware_list.md.jinja2 @@ -0,0 +1,3 @@ +{%- for board in boards %} +- {{board.nick}}: [{{board.name}} UF2-file](firmware/{{board.fqbn|replace(':', '.')}}/melexis-i2c-stick-arduino.ino.uf2) -- [board url]({{board.url}}) +{% endfor %} diff --git a/i2c-stick-arduino/i2c-stick-arduino.ino b/i2c-stick-arduino/i2c-stick-arduino.ino index 9f5ed39..1d0d324 100644 --- a/i2c-stick-arduino/i2c-stick-arduino.ino +++ b/i2c-stick-arduino/i2c-stick-arduino.ino @@ -130,6 +130,21 @@ hal_get_board_info() return BOARD_INFO; } +void +hal_write_pin(uint8_t pin, uint8_t state) +{ + pinMode(pin, OUTPUT); + digitalWrite(pin, state ? 1 : 0); +} + + +uint8_t +hal_read_pin(uint8_t pin) +{ + pinMode(pin, INPUT); + return digitalRead(pin); +} + uint64_t hal_get_millis() @@ -138,6 +153,13 @@ hal_get_millis() } +void +hal_delay(uint32_t ms) +{ + delay(ms); +} + + int16_t hal_i2c_slave_address_available(uint8_t sa) { diff --git a/i2c-stick-arduino/i2c_stick.h b/i2c-stick-arduino/i2c_stick.h index 3a9d26a..401c2ed 100644 --- a/i2c-stick-arduino/i2c_stick.h +++ b/i2c-stick-arduino/i2c_stick.h @@ -74,7 +74,6 @@ void send_broadcast_message(const char *msg); void send_answer_chunk(uint8_t channel_mask, const char *answer, uint8_t terminate); void send_answer_chunk_binary(uint8_t channel_mask, const char *blob, uint16_t length, uint8_t terminate); - int16_t i2c_stick_register_driver(uint8_t sa, uint8_t drv); #ifdef __cplusplus diff --git a/i2c-stick-arduino/i2c_stick_cmd.cpp b/i2c-stick-arduino/i2c_stick_cmd.cpp index e946567..bb41f63 100644 --- a/i2c-stick-arduino/i2c_stick_cmd.cpp +++ b/i2c-stick-arduino/i2c_stick_cmd.cpp @@ -471,6 +471,11 @@ handle_cmd(uint8_t channel_mask, const char *cmd) g_sa_drv_register[spot].nd_ = 0; } + // SCL low for >1.44ms ==> MLX90614 in PWM or thermal relay requires this to enter communication mode + hal_write_pin(17u, 0); + hal_delay(2); + hal_write_pin(17u, 1); + for (uint8_t sa = 1; sa<128; sa++) { g_sa_list[sa].found_ = 0; diff --git a/i2c-stick-arduino/i2c_stick_dispatcher.cpp b/i2c-stick-arduino/i2c_stick_dispatcher.cpp index 697cff6..a44a184 100644 --- a/i2c-stick-arduino/i2c_stick_dispatcher.cpp +++ b/i2c-stick-arduino/i2c_stick_dispatcher.cpp @@ -1,5 +1,452 @@ // this file is automatically generated: // please edit 'context.yaml', and then: -// run the makefile `make source`. +// run the python doit script `python dodo.py source` or `doit source`. -#error "This file should be automatically generated; please run `make source` from command line" +#include "i2c_stick_dispatcher.h" +#include "i2c_stick.h" +#include "i2c_stick_cmd.h" + +// Include all the drivers cmd header files: +#include "mlx90614_cmd.h" +#include "mlx90640_cmd.h" +#include "mlx90641_cmd.h" +#include "mlx90632_cmd.h" +#include "mlx90621_cmd.h" + +#include +#include + +int16_t +i2c_stick_register_all_drivers() +{ + int16_t result = 1; + if (cmd_90614_register_driver() < 0) result = -1; + if (cmd_90640_register_driver() < 0) result = -1; + if (cmd_90641_register_driver() < 0) result = -1; + if (cmd_90632_register_driver() < 0) result = -1; + if (cmd_90621_register_driver() < 0) result = -1; + return result; +} + + +const char* +i2c_stick_get_drv_name_by_drv(uint8_t drv) +{ + switch(drv) + { + case DRV_MLX90614_ID: + return DRV_MLX90614_NAME; + case DRV_MLX90640_ID: + return DRV_MLX90640_NAME; + case DRV_MLX90641_ID: + return DRV_MLX90641_NAME; + case DRV_MLX90632_ID: + return DRV_MLX90632_NAME; + case DRV_MLX90621_ID: + return DRV_MLX90621_NAME; + default: + if (0) {} + } + return "Unknown"; +} + + +uint8_t +i2c_stick_get_drv_by_drv_name(const char *drv_name) +{ + if (!strcasecmp(drv_name, DRV_MLX90614_NAME)) return DRV_MLX90614_ID; + if (!strcasecmp(drv_name, DRV_MLX90640_NAME)) return DRV_MLX90640_ID; + if (!strcasecmp(drv_name, DRV_MLX90641_NAME)) return DRV_MLX90641_ID; + if (!strcasecmp(drv_name, DRV_MLX90632_NAME)) return DRV_MLX90632_ID; + if (!strcasecmp(drv_name, DRV_MLX90621_NAME)) return DRV_MLX90621_ID; + return 0; +} + + + +// command functions. + +uint8_t +cmd_mv(uint8_t sa, float *mv_list, uint16_t *mv_count, char const **error_message) +{ + // sanity check + if (sa > 127) { return 0; } + + uint16_t spot = g_sa_list[sa].spot_; + uint8_t drv = g_sa_drv_register[spot].drv_; + + switch(drv) + { + case DRV_MLX90614_ID: + cmd_90614_mv(sa, mv_list, mv_count, error_message); + break; + case DRV_MLX90640_ID: + cmd_90640_mv(sa, mv_list, mv_count, error_message); + break; + case DRV_MLX90641_ID: + cmd_90641_mv(sa, mv_list, mv_count, error_message); + break; + case DRV_MLX90632_ID: + cmd_90632_mv(sa, mv_list, mv_count, error_message); + break; + case DRV_MLX90621_ID: + cmd_90621_mv(sa, mv_list, mv_count, error_message); + break; + default: + return 0; + } + return drv; +} + + +uint8_t +cmd_raw(uint8_t sa, uint16_t *raw_list, uint16_t *raw_count, char const **error_message) +{ + // sanity check + if (sa > 127) { return 0; } + + uint16_t spot = g_sa_list[sa].spot_; + uint8_t drv = g_sa_drv_register[spot].drv_; + + switch(drv) + { + case DRV_MLX90614_ID: + cmd_90614_raw(sa, raw_list, raw_count, error_message); + break; + case DRV_MLX90640_ID: + cmd_90640_raw(sa, raw_list, raw_count, error_message); + break; + case DRV_MLX90641_ID: + cmd_90641_raw(sa, raw_list, raw_count, error_message); + break; + case DRV_MLX90632_ID: + cmd_90632_raw(sa, raw_list, raw_count, error_message); + break; + case DRV_MLX90621_ID: + cmd_90621_raw(sa, raw_list, raw_count, error_message); + break; + default: + return 0; + } + return drv; +} + + +uint8_t +cmd_nd(uint8_t sa, uint8_t *nd, char const **error_message) +{ + // sanity check + if (sa > 127) { return 0; } + + uint16_t spot = g_sa_list[sa].spot_; + uint8_t drv = g_sa_drv_register[spot].drv_; + + switch(drv) + { + case DRV_MLX90614_ID: + cmd_90614_nd(sa, nd, error_message); + break; + case DRV_MLX90640_ID: + cmd_90640_nd(sa, nd, error_message); + break; + case DRV_MLX90641_ID: + cmd_90641_nd(sa, nd, error_message); + break; + case DRV_MLX90632_ID: + cmd_90632_nd(sa, nd, error_message); + break; + case DRV_MLX90621_ID: + cmd_90621_nd(sa, nd, error_message); + break; + default: + return 0; + } + return drv; +} + + +uint8_t +cmd_sn(uint8_t sa, uint16_t *sn_list, uint16_t *sn_count, char const **error_message) +{ + // sanity check + if (sa > 127) { return 0; } + + uint16_t spot = g_sa_list[sa].spot_; + uint8_t drv = g_sa_drv_register[spot].drv_; + + switch(drv) + { + case DRV_MLX90614_ID: + cmd_90614_sn(sa, sn_list, sn_count, error_message); + break; + case DRV_MLX90640_ID: + cmd_90640_sn(sa, sn_list, sn_count, error_message); + break; + case DRV_MLX90641_ID: + cmd_90641_sn(sa, sn_list, sn_count, error_message); + break; + case DRV_MLX90632_ID: + cmd_90632_sn(sa, sn_list, sn_count, error_message); + break; + case DRV_MLX90621_ID: + cmd_90621_sn(sa, sn_list, sn_count, error_message); + break; + default: + *sn_count = 0; + return 0; + } + return drv; +} + + +uint8_t +cmd_cs(uint8_t sa, uint8_t channel_mask, const char *input) +{ + // sanity check + if (sa > 127) { return 0; } + + uint16_t spot = g_sa_list[sa].spot_; + uint8_t drv = g_sa_drv_register[spot].drv_; + uint8_t raw = g_sa_drv_register[spot].raw_; + + char buf[16]; memset(buf, 0, sizeof(buf)); + + send_answer_chunk(channel_mask, "cs:", 0); + uint8_to_hex(buf, sa); + send_answer_chunk(channel_mask, buf, 0); + send_answer_chunk(channel_mask, ":RAW=", 0); + itoa(raw, buf, 10); + send_answer_chunk(channel_mask, buf, 1); + + switch(drv) + { + case DRV_MLX90614_ID: + cmd_90614_cs(sa, channel_mask, input); + break; + case DRV_MLX90640_ID: + cmd_90640_cs(sa, channel_mask, input); + break; + case DRV_MLX90641_ID: + cmd_90641_cs(sa, channel_mask, input); + break; + case DRV_MLX90632_ID: + cmd_90632_cs(sa, channel_mask, input); + break; + case DRV_MLX90621_ID: + cmd_90621_cs(sa, channel_mask, input); + break; + default: + return 0; + } + return drv; +} + + +uint8_t +cmd_cs_write(uint8_t sa, uint8_t channel_mask, const char *input) +{ + // sanity check + if (sa > 127) { return 0; } + + uint16_t spot = g_sa_list[sa].spot_; + uint8_t drv = g_sa_drv_register[spot].drv_; + + char buf[16]; memset(buf, 0, sizeof(buf)); + + const char *var_name = "RAW="; + if (!strncmp(var_name, input, strlen(var_name))) + { + // 1.1. try to find if the desired value is a 'driver-name' + int16_t value = atoi(input+strlen(var_name)); + if ((value >= 0) && (value <= 1)) + { + if (value == 1) + { + g_sa_drv_register[spot].raw_ = 1; + } else + { + g_sa_drv_register[spot].raw_ = 0; + } + send_answer_chunk(channel_mask, "+cs:", 0); + uint8_to_hex(buf, sa); + send_answer_chunk(channel_mask, buf, 0); + send_answer_chunk(channel_mask, ":RAW=", 0); + uint8_to_hex(buf, g_sa_drv_register[spot].raw_); + send_answer_chunk(channel_mask, buf, 0); + send_answer_chunk(channel_mask, ":OK [host-register]", 1); + } else + { + send_answer_chunk(channel_mask, "+cs:", 0); + uint8_to_hex(buf, sa); + send_answer_chunk(channel_mask, buf, 0); + send_answer_chunk(channel_mask, ":RAW= FAIL; value not valid", 1); + } + return drv; + } + + switch(drv) + { + case DRV_MLX90614_ID: + cmd_90614_cs_write(sa, channel_mask, input); + break; + case DRV_MLX90640_ID: + cmd_90640_cs_write(sa, channel_mask, input); + break; + case DRV_MLX90641_ID: + cmd_90641_cs_write(sa, channel_mask, input); + break; + case DRV_MLX90632_ID: + cmd_90632_cs_write(sa, channel_mask, input); + break; + case DRV_MLX90621_ID: + cmd_90621_cs_write(sa, channel_mask, input); + break; + default: + return 0; + } + return drv; +} + + +uint8_t +cmd_mr(uint8_t sa, uint16_t *mem_list, uint16_t mem_start_address, uint16_t mem_count, uint8_t *bit_per_address, uint8_t *address_increments, char const **error_message) +{ + // sanity check + if (sa > 127) { return 0; } + + uint16_t spot = g_sa_list[sa].spot_; + uint8_t drv = g_sa_drv_register[spot].drv_; + + switch(drv) + { + case DRV_MLX90614_ID: + cmd_90614_mr(sa, mem_list, mem_start_address, mem_count, bit_per_address, address_increments, error_message); + break; + case DRV_MLX90640_ID: + cmd_90640_mr(sa, mem_list, mem_start_address, mem_count, bit_per_address, address_increments, error_message); + break; + case DRV_MLX90641_ID: + cmd_90641_mr(sa, mem_list, mem_start_address, mem_count, bit_per_address, address_increments, error_message); + break; + case DRV_MLX90632_ID: + cmd_90632_mr(sa, mem_list, mem_start_address, mem_count, bit_per_address, address_increments, error_message); + break; + case DRV_MLX90621_ID: + cmd_90621_mr(sa, mem_list, mem_start_address, mem_count, bit_per_address, address_increments, error_message); + break; + default: + return 0; + } + + return drv; +} + + +uint8_t +cmd_mw(uint8_t sa, uint16_t *mem_list, uint16_t mem_start_address, uint16_t mem_count, uint8_t *bit_per_address, uint8_t *address_increments, char const **error_message) +{ + // sanity check + if (sa > 127) { return 0; } + + uint16_t spot = g_sa_list[sa].spot_; + uint8_t drv = g_sa_drv_register[spot].drv_; + + switch(drv) + { + case DRV_MLX90614_ID: + cmd_90614_mw(sa, mem_list, mem_start_address, mem_count, bit_per_address, address_increments, error_message); + break; + case DRV_MLX90640_ID: + cmd_90640_mw(sa, mem_list, mem_start_address, mem_count, bit_per_address, address_increments, error_message); + break; + case DRV_MLX90641_ID: + cmd_90641_mw(sa, mem_list, mem_start_address, mem_count, bit_per_address, address_increments, error_message); + break; + case DRV_MLX90632_ID: + cmd_90632_mw(sa, mem_list, mem_start_address, mem_count, bit_per_address, address_increments, error_message); + break; + case DRV_MLX90621_ID: + cmd_90621_mw(sa, mem_list, mem_start_address, mem_count, bit_per_address, address_increments, error_message); + break; + default: + return 0; + } + + return drv; +} + + +uint8_t +cmd_is(uint8_t sa, uint8_t drv, uint8_t *is_ok, char const **error_message) +{ + if ((drv <= 0) || (drv > 63)) + { + *is_ok = 0; + return 0; + } + + switch(drv) + { + case DRV_MLX90614_ID: + cmd_90614_is(sa, is_ok, error_message); + break; + case DRV_MLX90640_ID: + cmd_90640_is(sa, is_ok, error_message); + break; + case DRV_MLX90641_ID: + cmd_90641_is(sa, is_ok, error_message); + break; + case DRV_MLX90632_ID: + cmd_90632_is(sa, is_ok, error_message); + break; + case DRV_MLX90621_ID: + cmd_90621_is(sa, is_ok, error_message); + break; + default: + return 0; + } + + return drv; +} + + + +uint8_t +cmd_tear_down(uint8_t sa) +{ + if (sa == 255) + { + for (sa = 0; sa <= 127; sa++) + { + cmd_tear_down(sa); + } + return sa; + } + // sanity check + if (sa > 127) { return 0; } + + uint16_t spot = g_sa_list[sa].spot_; + uint8_t drv = g_sa_drv_register[spot].drv_; + + switch(drv) + { + case DRV_MLX90614_ID: + cmd_90614_tear_down(sa); + break; + case DRV_MLX90640_ID: + cmd_90640_tear_down(sa); + break; + case DRV_MLX90641_ID: + cmd_90641_tear_down(sa); + break; + case DRV_MLX90632_ID: + cmd_90632_tear_down(sa); + break; + case DRV_MLX90621_ID: + cmd_90621_tear_down(sa); + break; + default: + return 0; + } + return drv; +} \ No newline at end of file diff --git a/i2c-stick-arduino/i2c_stick_dispatcher.cpp.jinja2 b/i2c-stick-arduino/i2c_stick_dispatcher.cpp.jinja2 index 909c2d0..00b057b 100644 --- a/i2c-stick-arduino/i2c_stick_dispatcher.cpp.jinja2 +++ b/i2c-stick-arduino/i2c_stick_dispatcher.cpp.jinja2 @@ -1,6 +1,6 @@ // this file is automatically generated: // please edit 'context.yaml', and then: -// run the makefile `make source`. +// run the python doit script `python dodo.py generate` or `doit generate`. #include "i2c_stick_dispatcher.h" #include "i2c_stick.h" diff --git a/i2c-stick-arduino/i2c_stick_dispatcher.h b/i2c-stick-arduino/i2c_stick_dispatcher.h index 697cff6..78a2b3d 100644 --- a/i2c-stick-arduino/i2c_stick_dispatcher.h +++ b/i2c-stick-arduino/i2c_stick_dispatcher.h @@ -1,5 +1,46 @@ // this file is automatically generated: // please edit 'context.yaml', and then: -// run the makefile `make source`. +// run the python doit script `python dodo.py source` or `doit source`. -#error "This file should be automatically generated; please run `make source` from command line" +#ifndef __I2C_STICK_DISPATCHER_H__ +#define __I2C_STICK_DISPATCHER_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +// driver declarations: +#define DRV_MLX90614_ID 1 +#define DRV_MLX90614_NAME "MLX90614" +#define DRV_MLX90640_ID 2 +#define DRV_MLX90640_NAME "MLX90640" +#define DRV_MLX90641_ID 3 +#define DRV_MLX90641_NAME "MLX90641" +#define DRV_MLX90632_ID 4 +#define DRV_MLX90632_NAME "MLX90632" +#define DRV_MLX90621_ID 5 +#define DRV_MLX90621_NAME "MLX90621" + +int16_t i2c_stick_register_all_drivers(); +const char* i2c_stick_get_drv_name_by_drv(uint8_t drv); +uint8_t i2c_stick_get_drv_by_drv_name(const char *drv_name); + +uint8_t cmd_mv(uint8_t sa, float *mv_list, uint16_t *mv_count, char const **error_message); +uint8_t cmd_raw(uint8_t sa, uint16_t *raw_list, uint16_t *raw_count, char const **error_message); +uint8_t cmd_nd(uint8_t sa, uint8_t *nd, char const **error_message); +uint8_t cmd_sn(uint8_t sa, uint16_t *sn_list, uint16_t *sn_count, char const **error_message); +uint8_t cmd_cs(uint8_t sa, uint8_t channel_mask, const char *input); +uint8_t cmd_cs_write(uint8_t sa, uint8_t channel_mask, const char *input); +uint8_t cmd_mr(uint8_t sa, uint16_t *mem_list, uint16_t mem_start_address, uint16_t mem_count, uint8_t *bit_per_address, uint8_t *address_increments, char const **error_message); +uint8_t cmd_mw(uint8_t sa, uint16_t *mem_list, uint16_t mem_start_address, uint16_t mem_count, uint8_t *bit_per_address, uint8_t *address_increments, char const **error_message); + +uint8_t cmd_is(uint8_t sa, uint8_t drv, uint8_t *is_ok, char const **error_message); +uint8_t cmd_tear_down(uint8_t sa); + +#ifdef __cplusplus +} +#endif + +#endif // __I2C_STICK_DISPATCHER_H__ \ No newline at end of file diff --git a/i2c-stick-arduino/i2c_stick_dispatcher.h.jinja2 b/i2c-stick-arduino/i2c_stick_dispatcher.h.jinja2 index e94f337..eb17967 100644 --- a/i2c-stick-arduino/i2c_stick_dispatcher.h.jinja2 +++ b/i2c-stick-arduino/i2c_stick_dispatcher.h.jinja2 @@ -1,6 +1,6 @@ // this file is automatically generated: // please edit 'context.yaml', and then: -// run the makefile `make source`. +// run the python doit script `python dodo.py generate` or `doit generate`. #ifndef __I2C_STICK_DISPATCHER_H__ #define __I2C_STICK_DISPATCHER_H__ diff --git a/i2c-stick-arduino/i2c_stick_hal.h b/i2c-stick-arduino/i2c_stick_hal.h index 51b3f56..8e3d7fb 100644 --- a/i2c-stick-arduino/i2c_stick_hal.h +++ b/i2c-stick-arduino/i2c_stick_hal.h @@ -9,7 +9,9 @@ extern "C" { const char *hal_get_board_info(); +void hal_delay(uint32_t ms); uint64_t hal_get_millis(); + int16_t hal_i2c_slave_address_available(uint8_t sa); void hal_i2c_set_clock_frequency(uint32_t frequency_in_hz); @@ -17,6 +19,9 @@ int16_t hal_i2c_direct_read(uint8_t sa, uint8_t *read_buffer, uint16_t read_n_by int16_t hal_i2c_direct_write(uint8_t sa, uint8_t *write_buffer, uint16_t write_n_bytes); int16_t hal_i2c_indirect_read(uint8_t sa, uint8_t *write_buffer, uint16_t write_n_bytes, uint8_t *read_buffer, uint16_t read_n_bytes); +void hal_write_pin(uint8_t pin, uint8_t state); +uint8_t hal_read_pin(uint8_t pin); + void hal_i2c_set_pwm(uint8_t pin_no, uint8_t pwm); #ifdef __cplusplus diff --git a/i2c-stick-arduino/mailmerge.py b/i2c-stick-arduino/mailmerge.py index 331960a..18796ec 100644 --- a/i2c-stick-arduino/mailmerge.py +++ b/i2c-stick-arduino/mailmerge.py @@ -1,30 +1,25 @@ import os import sys import yaml - -from jinja2 import Environment, FileSystemLoader, select_autoescape +import jinja2 +import yamlinclude +import argparse # Capture our current directory THIS_DIR = os.path.dirname(os.path.abspath(__file__)) -from yamlinclude import YamlIncludeConstructor - -YamlIncludeConstructor.add_to_loader_class(loader_class=yaml.FullLoader, base_dir=THIS_DIR) -loader=FileSystemLoader(THIS_DIR) +yamlinclude.YamlIncludeConstructor.add_to_loader_class(loader_class=yaml.FullLoader, base_dir=THIS_DIR) +loader = jinja2.FileSystemLoader(THIS_DIR) - -import argparse - argParser = argparse.ArgumentParser() argParser.add_argument("-c", "--context", default="context.yaml", help="the context yaml file") -argParser.add_argument("-t", "--template", help="the template file to be used") -argParser.add_argument("-o", "--output", help="the output file name") +argParser.add_argument("-t", "--template", help="the template file to be used") +argParser.add_argument("-o", "--output", help="the output file name") args = argParser.parse_args() - if args.template is None: print("ERROR: Please supply a template file") sys.exit(0) @@ -37,14 +32,12 @@ print("ERROR: Please supply an output file different from template file.") sys.exit(0) - with open(args.context, 'r') as file: context = yaml.load(file, Loader=yaml.FullLoader) - -env = Environment( +env = jinja2.Environment( loader=loader, - autoescape=select_autoescape() + autoescape=jinja2.select_autoescape() ) template = env.get_template(args.template) diff --git a/i2c-stick-arduino/mlx90614_cmd.h b/i2c-stick-arduino/mlx90614_cmd.h index b9afa77..8f18342 100644 --- a/i2c-stick-arduino/mlx90614_cmd.h +++ b/i2c-stick-arduino/mlx90614_cmd.h @@ -29,7 +29,6 @@ void cmd_90614_is(uint8_t sa, uint8_t *is_ok, char const **error_message); void cmd_90614_tear_down(uint8_t sa); - #ifdef __cplusplus } #endif diff --git a/i2c-stick-arduino/mlx90621_api.cpp b/i2c-stick-arduino/mlx90621_api.cpp new file mode 100644 index 0000000..3400d4d --- /dev/null +++ b/i2c-stick-arduino/mlx90621_api.cpp @@ -0,0 +1,474 @@ +/** + * @copyright (C) 2017 Melexis N.V. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#include "mlx90621_i2c_driver.h" +#include "mlx90621_api.h" +#include + + +void ExtractPTATParameters(uint8_t *eeData, paramsMLX90621 *mlx90621); +void ExtractTgcParameters(uint8_t *eeData, paramsMLX90621 *mlx90621); +void ExtractKsTaParameters(uint8_t *eeData, paramsMLX90621 *mlx90621); +void ExtractKsToParameters(uint8_t *eeData, paramsMLX90621 *mlx90621); +void ExtractAlphaParameters(uint8_t *eeData, paramsMLX90621 *mlx90621); +void ExtractOffsetParameters(uint8_t *eeData, paramsMLX90621 *mlx90621); + + +int MLX90621_DumpEE(uint8_t *eeData) +{ + return MLX90621_I2CReadEEPROM(0x50, 0, 256, eeData); +} + + +int MLX90621_GetFrameData(uint16_t *frameData) +{ + int error = 1; + + error = MLX90621_I2CRead(0x60, 0x02, 0, 1, 66, frameData); + + return error; +} + +int MLX90621_Configure(uint8_t *eeData) +{ + int error = 1; + uint16_t value; + + error = MLX90621_I2CWrite(0x60, 0x04, 0xAA, eeData[247]); + + if (error != 0) + { + return error; + } + + value = 256*eeData[246] + eeData[245]; + value = value | 0x0400; + error = MLX90621_I2CWrite(0x60, 0x03, 0x55, value); + + return error; + +} + +int MLX90621_GetOscillatorTrim(uint16_t *oscTrim) +{ + int error = 1; + + error = MLX90621_I2CRead(0x60, 0x02, 0x93, 0, 1, oscTrim); + + return error; +} + +int MLX90621_GetConfiguration(uint16_t *cfgReg) +{ + int error = 1; + + error = MLX90621_I2CRead(0x60, 0x02, 0x92, 0, 1, cfgReg); + + return error; +} + + +int MLX90621_ExtractParameters(uint8_t *eeData, paramsMLX90621 *mlx90621) +{ + int error = 0; + + ExtractPTATParameters(eeData, mlx90621); + ExtractTgcParameters(eeData, mlx90621); + ExtractKsTaParameters(eeData, mlx90621); + ExtractKsToParameters(eeData, mlx90621); + ExtractAlphaParameters(eeData, mlx90621); + ExtractOffsetParameters(eeData, mlx90621); + + return error; + +} + +//------------------------------------------------------------------------------ + +int MLX90621_SetResolution(uint8_t resolution) +{ + uint16_t cfgReg; + int value; + int error; + + value = (resolution & 0x03) << 4; + + error = MLX90621_GetConfiguration(&cfgReg); + + if(error == 0) + { + value = (cfgReg & 0xFFCF) | value; + error = MLX90621_I2CWrite(0x60, 0x03, 0x55, value); + } + + return error; +} + +//------------------------------------------------------------------------------ + +int MLX90621_GetCurResolution() +{ + uint16_t cfgReg; + int resolution; + int error; + + error = MLX90621_GetConfiguration(&cfgReg); + if(error != 0) + { + return error; + } + resolution = (cfgReg & 0x0030) >> 4; + + return resolution; +} + +//------------------------------------------------------------------------------ + +int MLX90621_SetRefreshRate(uint8_t refreshRate) +{ + uint16_t cfgReg; + int value; + int error; + + value = refreshRate & 0x0F; + + error = MLX90621_GetConfiguration(&cfgReg); + + if(error == 0) + { + value = (cfgReg & 0xFFF0) | value; + error = MLX90621_I2CWrite(0x60, 0x03, 0x55, value); + } + + return error; +} + +//------------------------------------------------------------------------------ + +int MLX90621_GetRefreshRate() +{ + uint16_t cfgReg; + int rr; + int error; + + error = MLX90621_GetConfiguration(&cfgReg); + if(error != 0) + { + return error; + } + rr = (cfgReg & 0x000F); + + return rr; +} + +//------------------------------------------------------------------------------ + +void MLX90621_CalculateTo(uint16_t *frameData, const paramsMLX90621 *params, float emissivity, float tr, float *result) +{ + float ta; + float ta4; + float tr4; + float taTr; + float irDataCP; + float irData; + float alphaCompensated; + float Sx; + float To; + + ta = MLX90621_GetTa(frameData, params); + + ta4 = (ta + 273.15); + ta4 = ta4 * ta4; + ta4 = ta4 * ta4; + tr4 = (tr + 273.15); + tr4 = tr4 * tr4; + tr4 = tr4 * tr4; + taTr = tr4 - (tr4-ta4)/emissivity; + +//------------------------- To calculation ------------------------------------- + + irDataCP = frameData[65]; + + if(irDataCP > 32767) + { + irDataCP = irDataCP - 65536; + } + + irDataCP = irDataCP - (params->cpA + params->cpB * (ta - 25)); + + for( int pixelNumber = 0; pixelNumber < 64; pixelNumber++) + { + irData = frameData[pixelNumber]; + if(irData > 32767) + { + irData = irData - 65536; + } + + irData = irData - (params->ai[pixelNumber] + params->bi[pixelNumber] * (ta - 25)); + + irData = irData - params->tgc * irDataCP; + irData = irData / emissivity; + + alphaCompensated = params->alpha[pixelNumber] - params->tgc * params->cpAlpha; + alphaCompensated = alphaCompensated *(1 + params->KsTa * (ta - 25)); + + Sx = alphaCompensated * alphaCompensated * alphaCompensated * (irData + alphaCompensated * taTr); + Sx = sqrt(sqrt(Sx)) * params->ksTo; + + To = sqrt(sqrt(irData/(alphaCompensated * (1 - params->ksTo * 273.15) + Sx) + taTr)) - 273.15; + + result[pixelNumber] = To; + + } +} + +//------------------------------------------------------------------------------ + +void MLX90621_GetImage(uint16_t *frameData, const paramsMLX90621 *params, float *result) +{ + float ta; + float irDataCP; + float irData; + float alphaCompensated; + + ta = MLX90621_GetTa(frameData, params); + +//------------------------- Image calculation ------------------------------------- + + irDataCP = frameData[65]; + + if(irDataCP > 32767) + { + irDataCP = irDataCP - 65536; + } + + irDataCP = irDataCP - (params->cpA + params->cpB * (ta - 25)); + + for( int pixelNumber = 0; pixelNumber < 64; pixelNumber++) + { + irData = frameData[pixelNumber]; + if(irData > 32767) + { + irData = irData - 65536; + } + + irData = irData - (params->ai[pixelNumber] + params->bi[pixelNumber] * (ta - 25)); + + irData = irData - params->tgc * irDataCP; + + alphaCompensated = params->alpha[pixelNumber] - params->tgc * irDataCP; + alphaCompensated = alphaCompensated *(1 + params->KsTa * (ta - 25)); + + result[pixelNumber] = irData/alphaCompensated; + + } +} + +//------------------------------------------------------------------------------ + +float MLX90621_GetTa(uint16_t *frameData, const paramsMLX90621 *params) +{ + float ptat; + float ta; + + ptat = frameData[64]; + if(ptat > 32767) + { + ptat = ptat - 65536; + } + + ta = params->vTh25 - ptat; + ta = 4*params->kT2*ta; + ta = params->kT1*params->kT1 - ta; + ta = sqrt(ta)-params->kT1; + ta = ta / (2*params->kT2); + ta = ta + 25; + + return ta; +} + +//------------------------------------------------------------------------------ + +void ExtractPTATParameters(uint8_t *eeData, paramsMLX90621 *mlx90621) +{ + float kt1; + float kt2; + int16_t vth25; + int kt1Scale = 0; + int kt2Scale = 0; + int resolution = 3; + uint16_t data; + + resolution = resolution - MLX90621_GetCurResolution(); + kt1Scale = (eeData[210] & 0xF0) >> 4; + kt2Scale = eeData[210] & 0x0F; + kt2Scale = kt2Scale + 10; + kt1Scale = kt1Scale + resolution; + kt2Scale = kt2Scale + resolution; + + data = (eeData[219]<<8) + eeData[218]; + vth25 = data; + + kt1 = (eeData[221]<<8) + eeData[220]; + if (kt1 > 32767) + { + kt1 = kt1 - 65536; + } + + kt1 = kt1 / (1< 32767) + { + kt2 = kt2 - 65536; + } + + kt2 = kt2 / (1<vTh25 = vth25; + mlx90621->kT1 = kt1; + mlx90621->kT2 = kt2; + +} + +//------------------------------------------------------------------------------ + +void ExtractTgcParameters(uint8_t *eeData, paramsMLX90621 *mlx90621) +{ + float tgc; + tgc = eeData[216]/32.0f; + + mlx90621->tgc = tgc; +} + +//------------------------------------------------------------------------------ + +void ExtractKsTaParameters(uint8_t *eeData, paramsMLX90621 *mlx90621) +{ + float KsTa; + KsTa = (eeData[231] << 8) + eeData[230]; + if(KsTa > 32767) + { + KsTa = KsTa - 65536; + } + KsTa = KsTa / (1<<20); + + mlx90621->KsTa = KsTa; +} + +//------------------------------------------------------------------------------ + +void ExtractKsToParameters(uint8_t *eeData, paramsMLX90621 *mlx90621) +{ + int scale; + + scale = eeData[192] & 0x0F; + scale = scale + 8; + + mlx90621->ksTo = eeData[196]; + + if(mlx90621->ksTo > 127) + { + mlx90621->ksTo = mlx90621->ksTo - 256; + } + mlx90621->ksTo = mlx90621->ksTo / (1 << scale); + +} + +//------------------------------------------------------------------------------ + +void ExtractAlphaParameters(uint8_t *eeData, paramsMLX90621 *mlx90621) +{ + double alphaScale; + double deltaScale; + uint8_t resScale; + float alphaCom; + float alphaTemp; + float temp; + + alphaScale = eeData[226]; + deltaScale = eeData[227]; + resScale = 3 - MLX90621_GetCurResolution(); + alphaCom = (eeData[225]<<8) + eeData[224]; + alphaScale = pow(2,alphaScale); + deltaScale = pow(2,deltaScale); + alphaCom = alphaCom / alphaScale; + + for(int i = 0; i < 64; i++) + { + temp = eeData[128+i]; + temp = temp / deltaScale; + alphaTemp = (alphaCom + temp)/(1<alpha[i] = alphaTemp; + } + + alphaTemp = (eeData[215]<<8) + eeData[214]; + alphaTemp = alphaTemp / alphaScale; + + mlx90621->cpAlpha = alphaTemp / (1<>4; + bScale = eeData[217] & 0x0F; + resScale = 3 - MLX90621_GetCurResolution(); + bScale = pow(2, (double)(bScale+resScale)); + + data = (eeData[209]<<8) + eeData[208]; + aCom = data; + + for(int i=0; i<64; i++) + { + aTemp = eeData[i]< 127) + { + bTemp = bTemp - 256; + } + bTemp = bTemp / bScale; + + mlx90621->ai[i] = (aCom + aTemp) / (1<bi[i] = bTemp; + } + + aTemp = (eeData[212]<<8) + eeData[211]; + if (aTemp > 32767) + { + aTemp = aTemp - 65536; + } + aTemp = aTemp / (1< 127) + { + bTemp = bTemp - 256; + } + bTemp = bTemp / bScale; + + mlx90621->cpA = aTemp; + mlx90621->cpB = bTemp; +} diff --git a/i2c-stick-arduino/mlx90621_api.h b/i2c-stick-arduino/mlx90621_api.h new file mode 100644 index 0000000..3238361 --- /dev/null +++ b/i2c-stick-arduino/mlx90621_api.h @@ -0,0 +1,54 @@ +/** + * @copyright (C) 2017 Melexis N.V. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#ifndef _MLX621_API_H_ +#define _MLX621_API_H_ + +#define SCALEALPHA 0.000001 + +typedef struct + { + int16_t vTh25; + float kT1; + float kT2; + float tgc; + float KsTa; + float ksTo; + float alpha[64]; + float ai[64]; + float bi[64]; + float cpAlpha; + float cpA; + float cpB; + uint16_t brokenPixels[5]; + uint16_t outlierPixels[5]; + } paramsMLX90621; + + int MLX90621_DumpEE(uint8_t *eeData); + int MLX90621_GetFrameData(uint16_t *frameData); + int MLX90621_Configure(uint8_t *eeData); + int MLX90621_GetOscillatorTrim(uint16_t *oscTrim); + int MLX90621_GetConfiguration(uint16_t *cfgReg); + int MLX90621_ExtractParameters(uint8_t *eeData, paramsMLX90621 *mlx90621); + float MLX90621_GetTa(uint16_t *frameData, const paramsMLX90621 *params); + void MLX90621_GetImage(uint16_t *frameData, const paramsMLX90621 *params, float *result); + void MLX90621_CalculateTo(uint16_t *frameData, const paramsMLX90621 *params, float emissivity, float tr, float *result); + int MLX90621_SetResolution(uint8_t resolution); + int MLX90621_GetCurResolution(); + int MLX90621_SetRefreshRate(uint8_t refreshRate); + int MLX90621_GetRefreshRate(); + +#endif diff --git a/i2c-stick-arduino/mlx90621_cmd.cpp b/i2c-stick-arduino/mlx90621_cmd.cpp new file mode 100644 index 0000000..1254020 --- /dev/null +++ b/i2c-stick-arduino/mlx90621_cmd.cpp @@ -0,0 +1,457 @@ +#include "mlx90621_cmd.h" +#include "i2c_stick.h" +#include "i2c_stick_cmd.h" +#include "i2c_stick_dispatcher.h" +#include "i2c_stick_hal.h" + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef MAX_MLX90621_SLAVES +#define MAX_MLX90621_SLAVES 8 +#endif // MAX_MLX90621_SLAVES + +#define MLX90621_ERROR_BUFFER_TOO_SMALL "Buffer too small" +#define MLX90621_ERROR_COMMUNICATION "Communication error" +#define MLX90621_ERROR_NO_FREE_HANDLE "No free handle; pls recompile firmware with higher 'MAX_MLX90621_SLAVES'" +#define MLX90621_ERROR_OUT_OF_RANGE "Out of range" + + +static MLX90621_t *g_mlx90621_list[MAX_MLX90621_SLAVES]; + + +MLX90621_t * +cmd_90621_get_handle(uint8_t sa) +{ + if (sa >= 128) + { + return NULL; + } + + for (uint8_t i=0; islave_address_ & 0x7F) == sa) + { // found! + return g_mlx90621_list[i]; + } + } + + // not found => try to find a handle with slave address zero (not yet initialized)! + for (uint8_t i=0; islave_address_ == 0) + { // found! + return g_mlx90621_list[i]; + } + } + + // not found => use first free spot! + uint8_t i=0; + for (; islave_address_ = 0x80 | sa; + return g_mlx90621_list[i]; + } + } + + return NULL; // no free spot available +} + + +static void +delete_handle(uint8_t sa) +{ + for (uint8_t i=0; islave_address_ & 0x7F) == sa) + { // found! + memset(g_mlx90621_list[i], 0, sizeof(MLX90621_t)); + free(g_mlx90621_list[i]); + g_mlx90621_list[i] = NULL; + } + } +} + + +int16_t +cmd_90621_register_driver() +{ + int16_t r = 0; + + r = i2c_stick_register_driver(0x60, DRV_MLX90621_ID); + if (r < 0) return r; + + return 1; +} + + +void +cmd_90621_init(uint8_t sa) +{ + MLX90621_t *mlx = cmd_90621_get_handle(sa); + if (mlx == NULL) + { + return; + } + // init functions goes here + + // turn off bit7, to indicate other routines this slave has been init + mlx->slave_address_ &= 0x7F; +} + + +void +cmd_90621_tear_down(uint8_t sa) +{ // nothing special to do, just release all associated memory + delete_handle(sa); +} + + +void +cmd_90621_mv(uint8_t sa, float *mv_list, uint16_t *mv_count, char const **error_message) +{ + MLX90621_t *mlx = cmd_90621_get_handle(sa); + if (mlx == NULL) + { + *mv_count = 0; + *error_message = MLX90621_ERROR_NO_FREE_HANDLE; + return; + } + if (mlx->slave_address_ & 0x80) + { + cmd_90621_init(sa); + } + + if (*mv_count <= 2) // check Measurement Value buffer length + { + *mv_count = 0; + *error_message = MLX90621_ERROR_BUFFER_TOO_SMALL; + return; + } + *mv_count = 2; + + // todo: + // + // get the measurement values from the sensor + // +} + + +void +cmd_90621_raw(uint8_t sa, uint16_t *raw_list, uint16_t *raw_count, char const **error_message) +{ + MLX90621_t *mlx = cmd_90621_get_handle(sa); + if (mlx == NULL) + { + *raw_count = 0; + *error_message = MLX90621_ERROR_NO_FREE_HANDLE; + return; + } + if (mlx->slave_address_ & 0x80) + { + cmd_90621_init(sa); + } + + if (*raw_count < 3) // check Raw Value buffer length + { + *raw_count = 0; // input buffer not long enough, report nothing. + *error_message = MLX90621_ERROR_BUFFER_TOO_SMALL; + return; + } + *raw_count = 3; + + // todo: + // + // get the raw values from the sensor + // +} + + +void +cmd_90621_nd(uint8_t sa, uint8_t *nd, char const **error_message) +{ + MLX90621_t *mlx = cmd_90621_get_handle(sa); + if (mlx == NULL) + { + *error_message = MLX90621_ERROR_NO_FREE_HANDLE; + return; + } + if (mlx->slave_address_ & 0x80) + { + cmd_90621_init(sa); + } + + // todo: + // + // read the status from the sensor and check if new data is available (ND=New Data). + // + } + + +void +cmd_90621_sn(uint8_t sa, uint16_t *sn_list, uint16_t *sn_count, char const **error_message) +{ + MLX90621_t *mlx = cmd_90621_get_handle(sa); + if (mlx == NULL) + { + *sn_count = 0; + *error_message = MLX90621_ERROR_NO_FREE_HANDLE; + return; + } + if (mlx->slave_address_ & 0x80) + { + cmd_90621_init(sa); + } + + if (*sn_count < 4) // check the Serial Number buffer length + { + *sn_count = 0; // input buffer not long enough, report nothing. + *error_message = MLX90621_ERROR_BUFFER_TOO_SMALL; + return; + } + *sn_count = 4; + + // todo: + // + // read the serial number from the sensor. + // +} + + +void +cmd_90621_cs(uint8_t sa, uint8_t channel_mask, const char *input) +{ + MLX90621_t *mlx = cmd_90621_get_handle(sa); + if (mlx == NULL) + { + return; + } + if (mlx->slave_address_ & 0x80) + { + cmd_90621_init(sa); + } + + // todo: + // + // read the CS(Configuration of the Slave) from the sensor. + // + + char buf[16]; memset(buf, 0, sizeof(buf)); + send_answer_chunk(channel_mask, "cs:", 0); + uint8_to_hex(buf, sa); + send_answer_chunk(channel_mask, buf, 0); + send_answer_chunk(channel_mask, ":SA=", 0); + uint8_to_hex(buf, sa); + send_answer_chunk(channel_mask, buf, 1); + + + // todo: + // + // Send the answer back in the format + // "cs::=" + // + + + // todo: + // + // Send the configuration of the MV header, unit and resolution back to the terminal(not to sensor!) + // + + // send_answer_chunk(channel_mask, "cs:", 0); + // uint8_to_hex(buf, sa); + // send_answer_chunk(channel_mask, buf, 0); + // send_answer_chunk(channel_mask, ":RO:MV_HEADER=TA,TO", 1); + + // send_answer_chunk(channel_mask, "cs:", 0); + // uint8_to_hex(buf, sa); + // send_answer_chunk(channel_mask, buf, 0); + // send_answer_chunk(channel_mask, ":RO:MV_UNIT=DegC,DegC", 1); + + // send_answer_chunk(channel_mask, "cs:", 0); + // uint8_to_hex(buf, sa); + // send_answer_chunk(channel_mask, buf, 0); + // send_answer_chunk(channel_mask, ":RO:MV_RES=" xstr(MLX90614_LSB_C) "," xstr(MLX90614_LSB_C), 1); +} + + +void +cmd_90621_cs_write(uint8_t sa, uint8_t channel_mask, const char *input) +{ + char buf[16]; memset(buf, 0, sizeof(buf)); + MLX90621_t *mlx = cmd_90621_get_handle(sa); + if (mlx == NULL) + { + return; + } + if (mlx->slave_address_ & 0x80) + { + cmd_90621_init(sa); + } + + + // + // todo: + // + // write the configuration of the slave to the sensor and report to the channel the status. + // + // Please get inspired from other drivers like MLX90614. + // + // Also if SA can be re-programmed, please add the correct sequence here, see also MLX90614 or MLX90632 for an extensive example. + // + + // finally we have a catch all to inform the user that they asked something unknown. + send_answer_chunk(channel_mask, "+cs:", 0); + uint8_to_hex(buf, sa); + send_answer_chunk(channel_mask, buf, 0); + send_answer_chunk(channel_mask, ":FAIL; unknown variable", 1); +} + + +void +cmd_90621_mr(uint8_t sa, uint16_t *mem_data, uint16_t mem_start_address, uint16_t mem_count, uint8_t *bit_per_address, uint8_t *address_increments, char const **error_message) +{ + MLX90621_t *mlx = cmd_90621_get_handle(sa); + if (mlx == NULL) + { + *bit_per_address = 0; + *address_increments = 0; + *error_message = MLX90621_ERROR_NO_FREE_HANDLE; + return; + } + if (mlx->slave_address_ & 0x80) + { + cmd_90621_init(sa); + } + + // indicate 16 bit at each single address: + *bit_per_address = 16; + *address_increments = 1; + + if ((mem_start_address + mem_count) > 0x00FF) + { + *bit_per_address = 0; + *address_increments = 0; + *error_message = MLX90621_ERROR_OUT_OF_RANGE; + return; + } + + for (uint16_t i=0; islave_address_ & 0x80) + { + cmd_90621_init(sa); + } + + *bit_per_address = 16; + *address_increments = 1; + + if ((mem_start_address + mem_count) > 0x00FF) + { + *bit_per_address = 0; + *address_increments = 0; + *error_message = MLX90621_ERROR_OUT_OF_RANGE; + return; + } + + for (uint16_t i=0; i slave address is actually a MLX90621! + // often times this can be done by reading some specific values from the ROM or EEPROM, + // and verify the values are as expected. + // + + // remember there is no communication initiated yet... + + // in this ecample below for MLX90614 we check if the EEPROM reads the slave address at address 0x2E... + +// MLX90614_SMBusInit(); +// if (MLX90614_SMBusRead(sa, 0x2E, &value) < 0) + { + *error_message = MLX90621_ERROR_COMMUNICATION; + *is_ok = 0; + return; + } + if (value & 0x007F != sa) + { + *is_ok = 0; + } +} + + +#ifdef __cplusplus +} +#endif diff --git a/i2c-stick-arduino/mlx90621_cmd.h b/i2c-stick-arduino/mlx90621_cmd.h new file mode 100644 index 0000000..f063bde --- /dev/null +++ b/i2c-stick-arduino/mlx90621_cmd.h @@ -0,0 +1,36 @@ +#ifndef _MLX90621_CMD_ +#define _MLX90621_CMD_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct MLX90621_t +{ + uint8_t slave_address_; + // local caching of sensor values whenever needed; + // stored along with , such that multiple sensors can be supported. +}; + + +int16_t cmd_90621_register_driver(); + +void cmd_90621_mv(uint8_t sa, float *mv_list, uint16_t *mv_count, char const **error_message); +void cmd_90621_raw(uint8_t sa, uint16_t *raw_list, uint16_t *raw_count, char const **error_message); +void cmd_90621_nd(uint8_t sa, uint8_t *nd, char const **error_message); +void cmd_90621_sn(uint8_t sa, uint16_t *sn_list, uint16_t *sn_count, char const **error_message); +void cmd_90621_cs(uint8_t sa, uint8_t channel_mask, const char *input); +void cmd_90621_cs_write(uint8_t sa, uint8_t channel_mask, const char *input); +void cmd_90621_mr(uint8_t sa, uint16_t *mem_data, uint16_t mem_start_address, uint16_t mem_count, uint8_t *bit_per_address, uint8_t *address_increments, char const **error_message); +void cmd_90621_mw(uint8_t sa, uint16_t *mem_data, uint16_t mem_start_address, uint16_t mem_count, uint8_t *bit_per_address, uint8_t *address_increments, char const **error_message); +void cmd_90621_is(uint8_t sa, uint8_t *is_ok, char const **error_message); + +void cmd_90621_tear_down(uint8_t sa); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/i2c-stick-arduino/mlx90621_i2c_driver.cpp b/i2c-stick-arduino/mlx90621_i2c_driver.cpp new file mode 100644 index 0000000..efdc5e6 --- /dev/null +++ b/i2c-stick-arduino/mlx90621_i2c_driver.cpp @@ -0,0 +1,180 @@ +/** + * @copyright (C) 2017 Melexis N.V. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#include +#include +#include "mlx90621_i2c_driver.h" + +#include "i2c_stick.h" +#include "i2c_stick_arduino.h" + + +void MLX90621_I2CInit() +{ + delayMicroseconds(5); + WIRE.endTransmission(); +} + +int MLX90621_I2CReadEEPROM(uint8_t slaveAddr, uint8_t startAddress, uint16_t nMemAddressRead, uint8_t *data) +{ + int16_t ack = 0; + int16_t cnt = 0; + int16_t n = 0; + uint8_t *p; + + p = data; + + WIRE.endTransmission(); + delayMicroseconds(5); + + for (cnt = nMemAddressRead; cnt > 0; cnt -= READ_BUFFER_SIZE) + { + WIRE.beginTransmission(slaveAddr); + WIRE.write(startAddress); + ack = WIRE.endTransmission(false); // repeated start +#ifdef ARDUINO_ARCH_RP2040 + if (ack == 4) ack = 0; // ignore error=4 ('other error', but I can't seem to find anything wrong; only on this MCU platform) +#endif + if (ack != 0x00) + { + return -1; + } + n = cnt > READ_BUFFER_SIZE ? READ_BUFFER_SIZE : cnt; + startAddress += n; + WIRE.requestFrom((int)slaveAddr, (int)n); + for(uint16_t i; i 0; cnt -= READ_BUFFER_SIZE) + { + WIRE.beginTransmission(slaveAddr); + WIRE.write(command); + WIRE.write(startAddress); + WIRE.write(addressStep); + WIRE.write(nMemAddressRead); + ack = WIRE.endTransmission(false); // repeated start +#ifdef ARDUINO_ARCH_RP2040 + if (ack == 4) ack = 0; // ignore error=4 ('other error', but I can't seem to find anything wrong; only on this MCU platform) +#endif + if (ack != 0x00) + { + return -1; + } + n = cnt > READ_BUFFER_SIZE ? READ_BUFFER_SIZE : cnt; + startAddress += (n/2); + WIRE.requestFrom((int)slaveAddr, (int)n); + for(; n>0; n-=2) + { + uint16_t val = WIRE.read(); + val <<= 8; + val |= WIRE.read(); + *p++ = val; + } + } + + ack = WIRE.endTransmission(); // stop transmitting +#ifdef ARDUINO_ARCH_RP2040 + if (ack == 4) ack = 0; // ignore error=4 ('other error', but I can't seem to find anything wrong; only on this MCU platform) +#endif + + if (ack != 0x00) + { + return -1; + } + + return 0; +} + + + void MLX90621_I2CFreqSet(int freq) +{ + WIRE.end(); // some MCU cannot change the clock while I2C is active. + WIRE.setClock(freq); // RP2040 requires first to set the clock + WIRE.begin(); + WIRE.setClock(freq); // NRF52840 requires first begin, then set clock. +} + + +int MLX90621_I2CWrite(uint8_t slaveAddr, uint8_t command, uint8_t checkValue, uint16_t data) +{ + char cmd[5] = {0,0,0,0,0}; + cmd[0] = command; + cmd[2] = data & 0x00FF; + cmd[1] = cmd[2] - checkValue; + cmd[4] = data >> 8; + cmd[3] = cmd[4] - checkValue; + + uint16_t dataCheck; + WIRE.beginTransmission(slaveAddr); + for (uint8_t i=0; i<5; i++) + { + WIRE.write(cmd[i]); + } + int16_t ack = WIRE.endTransmission(); + delayMicroseconds(5); + +#ifdef ARDUINO_ARCH_RP2040 + if (ack == 4) ack = 0; // ignore error=4 ('other error', but I can't seem to find anything wrong; only on this MCU platform) +#endif + if (ack != 0x00) + { + return -1; + } + // if (writeAddress_MSB == 0x24) // write to EEPROM? + // { + // delay(10); // 10 ms write time + // } + + MLX90621_I2CRead(slaveAddr, 0x02, 0x8F+command, 0, 1, &dataCheck); + + if ( dataCheck != data) + { + return -2; + } + + return 0; +} + diff --git a/i2c-stick-arduino/mlx90621_i2c_driver.h b/i2c-stick-arduino/mlx90621_i2c_driver.h new file mode 100644 index 0000000..ff8d474 --- /dev/null +++ b/i2c-stick-arduino/mlx90621_i2c_driver.h @@ -0,0 +1,27 @@ +/** + * @copyright (C) 2017 Melexis N.V. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#ifndef _MLX90621_I2C_Driver_H_ +#define _MLX90621_I2C_Driver_H_ + +#include + + void MLX90621_I2CInit(void); + int MLX90621_I2CReadEEPROM(uint8_t slaveAddr, uint8_t startAddress, uint16_t nMemAddressRead, uint8_t *data); + int MLX90621_I2CRead(uint8_t slaveAddr, uint8_t command, uint8_t startAddress, uint8_t addressStep, uint8_t nMemAddressRead, uint16_t *data); + int MLX90621_I2CWrite(uint8_t slaveAddr, uint8_t command, uint8_t checkValue, uint16_t data); + void MLX90621_I2CFreqSet(int freq); +#endif \ No newline at end of file diff --git a/i2c-stick-arduino/requirements.txt b/i2c-stick-arduino/requirements.txt new file mode 100644 index 0000000..703ed3c --- /dev/null +++ b/i2c-stick-arduino/requirements.txt @@ -0,0 +1,7 @@ +pyyaml-include>=1.3.1 +Jinja2>=3.1.2 +PyYAML>=6.0.1 +pyserial>=3.5 +bumpver>=2023.1127 +doit>=0.36.0 +requests>=2.31.0 From d6a8c1f8eebf5b460fae8191a4a4e559a14d631d Mon Sep 17 00:00:00 2001 From: Karel Vanroye Date: Fri, 20 Oct 2023 14:37:10 -0700 Subject: [PATCH 030/112] fixed bugs --- i2c-stick-arduino/mlx90621_i2c_driver.cpp | 42 +++++++++++------------ 1 file changed, 20 insertions(+), 22 deletions(-) diff --git a/i2c-stick-arduino/mlx90621_i2c_driver.cpp b/i2c-stick-arduino/mlx90621_i2c_driver.cpp index efdc5e6..5c574b9 100644 --- a/i2c-stick-arduino/mlx90621_i2c_driver.cpp +++ b/i2c-stick-arduino/mlx90621_i2c_driver.cpp @@ -50,26 +50,25 @@ int MLX90621_I2CReadEEPROM(uint8_t slaveAddr, uint8_t startAddress, uint16_t nMe #endif if (ack != 0x00) { - return -1; + return -1; } n = cnt > READ_BUFFER_SIZE ? READ_BUFFER_SIZE : cnt; startAddress += n; WIRE.requestFrom((int)slaveAddr, (int)n); - for(uint16_t i; i 0; cnt -= READ_BUFFER_SIZE) { + n = cnt > READ_BUFFER_SIZE ? READ_BUFFER_SIZE : cnt; WIRE.beginTransmission(slaveAddr); WIRE.write(command); WIRE.write(startAddress); @@ -103,33 +103,32 @@ int MLX90621_I2CRead(uint8_t slaveAddr,uint8_t command, uint8_t startAddress, ui { return -1; } - n = cnt > READ_BUFFER_SIZE ? READ_BUFFER_SIZE : cnt; - startAddress += (n/2); WIRE.requestFrom((int)slaveAddr, (int)n); + startAddress += (n/2); for(; n>0; n-=2) { - uint16_t val = WIRE.read(); - val <<= 8; - val |= WIRE.read(); - *p++ = val; + uint16_t low_byte = WIRE.read(); + uint16_t high_byte = WIRE.read(); + *p = (low_byte | (high_byte << 8)); + *p++; } - } - - ack = WIRE.endTransmission(); // stop transmitting + ack = WIRE.endTransmission(); // stop transmitting #ifdef ARDUINO_ARCH_RP2040 - if (ack == 4) ack = 0; // ignore error=4 ('other error', but I can't seem to find anything wrong; only on this MCU platform) + if (ack == 4) ack = 0; // ignore error=4 ('other error', but I can't seem to find anything wrong; only on this MCU platform) #endif - if (ack != 0x00) - { + if (ack != 0x00) + { return -1; + } } + return 0; } - void MLX90621_I2CFreqSet(int freq) +void MLX90621_I2CFreqSet(int freq) { WIRE.end(); // some MCU cannot change the clock while I2C is active. WIRE.setClock(freq); // RP2040 requires first to set the clock @@ -177,4 +176,3 @@ int MLX90621_I2CWrite(uint8_t slaveAddr, uint8_t command, uint8_t checkValue, ui return 0; } - From 71004739a3fe49f9626cf9f2bcae9476422e5dde Mon Sep 17 00:00:00 2001 From: Karel Vanroye Date: Fri, 20 Oct 2023 14:38:11 -0700 Subject: [PATCH 031/112] empty file --- i2c-stick-arduino/i2c_stick_dispatcher.cpp | 452 +-------------------- i2c-stick-arduino/i2c_stick_dispatcher.h | 46 +-- 2 files changed, 6 insertions(+), 492 deletions(-) diff --git a/i2c-stick-arduino/i2c_stick_dispatcher.cpp b/i2c-stick-arduino/i2c_stick_dispatcher.cpp index a44a184..b2aaa43 100644 --- a/i2c-stick-arduino/i2c_stick_dispatcher.cpp +++ b/i2c-stick-arduino/i2c_stick_dispatcher.cpp @@ -1,452 +1,6 @@ + // this file is automatically generated: // please edit 'context.yaml', and then: -// run the python doit script `python dodo.py source` or `doit source`. - -#include "i2c_stick_dispatcher.h" -#include "i2c_stick.h" -#include "i2c_stick_cmd.h" - -// Include all the drivers cmd header files: -#include "mlx90614_cmd.h" -#include "mlx90640_cmd.h" -#include "mlx90641_cmd.h" -#include "mlx90632_cmd.h" -#include "mlx90621_cmd.h" - -#include -#include - -int16_t -i2c_stick_register_all_drivers() -{ - int16_t result = 1; - if (cmd_90614_register_driver() < 0) result = -1; - if (cmd_90640_register_driver() < 0) result = -1; - if (cmd_90641_register_driver() < 0) result = -1; - if (cmd_90632_register_driver() < 0) result = -1; - if (cmd_90621_register_driver() < 0) result = -1; - return result; -} - - -const char* -i2c_stick_get_drv_name_by_drv(uint8_t drv) -{ - switch(drv) - { - case DRV_MLX90614_ID: - return DRV_MLX90614_NAME; - case DRV_MLX90640_ID: - return DRV_MLX90640_NAME; - case DRV_MLX90641_ID: - return DRV_MLX90641_NAME; - case DRV_MLX90632_ID: - return DRV_MLX90632_NAME; - case DRV_MLX90621_ID: - return DRV_MLX90621_NAME; - default: - if (0) {} - } - return "Unknown"; -} - - -uint8_t -i2c_stick_get_drv_by_drv_name(const char *drv_name) -{ - if (!strcasecmp(drv_name, DRV_MLX90614_NAME)) return DRV_MLX90614_ID; - if (!strcasecmp(drv_name, DRV_MLX90640_NAME)) return DRV_MLX90640_ID; - if (!strcasecmp(drv_name, DRV_MLX90641_NAME)) return DRV_MLX90641_ID; - if (!strcasecmp(drv_name, DRV_MLX90632_NAME)) return DRV_MLX90632_ID; - if (!strcasecmp(drv_name, DRV_MLX90621_NAME)) return DRV_MLX90621_ID; - return 0; -} - - - -// command functions. - -uint8_t -cmd_mv(uint8_t sa, float *mv_list, uint16_t *mv_count, char const **error_message) -{ - // sanity check - if (sa > 127) { return 0; } - - uint16_t spot = g_sa_list[sa].spot_; - uint8_t drv = g_sa_drv_register[spot].drv_; - - switch(drv) - { - case DRV_MLX90614_ID: - cmd_90614_mv(sa, mv_list, mv_count, error_message); - break; - case DRV_MLX90640_ID: - cmd_90640_mv(sa, mv_list, mv_count, error_message); - break; - case DRV_MLX90641_ID: - cmd_90641_mv(sa, mv_list, mv_count, error_message); - break; - case DRV_MLX90632_ID: - cmd_90632_mv(sa, mv_list, mv_count, error_message); - break; - case DRV_MLX90621_ID: - cmd_90621_mv(sa, mv_list, mv_count, error_message); - break; - default: - return 0; - } - return drv; -} - - -uint8_t -cmd_raw(uint8_t sa, uint16_t *raw_list, uint16_t *raw_count, char const **error_message) -{ - // sanity check - if (sa > 127) { return 0; } - - uint16_t spot = g_sa_list[sa].spot_; - uint8_t drv = g_sa_drv_register[spot].drv_; - - switch(drv) - { - case DRV_MLX90614_ID: - cmd_90614_raw(sa, raw_list, raw_count, error_message); - break; - case DRV_MLX90640_ID: - cmd_90640_raw(sa, raw_list, raw_count, error_message); - break; - case DRV_MLX90641_ID: - cmd_90641_raw(sa, raw_list, raw_count, error_message); - break; - case DRV_MLX90632_ID: - cmd_90632_raw(sa, raw_list, raw_count, error_message); - break; - case DRV_MLX90621_ID: - cmd_90621_raw(sa, raw_list, raw_count, error_message); - break; - default: - return 0; - } - return drv; -} - - -uint8_t -cmd_nd(uint8_t sa, uint8_t *nd, char const **error_message) -{ - // sanity check - if (sa > 127) { return 0; } - - uint16_t spot = g_sa_list[sa].spot_; - uint8_t drv = g_sa_drv_register[spot].drv_; - - switch(drv) - { - case DRV_MLX90614_ID: - cmd_90614_nd(sa, nd, error_message); - break; - case DRV_MLX90640_ID: - cmd_90640_nd(sa, nd, error_message); - break; - case DRV_MLX90641_ID: - cmd_90641_nd(sa, nd, error_message); - break; - case DRV_MLX90632_ID: - cmd_90632_nd(sa, nd, error_message); - break; - case DRV_MLX90621_ID: - cmd_90621_nd(sa, nd, error_message); - break; - default: - return 0; - } - return drv; -} - - -uint8_t -cmd_sn(uint8_t sa, uint16_t *sn_list, uint16_t *sn_count, char const **error_message) -{ - // sanity check - if (sa > 127) { return 0; } - - uint16_t spot = g_sa_list[sa].spot_; - uint8_t drv = g_sa_drv_register[spot].drv_; - - switch(drv) - { - case DRV_MLX90614_ID: - cmd_90614_sn(sa, sn_list, sn_count, error_message); - break; - case DRV_MLX90640_ID: - cmd_90640_sn(sa, sn_list, sn_count, error_message); - break; - case DRV_MLX90641_ID: - cmd_90641_sn(sa, sn_list, sn_count, error_message); - break; - case DRV_MLX90632_ID: - cmd_90632_sn(sa, sn_list, sn_count, error_message); - break; - case DRV_MLX90621_ID: - cmd_90621_sn(sa, sn_list, sn_count, error_message); - break; - default: - *sn_count = 0; - return 0; - } - return drv; -} - - -uint8_t -cmd_cs(uint8_t sa, uint8_t channel_mask, const char *input) -{ - // sanity check - if (sa > 127) { return 0; } - - uint16_t spot = g_sa_list[sa].spot_; - uint8_t drv = g_sa_drv_register[spot].drv_; - uint8_t raw = g_sa_drv_register[spot].raw_; - - char buf[16]; memset(buf, 0, sizeof(buf)); - - send_answer_chunk(channel_mask, "cs:", 0); - uint8_to_hex(buf, sa); - send_answer_chunk(channel_mask, buf, 0); - send_answer_chunk(channel_mask, ":RAW=", 0); - itoa(raw, buf, 10); - send_answer_chunk(channel_mask, buf, 1); - - switch(drv) - { - case DRV_MLX90614_ID: - cmd_90614_cs(sa, channel_mask, input); - break; - case DRV_MLX90640_ID: - cmd_90640_cs(sa, channel_mask, input); - break; - case DRV_MLX90641_ID: - cmd_90641_cs(sa, channel_mask, input); - break; - case DRV_MLX90632_ID: - cmd_90632_cs(sa, channel_mask, input); - break; - case DRV_MLX90621_ID: - cmd_90621_cs(sa, channel_mask, input); - break; - default: - return 0; - } - return drv; -} - - -uint8_t -cmd_cs_write(uint8_t sa, uint8_t channel_mask, const char *input) -{ - // sanity check - if (sa > 127) { return 0; } - - uint16_t spot = g_sa_list[sa].spot_; - uint8_t drv = g_sa_drv_register[spot].drv_; - - char buf[16]; memset(buf, 0, sizeof(buf)); - - const char *var_name = "RAW="; - if (!strncmp(var_name, input, strlen(var_name))) - { - // 1.1. try to find if the desired value is a 'driver-name' - int16_t value = atoi(input+strlen(var_name)); - if ((value >= 0) && (value <= 1)) - { - if (value == 1) - { - g_sa_drv_register[spot].raw_ = 1; - } else - { - g_sa_drv_register[spot].raw_ = 0; - } - send_answer_chunk(channel_mask, "+cs:", 0); - uint8_to_hex(buf, sa); - send_answer_chunk(channel_mask, buf, 0); - send_answer_chunk(channel_mask, ":RAW=", 0); - uint8_to_hex(buf, g_sa_drv_register[spot].raw_); - send_answer_chunk(channel_mask, buf, 0); - send_answer_chunk(channel_mask, ":OK [host-register]", 1); - } else - { - send_answer_chunk(channel_mask, "+cs:", 0); - uint8_to_hex(buf, sa); - send_answer_chunk(channel_mask, buf, 0); - send_answer_chunk(channel_mask, ":RAW= FAIL; value not valid", 1); - } - return drv; - } - - switch(drv) - { - case DRV_MLX90614_ID: - cmd_90614_cs_write(sa, channel_mask, input); - break; - case DRV_MLX90640_ID: - cmd_90640_cs_write(sa, channel_mask, input); - break; - case DRV_MLX90641_ID: - cmd_90641_cs_write(sa, channel_mask, input); - break; - case DRV_MLX90632_ID: - cmd_90632_cs_write(sa, channel_mask, input); - break; - case DRV_MLX90621_ID: - cmd_90621_cs_write(sa, channel_mask, input); - break; - default: - return 0; - } - return drv; -} - - -uint8_t -cmd_mr(uint8_t sa, uint16_t *mem_list, uint16_t mem_start_address, uint16_t mem_count, uint8_t *bit_per_address, uint8_t *address_increments, char const **error_message) -{ - // sanity check - if (sa > 127) { return 0; } - - uint16_t spot = g_sa_list[sa].spot_; - uint8_t drv = g_sa_drv_register[spot].drv_; - - switch(drv) - { - case DRV_MLX90614_ID: - cmd_90614_mr(sa, mem_list, mem_start_address, mem_count, bit_per_address, address_increments, error_message); - break; - case DRV_MLX90640_ID: - cmd_90640_mr(sa, mem_list, mem_start_address, mem_count, bit_per_address, address_increments, error_message); - break; - case DRV_MLX90641_ID: - cmd_90641_mr(sa, mem_list, mem_start_address, mem_count, bit_per_address, address_increments, error_message); - break; - case DRV_MLX90632_ID: - cmd_90632_mr(sa, mem_list, mem_start_address, mem_count, bit_per_address, address_increments, error_message); - break; - case DRV_MLX90621_ID: - cmd_90621_mr(sa, mem_list, mem_start_address, mem_count, bit_per_address, address_increments, error_message); - break; - default: - return 0; - } - - return drv; -} - - -uint8_t -cmd_mw(uint8_t sa, uint16_t *mem_list, uint16_t mem_start_address, uint16_t mem_count, uint8_t *bit_per_address, uint8_t *address_increments, char const **error_message) -{ - // sanity check - if (sa > 127) { return 0; } - - uint16_t spot = g_sa_list[sa].spot_; - uint8_t drv = g_sa_drv_register[spot].drv_; - - switch(drv) - { - case DRV_MLX90614_ID: - cmd_90614_mw(sa, mem_list, mem_start_address, mem_count, bit_per_address, address_increments, error_message); - break; - case DRV_MLX90640_ID: - cmd_90640_mw(sa, mem_list, mem_start_address, mem_count, bit_per_address, address_increments, error_message); - break; - case DRV_MLX90641_ID: - cmd_90641_mw(sa, mem_list, mem_start_address, mem_count, bit_per_address, address_increments, error_message); - break; - case DRV_MLX90632_ID: - cmd_90632_mw(sa, mem_list, mem_start_address, mem_count, bit_per_address, address_increments, error_message); - break; - case DRV_MLX90621_ID: - cmd_90621_mw(sa, mem_list, mem_start_address, mem_count, bit_per_address, address_increments, error_message); - break; - default: - return 0; - } - - return drv; -} - - -uint8_t -cmd_is(uint8_t sa, uint8_t drv, uint8_t *is_ok, char const **error_message) -{ - if ((drv <= 0) || (drv > 63)) - { - *is_ok = 0; - return 0; - } - - switch(drv) - { - case DRV_MLX90614_ID: - cmd_90614_is(sa, is_ok, error_message); - break; - case DRV_MLX90640_ID: - cmd_90640_is(sa, is_ok, error_message); - break; - case DRV_MLX90641_ID: - cmd_90641_is(sa, is_ok, error_message); - break; - case DRV_MLX90632_ID: - cmd_90632_is(sa, is_ok, error_message); - break; - case DRV_MLX90621_ID: - cmd_90621_is(sa, is_ok, error_message); - break; - default: - return 0; - } - - return drv; -} - - - -uint8_t -cmd_tear_down(uint8_t sa) -{ - if (sa == 255) - { - for (sa = 0; sa <= 127; sa++) - { - cmd_tear_down(sa); - } - return sa; - } - // sanity check - if (sa > 127) { return 0; } - - uint16_t spot = g_sa_list[sa].spot_; - uint8_t drv = g_sa_drv_register[spot].drv_; +// run the doit command `python dodo.py generate` or `doit generate`. - switch(drv) - { - case DRV_MLX90614_ID: - cmd_90614_tear_down(sa); - break; - case DRV_MLX90640_ID: - cmd_90640_tear_down(sa); - break; - case DRV_MLX90641_ID: - cmd_90641_tear_down(sa); - break; - case DRV_MLX90632_ID: - cmd_90632_tear_down(sa); - break; - case DRV_MLX90621_ID: - cmd_90621_tear_down(sa); - break; - default: - return 0; - } - return drv; -} \ No newline at end of file +#error "This file is automatically generated; please run `python dodo.py source` or `doit source` from command line" diff --git a/i2c-stick-arduino/i2c_stick_dispatcher.h b/i2c-stick-arduino/i2c_stick_dispatcher.h index 78a2b3d..b2aaa43 100644 --- a/i2c-stick-arduino/i2c_stick_dispatcher.h +++ b/i2c-stick-arduino/i2c_stick_dispatcher.h @@ -1,46 +1,6 @@ + // this file is automatically generated: // please edit 'context.yaml', and then: -// run the python doit script `python dodo.py source` or `doit source`. - -#ifndef __I2C_STICK_DISPATCHER_H__ -#define __I2C_STICK_DISPATCHER_H__ - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -// driver declarations: -#define DRV_MLX90614_ID 1 -#define DRV_MLX90614_NAME "MLX90614" -#define DRV_MLX90640_ID 2 -#define DRV_MLX90640_NAME "MLX90640" -#define DRV_MLX90641_ID 3 -#define DRV_MLX90641_NAME "MLX90641" -#define DRV_MLX90632_ID 4 -#define DRV_MLX90632_NAME "MLX90632" -#define DRV_MLX90621_ID 5 -#define DRV_MLX90621_NAME "MLX90621" - -int16_t i2c_stick_register_all_drivers(); -const char* i2c_stick_get_drv_name_by_drv(uint8_t drv); -uint8_t i2c_stick_get_drv_by_drv_name(const char *drv_name); - -uint8_t cmd_mv(uint8_t sa, float *mv_list, uint16_t *mv_count, char const **error_message); -uint8_t cmd_raw(uint8_t sa, uint16_t *raw_list, uint16_t *raw_count, char const **error_message); -uint8_t cmd_nd(uint8_t sa, uint8_t *nd, char const **error_message); -uint8_t cmd_sn(uint8_t sa, uint16_t *sn_list, uint16_t *sn_count, char const **error_message); -uint8_t cmd_cs(uint8_t sa, uint8_t channel_mask, const char *input); -uint8_t cmd_cs_write(uint8_t sa, uint8_t channel_mask, const char *input); -uint8_t cmd_mr(uint8_t sa, uint16_t *mem_list, uint16_t mem_start_address, uint16_t mem_count, uint8_t *bit_per_address, uint8_t *address_increments, char const **error_message); -uint8_t cmd_mw(uint8_t sa, uint16_t *mem_list, uint16_t mem_start_address, uint16_t mem_count, uint8_t *bit_per_address, uint8_t *address_increments, char const **error_message); - -uint8_t cmd_is(uint8_t sa, uint8_t drv, uint8_t *is_ok, char const **error_message); -uint8_t cmd_tear_down(uint8_t sa); - -#ifdef __cplusplus -} -#endif +// run the doit command `python dodo.py generate` or `doit generate`. -#endif // __I2C_STICK_DISPATCHER_H__ \ No newline at end of file +#error "This file is automatically generated; please run `python dodo.py source` or `doit source` from command line" From bbdab9df395e338505e638cc1081d92eda9fa317 Mon Sep 17 00:00:00 2001 From: Karel Vanroye Date: Fri, 20 Oct 2023 14:38:40 -0700 Subject: [PATCH 032/112] work in progress --- i2c-stick-arduino/mlx90621_cmd.cpp | 64 +++++++++++++++++++++++++----- 1 file changed, 55 insertions(+), 9 deletions(-) diff --git a/i2c-stick-arduino/mlx90621_cmd.cpp b/i2c-stick-arduino/mlx90621_cmd.cpp index 1254020..eadb11b 100644 --- a/i2c-stick-arduino/mlx90621_cmd.cpp +++ b/i2c-stick-arduino/mlx90621_cmd.cpp @@ -4,9 +4,13 @@ #include "i2c_stick_dispatcher.h" #include "i2c_stick_hal.h" +#include "mlx90621_api.h" + #include #include +#include + #ifdef __cplusplus extern "C" { #endif @@ -421,12 +425,54 @@ cmd_90621_mw(uint8_t sa, uint16_t *mem_data, uint16_t mem_start_address, uint16_ } + void cmd_90621_is(uint8_t sa, uint8_t *is_ok, char const **error_message) { // function to call prior any init, only to check is the connected slave IS a MLX90614. uint16_t value; *is_ok = 1; // be optimistic! + Serial.printf("\ntesting!"); + + + float emissivity = 0.95; + float tr; + static uint8_t eeMLX90621[256]; + static uint16_t mlx90621Frame[66]; + paramsMLX90621 mlx90621; + static float mlx90621To[64]; + int status; + status = MLX90621_DumpEE (eeMLX90621); + MLX90621_Configure(eeMLX90621); + MLX90621_SetRefreshRate (0x09); // 32Hz + + status = MLX90621_ExtractParameters(eeMLX90621, &mlx90621); + + int rr = MLX90621_GetRefreshRate(); + Serial.printf("RefreshRate: %d\n", rr); + + memset(&mlx90621Frame, 0, sizeof(mlx90621Frame)); + status = MLX90621_GetFrameData (mlx90621Frame); + + + + float Ta = MLX90621_GetTa (mlx90621Frame, &mlx90621); + Serial.printf("Ta: %f C\n", Ta); + + + tr = 23.15; + MLX90621_CalculateTo(mlx90621Frame, &mlx90621, emissivity, tr, mlx90621To); + for (int i=0; i<64; i++) + { + Serial.printf("pixel[%2d]: %.2f\n", i, mlx90621To[i]); + } + + + + + + Serial.printf("\n"); + // todo: // // find a way to verify the connected slave at slave address is actually a MLX90621! @@ -440,15 +486,15 @@ cmd_90621_is(uint8_t sa, uint8_t *is_ok, char const **error_message) // MLX90614_SMBusInit(); // if (MLX90614_SMBusRead(sa, 0x2E, &value) < 0) - { - *error_message = MLX90621_ERROR_COMMUNICATION; - *is_ok = 0; - return; - } - if (value & 0x007F != sa) - { - *is_ok = 0; - } +// { +// *error_message = MLX90621_ERROR_COMMUNICATION; +// *is_ok = 0; +// return; +// } +// if (value & 0x007F != sa) +// { +// *is_ok = 0; +// } } From fb0737f937a3a47a2c8ab274cedb2b4c5487824b Mon Sep 17 00:00:00 2001 From: Karel Vanroye Date: Sat, 21 Oct 2023 16:01:53 -0700 Subject: [PATCH 033/112] mlx90621 adding to the list; work in progress --- i2c-stick-arduino/mlx90621_api.h | 2 +- i2c-stick-arduino/mlx90621_cmd.cpp | 187 ++++++++++++++++++----------- i2c-stick-arduino/mlx90621_cmd.h | 9 ++ 3 files changed, 129 insertions(+), 69 deletions(-) diff --git a/i2c-stick-arduino/mlx90621_api.h b/i2c-stick-arduino/mlx90621_api.h index 3238361..7d160a4 100644 --- a/i2c-stick-arduino/mlx90621_api.h +++ b/i2c-stick-arduino/mlx90621_api.h @@ -23,7 +23,7 @@ typedef struct { int16_t vTh25; float kT1; - float kT2; + float kT2; float tgc; float KsTa; float ksTo; diff --git a/i2c-stick-arduino/mlx90621_cmd.cpp b/i2c-stick-arduino/mlx90621_cmd.cpp index eadb11b..309d32b 100644 --- a/i2c-stick-arduino/mlx90621_cmd.cpp +++ b/i2c-stick-arduino/mlx90621_cmd.cpp @@ -5,6 +5,7 @@ #include "i2c_stick_hal.h" #include "mlx90621_api.h" +#include "mlx90621_i2c_driver.h" #include #include @@ -109,6 +110,65 @@ cmd_90621_register_driver() } +static int8_t +check_90621_calibration_ranges(paramsMLX90621 *mlx90621) +{ + // those ranges are experimental; one might require to tweak those... + + // Serial.printf("mlx90621->vTh25: %d\n", mlx90621->vTh25); + // Serial.printf("mlx90621->kT1: %f\n", mlx90621->kT1); + // Serial.printf("mlx90621->kT2: %f\n", mlx90621->kT2); + // Serial.printf("mlx90621->tgc: %f\n", mlx90621->tgc); + // Serial.printf("mlx90621->KsTa: %f\n", mlx90621->KsTa); + // Serial.printf("mlx90621->ksTo: %f\n", mlx90621->ksTo); + // for (int i=0; i<64; i++) + // { + // Serial.printf("mlx90621->alpha[%d]: %fe-6\n", i, (mlx90621->alpha[i] * 1000000.0)); + // } + + if ((mlx90621->vTh25 < 20000) || + (mlx90621->vTh25 > 30000)) + { + return 1; + } + if ((mlx90621->kT1 < 70.0) || + (mlx90621->kT1 > 100.0)) + { + return 1; + } + if ((mlx90621->kT2 < -0.1) || + (mlx90621->kT2 > 0.1)) + { + return 1; + } + if ((mlx90621->tgc < 0.25) || + (mlx90621->tgc > 2.00)) + { + return 1; + } + if ((mlx90621->KsTa < 0.0001) || + (mlx90621->KsTa > 0.0100)) + { + return 1; + } + if ((mlx90621->ksTo < -0.0100) || + (mlx90621->ksTo > -0.0001)) + { + return 1; + } + + for (int i=0; i<64; i++) + { + if ((mlx90621->alpha[i] < 0.001E-6) || + (mlx90621->alpha[i] > 2.0E-6)) + { + return 1; + } + } + return 0; +} + + void cmd_90621_init(uint8_t sa) { @@ -118,6 +178,18 @@ cmd_90621_init(uint8_t sa) return; } // init functions goes here + mlx->slave_address_ = sa; + + mlx->emissivity_ = 0.95; + mlx->tr_ = 25.0; + + uint8_t eeMLX90621[256]; + + MLX90621_I2CInit(); + MLX90621_DumpEE (eeMLX90621); + MLX90621_Configure(eeMLX90621); + MLX90621_SetRefreshRate (0x09); // 32Hz + MLX90621_ExtractParameters(eeMLX90621, &mlx->mlx90621_); // turn off bit7, to indicate other routines this slave has been init mlx->slave_address_ &= 0x7F; @@ -146,18 +218,26 @@ cmd_90621_mv(uint8_t sa, float *mv_list, uint16_t *mv_count, char const **error_ cmd_90621_init(sa); } - if (*mv_count <= 2) // check Measurement Value buffer length + if (*mv_count <= 65) // check Measurement Value buffer length { *mv_count = 0; *error_message = MLX90621_ERROR_BUFFER_TOO_SMALL; return; } - *mv_count = 2; + *mv_count = 65; - // todo: - // - // get the measurement values from the sensor - // + uint16_t mlx90621Frame[66]; + memset(&mlx90621Frame, 0, sizeof(mlx90621Frame)); + MLX90621_GetFrameData (mlx90621Frame); + + mlx->ta_ = MLX90621_GetTa (mlx90621Frame, &mlx->mlx90621_); + mv_list[0] = mlx->ta_; + + MLX90621_CalculateTo(mlx90621Frame, &mlx->mlx90621_, mlx->emissivity_, mlx->tr_, mlx->to_); + for (int i=0; i<64; i++) + { + mv_list[i+1] = mlx->to_[i]; + } } @@ -176,18 +256,21 @@ cmd_90621_raw(uint8_t sa, uint16_t *raw_list, uint16_t *raw_count, char const ** cmd_90621_init(sa); } - if (*raw_count < 3) // check Raw Value buffer length + if (*raw_count < 66) // check Raw Value buffer length { *raw_count = 0; // input buffer not long enough, report nothing. *error_message = MLX90621_ERROR_BUFFER_TOO_SMALL; return; } - *raw_count = 3; + *raw_count = 66; - // todo: - // - // get the raw values from the sensor - // + uint16_t mlx90621Frame[66]; + memset(&mlx90621Frame, 0, sizeof(mlx90621Frame)); + MLX90621_GetFrameData (mlx90621Frame); + for (uint16_t i=0; i<66; i++) + { + raw_list[i] = (uint16_t)mlx90621Frame[i]; + } } @@ -205,6 +288,8 @@ cmd_90621_nd(uint8_t sa, uint8_t *nd, char const **error_message) cmd_90621_init(sa); } + *nd = 1; // not implemented, but there is 'always' new data... + // todo: // // read the status from the sensor and check if new data is available (ND=New Data). @@ -235,6 +320,11 @@ cmd_90621_sn(uint8_t sa, uint16_t *sn_list, uint16_t *sn_count, char const **err } *sn_count = 4; + sn_list[0] = 0; + sn_list[1] = 0; + sn_list[2] = 0; + sn_list[3] = 0; + // todo: // // read the serial number from the sensor. @@ -425,76 +515,37 @@ cmd_90621_mw(uint8_t sa, uint16_t *mem_data, uint16_t mem_start_address, uint16_ } - void cmd_90621_is(uint8_t sa, uint8_t *is_ok, char const **error_message) { // function to call prior any init, only to check is the connected slave IS a MLX90614. uint16_t value; *is_ok = 1; // be optimistic! - Serial.printf("\ntesting!"); - - - float emissivity = 0.95; - float tr; - static uint8_t eeMLX90621[256]; - static uint16_t mlx90621Frame[66]; + uint8_t eeMLX90621[256]; paramsMLX90621 mlx90621; - static float mlx90621To[64]; int status; + + MLX90621_I2CInit(); status = MLX90621_DumpEE (eeMLX90621); - MLX90621_Configure(eeMLX90621); - MLX90621_SetRefreshRate (0x09); // 32Hz + if (status != 0) + { + *is_ok = 0; + return; + } status = MLX90621_ExtractParameters(eeMLX90621, &mlx90621); - - int rr = MLX90621_GetRefreshRate(); - Serial.printf("RefreshRate: %d\n", rr); - - memset(&mlx90621Frame, 0, sizeof(mlx90621Frame)); - status = MLX90621_GetFrameData (mlx90621Frame); - - - - float Ta = MLX90621_GetTa (mlx90621Frame, &mlx90621); - Serial.printf("Ta: %f C\n", Ta); - - - tr = 23.15; - MLX90621_CalculateTo(mlx90621Frame, &mlx90621, emissivity, tr, mlx90621To); - for (int i=0; i<64; i++) + if (status != 0) { - Serial.printf("pixel[%2d]: %.2f\n", i, mlx90621To[i]); + *is_ok = 0; + return; } - - - - - Serial.printf("\n"); - - // todo: - // - // find a way to verify the connected slave at slave address is actually a MLX90621! - // often times this can be done by reading some specific values from the ROM or EEPROM, - // and verify the values are as expected. - // - - // remember there is no communication initiated yet... - - // in this ecample below for MLX90614 we check if the EEPROM reads the slave address at address 0x2E... - -// MLX90614_SMBusInit(); -// if (MLX90614_SMBusRead(sa, 0x2E, &value) < 0) -// { -// *error_message = MLX90621_ERROR_COMMUNICATION; -// *is_ok = 0; -// return; -// } -// if (value & 0x007F != sa) -// { -// *is_ok = 0; -// } + status = check_90621_calibration_ranges(&mlx90621); + if (status != 0) + { + *is_ok = 0; + return; + } } diff --git a/i2c-stick-arduino/mlx90621_cmd.h b/i2c-stick-arduino/mlx90621_cmd.h index f063bde..e248301 100644 --- a/i2c-stick-arduino/mlx90621_cmd.h +++ b/i2c-stick-arduino/mlx90621_cmd.h @@ -3,6 +3,9 @@ #include +#include "mlx90621_api.h" + + #ifdef __cplusplus extern "C" { #endif @@ -12,6 +15,12 @@ struct MLX90621_t uint8_t slave_address_; // local caching of sensor values whenever needed; // stored along with , such that multiple sensors can be supported. + + float emissivity_; + float tr_; + paramsMLX90621 mlx90621_; + float to_[64]; + float ta_; }; From 647cdca67291b47a83fa8d99f7412c43c3bf0c16 Mon Sep 17 00:00:00 2001 From: karelv Date: Fri, 27 Oct 2023 15:45:01 -0700 Subject: [PATCH 034/112] updating dodo file for other platforms + enable lib install when needed --- i2c-stick-arduino/context.yaml | 17 +- i2c-stick-arduino/dodo.py | 292 +++++++++++++++++++++++++++------ 2 files changed, 252 insertions(+), 57 deletions(-) diff --git a/i2c-stick-arduino/context.yaml b/i2c-stick-arduino/context.yaml index a87cb3a..d6dd4d8 100644 --- a/i2c-stick-arduino/context.yaml +++ b/i2c-stick-arduino/context.yaml @@ -1,16 +1,27 @@ +ino: i2c-stick-arduino board_manager: additional-urls: - https://github.com/earlephilhower/arduino-pico/releases/download/global/package_rp2040_index.json - boards: - - rp2040:rp2040 + - https://www.pjrc.com/teensy/package_teensy_index.json boards: - fqbn: rp2040:rp2040:adafruit_trinkeyrp2040qt name: Adafruit Trinkey RP2040 QT nick: i2c-stick - platform: rp2040:rp2040 + core: rp2040:rp2040 + bin_extension: uf2 url: https://www.adafruit.com/product/5056 USB_PID: 0x8109 USB_VID: 0x239A +- fqbn: teensy:avr:teensy41 + name: Teensy 4.1 + nick: teensy41 + core: teensy:avr + bin_extension: hex + url: https://www.pjrc.com/store/teensy41.html + port_discovery_method: arduino-cli + USB_PID: 0x0483 + USB_VID: 0x16C0 + drivers: - function_id: '90614' id: 1 diff --git a/i2c-stick-arduino/dodo.py b/i2c-stick-arduino/dodo.py index d02acc2..4f60924 100644 --- a/i2c-stick-arduino/dodo.py +++ b/i2c-stick-arduino/dodo.py @@ -1,6 +1,3 @@ -# todo: -# [ ] create package / website within this dodo.py file. -# [ ] align version number of firmware and the python package. (make them one and the same!) import sys import subprocess @@ -33,6 +30,7 @@ from pathlib import Path import serial.tools.list_ports from doit.action import CmdAction +from doit.tools import run_once import platform with open(CONTEXT_FILE) as f: @@ -63,8 +61,17 @@ def remove(path): raise ValueError("path {} is not a file or dir.".format(p)) +def show_cmd(task): + msg = task.name + if task.verbosity >= 2: + for action in task.actions: + msg += "\n - " + str(action) + return msg + + def task_cleaner(): """ Clean the entire repository for a git commit & be ready to re-compile the entire project!""" + def do_clean(): patterns = ["build", "package", @@ -95,6 +102,7 @@ def do_clean(): return { "actions": None, "clean": [do_clean], + 'title': show_cmd, } @@ -105,11 +113,13 @@ def task_pip(): 'name': rqt_file, 'actions': ["pip install {} -r {}".format(PIP_USER, rqt_file)], 'file_dep': [rqt_file], + 'title': show_cmd, } def task_arduino_install_cli(): """Arduino: Install the arduino-cli tool""" + def do_install(task): if not Path("tools").is_dir(): os.mkdir('tools') @@ -126,7 +136,8 @@ def do_install(task): if system == 'windows': zip_suffix = 'zip' - url = "https://downloads.arduino.cc/arduino-cli/arduino-cli_latest_{}_{}.{}".format(os_dict[system], bits, zip_suffix) + url = "https://downloads.arduino.cc/arduino-cli/arduino-cli_latest_{}_{}.{}".format(os_dict[system], bits, + zip_suffix) print("downloading:", url) import io import zipfile @@ -147,8 +158,9 @@ def do_install(task): 'basename': 'arduino-install-cli', 'actions': [(do_install, )], 'verbosity': 2, - 'file_dep': ['requirements.txt'], 'targets': [ARDUINO_CLI], + 'uptodate': [run_once], + 'title': show_cmd, } @@ -172,98 +184,268 @@ def do_package(): 'clean': True, # 'file_dep': ['ktc_trial.yml', os.path.join("dist", 'ktc_trial.exe')], 'task_dep': ['arduino-compile', 'generate:firmware_list.md'], + 'title': show_cmd, } -def task_arduino_update_boards(): +def task_arduino_update_index(): """Arduino: get a fresh copy of the board index""" return { - 'basename': 'arduino-update-boards', + 'basename': 'arduino-update-index', 'actions': ["{} {} core update-index".format(ARDUINO_CLI, arduino_add_url), ], - 'file_dep': [CONTEXT_FILE], + 'uptodate': [run_once], 'task_dep': ['arduino-install-cli'], + 'title': show_cmd, } -def task_arduino_install_board(): - """Arduino: install the board tool-chain""" - for board in context['board_manager']['boards']: +def task_arduino_install_core(): + """Arduino: install the core tool-chain for a platform""" + cores = [board['core'] for board in context['boards']] + for core in cores: yield { - 'basename': 'arduino-install-board', - 'name': board, - 'actions': ["{} {} core install {}".format(ARDUINO_CLI, arduino_add_url, board), + 'basename': 'arduino-install-core', + 'name': core, + 'actions': ["{} {} core install {}".format(ARDUINO_CLI, arduino_add_url, core), ], - 'task_dep': ['arduino-install-cli', 'arduino-update-boards'], - 'file_dep': [CONTEXT_FILE], + 'task_dep': ['arduino-install-cli', 'arduino-update-index'], + 'uptodate': [run_once], + 'title': show_cmd, + } + + +def task_arduino_lib_update_index(): + """Arduino: get a fresh copy of the library index""" + return { + 'basename': 'arduino-lib-update-index', + 'actions': ["{} {} lib update-index".format(ARDUINO_CLI, arduino_add_url), + ], + 'uptodate': [run_once], + 'task_dep': ['arduino-install-cli'], + 'title': show_cmd, } def task_arduino_install_libs(): """Arduino: install the specific libraries""" - return { + yield { 'basename': 'arduino-install-libs', - "actions": None, + 'name': None, + } + libs = [] + if 'libraries' in context: + libs = context['libraries'] + for lib in libs: + lib_cli = "" + lib_name = "" + if 'name' in lib: + lib_cli = lib['name'] + lib_name = lib['name'] + if 'version' in lib: + lib_cli += "@" + str(lib['version']) + elif 'git' in lib: + lib_cli = '--git-url ' + lib['git'] + lib_name = lib['git'].split('/')[-1] + lib_name = lib_name.replace(".git", "") + os.environ['ARDUINO_LIBRARY_ENABLE_UNSAFE_INSTALL'] = 'true' + if 'version' in lib: + lib_cli += "#" + str(lib['version']) + elif 'zip' in lib: + lib_cli = '--zip-path ' + lib['zip'] + lib_name = Path(lib['zip']).stem + os.environ['ARDUINO_LIBRARY_ENABLE_UNSAFE_INSTALL'] = 'true' + + yield { + 'basename': 'arduino-install-libs', + 'name': lib_name, + 'actions': ["{} lib install {}".format(ARDUINO_CLI, lib_cli)], + 'uptodate': [run_once], + 'task_dep': ['arduino-install-cli', + 'arduino-lib-update-index'], + 'title': show_cmd, + } + + +def task_arduino_lib_upgrade(): + """Arduino: upgrade the libraries to its latest revision""" + yield { + 'basename': 'arduino-upgrade-libs', + 'name': None, + } + libs = [] + if 'libraries' in context: + libs = context['libraries'] + for lib in libs: + lib_cli = "" + lib_name = "" + cli_action = 'install' + if 'name' in lib: + lib_cli = lib['name'] + lib_name = lib['name'] + cli_action = 'upgrade' + elif 'git' in lib: + lib_cli = '--git-url ' + lib['git'] + lib_name = lib['git'].split('/')[-1] + lib_name = lib_name.replace(".git", "") + os.environ['ARDUINO_LIBRARY_ENABLE_UNSAFE_INSTALL'] = 'true' + elif 'zip' in lib: + lib_cli = '--zip-path ' + lib['zip'] + lib_name = Path(lib['zip']).stem + os.environ['ARDUINO_LIBRARY_ENABLE_UNSAFE_INSTALL'] = 'true' + + yield { + 'basename': 'arduino-upgrade-libs', + 'name': lib_name, + 'actions': ["{} lib {} {}".format(ARDUINO_CLI, cli_action, lib_cli)], + 'uptodate': [False], + 'verbosity': 2, + 'task_dep': ['arduino-install-cli', + 'arduino-lib-update-index'], + 'title': show_cmd, + } + + +def task_arduino_libs(): + """Arduino: list installed libraries""" + return { + 'basename': 'arduino-libs', + 'actions': ["{} {} lib list".format(ARDUINO_CLI, arduino_add_url), + ], + 'uptodate': [False], + 'verbosity': 2, 'task_dep': ['arduino-install-cli'], + 'title': show_cmd, } +def task_arduino_board_details(): + """Arduino: get board details, a list of parameters one normally sets via the menu interface.""" + for board in context['boards']: + fqbn = board['fqbn'] + yield { + 'basename': 'arduino-board-details', + 'name': board['nick'], + 'verbosity': 2, + 'actions': ["{} board details --fqbn {}".format(ARDUINO_CLI, fqbn)], + 'task_dep': ['arduino-install-cli', + 'arduino-install-core:'+board['core'], + ], + 'uptodate': [False], # force to run the task always + 'title': show_cmd, + } + + def task_arduino_compile(): """Arduino: Compile the sources into a UF2 file (and bin-file)""" working_directory = Path('.') headers = list(working_directory.glob('*.h')) cpp_files = list(working_directory.glob('*.cpp')) + + # dependency manager is defined for all code inside the generator: + dep_manager = doit.Globals.dep_manager + + def store(fqbn_store, extra_flags_store): + return dict(fqbn=fqbn_store, extra_flags=extra_flags_store) + for board in context['boards']: + fqbn = board['fqbn'] + if 'parameters' in board: + parameters = ",".join("{}={}".format(k, v) for k, v in board['parameters'].items()) + if parameters != "": + fqbn += ":" + parameters + extra_flags = "" + if 'extra_defines' in board: + for k, v in board['extra_defines'].items(): + if type(v) is str: + v = '"' + v + '"' + flag = "compiler.cpp.extra_flags=\"-D{}={}\"".format(k, v) + flag = flag.replace('"', '\\"') + extra_flags += '--build-property "{}" '.format(flag) + result = dep_manager.get_result("{}:{}".format("arduino-compile", board['nick'])) + clean_flag = "" + if type(result) is dict: + if result['fqbn'] != fqbn: + clean_flag = " --clean" + if result['extra_flags'] != extra_flags: + clean_flag = " --clean" + else: + clean_flag = " --clean" + yield { 'basename': 'arduino-compile', 'name': board['nick'], - 'actions': ["{} compile --fqbn {} i2c-stick-arduino.ino -e --clean".format(ARDUINO_CLI, board['fqbn']), + 'actions': ["{} compile --fqbn {} {} {}.ino -e {}".format( + ARDUINO_CLI, fqbn, extra_flags, context['ino'], clean_flag), + (store, [fqbn, extra_flags]), ], 'task_dep': ['arduino-install-cli', - 'arduino-install-board:'+board['platform'], + 'arduino-install-core:'+board['core'], 'arduino-install-libs', 'generate:i2c_stick_dispatcher.h', 'generate:i2c_stick_dispatcher.cpp', ], + 'title': show_cmd, 'file_dep': [CONTEXT_FILE, - 'i2c-stick-arduino.ino', + '{}.ino'.format(context['ino']), 'i2c_stick_dispatcher.h', - 'i2c_stick_dispatcher.cpp'] + headers + cpp_files, - 'targets': ['build/{}/i2c-stick-arduino.ino.uf2'.format(board['fqbn'].replace(":", "."))], + 'i2c_stick_dispatcher.cpp', + ] + headers + cpp_files, + 'targets': ['build/{}/{}.ino.{}'.format( + board['fqbn'].replace(":", "."), context['ino'], board['bin_extension'])], } def task_arduino_upload(): """Arduino: Upload to the target board""" + def do_upload(board_cfg, port): if port == 'auto': - filtered_ports = [] - pid = None - vid = None - if 'USB_VID' in board_cfg: - vid = board_cfg['USB_VID'] - if 'USB_PID' in board_cfg: - pid = board_cfg['USB_PID'] - for p in serial.tools.list_ports.comports(include_links=False): - if vid is None: + method = 'vid_pid' + if 'port_discovery_method' in board_cfg: + method = board_cfg['port_discovery_method'] + + if method == 'vid_pid': # special case for teensy + filtered_ports = [] + pid = None + vid = None + if 'USB_VID' in board_cfg: + vid = board_cfg['USB_VID'] + if 'USB_PID' in board_cfg: + pid = board_cfg['USB_PID'] + for p in serial.tools.list_ports.comports(include_links=False): + if vid is None: + if pid is None: + filtered_ports.append(p) + continue + + if vid is None: + if p.pid == pid: + filtered_ports.append(p) + continue if pid is None: - filtered_ports.append(p) - continue - - if vid is None: - if p.pid == pid: - filtered_ports.append(p) - continue - if pid is None: - if p.vid == vid: - filtered_ports.append(p) - continue + if p.vid == vid: + filtered_ports.append(p) + continue - if p.vid == vid: - if p.pid == pid: - filtered_ports.append(p) - port = filtered_ports[0].name - return "{} upload --fqbn {} i2c-stick-arduino.ino --port {}".format(ARDUINO_CLI, board_cfg['fqbn'], port) + if p.vid == vid: + if p.pid == pid: + filtered_ports.append(p) + port = filtered_ports[0].name + + if method == 'arduino-cli': + output = subprocess.check_output("{} board list --fqbn {}".format(ARDUINO_CLI, board_cfg['fqbn']), + text=True) + lines = output.split("\n") + if len(lines) >= 2: + port = lines[1].split(' ')[0] # we only use one; the first one; to upload... + + fqbn = board_cfg['fqbn'] + if 'parameters' in board_cfg: + parameters = ",".join("{}={}".format(k, v) for k, v in board_cfg['parameters'].items()) + if parameters != "": + fqbn += ":" + parameters + return "{} upload --fqbn {} {}.ino --port {}".format(ARDUINO_CLI, fqbn, context['ino'], port) for board in context['boards']: yield { @@ -277,11 +459,10 @@ def do_upload(board_cfg, port): 'default': 'auto', }, ], - 'actions': [CmdAction((do_upload, [board], {})), - ], + 'actions': [CmdAction((do_upload, [board], {}))], 'task_dep': ['arduino-install-cli', - 'arduino-compile', - ], + 'arduino-compile:{}'.format(board['nick']), + ], 'file_dep': [CONTEXT_FILE], 'uptodate': [False], # force to run the task always 'verbosity': 2, @@ -290,6 +471,7 @@ def do_upload(board_cfg, port): def task_generate(): """Generate file using context.yaml and jinja2 template files""" + def do_generate(template, output): this_dir = os.path.dirname(os.path.abspath(__file__)) yamlinclude.YamlIncludeConstructor.add_to_loader_class(loader_class=yaml.FullLoader, base_dir=this_dir) @@ -300,10 +482,10 @@ def do_generate(template, output): autoescape=jinja2.select_autoescape() ) - t = env.get_template(template) + jinja_t = env.get_template(template) with open(output, 'w') as output_f: - output_f.write(t.render(context)) + output_f.write(jinja_t.render(context)) working_directory = Path('.') for jinja2_file in working_directory.glob('*.jinja2'): @@ -316,6 +498,7 @@ def do_generate(template, output): 'file_dep': [jinja2_file.name], 'task_dep': ['pip:requirements.txt'], 'targets': [output_file.name], + 'title': show_cmd, } @@ -426,4 +609,5 @@ def do_add_driver(driver, src_name, function_id, sa_list): if __name__ == '__main__': import doit + doit.run(globals()) From 3bc0ede7367142946fba7b1e54b13a69d1672b54 Mon Sep 17 00:00:00 2001 From: karelv Date: Wed, 1 Nov 2023 13:23:26 -0700 Subject: [PATCH 035/112] add todo; remove show cmd for dynamic commands --- i2c-stick-arduino/dodo.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/i2c-stick-arduino/dodo.py b/i2c-stick-arduino/dodo.py index 4f60924..2e405d0 100644 --- a/i2c-stick-arduino/dodo.py +++ b/i2c-stick-arduino/dodo.py @@ -1,3 +1,7 @@ +# todo: +# [ ] bumpver version synchronization between firmware / web / python +# [ ] + import sys import subprocess @@ -160,7 +164,6 @@ def do_install(task): 'verbosity': 2, 'targets': [ARDUINO_CLI], 'uptodate': [run_once], - 'title': show_cmd, } From 6a74b528dfc2db9b03c54f0428db502b2763a286 Mon Sep 17 00:00:00 2001 From: karelv Date: Wed, 1 Nov 2023 13:34:17 -0700 Subject: [PATCH 036/112] reformat with pycharm --- i2c-stick-py/melexis/i2c_stick/I2CStick.py | 70 +++++++--------------- 1 file changed, 21 insertions(+), 49 deletions(-) diff --git a/i2c-stick-py/melexis/i2c_stick/I2CStick.py b/i2c-stick-py/melexis/i2c_stick/I2CStick.py index 76e0d1b..9f0b318 100644 --- a/i2c-stick-py/melexis/i2c_stick/I2CStick.py +++ b/i2c-stick-py/melexis/i2c_stick/I2CStick.py @@ -2,8 +2,10 @@ import time import re + class I2CStick: ser = None + def __init__(self, port): self.open(port) @@ -15,15 +17,13 @@ def open(self, port): self.ser.flushOutput() time.sleep(0.1) - def close(self): if self.ser is not None: self.ser.close() self.ser = None - def read_continuous_message(self): - line = self.ser.readline().decode('utf-8').rstrip() # read a '\n' terminated line + line = self.ser.readline().decode('utf-8').rstrip() # read a '\n' terminated line if line.startswith("@"): values = line.split(":") if values[2] == 'mv': @@ -31,7 +31,6 @@ def read_continuous_message(self): return {'sa': int(values[-3], 16), 'time': int(values[-2]), 'drv': int(values[1], 16), 'mv': mv_list} return None - def stop_continuous_mode(self): self.ser.write(b'!') time.sleep(0.1) @@ -39,20 +38,17 @@ def stop_continuous_mode(self): self.ser.flushOutput() time.sleep(0.1) - def trigger_continuous_mode(self): self.ser.write(b'!') time.sleep(0.1) self.ser.flushInput() self.ser.flushOutput() self.ser.write(b';') - self.ser.readline().decode('utf-8').rstrip() # read a '\n' terminated line - + self.ser.readline().decode('utf-8').rstrip() # read a '\n' terminated line def run_cmd(self, cmd): - self.ser.write(bytes(cmd+"\n", 'utf-8')) - return self.ser.readline().decode('utf-8').rstrip() # read a '\n' terminated line - + self.ser.write(bytes(cmd + "\n", 'utf-8')) + return self.ser.readline().decode('utf-8').rstrip() # read a '\n' terminated line def mlx(self): result = [] @@ -68,14 +64,13 @@ def mlx(self): return None result.append(a[1]) start = time.time() - a = self.ser.readline().decode('utf-8').rstrip() # read a '\n' terminated line + a = self.ser.readline().decode('utf-8').rstrip() # read a '\n' terminated line t = time.time() - start self.ser.timeout = timeout_old return result - def fv(self): a = self.run_cmd("fv") a = a.split(":") @@ -83,7 +78,6 @@ def fv(self): return None return a[1] - def bi(self): a = self.run_cmd("bi") a = a.split(":") @@ -91,19 +85,15 @@ def bi(self): return None return a[1] - def i2c_read(self, sa): return None - def i2c_write(self, sa): return None - def i2c_addressed_read(self, sa): return None - def ch(self): result = {} timeout_old = self.ser.timeout @@ -142,18 +132,16 @@ def ch(self): result[key].append(item) start = time.time() - a = self.ser.readline().decode('utf-8').rstrip() # read a '\n' terminated line + a = self.ser.readline().decode('utf-8').rstrip() # read a '\n' terminated line t = time.time() - start self.ser.timeout = timeout_old return result - def ch_write(self): return None - def scan(self): result = [] timeout_old = self.ser.timeout @@ -176,14 +164,13 @@ def scan(self): item['product'] = a[3] result.append(item) start = time.time() - a = self.ser.readline().decode('utf-8').rstrip() # read a '\n' terminated line + a = self.ser.readline().decode('utf-8').rstrip() # read a '\n' terminated line t = time.time() - start self.ser.timeout = timeout_old return result - def ls(self): result = [] timeout_old = self.ser.timeout @@ -206,16 +193,15 @@ def ls(self): item['product'] = a[3] result.append(item) start = time.time() - a = self.ser.readline().decode('utf-8').rstrip() # read a '\n' terminated line + a = self.ser.readline().decode('utf-8').rstrip() # read a '\n' terminated line t = time.time() - start self.ser.timeout = timeout_old return result - def dis(self, sa, disable=1): - a = self.run_cmd("dis:{:02X}:{}".format(sa,disable)) + a = self.run_cmd("dis:{:02X}:{}".format(sa, disable)) a = a.split(":") if a[0] != "dis": return None @@ -223,19 +209,16 @@ def dis(self, sa, disable=1): return None if a[2] == "FAIL": return "FAIL:" + a[3] - result = {} - result['status'] = a[3] - result['disabled'] = int(a[2]) + result = {'status': a[3], + 'disabled': int(a[2])} return result - def mv(self, sa): - self.ser.write('mv:{:02X}'.format(sa).encode()+ b'\n') - line = self.ser.readline().decode('utf-8').rstrip() # read a '\n' terminated line + self.ser.write('mv:{:02X}'.format(sa).encode() + b'\n') + line = self.ser.readline().decode('utf-8').rstrip() # read a '\n' terminated line values = line.split(":")[-1] return [float(value) for value in values.split(",")] - def sn(self, sa): a = self.run_cmd("sn:{:02X}".format(sa)) a = a.split(":") @@ -245,7 +228,6 @@ def sn(self, sa): return None return a[2] - def cs(self, sa): result = {} timeout_old = self.ser.timeout @@ -282,7 +264,7 @@ def cs(self, sa): value[i] = new_value else: value[i] = new_value['value'] - if (len(value) == 1): + if len(value) == 1: value = value[0] result['read_only'][a[0]] = value else: @@ -304,18 +286,17 @@ def cs(self, sa): value[i] = new_value else: value[i] = new_value['value'] - if (len(value) == 1): + if len(value) == 1: value = value[0] result[a[0]] = value start = time.time() - a = self.ser.readline().decode('utf-8').rstrip() # read a '\n' terminated line + a = self.ser.readline().decode('utf-8').rstrip() # read a '\n' terminated line t = time.time() - start self.ser.timeout = timeout_old return result - def cs_write(self, sa, item, value): a = self.run_cmd("+cs:{:02X}:{}={}".format(sa, item, value)) a = a.split(":") @@ -329,7 +310,6 @@ def cs_write(self, sa, item, value): return a[2] return a[2] - def nd(self, sa): a = self.run_cmd("nd:{:02X}".format(sa)) a = a.split(":") @@ -341,7 +321,6 @@ def nd(self, sa): return "FAIL:" + a[3] return int(a[2]) - def mr(self, sa, address, count): a = self.run_cmd("mr:{:02X}:{:04X},{:04X}".format(sa, address, count)) a = a.split(":") @@ -370,9 +349,8 @@ def mr(self, sa, address, count): return result - def mw(self, sa, address, data): - if type(data) == list: + if type(data) is list: data_str = ",".join(["{:04X}".format(x) for x in data]) else: data_str = "{:04X}".format(data) @@ -384,7 +362,6 @@ def mw(self, sa, address, data): return None return a[2] - def mv(self, sa): a = self.run_cmd("mv:{:02X}".format(sa)) a = a.split(":") @@ -397,7 +374,6 @@ def mv(self, sa): result['values'] = [float(x) for x in a[3].split(',')] return result - def raw(self, sa): a = self.run_cmd("raw:{:02X}".format(sa)) a = a.split(":") @@ -408,21 +384,17 @@ def raw(self, sa): if a[2] == "FAIL": return "FAIL:" + a[3] result = {} - result = {} result['time_ms'] = int(a[2]) result['values'] = [int(x, 16) for x in a[3].split(',')] - result['values'] = [x if x < 2**15 else x - 2**16 for x in result['values']] + result['values'] = [x if x < 2 ** 15 else x - 2 ** 16 for x in result['values']] return result - def pwm(self, pin, pwm): a = self.run_cmd("pwm:{}:{}".format(pin, pwm)) return a - - -if (__name__ == '__main__'): +if __name__ == '__main__': mis = I2CStick("COM154") print(mis.mv(0x3A)) mis.trigger_continuous_mode() From 077c15e3d49f1d94a6475028c85ffa72f3887444 Mon Sep 17 00:00:00 2001 From: karelv Date: Wed, 1 Nov 2023 13:35:40 -0700 Subject: [PATCH 037/112] allow check SA available from generic i2c command, let gernetic i2c command fail when amount of received bytes is not matching --- i2c-stick-arduino/i2c-stick-arduino.ino | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/i2c-stick-arduino/i2c-stick-arduino.ino b/i2c-stick-arduino/i2c-stick-arduino.ino index 1d0d324..eb50cd8 100644 --- a/i2c-stick-arduino/i2c-stick-arduino.ino +++ b/i2c-stick-arduino/i2c-stick-arduino.ino @@ -226,6 +226,16 @@ hal_i2c_direct_write(uint8_t sa, uint8_t *write_buffer, uint16_t write_n_bytes) WIRE.write(write_buffer[i]); } byte result = WIRE.endTransmission(); // stop transmitting + + if (write_n_bytes == 0) // shorthand for hal_i2c_slave_address_available + { + if (result != 2) + { // found SA; return OK + return 0; + } + return 1; // not found return not-ok. + } + #ifdef ARDUINO_ARCH_RP2040 if (result == 4) result = 0; // ignore error=4 ('other error', but I can't seem to find anything wrong; only on this MCU platform) #endif @@ -250,7 +260,11 @@ hal_i2c_indirect_read(uint8_t sa, uint8_t *write_buffer, uint16_t write_n_bytes, #endif if (result != 0) return result; - WIRE.requestFrom((uint8_t)sa, uint8_t(read_n_bytes), uint8_t(true)); + result = WIRE.requestFrom((uint8_t)sa, uint8_t(read_n_bytes), uint8_t(true)); + if (result != uint8_t(read_n_bytes)) + { + return -1; + } for (uint16_t i=0; i Date: Wed, 1 Nov 2023 13:38:13 -0700 Subject: [PATCH 038/112] commit generated dispatcher; now each fresh doit compile will re-generated the dispatcher file based on context.yaml --- i2c-stick-arduino/dodo.py | 16 - i2c-stick-arduino/i2c_stick_dispatcher.cpp | 452 ++++++++++++++++++++- i2c-stick-arduino/i2c_stick_dispatcher.h | 46 ++- 3 files changed, 492 insertions(+), 22 deletions(-) diff --git a/i2c-stick-arduino/dodo.py b/i2c-stick-arduino/dodo.py index 2e405d0..5bfd561 100644 --- a/i2c-stick-arduino/dodo.py +++ b/i2c-stick-arduino/dodo.py @@ -87,22 +87,6 @@ def do_clean(): except Exception as err: print(str(err)) - # reset the automatically generated files... - txt = """ -// this file is automatically generated: -// please edit 'context.yaml', and then: -// run the doit command `python dodo.py generate` or `doit generate`. - -#error "This file is automatically generated; please run `python dodo.py source` or `doit source` from command line" -""" - with open("i2c_stick_dispatcher.cpp", "w") as text_file: - text_file.write(txt) - with open("i2c_stick_dispatcher.h", "w") as text_file: - text_file.write(txt) - from doit.doit_cmd import DoitMain - DoitMain().run(["forget", "generate:i2c_stick_dispatcher.h"]) - DoitMain().run(["forget", "generate:i2c_stick_dispatcher.cpp"]) - return { "actions": None, "clean": [do_clean], diff --git a/i2c-stick-arduino/i2c_stick_dispatcher.cpp b/i2c-stick-arduino/i2c_stick_dispatcher.cpp index b2aaa43..ba491fc 100644 --- a/i2c-stick-arduino/i2c_stick_dispatcher.cpp +++ b/i2c-stick-arduino/i2c_stick_dispatcher.cpp @@ -1,6 +1,452 @@ - // this file is automatically generated: // please edit 'context.yaml', and then: -// run the doit command `python dodo.py generate` or `doit generate`. +// run the python doit script `python dodo.py generate` or `doit generate`. + +#include "i2c_stick_dispatcher.h" +#include "i2c_stick.h" +#include "i2c_stick_cmd.h" + +// Include all the drivers cmd header files: +#include "mlx90614_cmd.h" +#include "mlx90640_cmd.h" +#include "mlx90641_cmd.h" +#include "mlx90632_cmd.h" +#include "mlx90621_cmd.h" + +#include +#include + +int16_t +i2c_stick_register_all_drivers() +{ + int16_t result = 1; + if (cmd_90614_register_driver() < 0) result = -1; + if (cmd_90640_register_driver() < 0) result = -1; + if (cmd_90641_register_driver() < 0) result = -1; + if (cmd_90632_register_driver() < 0) result = -1; + if (cmd_90621_register_driver() < 0) result = -1; + return result; +} + + +const char* +i2c_stick_get_drv_name_by_drv(uint8_t drv) +{ + switch(drv) + { + case DRV_MLX90614_ID: + return DRV_MLX90614_NAME; + case DRV_MLX90640_ID: + return DRV_MLX90640_NAME; + case DRV_MLX90641_ID: + return DRV_MLX90641_NAME; + case DRV_MLX90632_ID: + return DRV_MLX90632_NAME; + case DRV_MLX90621_ID: + return DRV_MLX90621_NAME; + default: + if (0) {} + } + return "Unknown"; +} + + +uint8_t +i2c_stick_get_drv_by_drv_name(const char *drv_name) +{ + if (!strcasecmp(drv_name, DRV_MLX90614_NAME)) return DRV_MLX90614_ID; + if (!strcasecmp(drv_name, DRV_MLX90640_NAME)) return DRV_MLX90640_ID; + if (!strcasecmp(drv_name, DRV_MLX90641_NAME)) return DRV_MLX90641_ID; + if (!strcasecmp(drv_name, DRV_MLX90632_NAME)) return DRV_MLX90632_ID; + if (!strcasecmp(drv_name, DRV_MLX90621_NAME)) return DRV_MLX90621_ID; + return 0; +} + + + +// command functions. + +uint8_t +cmd_mv(uint8_t sa, float *mv_list, uint16_t *mv_count, char const **error_message) +{ + // sanity check + if (sa > 127) { return 0; } + + uint16_t spot = g_sa_list[sa].spot_; + uint8_t drv = g_sa_drv_register[spot].drv_; + + switch(drv) + { + case DRV_MLX90614_ID: + cmd_90614_mv(sa, mv_list, mv_count, error_message); + break; + case DRV_MLX90640_ID: + cmd_90640_mv(sa, mv_list, mv_count, error_message); + break; + case DRV_MLX90641_ID: + cmd_90641_mv(sa, mv_list, mv_count, error_message); + break; + case DRV_MLX90632_ID: + cmd_90632_mv(sa, mv_list, mv_count, error_message); + break; + case DRV_MLX90621_ID: + cmd_90621_mv(sa, mv_list, mv_count, error_message); + break; + default: + return 0; + } + return drv; +} + + +uint8_t +cmd_raw(uint8_t sa, uint16_t *raw_list, uint16_t *raw_count, char const **error_message) +{ + // sanity check + if (sa > 127) { return 0; } + + uint16_t spot = g_sa_list[sa].spot_; + uint8_t drv = g_sa_drv_register[spot].drv_; + + switch(drv) + { + case DRV_MLX90614_ID: + cmd_90614_raw(sa, raw_list, raw_count, error_message); + break; + case DRV_MLX90640_ID: + cmd_90640_raw(sa, raw_list, raw_count, error_message); + break; + case DRV_MLX90641_ID: + cmd_90641_raw(sa, raw_list, raw_count, error_message); + break; + case DRV_MLX90632_ID: + cmd_90632_raw(sa, raw_list, raw_count, error_message); + break; + case DRV_MLX90621_ID: + cmd_90621_raw(sa, raw_list, raw_count, error_message); + break; + default: + return 0; + } + return drv; +} + + +uint8_t +cmd_nd(uint8_t sa, uint8_t *nd, char const **error_message) +{ + // sanity check + if (sa > 127) { return 0; } + + uint16_t spot = g_sa_list[sa].spot_; + uint8_t drv = g_sa_drv_register[spot].drv_; + + switch(drv) + { + case DRV_MLX90614_ID: + cmd_90614_nd(sa, nd, error_message); + break; + case DRV_MLX90640_ID: + cmd_90640_nd(sa, nd, error_message); + break; + case DRV_MLX90641_ID: + cmd_90641_nd(sa, nd, error_message); + break; + case DRV_MLX90632_ID: + cmd_90632_nd(sa, nd, error_message); + break; + case DRV_MLX90621_ID: + cmd_90621_nd(sa, nd, error_message); + break; + default: + return 0; + } + return drv; +} + + +uint8_t +cmd_sn(uint8_t sa, uint16_t *sn_list, uint16_t *sn_count, char const **error_message) +{ + // sanity check + if (sa > 127) { return 0; } + + uint16_t spot = g_sa_list[sa].spot_; + uint8_t drv = g_sa_drv_register[spot].drv_; + + switch(drv) + { + case DRV_MLX90614_ID: + cmd_90614_sn(sa, sn_list, sn_count, error_message); + break; + case DRV_MLX90640_ID: + cmd_90640_sn(sa, sn_list, sn_count, error_message); + break; + case DRV_MLX90641_ID: + cmd_90641_sn(sa, sn_list, sn_count, error_message); + break; + case DRV_MLX90632_ID: + cmd_90632_sn(sa, sn_list, sn_count, error_message); + break; + case DRV_MLX90621_ID: + cmd_90621_sn(sa, sn_list, sn_count, error_message); + break; + default: + *sn_count = 0; + return 0; + } + return drv; +} + + +uint8_t +cmd_cs(uint8_t sa, uint8_t channel_mask, const char *input) +{ + // sanity check + if (sa > 127) { return 0; } + + uint16_t spot = g_sa_list[sa].spot_; + uint8_t drv = g_sa_drv_register[spot].drv_; + uint8_t raw = g_sa_drv_register[spot].raw_; + + char buf[16]; memset(buf, 0, sizeof(buf)); + + send_answer_chunk(channel_mask, "cs:", 0); + uint8_to_hex(buf, sa); + send_answer_chunk(channel_mask, buf, 0); + send_answer_chunk(channel_mask, ":RAW=", 0); + itoa(raw, buf, 10); + send_answer_chunk(channel_mask, buf, 1); + + switch(drv) + { + case DRV_MLX90614_ID: + cmd_90614_cs(sa, channel_mask, input); + break; + case DRV_MLX90640_ID: + cmd_90640_cs(sa, channel_mask, input); + break; + case DRV_MLX90641_ID: + cmd_90641_cs(sa, channel_mask, input); + break; + case DRV_MLX90632_ID: + cmd_90632_cs(sa, channel_mask, input); + break; + case DRV_MLX90621_ID: + cmd_90621_cs(sa, channel_mask, input); + break; + default: + return 0; + } + return drv; +} + + +uint8_t +cmd_cs_write(uint8_t sa, uint8_t channel_mask, const char *input) +{ + // sanity check + if (sa > 127) { return 0; } + + uint16_t spot = g_sa_list[sa].spot_; + uint8_t drv = g_sa_drv_register[spot].drv_; + + char buf[16]; memset(buf, 0, sizeof(buf)); + + const char *var_name = "RAW="; + if (!strncmp(var_name, input, strlen(var_name))) + { + // 1.1. try to find if the desired value is a 'driver-name' + int16_t value = atoi(input+strlen(var_name)); + if ((value >= 0) && (value <= 1)) + { + if (value == 1) + { + g_sa_drv_register[spot].raw_ = 1; + } else + { + g_sa_drv_register[spot].raw_ = 0; + } + send_answer_chunk(channel_mask, "+cs:", 0); + uint8_to_hex(buf, sa); + send_answer_chunk(channel_mask, buf, 0); + send_answer_chunk(channel_mask, ":RAW=", 0); + uint8_to_hex(buf, g_sa_drv_register[spot].raw_); + send_answer_chunk(channel_mask, buf, 0); + send_answer_chunk(channel_mask, ":OK [host-register]", 1); + } else + { + send_answer_chunk(channel_mask, "+cs:", 0); + uint8_to_hex(buf, sa); + send_answer_chunk(channel_mask, buf, 0); + send_answer_chunk(channel_mask, ":RAW= FAIL; value not valid", 1); + } + return drv; + } + + switch(drv) + { + case DRV_MLX90614_ID: + cmd_90614_cs_write(sa, channel_mask, input); + break; + case DRV_MLX90640_ID: + cmd_90640_cs_write(sa, channel_mask, input); + break; + case DRV_MLX90641_ID: + cmd_90641_cs_write(sa, channel_mask, input); + break; + case DRV_MLX90632_ID: + cmd_90632_cs_write(sa, channel_mask, input); + break; + case DRV_MLX90621_ID: + cmd_90621_cs_write(sa, channel_mask, input); + break; + default: + return 0; + } + return drv; +} + + +uint8_t +cmd_mr(uint8_t sa, uint16_t *mem_list, uint16_t mem_start_address, uint16_t mem_count, uint8_t *bit_per_address, uint8_t *address_increments, char const **error_message) +{ + // sanity check + if (sa > 127) { return 0; } + + uint16_t spot = g_sa_list[sa].spot_; + uint8_t drv = g_sa_drv_register[spot].drv_; + + switch(drv) + { + case DRV_MLX90614_ID: + cmd_90614_mr(sa, mem_list, mem_start_address, mem_count, bit_per_address, address_increments, error_message); + break; + case DRV_MLX90640_ID: + cmd_90640_mr(sa, mem_list, mem_start_address, mem_count, bit_per_address, address_increments, error_message); + break; + case DRV_MLX90641_ID: + cmd_90641_mr(sa, mem_list, mem_start_address, mem_count, bit_per_address, address_increments, error_message); + break; + case DRV_MLX90632_ID: + cmd_90632_mr(sa, mem_list, mem_start_address, mem_count, bit_per_address, address_increments, error_message); + break; + case DRV_MLX90621_ID: + cmd_90621_mr(sa, mem_list, mem_start_address, mem_count, bit_per_address, address_increments, error_message); + break; + default: + return 0; + } + + return drv; +} + + +uint8_t +cmd_mw(uint8_t sa, uint16_t *mem_list, uint16_t mem_start_address, uint16_t mem_count, uint8_t *bit_per_address, uint8_t *address_increments, char const **error_message) +{ + // sanity check + if (sa > 127) { return 0; } + + uint16_t spot = g_sa_list[sa].spot_; + uint8_t drv = g_sa_drv_register[spot].drv_; + + switch(drv) + { + case DRV_MLX90614_ID: + cmd_90614_mw(sa, mem_list, mem_start_address, mem_count, bit_per_address, address_increments, error_message); + break; + case DRV_MLX90640_ID: + cmd_90640_mw(sa, mem_list, mem_start_address, mem_count, bit_per_address, address_increments, error_message); + break; + case DRV_MLX90641_ID: + cmd_90641_mw(sa, mem_list, mem_start_address, mem_count, bit_per_address, address_increments, error_message); + break; + case DRV_MLX90632_ID: + cmd_90632_mw(sa, mem_list, mem_start_address, mem_count, bit_per_address, address_increments, error_message); + break; + case DRV_MLX90621_ID: + cmd_90621_mw(sa, mem_list, mem_start_address, mem_count, bit_per_address, address_increments, error_message); + break; + default: + return 0; + } + + return drv; +} + + +uint8_t +cmd_is(uint8_t sa, uint8_t drv, uint8_t *is_ok, char const **error_message) +{ + if ((drv <= 0) || (drv > 63)) + { + *is_ok = 0; + return 0; + } + + switch(drv) + { + case DRV_MLX90614_ID: + cmd_90614_is(sa, is_ok, error_message); + break; + case DRV_MLX90640_ID: + cmd_90640_is(sa, is_ok, error_message); + break; + case DRV_MLX90641_ID: + cmd_90641_is(sa, is_ok, error_message); + break; + case DRV_MLX90632_ID: + cmd_90632_is(sa, is_ok, error_message); + break; + case DRV_MLX90621_ID: + cmd_90621_is(sa, is_ok, error_message); + break; + default: + return 0; + } + + return drv; +} + + + +uint8_t +cmd_tear_down(uint8_t sa) +{ + if (sa == 255) + { + for (sa = 0; sa <= 127; sa++) + { + cmd_tear_down(sa); + } + return sa; + } + // sanity check + if (sa > 127) { return 0; } + + uint16_t spot = g_sa_list[sa].spot_; + uint8_t drv = g_sa_drv_register[spot].drv_; -#error "This file is automatically generated; please run `python dodo.py source` or `doit source` from command line" + switch(drv) + { + case DRV_MLX90614_ID: + cmd_90614_tear_down(sa); + break; + case DRV_MLX90640_ID: + cmd_90640_tear_down(sa); + break; + case DRV_MLX90641_ID: + cmd_90641_tear_down(sa); + break; + case DRV_MLX90632_ID: + cmd_90632_tear_down(sa); + break; + case DRV_MLX90621_ID: + cmd_90621_tear_down(sa); + break; + default: + return 0; + } + return drv; +} \ No newline at end of file diff --git a/i2c-stick-arduino/i2c_stick_dispatcher.h b/i2c-stick-arduino/i2c_stick_dispatcher.h index b2aaa43..efac110 100644 --- a/i2c-stick-arduino/i2c_stick_dispatcher.h +++ b/i2c-stick-arduino/i2c_stick_dispatcher.h @@ -1,6 +1,46 @@ - // this file is automatically generated: // please edit 'context.yaml', and then: -// run the doit command `python dodo.py generate` or `doit generate`. +// run the python doit script `python dodo.py generate` or `doit generate`. + +#ifndef __I2C_STICK_DISPATCHER_H__ +#define __I2C_STICK_DISPATCHER_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +// driver declarations: +#define DRV_MLX90614_ID 1 +#define DRV_MLX90614_NAME "MLX90614" +#define DRV_MLX90640_ID 2 +#define DRV_MLX90640_NAME "MLX90640" +#define DRV_MLX90641_ID 3 +#define DRV_MLX90641_NAME "MLX90641" +#define DRV_MLX90632_ID 4 +#define DRV_MLX90632_NAME "MLX90632" +#define DRV_MLX90621_ID 5 +#define DRV_MLX90621_NAME "MLX90621" + +int16_t i2c_stick_register_all_drivers(); +const char* i2c_stick_get_drv_name_by_drv(uint8_t drv); +uint8_t i2c_stick_get_drv_by_drv_name(const char *drv_name); + +uint8_t cmd_mv(uint8_t sa, float *mv_list, uint16_t *mv_count, char const **error_message); +uint8_t cmd_raw(uint8_t sa, uint16_t *raw_list, uint16_t *raw_count, char const **error_message); +uint8_t cmd_nd(uint8_t sa, uint8_t *nd, char const **error_message); +uint8_t cmd_sn(uint8_t sa, uint16_t *sn_list, uint16_t *sn_count, char const **error_message); +uint8_t cmd_cs(uint8_t sa, uint8_t channel_mask, const char *input); +uint8_t cmd_cs_write(uint8_t sa, uint8_t channel_mask, const char *input); +uint8_t cmd_mr(uint8_t sa, uint16_t *mem_list, uint16_t mem_start_address, uint16_t mem_count, uint8_t *bit_per_address, uint8_t *address_increments, char const **error_message); +uint8_t cmd_mw(uint8_t sa, uint16_t *mem_list, uint16_t mem_start_address, uint16_t mem_count, uint8_t *bit_per_address, uint8_t *address_increments, char const **error_message); + +uint8_t cmd_is(uint8_t sa, uint8_t drv, uint8_t *is_ok, char const **error_message); +uint8_t cmd_tear_down(uint8_t sa); + +#ifdef __cplusplus +} +#endif -#error "This file is automatically generated; please run `python dodo.py source` or `doit source` from command line" +#endif // __I2C_STICK_DISPATCHER_H__ \ No newline at end of file From 5ef16b30fc36503f7d5f08f5934fde6c00e2320e Mon Sep 17 00:00:00 2001 From: karelv Date: Wed, 1 Nov 2023 16:42:23 -0700 Subject: [PATCH 039/112] adding slave configuration to mlx90621 --- i2c-stick-arduino/mlx90621_api.cpp | 5 + i2c-stick-arduino/mlx90621_cmd.cpp | 363 ++++++++++++++++++++++++++--- i2c-stick-arduino/mlx90621_cmd.h | 7 + 3 files changed, 349 insertions(+), 26 deletions(-) diff --git a/i2c-stick-arduino/mlx90621_api.cpp b/i2c-stick-arduino/mlx90621_api.cpp index 3400d4d..b4edf62 100644 --- a/i2c-stick-arduino/mlx90621_api.cpp +++ b/i2c-stick-arduino/mlx90621_api.cpp @@ -212,6 +212,11 @@ void MLX90621_CalculateTo(uint16_t *frameData, const paramsMLX90621 *params, flo for( int pixelNumber = 0; pixelNumber < 64; pixelNumber++) { irData = frameData[pixelNumber]; + if (irData == 0x7FFF) + { + result[pixelNumber] = -999; // disabled value! + continue; + } if(irData > 32767) { irData = irData - 65536; diff --git a/i2c-stick-arduino/mlx90621_cmd.cpp b/i2c-stick-arduino/mlx90621_cmd.cpp index 309d32b..5103b3d 100644 --- a/i2c-stick-arduino/mlx90621_cmd.cpp +++ b/i2c-stick-arduino/mlx90621_cmd.cpp @@ -169,6 +169,72 @@ check_90621_calibration_ranges(paramsMLX90621 *mlx90621) } +// function to get the raw data, the frame_data is kept in the full pixel size with original pixel positions. +// the frame_data buffer is initialized with 0x7FFF to indicate the pixel is 'disabled' +static int +mlx90621_get_frame_data_special(uint16_t *frame_data, uint8_t start_row, uint8_t start_column, uint8_t rows, uint8_t columns) +{ + int error = 1; + + // check input parameters. + if (rows == 0) return 1; + if (columns == 0) return 1; + if (rows > 4) return 1; + if (columns > 16) return 1; + if (start_row > 4) start_row = 4; + if (start_column > 16) start_column = 16; + if (start_row == 0) start_row = 1; + if (start_column == 0) start_column = 1; + + if (rows >= 3) + { // read in column mode, we will likely read too much data, but we save the overhead communication. + uint8_t start_address = ((start_column-1) * 4); + uint8_t count = 4 * columns; + error = MLX90621_I2CRead(0x60, 0x02, start_address, 1, count, frame_data+start_address); + } else + { // read in row mode + for (uint8_t row = start_row-1; row skip to set the disable value! + continue; + } + } + frame_data[i] = 0x7FFF; + } + + + // Serial.printf("\nraw data:\n\n"); + // for (uint8_t row=0; row<4; row++) + // { + // for (uint8_t col=0; col<16; col++) + // { + // uint8_t i = col * 4 + row; + // Serial.printf("%04X ", frame_data[i]); + // } + // Serial.printf("\n"); + // } + + + // finally read PTAT & compensation pixel + error = MLX90621_I2CRead(0x60, 0x02, 0x40, 1, 2, frame_data+0x40); + return error; +} + + void cmd_90621_init(uint8_t sa) { @@ -182,6 +248,10 @@ cmd_90621_init(uint8_t sa) mlx->emissivity_ = 0.95; mlx->tr_ = 25.0; + mlx->rows_ = 4; + mlx->columns_ = 16; + mlx->start_row_ = 1; + mlx->start_column_ = 1; uint8_t eeMLX90621[256]; @@ -228,16 +298,30 @@ cmd_90621_mv(uint8_t sa, float *mv_list, uint16_t *mv_count, char const **error_ uint16_t mlx90621Frame[66]; memset(&mlx90621Frame, 0, sizeof(mlx90621Frame)); - MLX90621_GetFrameData (mlx90621Frame); + // MLX90621_GetFrameData (mlx90621Frame); + mlx90621_get_frame_data_special(mlx90621Frame, mlx->start_row_, mlx->start_column_, mlx->rows_, mlx->columns_); mlx->ta_ = MLX90621_GetTa (mlx90621Frame, &mlx->mlx90621_); mv_list[0] = mlx->ta_; MLX90621_CalculateTo(mlx90621Frame, &mlx->mlx90621_, mlx->emissivity_, mlx->tr_, mlx->to_); - for (int i=0; i<64; i++) + uint16_t result_counter = 0; + float *p = &mv_list[1]; + for (uint16_t i=0; i<64; i++) { - mv_list[i+1] = mlx->to_[i]; + uint8_t row = (i % 4) + 1; + uint8_t col = (i / 4) + 1; + if ((mlx->start_row_ <= row) && (row < (mlx->start_row_ + mlx->rows_))) + { + if ((mlx->start_column_ <= col) && (col < (mlx->start_column_ + mlx->columns_))) + { // this pixel is enabled => add to result list! + *p++ = mlx->to_[i]; + result_counter++; + continue; + } + } } + *mv_count = (result_counter + 1); } @@ -266,11 +350,33 @@ cmd_90621_raw(uint8_t sa, uint16_t *raw_list, uint16_t *raw_count, char const ** uint16_t mlx90621Frame[66]; memset(&mlx90621Frame, 0, sizeof(mlx90621Frame)); - MLX90621_GetFrameData (mlx90621Frame); + + mlx90621_get_frame_data_special(mlx90621Frame, mlx->start_row_, mlx->start_column_, mlx->rows_, mlx->columns_); + // MLX90621_GetFrameData (mlx90621Frame); + + uint16_t result_counter = 0; + uint16_t *p = raw_list; for (uint16_t i=0; i<66; i++) { - raw_list[i] = (uint16_t)mlx90621Frame[i]; + if (i>=64) // ptat & compensation pix + { + *p++ = (uint16_t)mlx90621Frame[i]; + result_counter++; + continue; + } + uint8_t row = (i % 4) + 1; + uint8_t col = (i / 4) + 1; + if ((mlx->start_row_ <= row) && (row < (mlx->start_row_ + mlx->rows_))) + { + if ((mlx->start_column_ <= col) && (col < (mlx->start_column_ + mlx->columns_))) + { // this pixel is enabled => add to result list! + *p++ = (uint16_t)mlx90621Frame[i]; + result_counter++; + continue; + } + } } + *raw_count = result_counter; } @@ -345,10 +451,11 @@ cmd_90621_cs(uint8_t sa, uint8_t channel_mask, const char *input) cmd_90621_init(sa); } - // todo: // // read the CS(Configuration of the Slave) from the sensor. // + uint8_t rr = MLX90621_GetRefreshRate(); + uint8_t res = MLX90621_GetCurResolution(); char buf[16]; memset(buf, 0, sizeof(buf)); send_answer_chunk(channel_mask, "cs:", 0); @@ -359,6 +466,48 @@ cmd_90621_cs(uint8_t sa, uint8_t channel_mask, const char *input) send_answer_chunk(channel_mask, buf, 1); + send_answer_chunk(channel_mask, "cs:", 0); + uint8_to_hex(buf, sa); + send_answer_chunk(channel_mask, buf, 0); + send_answer_chunk(channel_mask, ":RR=", 0); + itoa(rr, buf, 10); + send_answer_chunk(channel_mask, buf, 1); + + send_answer_chunk(channel_mask, "cs:", 0); + uint8_to_hex(buf, sa); + send_answer_chunk(channel_mask, buf, 0); + send_answer_chunk(channel_mask, ":RES=", 0); + itoa(res, buf, 10); + send_answer_chunk(channel_mask, buf, 1); + + send_answer_chunk(channel_mask, "cs:", 0); + uint8_to_hex(buf, sa); + send_answer_chunk(channel_mask, buf, 0); + send_answer_chunk(channel_mask, ":ROWS=", 0); + itoa(mlx->rows_, buf, 10); + send_answer_chunk(channel_mask, buf, 1); + + send_answer_chunk(channel_mask, "cs:", 0); + uint8_to_hex(buf, sa); + send_answer_chunk(channel_mask, buf, 0); + send_answer_chunk(channel_mask, ":COLUMNS=", 0); + itoa(mlx->columns_, buf, 10); + send_answer_chunk(channel_mask, buf, 1); + + send_answer_chunk(channel_mask, "cs:", 0); + uint8_to_hex(buf, sa); + send_answer_chunk(channel_mask, buf, 0); + send_answer_chunk(channel_mask, ":START_ROW=", 0); + itoa(mlx->start_row_, buf, 10); + send_answer_chunk(channel_mask, buf, 1); + + send_answer_chunk(channel_mask, "cs:", 0); + uint8_to_hex(buf, sa); + send_answer_chunk(channel_mask, buf, 0); + send_answer_chunk(channel_mask, ":START_COLUMN=", 0); + itoa(mlx->start_column_, buf, 10); + send_answer_chunk(channel_mask, buf, 1); + // todo: // // Send the answer back in the format @@ -366,25 +515,34 @@ cmd_90621_cs(uint8_t sa, uint8_t channel_mask, const char *input) // - // todo: + // todo: // // Send the configuration of the MV header, unit and resolution back to the terminal(not to sensor!) // - // send_answer_chunk(channel_mask, "cs:", 0); - // uint8_to_hex(buf, sa); - // send_answer_chunk(channel_mask, buf, 0); - // send_answer_chunk(channel_mask, ":RO:MV_HEADER=TA,TO", 1); + send_answer_chunk(channel_mask, "cs:", 0); + uint8_to_hex(buf, sa); + send_answer_chunk(channel_mask, buf, 0); + send_answer_chunk(channel_mask, ":RO:MV_HEADER=TA,TO_[", 0); + itoa(mlx->rows_ * mlx->columns_, buf, 10); + send_answer_chunk(channel_mask, buf, 0); + send_answer_chunk(channel_mask, "]", 1); - // send_answer_chunk(channel_mask, "cs:", 0); - // uint8_to_hex(buf, sa); - // send_answer_chunk(channel_mask, buf, 0); - // send_answer_chunk(channel_mask, ":RO:MV_UNIT=DegC,DegC", 1); + send_answer_chunk(channel_mask, "cs:", 0); + uint8_to_hex(buf, sa); + send_answer_chunk(channel_mask, buf, 0); + send_answer_chunk(channel_mask, ":RO:MV_UNIT=DegC,DegC[", 0); + itoa(mlx->rows_ * mlx->columns_, buf, 10); + send_answer_chunk(channel_mask, buf, 0); + send_answer_chunk(channel_mask, "]", 1); - // send_answer_chunk(channel_mask, "cs:", 0); - // uint8_to_hex(buf, sa); - // send_answer_chunk(channel_mask, buf, 0); - // send_answer_chunk(channel_mask, ":RO:MV_RES=" xstr(MLX90614_LSB_C) "," xstr(MLX90614_LSB_C), 1); + send_answer_chunk(channel_mask, "cs:", 0); + uint8_to_hex(buf, sa); + send_answer_chunk(channel_mask, buf, 0); + send_answer_chunk(channel_mask, ":RO:MV_RES=" xstr(MLX90621_LSB_C) "," xstr(MLX90621_LSB_C) "[", 0); + itoa(mlx->rows_ * mlx->columns_, buf, 10); + send_answer_chunk(channel_mask, buf, 0); + send_answer_chunk(channel_mask, "]", 1); } @@ -402,16 +560,169 @@ cmd_90621_cs_write(uint8_t sa, uint8_t channel_mask, const char *input) cmd_90621_init(sa); } - - // - // todo: // // write the configuration of the slave to the sensor and report to the channel the status. // - // Please get inspired from other drivers like MLX90614. - // - // Also if SA can be re-programmed, please add the correct sequence here, see also MLX90614 or MLX90632 for an extensive example. - // + + const char *var_name = "EM="; + if (!strncmp(var_name, input, strlen(var_name))) + { + float em = atof(input+strlen(var_name)); + send_answer_chunk(channel_mask, "+cs:", 0); + uint8_to_hex(buf, sa); + send_answer_chunk(channel_mask, buf, 0); + if ((em > 0.1) && (em <= 1.0)) + { + mlx->emissivity_ = em; + send_answer_chunk(channel_mask, ":EM=OK [hub-register]", 1); + } else + { + send_answer_chunk(channel_mask, ":EM=FAIL; outbound", 1); + } + return; + } + var_name = "TR="; + if (!strncmp(var_name, input, strlen(var_name))) + { + float tr = atof(input+strlen(var_name)); + send_answer_chunk(channel_mask, "+cs:", 0); + uint8_to_hex(buf, sa); + send_answer_chunk(channel_mask, buf, 0); + if ((tr >= -60) && (tr <= 100)) + { + mlx->tr_ = tr; + send_answer_chunk(channel_mask, ":TR=OK [hub-register]", 1); + } else + { + send_answer_chunk(channel_mask, ":TR=FAIL; outbound", 1); + } + return; + } + + var_name = "RR="; + if (!strncmp(var_name, input, strlen(var_name))) + { + int16_t rr = atoi(input+strlen(var_name)); + send_answer_chunk(channel_mask, "+cs:", 0); + uint8_to_hex(buf, sa); + send_answer_chunk(channel_mask, buf, 0); + if ((rr >= 0) && (rr <= 15)) + { + int ret = MLX90621_SetRefreshRate(rr); + if (ret == 0) + { + send_answer_chunk(channel_mask, ":RR=OK [mlx-register]", 1); + } else + { + send_answer_chunk(channel_mask, ":RR=FAIL; communication fail", 1); + } + } else + { + send_answer_chunk(channel_mask, ":RR=FAIL; outbound", 1); + } + return; + } + + var_name = "RES="; + if (!strncmp(var_name, input, strlen(var_name))) + { + int16_t res = atoi(input+strlen(var_name)); + send_answer_chunk(channel_mask, "+cs:", 0); + uint8_to_hex(buf, sa); + send_answer_chunk(channel_mask, buf, 0); + if ((res >= 0) && (res <= 3)) + { + int ret = MLX90621_SetResolution(res); + if (ret == 0) + { + send_answer_chunk(channel_mask, ":RES=OK [mlx-register]", 1); + } else + { + send_answer_chunk(channel_mask, ":RES=FAIL; communication fail", 1); + } + } else + { + send_answer_chunk(channel_mask, ":RES=FAIL; outbound", 1); + } + return; + } + + var_name = "ROWS="; + if (!strncmp(var_name, input, strlen(var_name))) + { + int16_t rows = atoi(input+strlen(var_name)); + send_answer_chunk(channel_mask, "+cs:", 0); + uint8_to_hex(buf, sa); + send_answer_chunk(channel_mask, buf, 0); + if ((rows >= 1) && (rows <= 4)) + { + mlx->rows_ = rows; + send_answer_chunk(channel_mask, ":ROW=OK [hub-register]", 1); + } else + { + send_answer_chunk(channel_mask, ":ROW=FAIL; outbound", 1); + } + return; + } + + var_name = "COLUMNS="; + if (!strncmp(var_name, input, strlen(var_name))) + { + int16_t columns = atoi(input+strlen(var_name)); + send_answer_chunk(channel_mask, "+cs:", 0); + uint8_to_hex(buf, sa); + send_answer_chunk(channel_mask, buf, 0); + if ((columns >= 1) && (columns <= 16)) + { + mlx->columns_ = columns; + send_answer_chunk(channel_mask, ":COLUMNS=OK [hub-register]", 1); + } else + { + send_answer_chunk(channel_mask, ":COLUMNS=FAIL; outbound", 1); + } + return; + } + + var_name = "START_ROW="; + if (!strncmp(var_name, input, strlen(var_name))) + { + int16_t start_row = atoi(input+strlen(var_name)); + send_answer_chunk(channel_mask, "+cs:", 0); + uint8_to_hex(buf, sa); + send_answer_chunk(channel_mask, buf, 0); + if ((start_row >= 1) && (start_row <= 4)) + { + mlx->start_row_ = start_row; + uint8_t max_rows = 4 - start_row + 1; + if (mlx->rows_ > max_rows) mlx->rows_ = max_rows; + send_answer_chunk(channel_mask, ":START_ROW=OK [hub-register]", 1); + } else + { + send_answer_chunk(channel_mask, ":START_ROW=FAIL; outbound", 1); + } + return; + } + + var_name = "START_COLUMN="; + if (!strncmp(var_name, input, strlen(var_name))) + { + int16_t start_column = atoi(input+strlen(var_name)); + send_answer_chunk(channel_mask, "+cs:", 0); + uint8_to_hex(buf, sa); + send_answer_chunk(channel_mask, buf, 0); + if ((start_column >= 1) && (start_column <= 16)) + { + mlx->start_column_ = start_column; + uint8_t max_columns = 16 - start_column + 1; + if (mlx->columns_ > max_columns) mlx->columns_ = max_columns; + send_answer_chunk(channel_mask, ":START_COLUMN=OK [hub-register]", 1); + } else + { + send_answer_chunk(channel_mask, ":START_COLUMN=FAIL; outbound", 1); + } + return; + } + // finally we have a catch all to inform the user that they asked something unknown. send_answer_chunk(channel_mask, "+cs:", 0); diff --git a/i2c-stick-arduino/mlx90621_cmd.h b/i2c-stick-arduino/mlx90621_cmd.h index e248301..7acefb3 100644 --- a/i2c-stick-arduino/mlx90621_cmd.h +++ b/i2c-stick-arduino/mlx90621_cmd.h @@ -10,6 +10,8 @@ extern "C" { #endif +#define MLX90621_LSB_C 32 + struct MLX90621_t { uint8_t slave_address_; @@ -21,6 +23,11 @@ struct MLX90621_t paramsMLX90621 mlx90621_; float to_[64]; float ta_; + + uint8_t rows_; + uint8_t columns_; + uint8_t start_row_; + uint8_t start_column_; }; From 7da793b0b1a79ae3e90e3920fc39870a2cfbecff Mon Sep 17 00:00:00 2001 From: karelv Date: Thu, 2 Nov 2023 14:40:12 -0700 Subject: [PATCH 040/112] add doc in python module + add 90621:sn/mw/mr commands --- i2c-stick-arduino/i2c_stick.h | 1 + i2c-stick-arduino/mlx90614_cmd.h | 1 + i2c-stick-arduino/mlx90621_cmd.cpp | 134 ++++++++++++----------------- 3 files changed, 55 insertions(+), 81 deletions(-) diff --git a/i2c-stick-arduino/i2c_stick.h b/i2c-stick-arduino/i2c_stick.h index 401c2ed..3a9d26a 100644 --- a/i2c-stick-arduino/i2c_stick.h +++ b/i2c-stick-arduino/i2c_stick.h @@ -74,6 +74,7 @@ void send_broadcast_message(const char *msg); void send_answer_chunk(uint8_t channel_mask, const char *answer, uint8_t terminate); void send_answer_chunk_binary(uint8_t channel_mask, const char *blob, uint16_t length, uint8_t terminate); + int16_t i2c_stick_register_driver(uint8_t sa, uint8_t drv); #ifdef __cplusplus diff --git a/i2c-stick-arduino/mlx90614_cmd.h b/i2c-stick-arduino/mlx90614_cmd.h index 8f18342..b9afa77 100644 --- a/i2c-stick-arduino/mlx90614_cmd.h +++ b/i2c-stick-arduino/mlx90614_cmd.h @@ -29,6 +29,7 @@ void cmd_90614_is(uint8_t sa, uint8_t *is_ok, char const **error_message); void cmd_90614_tear_down(uint8_t sa); + #ifdef __cplusplus } #endif diff --git a/i2c-stick-arduino/mlx90621_cmd.cpp b/i2c-stick-arduino/mlx90621_cmd.cpp index 5103b3d..10d779d 100644 --- a/i2c-stick-arduino/mlx90621_cmd.cpp +++ b/i2c-stick-arduino/mlx90621_cmd.cpp @@ -17,13 +17,14 @@ extern "C" { #endif #ifndef MAX_MLX90621_SLAVES -#define MAX_MLX90621_SLAVES 8 +#define MAX_MLX90621_SLAVES 1 #endif // MAX_MLX90621_SLAVES #define MLX90621_ERROR_BUFFER_TOO_SMALL "Buffer too small" #define MLX90621_ERROR_COMMUNICATION "Communication error" #define MLX90621_ERROR_NO_FREE_HANDLE "No free handle; pls recompile firmware with higher 'MAX_MLX90621_SLAVES'" #define MLX90621_ERROR_OUT_OF_RANGE "Out of range" +#define MLX90621_ERROR_NOT_IMPLEMENTED "Function not implemented" static MLX90621_t *g_mlx90621_list[MAX_MLX90621_SLAVES]; @@ -115,23 +116,23 @@ check_90621_calibration_ranges(paramsMLX90621 *mlx90621) { // those ranges are experimental; one might require to tweak those... - // Serial.printf("mlx90621->vTh25: %d\n", mlx90621->vTh25); - // Serial.printf("mlx90621->kT1: %f\n", mlx90621->kT1); - // Serial.printf("mlx90621->kT2: %f\n", mlx90621->kT2); - // Serial.printf("mlx90621->tgc: %f\n", mlx90621->tgc); - // Serial.printf("mlx90621->KsTa: %f\n", mlx90621->KsTa); - // Serial.printf("mlx90621->ksTo: %f\n", mlx90621->ksTo); - // for (int i=0; i<64; i++) - // { - // Serial.printf("mlx90621->alpha[%d]: %fe-6\n", i, (mlx90621->alpha[i] * 1000000.0)); - // } +// Serial.printf("mlx90621->vTh25: %d\n", mlx90621->vTh25); +// Serial.printf("mlx90621->kT1: %f\n", mlx90621->kT1); +// Serial.printf("mlx90621->kT2: %f\n", mlx90621->kT2); +// Serial.printf("mlx90621->tgc: %f\n", mlx90621->tgc); +// Serial.printf("mlx90621->KsTa: %f\n", mlx90621->KsTa); +// Serial.printf("mlx90621->ksTo: %f\n", mlx90621->ksTo); +// for (int i=0; i<64; i++) +// { +// Serial.printf("mlx90621->alpha[%d]: %fe-6\n", i, (mlx90621->alpha[i] * 1000000.0)); +// } if ((mlx90621->vTh25 < 20000) || (mlx90621->vTh25 > 30000)) { return 1; } - if ((mlx90621->kT1 < 70.0) || + if ((mlx90621->kT1 < 7.0) || (mlx90621->kT1 > 100.0)) { return 1; @@ -395,12 +396,7 @@ cmd_90621_nd(uint8_t sa, uint8_t *nd, char const **error_message) } *nd = 1; // not implemented, but there is 'always' new data... - - // todo: - // - // read the status from the sensor and check if new data is available (ND=New Data). - // - } +} void @@ -426,15 +422,21 @@ cmd_90621_sn(uint8_t sa, uint16_t *sn_list, uint16_t *sn_count, char const **err } *sn_count = 4; - sn_list[0] = 0; - sn_list[1] = 0; - sn_list[2] = 0; - sn_list[3] = 0; - - // todo: // // read the serial number from the sensor. // + uint8_t data[8]; + int result = MLX90621_I2CReadEEPROM(0x50, 0xF8, 8, data); + if (result != 0) + { + *error_message = MLX90621_ERROR_COMMUNICATION; + return; + } + + for (uint8_t i=0; i<4; i++) + { + sn_list[i] = (uint16_t)(data[i*2]) + ((uint16_t)(data[i*2+1]) << 8); + } } @@ -508,14 +510,6 @@ cmd_90621_cs(uint8_t sa, uint8_t channel_mask, const char *input) itoa(mlx->start_column_, buf, 10); send_answer_chunk(channel_mask, buf, 1); - // todo: - // - // Send the answer back in the format - // "cs::=" - // - - - // todo: // // Send the configuration of the MV header, unit and resolution back to the terminal(not to sensor!) // @@ -752,21 +746,15 @@ cmd_90621_mr(uint8_t sa, uint16_t *mem_data, uint16_t mem_start_address, uint16_ *bit_per_address = 16; *address_increments = 1; - if ((mem_start_address + mem_count) > 0x00FF) - { - *bit_per_address = 0; - *address_increments = 0; - *error_message = MLX90621_ERROR_OUT_OF_RANGE; - return; - } + bool is_out_of_range = true; - for (uint16_t i=0; i 128) mem_count = 128 - mem_start_address; + int32_t result = MLX90621_I2CReadEEPROM(0x50, mem_start_address*2, mem_count*2, (uint8_t *)mem_data); + if (result != 0) { *bit_per_address = 0; *address_increments = 0; @@ -774,29 +762,23 @@ cmd_90621_mr(uint8_t sa, uint16_t *mem_data, uint16_t mem_start_address, uint16_ return; } } -} - -void -cmd_90621_mw(uint8_t sa, uint16_t *mem_data, uint16_t mem_start_address, uint16_t mem_count, uint8_t *bit_per_address, uint8_t *address_increments, char const **error_message) -{ - MLX90621_t *mlx = cmd_90621_get_handle(sa); - if (mlx == NULL) - { - *bit_per_address = 0; - *address_increments = 0; - *error_message = MLX90621_ERROR_NO_FREE_HANDLE; - return; - } - if (mlx->slave_address_ & 0x80) + if ((0x4000 <= mem_start_address) && (mem_start_address < (0x4000+256))) // RAM - raw values! { - cmd_90621_init(sa); + is_out_of_range = false; + mem_start_address -= 0x4000; + if (mem_start_address + mem_count > 256) mem_count = 256 - mem_start_address; + int result = MLX90621_I2CRead(mlx->slave_address_, 0x02, mem_start_address, 1, mem_count, mem_data); + if (result != 0) + { + *bit_per_address = 0; + *address_increments = 0; + *error_message = MLX90621_ERROR_COMMUNICATION; + return; + } } - *bit_per_address = 16; - *address_increments = 1; - - if ((mem_start_address + mem_count) > 0x00FF) + if (is_out_of_range) { *bit_per_address = 0; *address_increments = 0; @@ -804,25 +786,15 @@ cmd_90621_mw(uint8_t sa, uint16_t *mem_data, uint16_t mem_start_address, uint16_ return; } - for (uint16_t i=0; i Date: Fri, 3 Nov 2023 11:31:06 -0700 Subject: [PATCH 041/112] update CH command format --- web-interface/interface.js | 21 +- web-interface/theme/package-lock.json | 5214 +++++++++++-------------- web-interface/theme/package.json | 8 +- 3 files changed, 2258 insertions(+), 2985 deletions(-) diff --git a/web-interface/interface.js b/web-interface/interface.js index ee187c8..5b52b42 100644 --- a/web-interface/interface.js +++ b/web-interface/interface.js @@ -813,16 +813,31 @@ $(document).ready(function () { if (line.startsWith ("ch:")) { // index slave let tmp = line.split(":"); - // ch:FORMAT=DEC(0) - // ch:I2C_FREQ=400kHz(1) + // old format: + // ch:FORMAT=DEC(0) + // ch:I2C_FREQ=400kHz(1) + // new format as of V1.4 + // FORMAT=0(DEC) + // I2C_FREQ=2(1MHz) let key_value = tmp[1].split('='); if (key_value[0] == 'I2C_FREQ') { + let value_list = ["F100k", "F400k", "F1M", "F50k", "F20k", "F10k"]; + + // try the old format let index = Number(key_value[1].split(/[\(\)]/)[1]); - let value = ["F100k", "F400k", "F1M", "F50k", "F20k", "F10k"][index]; + let value = value_list[index]; if (value !== undefined) { $('select.combo_i2c_freq').val(value); + } else + { // give the new format a shot + let index = Number(key_value[1].split(/[\(\)]/)[0]); + let value = value_list[index]; + if (value !== undefined) + { + $('select.combo_i2c_freq').val(value); + } } } } diff --git a/web-interface/theme/package-lock.json b/web-interface/theme/package-lock.json index 4344ae9..ca5c334 100644 --- a/web-interface/theme/package-lock.json +++ b/web-interface/theme/package-lock.json @@ -1,303 +1,391 @@ { "name": "melexis-i2c-stick-interface", "version": "1.0.0", - "lockfileVersion": 2, + "lockfileVersion": 1, "requires": true, - "packages": { - "": { - "name": "melexis-i2c-stick-interface", - "version": "1.0.0", - "license": "ISC", - "devDependencies": { - "bulma": "^0.9.4", - "node-sass": "^8.0.0" - } - }, - "node_modules/@babel/code-frame": { + "dependencies": { + "@babel/code-frame": { "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz", "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==", - "dev": true, - "dependencies": { + "requires": { "@babel/highlight": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" } }, - "node_modules/@babel/helper-validator-identifier": { + "@babel/helper-validator-identifier": { "version": "7.19.1", "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz", - "integrity": "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } + "integrity": "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==" }, - "node_modules/@babel/highlight": { + "@babel/highlight": { "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", - "dev": true, - "dependencies": { + "requires": { "@babel/helper-validator-identifier": "^7.18.6", "chalk": "^2.0.0", "js-tokens": "^4.0.0" }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/highlight/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==" + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "requires": { + "has-flag": "^3.0.0" + } + } } }, - "node_modules/@babel/highlight/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } + "@gar/promisify": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz", + "integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==" }, - "node_modules/@babel/highlight/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "dependencies": { - "color-name": "1.1.3" + "@jridgewell/gen-mapping": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", + "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", + "requires": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" } }, - "node_modules/@babel/highlight/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true + "@jridgewell/resolve-uri": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", + "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==" }, - "node_modules/@babel/highlight/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" + "@jridgewell/set-array": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", + "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==" + }, + "@jridgewell/source-map": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.5.tgz", + "integrity": "sha512-UTYAUj/wviwdsMfzoSJspJxbkH5o1snzwX0//0ENX1u/55kkZZkcTZP6u9bwKGkv+dkk9at4m1Cpt0uY80kcpQ==", + "requires": { + "@jridgewell/gen-mapping": "^0.3.0", + "@jridgewell/trace-mapping": "^0.3.9" } }, - "node_modules/@gar/promisify": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz", - "integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==", - "dev": true + "@jridgewell/sourcemap-codec": { + "version": "1.4.15", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==" }, - "node_modules/@npmcli/fs": { + "@jridgewell/trace-mapping": { + "version": "0.3.20", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.20.tgz", + "integrity": "sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q==", + "requires": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "@npmcli/fs": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-2.1.2.tgz", "integrity": "sha512-yOJKRvohFOaLqipNtwYB9WugyZKhC/DZC4VYPmpaCzDBrA8YpK3qHZ8/HGscMnE4GqbkLNuVcCnxkeQEdGt6LQ==", - "dev": true, - "dependencies": { + "requires": { "@gar/promisify": "^1.1.3", "semver": "^7.3.5" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, - "node_modules/@npmcli/move-file": { + "@npmcli/move-file": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-2.0.1.tgz", "integrity": "sha512-mJd2Z5TjYWq/ttPLLGqArdtnC74J6bOzg4rMDnN+p1xTacZ2yPRCk2y0oSWQtygLR9YVQXgOcONrwtnk3JupxQ==", - "deprecated": "This functionality has been moved to @npmcli/fs", - "dev": true, - "dependencies": { + "requires": { "mkdirp": "^1.0.4", "rimraf": "^3.0.2" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, - "node_modules/@tootallnate/once": { + "@tootallnate/once": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", - "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", - "dev": true, - "engines": { - "node": ">= 10" - } + "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==" + }, + "@trysound/sax": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz", + "integrity": "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==" }, - "node_modules/@types/minimist": { + "@types/minimist": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.2.tgz", - "integrity": "sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==", - "dev": true + "integrity": "sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==" }, - "node_modules/@types/normalize-package-data": { + "@types/normalize-package-data": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz", - "integrity": "sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==", - "dev": true + "integrity": "sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==" }, - "node_modules/abbrev": { + "abbrev": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", - "dev": true + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" + }, + "acorn": { + "version": "8.11.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.2.tgz", + "integrity": "sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==" }, - "node_modules/agent-base": { + "agent-base": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "dev": true, - "dependencies": { + "requires": { "debug": "4" - }, - "engines": { - "node": ">= 6.0.0" } }, - "node_modules/agentkeepalive": { + "agentkeepalive": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.2.1.tgz", "integrity": "sha512-Zn4cw2NEqd+9fiSVWMscnjyQ1a8Yfoc5oBajLeo5w+YBHgDUcEBY2hS4YpTz6iN5f/2zQiktcuM6tS8x1p9dpA==", - "dev": true, - "dependencies": { + "requires": { "debug": "^4.1.0", "depd": "^1.1.2", "humanize-ms": "^1.2.1" - }, - "engines": { - "node": ">= 8.0.0" } }, - "node_modules/aggregate-error": { + "aggregate-error": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", - "dev": true, - "dependencies": { + "requires": { "clean-stack": "^2.0.0", "indent-string": "^4.0.0" - }, - "engines": { - "node": ">=8" } }, - "node_modules/ansi-regex": { + "alphanum-sort": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/alphanum-sort/-/alphanum-sort-1.0.2.tgz", + "integrity": "sha512-0FcBfdcmaumGPQ0qPn7Q5qTgz/ooXgIyp1rf8ik5bGX8mpE2YHjC0P/eyQvxu1GURYQgq9ozf2mteQ5ZD9YiyQ==" + }, + "ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "engines": { - "node": ">=8" - } + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" }, - "node_modules/ansi-styles": { + "ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { + "requires": { "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/aproba": { + "aproba": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", - "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==", - "dev": true + "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==" }, - "node_modules/are-we-there-yet": { + "are-we-there-yet": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-3.0.1.tgz", "integrity": "sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg==", - "dev": true, - "dependencies": { + "requires": { "delegates": "^1.0.0", "readable-stream": "^3.6.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, - "node_modules/arrify": { + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "arrify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", - "integrity": "sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } + "integrity": "sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==" }, - "node_modules/async-foreach": { + "async-foreach": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/async-foreach/-/async-foreach-0.1.3.tgz", - "integrity": "sha512-VUeSMD8nEGBWaZK4lizI1sf3yEC7pnAQ/mrI7pC2fBz2s/tq5jWWEngTwaf0Gruu/OoXRGLGg1XFqpYBiGTYJA==", - "dev": true, - "engines": { - "node": "*" + "integrity": "sha512-VUeSMD8nEGBWaZK4lizI1sf3yEC7pnAQ/mrI7pC2fBz2s/tq5jWWEngTwaf0Gruu/OoXRGLGg1XFqpYBiGTYJA==" + }, + "autoprefixer": { + "version": "6.7.7", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-6.7.7.tgz", + "integrity": "sha512-WKExI/eSGgGAkWAO+wMVdFObZV7hQen54UpD1kCCTN3tvlL3W1jL4+lPP/M7MwoP7Q4RHzKtO3JQ4HxYEcd+xQ==", + "requires": { + "browserslist": "^1.7.6", + "caniuse-db": "^1.0.30000634", + "normalize-range": "^0.1.2", + "num2fraction": "^1.2.2", + "postcss": "^5.2.16", + "postcss-value-parser": "^3.2.3" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==" + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==" + }, + "browserslist": { + "version": "1.7.7", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-1.7.7.tgz", + "integrity": "sha512-qHJblDE2bXVRYzuDetv/wAeHOJyO97+9wxC1cdCtyzgNuSozOyRCiiLaCR1f71AN66lQdVVBipWm63V+a7bPOw==", + "requires": { + "caniuse-db": "^1.0.30000639", + "electron-to-chromium": "^1.2.7" + } + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==", + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + }, + "dependencies": { + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==" + } + } + }, + "has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha512-DyYHfIYwAJmjAjSSPKANxI8bFY9YtFrgkAfinBojQ8YJTOuOuav64tMUJv584SES4xl74PmuaevIyaLESHdTAA==" + }, + "postcss": { + "version": "5.2.18", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", + "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", + "requires": { + "chalk": "^1.1.3", + "js-base64": "^2.1.9", + "source-map": "^0.5.6", + "supports-color": "^3.2.3" + } + }, + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==" + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==" + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==", + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "supports-color": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha512-Jds2VIYDrlp5ui7t8abHN2bjAu4LV/q4N2KivFPpGH0lrka0BMq/33AmECUXlKPcHigkNaqfXRENFju+rlcy+A==", + "requires": { + "has-flag": "^1.0.0" + } + } } }, - "node_modules/balanced-match": { + "balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, - "node_modules/brace-expansion": { + "boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==" + }, + "brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { + "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, - "node_modules/bulma": { + "browserslist": { + "version": "4.22.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.1.tgz", + "integrity": "sha512-FEVc202+2iuClEhZhrWy6ZiAcRLvNMyYcxZ8raemul1DYVOVdFsbqckWLdsixQZCpJlwe77Z3UTalE7jsjnKfQ==", + "requires": { + "caniuse-lite": "^1.0.30001541", + "electron-to-chromium": "^1.4.535", + "node-releases": "^2.0.13", + "update-browserslist-db": "^1.0.13" + } + }, + "buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" + }, + "bulma": { "version": "0.9.4", "resolved": "https://registry.npmjs.org/bulma/-/bulma-0.9.4.tgz", - "integrity": "sha512-86FlT5+1GrsgKbPLRRY7cGDg8fsJiP/jzTqXXVqiUZZ2aZT8uemEOHlU1CDU+TxklPEZ11HZNNWclRBBecP4CQ==", - "dev": true + "integrity": "sha512-86FlT5+1GrsgKbPLRRY7cGDg8fsJiP/jzTqXXVqiUZZ2aZT8uemEOHlU1CDU+TxklPEZ11HZNNWclRBBecP4CQ==" }, - "node_modules/cacache": { + "cacache": { "version": "16.1.3", "resolved": "https://registry.npmjs.org/cacache/-/cacache-16.1.3.tgz", "integrity": "sha512-/+Emcj9DAXxX4cwlLmRI9c166RuL3w30zp4R7Joiv2cQTtTtA+jeuCAjH3ZlGnYS3tKENSrKhAzVVP9GVyzeYQ==", - "dev": true, - "dependencies": { + "requires": { "@npmcli/fs": "^2.1.0", "@npmcli/move-file": "^2.0.0", "chownr": "^2.0.0", @@ -317,350 +405,925 @@ "tar": "^6.1.11", "unique-filename": "^2.0.0" }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/cacache/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/cacache/node_modules/glob": { - "version": "8.0.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-8.0.3.tgz", - "integrity": "sha512-ull455NHSHI/Y1FqGaaYFaLGkNMMJbavMrEGFXG/PGrg6y7sutWHUHrz6gy6WEBH6akM1M414dWKCNs+IhKdiQ==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^5.0.1", - "once": "^1.3.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/cacache/node_modules/minimatch": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.0.tgz", - "integrity": "sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==", - "dev": true, "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=10" + "brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "requires": { + "balanced-match": "^1.0.0" + } + }, + "glob": { + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.0.3.tgz", + "integrity": "sha512-ull455NHSHI/Y1FqGaaYFaLGkNMMJbavMrEGFXG/PGrg6y7sutWHUHrz6gy6WEBH6akM1M414dWKCNs+IhKdiQ==", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + } + }, + "minimatch": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.0.tgz", + "integrity": "sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==", + "requires": { + "brace-expansion": "^2.0.1" + } + } } }, - "node_modules/camelcase": { + "camelcase": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true, - "engines": { - "node": ">=6" - } + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==" }, - "node_modules/camelcase-keys": { + "camelcase-keys": { "version": "6.2.2", "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-6.2.2.tgz", "integrity": "sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==", - "dev": true, - "dependencies": { + "requires": { "camelcase": "^5.3.1", "map-obj": "^4.0.0", "quick-lru": "^4.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/chalk": { + "caniuse-api": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-3.0.0.tgz", + "integrity": "sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==", + "requires": { + "browserslist": "^4.0.0", + "caniuse-lite": "^1.0.0", + "lodash.memoize": "^4.1.2", + "lodash.uniq": "^4.5.0" + } + }, + "caniuse-db": { + "version": "1.0.30001559", + "resolved": "https://registry.npmjs.org/caniuse-db/-/caniuse-db-1.0.30001559.tgz", + "integrity": "sha512-v0gHDJ0eR+mhzYeQK9e488H2FPOYJvMo7uSDzZMj67wKGI9oGMu4ARAVtqqqYTHqvWUMa7NtJfzkiBD8tTs4Jg==" + }, + "caniuse-lite": { + "version": "1.0.30001559", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001559.tgz", + "integrity": "sha512-cPiMKZgqgkg5LY3/ntGeLFUpi6tzddBNS58A4tnTgQw1zON7u2sZMU7SzOeVH4tj20++9ggL+V6FDOFMTaFFYA==" + }, + "chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { + "requires": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/chownr": { + "chownr": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", - "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", - "dev": true, - "engines": { - "node": ">=10" + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==" + }, + "clap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/clap/-/clap-1.2.3.tgz", + "integrity": "sha512-4CoL/A3hf90V3VIEjeuhSvlGFEHKzOz+Wfc2IVZc+FaUgU0ZQafJTP49fvnULipOPcAfqhyI2duwQyns6xqjYA==", + "requires": { + "chalk": "^1.1.3" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==" + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==" + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==", + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==", + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==" + } } }, - "node_modules/clean-stack": { + "clean-stack": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", - "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", - "dev": true, - "engines": { - "node": ">=6" - } + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==" }, - "node_modules/cliui": { + "cliui": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "dev": true, - "dependencies": { + "requires": { "string-width": "^4.2.0", "strip-ansi": "^6.0.1", "wrap-ansi": "^7.0.0" + } + }, + "clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==" + }, + "coa": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/coa/-/coa-1.0.4.tgz", + "integrity": "sha512-KAGck/eNAmCL0dcT3BiuYwLbExK6lduR8DxM3C1TyDzaXhZHyZ8ooX5I5+na2e3dPFuibfxrGdorr0/Lr7RYCQ==", + "requires": { + "q": "^1.1.2" + } + }, + "color": { + "version": "0.11.4", + "resolved": "https://registry.npmjs.org/color/-/color-0.11.4.tgz", + "integrity": "sha512-Ajpjd8asqZ6EdxQeqGzU5WBhhTfJ/0cA4Wlbre7e5vXfmDSmda7Ov6jeKoru+b0vHcb1CqvuroTHp5zIWzhVMA==", + "requires": { + "clone": "^1.0.2", + "color-convert": "^1.3.0", + "color-string": "^0.3.0" }, - "engines": { - "node": ">=12" + "dependencies": { + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" + } } }, - "node_modules/color-convert": { + "color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { + "requires": { "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" } }, - "node_modules/color-name": { + "color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "color-string": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-0.3.0.tgz", + "integrity": "sha512-sz29j1bmSDfoAxKIEU6zwoIZXN6BrFbAMIhfYCNyiZXBDuU/aiHlN84lp/xDzL2ubyFhLDobHIlU1X70XRrMDA==", + "requires": { + "color-name": "^1.0.0" + } }, - "node_modules/color-support": { + "color-support": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", - "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", - "dev": true, - "bin": { - "color-support": "bin.js" + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==" + }, + "colord": { + "version": "2.9.3", + "resolved": "https://registry.npmjs.org/colord/-/colord-2.9.3.tgz", + "integrity": "sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==" + }, + "colormin": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/colormin/-/colormin-1.1.2.tgz", + "integrity": "sha512-XSEQUUQUR/lXqGyddiNH3XYFUPYlYr1vXy9rTFMsSOw+J7Q6EQkdlQIrTlYn4TccpsOaUE1PYQNjBn20gwCdgQ==", + "requires": { + "color": "^0.11.0", + "css-color-names": "0.0.4", + "has": "^1.0.1" } }, - "node_modules/concat-map": { + "colors": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.1.2.tgz", + "integrity": "sha512-ENwblkFQpqqia6b++zLD/KUWafYlVY/UNnAp7oz7LY7E924wmpye416wBOmvv/HMWzl8gL1kJlfvId/1Dg176w==" + }, + "commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==" + }, + "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" }, - "node_modules/console-control-strings": { + "console-control-strings": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", - "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==", - "dev": true + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==" }, - "node_modules/core-util-is": { + "core-util-is": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", - "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", - "dev": true + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" }, - "node_modules/cross-spawn": { + "cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "dependencies": { + "requires": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" + } + }, + "css-color-names": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/css-color-names/-/css-color-names-0.0.4.tgz", + "integrity": "sha512-zj5D7X1U2h2zsXOAM8EyUREBnnts6H+Jm+d1M2DbiQQcUtnqgQsMrdo8JW9R80YFUmIdBZeMu5wvYM7hcgWP/Q==" + }, + "css-declaration-sorter": { + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-6.4.1.tgz", + "integrity": "sha512-rtdthzxKuyq6IzqX6jEcIzQF/YqccluefyCYheovBOLhFT/drQA9zj/UbRAa9J7C0o6EG6u3E6g+vKkay7/k3g==" + }, + "css-select": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz", + "integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==", + "requires": { + "boolbase": "^1.0.0", + "css-what": "^6.1.0", + "domhandler": "^5.0.2", + "domutils": "^3.0.1", + "nth-check": "^2.0.1" + } + }, + "css-tree": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.3.1.tgz", + "integrity": "sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==", + "requires": { + "mdn-data": "2.0.30", + "source-map-js": "^1.0.1" + } + }, + "css-what": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", + "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==" + }, + "cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==" + }, + "cssnano": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-6.0.1.tgz", + "integrity": "sha512-fVO1JdJ0LSdIGJq68eIxOqFpIJrZqXUsBt8fkrBcztCQqAjQD51OhZp7tc0ImcbwXD4k7ny84QTV90nZhmqbkg==", + "requires": { + "cssnano-preset-default": "^6.0.1", + "lilconfig": "^2.1.0" + } + }, + "cssnano-cli": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/cssnano-cli/-/cssnano-cli-1.0.5.tgz", + "integrity": "sha512-da+Cv+Sl+1ip2DQi24oirBQS71oQfT6tUDg7ViAjAv4BcU2HaMxwpvQamAshjWL1C7LCQGDCkn2KnzUKRrDZwQ==", + "requires": { + "cssnano": "^3.0.0", + "minimist": "^1.2.0", + "read-file-stdin": "^0.2.0", + "write-file-stdout": "0.0.2" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==" + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==" + }, + "browserslist": { + "version": "1.7.7", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-1.7.7.tgz", + "integrity": "sha512-qHJblDE2bXVRYzuDetv/wAeHOJyO97+9wxC1cdCtyzgNuSozOyRCiiLaCR1f71AN66lQdVVBipWm63V+a7bPOw==", + "requires": { + "caniuse-db": "^1.0.30000639", + "electron-to-chromium": "^1.2.7" + } + }, + "caniuse-api": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-1.6.1.tgz", + "integrity": "sha512-SBTl70K0PkDUIebbkXrxWqZlHNs0wRgRD6QZ8guctShjbh63gEPfF+Wj0Yw+75f5Y8tSzqAI/NcisYv/cCah2Q==", + "requires": { + "browserslist": "^1.3.6", + "caniuse-db": "^1.0.30000529", + "lodash.memoize": "^4.1.2", + "lodash.uniq": "^4.5.0" + } + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==", + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + }, + "dependencies": { + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==" + } + } + }, + "cssnano": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-3.10.0.tgz", + "integrity": "sha512-0o0IMQE0Ezo4b41Yrm8U6Rp9/Ag81vNXY1gZMnT1XhO4DpjEf2utKERqWJbOoz3g1Wdc1d3QSta/cIuJ1wSTEg==", + "requires": { + "autoprefixer": "^6.3.1", + "decamelize": "^1.1.2", + "defined": "^1.0.0", + "has": "^1.0.1", + "object-assign": "^4.0.1", + "postcss": "^5.0.14", + "postcss-calc": "^5.2.0", + "postcss-colormin": "^2.1.8", + "postcss-convert-values": "^2.3.4", + "postcss-discard-comments": "^2.0.4", + "postcss-discard-duplicates": "^2.0.1", + "postcss-discard-empty": "^2.0.1", + "postcss-discard-overridden": "^0.1.1", + "postcss-discard-unused": "^2.2.1", + "postcss-filter-plugins": "^2.0.0", + "postcss-merge-idents": "^2.1.5", + "postcss-merge-longhand": "^2.0.1", + "postcss-merge-rules": "^2.0.3", + "postcss-minify-font-values": "^1.0.2", + "postcss-minify-gradients": "^1.0.1", + "postcss-minify-params": "^1.0.4", + "postcss-minify-selectors": "^2.0.4", + "postcss-normalize-charset": "^1.1.0", + "postcss-normalize-url": "^3.0.7", + "postcss-ordered-values": "^2.1.0", + "postcss-reduce-idents": "^2.2.2", + "postcss-reduce-initial": "^1.0.0", + "postcss-reduce-transforms": "^1.0.3", + "postcss-svgo": "^2.1.1", + "postcss-unique-selectors": "^2.0.2", + "postcss-value-parser": "^3.2.3", + "postcss-zindex": "^2.0.1" + } + }, + "csso": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/csso/-/csso-2.3.2.tgz", + "integrity": "sha512-FmCI/hmqDeHHLaIQckMhMZneS84yzUZdrWDAvJVVxOwcKE1P1LF9FGmzr1ktIQSxOw6fl3PaQsmfg+GN+VvR3w==", + "requires": { + "clap": "^1.0.9", + "source-map": "^0.5.3" + } + }, + "has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha512-DyYHfIYwAJmjAjSSPKANxI8bFY9YtFrgkAfinBojQ8YJTOuOuav64tMUJv584SES4xl74PmuaevIyaLESHdTAA==" + }, + "mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "requires": { + "minimist": "^1.2.6" + } + }, + "postcss": { + "version": "5.2.18", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", + "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", + "requires": { + "chalk": "^1.1.3", + "js-base64": "^2.1.9", + "source-map": "^0.5.6", + "supports-color": "^3.2.3" + } + }, + "postcss-calc": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-5.3.1.tgz", + "integrity": "sha512-iBcptYFq+QUh9gzP7ta2btw50o40s4uLI4UDVgd5yRAZtUDWc5APdl5yQDd2h/TyiZNbJrv0HiYhT102CMgN7Q==", + "requires": { + "postcss": "^5.0.2", + "postcss-message-helpers": "^2.0.0", + "reduce-css-calc": "^1.2.6" + } + }, + "postcss-colormin": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-2.2.2.tgz", + "integrity": "sha512-XXitQe+jNNPf+vxvQXIQ1+pvdQKWKgkx8zlJNltcMEmLma1ypDRDQwlLt+6cP26fBreihNhZxohh1rcgCH2W5w==", + "requires": { + "colormin": "^1.0.5", + "postcss": "^5.0.13", + "postcss-value-parser": "^3.2.3" + } + }, + "postcss-convert-values": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/postcss-convert-values/-/postcss-convert-values-2.6.1.tgz", + "integrity": "sha512-SE7mf25D3ORUEXpu3WUqQqy0nCbMuM5BEny+ULE/FXdS/0UMA58OdzwvzuHJRpIFlk1uojt16JhaEogtP6W2oA==", + "requires": { + "postcss": "^5.0.11", + "postcss-value-parser": "^3.1.2" + } + }, + "postcss-discard-comments": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-2.0.4.tgz", + "integrity": "sha512-yGbyBDo5FxsImE90LD8C87vgnNlweQkODMkUZlDVM/CBgLr9C5RasLGJxxh9GjVOBeG8NcCMatoqI1pXg8JNXg==", + "requires": { + "postcss": "^5.0.14" + } + }, + "postcss-discard-duplicates": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-2.1.0.tgz", + "integrity": "sha512-+lk5W1uqO8qIUTET+UETgj9GWykLC3LOldr7EehmymV0Wu36kyoHimC4cILrAAYpHQ+fr4ypKcWcVNaGzm0reA==", + "requires": { + "postcss": "^5.0.4" + } + }, + "postcss-discard-empty": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-2.1.0.tgz", + "integrity": "sha512-IBFoyrwk52dhF+5z/ZAbzq5Jy7Wq0aLUsOn69JNS+7YeuyHaNzJwBIYE0QlUH/p5d3L+OON72Fsexyb7OK/3og==", + "requires": { + "postcss": "^5.0.14" + } + }, + "postcss-discard-overridden": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-0.1.1.tgz", + "integrity": "sha512-IyKoDL8QNObOiUc6eBw8kMxBHCfxUaERYTUe2QF8k7j/xiirayDzzkmlR6lMQjrAM1p1DDRTvWrS7Aa8lp6/uA==", + "requires": { + "postcss": "^5.0.16" + } + }, + "postcss-merge-longhand": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-2.0.2.tgz", + "integrity": "sha512-ma7YvxjdLQdifnc1HFsW/AW6fVfubGyR+X4bE3FOSdBVMY9bZjKVdklHT+odknKBB7FSCfKIHC3yHK7RUAqRPg==", + "requires": { + "postcss": "^5.0.4" + } + }, + "postcss-merge-rules": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/postcss-merge-rules/-/postcss-merge-rules-2.1.2.tgz", + "integrity": "sha512-Wgg2FS6W3AYBl+5L9poL6ZUISi5YzL+sDCJfM7zNw/Q1qsyVQXXZ2cbVui6mu2cYJpt1hOKCGj1xA4mq/obz/Q==", + "requires": { + "browserslist": "^1.5.2", + "caniuse-api": "^1.5.2", + "postcss": "^5.0.4", + "postcss-selector-parser": "^2.2.2", + "vendors": "^1.0.0" + } + }, + "postcss-minify-font-values": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/postcss-minify-font-values/-/postcss-minify-font-values-1.0.5.tgz", + "integrity": "sha512-vFSPzrJhNe6/8McOLU13XIsERohBJiIFFuC1PolgajOZdRWqRgKITP/A4Z/n4GQhEmtbxmO9NDw3QLaFfE1dFQ==", + "requires": { + "object-assign": "^4.0.1", + "postcss": "^5.0.4", + "postcss-value-parser": "^3.0.2" + } + }, + "postcss-minify-gradients": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-1.0.5.tgz", + "integrity": "sha512-DZhT0OE+RbVqVyGsTIKx84rU/5cury1jmwPa19bViqYPQu499ZU831yMzzsyC8EhiZVd73+h5Z9xb/DdaBpw7Q==", + "requires": { + "postcss": "^5.0.12", + "postcss-value-parser": "^3.3.0" + } + }, + "postcss-minify-params": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/postcss-minify-params/-/postcss-minify-params-1.2.2.tgz", + "integrity": "sha512-hhJdMVgP8vasrHbkKAk+ab28vEmPYgyuDzRl31V3BEB3QOR3L5TTIVEWLDNnZZ3+fiTi9d6Ker8GM8S1h8p2Ow==", + "requires": { + "alphanum-sort": "^1.0.1", + "postcss": "^5.0.2", + "postcss-value-parser": "^3.0.2", + "uniqs": "^2.0.0" + } + }, + "postcss-minify-selectors": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/postcss-minify-selectors/-/postcss-minify-selectors-2.1.1.tgz", + "integrity": "sha512-e13vxPBSo3ZaPne43KVgM+UETkx3Bs4/Qvm6yXI9HQpQp4nyb7HZ0gKpkF+Wn2x+/dbQ+swNpCdZSbMOT7+TIA==", + "requires": { + "alphanum-sort": "^1.0.2", + "has": "^1.0.1", + "postcss": "^5.0.14", + "postcss-selector-parser": "^2.0.0" + } + }, + "postcss-normalize-charset": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-1.1.1.tgz", + "integrity": "sha512-RKgjEks83l8w4yEhztOwNZ+nLSrJ+NvPNhpS+mVDzoaiRHZQVoG7NF2TP5qjwnaN9YswUhj6m1E0S0Z+WDCgEQ==", + "requires": { + "postcss": "^5.0.5" + } + }, + "postcss-normalize-url": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/postcss-normalize-url/-/postcss-normalize-url-3.0.8.tgz", + "integrity": "sha512-WqtWG6GV2nELsQEFES0RzfL2ebVwmGl/M8VmMbshKto/UClBo+mznX8Zi4/hkThdqx7ijwv+O8HWPdpK7nH/Ig==", + "requires": { + "is-absolute-url": "^2.0.0", + "normalize-url": "^1.4.0", + "postcss": "^5.0.14", + "postcss-value-parser": "^3.2.3" + } + }, + "postcss-ordered-values": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/postcss-ordered-values/-/postcss-ordered-values-2.2.3.tgz", + "integrity": "sha512-5RB1IUZhkxDCfa5fx/ogp/A82mtq+r7USqS+7zt0e428HJ7+BHCxyeY39ClmkkUtxdOd3mk8gD6d9bjH2BECMg==", + "requires": { + "postcss": "^5.0.4", + "postcss-value-parser": "^3.0.1" + } + }, + "postcss-reduce-initial": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-1.0.1.tgz", + "integrity": "sha512-jJFrV1vWOPCQsIVitawGesRgMgunbclERQ/IRGW7r93uHrVzNQQmHQ7znsOIjJPZ4yWMzs5A8NFhp3AkPHPbDA==", + "requires": { + "postcss": "^5.0.4" + } + }, + "postcss-reduce-transforms": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/postcss-reduce-transforms/-/postcss-reduce-transforms-1.0.4.tgz", + "integrity": "sha512-lGgRqnSuAR5i5uUg1TA33r9UngfTadWxOyL2qx1KuPoCQzfmtaHjp9PuwX7yVyRxG3BWBzeFUaS5uV9eVgnEgQ==", + "requires": { + "has": "^1.0.1", + "postcss": "^5.0.8", + "postcss-value-parser": "^3.0.1" + } + }, + "postcss-selector-parser": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-2.2.3.tgz", + "integrity": "sha512-3pqyakeGhrO0BQ5+/tGTfvi5IAUAhHRayGK8WFSu06aEv2BmHoXw/Mhb+w7VY5HERIuC+QoUI7wgrCcq2hqCVA==", + "requires": { + "flatten": "^1.0.2", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + } + }, + "postcss-svgo": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-2.1.6.tgz", + "integrity": "sha512-y5AdQdgBoF4rbpdbeWAJuxE953g/ylRfVNp6mvAi61VCN/Y25Tu9p5mh3CyI42WbTRIiwR9a1GdFtmDnNPeskQ==", + "requires": { + "is-svg": "^2.0.0", + "postcss": "^5.0.14", + "postcss-value-parser": "^3.2.3", + "svgo": "^0.7.0" + } + }, + "postcss-unique-selectors": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-2.0.2.tgz", + "integrity": "sha512-WZX8r1M0+IyljoJOJleg3kYm10hxNYF9scqAT7v/xeSX1IdehutOM85SNO0gP9K+bgs86XERr7Ud5u3ch4+D8g==", + "requires": { + "alphanum-sort": "^1.0.1", + "postcss": "^5.0.4", + "uniqs": "^2.0.0" + } + }, + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==" + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==" + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==", + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "supports-color": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha512-Jds2VIYDrlp5ui7t8abHN2bjAu4LV/q4N2KivFPpGH0lrka0BMq/33AmECUXlKPcHigkNaqfXRENFju+rlcy+A==", + "requires": { + "has-flag": "^1.0.0" + } + }, + "svgo": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/svgo/-/svgo-0.7.2.tgz", + "integrity": "sha512-jT/g9FFMoe9lu2IT6HtAxTA7RR2XOrmcrmCtGnyB/+GQnV6ZjNn+KOHZbZ35yL81+1F/aB6OeEsJztzBQ2EEwA==", + "requires": { + "coa": "~1.0.1", + "colors": "~1.1.2", + "csso": "~2.3.1", + "js-yaml": "~3.7.0", + "mkdirp": "~0.5.1", + "sax": "~1.2.1", + "whet.extend": "~0.9.9" + } + } + } + }, + "cssnano-preset-default": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-6.0.1.tgz", + "integrity": "sha512-7VzyFZ5zEB1+l1nToKyrRkuaJIx0zi/1npjvZfbBwbtNTzhLtlvYraK/7/uqmX2Wb2aQtd983uuGw79jAjLSuQ==", + "requires": { + "css-declaration-sorter": "^6.3.1", + "cssnano-utils": "^4.0.0", + "postcss-calc": "^9.0.0", + "postcss-colormin": "^6.0.0", + "postcss-convert-values": "^6.0.0", + "postcss-discard-comments": "^6.0.0", + "postcss-discard-duplicates": "^6.0.0", + "postcss-discard-empty": "^6.0.0", + "postcss-discard-overridden": "^6.0.0", + "postcss-merge-longhand": "^6.0.0", + "postcss-merge-rules": "^6.0.1", + "postcss-minify-font-values": "^6.0.0", + "postcss-minify-gradients": "^6.0.0", + "postcss-minify-params": "^6.0.0", + "postcss-minify-selectors": "^6.0.0", + "postcss-normalize-charset": "^6.0.0", + "postcss-normalize-display-values": "^6.0.0", + "postcss-normalize-positions": "^6.0.0", + "postcss-normalize-repeat-style": "^6.0.0", + "postcss-normalize-string": "^6.0.0", + "postcss-normalize-timing-functions": "^6.0.0", + "postcss-normalize-unicode": "^6.0.0", + "postcss-normalize-url": "^6.0.0", + "postcss-normalize-whitespace": "^6.0.0", + "postcss-ordered-values": "^6.0.0", + "postcss-reduce-initial": "^6.0.0", + "postcss-reduce-transforms": "^6.0.0", + "postcss-svgo": "^6.0.0", + "postcss-unique-selectors": "^6.0.0" + } + }, + "cssnano-utils": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cssnano-utils/-/cssnano-utils-4.0.0.tgz", + "integrity": "sha512-Z39TLP+1E0KUcd7LGyF4qMfu8ZufI0rDzhdyAMsa/8UyNUU8wpS0fhdBxbQbv32r64ea00h4878gommRVg2BHw==" + }, + "csso": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/csso/-/csso-5.0.5.tgz", + "integrity": "sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ==", + "requires": { + "css-tree": "~2.2.0" }, - "engines": { - "node": ">= 8" + "dependencies": { + "css-tree": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.2.1.tgz", + "integrity": "sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA==", + "requires": { + "mdn-data": "2.0.28", + "source-map-js": "^1.0.1" + } + }, + "mdn-data": { + "version": "2.0.28", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.28.tgz", + "integrity": "sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==" + } } }, - "node_modules/debug": { + "debug": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, - "dependencies": { + "requires": { "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } } }, - "node_modules/decamelize": { + "decamelize": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } + "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==" }, - "node_modules/decamelize-keys": { + "decamelize-keys": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.1.tgz", "integrity": "sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==", - "dev": true, - "dependencies": { + "requires": { "decamelize": "^1.1.0", "map-obj": "^1.0.0" }, - "engines": { - "node": ">=0.10.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "dependencies": { + "map-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", + "integrity": "sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==" + } } }, - "node_modules/decamelize-keys/node_modules/map-obj": { + "defined": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", - "integrity": "sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } + "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.1.tgz", + "integrity": "sha512-hsBd2qSVCRE+5PmNdHt1uzyrFu5d3RwmFDKzyNZMFq/EwDNJF7Ee5+D5oEKF0hU6LhtoUF1macFvOe4AskQC1Q==" }, - "node_modules/delegates": { + "delegates": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==", - "dev": true + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" }, - "node_modules/depd": { + "depd": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", - "dev": true, - "engines": { - "node": ">= 0.6" + "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==" + }, + "dom-serializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", + "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", + "requires": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "entities": "^4.2.0" + } + }, + "domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==" + }, + "domhandler": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", + "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", + "requires": { + "domelementtype": "^2.3.0" } }, - "node_modules/emoji-regex": { + "domutils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz", + "integrity": "sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==", + "requires": { + "dom-serializer": "^2.0.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3" + } + }, + "electron-to-chromium": { + "version": "1.4.575", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.575.tgz", + "integrity": "sha512-kY2BGyvgAHiX899oF6xLXSIf99bAvvdPhDoJwG77nxCSyWYuRH6e9a9a3gpXBvCs6lj4dQZJkfnW2hdKWHEISg==" + }, + "emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" }, - "node_modules/encoding": { + "encoding": { "version": "0.1.13", "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", - "dev": true, "optional": true, - "dependencies": { + "requires": { "iconv-lite": "^0.6.2" } }, - "node_modules/env-paths": { + "entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==" + }, + "env-paths": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", - "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", - "dev": true, - "engines": { - "node": ">=6" - } + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==" }, - "node_modules/err-code": { + "err-code": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", - "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==", - "dev": true + "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==" }, - "node_modules/error-ex": { + "error-ex": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true, - "dependencies": { + "requires": { "is-arrayish": "^0.2.1" } }, - "node_modules/escalade": { + "escalade": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", - "dev": true, - "engines": { - "node": ">=6" - } + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==" }, - "node_modules/escape-string-regexp": { + "escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true, - "engines": { - "node": ">=0.8.0" - } + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==" }, - "node_modules/find-up": { + "esprima": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", + "integrity": "sha512-OarPfz0lFCiW4/AV2Oy1Rp9qu0iusTKqykwTspGCZtPxmF81JR4MmIebvF1F9+UOKth2ZubLQ4XGGaU+hSn99A==" + }, + "find-up": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "dependencies": { + "requires": { "locate-path": "^5.0.0", "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" } }, - "node_modules/fs-minipass": { + "flatten": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/flatten/-/flatten-1.0.3.tgz", + "integrity": "sha512-dVsPA/UwQ8+2uoFe5GHtiBMu48dWLTdsuEd7CKGlZlD78r1TTWBvDuFaFGKCo/ZfEr95Uk56vZoX86OsHkUeIg==" + }, + "fs-minipass": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", - "dev": true, - "dependencies": { + "requires": { "minipass": "^3.0.0" - }, - "engines": { - "node": ">= 8" } }, - "node_modules/fs.realpath": { + "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" }, - "node_modules/function-bind": { + "function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + }, + "gather-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/gather-stream/-/gather-stream-1.0.0.tgz", + "integrity": "sha512-NspYMi3rN3EKmMdejUXbtluDYrcRlTEBBFhWzVRZVsOx94OPxlXp0AzyPKyLiT7iaurcoTE/KcHsHP/PowNEaA==" }, - "node_modules/gauge": { + "gauge": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/gauge/-/gauge-4.0.4.tgz", "integrity": "sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==", - "dev": true, - "dependencies": { + "requires": { "aproba": "^1.0.3 || ^2.0.0", "color-support": "^1.1.3", "console-control-strings": "^1.1.0", @@ -669,394 +1332,341 @@ "string-width": "^4.2.3", "strip-ansi": "^6.0.1", "wide-align": "^1.1.5" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, - "node_modules/gaze": { + "gaze": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/gaze/-/gaze-1.1.3.tgz", "integrity": "sha512-BRdNm8hbWzFzWHERTrejLqwHDfS4GibPoq5wjTPIoJHoBtKGPg3xAFfxmM+9ztbXelxcf2hwQcaz1PtmFeue8g==", - "dev": true, - "dependencies": { + "requires": { "globule": "^1.0.0" - }, - "engines": { - "node": ">= 4.0.0" } }, - "node_modules/get-caller-file": { + "get-caller-file": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true, - "engines": { - "node": "6.* || 8.* || >= 10.*" - } + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==" }, - "node_modules/get-stdin": { + "get-stdin": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", - "integrity": "sha512-F5aQMywwJ2n85s4hJPTT9RPxGmubonuB10MNYo17/xph174n2MIR33HRguhzVag10O/npM7SPk73LMZNP+FaWw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } + "integrity": "sha512-F5aQMywwJ2n85s4hJPTT9RPxGmubonuB10MNYo17/xph174n2MIR33HRguhzVag10O/npM7SPk73LMZNP+FaWw==" }, - "node_modules/glob": { + "glob": { "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, - "dependencies": { + "requires": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.1.1", "once": "^1.3.0", "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/globule": { + "globule": { "version": "1.3.4", "resolved": "https://registry.npmjs.org/globule/-/globule-1.3.4.tgz", "integrity": "sha512-OPTIfhMBh7JbBYDpa5b+Q5ptmMWKwcNcFSR/0c6t8V4f3ZAVBEsKNY37QdVqmLRYSMhOUGYrY0QhSoEpzGr/Eg==", - "dev": true, - "dependencies": { + "requires": { "glob": "~7.1.1", "lodash": "^4.17.21", "minimatch": "~3.0.2" }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/globule/node_modules/glob": { - "version": "7.1.7", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", - "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/globule/node_modules/minimatch": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.8.tgz", - "integrity": "sha512-6FsRAQsxQ61mw+qP1ZzbL9Bc78x2p5OqNgNpnoAFLTrX8n5Kxph0CsnhmKKNXTWjXqU5L0pGPR7hYk+XWZr60Q==", - "dev": true, "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" + "glob": { + "version": "7.1.7", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", + "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "minimatch": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.8.tgz", + "integrity": "sha512-6FsRAQsxQ61mw+qP1ZzbL9Bc78x2p5OqNgNpnoAFLTrX8n5Kxph0CsnhmKKNXTWjXqU5L0pGPR7hYk+XWZr60Q==", + "requires": { + "brace-expansion": "^1.1.7" + } + } } }, - "node_modules/graceful-fs": { + "graceful-fs": { "version": "4.2.10", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", - "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", - "dev": true + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" }, - "node_modules/hard-rejection": { + "hard-rejection": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/hard-rejection/-/hard-rejection-2.1.0.tgz", - "integrity": "sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==", - "dev": true, - "engines": { - "node": ">=6" - } + "integrity": "sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==" }, - "node_modules/has": { + "has": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, - "dependencies": { + "requires": { "function-bind": "^1.1.1" + } + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha512-C8vBJ8DwUCx19vhm7urhTuUsr4/IyP6l4VzNQDv+ryHQObW3TTTp9yB68WpYgRe2bbaGuZ/se74IqFeVnMnLZg==", + "requires": { + "ansi-regex": "^2.0.0" }, - "engines": { - "node": ">= 0.4.0" + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==" + } } }, - "node_modules/has-flag": { + "has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" }, - "node_modules/has-unicode": { + "has-unicode": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", - "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==", - "dev": true + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" }, - "node_modules/hosted-git-info": { + "hosted-git-info": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==", - "dev": true, - "dependencies": { + "requires": { "lru-cache": "^6.0.0" }, - "engines": { - "node": ">=10" - } - }, - "node_modules/hosted-git-info/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "requires": { + "yallist": "^4.0.0" + } + } } }, - "node_modules/http-cache-semantics": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", - "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==", - "dev": true + "html-comment-regex": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/html-comment-regex/-/html-comment-regex-1.1.2.tgz", + "integrity": "sha512-P+M65QY2JQ5Y0G9KKdlDpo0zK+/OHptU5AaBwUfAIDJZk1MYf32Frm84EcOytfJE0t5JvkAnKlmjsXDnWzCJmQ==" + }, + "http-cache-semantics": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", + "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==" }, - "node_modules/http-proxy-agent": { + "http-proxy-agent": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", - "dev": true, - "dependencies": { + "requires": { "@tootallnate/once": "2", "agent-base": "6", "debug": "4" - }, - "engines": { - "node": ">= 6" } }, - "node_modules/https-proxy-agent": { + "https-proxy-agent": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", - "dev": true, - "dependencies": { + "requires": { "agent-base": "6", "debug": "4" - }, - "engines": { - "node": ">= 6" } }, - "node_modules/humanize-ms": { + "humanize-ms": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==", - "dev": true, - "dependencies": { + "requires": { "ms": "^2.0.0" } }, - "node_modules/iconv-lite": { + "iconv-lite": { "version": "0.6.3", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "dev": true, "optional": true, - "dependencies": { + "requires": { "safer-buffer": ">= 2.1.2 < 3.0.0" - }, - "engines": { - "node": ">=0.10.0" } }, - "node_modules/imurmurhash": { + "imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", - "dev": true, - "engines": { - "node": ">=0.8.19" - } + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==" }, - "node_modules/indent-string": { + "indent-string": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "dev": true, - "engines": { - "node": ">=8" - } + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==" }, - "node_modules/infer-owner": { + "indexes-of": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/indexes-of/-/indexes-of-1.0.1.tgz", + "integrity": "sha512-bup+4tap3Hympa+JBJUG7XuOsdNQ6fxt0MHyXMKuLBKn0OqsTfvUxkUrroEX1+B2VsSHvCjiIcZVxRtYa4nllA==" + }, + "infer-owner": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", - "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", - "dev": true + "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==" }, - "node_modules/inflight": { + "inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "dev": true, - "dependencies": { + "requires": { "once": "^1.3.0", "wrappy": "1" } }, - "node_modules/inherits": { + "inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, - "node_modules/ip": { + "ip": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz", - "integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==", - "dev": true + "integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==" }, - "node_modules/is-arrayish": { + "is-absolute-url": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-absolute-url/-/is-absolute-url-2.1.0.tgz", + "integrity": "sha512-vOx7VprsKyllwjSkLV79NIhpyLfr3jAp7VaTCMXOJHu4m0Ew1CZ2fcjASwmV1jI3BWuWHB013M48eyeldk9gYg==" + }, + "is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", - "dev": true + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==" }, - "node_modules/is-core-module": { + "is-core-module": { "version": "2.11.0", "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz", "integrity": "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==", - "dev": true, - "dependencies": { + "requires": { "has": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-fullwidth-code-point": { + "is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, - "engines": { - "node": ">=8" - } + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" }, - "node_modules/is-lambda": { + "is-lambda": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz", - "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==", - "dev": true + "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==" }, - "node_modules/is-plain-obj": { + "is-plain-obj": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", - "integrity": "sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==", - "dev": true, - "engines": { - "node": ">=0.10.0" + "integrity": "sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==" + }, + "is-svg": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-svg/-/is-svg-2.1.0.tgz", + "integrity": "sha512-Ya1giYJUkcL/94quj0+XGcmts6cETPBW1MiFz1ReJrnDJ680F52qpAEGAEGU0nq96FRGIGPx6Yo1CyPXcOoyGw==", + "requires": { + "html-comment-regex": "^1.1.0" } }, - "node_modules/isarray": { + "isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", - "dev": true + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" }, - "node_modules/isexe": { + "isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" }, - "node_modules/js-base64": { + "js-base64": { "version": "2.6.4", "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.6.4.tgz", - "integrity": "sha512-pZe//GGmwJndub7ZghVHz7vjb2LgC1m8B07Au3eYqeqv9emhESByMXxaEgkUkEqJe87oBbSniGYoQNIBklc7IQ==", - "dev": true + "integrity": "sha512-pZe//GGmwJndub7ZghVHz7vjb2LgC1m8B07Au3eYqeqv9emhESByMXxaEgkUkEqJe87oBbSniGYoQNIBklc7IQ==" }, - "node_modules/js-tokens": { + "js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + }, + "js-yaml": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.7.0.tgz", + "integrity": "sha512-eIlkGty7HGmntbV6P/ZlAsoncFLGsNoM27lkTzS+oneY/EiNhj+geqD9ezg/ip+SW6Var0BJU2JtV0vEUZpWVQ==", + "requires": { + "argparse": "^1.0.7", + "esprima": "^2.6.0" + } }, - "node_modules/json-parse-even-better-errors": { + "json-parse-even-better-errors": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "dev": true + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" }, - "node_modules/kind-of": { + "kind-of": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==" }, - "node_modules/lines-and-columns": { + "lilconfig": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", + "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==" + }, + "lines-and-columns": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", - "dev": true + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==" }, - "node_modules/locate-path": { + "locate-path": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "dependencies": { + "requires": { "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" } }, - "node_modules/lodash": { + "lodash": { "version": "4.17.21", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" }, - "node_modules/lru-cache": { + "lodash.memoize": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", + "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==" + }, + "lodash.uniq": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", + "integrity": "sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==" + }, + "lru-cache": { "version": "7.14.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.14.1.tgz", - "integrity": "sha512-ysxwsnTKdAx96aTRdhDOCQfDgbHnt8SK0KY8SEjO0wHinhWOFTESbjVCMPbU1uGXg/ch4lifqx0wfjOawU2+WA==", - "dev": true, - "engines": { - "node": ">=12" - } + "integrity": "sha512-ysxwsnTKdAx96aTRdhDOCQfDgbHnt8SK0KY8SEjO0wHinhWOFTESbjVCMPbU1uGXg/ch4lifqx0wfjOawU2+WA==" }, - "node_modules/make-fetch-happen": { + "make-fetch-happen": { "version": "10.2.1", "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-10.2.1.tgz", "integrity": "sha512-NgOPbRiaQM10DYXvN3/hhGVI2M5MtITFryzBGxHM5p4wnFxsVCbxkrBrDsk+EZ5OB4jEOT7AjDxtdF+KVEFT7w==", - "dev": true, - "dependencies": { + "requires": { "agentkeepalive": "^4.2.1", "cacache": "^16.1.0", "http-cache-semantics": "^4.1.0", @@ -1073,29 +1683,28 @@ "promise-retry": "^2.0.1", "socks-proxy-agent": "^7.0.0", "ssri": "^9.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, - "node_modules/map-obj": { + "map-obj": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.3.0.tgz", - "integrity": "sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } + "integrity": "sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==" }, - "node_modules/meow": { + "math-expression-evaluator": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/math-expression-evaluator/-/math-expression-evaluator-1.4.0.tgz", + "integrity": "sha512-4vRUvPyxdO8cWULGTh9dZWL2tZK6LDBvj+OGHBER7poH9Qdt7kXEoj20wiz4lQUbUXQZFjPbe5mVDo9nutizCw==" + }, + "mdn-data": { + "version": "2.0.30", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz", + "integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==" + }, + "meow": { "version": "9.0.0", "resolved": "https://registry.npmjs.org/meow/-/meow-9.0.0.tgz", "integrity": "sha512-+obSblOQmRhcyBt62furQqRAQpNyWXo8BuQ5bN7dG8wmwQ+vwHKp/rCFD4CrTP8CsDQD1sjoZ94K417XEUk8IQ==", - "dev": true, - "dependencies": { + "requires": { "@types/minimist": "^1.2.0", "camelcase-keys": "^6.2.2", "decamelize": "^1.2.0", @@ -1108,179 +1717,126 @@ "trim-newlines": "^3.0.0", "type-fest": "^0.18.0", "yargs-parser": "^20.2.3" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/min-indent": { + "min-indent": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", - "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", - "dev": true, - "engines": { - "node": ">=4" - } + "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==" }, - "node_modules/minimatch": { + "minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { + "requires": { "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" } }, - "node_modules/minimist-options": { + "minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==" + }, + "minimist-options": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-4.1.0.tgz", "integrity": "sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==", - "dev": true, - "dependencies": { + "requires": { "arrify": "^1.0.1", "is-plain-obj": "^1.1.0", "kind-of": "^6.0.3" - }, - "engines": { - "node": ">= 6" } }, - "node_modules/minipass": { + "minipass": { "version": "3.3.4", "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.4.tgz", "integrity": "sha512-I9WPbWHCGu8W+6k1ZiGpPu0GkoKBeorkfKNuAFBNS1HNFJvke82sxvI5bzcCNpWPorkOO5QQ+zomzzwRxejXiw==", - "dev": true, - "dependencies": { + "requires": { "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" } }, - "node_modules/minipass-collect": { + "minipass-collect": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz", "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", - "dev": true, - "dependencies": { + "requires": { "minipass": "^3.0.0" - }, - "engines": { - "node": ">= 8" } }, - "node_modules/minipass-fetch": { + "minipass-fetch": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-2.1.2.tgz", "integrity": "sha512-LT49Zi2/WMROHYoqGgdlQIZh8mLPZmOrN2NdJjMXxYe4nkN6FUyuPuOAOedNJDrx0IRGg9+4guZewtp8hE6TxA==", - "dev": true, - "dependencies": { + "requires": { "encoding": "^0.1.13", "minipass": "^3.1.6", "minipass-sized": "^1.0.3", "minizlib": "^2.1.2" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - }, - "optionalDependencies": { - "encoding": "^0.1.13" } }, - "node_modules/minipass-flush": { + "minipass-flush": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", - "dev": true, - "dependencies": { + "requires": { "minipass": "^3.0.0" - }, - "engines": { - "node": ">= 8" } }, - "node_modules/minipass-pipeline": { + "minipass-pipeline": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", - "dev": true, - "dependencies": { + "requires": { "minipass": "^3.0.0" - }, - "engines": { - "node": ">=8" } }, - "node_modules/minipass-sized": { + "minipass-sized": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz", "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==", - "dev": true, - "dependencies": { + "requires": { "minipass": "^3.0.0" - }, - "engines": { - "node": ">=8" } }, - "node_modules/minizlib": { + "minizlib": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", - "dev": true, - "dependencies": { + "requires": { "minipass": "^3.0.0", "yallist": "^4.0.0" - }, - "engines": { - "node": ">= 8" } }, - "node_modules/mkdirp": { + "mkdirp": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true, - "bin": { - "mkdirp": "bin/cmd.js" - }, - "engines": { - "node": ">=10" - } + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==" }, - "node_modules/ms": { + "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, - "node_modules/nan": { + "nan": { "version": "2.17.0", "resolved": "https://registry.npmjs.org/nan/-/nan-2.17.0.tgz", - "integrity": "sha512-2ZTgtl0nJsO0KQCjEpxcIr5D+Yv90plTitZt9JBfQvVJDS5seMl3FOvsh3+9CoYWXf/1l5OaZzzF6nDm4cagaQ==", - "dev": true + "integrity": "sha512-2ZTgtl0nJsO0KQCjEpxcIr5D+Yv90plTitZt9JBfQvVJDS5seMl3FOvsh3+9CoYWXf/1l5OaZzzF6nDm4cagaQ==" + }, + "nanoid": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", + "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==" }, - "node_modules/negotiator": { + "negotiator": { "version": "0.6.3", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", - "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", - "dev": true, - "engines": { - "node": ">= 0.6" - } + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==" }, - "node_modules/node-gyp": { + "node-gyp": { "version": "8.4.1", "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-8.4.1.tgz", "integrity": "sha512-olTJRgUtAb/hOXG0E93wZDs5YiJlgbXxTwQAFHyNlRsXQnYzUaF2aGgujZbw+hR8aF4ZG/rST57bWMWD16jr9w==", - "dev": true, - "dependencies": { + "requires": { "env-paths": "^2.2.0", "glob": "^7.1.4", "graceful-fs": "^4.2.6", @@ -1292,197 +1848,153 @@ "tar": "^6.1.2", "which": "^2.0.2" }, - "bin": { - "node-gyp": "bin/node-gyp.js" - }, - "engines": { - "node": ">= 10.12.0" - } - }, - "node_modules/node-gyp/node_modules/@npmcli/fs": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-1.1.1.tgz", - "integrity": "sha512-8KG5RD0GVP4ydEzRn/I4BNDuxDtqVbOdm8675T49OIG/NGhaK0pjPX7ZcDlvKYbA+ulvVK3ztfcF4uBdOxuJbQ==", - "dev": true, - "dependencies": { - "@gar/promisify": "^1.0.1", - "semver": "^7.3.5" - } - }, - "node_modules/node-gyp/node_modules/@npmcli/move-file": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-1.1.2.tgz", - "integrity": "sha512-1SUf/Cg2GzGDyaf15aR9St9TWlb+XvbZXWpDx8YKs7MLzMH/BCeopv+y9vzrzgkfykCGuWOlSu3mZhj2+FQcrg==", - "deprecated": "This functionality has been moved to @npmcli/fs", - "dev": true, - "dependencies": { - "mkdirp": "^1.0.4", - "rimraf": "^3.0.2" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/node-gyp/node_modules/@tootallnate/once": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", - "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", - "dev": true, - "engines": { - "node": ">= 6" - } - }, - "node_modules/node-gyp/node_modules/cacache": { - "version": "15.3.0", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-15.3.0.tgz", - "integrity": "sha512-VVdYzXEn+cnbXpFgWs5hTT7OScegHVmLhJIR8Ufqk3iFD6A6j5iSX1KuBTfNEv4tdJWE2PzA6IVFtcLC7fN9wQ==", - "dev": true, - "dependencies": { - "@npmcli/fs": "^1.0.0", - "@npmcli/move-file": "^1.0.1", - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "glob": "^7.1.4", - "infer-owner": "^1.0.4", - "lru-cache": "^6.0.0", - "minipass": "^3.1.1", - "minipass-collect": "^1.0.2", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.2", - "mkdirp": "^1.0.3", - "p-map": "^4.0.0", - "promise-inflight": "^1.0.1", - "rimraf": "^3.0.2", - "ssri": "^8.0.1", - "tar": "^6.0.2", - "unique-filename": "^1.1.1" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/node-gyp/node_modules/http-proxy-agent": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", - "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", - "dev": true, - "dependencies": { - "@tootallnate/once": "1", - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/node-gyp/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/node-gyp/node_modules/make-fetch-happen": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-9.1.0.tgz", - "integrity": "sha512-+zopwDy7DNknmwPQplem5lAZX/eCOzSvSNNcSKm5eVwTkOBzoktEfXsa9L23J/GIRhxRsaxzkPEhrJEpE2F4Gg==", - "dev": true, - "dependencies": { - "agentkeepalive": "^4.1.3", - "cacache": "^15.2.0", - "http-cache-semantics": "^4.1.0", - "http-proxy-agent": "^4.0.1", - "https-proxy-agent": "^5.0.0", - "is-lambda": "^1.0.1", - "lru-cache": "^6.0.0", - "minipass": "^3.1.3", - "minipass-collect": "^1.0.2", - "minipass-fetch": "^1.3.2", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "negotiator": "^0.6.2", - "promise-retry": "^2.0.1", - "socks-proxy-agent": "^6.0.0", - "ssri": "^8.0.0" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/node-gyp/node_modules/minipass-fetch": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-1.4.1.tgz", - "integrity": "sha512-CGH1eblLq26Y15+Azk7ey4xh0J/XfJfrCox5LDJiKqI2Q2iwOLOKrlmIaODiSQS8d18jalF6y2K2ePUm0CmShw==", - "dev": true, - "dependencies": { - "encoding": "^0.1.12", - "minipass": "^3.1.0", - "minipass-sized": "^1.0.3", - "minizlib": "^2.0.0" - }, - "engines": { - "node": ">=8" - }, - "optionalDependencies": { - "encoding": "^0.1.12" - } - }, - "node_modules/node-gyp/node_modules/socks-proxy-agent": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-6.2.1.tgz", - "integrity": "sha512-a6KW9G+6B3nWZ1yB8G7pJwL3ggLy1uTzKAgCb7ttblwqdz9fMGJUuTy3uFzEP48FAs9FLILlmzDlE2JJhVQaXQ==", - "dev": true, - "dependencies": { - "agent-base": "^6.0.2", - "debug": "^4.3.3", - "socks": "^2.6.2" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/node-gyp/node_modules/ssri": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.1.tgz", - "integrity": "sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ==", - "dev": true, - "dependencies": { - "minipass": "^3.1.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/node-gyp/node_modules/unique-filename": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", - "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", - "dev": true, - "dependencies": { - "unique-slug": "^2.0.0" + "@npmcli/fs": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-1.1.1.tgz", + "integrity": "sha512-8KG5RD0GVP4ydEzRn/I4BNDuxDtqVbOdm8675T49OIG/NGhaK0pjPX7ZcDlvKYbA+ulvVK3ztfcF4uBdOxuJbQ==", + "requires": { + "@gar/promisify": "^1.0.1", + "semver": "^7.3.5" + } + }, + "@npmcli/move-file": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-1.1.2.tgz", + "integrity": "sha512-1SUf/Cg2GzGDyaf15aR9St9TWlb+XvbZXWpDx8YKs7MLzMH/BCeopv+y9vzrzgkfykCGuWOlSu3mZhj2+FQcrg==", + "requires": { + "mkdirp": "^1.0.4", + "rimraf": "^3.0.2" + } + }, + "@tootallnate/once": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", + "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==" + }, + "cacache": { + "version": "15.3.0", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-15.3.0.tgz", + "integrity": "sha512-VVdYzXEn+cnbXpFgWs5hTT7OScegHVmLhJIR8Ufqk3iFD6A6j5iSX1KuBTfNEv4tdJWE2PzA6IVFtcLC7fN9wQ==", + "requires": { + "@npmcli/fs": "^1.0.0", + "@npmcli/move-file": "^1.0.1", + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "glob": "^7.1.4", + "infer-owner": "^1.0.4", + "lru-cache": "^6.0.0", + "minipass": "^3.1.1", + "minipass-collect": "^1.0.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.2", + "mkdirp": "^1.0.3", + "p-map": "^4.0.0", + "promise-inflight": "^1.0.1", + "rimraf": "^3.0.2", + "ssri": "^8.0.1", + "tar": "^6.0.2", + "unique-filename": "^1.1.1" + } + }, + "http-proxy-agent": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", + "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", + "requires": { + "@tootallnate/once": "1", + "agent-base": "6", + "debug": "4" + } + }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "requires": { + "yallist": "^4.0.0" + } + }, + "make-fetch-happen": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-9.1.0.tgz", + "integrity": "sha512-+zopwDy7DNknmwPQplem5lAZX/eCOzSvSNNcSKm5eVwTkOBzoktEfXsa9L23J/GIRhxRsaxzkPEhrJEpE2F4Gg==", + "requires": { + "agentkeepalive": "^4.1.3", + "cacache": "^15.2.0", + "http-cache-semantics": "^4.1.0", + "http-proxy-agent": "^4.0.1", + "https-proxy-agent": "^5.0.0", + "is-lambda": "^1.0.1", + "lru-cache": "^6.0.0", + "minipass": "^3.1.3", + "minipass-collect": "^1.0.2", + "minipass-fetch": "^1.3.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "negotiator": "^0.6.2", + "promise-retry": "^2.0.1", + "socks-proxy-agent": "^6.0.0", + "ssri": "^8.0.0" + } + }, + "minipass-fetch": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-1.4.1.tgz", + "integrity": "sha512-CGH1eblLq26Y15+Azk7ey4xh0J/XfJfrCox5LDJiKqI2Q2iwOLOKrlmIaODiSQS8d18jalF6y2K2ePUm0CmShw==", + "requires": { + "encoding": "^0.1.12", + "minipass": "^3.1.0", + "minipass-sized": "^1.0.3", + "minizlib": "^2.0.0" + } + }, + "socks-proxy-agent": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-6.2.1.tgz", + "integrity": "sha512-a6KW9G+6B3nWZ1yB8G7pJwL3ggLy1uTzKAgCb7ttblwqdz9fMGJUuTy3uFzEP48FAs9FLILlmzDlE2JJhVQaXQ==", + "requires": { + "agent-base": "^6.0.2", + "debug": "^4.3.3", + "socks": "^2.6.2" + } + }, + "ssri": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.1.tgz", + "integrity": "sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ==", + "requires": { + "minipass": "^3.1.1" + } + }, + "unique-filename": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", + "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", + "requires": { + "unique-slug": "^2.0.0" + } + }, + "unique-slug": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz", + "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==", + "requires": { + "imurmurhash": "^0.1.4" + } + } } }, - "node_modules/node-gyp/node_modules/unique-slug": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz", - "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==", - "dev": true, - "dependencies": { - "imurmurhash": "^0.1.4" - } + "node-releases": { + "version": "2.0.13", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.13.tgz", + "integrity": "sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==" }, - "node_modules/node-sass": { + "node-sass": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/node-sass/-/node-sass-8.0.0.tgz", "integrity": "sha512-jPzqCF2/e6JXw6r3VxfIqYc8tKQdkj5Z/BDATYyG6FL6b/LuYBNFGFVhus0mthcWifHm/JzBpKAd+3eXsWeK/A==", - "dev": true, - "hasInstallScript": true, - "dependencies": { + "requires": { "async-foreach": "^0.1.3", "chalk": "^4.1.2", "cross-spawn": "^7.0.3", @@ -1497,2186 +2009,843 @@ "sass-graph": "^4.0.1", "stdout-stream": "^1.4.0", "true-case-path": "^2.2.1" - }, - "bin": { - "node-sass": "bin/node-sass" - }, - "engines": { - "node": ">=14" } }, - "node_modules/nopt": { + "nopt": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", - "dev": true, - "dependencies": { + "requires": { "abbrev": "1" - }, - "bin": { - "nopt": "bin/nopt.js" - }, - "engines": { - "node": ">=6" } }, - "node_modules/normalize-package-data": { + "normalize-package-data": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.3.tgz", "integrity": "sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==", - "dev": true, - "dependencies": { + "requires": { "hosted-git-info": "^4.0.1", "is-core-module": "^2.5.0", "semver": "^7.3.4", "validate-npm-package-license": "^3.0.1" - }, - "engines": { - "node": ">=10" } }, - "node_modules/npmlog": { + "normalize-range": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", + "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==" + }, + "normalize-url": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-1.9.1.tgz", + "integrity": "sha512-A48My/mtCklowHBlI8Fq2jFWK4tX4lJ5E6ytFsSOq1fzpvT0SQSgKhSg7lN5c2uYFOrUAOQp6zhhJnpp1eMloQ==", + "requires": { + "object-assign": "^4.0.1", + "prepend-http": "^1.0.0", + "query-string": "^4.1.0", + "sort-keys": "^1.0.0" + } + }, + "npmlog": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-6.0.2.tgz", "integrity": "sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==", - "dev": true, - "dependencies": { + "requires": { "are-we-there-yet": "^3.0.0", "console-control-strings": "^1.1.0", "gauge": "^4.0.3", "set-blocking": "^2.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, - "node_modules/once": { + "nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "requires": { + "boolbase": "^1.0.0" + } + }, + "num2fraction": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/num2fraction/-/num2fraction-1.2.2.tgz", + "integrity": "sha512-Y1wZESM7VUThYY+4W+X4ySH2maqcA+p7UR+w8VWNWVAd6lwuXXWz/w/Cz43J/dI2I+PS6wD5N+bJUF+gjWvIqg==" + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==" + }, + "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dev": true, - "dependencies": { + "requires": { "wrappy": "1" } }, - "node_modules/p-limit": { + "p-limit": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "dependencies": { + "requires": { "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/p-locate": { + "p-locate": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "dependencies": { + "requires": { "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" } }, - "node_modules/p-map": { + "p-map": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", - "dev": true, - "dependencies": { + "requires": { "aggregate-error": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/p-try": { + "p-try": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true, - "engines": { - "node": ">=6" - } + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==" }, - "node_modules/parse-json": { + "parse-json": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", - "dev": true, - "dependencies": { + "requires": { "@babel/code-frame": "^7.0.0", "error-ex": "^1.3.1", "json-parse-even-better-errors": "^2.3.0", "lines-and-columns": "^1.1.6" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/path-exists": { + "path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true, - "engines": { - "node": ">=8" - } + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==" }, - "node_modules/path-is-absolute": { + "path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==" }, - "node_modules/path-key": { + "path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, - "engines": { - "node": ">=8" - } + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==" }, - "node_modules/path-parse": { + "path-parse": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" }, - "node_modules/process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", - "dev": true + "picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" }, - "node_modules/promise-inflight": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", - "integrity": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==", - "dev": true + "postcss": { + "version": "8.4.31", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", + "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", + "requires": { + "nanoid": "^3.3.6", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + } }, - "node_modules/promise-retry": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", - "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", - "dev": true, - "dependencies": { - "err-code": "^2.0.2", - "retry": "^0.12.0" - }, - "engines": { - "node": ">=10" + "postcss-calc": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-9.0.1.tgz", + "integrity": "sha512-TipgjGyzP5QzEhsOZUaIkeO5mKeMFpebWzRogWG/ysonUlnHcq5aJe0jOjpfzUU8PeSaBQnrE8ehR0QA5vs8PQ==", + "requires": { + "postcss-selector-parser": "^6.0.11", + "postcss-value-parser": "^4.2.0" } }, - "node_modules/quick-lru": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-4.0.1.tgz", - "integrity": "sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==", - "dev": true, - "engines": { - "node": ">=8" + "postcss-colormin": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-6.0.0.tgz", + "integrity": "sha512-EuO+bAUmutWoZYgHn2T1dG1pPqHU6L4TjzPlu4t1wZGXQ/fxV16xg2EJmYi0z+6r+MGV1yvpx1BHkUaRrPa2bw==", + "requires": { + "browserslist": "^4.21.4", + "caniuse-api": "^3.0.0", + "colord": "^2.9.1", + "postcss-value-parser": "^4.2.0" } }, - "node_modules/read-pkg": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", - "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", - "dev": true, - "dependencies": { - "@types/normalize-package-data": "^2.4.0", - "normalize-package-data": "^2.5.0", - "parse-json": "^5.0.0", - "type-fest": "^0.6.0" - }, - "engines": { - "node": ">=8" + "postcss-convert-values": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/postcss-convert-values/-/postcss-convert-values-6.0.0.tgz", + "integrity": "sha512-U5D8QhVwqT++ecmy8rnTb+RL9n/B806UVaS3m60lqle4YDFcpbS3ae5bTQIh3wOGUSDHSEtMYLs/38dNG7EYFw==", + "requires": { + "browserslist": "^4.21.4", + "postcss-value-parser": "^4.2.0" } }, - "node_modules/read-pkg-up": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", - "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", - "dev": true, - "dependencies": { - "find-up": "^4.1.0", - "read-pkg": "^5.2.0", - "type-fest": "^0.8.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/read-pkg-up/node_modules/type-fest": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", - "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/read-pkg/node_modules/hosted-git-info": { - "version": "2.8.9", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", - "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", - "dev": true - }, - "node_modules/read-pkg/node_modules/normalize-package-data": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", - "dev": true, - "dependencies": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - } + "postcss-discard-comments": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-6.0.0.tgz", + "integrity": "sha512-p2skSGqzPMZkEQvJsgnkBhCn8gI7NzRH2683EEjrIkoMiwRELx68yoUJ3q3DGSGuQ8Ug9Gsn+OuDr46yfO+eFw==" }, - "node_modules/read-pkg/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true, - "bin": { - "semver": "bin/semver" - } + "postcss-discard-duplicates": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-6.0.0.tgz", + "integrity": "sha512-bU1SXIizMLtDW4oSsi5C/xHKbhLlhek/0/yCnoMQany9k3nPBq+Ctsv/9oMmyqbR96HYHxZcHyK2HR5P/mqoGA==" }, - "node_modules/read-pkg/node_modules/type-fest": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", - "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", - "dev": true, - "engines": { - "node": ">=8" - } + "postcss-discard-empty": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-6.0.0.tgz", + "integrity": "sha512-b+h1S1VT6dNhpcg+LpyiUrdnEZfICF0my7HAKgJixJLW7BnNmpRH34+uw/etf5AhOlIhIAuXApSzzDzMI9K/gQ==" }, - "node_modules/readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "dev": true, - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } + "postcss-discard-overridden": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-6.0.0.tgz", + "integrity": "sha512-4VELwssYXDFigPYAZ8vL4yX4mUepF/oCBeeIT4OXsJPYOtvJumyz9WflmJWTfDwCUcpDR+z0zvCWBXgTx35SVw==" }, - "node_modules/redent": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", - "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", - "dev": true, - "dependencies": { - "indent-string": "^4.0.0", - "strip-indent": "^3.0.0" + "postcss-discard-unused": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/postcss-discard-unused/-/postcss-discard-unused-2.2.3.tgz", + "integrity": "sha512-nCbFNfqYAbKCw9J6PSJubpN9asnrwVLkRDFc4KCwyUEdOtM5XDE/eTW3OpqHrYY1L4fZxgan7LLRAAYYBzwzrg==", + "requires": { + "postcss": "^5.0.14", + "uniqs": "^2.0.0" }, - "engines": { - "node": ">=8" - } - }, - "node_modules/require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/resolve": { - "version": "1.22.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", - "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", - "dev": true, "dependencies": { - "is-core-module": "^2.9.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/retry": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", - "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", - "dev": true, - "engines": { - "node": ">= 4" + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==" + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==" + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==", + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + }, + "dependencies": { + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==" + } + } + }, + "has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha512-DyYHfIYwAJmjAjSSPKANxI8bFY9YtFrgkAfinBojQ8YJTOuOuav64tMUJv584SES4xl74PmuaevIyaLESHdTAA==" + }, + "postcss": { + "version": "5.2.18", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", + "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", + "requires": { + "chalk": "^1.1.3", + "js-base64": "^2.1.9", + "source-map": "^0.5.6", + "supports-color": "^3.2.3" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==" + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==", + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "supports-color": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha512-Jds2VIYDrlp5ui7t8abHN2bjAu4LV/q4N2KivFPpGH0lrka0BMq/33AmECUXlKPcHigkNaqfXRENFju+rlcy+A==", + "requires": { + "has-flag": "^1.0.0" + } + } } }, - "node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" + "postcss-filter-plugins": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/postcss-filter-plugins/-/postcss-filter-plugins-2.0.3.tgz", + "integrity": "sha512-T53GVFsdinJhgwm7rg1BzbeBRomOg9y5MBVhGcsV0CxurUdVj1UlPdKtn7aqYA/c/QVkzKMjq2bSV5dKG5+AwQ==", + "requires": { + "postcss": "^5.0.4" }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==" + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==" + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==", + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + }, + "dependencies": { + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==" + } + } + }, + "has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha512-DyYHfIYwAJmjAjSSPKANxI8bFY9YtFrgkAfinBojQ8YJTOuOuav64tMUJv584SES4xl74PmuaevIyaLESHdTAA==" + }, + "postcss": { + "version": "5.2.18", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", + "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", + "requires": { + "chalk": "^1.1.3", + "js-base64": "^2.1.9", + "source-map": "^0.5.6", + "supports-color": "^3.2.3" + } }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==" }, - { - "type": "consulting", - "url": "https://feross.org/support" + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==", + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "supports-color": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha512-Jds2VIYDrlp5ui7t8abHN2bjAu4LV/q4N2KivFPpGH0lrka0BMq/33AmECUXlKPcHigkNaqfXRENFju+rlcy+A==", + "requires": { + "has-flag": "^1.0.0" + } } - ] - }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true, - "optional": true - }, - "node_modules/sass-graph": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/sass-graph/-/sass-graph-4.0.1.tgz", - "integrity": "sha512-5YCfmGBmxoIRYHnKK2AKzrAkCoQ8ozO+iumT8K4tXJXRVCPf+7s1/9KxTSW3Rbvf+7Y7b4FR3mWyLnQr3PHocA==", - "dev": true, - "dependencies": { - "glob": "^7.0.0", - "lodash": "^4.17.11", - "scss-tokenizer": "^0.4.3", - "yargs": "^17.2.1" - }, - "bin": { - "sassgraph": "bin/sassgraph" - }, - "engines": { - "node": ">=12" } }, - "node_modules/scss-tokenizer": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/scss-tokenizer/-/scss-tokenizer-0.4.3.tgz", - "integrity": "sha512-raKLgf1LI5QMQnG+RxHz6oK0sL3x3I4FN2UDLqgLOGO8hodECNnNh5BXn7fAyBxrA8zVzdQizQ6XjNJQ+uBwMw==", - "dev": true, + "postcss-merge-idents": { + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/postcss-merge-idents/-/postcss-merge-idents-2.1.7.tgz", + "integrity": "sha512-9DHmfCZ7/hNHhIKnNkz4CU0ejtGen5BbTRJc13Z2uHfCedeCUsK2WEQoAJRBL+phs68iWK6Qf8Jze71anuysWA==", + "requires": { + "has": "^1.0.1", + "postcss": "^5.0.10", + "postcss-value-parser": "^3.1.1" + }, "dependencies": { - "js-base64": "^2.4.9", - "source-map": "^0.7.3" + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==" + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==" + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==", + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + }, + "dependencies": { + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==" + } + } + }, + "has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha512-DyYHfIYwAJmjAjSSPKANxI8bFY9YtFrgkAfinBojQ8YJTOuOuav64tMUJv584SES4xl74PmuaevIyaLESHdTAA==" + }, + "postcss": { + "version": "5.2.18", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", + "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", + "requires": { + "chalk": "^1.1.3", + "js-base64": "^2.1.9", + "source-map": "^0.5.6", + "supports-color": "^3.2.3" + } + }, + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==" + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==" + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==", + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "supports-color": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha512-Jds2VIYDrlp5ui7t8abHN2bjAu4LV/q4N2KivFPpGH0lrka0BMq/33AmECUXlKPcHigkNaqfXRENFju+rlcy+A==", + "requires": { + "has-flag": "^1.0.0" + } + } } }, - "node_modules/semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" + "postcss-merge-longhand": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-6.0.0.tgz", + "integrity": "sha512-4VSfd1lvGkLTLYcxFuISDtWUfFS4zXe0FpF149AyziftPFQIWxjvFSKhA4MIxMe4XM3yTDgQMbSNgzIVxChbIg==", + "requires": { + "postcss-value-parser": "^4.2.0", + "stylehacks": "^6.0.0" } }, - "node_modules/semver/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" + "postcss-merge-rules": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/postcss-merge-rules/-/postcss-merge-rules-6.0.1.tgz", + "integrity": "sha512-a4tlmJIQo9SCjcfiCcCMg/ZCEe0XTkl/xK0XHBs955GWg9xDX3NwP9pwZ78QUOWB8/0XCjZeJn98Dae0zg6AAw==", + "requires": { + "browserslist": "^4.21.4", + "caniuse-api": "^3.0.0", + "cssnano-utils": "^4.0.0", + "postcss-selector-parser": "^6.0.5" } }, - "node_modules/set-blocking": { + "postcss-message-helpers": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", - "dev": true + "resolved": "https://registry.npmjs.org/postcss-message-helpers/-/postcss-message-helpers-2.0.0.tgz", + "integrity": "sha512-tPLZzVAiIJp46TBbpXtrUAKqedXSyW5xDEo1sikrfEfnTs+49SBZR/xDdqCiJvSSbtr615xDsaMF3RrxS2jZlA==" }, - "node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" + "postcss-minify-font-values": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/postcss-minify-font-values/-/postcss-minify-font-values-6.0.0.tgz", + "integrity": "sha512-zNRAVtyh5E8ndZEYXA4WS8ZYsAp798HiIQ1V2UF/C/munLp2r1UGHwf1+6JFu7hdEhJFN+W1WJQKBrtjhFgEnA==", + "requires": { + "postcss-value-parser": "^4.2.0" } }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, - "engines": { - "node": ">=8" + "postcss-minify-gradients": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-6.0.0.tgz", + "integrity": "sha512-wO0F6YfVAR+K1xVxF53ueZJza3L+R3E6cp0VwuXJQejnNUH0DjcAFe3JEBeTY1dLwGa0NlDWueCA1VlEfiKgAA==", + "requires": { + "colord": "^2.9.1", + "cssnano-utils": "^4.0.0", + "postcss-value-parser": "^4.2.0" } }, - "node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true - }, - "node_modules/smart-buffer": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", - "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", - "dev": true, - "engines": { - "node": ">= 6.0.0", - "npm": ">= 3.0.0" + "postcss-minify-params": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/postcss-minify-params/-/postcss-minify-params-6.0.0.tgz", + "integrity": "sha512-Fz/wMQDveiS0n5JPcvsMeyNXOIMrwF88n7196puSuQSWSa+/Ofc1gDOSY2xi8+A4PqB5dlYCKk/WfqKqsI+ReQ==", + "requires": { + "browserslist": "^4.21.4", + "cssnano-utils": "^4.0.0", + "postcss-value-parser": "^4.2.0" } }, - "node_modules/socks": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.1.tgz", - "integrity": "sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==", - "dev": true, - "dependencies": { - "ip": "^2.0.0", - "smart-buffer": "^4.2.0" - }, - "engines": { - "node": ">= 10.13.0", - "npm": ">= 3.0.0" + "postcss-minify-selectors": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/postcss-minify-selectors/-/postcss-minify-selectors-6.0.0.tgz", + "integrity": "sha512-ec/q9JNCOC2CRDNnypipGfOhbYPuUkewGwLnbv6omue/PSASbHSU7s6uSQ0tcFRVv731oMIx8k0SP4ZX6be/0g==", + "requires": { + "postcss-selector-parser": "^6.0.5" } }, - "node_modules/socks-proxy-agent": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-7.0.0.tgz", - "integrity": "sha512-Fgl0YPZ902wEsAyiQ+idGd1A7rSFx/ayC1CQVMw5P+EQx2V0SgpGtf6OKFhVjPflPUl9YMmEOnmfjCdMUsygww==", - "dev": true, - "dependencies": { - "agent-base": "^6.0.2", - "debug": "^4.3.3", - "socks": "^2.6.2" - }, - "engines": { - "node": ">= 10" - } + "postcss-normalize-charset": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-6.0.0.tgz", + "integrity": "sha512-cqundwChbu8yO/gSWkuFDmKrCZ2vJzDAocheT2JTd0sFNA4HMGoKMfbk2B+J0OmO0t5GUkiAkSM5yF2rSLUjgQ==" }, - "node_modules/source-map": { - "version": "0.7.4", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", - "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", - "dev": true, - "engines": { - "node": ">= 8" + "postcss-normalize-display-values": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-display-values/-/postcss-normalize-display-values-6.0.0.tgz", + "integrity": "sha512-Qyt5kMrvy7dJRO3OjF7zkotGfuYALETZE+4lk66sziWSPzlBEt7FrUshV6VLECkI4EN8Z863O6Nci4NXQGNzYw==", + "requires": { + "postcss-value-parser": "^4.2.0" } }, - "node_modules/spdx-correct": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", - "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", - "dev": true, - "dependencies": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" + "postcss-normalize-positions": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-positions/-/postcss-normalize-positions-6.0.0.tgz", + "integrity": "sha512-mPCzhSV8+30FZyWhxi6UoVRYd3ZBJgTRly4hOkaSifo0H+pjDYcii/aVT4YE6QpOil15a5uiv6ftnY3rm0igPg==", + "requires": { + "postcss-value-parser": "^4.2.0" } }, - "node_modules/spdx-exceptions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", - "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", - "dev": true - }, - "node_modules/spdx-expression-parse": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", - "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", - "dev": true, - "dependencies": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" + "postcss-normalize-repeat-style": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-6.0.0.tgz", + "integrity": "sha512-50W5JWEBiOOAez2AKBh4kRFm2uhrT3O1Uwdxz7k24aKtbD83vqmcVG7zoIwo6xI2FZ/HDlbrCopXhLeTpQib1A==", + "requires": { + "postcss-value-parser": "^4.2.0" } }, - "node_modules/spdx-license-ids": { - "version": "3.0.12", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.12.tgz", - "integrity": "sha512-rr+VVSXtRhO4OHbXUiAF7xW3Bo9DuuF6C5jH+q/x15j2jniycgKbxU09Hr0WqlSLUs4i4ltHGXqTe7VHclYWyA==", - "dev": true - }, - "node_modules/ssri": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-9.0.1.tgz", - "integrity": "sha512-o57Wcn66jMQvfHG1FlYbWeZWW/dHZhJXjpIcTfXldXEk5nz5lStPo3mK0OJQfGR3RbZUlbISexbljkJzuEj/8Q==", - "dev": true, - "dependencies": { - "minipass": "^3.1.1" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + "postcss-normalize-string": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-string/-/postcss-normalize-string-6.0.0.tgz", + "integrity": "sha512-KWkIB7TrPOiqb8ZZz6homet2KWKJwIlysF5ICPZrXAylGe2hzX/HSf4NTX2rRPJMAtlRsj/yfkrWGavFuB+c0w==", + "requires": { + "postcss-value-parser": "^4.2.0" } }, - "node_modules/stdout-stream": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/stdout-stream/-/stdout-stream-1.4.1.tgz", - "integrity": "sha512-j4emi03KXqJWcIeF8eIXkjMFN1Cmb8gUlDYGeBALLPo5qdyTfA9bOtl8m33lRoC+vFMkP3gl0WsDr6+gzxbbTA==", - "dev": true, - "dependencies": { - "readable-stream": "^2.0.1" + "postcss-normalize-timing-functions": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-6.0.0.tgz", + "integrity": "sha512-tpIXWciXBp5CiFs8sem90IWlw76FV4oi6QEWfQwyeREVwUy39VSeSqjAT7X0Qw650yAimYW5gkl2Gd871N5SQg==", + "requires": { + "postcss-value-parser": "^4.2.0" } }, - "node_modules/stdout-stream/node_modules/readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/stdout-stream/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "node_modules/stdout-stream/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "dependencies": { - "safe-buffer": "~5.1.0" + "postcss-normalize-unicode": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-unicode/-/postcss-normalize-unicode-6.0.0.tgz", + "integrity": "sha512-ui5crYkb5ubEUDugDc786L/Me+DXp2dLg3fVJbqyAl0VPkAeALyAijF2zOsnZyaS1HyfPuMH0DwyY18VMFVNkg==", + "requires": { + "browserslist": "^4.21.4", + "postcss-value-parser": "^4.2.0" } }, - "node_modules/string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dev": true, - "dependencies": { - "safe-buffer": "~5.2.0" - } - }, - "node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-indent": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", - "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", - "dev": true, - "dependencies": { - "min-indent": "^1.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/tar": { - "version": "6.1.12", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.12.tgz", - "integrity": "sha512-jU4TdemS31uABHd+Lt5WEYJuzn+TJTCBLljvIAHZOz6M9Os5pJ4dD+vRFLxPa/n3T0iEFzpi+0x1UfuDZYbRMw==", - "dev": true, - "dependencies": { - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "minipass": "^3.0.0", - "minizlib": "^2.1.1", - "mkdirp": "^1.0.3", - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/trim-newlines": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-3.0.1.tgz", - "integrity": "sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/true-case-path": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/true-case-path/-/true-case-path-2.2.1.tgz", - "integrity": "sha512-0z3j8R7MCjy10kc/g+qg7Ln3alJTodw9aDuVWZa3uiWqfuBMKeAeP2ocWcxoyM3D73yz3Jt/Pu4qPr4wHSdB/Q==", - "dev": true - }, - "node_modules/type-fest": { - "version": "0.18.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.18.1.tgz", - "integrity": "sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/unique-filename": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-2.0.1.tgz", - "integrity": "sha512-ODWHtkkdx3IAR+veKxFV+VBkUMcN+FaqzUUd7IZzt+0zhDZFPFxhlqwPF3YQvMHx1TD0tdgYl+kuPnJ8E6ql7A==", - "dev": true, - "dependencies": { - "unique-slug": "^3.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/unique-slug": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-3.0.0.tgz", - "integrity": "sha512-8EyMynh679x/0gqE9fT9oilG+qEt+ibFyqjuVTsZn1+CMxH+XLlpvr2UZx4nVcCwTpx81nICr2JQFkM+HPLq4w==", - "dev": true, - "dependencies": { - "imurmurhash": "^0.1.4" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", - "dev": true - }, - "node_modules/validate-npm-package-license": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", - "dev": true, - "dependencies": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } - }, - "node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/wide-align": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", - "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", - "dev": true, - "dependencies": { - "string-width": "^1.0.2 || 2 || 3 || 4" - } - }, - "node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true - }, - "node_modules/y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, - "node_modules/yargs": { - "version": "17.6.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.6.2.tgz", - "integrity": "sha512-1/9UrdHjDZc0eOU0HxOHoS78C69UD3JRMvzlJ7S79S2nTaWRA/whGCTV8o9e/N/1Va9YIV7Q4sOxD8VV4pCWOw==", - "dev": true, - "dependencies": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/yargs-parser": { - "version": "20.2.9", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", - "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/yargs/node_modules/yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "dev": true, - "engines": { - "node": ">=12" - } - } - }, - "dependencies": { - "@babel/code-frame": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz", - "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==", - "dev": true, - "requires": { - "@babel/highlight": "^7.18.6" - } - }, - "@babel/helper-validator-identifier": { - "version": "7.19.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz", - "integrity": "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==", - "dev": true - }, - "@babel/highlight": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", - "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.18.6", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "@gar/promisify": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz", - "integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==", - "dev": true - }, - "@npmcli/fs": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-2.1.2.tgz", - "integrity": "sha512-yOJKRvohFOaLqipNtwYB9WugyZKhC/DZC4VYPmpaCzDBrA8YpK3qHZ8/HGscMnE4GqbkLNuVcCnxkeQEdGt6LQ==", - "dev": true, - "requires": { - "@gar/promisify": "^1.1.3", - "semver": "^7.3.5" - } - }, - "@npmcli/move-file": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-2.0.1.tgz", - "integrity": "sha512-mJd2Z5TjYWq/ttPLLGqArdtnC74J6bOzg4rMDnN+p1xTacZ2yPRCk2y0oSWQtygLR9YVQXgOcONrwtnk3JupxQ==", - "dev": true, - "requires": { - "mkdirp": "^1.0.4", - "rimraf": "^3.0.2" - } - }, - "@tootallnate/once": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", - "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", - "dev": true - }, - "@types/minimist": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.2.tgz", - "integrity": "sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==", - "dev": true - }, - "@types/normalize-package-data": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz", - "integrity": "sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==", - "dev": true - }, - "abbrev": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", - "dev": true - }, - "agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "dev": true, - "requires": { - "debug": "4" - } - }, - "agentkeepalive": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.2.1.tgz", - "integrity": "sha512-Zn4cw2NEqd+9fiSVWMscnjyQ1a8Yfoc5oBajLeo5w+YBHgDUcEBY2hS4YpTz6iN5f/2zQiktcuM6tS8x1p9dpA==", - "dev": true, - "requires": { - "debug": "^4.1.0", - "depd": "^1.1.2", - "humanize-ms": "^1.2.1" - } - }, - "aggregate-error": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", - "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", - "dev": true, - "requires": { - "clean-stack": "^2.0.0", - "indent-string": "^4.0.0" - } - }, - "ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true - }, - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "aproba": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", - "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==", - "dev": true - }, - "are-we-there-yet": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-3.0.1.tgz", - "integrity": "sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg==", - "dev": true, - "requires": { - "delegates": "^1.0.0", - "readable-stream": "^3.6.0" - } - }, - "arrify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", - "integrity": "sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==", - "dev": true - }, - "async-foreach": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/async-foreach/-/async-foreach-0.1.3.tgz", - "integrity": "sha512-VUeSMD8nEGBWaZK4lizI1sf3yEC7pnAQ/mrI7pC2fBz2s/tq5jWWEngTwaf0Gruu/OoXRGLGg1XFqpYBiGTYJA==", - "dev": true - }, - "balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true - }, - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "bulma": { - "version": "0.9.4", - "resolved": "https://registry.npmjs.org/bulma/-/bulma-0.9.4.tgz", - "integrity": "sha512-86FlT5+1GrsgKbPLRRY7cGDg8fsJiP/jzTqXXVqiUZZ2aZT8uemEOHlU1CDU+TxklPEZ11HZNNWclRBBecP4CQ==", - "dev": true - }, - "cacache": { - "version": "16.1.3", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-16.1.3.tgz", - "integrity": "sha512-/+Emcj9DAXxX4cwlLmRI9c166RuL3w30zp4R7Joiv2cQTtTtA+jeuCAjH3ZlGnYS3tKENSrKhAzVVP9GVyzeYQ==", - "dev": true, - "requires": { - "@npmcli/fs": "^2.1.0", - "@npmcli/move-file": "^2.0.0", - "chownr": "^2.0.0", - "fs-minipass": "^2.1.0", - "glob": "^8.0.1", - "infer-owner": "^1.0.4", - "lru-cache": "^7.7.1", - "minipass": "^3.1.6", - "minipass-collect": "^1.0.2", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "mkdirp": "^1.0.4", - "p-map": "^4.0.0", - "promise-inflight": "^1.0.1", - "rimraf": "^3.0.2", - "ssri": "^9.0.0", - "tar": "^6.1.11", - "unique-filename": "^2.0.0" - }, - "dependencies": { - "brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0" - } - }, - "glob": { - "version": "8.0.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-8.0.3.tgz", - "integrity": "sha512-ull455NHSHI/Y1FqGaaYFaLGkNMMJbavMrEGFXG/PGrg6y7sutWHUHrz6gy6WEBH6akM1M414dWKCNs+IhKdiQ==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^5.0.1", - "once": "^1.3.0" - } - }, - "minimatch": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.0.tgz", - "integrity": "sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==", - "dev": true, - "requires": { - "brace-expansion": "^2.0.1" - } - } - } - }, - "camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true - }, - "camelcase-keys": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-6.2.2.tgz", - "integrity": "sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==", - "dev": true, - "requires": { - "camelcase": "^5.3.1", - "map-obj": "^4.0.0", - "quick-lru": "^4.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "chownr": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", - "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", - "dev": true - }, - "clean-stack": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", - "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", - "dev": true - }, - "cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "dev": true, - "requires": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "color-support": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", - "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", - "dev": true - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true - }, - "console-control-strings": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", - "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==", - "dev": true - }, - "core-util-is": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", - "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", - "dev": true - }, - "cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "requires": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - } - }, - "debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, - "requires": { - "ms": "2.1.2" - } - }, - "decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", - "dev": true - }, - "decamelize-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.1.tgz", - "integrity": "sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==", - "dev": true, - "requires": { - "decamelize": "^1.1.0", - "map-obj": "^1.0.0" - }, - "dependencies": { - "map-obj": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", - "integrity": "sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==", - "dev": true - } - } - }, - "delegates": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==", - "dev": true - }, - "depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", - "dev": true - }, - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "encoding": { - "version": "0.1.13", - "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", - "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", - "dev": true, - "optional": true, - "requires": { - "iconv-lite": "^0.6.2" - } - }, - "env-paths": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", - "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", - "dev": true - }, - "err-code": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", - "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==", - "dev": true - }, - "error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true, - "requires": { - "is-arrayish": "^0.2.1" - } - }, - "escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", - "dev": true - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true - }, - "find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "requires": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - } - }, - "fs-minipass": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", - "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", - "dev": true, - "requires": { - "minipass": "^3.0.0" - } - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true - }, - "function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true - }, - "gauge": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-4.0.4.tgz", - "integrity": "sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==", - "dev": true, - "requires": { - "aproba": "^1.0.3 || ^2.0.0", - "color-support": "^1.1.3", - "console-control-strings": "^1.1.0", - "has-unicode": "^2.0.1", - "signal-exit": "^3.0.7", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1", - "wide-align": "^1.1.5" - } - }, - "gaze": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/gaze/-/gaze-1.1.3.tgz", - "integrity": "sha512-BRdNm8hbWzFzWHERTrejLqwHDfS4GibPoq5wjTPIoJHoBtKGPg3xAFfxmM+9ztbXelxcf2hwQcaz1PtmFeue8g==", - "dev": true, - "requires": { - "globule": "^1.0.0" - } - }, - "get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true - }, - "get-stdin": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", - "integrity": "sha512-F5aQMywwJ2n85s4hJPTT9RPxGmubonuB10MNYo17/xph174n2MIR33HRguhzVag10O/npM7SPk73LMZNP+FaWw==", - "dev": true - }, - "glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "globule": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/globule/-/globule-1.3.4.tgz", - "integrity": "sha512-OPTIfhMBh7JbBYDpa5b+Q5ptmMWKwcNcFSR/0c6t8V4f3ZAVBEsKNY37QdVqmLRYSMhOUGYrY0QhSoEpzGr/Eg==", - "dev": true, - "requires": { - "glob": "~7.1.1", - "lodash": "^4.17.21", - "minimatch": "~3.0.2" - }, - "dependencies": { - "glob": { - "version": "7.1.7", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", - "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "minimatch": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.8.tgz", - "integrity": "sha512-6FsRAQsxQ61mw+qP1ZzbL9Bc78x2p5OqNgNpnoAFLTrX8n5Kxph0CsnhmKKNXTWjXqU5L0pGPR7hYk+XWZr60Q==", - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - } - } - }, - "graceful-fs": { - "version": "4.2.10", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", - "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", - "dev": true - }, - "hard-rejection": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/hard-rejection/-/hard-rejection-2.1.0.tgz", - "integrity": "sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==", - "dev": true - }, - "has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, - "requires": { - "function-bind": "^1.1.1" - } - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "has-unicode": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", - "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==", - "dev": true - }, - "hosted-git-info": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", - "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - }, - "dependencies": { - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "requires": { - "yallist": "^4.0.0" - } - } - } - }, - "http-cache-semantics": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", - "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==", - "dev": true - }, - "http-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", - "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", - "dev": true, - "requires": { - "@tootallnate/once": "2", - "agent-base": "6", - "debug": "4" - } - }, - "https-proxy-agent": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", - "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", - "dev": true, - "requires": { - "agent-base": "6", - "debug": "4" - } - }, - "humanize-ms": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", - "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==", - "dev": true, - "requires": { - "ms": "^2.0.0" - } - }, - "iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "dev": true, - "optional": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - } - }, - "imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", - "dev": true - }, - "indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "dev": true - }, - "infer-owner": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", - "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", - "dev": true - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "dev": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, - "ip": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz", - "integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==", - "dev": true - }, - "is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", - "dev": true - }, - "is-core-module": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz", - "integrity": "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==", - "dev": true, - "requires": { - "has": "^1.0.3" - } - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true - }, - "is-lambda": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz", - "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==", - "dev": true - }, - "is-plain-obj": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", - "integrity": "sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==", - "dev": true - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", - "dev": true - }, - "isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true - }, - "js-base64": { - "version": "2.6.4", - "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.6.4.tgz", - "integrity": "sha512-pZe//GGmwJndub7ZghVHz7vjb2LgC1m8B07Au3eYqeqv9emhESByMXxaEgkUkEqJe87oBbSniGYoQNIBklc7IQ==", - "dev": true - }, - "js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true - }, - "json-parse-even-better-errors": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "dev": true - }, - "kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true - }, - "lines-and-columns": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", - "dev": true - }, - "locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "requires": { - "p-locate": "^4.1.0" - } - }, - "lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true - }, - "lru-cache": { - "version": "7.14.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.14.1.tgz", - "integrity": "sha512-ysxwsnTKdAx96aTRdhDOCQfDgbHnt8SK0KY8SEjO0wHinhWOFTESbjVCMPbU1uGXg/ch4lifqx0wfjOawU2+WA==", - "dev": true - }, - "make-fetch-happen": { - "version": "10.2.1", - "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-10.2.1.tgz", - "integrity": "sha512-NgOPbRiaQM10DYXvN3/hhGVI2M5MtITFryzBGxHM5p4wnFxsVCbxkrBrDsk+EZ5OB4jEOT7AjDxtdF+KVEFT7w==", - "dev": true, - "requires": { - "agentkeepalive": "^4.2.1", - "cacache": "^16.1.0", - "http-cache-semantics": "^4.1.0", - "http-proxy-agent": "^5.0.0", - "https-proxy-agent": "^5.0.0", - "is-lambda": "^1.0.1", - "lru-cache": "^7.7.1", - "minipass": "^3.1.6", - "minipass-collect": "^1.0.2", - "minipass-fetch": "^2.0.3", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "negotiator": "^0.6.3", - "promise-retry": "^2.0.1", - "socks-proxy-agent": "^7.0.0", - "ssri": "^9.0.0" - } - }, - "map-obj": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.3.0.tgz", - "integrity": "sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==", - "dev": true - }, - "meow": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/meow/-/meow-9.0.0.tgz", - "integrity": "sha512-+obSblOQmRhcyBt62furQqRAQpNyWXo8BuQ5bN7dG8wmwQ+vwHKp/rCFD4CrTP8CsDQD1sjoZ94K417XEUk8IQ==", - "dev": true, - "requires": { - "@types/minimist": "^1.2.0", - "camelcase-keys": "^6.2.2", - "decamelize": "^1.2.0", - "decamelize-keys": "^1.1.0", - "hard-rejection": "^2.1.0", - "minimist-options": "4.1.0", - "normalize-package-data": "^3.0.0", - "read-pkg-up": "^7.0.1", - "redent": "^3.0.0", - "trim-newlines": "^3.0.0", - "type-fest": "^0.18.0", - "yargs-parser": "^20.2.3" - } - }, - "min-indent": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", - "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", - "dev": true - }, - "minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minimist-options": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-4.1.0.tgz", - "integrity": "sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==", - "dev": true, - "requires": { - "arrify": "^1.0.1", - "is-plain-obj": "^1.1.0", - "kind-of": "^6.0.3" - } - }, - "minipass": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.4.tgz", - "integrity": "sha512-I9WPbWHCGu8W+6k1ZiGpPu0GkoKBeorkfKNuAFBNS1HNFJvke82sxvI5bzcCNpWPorkOO5QQ+zomzzwRxejXiw==", - "dev": true, - "requires": { - "yallist": "^4.0.0" - } - }, - "minipass-collect": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz", - "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", - "dev": true, - "requires": { - "minipass": "^3.0.0" - } - }, - "minipass-fetch": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-2.1.2.tgz", - "integrity": "sha512-LT49Zi2/WMROHYoqGgdlQIZh8mLPZmOrN2NdJjMXxYe4nkN6FUyuPuOAOedNJDrx0IRGg9+4guZewtp8hE6TxA==", - "dev": true, - "requires": { - "encoding": "^0.1.13", - "minipass": "^3.1.6", - "minipass-sized": "^1.0.3", - "minizlib": "^2.1.2" - } - }, - "minipass-flush": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", - "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", - "dev": true, - "requires": { - "minipass": "^3.0.0" - } - }, - "minipass-pipeline": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", - "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", - "dev": true, - "requires": { - "minipass": "^3.0.0" - } - }, - "minipass-sized": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz", - "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==", - "dev": true, - "requires": { - "minipass": "^3.0.0" - } - }, - "minizlib": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", - "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", - "dev": true, - "requires": { - "minipass": "^3.0.0", - "yallist": "^4.0.0" - } - }, - "mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "nan": { - "version": "2.17.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.17.0.tgz", - "integrity": "sha512-2ZTgtl0nJsO0KQCjEpxcIr5D+Yv90plTitZt9JBfQvVJDS5seMl3FOvsh3+9CoYWXf/1l5OaZzzF6nDm4cagaQ==", - "dev": true - }, - "negotiator": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", - "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", - "dev": true - }, - "node-gyp": { - "version": "8.4.1", - "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-8.4.1.tgz", - "integrity": "sha512-olTJRgUtAb/hOXG0E93wZDs5YiJlgbXxTwQAFHyNlRsXQnYzUaF2aGgujZbw+hR8aF4ZG/rST57bWMWD16jr9w==", - "dev": true, - "requires": { - "env-paths": "^2.2.0", - "glob": "^7.1.4", - "graceful-fs": "^4.2.6", - "make-fetch-happen": "^9.1.0", - "nopt": "^5.0.0", - "npmlog": "^6.0.0", - "rimraf": "^3.0.2", - "semver": "^7.3.5", - "tar": "^6.1.2", - "which": "^2.0.2" - }, - "dependencies": { - "@npmcli/fs": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-1.1.1.tgz", - "integrity": "sha512-8KG5RD0GVP4ydEzRn/I4BNDuxDtqVbOdm8675T49OIG/NGhaK0pjPX7ZcDlvKYbA+ulvVK3ztfcF4uBdOxuJbQ==", - "dev": true, - "requires": { - "@gar/promisify": "^1.0.1", - "semver": "^7.3.5" - } - }, - "@npmcli/move-file": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-1.1.2.tgz", - "integrity": "sha512-1SUf/Cg2GzGDyaf15aR9St9TWlb+XvbZXWpDx8YKs7MLzMH/BCeopv+y9vzrzgkfykCGuWOlSu3mZhj2+FQcrg==", - "dev": true, - "requires": { - "mkdirp": "^1.0.4", - "rimraf": "^3.0.2" - } - }, - "@tootallnate/once": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", - "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", - "dev": true - }, - "cacache": { - "version": "15.3.0", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-15.3.0.tgz", - "integrity": "sha512-VVdYzXEn+cnbXpFgWs5hTT7OScegHVmLhJIR8Ufqk3iFD6A6j5iSX1KuBTfNEv4tdJWE2PzA6IVFtcLC7fN9wQ==", - "dev": true, - "requires": { - "@npmcli/fs": "^1.0.0", - "@npmcli/move-file": "^1.0.1", - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "glob": "^7.1.4", - "infer-owner": "^1.0.4", - "lru-cache": "^6.0.0", - "minipass": "^3.1.1", - "minipass-collect": "^1.0.2", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.2", - "mkdirp": "^1.0.3", - "p-map": "^4.0.0", - "promise-inflight": "^1.0.1", - "rimraf": "^3.0.2", - "ssri": "^8.0.1", - "tar": "^6.0.2", - "unique-filename": "^1.1.1" - } - }, - "http-proxy-agent": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", - "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", - "dev": true, - "requires": { - "@tootallnate/once": "1", - "agent-base": "6", - "debug": "4" - } - }, - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "requires": { - "yallist": "^4.0.0" - } - }, - "make-fetch-happen": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-9.1.0.tgz", - "integrity": "sha512-+zopwDy7DNknmwPQplem5lAZX/eCOzSvSNNcSKm5eVwTkOBzoktEfXsa9L23J/GIRhxRsaxzkPEhrJEpE2F4Gg==", - "dev": true, - "requires": { - "agentkeepalive": "^4.1.3", - "cacache": "^15.2.0", - "http-cache-semantics": "^4.1.0", - "http-proxy-agent": "^4.0.1", - "https-proxy-agent": "^5.0.0", - "is-lambda": "^1.0.1", - "lru-cache": "^6.0.0", - "minipass": "^3.1.3", - "minipass-collect": "^1.0.2", - "minipass-fetch": "^1.3.2", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "negotiator": "^0.6.2", - "promise-retry": "^2.0.1", - "socks-proxy-agent": "^6.0.0", - "ssri": "^8.0.0" - } + "postcss-normalize-url": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-url/-/postcss-normalize-url-6.0.0.tgz", + "integrity": "sha512-98mvh2QzIPbb02YDIrYvAg4OUzGH7s1ZgHlD3fIdTHLgPLRpv1ZTKJDnSAKr4Rt21ZQFzwhGMXxpXlfrUBKFHw==", + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-normalize-whitespace": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-whitespace/-/postcss-normalize-whitespace-6.0.0.tgz", + "integrity": "sha512-7cfE1AyLiK0+ZBG6FmLziJzqQCpTQY+8XjMhMAz8WSBSCsCNNUKujgIgjCAmDT3cJ+3zjTXFkoD15ZPsckArVw==", + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-ordered-values": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/postcss-ordered-values/-/postcss-ordered-values-6.0.0.tgz", + "integrity": "sha512-K36XzUDpvfG/nWkjs6d1hRBydeIxGpKS2+n+ywlKPzx1nMYDYpoGbcjhj5AwVYJK1qV2/SDoDEnHzlPD6s3nMg==", + "requires": { + "cssnano-utils": "^4.0.0", + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-reduce-idents": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/postcss-reduce-idents/-/postcss-reduce-idents-2.4.0.tgz", + "integrity": "sha512-0+Ow9e8JLtffjumJJFPqvN4qAvokVbdQPnijUDSOX8tfTwrILLP4ETvrZcXZxAtpFLh/U0c+q8oRMJLr1Kiu4w==", + "requires": { + "postcss": "^5.0.4", + "postcss-value-parser": "^3.0.2" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==" }, - "minipass-fetch": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-1.4.1.tgz", - "integrity": "sha512-CGH1eblLq26Y15+Azk7ey4xh0J/XfJfrCox5LDJiKqI2Q2iwOLOKrlmIaODiSQS8d18jalF6y2K2ePUm0CmShw==", - "dev": true, - "requires": { - "encoding": "^0.1.12", - "minipass": "^3.1.0", - "minipass-sized": "^1.0.3", - "minizlib": "^2.0.0" - } + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==" }, - "socks-proxy-agent": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-6.2.1.tgz", - "integrity": "sha512-a6KW9G+6B3nWZ1yB8G7pJwL3ggLy1uTzKAgCb7ttblwqdz9fMGJUuTy3uFzEP48FAs9FLILlmzDlE2JJhVQaXQ==", - "dev": true, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==", "requires": { - "agent-base": "^6.0.2", - "debug": "^4.3.3", - "socks": "^2.6.2" + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + }, + "dependencies": { + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==" + } } }, - "ssri": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.1.tgz", - "integrity": "sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ==", - "dev": true, + "has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha512-DyYHfIYwAJmjAjSSPKANxI8bFY9YtFrgkAfinBojQ8YJTOuOuav64tMUJv584SES4xl74PmuaevIyaLESHdTAA==" + }, + "postcss": { + "version": "5.2.18", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", + "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", "requires": { - "minipass": "^3.1.1" + "chalk": "^1.1.3", + "js-base64": "^2.1.9", + "source-map": "^0.5.6", + "supports-color": "^3.2.3" } }, - "unique-filename": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", - "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", - "dev": true, + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==" + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==" + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==", "requires": { - "unique-slug": "^2.0.0" + "ansi-regex": "^2.0.0" } }, - "unique-slug": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz", - "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==", - "dev": true, + "supports-color": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha512-Jds2VIYDrlp5ui7t8abHN2bjAu4LV/q4N2KivFPpGH0lrka0BMq/33AmECUXlKPcHigkNaqfXRENFju+rlcy+A==", "requires": { - "imurmurhash": "^0.1.4" + "has-flag": "^1.0.0" } } } }, - "node-sass": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/node-sass/-/node-sass-8.0.0.tgz", - "integrity": "sha512-jPzqCF2/e6JXw6r3VxfIqYc8tKQdkj5Z/BDATYyG6FL6b/LuYBNFGFVhus0mthcWifHm/JzBpKAd+3eXsWeK/A==", - "dev": true, - "requires": { - "async-foreach": "^0.1.3", - "chalk": "^4.1.2", - "cross-spawn": "^7.0.3", - "gaze": "^1.0.0", - "get-stdin": "^4.0.1", - "glob": "^7.0.3", - "lodash": "^4.17.15", - "make-fetch-happen": "^10.0.4", - "meow": "^9.0.0", - "nan": "^2.17.0", - "node-gyp": "^8.4.1", - "sass-graph": "^4.0.1", - "stdout-stream": "^1.4.0", - "true-case-path": "^2.2.1" - } - }, - "nopt": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", - "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", - "dev": true, - "requires": { - "abbrev": "1" - } - }, - "normalize-package-data": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.3.tgz", - "integrity": "sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==", - "dev": true, + "postcss-reduce-initial": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-6.0.0.tgz", + "integrity": "sha512-s2UOnidpVuXu6JiiI5U+fV2jamAw5YNA9Fdi/GRK0zLDLCfXmSGqQtzpUPtfN66RtCbb9fFHoyZdQaxOB3WxVA==", "requires": { - "hosted-git-info": "^4.0.1", - "is-core-module": "^2.5.0", - "semver": "^7.3.4", - "validate-npm-package-license": "^3.0.1" + "browserslist": "^4.21.4", + "caniuse-api": "^3.0.0" } }, - "npmlog": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-6.0.2.tgz", - "integrity": "sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==", - "dev": true, + "postcss-reduce-transforms": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/postcss-reduce-transforms/-/postcss-reduce-transforms-6.0.0.tgz", + "integrity": "sha512-FQ9f6xM1homnuy1wLe9lP1wujzxnwt1EwiigtWwuyf8FsqqXUDUp2Ulxf9A5yjlUOTdCJO6lonYjg1mgqIIi2w==", "requires": { - "are-we-there-yet": "^3.0.0", - "console-control-strings": "^1.1.0", - "gauge": "^4.0.3", - "set-blocking": "^2.0.0" + "postcss-value-parser": "^4.2.0" } }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dev": true, + "postcss-selector-parser": { + "version": "6.0.13", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.13.tgz", + "integrity": "sha512-EaV1Gl4mUEV4ddhDnv/xtj7sxwrwxdetHdWUGnT4VJQf+4d05v6lHYZr8N573k5Z0BViss7BDhfWtKS3+sfAqQ==", "requires": { - "wrappy": "1" + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" } }, - "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, + "postcss-svgo": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-6.0.0.tgz", + "integrity": "sha512-r9zvj/wGAoAIodn84dR/kFqwhINp5YsJkLoujybWG59grR/IHx+uQ2Zo+IcOwM0jskfYX3R0mo+1Kip1VSNcvw==", "requires": { - "p-try": "^2.0.0" + "postcss-value-parser": "^4.2.0", + "svgo": "^3.0.2" } }, - "p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, + "postcss-unique-selectors": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-6.0.0.tgz", + "integrity": "sha512-EPQzpZNxOxP7777t73RQpZE5e9TrnCrkvp7AH7a0l89JmZiPnS82y216JowHXwpBCQitfyxrof9TK3rYbi7/Yw==", "requires": { - "p-limit": "^2.2.0" + "postcss-selector-parser": "^6.0.5" } }, - "p-map": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", - "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", - "dev": true, - "requires": { - "aggregate-error": "^3.0.0" - } + "postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" }, - "p-try": { + "postcss-zindex": { "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true - }, - "parse-json": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", - "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", - "dev": true, + "resolved": "https://registry.npmjs.org/postcss-zindex/-/postcss-zindex-2.2.0.tgz", + "integrity": "sha512-uhRZ2hRgj0lorxm9cr62B01YzpUe63h0RXMXQ4gWW3oa2rpJh+FJAiEAytaFCPU/VgaBS+uW2SJ1XKyDNz1h4w==", "requires": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-even-better-errors": "^2.3.0", - "lines-and-columns": "^1.1.6" + "has": "^1.0.1", + "postcss": "^5.0.4", + "uniqs": "^2.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==" + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==" + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==", + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + }, + "dependencies": { + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==" + } + } + }, + "has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha512-DyYHfIYwAJmjAjSSPKANxI8bFY9YtFrgkAfinBojQ8YJTOuOuav64tMUJv584SES4xl74PmuaevIyaLESHdTAA==" + }, + "postcss": { + "version": "5.2.18", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", + "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", + "requires": { + "chalk": "^1.1.3", + "js-base64": "^2.1.9", + "source-map": "^0.5.6", + "supports-color": "^3.2.3" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==" + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==", + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "supports-color": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha512-Jds2VIYDrlp5ui7t8abHN2bjAu4LV/q4N2KivFPpGH0lrka0BMq/33AmECUXlKPcHigkNaqfXRENFju+rlcy+A==", + "requires": { + "has-flag": "^1.0.0" + } + } } }, - "path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "dev": true - }, - "path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true - }, - "path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true + "prepend-http": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz", + "integrity": "sha512-PhmXi5XmoyKw1Un4E+opM2KcsJInDvKyuOumcjjw3waw86ZNjHwVUOOWLc4bCzLdcKNaWBH9e99sbWzDQsVaYg==" }, "process-nextick-args": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", - "dev": true + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" }, "promise-inflight": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", - "integrity": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==", - "dev": true + "integrity": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==" }, "promise-retry": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", - "dev": true, "requires": { "err-code": "^2.0.2", "retry": "^0.12.0" } }, + "q": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", + "integrity": "sha512-kV/CThkXo6xyFEZUugw/+pIOywXcDbFYgSct5cT3gqlbkBE1SJdwy6UQoZvodiWF/ckQLZyDE/Bu1M6gVu5lVw==" + }, + "query-string": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/query-string/-/query-string-4.3.4.tgz", + "integrity": "sha512-O2XLNDBIg1DnTOa+2XrIwSiXEV8h2KImXUnjhhn2+UsvZ+Es2uyd5CCRTNQlDGbzUQOW3aYCBx9rVA6dzsiY7Q==", + "requires": { + "object-assign": "^4.1.0", + "strict-uri-encode": "^1.0.0" + } + }, "quick-lru": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-4.0.1.tgz", - "integrity": "sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==", - "dev": true + "integrity": "sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==" + }, + "read-file-stdin": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/read-file-stdin/-/read-file-stdin-0.2.1.tgz", + "integrity": "sha512-dAqysQ4kfj9m5aejZOPr+aRGXZJXdLkMOLZ3BXMwMBQHiO+aylGBFJPh88AYPQrOf+D43F4Uc2oUIW9kBlItLA==", + "requires": { + "gather-stream": "^1.0.0" + } }, "read-pkg": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", - "dev": true, "requires": { "@types/normalize-package-data": "^2.4.0", "normalize-package-data": "^2.5.0", @@ -3687,14 +2856,12 @@ "hosted-git-info": { "version": "2.8.9", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", - "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", - "dev": true + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==" }, "normalize-package-data": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", - "dev": true, "requires": { "hosted-git-info": "^2.1.4", "resolve": "^1.10.0", @@ -3703,16 +2870,14 @@ } }, "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==" }, "type-fest": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", - "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", - "dev": true + "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==" } } }, @@ -3720,7 +2885,6 @@ "version": "7.0.1", "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", - "dev": true, "requires": { "find-up": "^4.1.0", "read-pkg": "^5.2.0", @@ -3730,8 +2894,7 @@ "type-fest": { "version": "0.8.1", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", - "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", - "dev": true + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==" } } }, @@ -3739,7 +2902,6 @@ "version": "3.6.0", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "dev": true, "requires": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", @@ -3750,23 +2912,45 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", - "dev": true, "requires": { "indent-string": "^4.0.0", "strip-indent": "^3.0.0" } }, + "reduce-css-calc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/reduce-css-calc/-/reduce-css-calc-1.3.0.tgz", + "integrity": "sha512-0dVfwYVOlf/LBA2ec4OwQ6p3X9mYxn/wOl2xTcLwjnPYrkgEfPx3VI4eGCH3rQLlPISG5v9I9bkZosKsNRTRKA==", + "requires": { + "balanced-match": "^0.4.2", + "math-expression-evaluator": "^1.2.14", + "reduce-function-call": "^1.0.1" + }, + "dependencies": { + "balanced-match": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz", + "integrity": "sha512-STw03mQKnGUYtoNjmowo4F2cRmIIxYEGiMsjjwla/u5P1lxadj/05WkNaFjNiKTgJkj8KiXbgAiRTmcQRwQNtg==" + } + } + }, + "reduce-function-call": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/reduce-function-call/-/reduce-function-call-1.0.3.tgz", + "integrity": "sha512-Hl/tuV2VDgWgCSEeWMLwxLZqX7OK59eU1guxXsRKTAyeYimivsKdtcV4fu3r710tpG5GmDKDhQ0HSZLExnNmyQ==", + "requires": { + "balanced-match": "^1.0.0" + } + }, "require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", - "dev": true + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==" }, "resolve": { "version": "1.22.1", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", - "dev": true, "requires": { "is-core-module": "^2.9.0", "path-parse": "^1.0.7", @@ -3776,14 +2960,12 @@ "retry": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", - "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", - "dev": true + "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==" }, "rimraf": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, "requires": { "glob": "^7.1.3" } @@ -3791,21 +2973,18 @@ "safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" }, "safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true, "optional": true }, "sass-graph": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/sass-graph/-/sass-graph-4.0.1.tgz", "integrity": "sha512-5YCfmGBmxoIRYHnKK2AKzrAkCoQ8ozO+iumT8K4tXJXRVCPf+7s1/9KxTSW3Rbvf+7Y7b4FR3mWyLnQr3PHocA==", - "dev": true, "requires": { "glob": "^7.0.0", "lodash": "^4.17.11", @@ -3813,21 +2992,24 @@ "yargs": "^17.2.1" } }, + "sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" + }, "scss-tokenizer": { "version": "0.4.3", "resolved": "https://registry.npmjs.org/scss-tokenizer/-/scss-tokenizer-0.4.3.tgz", "integrity": "sha512-raKLgf1LI5QMQnG+RxHz6oK0sL3x3I4FN2UDLqgLOGO8hodECNnNh5BXn7fAyBxrA8zVzdQizQ6XjNJQ+uBwMw==", - "dev": true, "requires": { "js-base64": "^2.4.9", "source-map": "^0.7.3" } }, "semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", - "dev": true, + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "requires": { "lru-cache": "^6.0.0" }, @@ -3836,7 +3018,6 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, "requires": { "yallist": "^4.0.0" } @@ -3846,14 +3027,12 @@ "set-blocking": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", - "dev": true + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==" }, "shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, "requires": { "shebang-regex": "^3.0.0" } @@ -3861,26 +3040,22 @@ "shebang-regex": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==" }, "signal-exit": { "version": "3.0.7", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" }, "smart-buffer": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", - "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", - "dev": true + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==" }, "socks": { "version": "2.7.1", "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.1.tgz", "integrity": "sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==", - "dev": true, "requires": { "ip": "^2.0.0", "smart-buffer": "^4.2.0" @@ -3890,24 +3065,50 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-7.0.0.tgz", "integrity": "sha512-Fgl0YPZ902wEsAyiQ+idGd1A7rSFx/ayC1CQVMw5P+EQx2V0SgpGtf6OKFhVjPflPUl9YMmEOnmfjCdMUsygww==", - "dev": true, "requires": { "agent-base": "^6.0.2", "debug": "^4.3.3", "socks": "^2.6.2" } }, + "sort-keys": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-1.1.2.tgz", + "integrity": "sha512-vzn8aSqKgytVik0iwdBEi+zevbTYZogewTUM6dtpmGwEcdzbub/TX4bCzRhebDCRC3QzXgJsLRKB2V/Oof7HXg==", + "requires": { + "is-plain-obj": "^1.0.0" + } + }, "source-map": { "version": "0.7.4", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", - "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", - "dev": true + "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==" + }, + "source-map-js": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", + "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==" + }, + "source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } }, "spdx-correct": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", - "dev": true, "requires": { "spdx-expression-parse": "^3.0.0", "spdx-license-ids": "^3.0.0" @@ -3916,14 +3117,12 @@ "spdx-exceptions": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", - "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", - "dev": true + "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==" }, "spdx-expression-parse": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", - "dev": true, "requires": { "spdx-exceptions": "^2.1.0", "spdx-license-ids": "^3.0.0" @@ -3932,14 +3131,17 @@ "spdx-license-ids": { "version": "3.0.12", "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.12.tgz", - "integrity": "sha512-rr+VVSXtRhO4OHbXUiAF7xW3Bo9DuuF6C5jH+q/x15j2jniycgKbxU09Hr0WqlSLUs4i4ltHGXqTe7VHclYWyA==", - "dev": true + "integrity": "sha512-rr+VVSXtRhO4OHbXUiAF7xW3Bo9DuuF6C5jH+q/x15j2jniycgKbxU09Hr0WqlSLUs4i4ltHGXqTe7VHclYWyA==" + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==" }, "ssri": { "version": "9.0.1", "resolved": "https://registry.npmjs.org/ssri/-/ssri-9.0.1.tgz", "integrity": "sha512-o57Wcn66jMQvfHG1FlYbWeZWW/dHZhJXjpIcTfXldXEk5nz5lStPo3mK0OJQfGR3RbZUlbISexbljkJzuEj/8Q==", - "dev": true, "requires": { "minipass": "^3.1.1" } @@ -3948,7 +3150,6 @@ "version": "1.4.1", "resolved": "https://registry.npmjs.org/stdout-stream/-/stdout-stream-1.4.1.tgz", "integrity": "sha512-j4emi03KXqJWcIeF8eIXkjMFN1Cmb8gUlDYGeBALLPo5qdyTfA9bOtl8m33lRoC+vFMkP3gl0WsDr6+gzxbbTA==", - "dev": true, "requires": { "readable-stream": "^2.0.1" }, @@ -3957,7 +3158,6 @@ "version": "2.3.7", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, "requires": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", @@ -3971,45 +3171,45 @@ "safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" }, "string_decoder": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, "requires": { "safe-buffer": "~5.1.0" } } } }, - "string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dev": true, - "requires": { - "safe-buffer": "~5.2.0" - } + "strict-uri-encode": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz", + "integrity": "sha512-R3f198pcvnB+5IpnBlRkphuE9n46WyVl8I39W/ZUTZLz4nqSP/oLYUrcnJrw462Ds8he4YKMov2efsTIw1BDGQ==" }, "string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, "requires": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, + "string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "requires": { + "safe-buffer": "~5.2.0" + } + }, "strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, "requires": { "ansi-regex": "^5.0.1" } @@ -4018,16 +3218,23 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", - "dev": true, "requires": { "min-indent": "^1.0.0" } }, + "stylehacks": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-6.0.0.tgz", + "integrity": "sha512-+UT589qhHPwz6mTlCLSt/vMNTJx8dopeJlZAlBMJPWA3ORqu6wmQY7FBXf+qD+FsqoBJODyqNxOUP3jdntFRdw==", + "requires": { + "browserslist": "^4.21.4", + "postcss-selector-parser": "^6.0.4" + } + }, "supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, "requires": { "has-flag": "^4.0.0" } @@ -4035,14 +3242,25 @@ "supports-preserve-symlinks-flag": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "dev": true + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==" + }, + "svgo": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/svgo/-/svgo-3.0.2.tgz", + "integrity": "sha512-Z706C1U2pb1+JGP48fbazf3KxHrWOsLme6Rv7imFBn5EnuanDW1GPaA/P1/dvObE670JDePC3mnj0k0B7P0jjQ==", + "requires": { + "@trysound/sax": "0.2.0", + "commander": "^7.2.0", + "css-select": "^5.1.0", + "css-tree": "^2.2.1", + "csso": "^5.0.5", + "picocolors": "^1.0.0" + } }, "tar": { "version": "6.1.12", "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.12.tgz", "integrity": "sha512-jU4TdemS31uABHd+Lt5WEYJuzn+TJTCBLljvIAHZOz6M9Os5pJ4dD+vRFLxPa/n3T0iEFzpi+0x1UfuDZYbRMw==", - "dev": true, "requires": { "chownr": "^2.0.0", "fs-minipass": "^2.0.0", @@ -4052,29 +3270,53 @@ "yallist": "^4.0.0" } }, + "terser": { + "version": "5.24.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.24.0.tgz", + "integrity": "sha512-ZpGR4Hy3+wBEzVEnHvstMvqpD/nABNelQn/z2r0fjVWGQsN3bpOLzQlqDxmb4CDZnXq5lpjnQ+mHQLAOpfM5iw==", + "requires": { + "@jridgewell/source-map": "^0.3.3", + "acorn": "^8.8.2", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + }, + "dependencies": { + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" + } + } + }, "trim-newlines": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-3.0.1.tgz", - "integrity": "sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==", - "dev": true + "integrity": "sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==" }, "true-case-path": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/true-case-path/-/true-case-path-2.2.1.tgz", - "integrity": "sha512-0z3j8R7MCjy10kc/g+qg7Ln3alJTodw9aDuVWZa3uiWqfuBMKeAeP2ocWcxoyM3D73yz3Jt/Pu4qPr4wHSdB/Q==", - "dev": true + "integrity": "sha512-0z3j8R7MCjy10kc/g+qg7Ln3alJTodw9aDuVWZa3uiWqfuBMKeAeP2ocWcxoyM3D73yz3Jt/Pu4qPr4wHSdB/Q==" }, "type-fest": { "version": "0.18.1", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.18.1.tgz", - "integrity": "sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==", - "dev": true + "integrity": "sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==" + }, + "uniq": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/uniq/-/uniq-1.0.1.tgz", + "integrity": "sha512-Gw+zz50YNKPDKXs+9d+aKAjVwpjNwqzvNpLigIruT4HA9lMZNdMqs9x07kKHB/L9WRzqp4+DlTU5s4wG2esdoA==" + }, + "uniqs": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/uniqs/-/uniqs-2.0.0.tgz", + "integrity": "sha512-mZdDpf3vBV5Efh29kMw5tXoup/buMgxLzOt/XKFKcVmi+15ManNQWr6HfZ2aiZTYlYixbdNJ0KFmIZIv52tHSQ==" }, "unique-filename": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-2.0.1.tgz", "integrity": "sha512-ODWHtkkdx3IAR+veKxFV+VBkUMcN+FaqzUUd7IZzt+0zhDZFPFxhlqwPF3YQvMHx1TD0tdgYl+kuPnJ8E6ql7A==", - "dev": true, "requires": { "unique-slug": "^3.0.0" } @@ -4083,32 +3325,47 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-3.0.0.tgz", "integrity": "sha512-8EyMynh679x/0gqE9fT9oilG+qEt+ibFyqjuVTsZn1+CMxH+XLlpvr2UZx4nVcCwTpx81nICr2JQFkM+HPLq4w==", - "dev": true, "requires": { "imurmurhash": "^0.1.4" } }, + "update-browserslist-db": { + "version": "1.0.13", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", + "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", + "requires": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0" + } + }, "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", - "dev": true + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" }, "validate-npm-package-license": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", - "dev": true, "requires": { "spdx-correct": "^3.0.0", "spdx-expression-parse": "^3.0.0" } }, + "vendors": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/vendors/-/vendors-1.0.4.tgz", + "integrity": "sha512-/juG65kTL4Cy2su4P8HjtkTxk6VmJDiOPBufWniqQ6wknac6jNiXS9vU+hO3wgusiyqWlzTbVHi0dyJqRONg3w==" + }, + "whet.extend": { + "version": "0.9.9", + "resolved": "https://registry.npmjs.org/whet.extend/-/whet.extend-0.9.9.tgz", + "integrity": "sha512-mmIPAft2vTgEILgPeZFqE/wWh24SEsR/k+N9fJ3Jxrz44iDFy9aemCxdksfURSHYFCLmvs/d/7Iso5XjPpNfrA==" + }, "which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, "requires": { "isexe": "^2.0.0" } @@ -4117,7 +3374,6 @@ "version": "1.1.5", "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", - "dev": true, "requires": { "string-width": "^1.0.2 || 2 || 3 || 4" } @@ -4126,7 +3382,6 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, "requires": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", @@ -4136,26 +3391,27 @@ "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + }, + "write-file-stdout": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/write-file-stdout/-/write-file-stdout-0.0.2.tgz", + "integrity": "sha512-KofbSPeePSre3soWCMaqcWHVZy9t/rbJaEMa2h19cupODsvc4eh7390Se1TjzZEL77rS+D6dznu0TLXyCbR+sw==" }, "y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==" }, "yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, "yargs": { "version": "17.6.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.6.2.tgz", "integrity": "sha512-1/9UrdHjDZc0eOU0HxOHoS78C69UD3JRMvzlJ7S79S2nTaWRA/whGCTV8o9e/N/1Va9YIV7Q4sOxD8VV4pCWOw==", - "dev": true, "requires": { "cliui": "^8.0.1", "escalade": "^3.1.1", @@ -4169,16 +3425,14 @@ "yargs-parser": { "version": "21.1.1", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "dev": true + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==" } } }, "yargs-parser": { "version": "20.2.9", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", - "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", - "dev": true + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==" } } } diff --git a/web-interface/theme/package.json b/web-interface/theme/package.json index d4a4cc6..051c21e 100644 --- a/web-interface/theme/package.json +++ b/web-interface/theme/package.json @@ -10,8 +10,12 @@ }, "author": "", "license": "ISC", - "devDependencies": { + "dependencies": { "bulma": "^0.9.4", - "node-sass": "^8.0.0" + "cssnano": "^6.0.1", + "node-sass": "^8.0.0", + "postcss": "^8.4.31", + "cssnano-cli": "^1.0.5", + "terser": "^5.24.0" } } From a93525b5e54e6121a82e6a509316eecf1e6def7d Mon Sep 17 00:00:00 2001 From: karelv Date: Fri, 3 Nov 2023 11:32:10 -0700 Subject: [PATCH 042/112] add doc + implement ch_write --- i2c-stick-py/melexis/i2c_stick/I2CStick.py | 67 +++++++++++++++++++--- 1 file changed, 59 insertions(+), 8 deletions(-) diff --git a/i2c-stick-py/melexis/i2c_stick/I2CStick.py b/i2c-stick-py/melexis/i2c_stick/I2CStick.py index 9f0b318..9d0374b 100644 --- a/i2c-stick-py/melexis/i2c_stick/I2CStick.py +++ b/i2c-stick-py/melexis/i2c_stick/I2CStick.py @@ -10,6 +10,7 @@ def __init__(self, port): self.open(port) def open(self, port): + """Open the PC connection to the I2C-stick""" self.ser = serial.Serial(port, 921600, timeout=5) self.ser.write(b'!') time.sleep(0.2) @@ -18,11 +19,13 @@ def open(self, port): time.sleep(0.1) def close(self): + """Close the PC connection to the I2C-stick""" if self.ser is not None: self.ser.close() self.ser = None def read_continuous_message(self): + """Read the message from continuous mode""" line = self.ser.readline().decode('utf-8').rstrip() # read a '\n' terminated line if line.startswith("@"): values = line.split(":") @@ -32,6 +35,7 @@ def read_continuous_message(self): return None def stop_continuous_mode(self): + """Stop continuous mode""" self.ser.write(b'!') time.sleep(0.1) self.ser.flushInput() @@ -39,6 +43,7 @@ def stop_continuous_mode(self): time.sleep(0.1) def trigger_continuous_mode(self): + """Start continuous mode""" self.ser.write(b'!') time.sleep(0.1) self.ser.flushInput() @@ -47,10 +52,12 @@ def trigger_continuous_mode(self): self.ser.readline().decode('utf-8').rstrip() # read a '\n' terminated line def run_cmd(self, cmd): + """Generic run command""" self.ser.write(bytes(cmd + "\n", 'utf-8')) return self.ser.readline().decode('utf-8').rstrip() # read a '\n' terminated line def mlx(self): + """MeLeXis test command""" result = [] timeout_old = self.ser.timeout self.ser.timeout = 0.25 @@ -72,13 +79,18 @@ def mlx(self): return result def fv(self): + """Firmware Version command""" a = self.run_cmd("fv") a = a.split(":") if a[0] != "fv": return None return a[1] + def firmware_version(self): + return self.fv() + def bi(self): + """get Board Information""" a = self.run_cmd("bi") a = a.split(":") if a[0] != "bi": @@ -95,6 +107,7 @@ def i2c_addressed_read(self, sa): return None def ch(self): + """get Configure Host command""" result = {} timeout_old = self.ser.timeout self.ser.timeout = 0.25 @@ -139,10 +152,43 @@ def ch(self): return result - def ch_write(self): - return None + def ch_write(self, item, value): + """set the Configuration of the Host(I2C-stick)""" + """ + +ch:I2C_FREQ=F100k + 2023/11/01 17:16:01.613 -> - +ch:I2C_FREQ=F400k + 2023/11/01 17:16:01.613 -> - +ch:I2C_FREQ=F1M + 2023/11/01 17:16:01.613 -> - +ch:I2C_FREQ=F50k + 2023/11/01 17:16:01.613 -> - +ch:I2C_FREQ=F20k + 2023/11/01 17:16:01.613 -> - +ch:I2C_FREQ=F10k + + """ + str_value = str(value) + if item == "I2C_FREQ": + items = { + 10000: 'F10k', + 20000: 'F20k', + 50000: 'F50k', + 100000: 'F100k', + 400000: 'F400k', + 1000000: 'F1M', + } + if value not in items.keys(): + return "value not valid" + str_value = items[value] + a = self.run_cmd("+ch:{}={}".format(item, str_value)) + a = a.split(":") + # +ch:OK [host-register] + # +ch:I2C_FREQ=F2M:ERROR: Invalid value + if a[0] != "+ch": + return "wrong command returned" + if a[1].startswith("OK"): + return + else: + return a[1] def scan(self): + """SCAN the i2c bus for slaves""" result = [] timeout_old = self.ser.timeout self.ser.timeout = 0.25 @@ -172,6 +218,7 @@ def scan(self): return result def ls(self): + """List Slaves which are previously found by scan command""" result = [] timeout_old = self.ser.timeout self.ser.timeout = 0.25 @@ -201,6 +248,7 @@ def ls(self): return result def dis(self, sa, disable=1): + """DISable a slave from continuous mode""" a = self.run_cmd("dis:{:02X}:{}".format(sa, disable)) a = a.split(":") if a[0] != "dis": @@ -213,13 +261,8 @@ def dis(self, sa, disable=1): 'disabled': int(a[2])} return result - def mv(self, sa): - self.ser.write('mv:{:02X}'.format(sa).encode() + b'\n') - line = self.ser.readline().decode('utf-8').rstrip() # read a '\n' terminated line - values = line.split(":")[-1] - return [float(value) for value in values.split(",")] - def sn(self, sa): + """read the Serial Number of the slave""" a = self.run_cmd("sn:{:02X}".format(sa)) a = a.split(":") if a[0] != "sn": @@ -229,6 +272,7 @@ def sn(self, sa): return a[2] def cs(self, sa): + """read the Configuration of the Slave""" result = {} timeout_old = self.ser.timeout self.ser.timeout = 0.25 @@ -298,6 +342,7 @@ def cs(self, sa): return result def cs_write(self, sa, item, value): + """write the Configuration of the Slave""" a = self.run_cmd("+cs:{:02X}:{}={}".format(sa, item, value)) a = a.split(":") # +cs:3A:MEAS_SELECT=OK [host&mlx-register]' @@ -311,6 +356,7 @@ def cs_write(self, sa, item, value): return a[2] def nd(self, sa): + """check if New Data is available for the slave""" a = self.run_cmd("nd:{:02X}".format(sa)) a = a.split(":") if a[0] != "nd": @@ -322,6 +368,7 @@ def nd(self, sa): return int(a[2]) def mr(self, sa, address, count): + """Memory Read from the slave""" a = self.run_cmd("mr:{:02X}:{:04X},{:04X}".format(sa, address, count)) a = a.split(":") if a[0] != "mr": @@ -350,6 +397,7 @@ def mr(self, sa, address, count): return result def mw(self, sa, address, data): + """Memory Write to the slave""" if type(data) is list: data_str = ",".join(["{:04X}".format(x) for x in data]) else: @@ -363,6 +411,7 @@ def mw(self, sa, address, data): return a[2] def mv(self, sa): + """Measure Values from slave sensor""" a = self.run_cmd("mv:{:02X}".format(sa)) a = a.split(":") if a[0] != "mv": @@ -375,6 +424,7 @@ def mv(self, sa): return result def raw(self, sa): + """measure RAW values from slave sensor""" a = self.run_cmd("raw:{:02X}".format(sa)) a = a.split(":") if a[0] != "raw": @@ -390,6 +440,7 @@ def raw(self, sa): return result def pwm(self, pin, pwm): + """set a PWM duty cycle on a pin of the I2C-stick""" a = self.run_cmd("pwm:{}:{}".format(pin, pwm)) return a From cc595d230e13554288fe834ea7a22c6bd7f9df78 Mon Sep 17 00:00:00 2001 From: karelv Date: Fri, 3 Nov 2023 16:58:03 -0700 Subject: [PATCH 043/112] add modal pop up box for displaying errors to the users. --- web-interface/index.jinja2.html | 16 +++ web-interface/interface.js | 112 +++++++++++++------- web-interface/theme/sass/melexis-bulma.scss | 7 ++ 3 files changed, 94 insertions(+), 41 deletions(-) diff --git a/web-interface/index.jinja2.html b/web-interface/index.jinja2.html index 5dfd7a6..7344a4e 100644 --- a/web-interface/index.jinja2.html +++ b/web-interface/index.jinja2.html @@ -276,6 +276,22 @@ + + diff --git a/web-interface/interface.js b/web-interface/interface.js index 5b52b42..7046287 100644 --- a/web-interface/interface.js +++ b/web-interface/interface.js @@ -79,8 +79,25 @@ $(window).resize(function() { set_spatial_chart_height(); }); - $(document).ready(function () { + $(".js-modal-trigger").click(function(){ + const modal = $(this).data('target'); + let target = $("#"+modal+'.modal'); + target.addClass('is-active'); + }); + + $('.modal-background, .modal-close, .modal-card-head .delete, .modal-card-foot .button').click(function(){ + $(this).closest('.modal').removeClass('is-active'); + }); + + $(document).on( "keydown", function(event) { + if (event.which == 27) + { // close any modal upon ESC-key press... + $(".modal").removeClass('is-active'); + } + }); + + $(".checkmark.default_off").prop('checked', false); // navbar main buttons-clicks @@ -124,20 +141,20 @@ $(document).ready(function () { function get_date_time() { - var now = new Date(); + var now = new Date(); var year = now.getFullYear(); - var month = now.getMonth()+1; + var month = now.getMonth()+1; var day = now.getDate(); var hour = now.getHours(); var minute = now.getMinutes(); - var second = now.getSeconds(); - var ms = now.getMilliseconds(); + var second = now.getSeconds(); + var ms = now.getMilliseconds(); if(month.toString().length == 1) { month = '0'+month; } if(day.toString().length == 1) { day = '0'+day; - } + } if(hour.toString().length == 1) { hour = '0'+hour; } @@ -146,14 +163,14 @@ function get_date_time() { } if(second.toString().length == 1) { second = '0'+second; - } + } if(ms.toString().length == 1) { ms = '00'+ms; - } + } if(ms.toString().length == 2) { ms = '0'+ms; - } - var dateTime = year+'/'+month+'/'+day+' '+hour+':'+minute+':'+second+'.'+ms; + } + var dateTime = year+'/'+month+'/'+day+' '+hour+':'+minute+':'+second+'.'+ms; return dateTime; } @@ -189,12 +206,12 @@ function hex_to_rgba(hex, a){ throw new Error('Bad Hex'); } -// img_dat is a imageData object, +// img_dat is a imageData object, // x,y are floats in the original coordinates // Returns the pixel colour at that point as an array of RGBA // Will copy last pixel's colour // https://stackoverflow.com/a/46249246/2491604 -function get_pixel_value(img_dat, x,y, result = []){ +function get_pixel_value(img_dat, x,y, result = []){ let i; // clamp and floor coordinate const ix1 = (x < 0 ? 0 : x >= img_dat.width ? img_dat.width - 1 : x)| 0; @@ -202,7 +219,7 @@ function get_pixel_value(img_dat, x,y, result = []){ // get next pixel pos const ix2 = ix1 === img_dat.width -1 ? ix1 : ix1 + 1; const iy2 = iy1 === img_dat.height -1 ? iy1 : iy1 + 1; - // get interpolation position + // get interpolation position const xpos = x % 1; const ypos = y % 1; // get pixel index @@ -235,7 +252,7 @@ function sent_command(command) { const sent_event = new CustomEvent('sent', { detail: command }); div = document.querySelector('#sent_data'); - div.dispatchEvent(sent_event); + div.dispatchEvent(sent_event); } @@ -257,7 +274,7 @@ $(document).ready(function () { if (!("serial" in navigator)) { // The Web Serial API is NOT supported. - $('button').prop('disabled', true); // disable all buttons! + $('button').not('.keep').prop('disabled', true); // disable all buttons! $("#serial_terminal").append('
==> This page uses "Web Serial API".

'); $("#serial_terminal").append('
https://developer.mozilla.org/en-US/docs/Web/API/Web_Serial_API

'); $("#serial_terminal").append('
 

'); @@ -279,7 +296,7 @@ $(document).ready(function () { div = document.querySelector('#receive_data'); // show receiving data in terminal... - div.addEventListener('receive', (e) => { + div.addEventListener('receive', (e) => { var value_str = dec.decode(e.detail).replaceAll('\r', ''); let dt = get_date_time(); if (!($("#chk_add_datetime").is(":checked"))) @@ -335,7 +352,7 @@ $(document).ready(function () { }, false); // listener to generate recieve_line events. - div.addEventListener('receive', (e) => { + div.addEventListener('receive', (e) => { var value_str = dec.decode(e.detail); value_str = value_str.replaceAll('\r', ''); @@ -371,7 +388,7 @@ $(document).ready(function () { }); // listener to update the chart - div.addEventListener('receive_line', (e) => { + div.addEventListener('receive_line', (e) => { if ($("#chk_transient_enable").is(":checked")) { let line = e.detail; @@ -453,7 +470,7 @@ $(document).ready(function () { data: [], backgroundColor: hex_to_rgba(color_palette[trace_i%color_palette.length], 0.2), borderColor: hex_to_rgba(color_palette[trace_i%color_palette.length], 1), - borderWidth: 1, + borderWidth: 1, }; connected_slaves[sa]['transient_chart']['trace_i'].push(trace_i); transient_chart.data.datasets.push(dataset); @@ -469,7 +486,7 @@ $(document).ready(function () { data: [], backgroundColor: hex_to_rgba(color_palette[trace_i%color_palette.length], 0.2), borderColor: hex_to_rgba(color_palette[trace_i%color_palette.length], 1), - borderWidth: 1, + borderWidth: 1, }; connected_slaves[sa]['transient_chart']['trace_i'] = trace_i; transient_chart.data.datasets.push(dataset); @@ -495,7 +512,7 @@ $(document).ready(function () { } // todo: truncate of data needs to take longest period of time for 100 samples, then cut on time. - for (let index = 0; index < transient_chart.data.datasets.length; ++index) + for (let index = 0; index < transient_chart.data.datasets.length; ++index) { while (transient_chart.data.datasets[index].data.length > 100) { @@ -505,11 +522,11 @@ $(document).ready(function () { let now = new Date(); var time_diff = now - last_chart_update_time; - if (time_diff > 50) + if (time_diff > 50) { let x_min = transient_chart.data.datasets[0].data[0].x; let x_max = x_min; - for (let index = 0; index < transient_chart.data.datasets.length; ++index) + for (let index = 0; index < transient_chart.data.datasets.length; ++index) { for (let j = 0; j < transient_chart.data.datasets[index].data.length; j++) { @@ -535,7 +552,7 @@ $(document).ready(function () { // spatial chart updater - div.addEventListener('receive_line', (e) => { + div.addEventListener('receive_line', (e) => { if ($("#chk_spatial_enable").is(":checked") && $("#tab_int_spatial").hasClass("is-active") ) @@ -895,7 +912,7 @@ $(document).ready(function () { } if (line.startsWith ("cs:")) - { // parse config of slave + { // parse config of slave // "cs:3A:DRV=05" let tmp = line.split(":"); let sa = tmp[1]; @@ -972,20 +989,20 @@ $(document).ready(function () { { let v = Number(value[i]); value[i] = v; - } + } } } else { if (!isNaN(value)) { let v = Number(value); - value = v; - } + value = v; + } } } catch (error) - { + { // ignore error, keep value as a string. - } + } } if (sa in connected_slaves === false) @@ -1006,11 +1023,11 @@ $(document).ready(function () { div = document.querySelector('#sent_data'); - div.addEventListener('sent', async (e) => { + div.addEventListener('sent', async (e) => { let value_str = e.detail; if (value_str.length === 1) { - value_str += '\n'; + value_str += '\n'; } let value_byte = enc.encode(value_str); @@ -1032,13 +1049,13 @@ $(document).ready(function () { { term.scrollTop(term[0].scrollHeight); } - + await writer.write(value_byte); }, false); // reset the connected_slave container when we detect a scan or ls command. - div.addEventListener('sent', async (e) => { + div.addEventListener('sent', async (e) => { let value_str = e.detail; if (['5', 'scan\n', '5\n', 'ls\n'].includes(value_str)) { @@ -1078,12 +1095,17 @@ $(document).ready(function () { } } } - }); + }); transient_chart.options.animation.duration = 0; transient_chart.options.scales.x.ticks.count = 8; }); +function pop_error(message) +{ + $('#error-popup').find('.modal-card-body').html('

'+message+'

'); + $("#error-popup").addClass('is-active'); +} async function serial_open_and_start_reading() { @@ -1118,7 +1140,6 @@ async function serial_open_and_start_reading() $("div#main button.button").prop('disabled', true); // disable input entry! $("#btn_open_port").removeClass("is-light"); - dt = get_date_time(); if (!($("#chk_add_datetime").is(":checked"))) { @@ -1133,6 +1154,7 @@ async function serial_open_and_start_reading() } term.append("
"+dt+" ## 
" + "
" + "[disconnected] " + error.toString() + "

"); + pop_error(error.toString()); if ($("#chk_auto_scroll").is(":checked")) { @@ -1146,7 +1168,7 @@ async function serial_open_and_start_reading() $("div#main button.button").prop('disabled', false); // disable input entry! $("#btn_open_port").addClass("is-light"); - while (serial.readable && keep_reading) + while (serial.readable && keep_reading) { reader = serial.readable.getReader(); writer = serial.writable.getWriter(); @@ -1238,6 +1260,14 @@ $("#btn_open_port").click(async () => { { await close_port(); } + + if (!('serial' in navigator)) + { + pop_error($("#serial_terminal").html()); + return; + } + + const ports = await navigator.serial.getPorts(); for (let i = 0; i< ports.length; i++) { @@ -1264,7 +1294,7 @@ $("#btn_open_port").click(async () => { closed_promise = serial_open_and_start_reading(); }); -async function close_port() +async function close_port() { if (serial != null) { @@ -1326,7 +1356,7 @@ $("#serial_send").on('keyup', function (val, key) { if (single_char_cmd_list.includes(current_entry)) { // yes! Only here we have to sent without enter/sent click sent_command(current_entry); - $(this).val(""); + $(this).val(""); } } @@ -1335,7 +1365,7 @@ $("#serial_send").on('keyup', function (val, key) { if (val.key === "Enter") { // Yes, we have an Enter! let's sent the current buffer! sent_command(current_entry + '\n'); - $(this).val(""); + $(this).val(""); } } }); @@ -1413,7 +1443,7 @@ function heat_map(t_min, t_max) // // // -// +// // //function concatTypedArrays(a, b) { // a, b TypedArray of same type // var c = new (a.constructor)(a.length + b.length); diff --git a/web-interface/theme/sass/melexis-bulma.scss b/web-interface/theme/sass/melexis-bulma.scss index 7fbf1f8..bd624f6 100644 --- a/web-interface/theme/sass/melexis-bulma.scss +++ b/web-interface/theme/sass/melexis-bulma.scss @@ -30,11 +30,17 @@ $input-shadow: none; + // Import only what you need from Bulma @import "../node_modules/bulma/sass/utilities/_all.sass"; @import "../node_modules/bulma/sass/base/_all.sass"; + +$modal-background-background-color: bulmaRgba($scheme-invert, 0.75); + + /*@import "../node_modules/bulma/sass/elements/_all.sass";*/ @import "../node_modules/bulma/sass/elements/button.sass"; +@import "../node_modules/bulma/sass/elements/box.sass"; @import "../node_modules/bulma/sass/elements/content.sass"; @import "../node_modules/bulma/sass/elements/container.sass"; @import "../node_modules/bulma/sass/elements/title.sass"; @@ -42,6 +48,7 @@ $input-shadow: none; @import "../node_modules/bulma/sass/grid/columns.sass"; @import "../node_modules/bulma/sass/components/navbar.sass"; @import "../node_modules/bulma/sass/components/tabs.sass"; +@import "../node_modules/bulma/sass/components/modal.sass"; @import "../node_modules/bulma/sass/layout/hero.sass"; @import "../node_modules/bulma/sass/layout/section.sass"; From 0947bc0575029c6ca24968d54c3b352ea11a1d6b Mon Sep 17 00:00:00 2001 From: karelv Date: Fri, 3 Nov 2023 17:10:49 -0700 Subject: [PATCH 044/112] typo --- web-interface/index.jinja2.html | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/web-interface/index.jinja2.html b/web-interface/index.jinja2.html index 7344a4e..92e6dc2 100644 --- a/web-interface/index.jinja2.html +++ b/web-interface/index.jinja2.html @@ -276,18 +276,18 @@ -