From 098661fbb9230d96a83172f7312e70f74cd9908b Mon Sep 17 00:00:00 2001 From: Kevin BEAUGRAND Date: Sat, 23 Oct 2021 19:15:33 +0200 Subject: [PATCH] Dev 1.0 (#10) * Update VAQUAO sensor DTDL * Rename vaquao to vaqao * Update THr DTDL * Change vaqao Sensor model version * Change THr Sensor Model version * fix device ids for vaqaO * Fix device name and ids for THr * Fix for SensO * Update Codec report standard * Remove Status field from SensO * Update docker images with Code update * Update S0 sensor * Add Unit Tests * Add Unit Tests * Fix CI * Fix CI * Update .gitmodules * remove old submodules * Update CI * Add coverage in CI * Fix working Directory for CI * Launch build only after tests * Fix CI * Make replaceCodecImports.sh executable at test phase * Add coverage requirements * Update requirements + fix replaceCodecImports * update pytest to 6.2.5 * Change py test method * --- * --- * --- * --- * --- * Update dockerfiles * Update Sens'O DTDL * Rename DTDL files * Rename Watecco to Watteco * Rename organization * Rename https://github.com/kbeaugrand-org/iotedge-lorawan-watteco/ * Add Presso * --- * Add tests during CD phase * Update CODEOWNERS --- .github/workflows/cd.yml | 34 +- .github/workflows/ci.yml | 43 +- .gitignore | 3 + .vscode/settings.json | 7 + README.md | 46 +- dtdl/Watecco - S0 Sensor (50-70-001).json | 202 ------ dtdl/Watecco - Sens'O Sensor (50-70-011).json | 189 ------ dtdl/Watecco - THr Sensor (50-70-007).json | 216 ------ dtdl/Watecco - VAQA'O Sensor (50-70-168).json | 248 ------- dtdl/Watteco - Atmo (50-70-099).png | Bin 0 -> 80429 bytes dtdl/Watteco - Atmo Sensor (50-70-099).json | 526 +++++++++++++++ dtdl/Watteco - Press'O (50-70-017).json | 518 +++++++++++++++ dtdl/Watteco - PressO Sensor (50-70-017).jpg | Bin 0 -> 31732 bytes ...pg => Watteco - S0 Sensor (50-70-001).jpg} | Bin dtdl/Watteco - S0 Sensor (50-70-001).json | 510 +++++++++++++++ ...).png => Watteco - Sens'O (50-70-011).png} | Bin dtdl/Watteco - Sens'O Sensor (50-70-011).json | 590 +++++++++++++++++ ...g => Watteco - THr Sensor (50-70-007).jpg} | Bin dtdl/Watteco - THr Sensor (50-70-007).json | 526 +++++++++++++++ dtdl/Watteco - VAQA'O Sensor (50-70-168).json | 614 ++++++++++++++++++ ...> Watteco - VAQA'O Sensor (50-70-168).png} | Bin src/modules/WattecoDecoderModule/Batch | 1 + .../Codec-Report-Batch-Python | 1 - .../Codec-Report-Standard-Python | 1 - .../WattecoDecoderModule/Dockerfile.amd64 | 25 +- .../Dockerfile.amd64.debug | 25 +- .../WattecoDecoderModule/Dockerfile.arm32v7 | 26 +- .../Dockerfile.arm32v7.debug | 25 +- .../WattecoDecoderModule/Dockerfile.arm64v8 | 25 +- .../Dockerfile.arm64v8.debug | 25 +- src/modules/WattecoDecoderModule/Standard | 1 + src/modules/WattecoDecoderModule/__init__.py | 0 src/modules/WattecoDecoderModule/main.py | 104 ++- .../replaceCodecImports.sh | 9 + .../WattecoDecoderModule/requirements-dev.txt | 3 + src/modules/WattecoDecoderModule/test_main.py | 97 +++ 36 files changed, 3640 insertions(+), 1000 deletions(-) create mode 100644 .gitignore create mode 100644 .vscode/settings.json delete mode 100644 dtdl/Watecco - S0 Sensor (50-70-001).json delete mode 100644 dtdl/Watecco - Sens'O Sensor (50-70-011).json delete mode 100644 dtdl/Watecco - THr Sensor (50-70-007).json delete mode 100644 dtdl/Watecco - VAQA'O Sensor (50-70-168).json create mode 100644 dtdl/Watteco - Atmo (50-70-099).png create mode 100644 dtdl/Watteco - Atmo Sensor (50-70-099).json create mode 100644 dtdl/Watteco - Press'O (50-70-017).json create mode 100644 dtdl/Watteco - PressO Sensor (50-70-017).jpg rename dtdl/{Watecco - S0 Sensor (50-70-001).jpg => Watteco - S0 Sensor (50-70-001).jpg} (100%) create mode 100644 dtdl/Watteco - S0 Sensor (50-70-001).json rename dtdl/{Watecco - Sens'O (50-70-011).png => Watteco - Sens'O (50-70-011).png} (100%) create mode 100644 dtdl/Watteco - Sens'O Sensor (50-70-011).json rename dtdl/{Watecco - THr Sensor (50-70-007).jpg => Watteco - THr Sensor (50-70-007).jpg} (100%) create mode 100644 dtdl/Watteco - THr Sensor (50-70-007).json create mode 100644 dtdl/Watteco - VAQA'O Sensor (50-70-168).json rename dtdl/{Watecco - VAQA'O Sensor (50-70-168).png => Watteco - VAQA'O Sensor (50-70-168).png} (100%) create mode 160000 src/modules/WattecoDecoderModule/Batch delete mode 160000 src/modules/WattecoDecoderModule/Codec-Report-Batch-Python delete mode 160000 src/modules/WattecoDecoderModule/Codec-Report-Standard-Python create mode 160000 src/modules/WattecoDecoderModule/Standard create mode 100644 src/modules/WattecoDecoderModule/__init__.py create mode 100644 src/modules/WattecoDecoderModule/replaceCodecImports.sh create mode 100644 src/modules/WattecoDecoderModule/requirements-dev.txt create mode 100644 src/modules/WattecoDecoderModule/test_main.py diff --git a/.github/workflows/cd.yml b/.github/workflows/cd.yml index 9d18df2..4a492fb 100644 --- a/.github/workflows/cd.yml +++ b/.github/workflows/cd.yml @@ -6,7 +6,6 @@ on: types: [published] workflow_dispatch: - env: image_name: kbeaugrand/az-iotedge-watteco-decoder-module module_path: src/modules/WattecoDecoderModule @@ -14,10 +13,43 @@ env: # A workflow run is made up of one or more jobs that can run sequentially or in parallel jobs: + tests: + # The type of runner that the job will run on + runs-on: ubuntu-latest + name: "Test the decoder" + steps: + # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it + - uses: actions/checkout@v2 + with: + submodules: true + + - name: Set up Python + uses: actions/setup-python@v1 + with: + python-version: 3.9 + + - name: Install dependencies + working-directory: ${{ env.module_path }} + run: | + python -m pip install --upgrade pip + pip install -r requirements.txt + pip install -r requirements-dev.txt + + - name: Make Codec files replacements + working-directory: ${{ env.module_path }} + run: | + chmod +x replaceCodecImports.sh + ./replaceCodecImports.sh + + - name: Test with pytest + working-directory: ${{ env.module_path }} + run: pytest --cov=./ --cov-report=xml test_main.py + # This workflow contains a single job called "build" build: # The type of runner that the job will run on runs-on: ubuntu-latest + needs: tests strategy: matrix: arch: diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3ba116d..9bbd4d3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -11,27 +11,60 @@ on: # Allows you to run this workflow manually from the Actions tab workflow_dispatch: +env: + image_name: kbeaugrand/az-iotedge-watteco-decoder-module + module_path: src/modules/WattecoDecoderModule + # A workflow run is made up of one or more jobs that can run sequentially or in parallel jobs: + tests: + # The type of runner that the job will run on + runs-on: ubuntu-latest + name: "Test the decoder" + steps: + # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it + - uses: actions/checkout@v2 + with: + submodules: true + + - name: Set up Python + uses: actions/setup-python@v1 + with: + python-version: 3.9 + + - name: Install dependencies + working-directory: ${{ env.module_path }} + run: | + python -m pip install --upgrade pip + pip install -r requirements.txt + pip install -r requirements-dev.txt + + - name: Make Codec files replacements + working-directory: ${{ env.module_path }} + run: | + chmod +x replaceCodecImports.sh + ./replaceCodecImports.sh + + - name: Test with pytest + working-directory: ${{ env.module_path }} + run: pytest --cov=./ --cov-report=xml test_main.py + # This workflow contains a single job called "build" build: # The type of runner that the job will run on runs-on: ubuntu-latest + needs: tests strategy: matrix: arch: [amd64, arm32v7, arm64v8] - env: - image_name: kbeaugrand/az-iotedge-watteco-decoder-module - tag_name: 0.0.1 - module_path: src/modules/WattecoDecoderModule # Steps represent a sequence of tasks that will be executed as part of the job steps: # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it - uses: actions/checkout@v2 with: - submodules: true + submodules: true # - name: Docker Login # # You may pin to the exact commit or the version. diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..dbcd2b7 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +.pytest_cache +__pycache__ +.coverage \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..7a230e1 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,7 @@ +{ + "python.testing.pytestArgs": [ + "src" + ], + "python.testing.unittestEnabled": false, + "python.testing.pytestEnabled": true +} \ No newline at end of file diff --git a/README.md b/README.md index ec34234..f1c4962 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,12 @@ # Azure IoT Edge LoRaWAN Watteco Sensors Support -[![Build](https://github.com/kbeaugrand/iotedge-lorawan-watecco-decoder/actions/workflows/ci.yml/badge.svg?branch=master)](https://github.com/kbeaugrand/iotedge-lorawan-watecco-decoder/actions/workflows/ci.yml) -[![Continuous Deployment](https://github.com/kbeaugrand/iotedge-lorawan-watecco-decoder/actions/workflows/cd.yml/badge.svg)](https://github.com/kbeaugrand/iotedge-lorawan-watecco-decoder/actions/workflows/cd.yml) +[![Build](https://github.com/kbeaugrand-org/iotedge-lorawan-watteco/actions/workflows/ci.yml/badge.svg?branch=master)](https://github.com/kbeaugrand-org/iotedge-lorawan-watteco/actions/workflows/ci.yml) +[![Continuous Deployment](https://github.com/kbeaugrand-org/iotedge-lorawan-watteco/actions/workflows/cd.yml/badge.svg)](https://github.com/kbeaugrand-org/iotedge-lorawan-watteco/actions/workflows/cd.yml) ## Description -This repository stores the code for executing an Azure IoT Edge LoRaWAN Decoder module for Watecco Sensors. +This repository stores the code for executing an Azure IoT Edge LoRaWAN Decoder module for watteco Sensors. ### Batch Uncompress @@ -27,26 +27,26 @@ To distinguish which kind of frame is present, the decoding function will be awa __Current Version__ of NKE uncompress module used is __1.0.5__. -| Sensor Name | Decoder Endpoint | -|-----------------------------------------|---------------------------------| -| 50-70-001 S0 | /api/s0 | -| 50-70-007 THr harvesting | /api/thr | -| 50-70-011 Senso | /api/senso | -| 50-70-[014/039/051/072/079] PulseSenso | /api/pulsesenso | -| 50-70-016 Presso | /api/presso | -| 50-70-[043/142] Remote temperature | /api/remotetemperature | -| 50-70-049 Celso | /api/celso | -| 50-70-053 TH | /api/th | -| 50-70-071 Flasho | /api/flasho | -| 50-70-074 VAQAO+Plus | /api/vaqaoplus | -| 50-70-085 T | /api/t | -| 50-70-099 Atmo | /api/atmo | -| 50-70-101 Ventilo | /api/ventilo | -| 50-70-108 Closo | /api/closo | -| 50-70-123 PulseSenso Atex Zone 1 | /api/pulsesensoatexz1 | -| 50-70-139 Remote temperature 2CTN | /api/remotetemperature2ctn | -| 50-70-168 VAQAO | /api/vaqao | -| 50-70-098 Intens'O | /api/stdframe | +| Sensor Name | Decoder Endpoint | | +|-----------------------------------------|---------------------------------|-----| +| 50-70-001 S0 | /api/s0 | [X] | +| 50-70-007 THr harvesting | /api/thr | [X] | +| 50-70-011 Senso | /api/senso | [X] | +| 50-70-[014/039/051/072/079] PulseSenso | /api/pulsesenso | [ ] | +| 50-70-016 Presso | /api/presso | [X] | +| 50-70-[043/142] Remote temperature | /api/remotetemperature | [ ] | +| 50-70-049 Celso | /api/celso | [ ] | +| 50-70-053 TH | /api/th | [ ] | +| 50-70-071 Flasho | /api/flasho | [ ] | +| 50-70-074 VAQAO+Plus | /api/vaqaoplus | [X] | +| 50-70-085 T | /api/t | [ ] | +| 50-70-099 Atmo | /api/atmo | [X] | +| 50-70-101 Ventilo | /api/ventilo | [ ] | +| 50-70-108 Closo | /api/closo | [ ] | +| 50-70-123 PulseSenso Atex Zone 1 | /api/pulsesensoatexz1 | [ ] | +| 50-70-139 Remote temperature 2CTN | /api/remotetemperature2ctn | [ ] | +| 50-70-168 VAQAO | /api/vaqao | [X] | +| 50-70-098 Intens'O | /api/stdframe | [ ] | ## Deploy diff --git a/dtdl/Watecco - S0 Sensor (50-70-001).json b/dtdl/Watecco - S0 Sensor (50-70-001).json deleted file mode 100644 index 8832e8c..0000000 --- a/dtdl/Watecco - S0 Sensor (50-70-001).json +++ /dev/null @@ -1,202 +0,0 @@ -[ - { - "@id": "dtmi:kbeaugrand:watecco:S0;1", - "@type": "Interface", - "contents": [ - { - "@id": "dtmi:kbeaugrand:watecco:S0:Index1;1", - "@type": "Telemetry", - "displayName": { - "en": "Pulse Count" - }, - "name": "Index1", - "schema": "integer" - }, - { - "@id": "dtmi:kbeaugrand:watecco:S0:BatteryLevel;1", - "@type": [ - "Telemetry", - "Voltage" - ], - "displayName": { - "en": "BatteryLevel" - }, - "name": "BatteryLevel", - "schema": "integer", - "unit": "millivolt" - } - ], - "displayName": { - "en": "Watecco - S0 (50-70-001)" - }, - "extends": [ - "dtmi:kbeaugrand:watecco:S0:LoRaDevice;1" - ], - "@context": [ - "dtmi:iotcentral:context;2", - "dtmi:dtdl:context;2" - ] - }, - { - "@id": "dtmi:kbeaugrand:watecco:S0:LoRaDevice;1", - "@type": "Interface", - "contents": [ - { - "@id": "dtmi:kbeaugrand:watecco:S0:LoRaDevice:AppEUI;1", - "@type": "Property", - "description": { - "en": "This is the unique ID of the Application server." - }, - "displayName": { - "en": "AppEUI" - }, - "name": "AppEUI", - "schema": "string", - "writable": true - }, - { - "@id": "dtmi:kbeaugrand:watecco:S0:LoRaDevice:AppKey;1", - "@type": "Property", - "description": { - "en": "The data encryption key used to \"encode\" the messages between the end nodes and the Application Server" - }, - "displayName": { - "en": "AppKey" - }, - "name": "AppKey", - "schema": "string", - "writable": true - }, - { - "@id": "dtmi:kbeaugrand:watecco:S0:LoRaDevice:SensorDecoder;1", - "@type": "Property", - "description": { - "en": "The name of an integrated decoder function or the URI to a decoder in a custom decoder module in the format: http://modulename/api/decodername." - }, - "displayName": { - "en": "SensorDecoder" - }, - "name": "SensorDecoder", - "schema": "string", - "writable": true - }, - { - "@id": "dtmi:kbeaugrand:watecco:S0:LoRaDevice:RX2DataRate;1", - "@type": "Property", - "description": { - "en": "Rx2DataRate (Receive window 2 data rate, currently only supported for OTAA devices): Any of the allowed data rates." - }, - "displayName": { - "en": "RX2DataRate" - }, - "name": "RX2DataRate", - "schema": { - "@id": "dtmi:kbeaugrand:watecco:S0:LoRaDevice:RX2DataRate:schema;1", - "@type": "Enum", - "displayName": { - "en": "Enum" - }, - "enumValues": [ - { - "@id": "dtmi:kbeaugrand:watecco:S0:LoRaDevice:RX2DataRate:schema:SF12BW125;1", - "displayName": { - "en": "SF12BW125" - }, - "enumValue": "SF12BW125", - "name": "SF12BW125" - }, - { - "@id": "dtmi:kbeaugrand:watecco:S0:LoRaDevice:RX2DataRate:schema:SF11BW125;1", - "displayName": { - "en": "SF11BW125" - }, - "enumValue": "SF11BW125", - "name": "SF11BW125" - }, - { - "@id": "dtmi:kbeaugrand:watecco:S0:LoRaDevice:RX2DataRate:schema:SF10BW125;1", - "displayName": { - "en": "SF10BW125" - }, - "enumValue": "SF10BW125", - "name": "SF10BW125" - }, - { - "@id": "dtmi:kbeaugrand:watecco:S0:LoRaDevice:RX2DataRate:schema:SF8BW125;1", - "displayName": { - "en": "SF8BW125" - }, - "enumValue": "SF8BW125", - "name": "SF8BW125" - }, - { - "@id": "dtmi:kbeaugrand:watecco:S0:LoRaDevice:RX2DataRate:schema:SF7BW250;1", - "displayName": { - "en": "SF7BW250" - }, - "enumValue": "SF7BW250", - "name": "SF7BW250" - }, - { - "@id": "dtmi:kbeaugrand:watecco:S0:LoRaDevice:RX2DataRate:schema:SF7BW125;1", - "displayName": { - "en": "SF7BW125" - }, - "enumValue": "SF7BW125", - "name": "SF7BW125" - }, - { - "@id": "dtmi:kbeaugrand:watecco:S0:LoRaDevice:RX2DataRate:schema:SF9BW125;1", - "displayName": { - "en": "SF9BW125" - }, - "enumValue": "SF9BW125", - "name": "SF9BW125" - }, - { - "@id": "dtmi:kbeaugrand:watecco:S0:LoRaDevice:RX2DataRate:schema:SF8BW500;1", - "displayName": { - "en": "SF8BW500" - }, - "enumValue": "SF8BW500", - "name": "SF8BW500" - }, - { - "@id": "dtmi:kbeaugrand:watecco:S0:LoRaDevice:RX2DataRate:schema:SF11BW500;1", - "displayName": { - "en": "SF11BW500" - }, - "enumValue": "SF11BW500", - "name": "SF11BW500" - }, - { - "@id": "dtmi:kbeaugrand:watecco:S0:LoRaDevice:RX2DataRate:schema:SF10BW500;1", - "displayName": { - "en": "SF10BW500" - }, - "enumValue": "SF10BW500", - "name": "SF10BW500" - }, - { - "@id": "dtmi:kbeaugrand:watecco:S0:LoRaDevice:RX2DataRate:schema:SF9BW500;1", - "displayName": { - "en": "SF9BW500" - }, - "enumValue": "SF9BW500", - "name": "SF9BW500" - } - ], - "valueSchema": "string" - }, - "writable": true - } - ], - "displayName": { - "en": "LoRa Interface" - }, - "@context": [ - "dtmi:iotcentral:context;2", - "dtmi:dtdl:context;2" - ] - } -] \ No newline at end of file diff --git a/dtdl/Watecco - Sens'O Sensor (50-70-011).json b/dtdl/Watecco - Sens'O Sensor (50-70-011).json deleted file mode 100644 index 205cfed..0000000 --- a/dtdl/Watecco - Sens'O Sensor (50-70-011).json +++ /dev/null @@ -1,189 +0,0 @@ -[ - { - "@id": "dtmi:kbeaugrand:watecco:SensO;1", - "@type": "Interface", - "contents": [ - { - "@id": "dtmi:kbeaugrand:watecco:SensO:Volume;1", - "@type": "Telemetry", - "displayName": { - "en": "Volume" - }, - "name": "Volume", - "schema": "integer" - } - ], - "displayName": { - "en": "Watecco - SensO (50-70-011)" - }, - "extends": [ - "dtmi:kbeaugrand:watecco:SensO:LoRaDevice;1" - ], - "@context": [ - "dtmi:iotcentral:context;2", - "dtmi:dtdl:context;2" - ] - }, - { - "@id": "dtmi:kbeaugrand:watecco:SensO:LoRaDevice;1", - "@type": "Interface", - "contents": [ - { - "@id": "dtmi:kbeaugrand:watecco:SensO:LoRaDevice:AppEUI;1", - "@type": "Property", - "description": { - "en": "This is the unique ID of the Application server." - }, - "displayName": { - "en": "AppEUI" - }, - "name": "AppEUI", - "schema": "string", - "writable": true - }, - { - "@id": "dtmi:kbeaugrand:watecco:SensO:LoRaDevice:AppKey;1", - "@type": "Property", - "description": { - "en": "The data encryption key used to \"encode\" the messages between the end nodes and the Application Server" - }, - "displayName": { - "en": "AppKey" - }, - "name": "AppKey", - "schema": "string", - "writable": true - }, - { - "@id": "dtmi:kbeaugrand:watecco:SensO:LoRaDevice:SensorDecoder;1", - "@type": "Property", - "description": { - "en": "The name of an integrated decoder function or the URI to a decoder in a custom decoder module in the format: http://modulename/api/decodername." - }, - "displayName": { - "en": "SensorDecoder" - }, - "name": "SensorDecoder", - "schema": "string", - "writable": true - }, - { - "@id": "dtmi:kbeaugrand:watecco:SensO:LoRaDevice:RX2DataRate;1", - "@type": "Property", - "description": { - "en": "Rx2DataRate (Receive window 2 data rate, currently only supported for OTAA devices): Any of the allowed data rates." - }, - "displayName": { - "en": "RX2DataRate" - }, - "name": "RX2DataRate", - "schema": { - "@id": "dtmi:kbeaugrand:watecco:SensO:LoRaDevice:RX2DataRate:schema;1", - "@type": "Enum", - "displayName": { - "en": "Enum" - }, - "enumValues": [ - { - "@id": "dtmi:kbeaugrand:watecco:SensO:LoRaDevice:RX2DataRate:schema:SF12BW125;1", - "displayName": { - "en": "SF12BW125" - }, - "enumValue": "SF12BW125", - "name": "SF12BW125" - }, - { - "@id": "dtmi:kbeaugrand:watecco:SensO:LoRaDevice:RX2DataRate:schema:SF11BW125;1", - "displayName": { - "en": "SF11BW125" - }, - "enumValue": "SF11BW125", - "name": "SF11BW125" - }, - { - "@id": "dtmi:kbeaugrand:watecco:SensO:LoRaDevice:RX2DataRate:schema:SF10BW125;1", - "displayName": { - "en": "SF10BW125" - }, - "enumValue": "SF10BW125", - "name": "SF10BW125" - }, - { - "@id": "dtmi:kbeaugrand:watecco:SensO:LoRaDevice:RX2DataRate:schema:SF8BW125;1", - "displayName": { - "en": "SF8BW125" - }, - "enumValue": "SF8BW125", - "name": "SF8BW125" - }, - { - "@id": "dtmi:kbeaugrand:watecco:SensO:LoRaDevice:RX2DataRate:schema:SF7BW250;1", - "displayName": { - "en": "SF7BW250" - }, - "enumValue": "SF7BW250", - "name": "SF7BW250" - }, - { - "@id": "dtmi:kbeaugrand:watecco:SensO:LoRaDevice:RX2DataRate:schema:SF7BW125;1", - "displayName": { - "en": "SF7BW125" - }, - "enumValue": "SF7BW125", - "name": "SF7BW125" - }, - { - "@id": "dtmi:kbeaugrand:watecco:SensO:LoRaDevice:RX2DataRate:schema:SF9BW125;1", - "displayName": { - "en": "SF9BW125" - }, - "enumValue": "SF9BW125", - "name": "SF9BW125" - }, - { - "@id": "dtmi:kbeaugrand:watecco:SensO:LoRaDevice:RX2DataRate:schema:SF8BW500;1", - "displayName": { - "en": "SF8BW500" - }, - "enumValue": "SF8BW500", - "name": "SF8BW500" - }, - { - "@id": "dtmi:kbeaugrand:watecco:SensO:LoRaDevice:RX2DataRate:schema:SF11BW500;1", - "displayName": { - "en": "SF11BW500" - }, - "enumValue": "SF11BW500", - "name": "SF11BW500" - }, - { - "@id": "dtmi:kbeaugrand:watecco:SensO:LoRaDevice:RX2DataRate:schema:SF10BW500;1", - "displayName": { - "en": "SF10BW500" - }, - "enumValue": "SF10BW500", - "name": "SF10BW500" - }, - { - "@id": "dtmi:kbeaugrand:watecco:SensO:LoRaDevice:RX2DataRate:schema:SF9BW500;1", - "displayName": { - "en": "SF9BW500" - }, - "enumValue": "SF9BW500", - "name": "SF9BW500" - } - ], - "valueSchema": "string" - }, - "writable": true - } - ], - "displayName": { - "en": "LoRa Interface" - }, - "@context": [ - "dtmi:iotcentral:context;2", - "dtmi:dtdl:context;2" - ] - } -] \ No newline at end of file diff --git a/dtdl/Watecco - THr Sensor (50-70-007).json b/dtdl/Watecco - THr Sensor (50-70-007).json deleted file mode 100644 index 2b8a18e..0000000 --- a/dtdl/Watecco - THr Sensor (50-70-007).json +++ /dev/null @@ -1,216 +0,0 @@ -[ - { - "@id": "dtmi:kbeaugrand:watecco:THr;1", - "@type": "Interface", - "contents": [ - { - "@id": "dtmi:kbeaugrand:watecco:THr:Temperature;1", - "@type": [ - "Telemetry", - "Temperature" - ], - "displayName": { - "en": "Temperature" - }, - "name": "Temperature", - "schema": "double", - "unit": "degreeCelsius" - }, - { - "@id": "dtmi:kbeaugrand:watecco:THr:Humidity;1", - "@type": [ - "Telemetry", - "Humidity" - ], - "displayName": { - "en": "Humidity" - }, - "name": "Humidity", - "schema": "double", - "unit": "percent" - }, - { - "@id": "dtmi:kbeaugrand:watecco:THr:SinglePrecision;1", - "@type": "Telemetry", - "displayName": { - "en": "SinglePrecision" - }, - "name": "SinglePrecision", - "schema": "integer", - "unit": "percent" - } - ], - "displayName": { - "en": "Watecco - THr (50-70-007)" - }, - "extends": [ - "dtmi:kbeaugrand:watecco:THr:LoRaDevice;1" - ], - "@context": [ - "dtmi:iotcentral:context;2", - "dtmi:dtdl:context;2" - ] - }, - { - "@id": "dtmi:kbeaugrand:watecco:THr:LoRaDevice;1", - "@type": "Interface", - "contents": [ - { - "@id": "dtmi:kbeaugrand:watecco:THr:LoRaDevice:AppEUI;1", - "@type": "Property", - "description": { - "en": "This is the unique ID of the Application server." - }, - "displayName": { - "en": "AppEUI" - }, - "name": "AppEUI", - "schema": "string", - "writable": true - }, - { - "@id": "dtmi:kbeaugrand:watecco:THr:LoRaDevice:AppKey;1", - "@type": "Property", - "description": { - "en": "The data encryption key used to \"encode\" the messages between the end nodes and the Application Server" - }, - "displayName": { - "en": "AppKey" - }, - "name": "AppKey", - "schema": "string", - "writable": true - }, - { - "@id": "dtmi:kbeaugrand:watecco:THr:LoRaDevice:SensorDecoder;1", - "@type": "Property", - "description": { - "en": "The name of an integrated decoder function or the URI to a decoder in a custom decoder module in the format: http://modulename/api/decodername." - }, - "displayName": { - "en": "SensorDecoder" - }, - "name": "SensorDecoder", - "schema": "string", - "writable": true - }, - { - "@id": "dtmi:kbeaugrand:watecco:THr:LoRaDevice:RX2DataRate;1", - "@type": "Property", - "description": { - "en": "Rx2DataRate (Receive window 2 data rate, currently only supported for OTAA devices): Any of the allowed data rates." - }, - "displayName": { - "en": "RX2DataRate" - }, - "name": "RX2DataRate", - "schema": { - "@id": "dtmi:kbeaugrand:watecco:THr:LoRaDevice:RX2DataRate:schema;1", - "@type": "Enum", - "displayName": { - "en": "Enum" - }, - "enumValues": [ - { - "@id": "dtmi:kbeaugrand:watecco:THr:LoRaDevice:RX2DataRate:schema:SF12BW125;1", - "displayName": { - "en": "SF12BW125" - }, - "enumValue": "SF12BW125", - "name": "SF12BW125" - }, - { - "@id": "dtmi:kbeaugrand:watecco:THr:LoRaDevice:RX2DataRate:schema:SF11BW125;1", - "displayName": { - "en": "SF11BW125" - }, - "enumValue": "SF11BW125", - "name": "SF11BW125" - }, - { - "@id": "dtmi:kbeaugrand:watecco:THr:LoRaDevice:RX2DataRate:schema:SF10BW125;1", - "displayName": { - "en": "SF10BW125" - }, - "enumValue": "SF10BW125", - "name": "SF10BW125" - }, - { - "@id": "dtmi:kbeaugrand:watecco:THr:LoRaDevice:RX2DataRate:schema:SF8BW125;1", - "displayName": { - "en": "SF8BW125" - }, - "enumValue": "SF8BW125", - "name": "SF8BW125" - }, - { - "@id": "dtmi:kbeaugrand:watecco:THr:LoRaDevice:RX2DataRate:schema:SF7BW250;1", - "displayName": { - "en": "SF7BW250" - }, - "enumValue": "SF7BW250", - "name": "SF7BW250" - }, - { - "@id": "dtmi:kbeaugrand:watecco:THr:LoRaDevice:RX2DataRate:schema:SF7BW125;1", - "displayName": { - "en": "SF7BW125" - }, - "enumValue": "SF7BW125", - "name": "SF7BW125" - }, - { - "@id": "dtmi:kbeaugrand:watecco:THr:LoRaDevice:RX2DataRate:schema:SF9BW125;1", - "displayName": { - "en": "SF9BW125" - }, - "enumValue": "SF9BW125", - "name": "SF9BW125" - }, - { - "@id": "dtmi:kbeaugrand:watecco:THr:LoRaDevice:RX2DataRate:schema:SF8BW500;1", - "displayName": { - "en": "SF8BW500" - }, - "enumValue": "SF8BW500", - "name": "SF8BW500" - }, - { - "@id": "dtmi:kbeaugrand:watecco:THr:LoRaDevice:RX2DataRate:schema:SF11BW500;1", - "displayName": { - "en": "SF11BW500" - }, - "enumValue": "SF11BW500", - "name": "SF11BW500" - }, - { - "@id": "dtmi:kbeaugrand:watecco:THr:LoRaDevice:RX2DataRate:schema:SF10BW500;1", - "displayName": { - "en": "SF10BW500" - }, - "enumValue": "SF10BW500", - "name": "SF10BW500" - }, - { - "@id": "dtmi:kbeaugrand:watecco:THr:LoRaDevice:RX2DataRate:schema:SF9BW500;1", - "displayName": { - "en": "SF9BW500" - }, - "enumValue": "SF9BW500", - "name": "SF9BW500" - } - ], - "valueSchema": "string" - }, - "writable": true - } - ], - "displayName": { - "en": "LoRa Interface" - }, - "@context": [ - "dtmi:iotcentral:context;2", - "dtmi:dtdl:context;2" - ] - } -] \ No newline at end of file diff --git a/dtdl/Watecco - VAQA'O Sensor (50-70-168).json b/dtdl/Watecco - VAQA'O Sensor (50-70-168).json deleted file mode 100644 index 0f013c8..0000000 --- a/dtdl/Watecco - VAQA'O Sensor (50-70-168).json +++ /dev/null @@ -1,248 +0,0 @@ -[ - { - "@id": "dtmi:kbeaugrand:watecco:VAQUAO;1", - "@type": "Interface", - "contents": [ - { - "@id": "dtmi:kbeaugrand:watecco:VAQUAO:Temperature;1", - "@type": [ - "Telemetry", - "Temperature" - ], - "displayName": { - "en": "Temperature" - }, - "name": "Temperature", - "schema": "double" - }, - { - "@id": "dtmi:kbeaugrand:watecco:VAQUAO:Humidity;1", - "@type": [ - "Telemetry", - "Humidity" - ], - "displayName": { - "en": "Humidity" - }, - "name": "Humidity", - "schema": "double" - }, - { - "@id": "dtmi:kbeaugrand:watecco:VAQUAO:Illuminance;1", - "@type": [ - "Telemetry", - "Illuminance" - ], - "displayName": { - "en": "Illuminance" - }, - "name": "Illuminance", - "schema": "double" - }, - { - "@id": "dtmi:kbeaugrand:watecco:VAQUAO:Pressure;1", - "@type": [ - "Telemetry", - "Pressure" - ], - "displayName": { - "en": "Pressure" - }, - "name": "Pressure", - "schema": "double", - "unit": "bar" - }, - { - "@id": "dtmi:kbeaugrand:watecco:VAQUAO:Occupancy;1", - "@type": "Telemetry", - "displayName": { - "en": "Occupancy" - }, - "name": "Occupancy", - "schema": "boolean" - }, - { - "@id": "dtmi:kbeaugrand:watecco:VAQUAO:BatteryLevel;1", - "@type": "Telemetry", - "displayName": { - "en": "Battery Level" - }, - "name": "BatteryLevel", - "schema": "double", - "unit": "percent" - } - ], - "displayName": { - "en": "VAQA'O Sensor (50-70-168)" - }, - "extends": [ - "dtmi:kbeaugrand:watecco:VAQUAO:LoRaDevice;1" - ], - "@context": [ - "dtmi:iotcentral:context;2", - "dtmi:dtdl:context;2" - ] - }, - { - "@id": "dtmi:kbeaugrand:watecco:VAQUAO:LoRaDevice;1", - "@type": "Interface", - "contents": [ - { - "@id": "dtmi:kbeaugrand:watecco:VAQUAO:LoRaDevice:AppEUI;1", - "@type": "Property", - "description": { - "en": "This is the unique ID of the Application server." - }, - "displayName": { - "en": "AppEUI" - }, - "name": "AppEUI", - "schema": "string", - "writable": true - }, - { - "@id": "dtmi:kbeaugrand:watecco:VAQUAO:LoRaDevice:AppKey;1", - "@type": "Property", - "description": { - "en": "The data encryption key used to \"encode\" the messages between the end nodes and the Application Server" - }, - "displayName": { - "en": "AppKey" - }, - "name": "AppKey", - "schema": "string", - "writable": true - }, - { - "@id": "dtmi:kbeaugrand:watecco:VAQUAO:LoRaDevice:SensorDecoder;1", - "@type": "Property", - "description": { - "en": "The name of an integrated decoder function or the URI to a decoder in a custom decoder module in the format: http://modulename/api/decodername." - }, - "displayName": { - "en": "SensorDecoder" - }, - "name": "SensorDecoder", - "schema": "string", - "writable": true - }, - { - "@id": "dtmi:kbeaugrand:watecco:VAQUAO:LoRaDevice:RX2DataRate;1", - "@type": "Property", - "description": { - "en": "Rx2DataRate (Receive window 2 data rate, currently only supported for OTAA devices): Any of the allowed data rates." - }, - "displayName": { - "en": "RX2DataRate" - }, - "name": "RX2DataRate", - "schema": { - "@id": "dtmi:kbeaugrand:watecco:VAQUAO:LoRaDevice:RX2DataRate:schema;1", - "@type": "Enum", - "displayName": { - "en": "Enum" - }, - "enumValues": [ - { - "@id": "dtmi:kbeaugrand:watecco:VAQUAO:LoRaDevice:RX2DataRate:schema:SF12BW125;1", - "displayName": { - "en": "SF12BW125" - }, - "enumValue": "SF12BW125", - "name": "SF12BW125" - }, - { - "@id": "dtmi:kbeaugrand:watecco:VAQUAO:LoRaDevice:RX2DataRate:schema:SF11BW125;1", - "displayName": { - "en": "SF11BW125" - }, - "enumValue": "SF11BW125", - "name": "SF11BW125" - }, - { - "@id": "dtmi:kbeaugrand:watecco:VAQUAO:LoRaDevice:RX2DataRate:schema:SF10BW125;1", - "displayName": { - "en": "SF10BW125" - }, - "enumValue": "SF10BW125", - "name": "SF10BW125" - }, - { - "@id": "dtmi:kbeaugrand:watecco:VAQUAO:LoRaDevice:RX2DataRate:schema:SF8BW125;1", - "displayName": { - "en": "SF8BW125" - }, - "enumValue": "SF8BW125", - "name": "SF8BW125" - }, - { - "@id": "dtmi:kbeaugrand:watecco:VAQUAO:LoRaDevice:RX2DataRate:schema:SF7BW250;1", - "displayName": { - "en": "SF7BW250" - }, - "enumValue": "SF7BW250", - "name": "SF7BW250" - }, - { - "@id": "dtmi:kbeaugrand:watecco:VAQUAO:LoRaDevice:RX2DataRate:schema:SF7BW125;1", - "displayName": { - "en": "SF7BW125" - }, - "enumValue": "SF7BW125", - "name": "SF7BW125" - }, - { - "@id": "dtmi:kbeaugrand:watecco:VAQUAO:LoRaDevice:RX2DataRate:schema:SF9BW125;1", - "displayName": { - "en": "SF9BW125" - }, - "enumValue": "SF9BW125", - "name": "SF9BW125" - }, - { - "@id": "dtmi:kbeaugrand:watecco:VAQUAO:LoRaDevice:RX2DataRate:schema:SF8BW500;1", - "displayName": { - "en": "SF8BW500" - }, - "enumValue": "SF8BW500", - "name": "SF8BW500" - }, - { - "@id": "dtmi:kbeaugrand:watecco:VAQUAO:LoRaDevice:RX2DataRate:schema:SF11BW500;1", - "displayName": { - "en": "SF11BW500" - }, - "enumValue": "SF11BW500", - "name": "SF11BW500" - }, - { - "@id": "dtmi:kbeaugrand:watecco:VAQUAO:LoRaDevice:RX2DataRate:schema:SF10BW500;1", - "displayName": { - "en": "SF10BW500" - }, - "enumValue": "SF10BW500", - "name": "SF10BW500" - }, - { - "@id": "dtmi:kbeaugrand:watecco:VAQUAO:LoRaDevice:RX2DataRate:schema:SF9BW500;1", - "displayName": { - "en": "SF9BW500" - }, - "enumValue": "SF9BW500", - "name": "SF9BW500" - } - ], - "valueSchema": "string" - }, - "writable": true - } - ], - "displayName": { - "en": "LoRa Interface" - }, - "@context": [ - "dtmi:iotcentral:context;2", - "dtmi:dtdl:context;2" - ] - } -] \ No newline at end of file diff --git a/dtdl/Watteco - Atmo (50-70-099).png b/dtdl/Watteco - Atmo (50-70-099).png new file mode 100644 index 0000000000000000000000000000000000000000..191aedf0e552947060b6c10862b03336b00afe2d GIT binary patch literal 80429 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%0AIaTzNvC??ot6_g+=kJ4RMK2lOM#cg8Aw_o7? z=^MCt_R4?Etzr^%->KB6&#-mYd}QB!hz2^M)z#IZy0K9_DWs0ClWWyHB1wYoYpY-Q zKWjD7@&3A+x6kb#f{w%uLyo_88qjG#)l74m2zGxKbZixLoapMiNp#&=o&QImQ-AJ% z)!jj@t5wKpo2O}8g`c{tNOe^;n#)d{4Ik;MvU=xOe6z zuARCl9^wDLEeX2s(EGM_9A3Vbj#3xUKykf}j%wAE=EO7q>7TWZ{;})Z2_WwXHWGAS zx$Bqwd(2;0^~=uVydBk2uwGotn11YOs2banhFC*^agKa2WVwXM!q zf6nf#g6rQkZ>uZl)Qf{vkg4#~w)XP8ESIi)$%%j+UrfyR#1@qyn^GNvj#FKFMh@Pj zu3+H}AxQBd1aHHV+L|b*QVUM{Q$E2k2_( zpO$<1_}OoKL9hxpzSDu9;LGMaA5`;&tlx51$gx#G{kvA7$irPBs9L=iP21glVgHQz zOWxHg6#iB7y1Y#lbSi`ya(pRIBmLg^nmN@BK86_I|El(wa<6L#_;?v*TupuIG`@9= zfu?Qst_Z&UOY=Osui@L>=Vkz@Kf4N~uFLTH>hDJV-KpSG;nj5=wmM(6Hte|NWwf`W zf{mfaKw~oqIl-~H=anI+_P&bqbj4+&bmd#bx`OU?Y9W%7v+?BNE8M^F5I3lVj+v6e8~!>w2mh*6VSA+-ul%sjeA-ZaH&>-qHXnORDbra>#)`7>hj&W>vq`; zEN!c)OdDh>%v7MMmyvMKYA)Z@Pe2pb&k@w#axZHMB{!ubg0H9J9#?)|U0OE5EsIK4 zPIBqlqIBiECX$mg@RVP^bN>nM-+hR4Cr)AirmeVmG>OXE+sI2zNA|1N$WMQZ;+$NR z7Z#x`zYz76RcNkn_{+;(3A#Vf%li+oeZ^{|CnuwVVtQpo13|70EzR8V@E*Tw`|yooY4N@w~3!VL*Kk=(?`gox1~6cV@U%Gc4!}#8!c)T6>;q z?Jpg>D|Eis-wV3#mg~;EY}e1l(;38^?D%QG+O8qje)vpj?>BQ|O8jkv+}yUY}cPz+iEGQ zT7{GfK6N?|Yr|B9FVExUxmD+PY=>M%^C}t$`i)dN^IO{Ln^9fYjGFouG&HuMiNIJ- zsZ6}ul9s7!YDHs9I~u4GsxGKPYZ(ExpctivWNM4^3Q?G*AQNi0RY>!`x$5*b4KL$Tju8RJ6RdxI#<5tu)wxWqj)@CYM`G)-l z`loB6f5v9|2jmWjCN5#$QM#jl^hWx}Y@ja=e|hRZXsjlxuII(Hr*~J9GN81V*9Mac zFb0%r4Y26TL~Rv)R=$u`Gpv~AiHlk3pRkI|%huB8uW6-a>F29#rY`_lou|J0pyM3~ zZS*B*qh;8XZYs#XZJ)Nw+ZN>>?U%su+dSH47mM|k?ee&$4CM1zn&BF?G*pH)=fgDH z;$`@iio6XmPcfI38XytCKGENS%){(P8g5eknGRB4fHq-D;B=sA;R6oCjegIy^qINC ziQg;RK>KW@?KV(ZThHYzrMwzSe6{@YAliQ&xv{-XxPiy%bJbGHIiua+Udv=n(IB`Bb_sJtA7G(36n5)Yrfz=NmH@sRxB$#Xn@_7V>$o!z>9AGhy5z(X2- zNR`mNd-rkw!6V$G)b`*Zm9Nx3dGHjEZ$HNKJJjC2izoN)iI&gb-M@YV_by+>-HVrT z{q#9pKY0dEjvdFD_+`kXZT`EGpi{(04ZfPYg8sR-E{Mm~BgaviosW{Da#T%lQfYZBeI{~68~se=%69tv%Gxk8_~iruHkXS08bW^OD!+TR zoWAH4&7ECIzoROCUj)BPf?A$d+CU`|xul^^xV(vee~ny5)loTBOXXFK7%y$)b4=A@ zoTu|}epMw3s;k7byvhpXR+J;BybRgprJ_~mvw4_%5&4pdJSw+xOEgc|&EXU7g{8>m z@{7jvi%apA0F#wV(8wWRWM(5nfyV2!3?#o!#q*cRc=CiwvKP*=hcjnR;q2MdV)(*^^E7@M$B!rBRMIh=K7O3qB%C;U6vvMo zruGO<9y>TGMhjHw{AspR*5Qq03#Qr@;uz&Xv9Nc?^rXRz>-860IUhLVr6MMJq!oD5U z?%a(%J9c3=dDr%x!rQlO!{)?I*pj#z+c$5+jxF1o#KB>J8YwY87^@CR4jDApx70F2&A-71+LX88$6kgbj1%VoTg~Y#uWn8TTG4-_k!X zg99A{jqh-%qm-7DmX4cr+-7wM1t`pzS~eUXMYFH(_3N4czQ zIx14U&ZHwKA33w>D9Xcp4ua1`unXwRP+8lcu>w2+Jq8p(tD3&dHT>ciEf6uR)TE}S zG9FgJ#Yv9KRxW2b*>TIyS>tIuU)#K_b^`2}&eN1~ic6m++J-tTN;`t3nhaIQs-I5< ztpG74C++mb=cD)>mG*fm?wwP6=+qP2+P!w-Hlh;lu`3bIq{Pfl&nrMiexYbz6Fgo~ zs%9r=Wa4G|TfAV9&@i{pC|x{$^%{?oQ-tq7e~H_Vp9nJd?Dl9B_rrzu4oKYtOY&R@pKbC+=Z%mpN!K96Ik&f)0EvpAG=3j67x zw~t_QfV_9#AsnLi$k7wR2M!+X@csiwaNxjU96ChHkoWK3kKMa>W7jT%g5sS!cVfqm z9oVyHkC?~f+qV-Kwr&;XVV=+J&aDiMt=P6{GeKmd@Yao+I(hGoeb}{iHvwfEHm=Wsjv>3}4#v@_jVys%c9IKbF z#i}K%v3luhtY1#cFIn?IAVpnBkqoJ@2jr?}5@_IB>wV<)KO`M;ruA>sAp&gAan$8D)YgSA9 zXSBWlf_6$gZG0Y%_SZ%w4!iy17rdwGAE^EC@mGBOM35!75p4OKjySJFr4qM%`GRIx zb18#*UP#;A8>kL*DXflj%jcHV^Gn=YSi>bFr7H23d`gj(l*G!K7)Es>0dZSgPwA(& z8U-~~$StF!Q(A)T5`s>C9x@8@k(QT>H#ynDskv0zWYYNC9K5FA(W^8nXQ-@s`6fg7 z`RjB%Pf5em4h>j#-|KVfUz5ft)?Ab58bMFD{+ILX2Jicw$UhLdK!`t^`>y|y(ylEFUZQO~( z4coDP-Bzqyy9FE86G%2}#p;#oux8bItV~#gWlL6wHeuN+F}!%uGQ=-jf&~i}VIcv8 zJ#XFu;aRihVEXi#h@&qrd*Z~&m@r`y#*d$fapNXn^ysk|NniTm!$)G+un`zKbQnes z9f8=Gp%@eug8`Az9qu324-vuP!Xf^l2=ERR4)h5U_V)_tWFId-czSrl!_5rr$ADvXuTb zEmeNXIUJ2!X?hDyYx+P*i$K>*Ami~?ao;3A2klqTpG#bzO0z($BhYEgFjFC?p6pgn zfHS0cxYK0~1T60P<6b~f3iA_V>l;v1qq%sqfYNDxC6!(ke2r5%vgqf2OaDaa^iPyt zP(aQXenYT&l|`v2gP@e2*2#}kUUm3Bm0Ay8zQEmQl#-rM5_`t|#`a^(&#UAl$y7w8|H($QH;M`zAn6h1`>=_Dnj6O@pSQ(1L9=?s-n1f(Mb zt3$_ekjkVzR3@=^?>a!x*@x}h_F&6qhRs$=Bpb16<$B>232U)z=_4OI2JBg zirKRWBs1q@#`L+EJZU;6O^g#BKW+-fjGl<$!^Q~54jqMyxH|pH#J4**K&DzWs zmL}G)Ae)(5!_>qIMt#lEyO)V@ub#%}@k?L){8MlI^kXmd>|rGQ%g=p;c^;2*s}A@1 zg_ilTH+uX)%TwF?=f1+~v|c~;5yLKmVhLXgk*F(HFgX&^kZ! zJX-c|Kj0T?`~KJy=CmJ6`h0BbJ|=K7vw*+76Z*S)V3?;bj#Bx_P~vOgKGFZA+A+YV zdHA--_wC#%$5$f$XG^a^cWBK9JU@F2A4(eVfs)y;M5j+}pYi1rL5Se=E5VB0Ml@^W z6V`MjX{M5nLDo!UVl&Vvw9zsICk7n3g@)PuXm0f_?oC9q2HIxRmv^Xr&nLy330m!% zghl0OO$(p6ekYz+$LHGE+=IpD?s|SH3Af^T{Z#I$&j5Q%<(=yEf+A#4nU_lC-76~Z zUQj8QoSBUj0yqypew~VkT+*ey5q>~N&wDRk;@X(lPE6cGrO-AcBy6J8vKsO6 zYbmv?pwzMyGiS}mG%EimOq_;MRH6(UK1Q^|M~uY~I`R*UiABtSVHnVVC?dlKA|#N& z;uj7t_W)r}H-C7z`oZ1B7cP!oa3r|cS-Zf-(g~Jk_AocGg-Ks4^zB6u>0v6yjr&-N zaiiWA=+o0oOz-)#vG6ZH_U)L~<0m8h{6io7^iTTI)3CZuuU|~i=SNeR^st1{&*mM& z7JY0x+lXLh+}So}4xMa8pV7kH9+nm~Z0QJVD<{}kJBwkS&MlAgbROpA)aAJ~Gqr`e znVlH#x^1?#DM3}sRwlG8eGUsF8<_XC7B=Z+0n^@=Vp#Jz3BblQZe#)TKISm%Z3eR* zCa~yf3aj4cux9r%gJsXYu*LlY&dChlb= z^W)L$+09haHZ%)!k8E*y6-uj0P*`4!LMj7`Dl1VyDJ!q6ips(&WEEE-v#1hp3oEHS zEXV8Y5&~5rUS<^FMS4D-r{&_w>nuuB>6E745SUU3OfPWd?lXeYQ=GkaA15g_9X)#u zhfiO|o?~aR=ja*oS?oM?5?l5i!4jPI8Dp5SVDZzO9!Ih5W&Ta%5S5MeGQ;MMy$Hv};zI<-N z=4LK1F?OWX;?!ZIzV_(T+XlwQb}%9!^zCblK7FjwyElFDOzagq2wRvth%d4wwfyB~ z+uOOp&ej#SHZC3JX$}NBM+Xl$IeH2}u+@2NTV)!r>tL^0*3q8K>+mp{r;BB2J#`xn zG|uyQIzz|8h`>ZYhb8@7=Jd1hupRxZoowYIpsQ^Lv9`tMwf7Wua`1w)qc;tE!QPhk zWlNufS{`?D@D}ql_7Uc34q{!JPt%=j=x69+XIj6r-G!ZO=;yJf-vNC_drSKHsO52C z`njDrh0@RIXyphe3r9GcQ%k>pXM!i&$<&To8#q%Ubs;Ev8e1UL#tBgluGq48nevU& zUFkLGl5gF`m6NBD`s_KE7$rX8I&NORitFdk z;_BHmxJ;?&{MielY)d+E4hN2$!uCB!k+}T;maf@>MJu-wh!Qbt(OOKMy8`3m;xT&i zd<+{u8$-s-z`zkx5FI;-AT$o4(W4O5Z#ewJhr%ah5WIt9;2SmszM+HRM{QugVF>O& zLb%`H@#r^X0wSpm8!#Fn{fEKJKLXYcp6F$4L$-!Jr6o_lF!%)ZLqOO7cn3tn%O?!p zzTxookA%BturN>ap>_R(`Xewn8vcO;;U6#%er*2%!oL2|@bvBn4=)0xS0pVHBj)@1 z4}_230CIGPeQ9}~=Ia*;Ki-#5D16A?-XSzh`%;Fzy)^dm*34I1PtTy=wTF8k+$j;d zQ6l8l!y`~k_wowX%%^cS&--e=2hDd5g1b{7+?)d7>gW#_2S2zu()P6M>g)#>XG)q{ zc5|hJLnqU=-DsQcA;MlB^trnkR_*OcKet!7XnDT2eO&2x(8b;^!JX{m76@f8+ux;%M zY+bn=yH>5h?iDM<(}H&-tisl13D}mf5<6F~rTMF{W9>TZTE78%H*LnD?K^O2>vkO8 zu@gsk?Z&Y^dvWr>A)GmU6laef!?kngarfGFJSQ+_rlp~>yaI=I@5kiPlQ3h-Y|Nd# z7*nQFni|Ofn~Lb6QxP?E3ZjNgL4V=NV%ne)Gca__9K?*6PN{1qVre*btj5E~&&SA# z3ov@pB8;7~n83(zq~WQHF@D-oOo&@X!%Kw6(7X{7=3_XmH)8a3ghdWRPfA(V_CE0A z^HKeWBQ%1_$e|N3D0U)-4V!|PLE|xa2n`RPf2%+II2qW|SkkEl*en4P_-uz5W{1~>tp#{&uEVZnnDL?9L>DEoQSJRe$K+y0vM|JYFo z3ZTzG2ZfLz`Wb=;iD7QTLg;5!#(5dl>bSZbugAk-bgY5LI{$<1jRrnU-*-QXgrh-8lmp~2&V%= zgu5U5dHQ33ZxA-pcch`ZM)T#;G3hnvR5jJtp)5ZirFpr?f182goNScj=Ayc!M7X}D z22BkOXlrS~yY_Z*qV?A=UzD}~b@2(?#`*>v*}4}Sm#)M5<%vjGybcTIug0v|%Q0jA zdf}N1HeeQc?&8f@uxuOVE!iU4MF~5wFkw3ut=K7s=Plhr<>y8$SWfeJ8kvXZ((-d? z-8u1_Iy`I9M$yjZ;f0BqIe#7EW+z}?{CZ4^TTGyh!}K{TFlkym0d5M$OjUW9*O?Z!+-OD;fSVncp09@ z!%+iAUPMen*%y!Z4;_mBA-_3_4k!a@UEv6g2ZRq1jt(D;sIWmD?jI7<;b=Nw z45VoTLt`)?WFQ96fi9Yoc$9w>qW$_K%C{f-`9va|pxBRq*`HEL}qys>7Km;up zMr}A^g2Si3hP~^AT*_cnIs)AHbUR2eBsc z2-a-ei?y5fVcq8aSij`}Hf%kJ#BGNm*6ltbS{`4sQ!{-PmA~xOTlZrP zdG(fkShabtusXbA<8Cb9uoKJ3i#O~Lj$cpkT(?aOFIck$b60M}yj7d9aP3wC>qg=E z%QgtlTe_Y=x=wg@{2Jj|iwM-@nG088#)6fYK7R$`<|Sa-+~t@$XBnoEMoJ{bXM6hIVP9eauCrz9uJbBW5VIH11VJ^m#$Bfr_^td^~qsGn_9!XFg zF?y!(=&>^~mdgDx<7QzbCD*PVF)9uthfn>=BPhXs%dwnphfc!q*vZ|_XMerzX&5;y z4kKcxVK^o9VU*U{Jgz;Rx5?)1^L~EMLn&Fa8N}Ki97Dh#I2OYRuEV2;b@H&NSj6@p zDm=8`5DcUAKAfOBf&e;6XAce=+F>4#4Ihf(w@e9~}>>PFed$2NbxA2M$yO6Mc zCzh|UxhjIRtnFay8^T3Bw!|`-kH?SnoB^PO)w=`GChB9MN|6UNQ%@WkwVtCwe znm>e0a8x~Nz!=evAy~3U6EIctypho(F|z*%jP5@SV}xTB55cI&K^PN00DD($5EtI- ziX`a%BDFL&;WR<+{Hcq$b>$vzTziO1S03Q%jVHKr>p3pme1Wq!pX1!EWSqVIq?6Cw zdW_RIA9Zrl_4_z+^C3>&dL&vNKYrtZFb^NQb`Qrc-^S64w{YabO&mUdLs%U?c$T1g z<|_6P92tx%9Cs$2$BtuXHK3$vI|!Cr4xPgG{U?RD?K^?3dyjW`%bp}`-hE7X)2^e~ zxbp}$Y(Io`TPdLu6t&^VP+XlziE_hUtX#hbE7t8s!dil(;$^FMXuM)8mL+V)(&Yrk zWgCU#mu$eI#p|&!o=SWI;X*348I1E6QLf60cfWErY+I)>R3D8)`1J%v2ElP8XvB-+VireMn0 zshB*9+EG)5Cy$(hiNhxePZ%~4<6|da+|cnDM=%^m334o@$FYM5k^>2bRQivj(tbR7 z0+sg@1`fyg0mCqfQsY#D-ifWd{^MSP^Lvt@`wPTJwsQwh;`xooc=#*@cONF>-qY83 z@G=AUlHcNPawhI1XOnYqi+nTXt?-Rk8MvODj%zQ|zVgLK$+-L^1y^W0+^XZ39={U9 z7aqREh5IjX{_ZoJ<4aGvK=b7F2RLz!;CS_(aMG2#1jai!dg(TfFdWH;35tgpis!E5 z;HfJjNpjNMcl@I8-lPlIbL_lGjcRi2NQ!$2fQmQmIfjk9k0No`5p3F_F_+(5mUD^D zEtly$%w_wU4ZE>={VuFpw-YPZ?!byQ+mXQ6<&l@KA_%VBBD^GlKuBJ^e4}vuvP9uU zOE+NQ5&|K6@oGwmt3(^WbS;)9Y!L0-1qlSk<(Ri{1?Ev%-PLmlhTrR1GvYCG`XbSG z_3W98yLbtC8O>Wt>ntI#5^Tvlu1@E1-X42K+(H8Hf{yX-JR@#_SVr4%Q|A+a=V8W_ zSzmej8lV%7{pD+V6C(II_K5ho4jfoSUI(k|M04EUuCybz$%5R3@lo3-fdDsNu zDU=$g3XjFq*zt%PG6vHKdT~)haqH~={?miMM-p^@fo@#5j%RnCBjZgTo~7sDd1gLd zW*6aQPBC6&m*7QCDV~v^W^4S2=4tz3W&!TM&By(WJltca=ZazBbQ({~!Cms5)NI^- zlZ9KaGc~Y$k&YYBQgQw18(e$xTKFj;1h!LhT9yk5YK zy?o_HtXaQZIAIk5a@jg6nfX?&b;3*H*9gZiT!lpoR(7-t<|Sa^{1soB=V_1ga$P-t z?($Cad3-*V;Ou#G*a^bwG|hA#?+o6#vzLD5uJg2)@0d4pA$dV(&svDtGv;IFv^khQ zbv9;Aor5`3=L*lJ;n`E>VAkZ>m^qoiIB}+M+ypYE#5hWc)5a4Z$4pF?bZ_3>k?BSFb7Gg#TPg(ES_Y-qpKQLS8$68=09UNF$iN%qzjG z!g8b(RU)OZ0SIcXk6v|vkRjLsz#9*7icJta zsU$%agaUqK6@sEPCisccn9m_9=MA|m-hGtM6Q0J-!>7n6DFL3q_JhYM1rq!YBw_3R zV*-L(cM}MA5&)I-#}?pI(%(8Nhc|5AgLNBs3$IPwMJaHH@Tzs&DG6>9PFS^3c*W{X zSh;31)^6C2b&0gh+AU)GvK4$^Y9dw;2ong3%L#s}#rV>7Sh{!(7B5=$m6yb??qr@8 zzlZ>-<#>C4>_rP0q`x_SVdw3#yDrn67tUMql^4ui+{p{)#AD&? zMPGRV0dfAU1(-K;KIY9JKvG#hhsydn)8=C?rNwzu=3+iUQRCTIKxuJ4rNTJ`!P!&} z&lxolb4QHDf>Gm;m+@BlR{Up5g6>a>A(xf<7FSMPM`l(TvP$dmrlb~W74_sgjmzqg zS=orJ$|hu0P+Q)B%(8ldt;0K7*4yh{MQ`-b56ItzDSaq0XPw+Vo^x}-n`Uw0`` zI{`8PIR$o?1lei{e1KBlp);3+51zh=1E(%v|H<>%cj6rO9zTmcNoTP8*lFyh^tbEa z8SLCo32+}Jz&!*(Ho=p21uiwM~+(ls9MqvBR>o;x} z=3$;E=C36HuGxe&t2bgb!Eg1dM66nwD2BORk+AN&oUnW?0rG1nEa&;_mHD*XGJ@(i zylm;}E+$xZ@$zL~yX$&O7q7t5_^-W0IDw#=fF%o;VQCjHTeMuXOBO7};`vL+OR;Ef z0v64oggSc(7Eu`EHYf=P2Qj}qYg32|6BVJhYm=oXKiDDEx) zPn87SpHz84F^+9Hg#4@uye%S75yVnzT9H}Xg10rz$f7p4t_=nC?@(CRj>6hj6jrwg zXI3?R<+lXHjEV-Nm)8rY5-{1X%W2yL!W04_gHIcN&j@-V`6(&zQC6WSgV_(16@Di!-^B4tH>eCIU%ZZE7p~#( z*~`Kz01r|EJaGIH_9tD$-lLQP51$p@b%@}1@HBQDIE5Vq!0lA-ZliLSy>;iIPQzPv z9MpLG9^uW~c4O1lUD&u~XNP%Qn83&82L!O!uVe6SBmiy_?dnw<#Bf*hJZ-O8o%ogc zAp9$;C3YeZ`F!T-?s9Q0@b`OZ%fq>$hIfW8pa#;;tmR1YDC}HST ziuCuA6Q5E7v$X;Elv3Z*w}p6;QGmzk`N9uVspM6_r=9c|d}`X$h90Lr)eJxtethmv z1)tjSaq=3$?&@tEzj6yn1U>c@2e57DKH;r9_6n;2WN+i= zwQboYo`$k{(~b_S;|#xzlmNS01*0|~yPAQ>?S}PRlyMqfx8s}c3RUfGs_qI}cGvZ~ zbJyk9uGxUKtJih%>XmDRSFKo0a9$-IH?^7poIv1TwjQggq!-VoTf7QuJG=sG=dZ$w zIRr*ZeGI;3v*sgV`W&p75{HD*6R>OkVl>qJ=iNOaLH94}U27XIQwjF){u2}sa0<#A zP*Tx?imG;0SARfx)4NVCYivhpLt7^oH4+3HDB+O{>RXUs*Zh@psvCr}tLmxrr4qQJ z7H=zR@RnegURH(l(%+m`Qi;^!3gK4;C3uxzg5D0Uw>f?edD z`wmeW?CjkH!(Dq0U>5;#=dS(O!BE^r0PNzelnS>{0^Ce#kiBu!_Kx9An+c8t#w`R) z6_jdH?CLEHQ7tDDG}Y*xZdbt=oc)1m;94 z>)9Kqv|mqU{koL|#ue*D%j0Yw=Ld7Hq4Ih4vXxj(rSIy6OR#1^Jl4)#h&40kVa3$x zST=q#c2har+|ZzWWBxNFLH94{)2C0kwD$;}-F$$&{9+Umgo>)0QCicE%GwX8uInCj zU0vMN-T^xXU3bo{X%tprr@8}r!5W^j^Fc!`!OiW9VIa_)J&@-^DwRgfA$-Q=zAV?+gL&%(a^Yz3Vv1 zPxmF@C0)2g@Vg?cjgU3$dz|j*OPXT7=b@ko@8t>VE1iSYg?nr@M zy`3Paoea4g=9b4f8E)Uc7dsU5^YS<;s^i+`dD`YQ$yV3lVQ#xxdp@U4?QN*@zQ??- zwzqHIg`Hb=ck&LJ#@@bZC$??eA*>BQHji)FuuWK<&QB~}m%z6*uEzQ$3D~eW0g3U; zk+@(n*3O=bRdF+sFkv!Qj-P_+(lX_n^S>_%x_?10?mWPq6X!%HL|$<@itCzCM5Sse zm8Rv5A5hu&2^G!nJGm?P*d@*HI>D|xGwe9o<<&NIKu;b1D(NY}W2?a9boZvHT!2r7 zAA^t0Nl#69YRXfS9z%~49z&0P|BWW;G5i>KD)bn3U6UUB+Qa9#`rsL^+<%J8_nrt} zqQs{Sz;icl6YOr_)Rk);aAWAP)p0ftYmam4>uU9p=SNPQ!Qtbl#iP%=`tUJokDkQA zBPVd+@Nw)vl!Sc;k9BJmh-?PpuDz596*%su;k`7xho|v8f+LT2HP6>Jr$}C2HIMVU z+E(ZBFwg%zcU`YLf3*%jZhd=a@7%Umc*jZY2P2A^362-keBDQ%!>m z!BrcvX~jBhUbz-qR*(sNiSbLZVSYST&6$f8)8ddge<42nhdj$pg6=!@oFI2*_hIDI z7r%f&kzY}T;)Z4ct71xNC5@Ecnh16+o!u3DYzCb+?7DMT;Aune_fnoV^t4l6SMaI8 z>nLv(GxWMkdJI0cn)29c>eEhq48EIBl5yklOI&~SLO@S|uPglSKES0r_i*9X9fIC1 zDs68HGyFK|F#uJo(^Lp{wfe4y6K5}Wdf$V#lei@q9z8)oJbs3JT0rqDGZ+bqYD(OD z=ot1>N@VY&;R6K7gX9AQMD~7yqB{IXX85Vga;uJOTV0li_Yq{fTjqPM0$26Ez1?^Z z&D%pDR-Wq27EgKR;hhA`omApeI^D@ovds%f|)#`HEK0?#AeVEo`(DJhC zzSLo1Wj(dsuYmL5!6Y2&Vt#x*`@nvJ2S|Z zYIoE4PAapv?#6CPdb_FJzHuwItlfZ3tJh%w_&^80TGPB zI2}33DQInO7B8&&pOysOALw0M8@4Z6iI-Pyqku}d0)j*y!J)K@AXnRf@+N-sc^k?J zbmgt@gu4S(&7s|`FAcG{g63_R@)4DHSf6?)nwt#;CTn35s< z;8i;AC#MPUsqpIn;L{hl_2ilG&Bsp(e42#E)&?L0PunUGwbS3_8+UN&`fcHh*KP^u zb@kb+H*n_4^-ey0nMz{<9)nMXAGaz1*$h5ypCA}=V$^om(wVIea~aL zY?wI<_s(C$y$hG{=*l&u(*Hr~(`R^a>53S?PY0!v+`PZ^fdLY9zaxHZ^nneVah?7t zv(nxoGb>MAPEu4}i^{qtjj41MZq~erx{}|8+6~yc`mY4tx6a!!?7ru`odBKIr73E% z<5o?347=Yuho^R4JbsgjN3S)&W7w&{Q=zAUT{7-GdqKc^-U)ULIkq~?u+z4h__Tp{ z<)+3e@ECTS^0cicKu&||IYBOa`5d6y38H;okk9?89U$61Nnbz)o3^_vnY)6GVZ?Cb zVV=&*tMgQ=@Y9A?cUI3QYInA1_dK)J>FTt-1TMAbSv7aCu(`8^J6hD9Xzgnd`J!ua z9iq|;%@<#9*|Zm1H`DkQK4o#;WJ*RH&(D*r|!GE9e+<+Mwe^$B^p|be&S&vzHx^Q$fep zPIYW;u(8!t$5uNtv?0gt3ON;Y3^`t&L8sm6p@NRBp7-Nn0XD69>=QJNOJHqlm%nT- zdDXUS>3f*Z0V+OloIs@I{YfW<)$xNTPGjG(6Wx06QA$-ulCb+QB`;+??djaI)#Vv@ z+~ch6j&hpPohX5+J$;VgefAR0Ubu>jS8n3Ub^861uiv_lTX!Gf?t`bed;0|*+9 zk6z>1)7N-T3H|vC)hWWSQq%A{^$k)9QmL;}koGDW=_xOfMoxMC9LcYrA?3v@yryMe zK6!!E{$W*pg)F7YAR=%vHgy2?8E~9d_to=Po+TNj%l3i&#fvoL=Fb@~Cyh8z%x7-%D zz85ZRZvV=>jJ9)VAHV0^`exDQ*AwjO>X1`YgRH75ysfA}W@RNZ%FB^fT8cNt#duvr zEk9tOpj)1u(J`K!S4u!5$Ym8HCA&oUMMeRVGYN9(1h~{(JWI>N!&d|{zK53Y zpC#W;$rM({+4oX&#BvXk-{Rhjbm6FH0_0Z4{_$!U7WjfUktN(`25`mV*2TucSL*k_B~;B+Nm42 zasKi>T)IZfU!wUJ?}+g;7jEP9`CB-3?xrvgpFDd5NvE#j$ni@!oOBTfkDl*jo~HWH zu?u3_@zd9E?Bo?O?ZA<9*ngPs=-`(jo$FYSm*x4qUG~uvoDgr}^cDI%*Y4xY<+}uF zO074kgug}5zx`bJ#$(kl>41=o+fQEMF8wa=KhMC!mz17gW#jQ{K2?xL2bXj_OV2_w zRUWT%3z1$}inqn(qD?EMgBdxstbz`LeBi4>Rz)>3OX&ZFoKsds|JSwj|5S(ETKXTa zrGt500}5;EgiC50P|?t=IhfP`UPWyq%Bt(dDV*|}2H}#*S~1R*P6Zuo%jiH`L}=r|xp|b-xD@4%gp5Q_tnsy{1S#_MXM9P?8!>$OaWXDGd_hopD&VB? zGXmH%oV(3%dW4Jj9|<^}y-6^lBlkIK+2<)SoW4fjA)lcHafTAw8A@j-DRCuHiaL6M z0CAp5K2BVe&dzfA$;pg{c^WTw@(Lw1J{PCVW1r(vm3;X&LFDdZ(O$mu5Z4K!Hy^#g zE%syfOWb*yjC=I=en5%yAtlhqltjDw(JOw@cRHR@VttWLUs(FTc#~a-wA^B(^Ow1> z9GOJ~6Z#uzJBy~}(%&wh(sdF2ACyo6FC-w8P*N|ZlrE;#G@-1v8RhiStsq!A- zk{SXO%`f5e%mkxi`d=%gbe~H=%qT2C2K_Iwv+@g&otux0%xt_#P1k@aIR!7CCsUGp zfyeaseL#QDdvu_ALilGY3pC|URk{d z9Y1BHtf&a-1hA*~?&Hb5dw6u`4j$jVic=hNpUO#z?TYL-B`i;1B=oro& zIf?5RZ{YULhq!z92_DlCHHAtu2HsmbGNt9@BQ38GuPO2I%cN6s@{pQO(+f)RI;V)H zXy%NLMpFhX7XU_;o1fHiSQmo6%UZ;6HeoLKB z%iW;qH=n2A7L_Qs34V8ysT3s;-lfmM!#wTwOM+s`YutPN2KQ4_@gOaY%3AJ~eN8~k zAjmRQ2^#dpc}jkk{ua+OGR4cc`6b-1>38^s;GIgpSIx`1DFNi?({KSYDV=7P5KPEf zlvcCLC}o$GBbQQa9=|`A5^X_sHHs+R7E>ZAsi!Y=10{>bMilcGoWJOe1c4@oMhi-t zG{fZtl8V+gR8u0ap=4hB?gQ%He?&dGn#Q%=@Zl30KYc;{$IoaW^KdOKS4Y#uG#ck= zJg=Un@pjma$~bSE_rvFMd7pf4w~Rg$gQtuRm}QiV$_PZ|l$JOp{aA2T!O3y^s5JfVoWvmn-M5;QZ{z-2SB{@XIzhF(s91b|{|f0f=o)J4 zaEC83*s&M)&t1gB%hxEWUB(Rp+Jj41arevx+-K9g+h@+<+4Wm^PD$ed{qdjO<8ubj z@Qg~X=g;2IQ7s$kZ*!1Nr2+d*W)9vK7K=CMXB2AQpwCVr5Wb`%{R@idFUhYm8H8kR z$;s-tmQ%6|@P^6_ZKvfGcXBFOT`rB%Lk0mgmG<|BAkHOf8UcXKW$W8=DoH9RNmNpa zQbnnvnvU4D)xtS7R8G{@Qprmt3bpz5WNHf<>cq61nrhLqc^aF`8E#7&84%j0w87;& ze_^St5pE-pbmPkR?Wp?jo=iY_*N(dOcN){tx?8umqo%D@xVF8GrnRHGmC{a2voKHR zX;sZlVtNg^nx+f$IIpX;6`YKk8bw<{)5>`pG`*^gN-@RNv_EcnUa5d%J&Nk6{L*qh zfi#=IlS!au0Oix~>Mi}w)A?^eKu)1lolGe@Ig{a?K?k)o0y+Vo4m$VgpmCcHGB+Oa zdB_L2O9!3Xbb!4{W!o(_C8JxEc5hMH&A!QH`qfJ~d-)PhU%H5s7cSr=rP>o@J_mS& z{%;STI*%iVj|m?>bQA{<9Kyc62e5zNLG0bL54(2m5#GIhCw5VC+PQffwr|{m9UC@d z&!%nIy@7_;B#Jv5HYcpc=2feZxI6)g%a#dmqwy`vmm@Jg9vc=eMB>5)*f4J%*3BVM z%_LC8O~=aVGsv2DMO>WlS_0SBc?+>^{vzy%Uxou~)>DAkgzG0x;nwMMczO3ep5MNM zY&sy8(E+Wgu3p?h@$bBO?_1Jq&|RTg|MJ0;sL04ibzUi&s6=d_@}Z`@8Z9-Acvstk z_R2=IQQU9mR~^z(wvnQKYs-7oP>ESz*M@iPzoMz>BbwXjh)qZ1I{Gr#(3iZ5(?DaB z`10@Y?CjVF|LAG~;uM+BUQFJDlJ`b@O-;MgmgeR&3k630pQLVq;<=Hmuu#4eP0;#I$bRMy%vVM6FtnH3X=2E7xNE zs&!aLr5}&4Si+B8T8gC$mxy-7f_N;OH5W@~&cTY=^RR6CEG(He1B)k4!=iDMh2zIh z#)7dEuyFiD#7~@rC6lKRw5DMj0dErlZuhDc*uQQqrL#piN}uZj{frk59>AUR=aEA2 zE+Dv<66_0evi~FQgy<^02HnYRdy(}j8~K^VlN0mk@HJYf*X#4mDE$=_0sht2v%hnNm)I_042~7eT3*LgX@X;db?&f@b@ltigidY($KQO1)qvIsJnc$%I{rRi(jfAtb~UQlXz zP7tB?=F`Wx@#K*hzeiBHM``Bn!$-LD;Gyu1J9lyI)@@w9c}w`pjhnc5^%~A!rbK?8 z(#+X&qCIiuERIoG#ZEePT1-22?!1_<&O1tAVIMhuLiq5(BRE2d=g@(}*w2ZFd~p9E zVRd}pp8cJyPTRYilF^Rc*g+uLN{MJw;%02zut~IAHfB90vy7m#cpg95cRuFNoQp-%=OTW_JS>_v2lFOQ$Giz~;z5@4#!kiDQIj!e zW9F8H;gD^NM1_L9b5gpzi{X-)W z5fp~-z)*w*gdo&E7*W1~7~t)X{_fuB=jw(2 z4`&jvGN@!?r*oM~YQ-W@zXfMmqhTbOv=TpY`#HW`=)gs-p1E_@xwJY??56Yq4iXbZJ;#7 zUbA*1mh*Gg;#Uf zwby!9WM*ZhQdO0|e0D@+1YE3mrYw6n@RWf(eIS9w*4SD=##GxFhU)sz-=z!nExUv? zx2Z#8s~UD~RKd=*+pulrCTv=|4jUG)5n8`!HP$XziPiI$W7WK6SUqPcR?S|5)ui=v zmSN4z#aK6cDYndCg{|{eVbkp8*gSU$Hq-uF=zUujuExd%tFemSw`RdAtY5kTn^tVb z`V||5)-7Kzw00T&&6OL+xAFQmDtFSkY^QTzsVrK9U5nO2ZSgv2EZG39r5i~bpuJ=r z%<25oL&C`%oReQgA4Yu8pySq>3Q7fPQgYE+Sb@>DZt-ybF}jG)96Nz4+!=!VkZ7a1gHm(C>18%qkZoZ znC{(wJVAHwJrd>3TlaAL&I3{2xOrFT+V$IF+w~iF#&!A14WSDcuj1mRYdCZEqR@$x zXL0KEd7M0TPAs#I5X`tzfA>)a7P+WHN8ajy+dWDe*^AC0O3TLfqic8%+WJS(%B`Kf z+`VA{ja>w%)?T!?_oJnyM=UotccZDP3w3pELbbK6C@yV8Nm&yLit3P?UyZDs3S{S2 zisj7ga%5zcAtR#zsj0b?US%Sd=W>WnMpRT1!o%YcLa+%U*!cU0!`CMSo*n^kBe1wQ zd&807;^gQlWN+sN8!Mh5nkRU6gs~w{)@%b^Z3}2=m_kj}5IcA132ob=g{_-4v1OA6 zHf>PD>XqBDa`_glTCr7>%a?A#lKCsJkN`1n#zM^gdOqfS^Bv~TT!gvbF2Jm>=3&Mc zbMWowv+?z(Gx5bo-{8|fe2Gtf|Ao-Uzxx~?{q{2g|V+;LHo0f0Ix)ocnZq*KKSf`3jYj%!n^IBD*E$eoPlDBPK zt%B|JnW)hFw-eA zZnElk#Rm;K4z}8d1_x1@LMeua2f`if5#nfvC^r|xdbuOn*BjZP;m9PV1&1ItC|9ild#KJSL}gY!s`83ZT~LB5N^w}#MWsSbm30%;P+lX- zT5=|Jq{@O)QC5*VDIzDr$|EOIn2{@%bI6hKL(*L4k}FAzrL-s}5eeZjVhphOuxP}E zMu{>oEE4&Z)ndR(?#<6*xRuoLYgz^7^cA7LRN8w@ZY+`fQ%im!HnX7oW_*$A9=1AN~FtQGW8r8A81N zr{8^zKmPVBxxU69e)A1}|6gC@cmMene)}I^ie*WE`W?S-wkTO2{eC7LZx&{JwFEQ2 zUP^!KJAC%hTzvj9{p~O2r%-um9{Tiv;iv?te>Fe->nl`xo`tkE!rp(eUALu zu2`}OD@p5@Z^NdQJFsP?iqPg2JFsKT4ydeE!43kr3W0q4W({oKsE$np_f6Zhv4ON} ztHA`RZqdh%jXFZxH)vzqdM)f+rv}xvJF#<(3e>37r0-UZ0H{uXPmTWWu4P-P+zMU# zzIADvHaSJDW$U50VlDJnu0eBY*_4Of2M;;VLp&ts_VE4#JfIZwKBbjh-n)Ab z_wL-qU2=nW$PM12^z!-@N|~?Uz}3rFaOuJY+_-ujHN_>+-lPR%Rb$xb+Q8A+2@WPs zus3$36v+|R#`dr@qI8L8RX4DMm98}`w5?#KX%0&rE0`0EOf}44qHYQeTJ{P|KuR`G zFkOqh(iX&~6eB!77k*(WaPy6Uvqv}_odRHG;{|gIcNiEtK%0)KM(^LLYJ}}O46t#t z7B;Tc!j=uX*u0J|pw$`#IZbS$Z5vi|sV&n69g;3N32m%ftBLjN=zZ(8v7Yu@vr3&@ z)Gl&S1jl7Nv0|BuOiNX;bkQ~f!8R;gynS3NmhPYnU4<_AomfThS-nD4l+yYtUSFjq zmpWFjrsLD{3i=z%X`kh^&kEXS%?dSwuo~9UIj^U4X7TbG+9qi&UDT4+(}ljC+zyxP z=)#t?aUB6<13ANuTG&kGru76BDiy`sgm|6y+qy}6yyW+>czOF~UAYK0q#avy<yk7!>p_#irAYwO+GYgp?Z(jDZUoI8#?abfLZu0`Rd|~r zy_esw4~=aG(4cjVZITS2M!z?;4eC(ar~%E5n$V{6)Y_l{ZTeqWI_s!hOR4u7RcNo? z1s(c)^vEsh5oq<-?tt+|RfIcvzjc1z+|B)zj#FW z#v#%_0pb4f2=$LcuzxIqydn|k8HoS_mA^ZQ$}qoJgc7_$d}0vn9R+u<7z9RS5!}iU zom7IDS~tft|e{Z0&quY3T_I3lEr^yTgcJ zYij5Yb7N1K8M(ty*O}xbWT4|nZqI?-o;~zvU02r;IywYPZF?addW}mhO*?36+P+g7 z8a5N8sb>9_Ge#Hy4p^Q3EHJ%E~L7{3_G_I%t@*$yxFYZVp{FGwAFx z70d6Ep_&y8)GWtKA^N|0ou$9a0*3T=^yzQt()qIV==`K*Njh{h(~dB9>kk zilhDFauJnKK<=%8;8q|&7nfRw$iyPC9u}L2kmy{5Mr9#5GzEbn$)fZp2N)2P2)}@M z_z*a~37lR&(eU$0fUkEvygg&#<`MySp-8wohr`(+1djH>aB>bKcNhi-$52uT>>Vft zwhI!nvu6d%%ZakIBCsmR#@ZjYBpWL~A!|$Dw`4`Ku=IIL<`&*CHDh<`L&x%ig()qY z5TK3SVM>rTF?1uj!q~tCM*0M7J!cq`JC#x6gr$?q{Wau(aU zRNVHK^z43C7Wz&w*K>rKt^-VU=$y6fgm{@{tYr&RU6PIsjJ2(4-3mq|V=Z1*5M=|# zceKI9$eIQaQ5gi`LBEGgc5ZB zL&0?#XOA35RayZm(@W4&(Te)YRumT2qA0%!g?Ww0%dJOFb}e$LEGTS7enAs*3mTD= z-+;`bMr0H=j4QpMeq3q!bwZi6JuR;mNm-Rb$&|t-W>!p8dKnUuix8JsAj;T;d_)r@ zr7|L#CxIq-k_(KE%0VPK#IVqGgp(s=@p5QL8bX3o5lm$em4W0G1IUf~2PDDIpP)(d z^&?P{e0&L@ljQ9aH$h(HL_IyC;Ncz#H`j2ux`e$g-tHDLK`yk-(TM>YB*e=u1YBnV zt|UjhKseY2z~06mcGl!x39RYizS~-R3h}a{>}_bjNwTx{nIOgOwpQMMQ_|}; zmR_*7@D$}_S(~`P#?%$IW^UullVxk-4jW@PA!{R7SQ)y&(!hDbvXv26cQ^_0vW0=Y zC>3R?Zwm`uYnba;!Gfh_2`e3I*bp3T<+33_T9AvhBw47Lz-pHX>^03ura}%HBu!&D zs%pU3*zA90Ou1hZO3?ie#LY`rP?3;qkj#A4;2sP~0$pqWXRm)b=93rbjFn*7YH;x*NGwUC1eGMSev)3MxC0UDAx4 z(iQUm zDk_fLA}f|0XbibVR&-oGB4ZesIS7l)63den8j(3c;o&5LC<8QzfEh@@e3uxciek_* zUdNTo+6Z){cP4a$xCCl#`J?oXPb%>085D&kD}E zmLv;WHiwg@E*v#4{1^YPA4<@@$KVE!qa%A!lahz7iWUra@4>*pA#@KO zMf>0hG!33Y{orZT_a8#Tz~OQ6dR^Z^)b|`fUH5*}cI`uB*M6af&V8uw*o(UMJ*aKl zjhfamRJV+xs(A#Jtpv#y0%TJkN*a1lT;DB9X}PGbOQ^WE6NS|T#Hu#r(Rp#1PwtYJ zbIO{KRnmZ50%A^41F{P01Poc}xdcBFgOHVyRUzQWpky&5<5P>tHI|AphSF><<5CEQ zly0+l8!I|7pHl5SM8@Y5AoCDQiXlfCO>UAE5tS(v7Lh)#@JMo$RECC=qYO(G%UlLg z8qVTWJUAe6f`a@L-cq1{Ec|^rJ&zLNth10%~l+H&8@w&9E zC~wcOpOu$K=v(r33He#M6Dd(g#N>q(R=6$dJbMi$KkW+qSrcU zpDxycGw9rZ8l8Jjp<~ZUwC_HF-m#PD89gD?HGE8{WAKPj8-bD4GO&Mq_Izo^e8t)G zc|z%$PEyARs@h~wEN|{7Kn{wsw6S*_iskiPVlru-L0@qq>4FMMspYfi=M>eEE373L z){sN27Rt!05@mWWIl-I?f?=6Za%L&PutX>^y_ld_Bov=ohy+q1mnj6s>mXXNh_K0$uoVdPi|f*!%-SjmOD1;W=Y z06wn%1V%r2Ir|Dp%brd?@No2ohZDij$q(+1G9Y?T8t-LK``Y=yla@Uxb@!lj-koLX z0XGX*c#u5Jok>nY-sX-Z2e_Nrz{Av9z|KWmANvLd#gh~N>Y)VPdy3AQS`^16pu1}X zhmW1dfs>c8=j>JNJAV^<&)ve_Gpw7m{T7DKU%~L%D;PX;34^CDVu&<+l62w%WHac? zX3-xya+V-@27`xWv*}AS>G$rF&8FY2Fq3}!=piwCKF^{r&7|Klv|p%s@BqP(oMA5m zarbyx(?!m(V;Gg~L#S;ZM0IOFImJFyH1(jok>E!vYajsDcgiFOp){*LLy!TOTiSq} zlKOFF7uO-Hs1})p1Vp(q3J8Yzlp5zznoLm4ASklZ2#Tx}0%9@&F^OQv5KKxfLb6Q^ z=Iy*59-1IZURM-vpDcc_qC$h?-j?6b>s=6K1^7iO05ceYUO@=(3>5PB2!NlvKLOB> z0LaiIn7R6q0^sRP4v>Jy4$zkzp%A%39|zi(>T-3@UI(6(7lH^I5L8qkZ|m2YsZmOS8)2;Jscw)zHtvnZ$8Aa z8xL{(+5?=tav!HI-p7HPcX8mx9qhYy3;V9z#J)>6aNsgQ@Zt>|yl@={&R@r#^H;Iw z+*Ry8cLif-E(?t?5Kmpe(24UHJV78lc9vjB5IlT}AV>h*e_U3QdT6^qOl8Q^$fo@6q8D7xokyIHMzkmc7)9+sB9u2HX*;F5qag5BA3-8 zmtdGnFw7~gC6`!3E|DE!IXS{|N|D(SmJ0aslNZtx7wO~>Q__l&nqGo5f?^5*F^ODY z3Z=!0N+$RvCFD*J128ToYaDvK93PuKL9x+kv^|}cc^`&hvM6JsQVE19XJ6$t|2rK0P8yjP)Gl79YK)G znpOs2k0>jex(I-s(um z=r!J+LNH8C&O>q%Loa(=i3wQ~loX#auEe->B*vyAAvO*1F|1U?MW+x5shp&ksN}a4 ztFSLGzjL2RdhKTv8J;jv5iE9<>@EpQE#^CDnUdK^mWaTuk?VeWwlqx4vaoMC{g7Xq9;5#;ECU^_JUcY>abo#M%)pX&^k!!ec?va?Af#++GCa!tcTo32(K6^`N zZ$A+_Lm)hT^AV2TxG!|%Iyu8@cX8Off|fv=&B;71UoG?-IhsUA?VE|62Y)nY=?0N$_KZ z`34}^!v`U*9td}FN4SFv!fYH6O71Sez!WF;?vq~~|5~90-9H)J_)wIPjJDD`oH=|R z=g!>5P-UQ4T9b^p?w#xj%)9QD*}RhDfQiVhTPvNN`DD>qsOIsK!rL$ zxfB7&;FF-o^?$6c;eA4#LwnINxCiY6y9M}K`$osX*VIe!>ls3Q*T6XRB=A+Wb_-QD z5d<51L<2}!U8kt`Q>^EwVYHCFdT|6iDAIF(f zS8?vrJzT&4<}JAK>|T>+`MUP>%>-S2Lcn|ciU9eNK>0#Qq`RcEl=7Y-;IU5Mp|qEv zcang|I)3vmj@`I}qt|ca$hBKShY5a%2!01IU&jH0-$6=sx!!O8IRfBWg5T*&!N+ql z5d7K(ccXP+49$Hb27&V6UwR^ zQCii2lFE9a;tC$bvJOS%wJ0pB5h^IHMt(^Z@`@|R%bdb;WEYf)l81E4$t^;5PN5JF z?KD|AnN+6dA(H^dC9m`H1o7+g>HQ>42BrkO$?KCf*-^erli|ql%OccONr1UsBJW(hqG+rn%Bn~lQ1iesFP#EI;gAnWGhgf%S z#PYD{3_B}3M4H;-@WAl@=!n7pXedGVPsEYYJt&|b#qm8yaEa2#(*%>t1fq)%o(q^w z2Au>s)?^S$+oUNCrRfVf%~hPQb@Ig2()5Ka#rayL=?fJnr54i|GW0IUCZm=lO&?9w^5%fm)qjQA7M{4J>=?Hi&{i6bU zir{PPCQ-^OQr$Lke62mGZs``PYVIQNb)u@V16B2{sH|&2MQyWyo}_odPXeD*GVE9k zK_160zo2w{EITfFT~T?t#mLPe7?S(rlGk}zQ90R#Z;73vq8NVc7$p$$GP}shQiLOm zw@L3&eDB|q1kuTGlq4OOms1INoQ^AsQ*=d5*dCWAlopeUwCEJ1MWrA$G8w56Nd!TH zUSu4SC?$>$i9mc{2on8+k?0eMI1g{cIJ+a-$`Qdvmgui*dT(<+{Mt~0?jMYMH*X;) zA`S-z_u}G(YdB9(xpen2u0DP#oZDoGNsjLCiT9K0@)R{0c$1;`F8IA`-q!I6stI_~ zH|-te*00(t^`hfZMNAkPSP41EMVNxcNU9)e!?o6HA$+NV~lRfh!&*e1@V$x?tN!z7~omoYtRYE** zb3t*%_~gxsDkS&!b1KL${aNMbm5f7C0_MBKuPKW6pA6Q?;A4;~?#Jts0s1aw(R;Hq z^52r=U^7w)#-wyg**QJu`pNW!3}hr`A~QY%nQ^onlO~iJmnu_qGEySr$??S?B|HkL zp%F+92tfj+wec?ANO1BZcV~}7!=v&m=YKbpp!)}chjmH|i9~Nh2QHqyiVK%-ZdFu03T(_iTc$a{1^fE@ijb-N<2rna zXW_phbm06Y0v=C?ctMD#L1c}cJWD!5;FAOI$WKm>XZ@1gUhe?{9zl;CpXB=3@$sCb zlFO6SLFsM#z$l~vKv~iNpbedU1ifA~wD+K?y$g+PooEm<J! zTU9;JcF!~0H^@ZbE9cqktK{(G(TgXknB3pbs;J@@tB6HuGwYW?^IiKeG!-R*R1uVu z0m_oxrled_UN-Hkpxi9lPT~}O9DW2&34qzDxyVk*L3T1JDI3`dS;$KGsnI5l9UqUC z7?nVZC$|@aWJ+rj$>Ak=1tHPPAJI2!#q^dzC&5li zZy9u5BYQ}@(K$SZjv=0bpP)A|OyCN1ej2Tla!6S` z0uMRA%*1qL#HW($OCi^njPw|S9sw^sC=%&`;YjihLX;z=vIM+y$4hMEZP@U?-Iqrq)zhl=vraq+gvQhc2y z!BJ6@;mF(m*1kWd$;XnU2+jhouVnW~;LFb`MhU^NB#)F^isGCSlw^~u%%az`2#VZb zLuqd|0WT*dQ>LU;a(&6jrj#~2JPsK_QAqI#MuM9U!YGZsbn1-!iu%7FO3?j+I6OFn z!pJD>A0EL~p3C71Pt*65oD`*(_nza%!{@k5j_&@mXK%T;UkW;&)k{%4v$_D?<0s>= zV@(9zlL??>DMF87ckVX1y4$zMVaJjnCxMOuH+fxg_J0Xsx!rJDMdpH*!wrOGu;KdYMR zMp4$)HKV?c-b?F~H5q&i$;tanhA4~oWspiRo%|k_^!oUI@_iMh=sX4V7>MLp$KhC9 zh4P|Gp|ZjXl;xMBl%Q9XOUfZ2lH1EC*OyDM%Sp>YUIrlJ<2k8#P5f9?&1|0gzsO!CcP0;A8@B*Zn1rz4H-(%{Y+e? zi#;tQ5My-loTUr>^0nJSSIH^e;u+Ri1SK)gDT(Je{ds-=mTo_LGeMKV$GY<52`)b- zn2|0$BKJm4a&qge)L1dzKyl|j&fdLCtkJLxd z>t*PXdgRcP^e)H8YA4s%)jv#*Z-^Wp&q&73Z*Y9Mt(!ndYUyO>*Go>1>-{+WW#`AK z@K0)O>k{JG$(ma_gm{LsiQ-wyCaR&aZG!3>T2V((R1|OfIn@#rS-i~esUZhB`8d)( z{91JlfsizL9~Qr^D0ZWjv~LAD((^U2+EUD3#5nR5m**0h!^k$P9}?YET3cD3uL$aEFhnErLy~ z5pC;?U}GypS~()#-W74y&d6}}MJ~C(e7`U>q-NpDdvbwF(EXiwc<(+EgM!fC)F`HZ zyLSDKfZPoN$n`r9{`WygfBWyX%rflG(s`ca=@KWwPSNEt>=avQCDKUo$yBRuefrMKuxx8(Su-p}FHN)e`^}HTga7lCXKHFPXi6~VN!3H6l(UQ%rt zxy_O~)D+dCq=-OADlRNTX#uCUB`D4=Msa2#3e&kBFAqhO&K4w+yNgRjc61W5A`*}u z9D^j^FhsieiXqtpY#rfeZ7<3Q7f*s<01`=Q0innVjznH)H1f#}=6VNWl;D2t{6+ay z`Ok$CbblirKX{1zgj6wO*SQmCaE&hb>o@KS(A_1d+G;mJOziR2s}lX$FSRd`~;=ACn&`|PHFA2 zaVdgtSgt_^pFG8#Je4D>ca+Kzg5U5Mx`qgPR7%U8gIw1qQwOC>?fpYS+|V&u9Xe*<@y=|9z(90${K=bH9@qBTxA9AS3&#m$k=5Byb{`{xRKJ@T1s_mP*PZhlKe^n zT?LAB%21G5jO>&=WGChzH<{dBQWmlkGLRLYj*Qq;q(&qnGm>0hbSm;<(~*{(inNqe z+8vI)Nt- z9^mwWgXp9WIyW)_jb(K>u=g0woV|uiSMLZ%ca?x}n;>%g!IS@e(21@nKXo*goE=L_ zW6yI}6apQKK_^Lq-FO;H|Cb`{6oDtDv6DgfE{FGX&|~23K5-Izj#DXzog(lg*a^vD zH$+a4#n6-L_Qv72dmsA7_KpLOOGWsx6hWv6K1Fr*aia%2zyWfA1Uv>G15iPdE1cj2 z<>|4aChs#jP5xWrl)8akBc;&N`egBIyiWtA*4)qVUE=BC| zud=!w6;*90uWUsHfv&i)4yA?lC}R~h2yusO?x4+`w)s8Pg%pd>yHc_AUl_YXvMTmp)tqL3dJ zhD^Tz)CRg0mNI;1XTzm*~Q0*xk7M5H}t?7P|R}phvK~ z^XvsdYNGDGc!hf}UlYt;iuGFz#7R(N-Fo_Zg1CWVvZNMS1|CbXj!u%~<|c!V9i1e} z%}I?DoVreSbc(Q(Tphz~vLwhUN`jqKZ^xjMpvSOd(Cs~OO2AG6odi1u9H+4C>UdJ_ zQBHAb8%u&7!%h)+qA`Qq9fNORFTFHHQ(=Z5ZRh=435x6rTL^MZoEFpTysd@YVKaeF zR`!b5xM8G`(_>m!6z?M)S9ToQj~h`4ZuOKl3sE{PEsI7Jf9b=ZVUr^(LZt! zL!^_RU`%Ylre)`Uiox(oKa1NX}i+x8= zJpvxLkSc0&HxZehzoqMsUQEyha+i}OIWtKY?mwQ8uCiqHatflqG?p@T59D0-gjv zsZoQ$$Lc1?DN0Iv#k#zaqerf8uKOdnvD&y>3&W3=c{@8oc7Ia3%g__xV>l7mni*)M zCIW||1l&lxEbXKC9^TI2s%Bsjd}3? z-^GQS_i*XveW5F)Yd0U@`Yrm6lP=NkopptO|F`brBK>AA&~JsW3D)H+^qV?M@T0$X zlx}1P>HFJH-_ZzteuE4&`oFul;is}1&E=J-FDgM*b{@*oGLah{kMz(;#CiH5+{F_q zVG#tt4*c-ud-;|8&&LN3y8E~9AkoDejhT7aO+TQ4mR7Xa)}f)a6jhnoC`(8|PHZAF zW8#q+6_4E56ci=rqAaTf)ur`lZ0e@;V;FtI`{=HA82b+$$1%Dyou)h0>C4w}_Ua9s zyG}nA`oWyNepCE#6m|aAoe8>d`!4;M$YCky>nl?jKnBAcFi!O914PGc1XW@Xr)*c1p)lk4I7TTUYuX!GpS@MX0 zDYiv_RCH}Q$}YsV)syVWwM?Ju-;uK>n#-4)A?t4ls5PS5im@n5hi~zoV{_o3Ips&W z!YH%IxCoH>JP7;{3MepM124b7d}0I=wd#>%NqJi~ZrPS(npHC;rQaMBstVcp0nRC5 z6F|uUGbo*t_6ZV_EU3%xFm5dumne*~Rs$^Fo#1Ponl!oBnE%trai0 z4K#ZCx1*=~my@jP$KaLCam*cwNH3qD?U?U`BGllz2Zi_cvbV2_ZT%%RWkcAbWJ^a9 zHw9VWy)(8L0h`8|WTeM;Bs{j`E9X>t#4cna8ADE{mXRB6-1=1{4JRyxjX6B6P^GL!-PY0pP-gF4cd`?mW zmA+6VrecU^U0{ePgc1Jo8o9ij+$?@=;(bR{z~vMq{)%#o*ohL%Kt0V&k+SwmDsQ zOOn8~){Vn|}#Z8|>r{?J`HgZ?Nn!Nnm9P36$a!K3@R!Fnn1j^@IuBW-q8_`RuR7H{X_-6+PN zbeEhx_}*SI;I`AJ8v+=osaY0~OZCa&yImT^6a3-pZkr~4G?t;KtYW3CQ3uqmQ}j3% z9-kbGZwI+OcMt2DD@F`&vB4&s->YbAU%d8#NL&-0Ds^tMD-63eH5bQDEnhDX%sl-8 zYbXip8La-|EBJk!-{%ddiW1vT-5X6!(X`>fK>`AvxT)_{0s?sQay@ekEctKW9zBqZ z%nhZ!`7TC%fR6pP519GQxXSVd&xk{b#=|fMGb1w`7c1Zr_A3}qZ1Akr_n4pkNu1B& zPyH92%$Y_7okO|XDyvuVDjU7UbEnr%ivBlB`AfmEpq7I5-UCo;V0_SbyGfVSXWhDd za}&f%@aR9AA2qM_R9fR90-L0vY`H~pVsaY4?zh|j@KN?J`bhQS;E(5us zTJc20nV*x1EsyiLWDOkIv>wa{N0~< z0q_0C47h%xWS*A?*w*Qulcn9?WaX#W(_hQ6-+n*OcqlUhn=o>EK7!<18cA7~fIl2wrkT?zOxRT!M zK3;!#JM6eMnR~c{xWTSUD6}eOU!}j;;a_`20$tCOK;NEHYwt$fH zWODxKuZ$qqk@dLy!5a~iP zA;20Oe66m-@_6-k{M-gyqjCb*??Abo*o)<$;;=b=0O)Lgj;HTE_Tw|D->-OK)31&ljM zykY&&ZKK4yt_63Iu-;>E= zdkJfaxkNTa-p1U#z4@-&d2iGMf}K8l&-3%btf}?heC$)NQ&_wOqXiJTJQMXJib3Y- zTyj-S1KljXZ-s=Qs@C&IanjPMX;jHGGj_ZP1ec^J32_FAcC=KU`XDU3Fn>AbwWiI<hQdCo{}FO=5X|G5K>ccn%5AXb}JUmp{MWrL)u2MxEyqBWc{N#r70-e zn8wL$KjL8;o?WHP@hyqT7PI?|*APf1?#1E0(wSBFELCsls$XV%FH+0x7!3|1?mR!D zme0=Jv~y0!?TW4<<1if2u@rzr0>-txy7%7?PXZMDsX;vYr)lcjLWj z(^BXAi7z-Nq)Mz-nKAWs{k!O9d0C+#4{h6s(6HfSb-(ujsSVl`HtO&Mq)rJzBp2U< zr(|w)hqNJr-Y%N0e%uTFgoS8lB5yCXh;)&#eKu;eR&DAp5@Id{JxyHp>VpVVIMe1v zG*;NNkX(TPK;G(LP5hL$iw9{dYi`eM50ki`w(HD~@XpWt0I$zH&}Bs3CvizJRYb3M z0TT$LBKX8J+0TZ*_S#`$6k+Ylr+w{LhY2`_d5UrRX5$+RV{gX`|F?k#8-{;@k# z$UAY18>@Vz|5SCQWG2>76AL; zgV1OU_A^pZD{pbZ0%wGILehZO$jRmK^JeEYKcK||QftSYu+;X$*_lIiwU(2?!%FS4 z1(q;ldbJ8bQz>7CurM#xR%3OYJoejZtI_7{@% z!wE@h{B5NP!ww};AWl9RvdYcusetg5{jFqPBb95mEAHMUP{Mfco04#mb<0jFJLg0y zeT#@+K+JR^3N?lwN3!**A#LS}>BGg9 z9}LP2ACF`nhF5h-su^;4?Y^vgW)eNt3_WdG-!vOKjd8>UQgnqMM?CsVNN8f9a>4|% zZ=GBkdk!Y|f-ls~O@<{m;rA_psrL2~2U1iw1qO?GrRiq}BP(h@m(dmHJV`P<_4c$) zc#<+1s+K@bZhJT^NU^^hZVP$+HOY9vJuPog-ksTghtNN2V6=S1H&4zNr`)iBW-I5b zz3ZosZHoSA(Q&9s^dDYvU)DqK-S3WhANAe3i^~m3TLG)uRKRm(cSZlxK0eUdBL|(Dz5d)xdT;cLkZ0tIu8aij^MFBXsrNctk)J`eMtz8{bLZ;*Mm)TFx zhi4E)Pph&PDZGF0+Z@TX&<5DOb9twwA4m)Q^b+}UE`%RFYXy$}2-lvW&Hm=}&g9AS z$cB@586Pu?TTAc;2c@=t|K^faV3gmCkeZfC$xn-FEP1Lo?URDAE72CnED$-&!u zQxn7^B24olHMN5GD3eM~?}_Q8rB#v_&RcH{+)pCHNIm2}Ck)NXK6FRz9&*4YryZiK zRf)okqH_D#t$&?AF};18;VhFZq~W7Jo=Irm>AlC0pPnA5B`YFcFli8*wSpu+q+hxW z;zU$4Jt5s#(Zlx@9iS4B-7GI58K$SF<5Cgf_*uE5lavU0?||2Li$jIlO~MioSVMJu z{~lRvE4vLVCA4@bHotEie)gPx=J)2eWJM*Lm!W9zarRWj-ximRAG1|V#qn*ic|Fz^ ztOPoqgIW+SyW+216l{s)7{!1&F*u_MqDGf0qEp;%BYA5r93Pj;XQVGoN@DWNJVMc( zXs|IDtScmpQsQg0guc>2lspx{P_#KYn{siwT7o)8Ag&f`KK?ikcV~Ag62Yz4Ta)g} z@)XPBl`-dH#oe!7sx!Vdt3?g2OwA=f4|4|FGrn6`Fd2nvIVG~pz5ggkR*N- z(|8$Cq|Uxy&(s!BShCG2BF5V0SUFtSoo)~;As|G|y!n30)+WW!nM<0V!k1Wgm@HZQ zkvtW8Z$OV{J5|p)Vw5b*n5OiVNf#cwUc3+1kf714&D1?Xfx676Pm4Z{mlt;7XVO2z zYq8|z=jG&=B6*D`szNE@18nab{K0;{8So`>%-Yc!hx7w39GkgNPK;IwZ@M$%EqaHe z$NUvX5@zIll`_BBL`k8_QUv&qQdJolhopT+c2QxL!?V=$@}6%%+s<}+b+%^Z zgwf!ab!H|S@|`Zg!A8QRdp%@inNO-xuy&=OdFGQZQIy6owfhB)ze zVN7CXw3@zc@qi~3x2>H}CFH_XtTK8`MJ8-~je3R__3hoB$y3Xu?+KOzgZ$ibykuQn zcSo)l5xMaSmiu|Ds+E~d_41-9oCnjA5hGsoKG_yF5^d8w{ugVCZT+O>6RUV_Ss3?( zxcnVViw*+nH0O3Z#fP2TF6*-XJ5!{uvu?xM%p=*EI0|EeI3L09 z9wKINAcag#*Gn)`wKHeJ=?q+3TgCI2);Hf}?z7I~Zyfe?c)v{1)Wo`~xm`{M>x6%N z^4`$mYic?;1P~OX9Piu;p^XzLXVt3oBwBjF1i|+5I%;a9sTuDdeoO##_p}7rx7ae; zEGce+pzIhO7#%r#i%6dU(b5McCg$bvUdbS2pe&|>7&uxR)Y=->8`FOBn5KxkhgU2p68DrtX=iG>_+jj38JVKyYI;Q}SJu$B zw4SW=^vKIg^N2`-{*_E3rP}Ref z@LQE|ifKw@1TPNQhw7$daqYJQ2qw*k-05|l6L)a_`55+#Xo;M4&BaFf4P5fZNE_@X zbdokr3~3V_7NaeW%Gjjm6yYP+ove@H+h$+eh_*H}!&3lq_Y6HB&dqDc4He4sJVlt! z6-8)XnUsSB)np@iLRDK@f@LWVltft=2`)HPfAw(gUSXrBSm^BOIKu@L${P9mRER>I zt#I5!y~K~|>%yZ$`7E0ZR*T-?*&C2=YHEE;z6n|*ifj0Wk7~^q=Zg}^Pf{(ZRq0bwqW)Gh{=={pNC0gwWX|&>U#%z;gJ%u2iI|$b zd7P?48Q0j0@srj*qN+5>#<+k*=E@`7`ElFiPKj?vjGdMi2wY^QHPiWIp3v`oeD#(5g zz7Z4^SAYAQAuT2-Bw|$>g}Y9Vqs{NL@cjt|{Y}X>LvouPLjERW&>R3X@I=AAe?` zPYjI1wQV=a&JGLvqDV)Ba@WJ`enW#V_nzH=HYlEAu&`^H=)_ecB%LSV;DAasDSJAY z60Fhcu-lWPY?SZd2gJPWnaWKKPqG0NVr~&eHmBc(64+IeLY4j^7k@>6{`j0O^BK2- z0*5YfWei!YdPQ(uMY%1~_ZP5dY>~!LduRiue|nydSt?#jUqkVpv$MAJ+yphs=Tjd% zih+*Nj8ly7&taHhfogfnJF)kVTxcDSAj$R1L39FTMcG}`-0;|~%xAEQlI$+q{3aE8 z;(E6j5@NO1ZVB~~S^ReQ?bn2O^9yl=yG!H=t3}m>X5?&m7W3bdflBJca3R1B^|4&z zHWftykVmy;dq#-tAbob)?G=3L8_VWz25vq{^2yhd89yR8k^L4jI+yeEef@nTI_4Dn3Kah4M#^lj2u^RDUPpv=bixtX?Y*Ie4U8oL*{%j58r6N z7)}NTZafGiDAjco92)_-=?amERN28sN7VdYvZT?{P%~18R=}_#(yK`SxPnsRrEviJ zYqlT6`~i>Wu+T64j!K_;0UsXyySl}4VvL}3_TE(K?FU}xGUrhFa0~~Jl$1$;CmCiu zo8ywGWvbNOiAjvn@Ua#Q>kL@i-h4y>WV}Ashv}0Nef-ac!}R@Ur!9L&WT4vMm=crg7yZ2C#$Ukb2{YEG`mm10{hB`ixbvQx)GgG1_+>Jh#{Y< zh#)2U0>Mk7#vJO49bRns#3OnYbH@AA9DPA!?{L15FofskwOC2hk zo6VZ>CGxI}E=a)m}qLNeml@BD~;(1$uvxM0)szY>Q@3u_(W?fyKq$Ew8Huz-^mge7U&c%L>gv&h_uD!SG)rEw?JkpY;cmGYR8QXMg zNVG<4z#fI+QfH#AqRr9HS0!Z*|{gCk-y>Zp3eP18WiJbWpteYDqrmH+7zb(n3D!p zIR~!)axILKzNRoFYG_nTNtM5mA*Xs*`K8!&h%R=aND8pzfhCJx8r)HkbvqFbMSqtk zV*`rv2UiNfFt0b^nyFvnbKv}M6Q1sZRj&HJ z_s|E6zw|>`H7|yl76=I@r_>xh4QLxY;!~&!!i?QNS#3%|QR9d~&tyD<71pqm8zffntUjYg>0zLOLiE%eSqU$1T(8^)chP|0faEfE42)G5 z2E`2!6I*=)qm+H$oP4u}z*w2oybruStqeHmkN>d?bO#c;-H+H>`nWP~yI|(k z#AiKl-*3&nOBQ%s^W}rO+H0Y-^eKeGc3c-^T>Pl6IW#_pIq&gfJX8a5#G$kgs_cOi zAvU}#m3mUA@87@bCWGJySTPe(CerX!JwSaSH+cP}5O?W7K_H~2yHNKZ?({xf)S?ND zZraLpc;}#L>p{!H!eWeZ8JyDXp$~`qp+ndpKZDG;- z3yFo^Wod={PPiH72nsk#N-BTy*SHv?0YM0P1|FRfiz~sCH#| zSnqZ%2InD*@>v#gZR-W?*_Umtef>iWH5uRPs%(*+hclTL;Bc`I2(`HudkMI<_T&N| zF4*cd^AppCVaK7Kxqd=%JS|op>1>Bxb#H_w@+>Vp2ko|f{()Cpv$(5)rFu-v;hm$l zscE{ar(&z4npKypC$mtc%>%pOi^lMHd#CN$s|r_85^DlyH=Tr-cF3tLNYb{u~eMW&0~X))58$@(lT z5F^`$)v`|W3le->FT@ogi9>3LejPWC?h#mgQUWc^qsc9zI#vF0(tm(>qW6XTeUJWIPWcO`I92pFfdHWr&JrgTE~`v|_8 zSM!nV!_e|FhNP)PdpM>M-&BrZq21N}o=Y+47=Up@?ad^-z(ZkjtqA`I=L2TV4;oe3 z<)Q8FuB7&w#xY;wV{_ZFpc(LmyUB_0$Em@Cg_Y#cdPx%yVwV$Z?qPFr zT{d=Jctwo)rSEmz%HM_f|sB?0g{fCu%PVcl8+0Bvceph#`c7ynm- zCG{pb1Acwwn6T>ZOJp>1ySl@8NW0MzPQ0R$p7uUXhUF8&GcI1}$LQa*!!~681R91S z`fH_8+Sk_)8ts!Sifuhl$>aYB3s_r_JfJ&dfi)NhY-9law^H`S zV9p`>r+8os3)Yt}UmBY!P(u`VA5hlk)6o}W0ll$-UJzvDU0t-gS;W)z!DQ->KW@ zoXmNFfZLO8X+nDRkbaka_0O)l?hA6LnR4k&EYT@(O6d52dPov0k7o31Jqyo|)jg^n z@&6X-yaJDWu!4mRKmYNl(X+9*vlARrlfSp4H)@>yDnt?eHZ4!slC5QmA3usa$(c9x z6dHZv!2h=FXm(Zu^sMRM75o<;H&*A__gR^Ss#Jni^5IG0=y_tCB_qTdGr zxw)GV>Bd zXs_|QtZ+m7ToRcdwH$;?p`mL35|k@tnDMLoSlC`lX>Cz{%@@m==`H*1n6+7Eh|r{) z4h4xu2c|)2QHkpJrl9I}d3o~CI?Yw8%8hZDGYR1YvZ>aENMgC8HxrTUx^Zlavjhfo zL5PbHNrg^6cm^M!6`wyde$|#l6=}RN0zE)=?As+$OCcTmUw}zv1rGvW^}>i0)3E{g!A?d=)kLe+dv*eP+K;jw%PvyFuc#E_+jO((^MD?T?U zYIPy}EqM?5H(N7J8WeB>9Pk@o{5aBhJd}@*CpJ9WhnEnS0&64y>Q*H4lG5{agC_nRpv=0PTCPVwY`p3(=odQ&j8^dcQGg2$WquYNzjHRt3zXF)qV@}%{Y9G= z#7fAhQ|0rP|FTE7zN^%;$$jZRzC8Cd?EsV5L@iN zx>H3Yi6dudY{7wYkbPb+4h1gNx$X0nOI@6-)2N=@H4$gMX=I{c10$wr!fc8WB( z{nR^K;l^fW*gzEx+miJ50&&|Zp?`q|W6Q_nyvN`P*+)4m`*J-o^Ma7UmjjD8U?Rg3 zT(A-zWvQ2^gCxf%Q3dI=i(+DfJl5k;@FQ7idJU1z+RISY?aB`!sY&brML!&Wqr5&U z`S#x1=t=np!ubo3j<%gG3JgJM<~4b6P6`bCbGB zhB7*hjj(38wj8{uBj8`?&LJLg2^B{Uy$l&29Uu!1O1|a4&(!!=K;LX)Yiyq7s*r-b zx9&EAu^`Gg5ccQKH(-ArAraHjhc3<4vb9$I6FqeO2TO7RH+1Jv#l+VbVHzA>=0*4M zY23_1eo?)U@v%jM=XfBD!VzYwJR`wc!u>;u^+4wA!%e($uj-Z=p094d-i)+@G+sSD%D@kqp zOHI^QLduckyS?yeM-r*8ea04yN%@N5x8>v35l`j|aY0%f-Pa!}=>9BHJO0FhggPs` zw$#zXq@S4NV!>-1XWGtO@WaKq1RsagG_{+`!N+S1vD=$}JfE4JiJNJ{$aEurwl&N= z6sKl3!GptyH2+?5eIFxNQ><*NuVgAlYp|cHOJ=}w`+AqiuURaP`wQ;ls*($CY(R(! z{iv%;?w&!d5W@s(b(qK8T}rEL_RYWE+gZ7s7S!}kldm8u&KR;aA|1?wY#hC zZ^63jw5M6VHr2;XXE$;^<+l5Y85)tXsxxqT&9k_~*6YzQANCS zabgU2!=Ubre{o#`?Da&r!G;LJWr72tW@jg=Z=r?#dD!x=#=V@QtjR-vsYMjrpYS+$ z2MEElT&wnuon-3|_g|bIu0%I?DNE`as_Dv04bu;5BRHjG$a!Zu7QTG`0r|3<{iTRmQF)gd2H>;3sE=L$J>&_&)d=VQ@CNC|2KFfavX#lo z!;5^wSH>Bxngw7;obTb(^z$c1;^)5TnOG!I5oG1bkfbk)SG~CQM`POYI{Zg4P`kLM zl0LGOe)#*QG0;CSuyv1heX`U4gy;U6>K0|$iL{uGuw@jt+5gTAkn^M{1{uQa zFO+4x&R`LXy4w87)--=l_2QM8&UnK$IKAG5bWp86B`u9;x5G5rg z)WHECvMJ6ax^4P_08tVk-{kO15cfM~tR94=}P2zbA!ptfyojU@}lRc!UN2-*tRE1OeW0w`x%&|%GV<7O0=j^VJigSnCkw_|WH1KWi#{ z+3)(~1M=)5-jOnXv?|5G`zoUK(mQN?5=pf@^w#J6vi@ecTe-DJVQPq)ZL3Mn_bN`* zQ^|wcKe?c{r%S_OhfNi~Eqx!r-ph-vri_j8MvEp79oN)wQuLg)tj95!Mq!_JGd{x~ zbg25Q;qTId1>HooCe@TyzJN$pu8Q;f;$!H{WL?cP^<9=-Yl$awSo*AQRQ{nFhuW(C z>1`voKUaT_XU+!BEarpn6fsRUs)!yemX`~W#in@R>;jdWrN!0P_N4auq}V`v12#)# z&zJw*%!cs(Nvr1=k}_+2=Rv6RMEx`#JbVK-y7A&0Dva!ylm_;-Y-Tna0KH2(KrYu| z1FOu6o4#27JDvDKI}Via3DS*`mH@MMO%+6AH?#z1GoT~q9(t?jg?TsvIkihjsh^{VZjG3@iZeMxW5;u zZ38KQhG4cCnfjJ?vwzDagOlA`V*~RWK_O_-aC8P1*l8uihb%!YOP$e9@L;sE${}IC zl%n&4MP%``RTGKUaV#bS9S+Cot9$r9gcDp3@K}=p8D#Zz5~<^0qq>F~UID^SxNQVV zYW7hbWCj^9)1jG|@gePwfLofmf^YeroqmV)SWAWajFJJDR6xRLrvjnwWrC)6n?1q~?anTwK1# zJ2Ytz)sgu4_;zpZgeQ3ZUjdf<+;`XS?AX>a@Ca`XtrDi~P!5|9;89TntGRsi zvpA5ESY2*Ua!MlAkoMe)VvqU;03q0D_Al#dn%Z_@Vf;{-R9>4GI0QX^B{J`wCV=U# zZ@%N2k!gm>7*)QbY2Z8{ok9p*_^+ z)@j$SeaX6x88SP84sy7w2Y~^d3GMP^jFuQx zol{aw_KYLiJfLNh*K(N+xsk{r5Jbd!C3Q`qu&$-&juz^FQ8i!<1lNm=bKTxT=lWs6cUu z?Yei__k>3FP^q^K@eDo-) z7|uYjywU$>u~5EWf@#dRwAJT;KM5%hRrJP>HY`9K6&9nISg0r3KW029K_0K>=AVya zaKLm_FU2#|`+2;BOs7;1T8V!d>~kN@%v7SVFQj;(Ut zSn|v{!#a=E+#vuP4GpTD!+0WD#)zNuef{%K$-GtA{=Go3FNulyT&>GvG(zE3-W<2W z7{I<)85CS8BCCBm`v}I>PQ+NV+%t(WH{HE?b_~G_ukmnz03bV?icAnIG9ZSfdG{C( z?AXx2!3KKajQ#mfeDFKZ%y_lAsUO#rq2o(BIdEayI87IS1@uy9JYlWX{W}l>R>f_9 z))n@5GBWokj9-azyVep>FJgv|q9|DNwf8;Amy~JrDr)>f!t9u1lkwVxknw1-ri=xM zN!~h!+RXc_7A83sf=|o{z!Kgp{GJzQMNORs-wDn~*`TpZOg6xO+zDoVl<1ZIK+Go! zxZF1@uK{O1`Ga z?dFyIf0EV8tX2}50^R8oYmuD4@#D4}2Z9g>U+2Q&6B9mR0cBbD+>lKj+o=Ki+_okk zv$<5gZ+4s9kcn(cp=gtzMEr5EKc4R4;gx)$hTb?RDGi=~50!4{8OIsA448|Zjv{j* z5&S&K>nE@Lvu8GG00OY{TL!80C#f`S$*o9ZY`CkLeZDiV@!^v| zLAI*=FHE471Nl_F&xhCmovtPX@HOhm-Oohuh-`CBe0-jPU!+~*hOSM`VezrC-zT4S zsDKcX#&a?2txxkhA@l;ZD=DF9z(uKonCjfr&v=rcx`HQW>;cm&gSduopFfzJ!rY|w z2)irla_>B#JK38Tz9?pvo+DI@js-KMa}({8KUY@9|I}>scT$RK7Bnriu~m~-GlECB zhw`CN_i5c3;rduC(?9i9y6OB6!{-iGE6FVtQtkBQP^W zYtro>$u1|Q7;15GYh^n{v&vKZ)uRn||F2rtmZGSc1v z%qYF*9P$eJ8by)YNfp&>93ko3K4ZFkAjaI7fnl8i0z&R@{p4%SUasXcXCuX+{}21O z{^#qT0gyv4NHGp1vx!_#R8;$=-tLM4c*UD-DJMKSl`-e&D{OT9J9RM`DKf{rV|Mq` zItTB+AD^pz6+e@yCaW&n7Ml9HFv#5tj0enbDo_*P|N0wK((Lv(ib}@mx1ZlSsVcX@St_p`ENWR8yJ%D48xlTt?z^r4ksrK<&16*1bi(QU+GIF zHLLqO;CPDu8C}NCo?c@}CP&4{O!~^(2*@as?XainQclwN$R+IhbEaVFpXUUj=vfiE z^0yeO39H}V+twAL8Ipuam`U~rjNr$^lgF(P8>ziU89UwqE+OGCRmKPhN+Zpm?LE`; zWXY(%ITZiNp2dU|t5cQIKG!GYn7-$S6hO3XmdNiWS zc(}py?`PXvoOu-ZsXJ}^nHHq^RS_&q>@;7)jsdlcgC+0=J+ir{*}2g-2@pFzKI2`M z*wz&50Utk}sc~j@JosO4H0I;Hj{X;34QWu~`ErrlwZT10j4nacs8&gCaZ#GJF6<)@ zFGk8K1@mkYq^DWe%9W{q)#ntJ)#UVT!&r)bd-0XBnX_F99H?@rVXkVqF6IILIFrN8 zkIJdyVKFqo~hR!I@d-hNvS<qR(KmTJHS|f)VbgrbV^M46p|TSm!^6w9zZ@ydY{{XW zwi__kWhH*qxnBaf7-X>Fw&O!bi`Fm41kO6+0pGvei$m1x+GVXlR}KG*T^rvqf@ZxQ zpR3zsn{gt;R}zaI(dl@Z^|S~gep?i3N83O{Nl#BNB_}_0^Ac|$N}ID!f(j#e>6>(8 zgDUlwigM}xd&sS|>QF5z7f51P37ejCUIi!s+0)T8FHZNDMO4k6yxU~6>k7BAUY5g<-T=;|33hZ$VnG)v$i9XSiZSp#Pou)wZOG6@ww*vL5&@Hu+h?k zLuvMv_GBh|Mu3tZW_rg`@0C6t+#~DX?PxkBhjo-$eK%&HXCangl%3E1)c@3!^&0b1 z?lJZf^~DnZ?+1k~Oj0|Z>%MswVyFjR!3Uyc6qR);i~@CF7^aYgRSW=q3fgvho#@|^ z=?VFkjpMeqFArc@5(BW6*L2fic&ehCaO&MH0Ty0fBt4>QWhjPYxkD{Glbm9IB_1;r zd~I>iLe8*qFF(C}QduT!;oOie(<~8#Sbx$#&nRPYa_F`G>xKFPro7FpqBat$maMt$HX!`p#*)YXRjTM~te@UPff>xwR zJfKcW5!SoFt(|AHmuzQJ)Pob+Qy*ol};#gORy4Q08OsBHV#Ih}lc`5pQO>)Ky zQrOsqA$)v^$jPHwq0yD0)H2=`>XBG2wm;qXEgQ&c;MYEi25_|-%b4EB#T)nHC{4z6 zxF7a^3ubo4_>!0hCZKXWs8rcg%Qhck4KR2U)rEjE=E0Szh1N%^%!VJbX{>ZfHeQ^; z%IdNC-joiP$ncBF;~%F^#*mSzrIb^40Klv79mPE$ZigI@vo?HJsfQXtR_yNt4aBNy z)Scb9aMZ(JJKBws zot@zp71bsg=KMB1W9S6;4y;(>M;Kbug*|(+_Ng^VJWDl;nj_xM9TKa27vl*Dug&2b z??&v1{g>2ZpR2JPa`hIlx;;|DywRw`{1Y$}xL4^yoey_5P`^~7nuBn_rnqsVqba)H z-a*R`#f4ec)VPRFPv~JDTu8TzGzUGl74On}EdC%JJRG)tMvq^v z|4BYRkbPx+x6hm{`-k;=!I>DtSWe_vmD#tIYO+CVP?jEyl@-v3)*yV);F7#gOziI6 zseuRYvSLQD5J6^V`vw`2+xc0a!oElNlte`HjL2dgkFy^=Z0Z^52W^7x>i%()>}C?L zw7oqrfMY3ZA9W{>Y@XAE_s)sdUK$F|NGV_?%GyHWg+!yZfO3zst~HEy!OB3FQ*6ZiGSGZ*B1jm6SBw zTRXi$vOj*}h9_E3{oY74)-x-%<AcCc6?- zBmFI#>1N4}pZ9h4qQzl8R|4C-fHk5fiQ{zpiiba3yZ{60^225ZAbs zVK>6bJ!KA4_G89#xn0c&0Z@Ay2G1EtifoN(vO>)L?eS2#Jukq73R$Ajp$p>XFSC1> zmsx6@lj<5C^=G{b2xDFeiv79yo5@|e`x@ZUeMKUzaz|vrC=r>SDwK8;zLR~dQ|2*- zfg!KJxbV-PO`tiEspk{`X4d|k{%E%X<@kS&2IwD=H-^Zq)b#Pk`r0=WLgA8arfA z+io9RH)p{ERyXYxwwvM;T*DtoN``!blRW=o9wz^_n?A{zzfFE*a_nYZ`up|1^!KYv zQqj8`r!TjDkDABxqQQ6uner>I_x9W7rTi(Hzn8kB-xrR3eQWb4!KMDg5ZU|NYu5L- zyG|7W(zps;WgqbR55B&Qb(bz3VC}vpVePu1Y47@LsAE4!5-~qtBqPSgx3h!#@L{l1 z!F#x^i~20WQewz(H?aKl{(a-KIapUC6CuT6Zx>HA=FP8;^=CVXtZ#&eTwmj}y}dn; z1P?gD3M1u=t>X;F^KIps8Ntsd;BWQ+^YNzQzr;j%bf5E=&pjL46L;EdOA@%y;%dJ4 zWT%B%j7qqA(IG_&{_K$L?~#wNwLF#q`=9jdOj1~|jiIY$72tSAwM6UkyCrpZGraFw zqp+6u4^JOCM^!d6>>s>eJvg9{^%g*(-dQg%=431Fv3`f@emZV?oBhb08jmH;WvHNw8FHm{h+%BjAr)AiOKa6Vr z8_%;p?}w#_Qa|bEL8@1J*!tq1lToaV^hXzwe!s6CO4qla;F49Q@INPeeLvZc1Ig<; zPo@~vX5}{%NR;{B|JjV5p-5DO^rvoY3^}PJCJVEc zriq}5{JTUT{1pL^(1O&Q6{VK0T0Z8Spjs{)y|@T?q4)V=Fj@j4V~+^3N8G`R3V3AV2T$ZIZ}6jsG=B&=|LtjP@fF8{aUAj67c(R|H~xc% zony5yw0!sGN?l>+eqOisAX_>bu>QDEY!gS8mZ&9&%fr{H>zYQS>yBi!((?AFnfdK; zmigJwIrGOtrzgqE{oj(6p|FPq4bmkOPJ{25s#ow{=@I_1u{BZU{9Kgb=JJX|9IBj1 zDqxi6506#3zna*fIG)oaZEI3hF|uR)9UtpHG??P#L~qK@&&St0H^->vj3#o0L{w$+ zi4L2ve*WBN_s2_af9lhtK)Os=F3vxchwoz5HSiUb?0T`_X({hXg3#8MoS#qVh|rWV zdmi(A&dG><<6C$%4n&~VawtC?G})c3IyV;{_2X^ER1g_3pHo1bpCAkrkyjhFjHZ<-#82pL%6RzIvN)Z&ye z?`Dr;75q@ATZ7|BdAv3!_7KrVKu~Z!*kF2tA_yKp-c)3 zAOU?%P^g59+v>g+Rw26?+a0V6@oePc6eaSfJQOfPP+n0MRacQ$AB>@Pb~LT5D1J=c zS64OAHv3&;_?@!DU#ugOlMaGnjA!Z7d>A7~#(0jMq~ME%hj~g6rrU>2f{96L8Ey2I zk6a?p8Zzt5JN5;{!1!N1b5ocAVIYb8wVPr>Igf3M@uk*S+wF=clSaG z6n8IB+}+(R1T7kh6n805;0u9Lf);m|0zr#w2`+`=6nXRf8EDz-laf;~y?u*!ad8nBANT$Z>THqhzGg9U-yov0o!Y*(21tOwG={ak$p%%$-N;!e;3Og~rrkTqFb1=ZC9Z90wRij%4n6$l{1&7Tn9A_q z7%JQQSQZvBdXvh}AJh^R-`62Ws*r6PCv+MXbV{Q0fNGPd>&M$}b|;S5S&$fleIV)9 z+5U>@?XI{7@u9{AiND2OlwoP%_y4qOeNXc{fiPT;);-MUtngU(CxVH{mh3 zi}^Js1Og99qDRz>JdA`cIx}^C4NAAxSk$ZEr>AveZs4whf?35$3$a+@_23yvT4}KM zGhRVAQg`}@-L3bG#Km+5K9JseuJuOSjd(j-Ye&HNI4De>Bjf7oARX~sFr#XsV*WCT zmYD#&5!B)F^s>bbHpQhpUJKN&q48}mhp2p`+O6cyubO2wIdHp|&n%QH67e@*UpF=i zm3B6$mkFqRzKBaoEXI?>Mzyr`-hZI+6`;)6`5nyrE9`vWw}%IN+*5-+#`8GNQiFh1*nkswcB-3+SpJsM zctXzuwb~m+b9s0Y-P+IS&Cgd^H0*m*g`e|&^z^NX3E00Y5WuQB2$ct<3xQv|aYnDp zzIG=O8>v>yv005LTT-bkSt(DNUTZeETHOhjQxj0o!8+VM`?Q7P^(pp_g-a6qvrpRS z2Mt+M5bb}Z^4n^Mja8+u+&Q7bv$`YALREFya5s#?OSxCod@wl7jDiQU z^3z~?y^bg*zgad`dcfn79J{r;_$r%e_$>AMHew`Mcb1wwG}(>v%T){IH+&-&l2BCx znweS4*rOHZ`FXP9?D+-r=$R5rm{}Wsby8BRib=oknd;?U(xZ_?7jkRGif~OO+ic#l zCopn9g<%J|gWei^!|fm7|DPy3`3zFA-RMR)tTG&k3q!@N)xd=wR#CSO6hA|Uz zmx9=`-X1br$a8K$rh0mrSDa3ND=sy);f{F&?N%el@vfYCDetn& z|6nBM;n&nmsukV3WQMoDf98zmW`}+u9!_30TKU(9eC~z+Ykc~%;Zb{faf|#LL(tv7zlZczx&;MR@@@d@dWA7qxlLv9=Q@a|Ej_Q4<1Fht|rqM0&p zxf0OAuWvw6TwacnbUoz!omat50|QxG9-#;pFj1-7=!`>A=M2_S!nEuPksy0cMXv2t z`eZ+P{}a|^5RKS4a@9XiRZ7-8*Vl^`itM$$cFj%meP_~6s+2I6HB+_&pid%WG4o!xzB-bIdS*4$@2h4NHdDjKwl_Hdh28~|fD4L$wl@mFa27-C||4Oi_e84J^E1GYnCqI7_Upx4GdCE~JH3?~x)8ZAq1rES6vYL%cpNXt8d;DPg+D4k-pD)?JYTK84350qGvwaRa4bps z()&;3rW9_%V}FWd5{FBZ(8z2jyu3vlp)kH#b~3)ZP|kg+kg?rhc!_9($&3l^2f#M% zZoI-pYT9~U(7XT5jQ|d&>N9(rKFfA^+=IT&-gYDm*7)y=Y~sf8Pq6l?q?*b9F?$?y zLh`W(S1CdtsK~=_#KdI9c~^>#_dj8~_Pi$skTJFB5|x83s~jhKsnL%1i^AiR@)!En z`U!1py5o{?N&jAZL!c$n*)suGbP7eD?EP7@`;#I7GYhGE-sjV;;nY84_flmv4^87a zL!GRpp-%_jYLykkP^sfpheV_FILp}%Haf$S%#3Pn8cS(}TukB`13nd%5Uq_ZFX?=@ z>2$|Hb>i!DN`q{~>h zDTL`2-+X@HA?}dezN1V9tQa8Tm&fXTEyi9a$+l!}HN|_j z^T3nOFZ`9|%>n7Z2hs>haJ4uj4!)fYN(N8iwl8xRiA4!!&|bIv4y|&UguLp5tE$mB zcFbEhT40Fh3oH1p2SXmYPR!x!e&jaj>$!$=`}Of#?O&uBVop}HdLToZLVV#v`k!6U z+gBHBN*IMviIREhmTPcJvyQQy-E0~H$?)&Q)Z1HM<@mJG27`T$bX`T|uAl-Fq)=Y0 zOnQ}^1rytR$X(Oem(G+%h8#=)-2!6KBnBX?NR@`iXW9T@e{0wm^5nSWd|cX5K@){F zJS{dG^(^&7xwNj#Q%gbCuujwdo3?g3}sK4}gWpfFR(AKiv=oWod(VI`S@@|tmi7W0izKa zS1Az9`ZG;K4&{fKHJYfLh#wI1WzZ}aWWn@-UhvJ_8&0nGI&wT*s+T$iMUj8|-ANtG znWQCYs}4HMgkB_IUqp<`wyPZV+O<;crmM^CV8n#^OoJmuFdrke-}-rSlSePHi6 z=RDS*C@eY=(gGPD;u_Q7%-_`%h2pOkV6hh~N$N4G1wyAXJ0 zd6`Fcv8#gu{o}v7{n6YA3xiNGK|zB$pLNxl7xxj@cDIb?xtHdwksw#0*%_GBpPM}&8JOipCf<*_44hGn)`_T}R5JnvR zCDu30F8!|tO%d@<;O{I^4rNj=qZO)@fP&OFug&~gA&D#V>`+{XROAi_Rq&_Bl%;*%BZ$osDPU}jdLMeS98#U zIjRI^AuFn6I?C(C+A%$4#U*5AVs=_9Ps&i`+m3E4wDz%UzsK7pm3aLubE?HBpRNKF zQWvSvn~)5C5k6%b%ddgXGED5WePQ(HK25Rtg+k`l9(7q^6jhuwCMrcc@nS#fZEv_y zB@RXL1*CbIDJ(o6BQa%p2_|ueoiSHK(E-V zlFnHE=6`R^YJc*Pz-?xP@vz$H4AAt0DgGR^${PATnFnqC>kigTPdFj^$A`Kcqzk(P z>y?Ml^n%V1{FJ7+!KUfJx~k0vINv%46cf+FDEPudL- zE=z)tV)1pl-5@9-i3ZrS2Gd2f9*oX9U(Z`JZ5pb2^7|3a$a?_GsM`2uqk12s<+%ZqcsE7c*;&ZxFD(Xg|P}UwN0$ zIP$cI?TIhU12xp}+|Hy%Vdd=iR&3o~Wzx4ggDS0=jLfV@6(#&2to^vO+&|V&>yL?9_iH8++Af~h>=i3*@u9%; zVvu{~?V_yjJ(n}L8IDFeInb@v_!Zp>PgZ-?g1pytdw}Xn%BIM37>Lyrp)NR<z|r~ItH(}>6>$=16)1-o0d>4K-Wp1li_U3KDXRL*Ca`34&gnRlLj*K~~Y&k*82 z_Q%CvlUy|(2+dR^TbIhEI;xy$85PWlQ`W2lSh6hQuyN%)Lg{`Uxs6%~|A(}Xh}|oG z&={A0ABf*6`DE?kf+YnE{pPtEo#ZBBJ^9zcxXr%gAfUzZS<;oxu*9u>P>QTG7N3CAq8XyY&+0V|2y3xiW@j`%%6%_SzqT7CMjA z2_+R;oIg-4dNGfM%lr4%0GpGU2u$OEqjT;x~Ry z8V!`xynvvMPECq##)w;*lN!gx=fjw~ygrzcn_HvK_TCm|)npFdSyGKyRd;zS0X6X5 zkJs!efbb&#TcolaQbc_&RUa&%&tL%UOi}XIkAwm?wU09(CQPKs0dBp{p8Ne9(;6?~ zZWh^_N;YL9vy_JKruKW}jACr)B}{4OH-BRblUNe3)r*_dXjVnMNG_FOmd(as!o6pA znmu1-bF`H;u_aZPC4XWC&wmp^Xkb|NW;*%<)ifW1Ri#c3P{2AAEKV*V$vK&ERL$yL zPZ{xt_|M2669tz|OpsCj!R1c!An|xQ*#0X)(lTf~zl@M#FOQHo zE>#&K)%sIwYwyq?pc(8Wu-0H8D&e8pB{&Ln;culh1&Q)~GkySh*W)jGQE%4Vi6`W+ z6(7Pj8H>xhlAApk4?NabRaH7YTWz8UWvVK*0=%W#qb?iZuHppk8NOo#>24(MO$VKW z|C+s`iYngf>h2Kb&_*FnSO>MKXc#c0LVjm?auCmGS%}{6^cS!7mhw}jy6;SadNc;Mvlfn46xC3 zkWbe^b0PN4Uqu%ePSx*R+Ln3=>G7`i_WMkHoUfSrh>(aKqGY)CqH%<#!}x2EUuJ)e zal8;<8p+E~+Vrtlmvm=a^59syn4>gvB3}Do?lt&(7bt-3kNdk(Unk#@h}((8yVWvz zL4@!`)S{4E(~fKi$*8C06}U6T=R1>W@f3b~)lP*Z@$#Cij*59z%zTZ+d9n51D7m&By24yQ7}4D6f~}mfXu&8Jlg6 zA{(JXBOiZZOUdwLhVB>3FsOR%U9oJy<&nW1(vm;-6Std36C3ZGFnad{e2LmKx(ucWJtyGA&SX))t(32e+Z3NVX zJqj81Ks-BQJEf9%mCXY)-BRNl++#d;52OKcIgkSqRjFW?YeKw

*u*4{(zv*@J^LrMJpwTo1jSR{Kiqzc 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 HHRS&QX<0@W literal 0 HcmV?d00001 diff --git a/dtdl/Watteco - Atmo Sensor (50-70-099).json b/dtdl/Watteco - Atmo Sensor (50-70-099).json new file mode 100644 index 0000000..c138c91 --- /dev/null +++ b/dtdl/Watteco - Atmo Sensor (50-70-099).json @@ -0,0 +1,526 @@ +[ + { + "@id": "dtmi:watteco:Atmo;1", + "@type": "Interface", + "contents": [ + { + "@id": "dtmi:watteco:Atmo:data;1", + "@type": "Telemetry", + "comment": "Sens'O Sensors data", + "displayName": { + "en": "data" + }, + "name": "data", + "schema": { + "@id": "dtmi:watteco:Atmo:data:schema;1", + "@type": "Object", + "displayName": { + "en": "Object" + }, + "fields": [ + { + "@id": "dtmi:watteco:Atmo:data:schema:Temperature;1", + "displayName": { + "en": "Temperature" + }, + "name": "Temperature", + "schema": "double" + }, + { + "@id": "dtmi:watteco:Atmo:data:schema:RelativeHumidity;1", + "displayName": { + "en": "RelativeHumidity" + }, + "name": "RelativeHumidity", + "schema": "double" + }, + { + "@id": "dtmi:watteco:Atmo:data:schema:Pressure;1", + "displayName": { + "en": "Pressure" + }, + "name": "Pressure", + "schema": "integer" + }, + { + "@id": "dtmi:watteco:Atmo:data:schema:BatteryLevel;1", + "displayName": { + "en": "BatteryLevel" + }, + "name": "BatteryLevel", + "schema": "double" + } + ] + } + } + ], + "extends": [ + "dtmi:watteco:Atmo:LoRaDevice;1" + ], + "@context": [ + "dtmi:iotcentral:context;2", + "dtmi:dtdl:context;2" + ] + }, + { + "@context": [ + "dtmi:iotcentral:context;2", + "dtmi:dtdl:context;2" + ], + "@id": "dtmi:watteco:Atmo:LoRaDevice;1", + "@type": [ + "Interface", + "NamedInterface" + ], + "contents": [ + { + "@id": "dtmi:watteco:Atmo:LoRaDevice:AppEUI;1", + "@type": "Property", + "description": { + "en": "This is the unique ID of the Application server." + }, + "displayName": { + "en": "AppEUI" + }, + "name": "AppEUI", + "schema": "string", + "writable": true + }, + { + "@id": "dtmi:watteco:Atmo:LoRaDevice:AppKey;1", + "@type": "Property", + "description": { + "en": "The data encryption key used to \"encode\" the messages between the end nodes and the Application Server" + }, + "displayName": { + "en": "AppKey" + }, + "name": "AppKey", + "schema": "string", + "writable": true + }, + { + "@id": "dtmi:watteco:Atmo:LoRaDevice:SensorDecoder;1", + "@type": "Property", + "description": { + "en": "The name of an integrated decoder function or the URI to a decoder in a custom decoder module in the format: http://modulename/api/decodername." + }, + "displayName": { + "en": "SensorDecoder" + }, + "name": "SensorDecoder", + "schema": "string", + "writable": true + }, + { + "@id": "dtmi:watteco:Atmo:LoRaDevice:RX2DataRate;1", + "@type": "Property", + "description": { + "en": "Rx2DataRate (Receive window 2 data rate, currently only supported for OTAA devices): Any of the allowed data rates." + }, + "displayName": { + "en": "RX2DataRate" + }, + "name": "RX2DataRate", + "schema": { + "@id": "dtmi:watteco:Atmo:LoRaDevice:RX2DataRate:schema;1", + "@type": "Enum", + "displayName": { + "en": "Enum" + }, + "enumValues": [ + { + "@id": "dtmi:watteco:Atmo:LoRaDevice:RX2DataRate:schema:SF12BW125;1", + "displayName": { + "en": "SF12BW125" + }, + "enumValue": "SF12BW125", + "name": "SF12BW125" + }, + { + "@id": "dtmi:watteco:Atmo:LoRaDevice:RX2DataRate:schema:SF11BW125;1", + "displayName": { + "en": "SF11BW125" + }, + "enumValue": "SF11BW125", + "name": "SF11BW125" + }, + { + "@id": "dtmi:watteco:Atmo:LoRaDevice:RX2DataRate:schema:SF10BW125;1", + "displayName": { + "en": "SF10BW125" + }, + "enumValue": "SF10BW125", + "name": "SF10BW125" + }, + { + "@id": "dtmi:watteco:Atmo:LoRaDevice:RX2DataRate:schema:SF8BW125;1", + "displayName": { + "en": "SF8BW125" + }, + "enumValue": "SF8BW125", + "name": "SF8BW125" + }, + { + "@id": "dtmi:watteco:Atmo:LoRaDevice:RX2DataRate:schema:SF7BW250;1", + "displayName": { + "en": "SF7BW250" + }, + "enumValue": "SF7BW250", + "name": "SF7BW250" + }, + { + "@id": "dtmi:watteco:Atmo:LoRaDevice:RX2DataRate:schema:SF7BW125;1", + "displayName": { + "en": "SF7BW125" + }, + "enumValue": "SF7BW125", + "name": "SF7BW125" + }, + { + "@id": "dtmi:watteco:Atmo:LoRaDevice:RX2DataRate:schema:SF9BW125;1", + "displayName": { + "en": "SF9BW125" + }, + "enumValue": "SF9BW125", + "name": "SF9BW125" + }, + { + "@id": "dtmi:watteco:Atmo:LoRaDevice:RX2DataRate:schema:SF8BW500;1", + "displayName": { + "en": "SF8BW500" + }, + "enumValue": "SF8BW500", + "name": "SF8BW500" + }, + { + "@id": "dtmi:watteco:Atmo:LoRaDevice:RX2DataRate:schema:SF11BW500;1", + "displayName": { + "en": "SF11BW500" + }, + "enumValue": "SF11BW500", + "name": "SF11BW500" + }, + { + "@id": "dtmi:watteco:Atmo:LoRaDevice:RX2DataRate:schema:SF10BW500;1", + "displayName": { + "en": "SF10BW500" + }, + "enumValue": "SF10BW500", + "name": "SF10BW500" + }, + { + "@id": "dtmi:watteco:Atmo:LoRaDevice:RX2DataRate:schema:SF9BW500;1", + "displayName": { + "en": "SF9BW500" + }, + "enumValue": "SF9BW500", + "name": "SF9BW500" + } + ], + "valueSchema": "string" + }, + "writable": true + }, + { + "@id": "dtmi:watteco:Atmo:LoRaDevice:tmst;1", + "@type": "Telemetry", + "description": { + "en": "Internal timestamp of \"RX finished\" event (32b unsigned)" + }, + "displayName": { + "en": "TimeStamp" + }, + "name": "tmst", + "schema": "integer" + }, + { + "@id": "dtmi:watteco:Atmo:LoRaDevice:time;1", + "@type": "Telemetry", + "description": { + "en": "UTC time of pkt RX, us precision, ISO 8601 'compact' format" + }, + "displayName": { + "en": "Time" + }, + "name": "time", + "schema": "string" + }, + { + "@id": "dtmi:watteco:Atmo:LoRaDevice:tmms;1", + "@type": "Telemetry", + "description": { + "en": "GPS time of pkt RX, number of milliseconds since 06.Jan.1980" + }, + "displayName": { + "en": "GPS Time" + }, + "name": "tmms", + "schema": "integer" + }, + { + "@id": "dtmi:watteco:Atmo:LoRaDevice:freq;1", + "@type": [ + "Telemetry", + "Frequency" + ], + "description": { + "en": "RX central frequency in MHz (unsigned float, Hz precision)" + }, + "displayName": { + "en": "Frequency" + }, + "name": "freq", + "schema": "float", + "unit": "megahertz" + }, + { + "@id": "dtmi:watteco:Atmo:LoRaDevice:chan;1", + "@type": "Telemetry", + "description": { + "en": "Concentrator \"IF\" channel used for RX (unsigned integer)" + }, + "displayName": { + "en": "Channel" + }, + "name": "chan", + "schema": "integer" + }, + { + "@id": "dtmi:watteco:Atmo:LoRaDevice:rfch;1", + "@type": "Telemetry", + "description": { + "en": "Concentrator \"RF chain\" used for RX (unsigned integer)" + }, + "displayName": { + "en": "RF Chain" + }, + "name": "rfch", + "schema": "integer" + }, + { + "@id": "dtmi:watteco:Atmo:LoRaDevice:stat;1", + "@type": "Telemetry", + "description": { + "en": " CRC status: 1 = OK, -1 = fail, 0 = no CRC" + }, + "displayName": { + "en": "Status" + }, + "name": "stat", + "schema": "integer" + }, + { + "@id": "dtmi:watteco:Atmo:LoRaDevice:datr;1", + "@type": "Telemetry", + "description": { + "en": "LoRa datarate identifier (eg. SF12BW500)" + }, + "displayName": { + "en": "Data Rate" + }, + "name": "datr", + "schema": "string" + }, + { + "@id": "dtmi:watteco:Atmo:LoRaDevice:codr;1", + "@type": "Telemetry", + "description": { + "en": "FSK datarate (unsigned, in bits per second)" + }, + "displayName": { + "en": "Coding Rate" + }, + "name": "codr", + "schema": "string" + }, + { + "@id": "dtmi:watteco:Atmo:LoRaDevice:rssi;1", + "@type": "Telemetry", + "description": { + "en": "RSSI in dBm (signed integer, 1 dB precision)" + }, + "displayName": { + "en": "RSSI" + }, + "name": "rssi", + "schema": "integer" + }, + { + "@id": "dtmi:watteco:Atmo:LoRaDevice:lsnr;1", + "@type": "Telemetry", + "description": { + "en": "Lora SNR ratio in dB (signed float, 0.1 dB precision)" + }, + "displayName": { + "en": "LSNR" + }, + "name": "lsnr", + "schema": "double" + }, + { + "@id": "dtmi:watteco:Atmo:LoRaDevice:size;1", + "@type": "Telemetry", + "description": { + "en": "RF packet payload size in bytes (unsigned integer)" + }, + "displayName": { + "en": "RF Size" + }, + "name": "size", + "schema": "integer" + }, + { + "@id": "dtmi:watteco:Atmo:LoRaDevice:modu;1", + "@type": "Telemetry", + "description": { + "en": "Modulation identifier \"LORA\" or \"FSK\"" + }, + "displayName": { + "en": "Modulation" + }, + "name": "modu", + "schema": "string" + }, + { + "@id": "dtmi:watteco:Atmo:LoRaDevice:rawdata;1", + "@type": "Telemetry", + "displayName": { + "en": "Raw Data" + }, + "name": "rawdata", + "schema": "string" + }, + { + "@id": "dtmi:watteco:Atmo:LoRaDevice:fcnt;1", + "@type": "Telemetry", + "displayName": { + "en": "Frame Counter" + }, + "name": "fcnt", + "schema": "integer" + }, + { + "@id": "dtmi:watteco:Atmo:LoRaDevice:port;1", + "@type": "Telemetry", + "displayName": { + "en": "Port" + }, + "name": "port", + "schema": "integer" + }, + { + "@id": "dtmi:watteco:Atmo:LoRaDevice:gatewayid;1", + "@type": "Telemetry", + "displayName": { + "en": "Gateway ID" + }, + "name": "gatewayid", + "schema": "string" + }, + { + "@id": "dtmi:watteco:Atmo:LoRaDevice:edgets;1", + "@type": "Telemetry", + "displayName": { + "en": "Edge TimeStamp" + }, + "name": "edgets", + "schema": "integer" + }, + { + "@id": "dtmi:watteco:Atmo:LoRaDevice:AppSKey;1", + "@type": "Property", + "displayName": { + "en": "AppSKey" + }, + "name": "AppSKey", + "schema": "string" + }, + { + "@id": "dtmi:watteco:Atmo:LoRaDevice:NwkSKey;1", + "@type": "Property", + "displayName": { + "en": "NwkSKey" + }, + "name": "NwkSKey", + "schema": "string" + }, + { + "@id": "dtmi:watteco:Atmo:LoRaDevice:DevAddr;1", + "@type": "Property", + "displayName": { + "en": "DevAddr" + }, + "name": "DevAddr", + "schema": "string" + }, + { + "@id": "dtmi:watteco:Atmo:LoRaDevice:FCntDown;1", + "@type": "Property", + "displayName": { + "en": "FCntDown" + }, + "name": "FCntDown", + "schema": "integer" + }, + { + "@id": "dtmi:watteco:Atmo:LoRaDevice:FCntUp;1", + "@type": "Property", + "displayName": { + "en": "FCntUp" + }, + "name": "FCntUp", + "schema": "integer" + }, + { + "@id": "dtmi:watteco:Atmo:LoRaDevice:DevEUI;1", + "@type": "Property", + "displayName": { + "en": "DevEUI" + }, + "name": "DevEUI", + "schema": "string" + }, + { + "@id": "dtmi:watteco:Atmo:LoRaDevice:NetId;1", + "@type": "Property", + "displayName": { + "en": "NetId" + }, + "name": "NetId", + "schema": "string" + }, + { + "@id": "dtmi:watteco:Atmo:LoRaDevice:DevNonce;1", + "@type": "Property", + "displayName": { + "en": "DevNonce" + }, + "name": "DevNonce", + "schema": "string" + }, + { + "@id": "dtmi:watteco:Atmo:LoRaDevice:RX1DROffset;1", + "@type": "Property", + "displayName": { + "en": "RX1DROffset" + }, + "name": "RX1DROffset", + "schema": "string" + }, + { + "@id": "dtmi:watteco:Atmo:LoRaDevice:RXDelay;1", + "@type": "Property", + "displayName": { + "en": "RXDelay" + }, + "name": "RXDelay", + "schema": "string" + } + ], + "displayName": { + "en": "LoRa Interface" + }, + "name": "LoRa" + } +] \ No newline at end of file diff --git a/dtdl/Watteco - Press'O (50-70-017).json b/dtdl/Watteco - Press'O (50-70-017).json new file mode 100644 index 0000000..2122e8e --- /dev/null +++ b/dtdl/Watteco - Press'O (50-70-017).json @@ -0,0 +1,518 @@ +[ + { + "@id": "dtmi:watteco:PressO;1", + "@type": "Interface", + "contents": [ + { + "@id": "dtmi:watteco:Atmo:data;1", + "@type": "Telemetry", + "comment": "Sens'O Sensors data", + "displayName": { + "en": "data" + }, + "name": "data", + "schema": { + "@id": "dtmi:watteco:Atmo:data:schema;1", + "@type": "Object", + "displayName": { + "en": "Object" + }, + "fields": [ + { + "@id": "dtmi:watteco:Atmo:data:schema:mA;1", + "displayName": { + "en": "4-20mA" + }, + "name": "mA", + "schema": "double" + }, + { + "@id": "dtmi:watteco:Atmo:data:schema:V;1", + "displayName": { + "en": "0-10V" + }, + "name": "V", + "schema": "double" + }, + { + "@id": "dtmi:watteco:Atmo:data:schema:BatteryLevel;1", + "displayName": { + "en": "BatteryLevel" + }, + "name": "BatteryLevel", + "schema": "double" + } + ] + } + } + ], + "extends": [ + "dtmi:watteco:Atmo:LoRaDevice;1" + ], + "@context": [ + "dtmi:iotcentral:context;2", + "dtmi:dtdl:context;2" + ] + }, + { + "@context": [ + "dtmi:iotcentral:context;2", + "dtmi:dtdl:context;2" + ], + "@id": "dtmi:watteco:Atmo:LoRaDevice;1", + "@type": [ + "Interface", + "NamedInterface" + ], + "contents": [ + { + "@id": "dtmi:watteco:Atmo:LoRaDevice:AppEUI;1", + "@type": "Property", + "description": { + "en": "This is the unique ID of the Application server." + }, + "displayName": { + "en": "AppEUI" + }, + "name": "AppEUI", + "schema": "string", + "writable": true + }, + { + "@id": "dtmi:watteco:Atmo:LoRaDevice:AppKey;1", + "@type": "Property", + "description": { + "en": "The data encryption key used to \"encode\" the messages between the end nodes and the Application Server" + }, + "displayName": { + "en": "AppKey" + }, + "name": "AppKey", + "schema": "string", + "writable": true + }, + { + "@id": "dtmi:watteco:Atmo:LoRaDevice:SensorDecoder;1", + "@type": "Property", + "description": { + "en": "The name of an integrated decoder function or the URI to a decoder in a custom decoder module in the format: http://modulename/api/decodername." + }, + "displayName": { + "en": "SensorDecoder" + }, + "name": "SensorDecoder", + "schema": "string", + "writable": true + }, + { + "@id": "dtmi:watteco:Atmo:LoRaDevice:RX2DataRate;1", + "@type": "Property", + "description": { + "en": "Rx2DataRate (Receive window 2 data rate, currently only supported for OTAA devices): Any of the allowed data rates." + }, + "displayName": { + "en": "RX2DataRate" + }, + "name": "RX2DataRate", + "schema": { + "@id": "dtmi:watteco:Atmo:LoRaDevice:RX2DataRate:schema;1", + "@type": "Enum", + "displayName": { + "en": "Enum" + }, + "enumValues": [ + { + "@id": "dtmi:watteco:Atmo:LoRaDevice:RX2DataRate:schema:SF12BW125;1", + "displayName": { + "en": "SF12BW125" + }, + "enumValue": "SF12BW125", + "name": "SF12BW125" + }, + { + "@id": "dtmi:watteco:Atmo:LoRaDevice:RX2DataRate:schema:SF11BW125;1", + "displayName": { + "en": "SF11BW125" + }, + "enumValue": "SF11BW125", + "name": "SF11BW125" + }, + { + "@id": "dtmi:watteco:Atmo:LoRaDevice:RX2DataRate:schema:SF10BW125;1", + "displayName": { + "en": "SF10BW125" + }, + "enumValue": "SF10BW125", + "name": "SF10BW125" + }, + { + "@id": "dtmi:watteco:Atmo:LoRaDevice:RX2DataRate:schema:SF8BW125;1", + "displayName": { + "en": "SF8BW125" + }, + "enumValue": "SF8BW125", + "name": "SF8BW125" + }, + { + "@id": "dtmi:watteco:Atmo:LoRaDevice:RX2DataRate:schema:SF7BW250;1", + "displayName": { + "en": "SF7BW250" + }, + "enumValue": "SF7BW250", + "name": "SF7BW250" + }, + { + "@id": "dtmi:watteco:Atmo:LoRaDevice:RX2DataRate:schema:SF7BW125;1", + "displayName": { + "en": "SF7BW125" + }, + "enumValue": "SF7BW125", + "name": "SF7BW125" + }, + { + "@id": "dtmi:watteco:Atmo:LoRaDevice:RX2DataRate:schema:SF9BW125;1", + "displayName": { + "en": "SF9BW125" + }, + "enumValue": "SF9BW125", + "name": "SF9BW125" + }, + { + "@id": "dtmi:watteco:Atmo:LoRaDevice:RX2DataRate:schema:SF8BW500;1", + "displayName": { + "en": "SF8BW500" + }, + "enumValue": "SF8BW500", + "name": "SF8BW500" + }, + { + "@id": "dtmi:watteco:Atmo:LoRaDevice:RX2DataRate:schema:SF11BW500;1", + "displayName": { + "en": "SF11BW500" + }, + "enumValue": "SF11BW500", + "name": "SF11BW500" + }, + { + "@id": "dtmi:watteco:Atmo:LoRaDevice:RX2DataRate:schema:SF10BW500;1", + "displayName": { + "en": "SF10BW500" + }, + "enumValue": "SF10BW500", + "name": "SF10BW500" + }, + { + "@id": "dtmi:watteco:Atmo:LoRaDevice:RX2DataRate:schema:SF9BW500;1", + "displayName": { + "en": "SF9BW500" + }, + "enumValue": "SF9BW500", + "name": "SF9BW500" + } + ], + "valueSchema": "string" + }, + "writable": true + }, + { + "@id": "dtmi:watteco:Atmo:LoRaDevice:tmst;1", + "@type": "Telemetry", + "description": { + "en": "Internal timestamp of \"RX finished\" event (32b unsigned)" + }, + "displayName": { + "en": "TimeStamp" + }, + "name": "tmst", + "schema": "integer" + }, + { + "@id": "dtmi:watteco:Atmo:LoRaDevice:time;1", + "@type": "Telemetry", + "description": { + "en": "UTC time of pkt RX, us precision, ISO 8601 'compact' format" + }, + "displayName": { + "en": "Time" + }, + "name": "time", + "schema": "string" + }, + { + "@id": "dtmi:watteco:Atmo:LoRaDevice:tmms;1", + "@type": "Telemetry", + "description": { + "en": "GPS time of pkt RX, number of milliseconds since 06.Jan.1980" + }, + "displayName": { + "en": "GPS Time" + }, + "name": "tmms", + "schema": "integer" + }, + { + "@id": "dtmi:watteco:Atmo:LoRaDevice:freq;1", + "@type": [ + "Telemetry", + "Frequency" + ], + "description": { + "en": "RX central frequency in MHz (unsigned float, Hz precision)" + }, + "displayName": { + "en": "Frequency" + }, + "name": "freq", + "schema": "float", + "unit": "megahertz" + }, + { + "@id": "dtmi:watteco:Atmo:LoRaDevice:chan;1", + "@type": "Telemetry", + "description": { + "en": "Concentrator \"IF\" channel used for RX (unsigned integer)" + }, + "displayName": { + "en": "Channel" + }, + "name": "chan", + "schema": "integer" + }, + { + "@id": "dtmi:watteco:Atmo:LoRaDevice:rfch;1", + "@type": "Telemetry", + "description": { + "en": "Concentrator \"RF chain\" used for RX (unsigned integer)" + }, + "displayName": { + "en": "RF Chain" + }, + "name": "rfch", + "schema": "integer" + }, + { + "@id": "dtmi:watteco:Atmo:LoRaDevice:stat;1", + "@type": "Telemetry", + "description": { + "en": " CRC status: 1 = OK, -1 = fail, 0 = no CRC" + }, + "displayName": { + "en": "Status" + }, + "name": "stat", + "schema": "integer" + }, + { + "@id": "dtmi:watteco:Atmo:LoRaDevice:datr;1", + "@type": "Telemetry", + "description": { + "en": "LoRa datarate identifier (eg. SF12BW500)" + }, + "displayName": { + "en": "Data Rate" + }, + "name": "datr", + "schema": "string" + }, + { + "@id": "dtmi:watteco:Atmo:LoRaDevice:codr;1", + "@type": "Telemetry", + "description": { + "en": "FSK datarate (unsigned, in bits per second)" + }, + "displayName": { + "en": "Coding Rate" + }, + "name": "codr", + "schema": "string" + }, + { + "@id": "dtmi:watteco:Atmo:LoRaDevice:rssi;1", + "@type": "Telemetry", + "description": { + "en": "RSSI in dBm (signed integer, 1 dB precision)" + }, + "displayName": { + "en": "RSSI" + }, + "name": "rssi", + "schema": "integer" + }, + { + "@id": "dtmi:watteco:Atmo:LoRaDevice:lsnr;1", + "@type": "Telemetry", + "description": { + "en": "Lora SNR ratio in dB (signed float, 0.1 dB precision)" + }, + "displayName": { + "en": "LSNR" + }, + "name": "lsnr", + "schema": "double" + }, + { + "@id": "dtmi:watteco:Atmo:LoRaDevice:size;1", + "@type": "Telemetry", + "description": { + "en": "RF packet payload size in bytes (unsigned integer)" + }, + "displayName": { + "en": "RF Size" + }, + "name": "size", + "schema": "integer" + }, + { + "@id": "dtmi:watteco:Atmo:LoRaDevice:modu;1", + "@type": "Telemetry", + "description": { + "en": "Modulation identifier \"LORA\" or \"FSK\"" + }, + "displayName": { + "en": "Modulation" + }, + "name": "modu", + "schema": "string" + }, + { + "@id": "dtmi:watteco:Atmo:LoRaDevice:rawdata;1", + "@type": "Telemetry", + "displayName": { + "en": "Raw Data" + }, + "name": "rawdata", + "schema": "string" + }, + { + "@id": "dtmi:watteco:Atmo:LoRaDevice:fcnt;1", + "@type": "Telemetry", + "displayName": { + "en": "Frame Counter" + }, + "name": "fcnt", + "schema": "integer" + }, + { + "@id": "dtmi:watteco:Atmo:LoRaDevice:port;1", + "@type": "Telemetry", + "displayName": { + "en": "Port" + }, + "name": "port", + "schema": "integer" + }, + { + "@id": "dtmi:watteco:Atmo:LoRaDevice:gatewayid;1", + "@type": "Telemetry", + "displayName": { + "en": "Gateway ID" + }, + "name": "gatewayid", + "schema": "string" + }, + { + "@id": "dtmi:watteco:Atmo:LoRaDevice:edgets;1", + "@type": "Telemetry", + "displayName": { + "en": "Edge TimeStamp" + }, + "name": "edgets", + "schema": "integer" + }, + { + "@id": "dtmi:watteco:Atmo:LoRaDevice:AppSKey;1", + "@type": "Property", + "displayName": { + "en": "AppSKey" + }, + "name": "AppSKey", + "schema": "string" + }, + { + "@id": "dtmi:watteco:Atmo:LoRaDevice:NwkSKey;1", + "@type": "Property", + "displayName": { + "en": "NwkSKey" + }, + "name": "NwkSKey", + "schema": "string" + }, + { + "@id": "dtmi:watteco:Atmo:LoRaDevice:DevAddr;1", + "@type": "Property", + "displayName": { + "en": "DevAddr" + }, + "name": "DevAddr", + "schema": "string" + }, + { + "@id": "dtmi:watteco:Atmo:LoRaDevice:FCntDown;1", + "@type": "Property", + "displayName": { + "en": "FCntDown" + }, + "name": "FCntDown", + "schema": "integer" + }, + { + "@id": "dtmi:watteco:Atmo:LoRaDevice:FCntUp;1", + "@type": "Property", + "displayName": { + "en": "FCntUp" + }, + "name": "FCntUp", + "schema": "integer" + }, + { + "@id": "dtmi:watteco:Atmo:LoRaDevice:DevEUI;1", + "@type": "Property", + "displayName": { + "en": "DevEUI" + }, + "name": "DevEUI", + "schema": "string" + }, + { + "@id": "dtmi:watteco:Atmo:LoRaDevice:NetId;1", + "@type": "Property", + "displayName": { + "en": "NetId" + }, + "name": "NetId", + "schema": "string" + }, + { + "@id": "dtmi:watteco:Atmo:LoRaDevice:DevNonce;1", + "@type": "Property", + "displayName": { + "en": "DevNonce" + }, + "name": "DevNonce", + "schema": "string" + }, + { + "@id": "dtmi:watteco:Atmo:LoRaDevice:RX1DROffset;1", + "@type": "Property", + "displayName": { + "en": "RX1DROffset" + }, + "name": "RX1DROffset", + "schema": "string" + }, + { + "@id": "dtmi:watteco:Atmo:LoRaDevice:RXDelay;1", + "@type": "Property", + "displayName": { + "en": "RXDelay" + }, + "name": "RXDelay", + "schema": "string" + } + ], + "displayName": { + "en": "LoRa Interface" + }, + "name": "LoRa" + } + ] \ No newline at end of file diff --git a/dtdl/Watteco - PressO Sensor (50-70-017).jpg b/dtdl/Watteco - PressO Sensor (50-70-017).jpg new file mode 100644 index 0000000000000000000000000000000000000000..9c11cf4c20cc19133ecd26085a4ad6a0ab6cb71f GIT binary patch literal 31732 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 TO>h6d_Ww`d-%o)3uetvP97Fc^ literal 0 HcmV?d00001 diff --git a/dtdl/Watecco - S0 Sensor (50-70-001).jpg b/dtdl/Watteco - S0 Sensor (50-70-001).jpg similarity index 100% rename from dtdl/Watecco - S0 Sensor (50-70-001).jpg rename to dtdl/Watteco - S0 Sensor (50-70-001).jpg diff --git a/dtdl/Watteco - S0 Sensor (50-70-001).json b/dtdl/Watteco - S0 Sensor (50-70-001).json new file mode 100644 index 0000000..42ca5a2 --- /dev/null +++ b/dtdl/Watteco - S0 Sensor (50-70-001).json @@ -0,0 +1,510 @@ +[ + { + "@id": "dtmi:watteco:S0;1", + "@type": "Interface", + "contents": [ + { + "@id": "dtmi:watteco:S0:data;1", + "@type": "Telemetry", + "comment": "Sens'O Sensors data", + "displayName": { + "en": "data" + }, + "name": "data", + "schema": { + "@id": "dtmi:watteco:S0:data:schema;1", + "@type": "Object", + "displayName": { + "en": "Object" + }, + "fields": [ + { + "@id": "dtmi:watteco:S0:data:schema:Volume;1", + "displayName": { + "en": "Volume" + }, + "name": "Volume", + "schema": "double" + }, + { + "@id": "dtmi:watteco:S0:data:schema:DisposableBatteryVoltage;1", + "displayName": { + "en": "DisposableBatteryVoltage" + }, + "name": "DisposableBatteryVoltage", + "schema": "double" + } + ] + } + } + ], + "extends": [ + "dtmi:watteco:S0:LoRaDevice;1" + ], + "@context": [ + "dtmi:iotcentral:context;2", + "dtmi:dtdl:context;2" + ] + }, + { + "@context": [ + "dtmi:iotcentral:context;2", + "dtmi:dtdl:context;2" + ], + "@id": "dtmi:watteco:S0:LoRaDevice;1", + "@type": [ + "Interface", + "NamedInterface" + ], + "contents": [ + { + "@id": "dtmi:watteco:S0:LoRaDevice:AppEUI;1", + "@type": "Property", + "description": { + "en": "This is the unique ID of the Application server." + }, + "displayName": { + "en": "AppEUI" + }, + "name": "AppEUI", + "schema": "string", + "writable": true + }, + { + "@id": "dtmi:watteco:S0:LoRaDevice:AppKey;1", + "@type": "Property", + "description": { + "en": "The data encryption key used to \"encode\" the messages between the end nodes and the Application Server" + }, + "displayName": { + "en": "AppKey" + }, + "name": "AppKey", + "schema": "string", + "writable": true + }, + { + "@id": "dtmi:watteco:S0:LoRaDevice:SensorDecoder;1", + "@type": "Property", + "description": { + "en": "The name of an integrated decoder function or the URI to a decoder in a custom decoder module in the format: http://modulename/api/decodername." + }, + "displayName": { + "en": "SensorDecoder" + }, + "name": "SensorDecoder", + "schema": "string", + "writable": true + }, + { + "@id": "dtmi:watteco:S0:LoRaDevice:RX2DataRate;1", + "@type": "Property", + "description": { + "en": "Rx2DataRate (Receive window 2 data rate, currently only supported for OTAA devices): Any of the allowed data rates." + }, + "displayName": { + "en": "RX2DataRate" + }, + "name": "RX2DataRate", + "schema": { + "@id": "dtmi:watteco:S0:LoRaDevice:RX2DataRate:schema;1", + "@type": "Enum", + "displayName": { + "en": "Enum" + }, + "enumValues": [ + { + "@id": "dtmi:watteco:S0:LoRaDevice:RX2DataRate:schema:SF12BW125;1", + "displayName": { + "en": "SF12BW125" + }, + "enumValue": "SF12BW125", + "name": "SF12BW125" + }, + { + "@id": "dtmi:watteco:S0:LoRaDevice:RX2DataRate:schema:SF11BW125;1", + "displayName": { + "en": "SF11BW125" + }, + "enumValue": "SF11BW125", + "name": "SF11BW125" + }, + { + "@id": "dtmi:watteco:S0:LoRaDevice:RX2DataRate:schema:SF10BW125;1", + "displayName": { + "en": "SF10BW125" + }, + "enumValue": "SF10BW125", + "name": "SF10BW125" + }, + { + "@id": "dtmi:watteco:S0:LoRaDevice:RX2DataRate:schema:SF8BW125;1", + "displayName": { + "en": "SF8BW125" + }, + "enumValue": "SF8BW125", + "name": "SF8BW125" + }, + { + "@id": "dtmi:watteco:S0:LoRaDevice:RX2DataRate:schema:SF7BW250;1", + "displayName": { + "en": "SF7BW250" + }, + "enumValue": "SF7BW250", + "name": "SF7BW250" + }, + { + "@id": "dtmi:watteco:S0:LoRaDevice:RX2DataRate:schema:SF7BW125;1", + "displayName": { + "en": "SF7BW125" + }, + "enumValue": "SF7BW125", + "name": "SF7BW125" + }, + { + "@id": "dtmi:watteco:S0:LoRaDevice:RX2DataRate:schema:SF9BW125;1", + "displayName": { + "en": "SF9BW125" + }, + "enumValue": "SF9BW125", + "name": "SF9BW125" + }, + { + "@id": "dtmi:watteco:S0:LoRaDevice:RX2DataRate:schema:SF8BW500;1", + "displayName": { + "en": "SF8BW500" + }, + "enumValue": "SF8BW500", + "name": "SF8BW500" + }, + { + "@id": "dtmi:watteco:S0:LoRaDevice:RX2DataRate:schema:SF11BW500;1", + "displayName": { + "en": "SF11BW500" + }, + "enumValue": "SF11BW500", + "name": "SF11BW500" + }, + { + "@id": "dtmi:watteco:S0:LoRaDevice:RX2DataRate:schema:SF10BW500;1", + "displayName": { + "en": "SF10BW500" + }, + "enumValue": "SF10BW500", + "name": "SF10BW500" + }, + { + "@id": "dtmi:watteco:S0:LoRaDevice:RX2DataRate:schema:SF9BW500;1", + "displayName": { + "en": "SF9BW500" + }, + "enumValue": "SF9BW500", + "name": "SF9BW500" + } + ], + "valueSchema": "string" + }, + "writable": true + }, + { + "@id": "dtmi:watteco:S0:LoRaDevice:tmst;1", + "@type": "Telemetry", + "description": { + "en": "Internal timestamp of \"RX finished\" event (32b unsigned)" + }, + "displayName": { + "en": "TimeStamp" + }, + "name": "tmst", + "schema": "integer" + }, + { + "@id": "dtmi:watteco:S0:LoRaDevice:time;1", + "@type": "Telemetry", + "description": { + "en": "UTC time of pkt RX, us precision, ISO 8601 'compact' format" + }, + "displayName": { + "en": "Time" + }, + "name": "time", + "schema": "string" + }, + { + "@id": "dtmi:watteco:S0:LoRaDevice:tmms;1", + "@type": "Telemetry", + "description": { + "en": "GPS time of pkt RX, number of milliseconds since 06.Jan.1980" + }, + "displayName": { + "en": "GPS Time" + }, + "name": "tmms", + "schema": "integer" + }, + { + "@id": "dtmi:watteco:S0:LoRaDevice:freq;1", + "@type": [ + "Telemetry", + "Frequency" + ], + "description": { + "en": "RX central frequency in MHz (unsigned float, Hz precision)" + }, + "displayName": { + "en": "Frequency" + }, + "name": "freq", + "schema": "float", + "unit": "megahertz" + }, + { + "@id": "dtmi:watteco:S0:LoRaDevice:chan;1", + "@type": "Telemetry", + "description": { + "en": "Concentrator \"IF\" channel used for RX (unsigned integer)" + }, + "displayName": { + "en": "Channel" + }, + "name": "chan", + "schema": "integer" + }, + { + "@id": "dtmi:watteco:S0:LoRaDevice:rfch;1", + "@type": "Telemetry", + "description": { + "en": "Concentrator \"RF chain\" used for RX (unsigned integer)" + }, + "displayName": { + "en": "RF Chain" + }, + "name": "rfch", + "schema": "integer" + }, + { + "@id": "dtmi:watteco:S0:LoRaDevice:stat;1", + "@type": "Telemetry", + "description": { + "en": " CRC status: 1 = OK, -1 = fail, 0 = no CRC" + }, + "displayName": { + "en": "Status" + }, + "name": "stat", + "schema": "integer" + }, + { + "@id": "dtmi:watteco:S0:LoRaDevice:datr;1", + "@type": "Telemetry", + "description": { + "en": "LoRa datarate identifier (eg. SF12BW500)" + }, + "displayName": { + "en": "Data Rate" + }, + "name": "datr", + "schema": "string" + }, + { + "@id": "dtmi:watteco:S0:LoRaDevice:codr;1", + "@type": "Telemetry", + "description": { + "en": "FSK datarate (unsigned, in bits per second)" + }, + "displayName": { + "en": "Coding Rate" + }, + "name": "codr", + "schema": "string" + }, + { + "@id": "dtmi:watteco:S0:LoRaDevice:rssi;1", + "@type": "Telemetry", + "description": { + "en": "RSSI in dBm (signed integer, 1 dB precision)" + }, + "displayName": { + "en": "RSSI" + }, + "name": "rssi", + "schema": "integer" + }, + { + "@id": "dtmi:watteco:S0:LoRaDevice:lsnr;1", + "@type": "Telemetry", + "description": { + "en": "Lora SNR ratio in dB (signed float, 0.1 dB precision)" + }, + "displayName": { + "en": "LSNR" + }, + "name": "lsnr", + "schema": "double" + }, + { + "@id": "dtmi:watteco:S0:LoRaDevice:size;1", + "@type": "Telemetry", + "description": { + "en": "RF packet payload size in bytes (unsigned integer)" + }, + "displayName": { + "en": "RF Size" + }, + "name": "size", + "schema": "integer" + }, + { + "@id": "dtmi:watteco:S0:LoRaDevice:modu;1", + "@type": "Telemetry", + "description": { + "en": "Modulation identifier \"LORA\" or \"FSK\"" + }, + "displayName": { + "en": "Modulation" + }, + "name": "modu", + "schema": "string" + }, + { + "@id": "dtmi:watteco:S0:LoRaDevice:rawdata;1", + "@type": "Telemetry", + "displayName": { + "en": "Raw Data" + }, + "name": "rawdata", + "schema": "string" + }, + { + "@id": "dtmi:watteco:S0:LoRaDevice:fcnt;1", + "@type": "Telemetry", + "displayName": { + "en": "Frame Counter" + }, + "name": "fcnt", + "schema": "integer" + }, + { + "@id": "dtmi:watteco:S0:LoRaDevice:port;1", + "@type": "Telemetry", + "displayName": { + "en": "Port" + }, + "name": "port", + "schema": "integer" + }, + { + "@id": "dtmi:watteco:S0:LoRaDevice:gatewayid;1", + "@type": "Telemetry", + "displayName": { + "en": "Gateway ID" + }, + "name": "gatewayid", + "schema": "string" + }, + { + "@id": "dtmi:watteco:S0:LoRaDevice:edgets;1", + "@type": "Telemetry", + "displayName": { + "en": "Edge TimeStamp" + }, + "name": "edgets", + "schema": "integer" + }, + { + "@id": "dtmi:watteco:S0:LoRaDevice:AppSKey;1", + "@type": "Property", + "displayName": { + "en": "AppSKey" + }, + "name": "AppSKey", + "schema": "string" + }, + { + "@id": "dtmi:watteco:S0:LoRaDevice:NwkSKey;1", + "@type": "Property", + "displayName": { + "en": "NwkSKey" + }, + "name": "NwkSKey", + "schema": "string" + }, + { + "@id": "dtmi:watteco:S0:LoRaDevice:DevAddr;1", + "@type": "Property", + "displayName": { + "en": "DevAddr" + }, + "name": "DevAddr", + "schema": "string" + }, + { + "@id": "dtmi:watteco:S0:LoRaDevice:FCntDown;1", + "@type": "Property", + "displayName": { + "en": "FCntDown" + }, + "name": "FCntDown", + "schema": "integer" + }, + { + "@id": "dtmi:watteco:S0:LoRaDevice:FCntUp;1", + "@type": "Property", + "displayName": { + "en": "FCntUp" + }, + "name": "FCntUp", + "schema": "integer" + }, + { + "@id": "dtmi:watteco:S0:LoRaDevice:DevEUI;1", + "@type": "Property", + "displayName": { + "en": "DevEUI" + }, + "name": "DevEUI", + "schema": "string" + }, + { + "@id": "dtmi:watteco:S0:LoRaDevice:NetId;1", + "@type": "Property", + "displayName": { + "en": "NetId" + }, + "name": "NetId", + "schema": "string" + }, + { + "@id": "dtmi:watteco:S0:LoRaDevice:DevNonce;1", + "@type": "Property", + "displayName": { + "en": "DevNonce" + }, + "name": "DevNonce", + "schema": "string" + }, + { + "@id": "dtmi:watteco:S0:LoRaDevice:RX1DROffset;1", + "@type": "Property", + "displayName": { + "en": "RX1DROffset" + }, + "name": "RX1DROffset", + "schema": "string" + }, + { + "@id": "dtmi:watteco:S0:LoRaDevice:RXDelay;1", + "@type": "Property", + "displayName": { + "en": "RXDelay" + }, + "name": "RXDelay", + "schema": "string" + } + ], + "displayName": { + "en": "LoRa Interface" + }, + "name": "LoRa" + } +] \ No newline at end of file diff --git a/dtdl/Watecco - Sens'O (50-70-011).png b/dtdl/Watteco - Sens'O (50-70-011).png similarity index 100% rename from dtdl/Watecco - Sens'O (50-70-011).png rename to dtdl/Watteco - Sens'O (50-70-011).png diff --git a/dtdl/Watteco - Sens'O Sensor (50-70-011).json b/dtdl/Watteco - Sens'O Sensor (50-70-011).json new file mode 100644 index 0000000..695a4e4 --- /dev/null +++ b/dtdl/Watteco - Sens'O Sensor (50-70-011).json @@ -0,0 +1,590 @@ +[ + { + "@id": "dtmi:watteco:SensO;1", + "@type": "Interface", + "contents": [ + { + "@id": "dtmi:watteco:SensO:data;1", + "@type": "Telemetry", + "comment": "Sens'O Sensors data", + "displayName": { + "en": "data" + }, + "name": "data", + "schema": { + "@id": "dtmi:watteco:SensO:data:schema;1", + "@type": "Object", + "displayName": { + "en": "Object" + }, + "fields": [ + { + "@id": "dtmi:watteco:SensO:data:schema:Volume;1", + "displayName": { + "en": "Volume" + }, + "name": "Volume", + "schema": "double" + }, + { + "@id": "dtmi:watteco:SensO:data:schema:DisposableBatteryVoltage;1", + "displayName": { + "en": "DisposableBatteryVoltage" + }, + "name": "DisposableBatteryVoltage", + "schema": "double" + }, + { + "@id": "dtmi:watteco:SensO:data:Status;1", + "displayName": { + "en": "Status" + }, + "name": "Status", + "schema": { + "@id": "dtmi:watteco:SensO:data:Status:schema;1", + "@type": "Object", + "displayName": { + "en": "Status" + }, + "fields": [ + { + "@id": "dtmi:watteco:SensO:data:Status:schema:Freeze;1", + "displayName": { + "en": "Freeze" + }, + "name": "Freeze", + "schema": "boolean" + }, + { + "@id": "dtmi:watteco:SensO:data:Status:schema:Installation;1", + "displayName": { + "en": "Installation" + }, + "name": "Installation", + "schema": "boolean" + }, + { + "@id": "dtmi:watteco:SensO:data:Status:schema:Battery;1", + "displayName": { + "en": "Battery" + }, + "name": "Battery", + "schema": "boolean" + }, + { + "@id": "dtmi:watteco:SensO:data:Status:schema:Fraud;1", + "displayName": { + "en": "Fraud" + }, + "name": "Fraud", + "schema": "boolean" + }, + { + "@id": "dtmi:watteco:SensO:data:Status:schema:BackWaterLevel3;1", + "displayName": { + "en": "BackWaterLevel3" + }, + "name": "BackWaterLevel3", + "schema": "boolean" + }, + { + "@id": "dtmi:watteco:SensO:data:Status:schema:BackWaterLevel2;1", + "displayName": { + "en": "BackWaterLevel2" + }, + "name": "BackWaterLevel2", + "schema": "boolean" + }, + { + "@id": "dtmi:watteco:SensO:data:Status:schema:BackWaterLevel1;1", + "displayName": { + "en": "BackWaterLevel1" + }, + "name": "BackWaterLevel1", + "schema": "boolean" + }, + { + "@id": "dtmi:watteco:SensO:data:Status:schema:Leak;1", + "displayName": { + "en": "Leak" + }, + "name": "Leak", + "schema": "boolean" + } + ] + } + } + ] + } + } + ], + "extends": [ + "dtmi:watteco:SensO:LoRaDevice;1" + ], + "@context": [ + "dtmi:iotcentral:context;2", + "dtmi:dtdl:context;2" + ] + }, + { + "@context": [ + "dtmi:iotcentral:context;2", + "dtmi:dtdl:context;2" + ], + "@id": "dtmi:watteco:SensO:LoRaDevice;1", + "@type": [ + "Interface", + "NamedInterface" + ], + "contents": [ + { + "@id": "dtmi:watteco:SensO:LoRaDevice:AppEUI;1", + "@type": "Property", + "description": { + "en": "This is the unique ID of the Application server." + }, + "displayName": { + "en": "AppEUI" + }, + "name": "AppEUI", + "schema": "string", + "writable": true + }, + { + "@id": "dtmi:watteco:SensO:LoRaDevice:AppKey;1", + "@type": "Property", + "description": { + "en": "The data encryption key used to \"encode\" the messages between the end nodes and the Application Server" + }, + "displayName": { + "en": "AppKey" + }, + "name": "AppKey", + "schema": "string", + "writable": true + }, + { + "@id": "dtmi:watteco:SensO:LoRaDevice:SensorDecoder;1", + "@type": "Property", + "description": { + "en": "The name of an integrated decoder function or the URI to a decoder in a custom decoder module in the format: http://modulename/api/decodername." + }, + "displayName": { + "en": "SensorDecoder" + }, + "name": "SensorDecoder", + "schema": "string", + "writable": true + }, + { + "@id": "dtmi:watteco:SensO:LoRaDevice:RX2DataRate;1", + "@type": "Property", + "description": { + "en": "Rx2DataRate (Receive window 2 data rate, currently only supported for OTAA devices): Any of the allowed data rates." + }, + "displayName": { + "en": "RX2DataRate" + }, + "name": "RX2DataRate", + "schema": { + "@id": "dtmi:watteco:SensO:LoRaDevice:RX2DataRate:schema;1", + "@type": "Enum", + "displayName": { + "en": "Enum" + }, + "enumValues": [ + { + "@id": "dtmi:watteco:SensO:LoRaDevice:RX2DataRate:schema:SF12BW125;1", + "displayName": { + "en": "SF12BW125" + }, + "enumValue": "SF12BW125", + "name": "SF12BW125" + }, + { + "@id": "dtmi:watteco:SensO:LoRaDevice:RX2DataRate:schema:SF11BW125;1", + "displayName": { + "en": "SF11BW125" + }, + "enumValue": "SF11BW125", + "name": "SF11BW125" + }, + { + "@id": "dtmi:watteco:SensO:LoRaDevice:RX2DataRate:schema:SF10BW125;1", + "displayName": { + "en": "SF10BW125" + }, + "enumValue": "SF10BW125", + "name": "SF10BW125" + }, + { + "@id": "dtmi:watteco:SensO:LoRaDevice:RX2DataRate:schema:SF8BW125;1", + "displayName": { + "en": "SF8BW125" + }, + "enumValue": "SF8BW125", + "name": "SF8BW125" + }, + { + "@id": "dtmi:watteco:SensO:LoRaDevice:RX2DataRate:schema:SF7BW250;1", + "displayName": { + "en": "SF7BW250" + }, + "enumValue": "SF7BW250", + "name": "SF7BW250" + }, + { + "@id": "dtmi:watteco:SensO:LoRaDevice:RX2DataRate:schema:SF7BW125;1", + "displayName": { + "en": "SF7BW125" + }, + "enumValue": "SF7BW125", + "name": "SF7BW125" + }, + { + "@id": "dtmi:watteco:SensO:LoRaDevice:RX2DataRate:schema:SF9BW125;1", + "displayName": { + "en": "SF9BW125" + }, + "enumValue": "SF9BW125", + "name": "SF9BW125" + }, + { + "@id": "dtmi:watteco:SensO:LoRaDevice:RX2DataRate:schema:SF8BW500;1", + "displayName": { + "en": "SF8BW500" + }, + "enumValue": "SF8BW500", + "name": "SF8BW500" + }, + { + "@id": "dtmi:watteco:SensO:LoRaDevice:RX2DataRate:schema:SF11BW500;1", + "displayName": { + "en": "SF11BW500" + }, + "enumValue": "SF11BW500", + "name": "SF11BW500" + }, + { + "@id": "dtmi:watteco:SensO:LoRaDevice:RX2DataRate:schema:SF10BW500;1", + "displayName": { + "en": "SF10BW500" + }, + "enumValue": "SF10BW500", + "name": "SF10BW500" + }, + { + "@id": "dtmi:watteco:SensO:LoRaDevice:RX2DataRate:schema:SF9BW500;1", + "displayName": { + "en": "SF9BW500" + }, + "enumValue": "SF9BW500", + "name": "SF9BW500" + } + ], + "valueSchema": "string" + }, + "writable": true + }, + { + "@id": "dtmi:watteco:SensO:LoRaDevice:tmst;1", + "@type": "Telemetry", + "description": { + "en": "Internal timestamp of \"RX finished\" event (32b unsigned)" + }, + "displayName": { + "en": "TimeStamp" + }, + "name": "tmst", + "schema": "integer" + }, + { + "@id": "dtmi:watteco:SensO:LoRaDevice:time;1", + "@type": "Telemetry", + "description": { + "en": "UTC time of pkt RX, us precision, ISO 8601 'compact' format" + }, + "displayName": { + "en": "Time" + }, + "name": "time", + "schema": "string" + }, + { + "@id": "dtmi:watteco:SensO:LoRaDevice:tmms;1", + "@type": "Telemetry", + "description": { + "en": "GPS time of pkt RX, number of milliseconds since 06.Jan.1980" + }, + "displayName": { + "en": "GPS Time" + }, + "name": "tmms", + "schema": "integer" + }, + { + "@id": "dtmi:watteco:SensO:LoRaDevice:freq;1", + "@type": [ + "Telemetry", + "Frequency" + ], + "description": { + "en": "RX central frequency in MHz (unsigned float, Hz precision)" + }, + "displayName": { + "en": "Frequency" + }, + "name": "freq", + "schema": "float", + "unit": "megahertz" + }, + { + "@id": "dtmi:watteco:SensO:LoRaDevice:chan;1", + "@type": "Telemetry", + "description": { + "en": "Concentrator \"IF\" channel used for RX (unsigned integer)" + }, + "displayName": { + "en": "Channel" + }, + "name": "chan", + "schema": "integer" + }, + { + "@id": "dtmi:watteco:SensO:LoRaDevice:rfch;1", + "@type": "Telemetry", + "description": { + "en": "Concentrator \"RF chain\" used for RX (unsigned integer)" + }, + "displayName": { + "en": "RF Chain" + }, + "name": "rfch", + "schema": "integer" + }, + { + "@id": "dtmi:watteco:SensO:LoRaDevice:stat;1", + "@type": "Telemetry", + "description": { + "en": " CRC status: 1 = OK, -1 = fail, 0 = no CRC" + }, + "displayName": { + "en": "Status" + }, + "name": "stat", + "schema": "integer" + }, + { + "@id": "dtmi:watteco:SensO:LoRaDevice:datr;1", + "@type": "Telemetry", + "description": { + "en": "LoRa datarate identifier (eg. SF12BW500)" + }, + "displayName": { + "en": "Data Rate" + }, + "name": "datr", + "schema": "string" + }, + { + "@id": "dtmi:watteco:SensO:LoRaDevice:codr;1", + "@type": "Telemetry", + "description": { + "en": "FSK datarate (unsigned, in bits per second)" + }, + "displayName": { + "en": "Coding Rate" + }, + "name": "codr", + "schema": "string" + }, + { + "@id": "dtmi:watteco:SensO:LoRaDevice:rssi;1", + "@type": "Telemetry", + "description": { + "en": "RSSI in dBm (signed integer, 1 dB precision)" + }, + "displayName": { + "en": "RSSI" + }, + "name": "rssi", + "schema": "integer" + }, + { + "@id": "dtmi:watteco:SensO:LoRaDevice:lsnr;1", + "@type": "Telemetry", + "description": { + "en": "Lora SNR ratio in dB (signed float, 0.1 dB precision)" + }, + "displayName": { + "en": "LSNR" + }, + "name": "lsnr", + "schema": "double" + }, + { + "@id": "dtmi:watteco:SensO:LoRaDevice:size;1", + "@type": "Telemetry", + "description": { + "en": "RF packet payload size in bytes (unsigned integer)" + }, + "displayName": { + "en": "RF Size" + }, + "name": "size", + "schema": "integer" + }, + { + "@id": "dtmi:watteco:SensO:LoRaDevice:modu;1", + "@type": "Telemetry", + "description": { + "en": "Modulation identifier \"LORA\" or \"FSK\"" + }, + "displayName": { + "en": "Modulation" + }, + "name": "modu", + "schema": "string" + }, + { + "@id": "dtmi:watteco:SensO:LoRaDevice:rawdata;1", + "@type": "Telemetry", + "displayName": { + "en": "Raw Data" + }, + "name": "rawdata", + "schema": "string" + }, + { + "@id": "dtmi:watteco:SensO:LoRaDevice:fcnt;1", + "@type": "Telemetry", + "displayName": { + "en": "Frame Counter" + }, + "name": "fcnt", + "schema": "integer" + }, + { + "@id": "dtmi:watteco:SensO:LoRaDevice:port;1", + "@type": "Telemetry", + "displayName": { + "en": "Port" + }, + "name": "port", + "schema": "integer" + }, + { + "@id": "dtmi:watteco:SensO:LoRaDevice:gatewayid;1", + "@type": "Telemetry", + "displayName": { + "en": "Gateway ID" + }, + "name": "gatewayid", + "schema": "string" + }, + { + "@id": "dtmi:watteco:SensO:LoRaDevice:edgets;1", + "@type": "Telemetry", + "displayName": { + "en": "Edge TimeStamp" + }, + "name": "edgets", + "schema": "integer" + }, + { + "@id": "dtmi:watteco:SensO:LoRaDevice:AppSKey;1", + "@type": "Property", + "displayName": { + "en": "AppSKey" + }, + "name": "AppSKey", + "schema": "string" + }, + { + "@id": "dtmi:watteco:SensO:LoRaDevice:NwkSKey;1", + "@type": "Property", + "displayName": { + "en": "NwkSKey" + }, + "name": "NwkSKey", + "schema": "string" + }, + { + "@id": "dtmi:watteco:SensO:LoRaDevice:DevAddr;1", + "@type": "Property", + "displayName": { + "en": "DevAddr" + }, + "name": "DevAddr", + "schema": "string" + }, + { + "@id": "dtmi:watteco:SensO:LoRaDevice:FCntDown;1", + "@type": "Property", + "displayName": { + "en": "FCntDown" + }, + "name": "FCntDown", + "schema": "integer" + }, + { + "@id": "dtmi:watteco:SensO:LoRaDevice:FCntUp;1", + "@type": "Property", + "displayName": { + "en": "FCntUp" + }, + "name": "FCntUp", + "schema": "integer" + }, + { + "@id": "dtmi:watteco:SensO:LoRaDevice:DevEUI;1", + "@type": "Property", + "displayName": { + "en": "DevEUI" + }, + "name": "DevEUI", + "schema": "string" + }, + { + "@id": "dtmi:watteco:SensO:LoRaDevice:NetId;1", + "@type": "Property", + "displayName": { + "en": "NetId" + }, + "name": "NetId", + "schema": "string" + }, + { + "@id": "dtmi:watteco:SensO:LoRaDevice:DevNonce;1", + "@type": "Property", + "displayName": { + "en": "DevNonce" + }, + "name": "DevNonce", + "schema": "string" + }, + { + "@id": "dtmi:watteco:SensO:LoRaDevice:RX1DROffset;1", + "@type": "Property", + "displayName": { + "en": "RX1DROffset" + }, + "name": "RX1DROffset", + "schema": "string" + }, + { + "@id": "dtmi:watteco:SensO:LoRaDevice:RXDelay;1", + "@type": "Property", + "displayName": { + "en": "RXDelay" + }, + "name": "RXDelay", + "schema": "string" + } + ], + "displayName": { + "en": "LoRa Interface" + }, + "name": "LoRa" + } + ] \ No newline at end of file diff --git a/dtdl/Watecco - THr Sensor (50-70-007).jpg b/dtdl/Watteco - THr Sensor (50-70-007).jpg similarity index 100% rename from dtdl/Watecco - THr Sensor (50-70-007).jpg rename to dtdl/Watteco - THr Sensor (50-70-007).jpg diff --git a/dtdl/Watteco - THr Sensor (50-70-007).json b/dtdl/Watteco - THr Sensor (50-70-007).json new file mode 100644 index 0000000..3b1f1cd --- /dev/null +++ b/dtdl/Watteco - THr Sensor (50-70-007).json @@ -0,0 +1,526 @@ +[ + { + "@id": "dtmi:watteco:THr;1", + "@type": "Interface", + "contents": [ + { + "@id": "dtmi:watteco:THr:data;1", + "@type": "Telemetry", + "comment": "THr Sensors data", + "displayName": { + "en": "data" + }, + "name": "data", + "schema": { + "@id": "dtmi:watteco:THr:data:schema;1", + "@type": "Object", + "displayName": { + "en": "Object" + }, + "fields": [ + { + "@id": "dtmi:watteco:THr:data:schema:Temperature;1", + "displayName": { + "en": "Temperature" + }, + "name": "Temperature", + "schema": "double" + }, + { + "@id": "dtmi:watteco:THr:data:schema:Illuminance;1", + "displayName": { + "en": "Illuminance" + }, + "name": "Illuminance", + "schema": "double" + }, + { + "@id": "dtmi:watteco:THr:data:schema:DisposableBatteryVoltage;1", + "displayName": { + "en": "DisposableBatteryVoltage" + }, + "name": "DisposableBatteryVoltage", + "schema": "double" + }, + { + "@id": "dtmi:watteco:THr:data:schema:RechargeableBatteryVoltage;1", + "displayName": { + "en": "RechargeableBatteryVoltage" + }, + "name": "RechargeableBatteryVoltage", + "schema": "double" + } + ] + } + } + ], + "extends": [ + "dtmi:watteco:THr:LoRaDevice;1" + ], + "@context": [ + "dtmi:iotcentral:context;2", + "dtmi:dtdl:context;2" + ] + }, + { + "@context": [ + "dtmi:iotcentral:context;2", + "dtmi:dtdl:context;2" + ], + "@id": "dtmi:watteco:THr:LoRaDevice;1", + "@type": [ + "Interface", + "NamedInterface" + ], + "contents": [ + { + "@id": "dtmi:watteco:THr:LoRaDevice:AppEUI;1", + "@type": "Property", + "description": { + "en": "This is the unique ID of the Application server." + }, + "displayName": { + "en": "AppEUI" + }, + "name": "AppEUI", + "schema": "string", + "writable": true + }, + { + "@id": "dtmi:watteco:THr:LoRaDevice:AppKey;1", + "@type": "Property", + "description": { + "en": "The data encryption key used to \"encode\" the messages between the end nodes and the Application Server" + }, + "displayName": { + "en": "AppKey" + }, + "name": "AppKey", + "schema": "string", + "writable": true + }, + { + "@id": "dtmi:watteco:THr:LoRaDevice:SensorDecoder;1", + "@type": "Property", + "description": { + "en": "The name of an integrated decoder function or the URI to a decoder in a custom decoder module in the format: http://modulename/api/decodername." + }, + "displayName": { + "en": "SensorDecoder" + }, + "name": "SensorDecoder", + "schema": "string", + "writable": true + }, + { + "@id": "dtmi:watteco:THr:LoRaDevice:RX2DataRate;1", + "@type": "Property", + "description": { + "en": "Rx2DataRate (Receive window 2 data rate, currently only supported for OTAA devices): Any of the allowed data rates." + }, + "displayName": { + "en": "RX2DataRate" + }, + "name": "RX2DataRate", + "schema": { + "@id": "dtmi:watteco:THr:LoRaDevice:RX2DataRate:schema;1", + "@type": "Enum", + "displayName": { + "en": "Enum" + }, + "enumValues": [ + { + "@id": "dtmi:watteco:THr:LoRaDevice:RX2DataRate:schema:SF12BW125;1", + "displayName": { + "en": "SF12BW125" + }, + "enumValue": "SF12BW125", + "name": "SF12BW125" + }, + { + "@id": "dtmi:watteco:THr:LoRaDevice:RX2DataRate:schema:SF11BW125;1", + "displayName": { + "en": "SF11BW125" + }, + "enumValue": "SF11BW125", + "name": "SF11BW125" + }, + { + "@id": "dtmi:watteco:THr:LoRaDevice:RX2DataRate:schema:SF10BW125;1", + "displayName": { + "en": "SF10BW125" + }, + "enumValue": "SF10BW125", + "name": "SF10BW125" + }, + { + "@id": "dtmi:watteco:THr:LoRaDevice:RX2DataRate:schema:SF8BW125;1", + "displayName": { + "en": "SF8BW125" + }, + "enumValue": "SF8BW125", + "name": "SF8BW125" + }, + { + "@id": "dtmi:watteco:THr:LoRaDevice:RX2DataRate:schema:SF7BW250;1", + "displayName": { + "en": "SF7BW250" + }, + "enumValue": "SF7BW250", + "name": "SF7BW250" + }, + { + "@id": "dtmi:watteco:THr:LoRaDevice:RX2DataRate:schema:SF7BW125;1", + "displayName": { + "en": "SF7BW125" + }, + "enumValue": "SF7BW125", + "name": "SF7BW125" + }, + { + "@id": "dtmi:watteco:THr:LoRaDevice:RX2DataRate:schema:SF9BW125;1", + "displayName": { + "en": "SF9BW125" + }, + "enumValue": "SF9BW125", + "name": "SF9BW125" + }, + { + "@id": "dtmi:watteco:THr:LoRaDevice:RX2DataRate:schema:SF8BW500;1", + "displayName": { + "en": "SF8BW500" + }, + "enumValue": "SF8BW500", + "name": "SF8BW500" + }, + { + "@id": "dtmi:watteco:THr:LoRaDevice:RX2DataRate:schema:SF11BW500;1", + "displayName": { + "en": "SF11BW500" + }, + "enumValue": "SF11BW500", + "name": "SF11BW500" + }, + { + "@id": "dtmi:watteco:THr:LoRaDevice:RX2DataRate:schema:SF10BW500;1", + "displayName": { + "en": "SF10BW500" + }, + "enumValue": "SF10BW500", + "name": "SF10BW500" + }, + { + "@id": "dtmi:watteco:THr:LoRaDevice:RX2DataRate:schema:SF9BW500;1", + "displayName": { + "en": "SF9BW500" + }, + "enumValue": "SF9BW500", + "name": "SF9BW500" + } + ], + "valueSchema": "string" + }, + "writable": true + }, + { + "@id": "dtmi:watteco:THr:LoRaDevice:tmst;1", + "@type": "Telemetry", + "description": { + "en": "Internal timestamp of \"RX finished\" event (32b unsigned)" + }, + "displayName": { + "en": "TimeStamp" + }, + "name": "tmst", + "schema": "integer" + }, + { + "@id": "dtmi:watteco:THr:LoRaDevice:time;1", + "@type": "Telemetry", + "description": { + "en": "UTC time of pkt RX, us precision, ISO 8601 'compact' format" + }, + "displayName": { + "en": "Time" + }, + "name": "time", + "schema": "string" + }, + { + "@id": "dtmi:watteco:THr:LoRaDevice:tmms;1", + "@type": "Telemetry", + "description": { + "en": "GPS time of pkt RX, number of milliseconds since 06.Jan.1980" + }, + "displayName": { + "en": "GPS Time" + }, + "name": "tmms", + "schema": "integer" + }, + { + "@id": "dtmi:watteco:THr:LoRaDevice:freq;1", + "@type": [ + "Telemetry", + "Frequency" + ], + "description": { + "en": "RX central frequency in MHz (unsigned float, Hz precision)" + }, + "displayName": { + "en": "Frequency" + }, + "name": "freq", + "schema": "float", + "unit": "megahertz" + }, + { + "@id": "dtmi:watteco:THr:LoRaDevice:chan;1", + "@type": "Telemetry", + "description": { + "en": "Concentrator \"IF\" channel used for RX (unsigned integer)" + }, + "displayName": { + "en": "Channel" + }, + "name": "chan", + "schema": "integer" + }, + { + "@id": "dtmi:watteco:THr:LoRaDevice:rfch;1", + "@type": "Telemetry", + "description": { + "en": "Concentrator \"RF chain\" used for RX (unsigned integer)" + }, + "displayName": { + "en": "RF Chain" + }, + "name": "rfch", + "schema": "integer" + }, + { + "@id": "dtmi:watteco:THr:LoRaDevice:stat;1", + "@type": "Telemetry", + "description": { + "en": " CRC status: 1 = OK, -1 = fail, 0 = no CRC" + }, + "displayName": { + "en": "Status" + }, + "name": "stat", + "schema": "integer" + }, + { + "@id": "dtmi:watteco:THr:LoRaDevice:datr;1", + "@type": "Telemetry", + "description": { + "en": "LoRa datarate identifier (eg. SF12BW500)" + }, + "displayName": { + "en": "Data Rate" + }, + "name": "datr", + "schema": "string" + }, + { + "@id": "dtmi:watteco:THr:LoRaDevice:codr;1", + "@type": "Telemetry", + "description": { + "en": "FSK datarate (unsigned, in bits per second)" + }, + "displayName": { + "en": "Coding Rate" + }, + "name": "codr", + "schema": "string" + }, + { + "@id": "dtmi:watteco:THr:LoRaDevice:rssi;1", + "@type": "Telemetry", + "description": { + "en": "RSSI in dBm (signed integer, 1 dB precision)" + }, + "displayName": { + "en": "RSSI" + }, + "name": "rssi", + "schema": "integer" + }, + { + "@id": "dtmi:watteco:THr:LoRaDevice:lsnr;1", + "@type": "Telemetry", + "description": { + "en": "Lora SNR ratio in dB (signed float, 0.1 dB precision)" + }, + "displayName": { + "en": "LSNR" + }, + "name": "lsnr", + "schema": "double" + }, + { + "@id": "dtmi:watteco:THr:LoRaDevice:size;1", + "@type": "Telemetry", + "description": { + "en": "RF packet payload size in bytes (unsigned integer)" + }, + "displayName": { + "en": "RF Size" + }, + "name": "size", + "schema": "integer" + }, + { + "@id": "dtmi:watteco:THr:LoRaDevice:modu;1", + "@type": "Telemetry", + "description": { + "en": "Modulation identifier \"LORA\" or \"FSK\"" + }, + "displayName": { + "en": "Modulation" + }, + "name": "modu", + "schema": "string" + }, + { + "@id": "dtmi:watteco:THr:LoRaDevice:rawdata;1", + "@type": "Telemetry", + "displayName": { + "en": "Raw Data" + }, + "name": "rawdata", + "schema": "string" + }, + { + "@id": "dtmi:watteco:THr:LoRaDevice:fcnt;1", + "@type": "Telemetry", + "displayName": { + "en": "Frame Counter" + }, + "name": "fcnt", + "schema": "integer" + }, + { + "@id": "dtmi:watteco:THr:LoRaDevice:port;1", + "@type": "Telemetry", + "displayName": { + "en": "Port" + }, + "name": "port", + "schema": "integer" + }, + { + "@id": "dtmi:watteco:THr:LoRaDevice:gatewayid;1", + "@type": "Telemetry", + "displayName": { + "en": "Gateway ID" + }, + "name": "gatewayid", + "schema": "string" + }, + { + "@id": "dtmi:watteco:THr:LoRaDevice:edgets;1", + "@type": "Telemetry", + "displayName": { + "en": "Edge TimeStamp" + }, + "name": "edgets", + "schema": "integer" + }, + { + "@id": "dtmi:watteco:THr:LoRaDevice:AppSKey;1", + "@type": "Property", + "displayName": { + "en": "AppSKey" + }, + "name": "AppSKey", + "schema": "string" + }, + { + "@id": "dtmi:watteco:THr:LoRaDevice:NwkSKey;1", + "@type": "Property", + "displayName": { + "en": "NwkSKey" + }, + "name": "NwkSKey", + "schema": "string" + }, + { + "@id": "dtmi:watteco:THr:LoRaDevice:DevAddr;1", + "@type": "Property", + "displayName": { + "en": "DevAddr" + }, + "name": "DevAddr", + "schema": "string" + }, + { + "@id": "dtmi:watteco:THr:LoRaDevice:FCntDown;1", + "@type": "Property", + "displayName": { + "en": "FCntDown" + }, + "name": "FCntDown", + "schema": "integer" + }, + { + "@id": "dtmi:watteco:THr:LoRaDevice:FCntUp;1", + "@type": "Property", + "displayName": { + "en": "FCntUp" + }, + "name": "FCntUp", + "schema": "integer" + }, + { + "@id": "dtmi:watteco:THr:LoRaDevice:DevEUI;1", + "@type": "Property", + "displayName": { + "en": "DevEUI" + }, + "name": "DevEUI", + "schema": "string" + }, + { + "@id": "dtmi:watteco:THr:LoRaDevice:NetId;1", + "@type": "Property", + "displayName": { + "en": "NetId" + }, + "name": "NetId", + "schema": "string" + }, + { + "@id": "dtmi:watteco:THr:LoRaDevice:DevNonce;1", + "@type": "Property", + "displayName": { + "en": "DevNonce" + }, + "name": "DevNonce", + "schema": "string" + }, + { + "@id": "dtmi:watteco:THr:LoRaDevice:RX1DROffset;1", + "@type": "Property", + "displayName": { + "en": "RX1DROffset" + }, + "name": "RX1DROffset", + "schema": "string" + }, + { + "@id": "dtmi:watteco:THr:LoRaDevice:RXDelay;1", + "@type": "Property", + "displayName": { + "en": "RXDelay" + }, + "name": "RXDelay", + "schema": "string" + } + ], + "displayName": { + "en": "LoRa Interface" + }, + "name": "LoRa" + } +] \ No newline at end of file diff --git a/dtdl/Watteco - VAQA'O Sensor (50-70-168).json b/dtdl/Watteco - VAQA'O Sensor (50-70-168).json new file mode 100644 index 0000000..5d798e4 --- /dev/null +++ b/dtdl/Watteco - VAQA'O Sensor (50-70-168).json @@ -0,0 +1,614 @@ +[ + { + "@id": "dtmi:watteco:vaqaoplus;1", + "@type": "Interface", + "contents": [ + { + "@id": "dtmi:watteco:vaqaoplus:data;1", + "@type": "Telemetry", + "comment": "VaqaO Sensors data", + "displayName": { + "en": "data" + }, + "name": "data", + "schema": { + "@id": "dtmi:watteco:vaqaoplus:data:schema;1", + "@type": "Object", + "displayName": { + "en": "Object" + }, + "fields": [ + { + "@id": "dtmi:watteco:vaqaoplus:data:schema:Temperature;1", + "displayName": { + "en": "Temperature" + }, + "name": "Temperature", + "schema": "double" + }, + { + "@id": "dtmi:watteco:vaqaoplus:data:schema:RelativeHumidity;1", + "displayName": { + "en": "RelativeHumidity" + }, + "name": "RelativeHumidity", + "schema": "double" + }, + { + "@id": "dtmi:watteco:vaqaoplus:data:schema:CO2;1", + "displayName": { + "en": "CO2" + }, + "name": "CO2", + "schema": "double" + }, + { + "@id": "dtmi:watteco:vaqaoplus:data:schema:COV;1", + "displayName": { + "en": "COV" + }, + "name": "COV", + "schema": "double" + }, + { + "@id": "dtmi:watteco:vaqaoplus:data:schema:LUX;1", + "displayName": { + "en": "LUX" + }, + "name": "LUX", + "schema": "double" + }, + { + "@id": "dtmi:watteco:vaqaoplus:data:schema:Pressure;1", + "displayName": { + "en": "Pressure" + }, + "name": "Pressure", + "schema": "double" + }, + { + "@id": "dtmi:watteco:vaqaoplus:data:schema:Occupancy;1", + "displayName": { + "en": "Occupancy" + }, + "name": "Occupancy", + "schema": { + "@type": "Enum", + "enumValues": [ + { + "displayName": { + "en": "Occupied" + }, + "enumValue": 1, + "name": "Occupied" + }, + { + "displayName": { + "en": "Vacant" + }, + "enumValue": 0, + "name": "Vacant" + } + ], + "valueSchema": "integer" + } + }, + { + "@id": "dtmi:watteco:vaqaoplus:data:schema:Configuration;1", + "displayName": { + "en": "Configuration" + }, + "name": "Configuration", + "schema": { + "@id": "dtmi:watteco:vaqaoplus:data:schema:Configuration:schema;1", + "@type": "Object", + "fields": [ + { + "@id": "dtmi:watteco:vaqaoplus:data:schema:Configuration:schema:CurrentPowerMode;1", + "displayName": { + "en": "CurrentPowerMode" + }, + "name": "CurrentPowerMode", + "schema": "string" + }, + { + "@id": "dtmi:watteco:vaqaoplus:data:schema:Configuration:schema:AvailablePowerSourceBitField;1", + "displayName": { + "en": "AvailablePowerSourceBitField" + }, + "name": "AvailablePowerSourceBitField", + "schema": "integer" + }, + { + "@id": "dtmi:watteco:vaqaoplus:data:schema:Configuration:schema:DisposableBatteryVoltage;1", + "displayName": { + "en": "DisposableBatteryVoltage" + }, + "name": "DisposableBatteryVoltage", + "schema": "double" + }, + { + "@id": "dtmi:watteco:vaqaoplus:data:schema:Configuration:schema:CurrentPowerSource;1", + "displayName": { + "en": "CurrentPowerSource" + }, + "name": "CurrentPowerSource", + "schema": "string" + } + ] + } + } + ] + } + } + ], + "extends": [ + "dtmi:watteco:vaqaoplus:LoRaDevice;1" + ], + "@context": [ + "dtmi:iotcentral:context;2", + "dtmi:dtdl:context;2" + ] + }, + { + "@context": [ + "dtmi:iotcentral:context;2", + "dtmi:dtdl:context;2" + ], + "@id": "dtmi:watteco:vaqaoplus:LoRaDevice;1", + "@type": [ + "Interface", + "NamedInterface" + ], + "contents": [ + { + "@id": "dtmi:watteco:vaqaoplus:LoRaDevice:AppEUI;1", + "@type": "Property", + "description": { + "en": "This is the unique ID of the Application server." + }, + "displayName": { + "en": "AppEUI" + }, + "name": "AppEUI", + "schema": "string", + "writable": true + }, + { + "@id": "dtmi:watteco:vaqaoplus:LoRaDevice:AppKey;1", + "@type": "Property", + "description": { + "en": "The data encryption key used to \"encode\" the messages between the end nodes and the Application Server" + }, + "displayName": { + "en": "AppKey" + }, + "name": "AppKey", + "schema": "string", + "writable": true + }, + { + "@id": "dtmi:watteco:vaqaoplus:LoRaDevice:SensorDecoder;1", + "@type": "Property", + "description": { + "en": "The name of an integrated decoder function or the URI to a decoder in a custom decoder module in the format: http://modulename/api/decodername." + }, + "displayName": { + "en": "SensorDecoder" + }, + "name": "SensorDecoder", + "schema": "string", + "writable": true + }, + { + "@id": "dtmi:watteco:vaqaoplus:LoRaDevice:RX2DataRate;1", + "@type": "Property", + "description": { + "en": "Rx2DataRate (Receive window 2 data rate, currently only supported for OTAA devices): Any of the allowed data rates." + }, + "displayName": { + "en": "RX2DataRate" + }, + "name": "RX2DataRate", + "schema": { + "@id": "dtmi:watteco:vaqaoplus:LoRaDevice:RX2DataRate:schema;1", + "@type": "Enum", + "displayName": { + "en": "Enum" + }, + "enumValues": [ + { + "@id": "dtmi:watteco:vaqaoplus:LoRaDevice:RX2DataRate:schema:SF12BW125;1", + "displayName": { + "en": "SF12BW125" + }, + "enumValue": "SF12BW125", + "name": "SF12BW125" + }, + { + "@id": "dtmi:watteco:vaqaoplus:LoRaDevice:RX2DataRate:schema:SF11BW125;1", + "displayName": { + "en": "SF11BW125" + }, + "enumValue": "SF11BW125", + "name": "SF11BW125" + }, + { + "@id": "dtmi:watteco:vaqaoplus:LoRaDevice:RX2DataRate:schema:SF10BW125;1", + "displayName": { + "en": "SF10BW125" + }, + "enumValue": "SF10BW125", + "name": "SF10BW125" + }, + { + "@id": "dtmi:watteco:vaqaoplus:LoRaDevice:RX2DataRate:schema:SF8BW125;1", + "displayName": { + "en": "SF8BW125" + }, + "enumValue": "SF8BW125", + "name": "SF8BW125" + }, + { + "@id": "dtmi:watteco:vaqaoplus:LoRaDevice:RX2DataRate:schema:SF7BW250;1", + "displayName": { + "en": "SF7BW250" + }, + "enumValue": "SF7BW250", + "name": "SF7BW250" + }, + { + "@id": "dtmi:watteco:vaqaoplus:LoRaDevice:RX2DataRate:schema:SF7BW125;1", + "displayName": { + "en": "SF7BW125" + }, + "enumValue": "SF7BW125", + "name": "SF7BW125" + }, + { + "@id": "dtmi:watteco:vaqaoplus:LoRaDevice:RX2DataRate:schema:SF9BW125;1", + "displayName": { + "en": "SF9BW125" + }, + "enumValue": "SF9BW125", + "name": "SF9BW125" + }, + { + "@id": "dtmi:watteco:vaqaoplus:LoRaDevice:RX2DataRate:schema:SF8BW500;1", + "displayName": { + "en": "SF8BW500" + }, + "enumValue": "SF8BW500", + "name": "SF8BW500" + }, + { + "@id": "dtmi:watteco:vaqaoplus:LoRaDevice:RX2DataRate:schema:SF11BW500;1", + "displayName": { + "en": "SF11BW500" + }, + "enumValue": "SF11BW500", + "name": "SF11BW500" + }, + { + "@id": "dtmi:watteco:vaqaoplus:LoRaDevice:RX2DataRate:schema:SF10BW500;1", + "displayName": { + "en": "SF10BW500" + }, + "enumValue": "SF10BW500", + "name": "SF10BW500" + }, + { + "@id": "dtmi:watteco:vaqaoplus:LoRaDevice:RX2DataRate:schema:SF9BW500;1", + "displayName": { + "en": "SF9BW500" + }, + "enumValue": "SF9BW500", + "name": "SF9BW500" + } + ], + "valueSchema": "string" + }, + "writable": true + }, + { + "@id": "dtmi:watteco:vaqaoplus:LoRaDevice:tmst;1", + "@type": "Telemetry", + "description": { + "en": "Internal timestamp of \"RX finished\" event (32b unsigned)" + }, + "displayName": { + "en": "TimeStamp" + }, + "name": "tmst", + "schema": "integer" + }, + { + "@id": "dtmi:watteco:vaqaoplus:LoRaDevice:time;1", + "@type": "Telemetry", + "description": { + "en": "UTC time of pkt RX, us precision, ISO 8601 'compact' format" + }, + "displayName": { + "en": "Time" + }, + "name": "time", + "schema": "string" + }, + { + "@id": "dtmi:watteco:vaqaoplus:LoRaDevice:tmms;1", + "@type": "Telemetry", + "description": { + "en": "GPS time of pkt RX, number of milliseconds since 06.Jan.1980" + }, + "displayName": { + "en": "GPS Time" + }, + "name": "tmms", + "schema": "integer" + }, + { + "@id": "dtmi:watteco:vaqaoplus:LoRaDevice:freq;1", + "@type": [ + "Telemetry", + "Frequency" + ], + "description": { + "en": "RX central frequency in MHz (unsigned float, Hz precision)" + }, + "displayName": { + "en": "Frequency" + }, + "name": "freq", + "schema": "float", + "unit": "megahertz" + }, + { + "@id": "dtmi:watteco:vaqaoplus:LoRaDevice:chan;1", + "@type": "Telemetry", + "description": { + "en": "Concentrator \"IF\" channel used for RX (unsigned integer)" + }, + "displayName": { + "en": "Channel" + }, + "name": "chan", + "schema": "integer" + }, + { + "@id": "dtmi:watteco:vaqaoplus:LoRaDevice:rfch;1", + "@type": "Telemetry", + "description": { + "en": "Concentrator \"RF chain\" used for RX (unsigned integer)" + }, + "displayName": { + "en": "RF Chain" + }, + "name": "rfch", + "schema": "integer" + }, + { + "@id": "dtmi:watteco:vaqaoplus:LoRaDevice:stat;1", + "@type": "Telemetry", + "description": { + "en": " CRC status: 1 = OK, -1 = fail, 0 = no CRC" + }, + "displayName": { + "en": "Status" + }, + "name": "stat", + "schema": "integer" + }, + { + "@id": "dtmi:watteco:vaqaoplus:LoRaDevice:datr;1", + "@type": "Telemetry", + "description": { + "en": "LoRa datarate identifier (eg. SF12BW500)" + }, + "displayName": { + "en": "Data Rate" + }, + "name": "datr", + "schema": "string" + }, + { + "@id": "dtmi:watteco:vaqaoplus:LoRaDevice:codr;1", + "@type": "Telemetry", + "description": { + "en": "FSK datarate (unsigned, in bits per second)" + }, + "displayName": { + "en": "Coding Rate" + }, + "name": "codr", + "schema": "string" + }, + { + "@id": "dtmi:watteco:vaqaoplus:LoRaDevice:rssi;1", + "@type": "Telemetry", + "description": { + "en": "RSSI in dBm (signed integer, 1 dB precision)" + }, + "displayName": { + "en": "RSSI" + }, + "name": "rssi", + "schema": "integer" + }, + { + "@id": "dtmi:watteco:vaqaoplus:LoRaDevice:lsnr;1", + "@type": "Telemetry", + "description": { + "en": "Lora SNR ratio in dB (signed float, 0.1 dB precision)" + }, + "displayName": { + "en": "LSNR" + }, + "name": "lsnr", + "schema": "double" + }, + { + "@id": "dtmi:watteco:vaqaoplus:LoRaDevice:size;1", + "@type": "Telemetry", + "description": { + "en": "RF packet payload size in bytes (unsigned integer)" + }, + "displayName": { + "en": "RF Size" + }, + "name": "size", + "schema": "integer" + }, + { + "@id": "dtmi:watteco:vaqaoplus:LoRaDevice:modu;1", + "@type": "Telemetry", + "description": { + "en": "Modulation identifier \"LORA\" or \"FSK\"" + }, + "displayName": { + "en": "Modulation" + }, + "name": "modu", + "schema": "string" + }, + { + "@id": "dtmi:watteco:vaqaoplus:LoRaDevice:rawdata;1", + "@type": "Telemetry", + "displayName": { + "en": "Raw Data" + }, + "name": "rawdata", + "schema": "string" + }, + { + "@id": "dtmi:watteco:vaqaoplus:LoRaDevice:fcnt;1", + "@type": "Telemetry", + "displayName": { + "en": "Frame Counter" + }, + "name": "fcnt", + "schema": "integer" + }, + { + "@id": "dtmi:watteco:vaqaoplus:LoRaDevice:port;1", + "@type": "Telemetry", + "displayName": { + "en": "Port" + }, + "name": "port", + "schema": "integer" + }, + { + "@id": "dtmi:watteco:vaqaoplus:LoRaDevice:gatewayid;1", + "@type": "Telemetry", + "displayName": { + "en": "Gateway ID" + }, + "name": "gatewayid", + "schema": "string" + }, + { + "@id": "dtmi:watteco:vaqaoplus:LoRaDevice:edgets;1", + "@type": "Telemetry", + "displayName": { + "en": "Edge TimeStamp" + }, + "name": "edgets", + "schema": "integer" + }, + { + "@id": "dtmi:watteco:vaqaoplus:LoRaDevice:AppSKey;1", + "@type": "Property", + "displayName": { + "en": "AppSKey" + }, + "name": "AppSKey", + "schema": "string" + }, + { + "@id": "dtmi:watteco:vaqaoplus:LoRaDevice:NwkSKey;1", + "@type": "Property", + "displayName": { + "en": "NwkSKey" + }, + "name": "NwkSKey", + "schema": "string" + }, + { + "@id": "dtmi:watteco:vaqaoplus:LoRaDevice:DevAddr;1", + "@type": "Property", + "displayName": { + "en": "DevAddr" + }, + "name": "DevAddr", + "schema": "string" + }, + { + "@id": "dtmi:watteco:vaqaoplus:LoRaDevice:FCntDown;1", + "@type": "Property", + "displayName": { + "en": "FCntDown" + }, + "name": "FCntDown", + "schema": "integer" + }, + { + "@id": "dtmi:watteco:vaqaoplus:LoRaDevice:FCntUp;1", + "@type": "Property", + "displayName": { + "en": "FCntUp" + }, + "name": "FCntUp", + "schema": "integer" + }, + { + "@id": "dtmi:watteco:vaqaoplus:LoRaDevice:DevEUI;1", + "@type": "Property", + "displayName": { + "en": "DevEUI" + }, + "name": "DevEUI", + "schema": "string" + }, + { + "@id": "dtmi:watteco:vaqaoplus:LoRaDevice:NetId;1", + "@type": "Property", + "displayName": { + "en": "NetId" + }, + "name": "NetId", + "schema": "string" + }, + { + "@id": "dtmi:watteco:vaqaoplus:LoRaDevice:DevNonce;1", + "@type": "Property", + "displayName": { + "en": "DevNonce" + }, + "name": "DevNonce", + "schema": "string" + }, + { + "@id": "dtmi:watteco:vaqaoplus:LoRaDevice:RX1DROffset;1", + "@type": "Property", + "displayName": { + "en": "RX1DROffset" + }, + "name": "RX1DROffset", + "schema": "string" + }, + { + "@id": "dtmi:watteco:vaqaoplus:LoRaDevice:RXDelay;1", + "@type": "Property", + "displayName": { + "en": "RXDelay" + }, + "name": "RXDelay", + "schema": "string" + } + ], + "displayName": { + "en": "LoRa Interface" + }, + "name": "LoRa" + } +] \ No newline at end of file diff --git a/dtdl/Watecco - VAQA'O Sensor (50-70-168).png b/dtdl/Watteco - VAQA'O Sensor (50-70-168).png similarity index 100% rename from dtdl/Watecco - VAQA'O Sensor (50-70-168).png rename to dtdl/Watteco - VAQA'O Sensor (50-70-168).png diff --git a/src/modules/WattecoDecoderModule/Batch b/src/modules/WattecoDecoderModule/Batch new file mode 160000 index 0000000..9ea0a36 --- /dev/null +++ b/src/modules/WattecoDecoderModule/Batch @@ -0,0 +1 @@ +Subproject commit 9ea0a36e4f60a4fc0aef7c4ed6bcb9b3407bc3d9 diff --git a/src/modules/WattecoDecoderModule/Codec-Report-Batch-Python b/src/modules/WattecoDecoderModule/Codec-Report-Batch-Python deleted file mode 160000 index 1a62868..0000000 --- a/src/modules/WattecoDecoderModule/Codec-Report-Batch-Python +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 1a62868de60254c25f16340f47e88484b46bc383 diff --git a/src/modules/WattecoDecoderModule/Codec-Report-Standard-Python b/src/modules/WattecoDecoderModule/Codec-Report-Standard-Python deleted file mode 160000 index d56dbee..0000000 --- a/src/modules/WattecoDecoderModule/Codec-Report-Standard-Python +++ /dev/null @@ -1 +0,0 @@ -Subproject commit d56dbee7e8629462ae241e38be6113a889a6d954 diff --git a/src/modules/WattecoDecoderModule/Dockerfile.amd64 b/src/modules/WattecoDecoderModule/Dockerfile.amd64 index 8ad8326..cd565fb 100644 --- a/src/modules/WattecoDecoderModule/Dockerfile.amd64 +++ b/src/modules/WattecoDecoderModule/Dockerfile.amd64 @@ -2,27 +2,24 @@ FROM busybox as builder WORKDIR /src -COPY ./Codec-Report-Standard-Python/srcWatteco/* ./Codec/Standard/ -COPY ./Codec-Report-Batch-Python/br_uncompress.py ./Codec/Batch/ -COPY ./Codec-Report-Batch-Python/constants.py ./Codec/Batch/ -COPY ./requirements.txt . +COPY . . -RUN sed -i 's/from ZCL/from .ZCL/' ./Codec/Standard/Decoding_Functions.py -RUN sed -i 's/from ZCL/from .ZCL/' ./Codec/Standard/ZCL_FRAME.py -RUN sed -i 's/from ZCL/from .ZCL/' ./Codec/Standard/ZCL.py -RUN sed -i 's/from WTC_CodecTools/from .WTC_CodecTools/' ./Codec/Standard/ZCL.py -RUN sed -i 's/import constants/from . import constants/' ./Codec/Batch/br_uncompress.py - -COPY ./main.py . +RUN chmod +x replaceCodecImports.sh && ./replaceCodecImports.sh FROM amd64/python:3.7-slim-buster EXPOSE 80 -WORKDIR / +WORKDIR /app + +COPY --from=builder /src/Batch/ ./Batch/ +COPY --from=builder /src/Standard/ ./Standard/ -COPY --from=builder /src/* /app/ +COPY --from=builder /src/main.py ./ +COPY --from=builder /src/requirements.txt ./ -RUN pip install -r /app/requirements.txt +RUN pip install -r requirements.txt + +WORKDIR / CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "80"] \ No newline at end of file diff --git a/src/modules/WattecoDecoderModule/Dockerfile.amd64.debug b/src/modules/WattecoDecoderModule/Dockerfile.amd64.debug index 1981002..c9a3815 100644 --- a/src/modules/WattecoDecoderModule/Dockerfile.amd64.debug +++ b/src/modules/WattecoDecoderModule/Dockerfile.amd64.debug @@ -2,28 +2,25 @@ FROM busybox as builder WORKDIR /src -COPY ./Codec-Report-Standard-Python/srcWatteco/* ./Codec/Standard/ -COPY ./Codec-Report-Batch-Python/br_uncompress.py ./Codec/Batch/ -COPY ./Codec-Report-Batch-Python/constants.py ./Codec/Batch/ -COPY ./requirements.txt . +COPY . . -RUN sed -i 's/from ZCL/from .ZCL/' ./Codec/Standard/Decoding_Functions.py -RUN sed -i 's/from ZCL/from .ZCL/' ./Codec/Standard/ZCL_FRAME.py -RUN sed -i 's/from ZCL/from .ZCL/' ./Codec/Standard/ZCL.py -RUN sed -i 's/from WTC_CodecTools/from .WTC_CodecTools/' ./Codec/Standard/ZCL.py -RUN sed -i 's/import constants/from . import constants/' ./Codec/Batch/br_uncompress.py - -COPY ./main.py . +RUN chmod +x replaceCodecImports.sh && ./replaceCodecImports.sh FROM amd64/python:3.7-slim-buster EXPOSE 80 -WORKDIR / +WORKDIR /app + +COPY --from=builder /src/Batch/ ./Batch/ +COPY --from=builder /src/Standard/ ./Standard/ -COPY --from=builder /src/* /app/ +COPY --from=builder /src/main.py ./ +COPY --from=builder /src/requirements.txt ./ RUN pip install ptvsd==4.1.3 -RUN pip install -r /app/requirements.txt +RUN pip install -r requirements.txt + +WORKDIR / CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "80"] \ No newline at end of file diff --git a/src/modules/WattecoDecoderModule/Dockerfile.arm32v7 b/src/modules/WattecoDecoderModule/Dockerfile.arm32v7 index 08e9fdc..c8c8070 100644 --- a/src/modules/WattecoDecoderModule/Dockerfile.arm32v7 +++ b/src/modules/WattecoDecoderModule/Dockerfile.arm32v7 @@ -2,27 +2,23 @@ FROM busybox as builder WORKDIR /src -COPY ./Codec-Report-Standard-Python/srcWatteco/* ./Codec/Standard/ -COPY ./Codec-Report-Batch-Python/br_uncompress.py ./Codec/Batch/ -COPY ./Codec-Report-Batch-Python/constants.py ./Codec/Batch/ -COPY ./requirements.txt . - -RUN sed -i 's/from ZCL/from .ZCL/' ./Codec/Standard/Decoding_Functions.py -RUN sed -i 's/from ZCL/from .ZCL/' ./Codec/Standard/ZCL_FRAME.py -RUN sed -i 's/from ZCL/from .ZCL/' ./Codec/Standard/ZCL.py -RUN sed -i 's/from WTC_CodecTools/from .WTC_CodecTools/' ./Codec/Standard/ZCL.py -RUN sed -i 's/import constants/from . import constants/' ./Codec/Batch/br_uncompress.py - -COPY ./main.py . +COPY . . +RUN chmod +x replaceCodecImports.sh && ./replaceCodecImports.sh FROM arm32v7/python:3.7-slim-buster EXPOSE 80 -WORKDIR / +WORKDIR /app -COPY --from=builder /src/* /app/ +COPY --from=builder /src/Batch/ ./Batch/ +COPY --from=builder /src/Standard/ ./Standard/ -RUN pip install -r /app/requirements.txt +COPY --from=builder /src/main.py ./ +COPY --from=builder /src/requirements.txt ./ + +RUN pip install -r requirements.txt + +WORKDIR / CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "80"] \ No newline at end of file diff --git a/src/modules/WattecoDecoderModule/Dockerfile.arm32v7.debug b/src/modules/WattecoDecoderModule/Dockerfile.arm32v7.debug index e9a2eb7..f51d930 100644 --- a/src/modules/WattecoDecoderModule/Dockerfile.arm32v7.debug +++ b/src/modules/WattecoDecoderModule/Dockerfile.arm32v7.debug @@ -2,28 +2,25 @@ FROM busybox as builder WORKDIR /src -COPY ./Codec-Report-Standard-Python/srcWatteco/* ./Codec/Standard/ -COPY ./Codec-Report-Batch-Python/br_uncompress.py ./Codec/Batch/ -COPY ./Codec-Report-Batch-Python/constants.py ./Codec/Batch/ -COPY ./requirements.txt . +COPY . . -RUN sed -i 's/from ZCL/from .ZCL/' ./Codec/Standard/Decoding_Functions.py -RUN sed -i 's/from ZCL/from .ZCL/' ./Codec/Standard/ZCL_FRAME.py -RUN sed -i 's/from ZCL/from .ZCL/' ./Codec/Standard/ZCL.py -RUN sed -i 's/from WTC_CodecTools/from .WTC_CodecTools/' ./Codec/Standard/ZCL.py -RUN sed -i 's/import constants/from . import constants/' ./Codec/Batch/br_uncompress.py - -COPY ./main.py . +RUN chmod +x replaceCodecImports.sh && ./replaceCodecImports.sh FROM arm32v7/python:3.7-slim-buster EXPOSE 80 -WORKDIR / +WORKDIR /app + +COPY --from=builder /src/Batch/ ./Batch/ +COPY --from=builder /src/Standard/ ./Standard/ -COPY --from=builder /src/* /app/ +COPY --from=builder /src/main.py ./ +COPY --from=builder /src/requirements.txt ./ RUN pip install ptvsd==4.1.3 -RUN pip install -r /app/requirements.txt +RUN pip install -r requirements.txt + +WORKDIR / CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "80"] \ No newline at end of file diff --git a/src/modules/WattecoDecoderModule/Dockerfile.arm64v8 b/src/modules/WattecoDecoderModule/Dockerfile.arm64v8 index f21bb33..b8f9064 100644 --- a/src/modules/WattecoDecoderModule/Dockerfile.arm64v8 +++ b/src/modules/WattecoDecoderModule/Dockerfile.arm64v8 @@ -2,27 +2,24 @@ FROM busybox as builder WORKDIR /src -COPY ./Codec-Report-Standard-Python/srcWatteco/* ./Codec/Standard/ -COPY ./Codec-Report-Batch-Python/br_uncompress.py ./Codec/Batch/ -COPY ./Codec-Report-Batch-Python/constants.py ./Codec/Batch/ -COPY ./requirements.txt . +COPY . . -RUN sed -i 's/from ZCL/from .ZCL/' ./Codec/Standard/Decoding_Functions.py -RUN sed -i 's/from ZCL/from .ZCL/' ./Codec/Standard/ZCL_FRAME.py -RUN sed -i 's/from ZCL/from .ZCL/' ./Codec/Standard/ZCL.py -RUN sed -i 's/from WTC_CodecTools/from .WTC_CodecTools/' ./Codec/Standard/ZCL.py -RUN sed -i 's/import constants/from . import constants/' ./Codec/Batch/br_uncompress.py - -COPY ./main.py . +RUN chmod +x replaceCodecImports.sh && ./replaceCodecImports.sh FROM arm64v8/python:3.7-slim-buster EXPOSE 80 -WORKDIR / +WORKDIR /app + +COPY --from=builder /src/Batch/ ./Batch/ +COPY --from=builder /src/Standard/ ./Standard/ -COPY --from=builder /src/* /app/ +COPY --from=builder /src/main.py ./ +COPY --from=builder /src/requirements.txt ./ -RUN pip install -r /app/requirements.txt +RUN pip install -r requirements.txt + +WORKDIR / CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "80"] \ No newline at end of file diff --git a/src/modules/WattecoDecoderModule/Dockerfile.arm64v8.debug b/src/modules/WattecoDecoderModule/Dockerfile.arm64v8.debug index 1028126..4e5ebd5 100644 --- a/src/modules/WattecoDecoderModule/Dockerfile.arm64v8.debug +++ b/src/modules/WattecoDecoderModule/Dockerfile.arm64v8.debug @@ -2,28 +2,25 @@ FROM busybox as builder WORKDIR /src -COPY ./Codec-Report-Standard-Python/srcWatteco/* ./Codec/Standard/ -COPY ./Codec-Report-Batch-Python/br_uncompress.py ./Codec/Batch/ -COPY ./Codec-Report-Batch-Python/constants.py ./Codec/Batch/ -COPY ./requirements.txt . +COPY . . -RUN sed -i 's/from ZCL/from .ZCL/' ./Codec/Standard/Decoding_Functions.py -RUN sed -i 's/from ZCL/from .ZCL/' ./Codec/Standard/ZCL_FRAME.py -RUN sed -i 's/from ZCL/from .ZCL/' ./Codec/Standard/ZCL.py -RUN sed -i 's/from WTC_CodecTools/from .WTC_CodecTools/' ./Codec/Standard/ZCL.py -RUN sed -i 's/import constants/from . import constants/' ./Codec/Batch/br_uncompress.py - -COPY ./main.py . +RUN chmod +x replaceCodecImports.sh && ./replaceCodecImports.sh FROM arm64v8/python:3.7-slim-buster EXPOSE 80 -WORKDIR / +WORKDIR /app + +COPY --from=builder /src/Batch/ ./Batch/ +COPY --from=builder /src/Standard/ ./Standard/ -COPY --from=builder /src/* /app/ +COPY --from=builder /src/main.py ./ +COPY --from=builder /src/requirements.txt ./ RUN pip install ptvsd==4.1.3 -RUN pip install -r /app/requirements.txt +RUN pip install -r requirements.txt + +WORKDIR / CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "80"] \ No newline at end of file diff --git a/src/modules/WattecoDecoderModule/Standard b/src/modules/WattecoDecoderModule/Standard new file mode 160000 index 0000000..44c1d62 --- /dev/null +++ b/src/modules/WattecoDecoderModule/Standard @@ -0,0 +1 @@ +Subproject commit 44c1d62e75c03b5b2010b0e2323366fdc9b01f5f diff --git a/src/modules/WattecoDecoderModule/__init__.py b/src/modules/WattecoDecoderModule/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/modules/WattecoDecoderModule/main.py b/src/modules/WattecoDecoderModule/main.py index cc0b1c0..bc0b7d6 100644 --- a/src/modules/WattecoDecoderModule/main.py +++ b/src/modules/WattecoDecoderModule/main.py @@ -7,7 +7,7 @@ from fastapi import FastAPI from datetime import datetime -from .Standard.Decoding_Functions import Decoding_JSON, version +from .Standard.srcWatteco.Decoding_Functions import Decoding_JSON, version from .Batch import br_uncompress from .Batch.br_uncompress import hex_to_array @@ -15,7 +15,6 @@ def parseFor(tagz: int, commands, payload: str): splited_commands=br_uncompress.split_commands(commands) - print(splited_commands) inputData = base64.b64decode(payload).hex() @@ -44,24 +43,7 @@ def parseFor(tagz: int, commands, payload: str): def parseUnitaryFrame(payload: str): inputData = base64.b64decode(payload).hex() - frame = json.loads(Decoding_JSON(inputData, False)) - - result = {} - result[frame['ClusterID']] = frame['Data'] - - if (frame['AttributeID'] == "NodePowerDescriptor"): - result[frame['ClusterID']]['DisposableBatteryVoltage'] = result[frame['ClusterID']]['DisposableBatteryVoltage'] / 1000 - - if (frame['AttributeID'] == "Occupancy"): - occupancy = 0; - for item in frame['Data']: - print (item) - if frame['Data'][item] == 1: - occupancy = 1 - - result['Occupancy'] = occupancy - - return result + return json.loads(Decoding_JSON(inputData, False)) @app.get("/api/stdframe") def S0Decoder(devEUI: str, payload: str, fport: int): @@ -69,15 +51,57 @@ def S0Decoder(devEUI: str, payload: str, fport: int): @app.get("/api/s0") def S0Decoder(devEUI: str, payload: str, fport: int): - return parseFor(1, ['0,1,10,Index1', '1,100,6,BatteryLevel'], payload) + result = parseFor(1, ['0,1,10,Pulse', '1,100,6,DisposableBatteryVoltage'], payload) + + if 'CommandID' in result and result['CommandID'] == 'ReportAttributes': + if result['AttributeID'] == 'PresentValue': + return { + 'State': result['Data'] + } + if result['AttributeID'] == 'Count': + return { + 'Pulse': result['Data'] + } + else: + result['DisposableBatteryVoltage'] = result['DisposableBatteryVoltage'] / 1000 + return result @app.get("/api/thr") def THRDecoder(devEUI: str, payload: str, fport: int): - return parseFor(3, ['0,10,7,Temperature', '1,100,6,RelativeHumidity', ' 2,10,12,Luminosity', '3,100,6,Disposable_BatteryLevel', '4,100,6,Rechargeable_BatteryLevel'], payload) + result = parseFor(3, ['0,10,7,Temperature', '1,100,6,RelativeHumidity', ' 2,10,12,Illuminance', '3,100,6,DisposableBatteryVoltage', '4,100,6,RechargeableBatteryVoltage'], payload) + + if 'AnalogInput' in result.keys(): + result['Illuminance'] = result.pop('AnalogInput') + result['DisposableBatteryVoltage'] = result['DisposableBatteryVoltage'] / 1000 + result['RechargeableBatteryVoltage'] = result['RechargeableBatteryVoltage'] / 1000 + + return result @app.get("/api/senso") def SensoDecoder(devEUI: str, payload: str, fport: int): - return parseFor(3, ['0,1,4,Status', '1,1,11,Index', '2,1,5,MinFlow', '3,1,5,MaxFlow'], payload) + result = parseFor(1, ['0,1,11,Volume', '1,100,6,DisposableBatteryVoltage'], payload) + + if 'CommandID' in result and result['CommandID'] == 'ReportAttributes': + if result['AttributeID'] == 'Volume': + return { + 'Volume': result['Data'] + } + if result['AttributeID'] == 'Status': + return { + 'Status': { + 'Freeze': result['Data']['b7'], + 'Installation': result['Data']['b6'], + 'Battery': result['Data']['b5'], + 'Fraud': result['Data']['b4'], + 'BackWaterLevel3': result['Data']['b3'], + 'BackWaterLevel2': result['Data']['b2'], + 'BackWaterLevel1': result['Data']['b1'], + 'Leak': result['Data']['b0'] + } + } + else: + result['DisposableBatteryVoltage'] = result['DisposableBatteryVoltage'] / 1000 + return result @app.get("/api/pulsesenso") def PulseSensoDecoder(devEUI: str, payload: str, fport: int): @@ -85,7 +109,22 @@ def PulseSensoDecoder(devEUI: str, payload: str, fport: int): @app.get("/api/presso") def PressoDecoder(devEUI: str, payload: str, fport: int): - return parseFor(3, ['0,0.004,12,4-20mA', '1,1,12,0-10V', '2,100,6,BatteryLevel', '3,100,6,ExtPowerLevel', '4,1,10,Index'], payload) + result = parseFor(3, ['0,0.004,12,mA', '1,1,12,V', '2,100,6,BatteryLevel', '3,100,6,ExtPowerLevel', '4,1,10,Index'], payload) + + if 'CommandID' in result and result['CommandID'] == 'ReportAttributes': + if result['AttributeID'] == 'PresentValue' and result['EndPoint'] == 0: + return { + 'mA': result['Data'] + } + if result['AttributeID'] == 'PresentValue' and result['EndPoint'] == 1: + return { + 'V': result['Data'] / 1000 + } + + result['BatteryLevel'] = result['BatteryLevel'] / 1000 + result['V'] = result['V'] / 1000 + + return result @app.get("/remotetemperature") def RemoteTemperatureDecoder(devEUI: str, payload: str, fport: int): @@ -109,7 +148,12 @@ def TDecoder(devEUI: str, payload: str, fport: int): @app.get("/api/atmo") def AtmoDecoder(devEUI: str, payload: str, fport: int): - return parseFor(3, ['0,1,7,Temperature', '1,1,6,RelativeHumidity', '2,1,7,Pressure', '3,1,10,Index1', '4,1,10,Index2', '5,1,6,BatteryLevel'], payload) + result = parseFor(3, ['0,1,7,Temperature', '1,1,6,RelativeHumidity', '2,1,7,Pressure', '3,1,10,Index1', '4,1,10,Index2', '5,1,6,BatteryLevel'], payload) + + result.pop('Index1') + result.pop('Index2') + + return result @app.get("/api/ventilo") def VentiloDecoder(devEUI: str, payload: str, fport: int): @@ -127,10 +171,12 @@ def PulseSensoAtexZ1Decoder(devEUI: str, payload: str, fport: int): def RemoteTemperature2CTNDecoder(devEUI: str, payload: str, fport: int): return parseFor(3, ['0,10,7,Temperature1', '1,10,7,Temperature2'], payload) -@app.get("/api/vaquao") +@app.get("/api/vaqao") def VAQAODecoder(devEUI: str, payload: str, fport: int): - return parseFor(3, ['1,10,7,Temperature' ,'2,100,6,RelativeHumidity', '3,10,6,CO2', '4,10,6,COV'], payload) + frame = parseFor(3, ['1,10,7,Temperature' ,'2,100,6,RelativeHumidity', '3,10,6,CO2', '4,10,6,COV'], payload) + return frame -@app.get("/api/vaquaoplus") +@app.get("/api/vaqaoplus") def VAQAOPlusDecoder(devEUI: str, payload: str, fport: int): - return parseFor(3, ['0,1,4,Occupancy', '1,10,7,Temperature', '2,100,6,RelativeHumidity', '3,10,6,CO2', '4,10,6,COV', '5,10,6,LUX', '6,10,6,Pressure'], payload) \ No newline at end of file + frame = parseFor(3, ['0,1,4,Occupancy', '1,10,7,Temperature', '2,100,6,RelativeHumidity', '3,10,6,CO2', '4,10,6,COV', '5,10,6,LUX', '6,10,6,Pressure'], payload) + return frame \ No newline at end of file diff --git a/src/modules/WattecoDecoderModule/replaceCodecImports.sh b/src/modules/WattecoDecoderModule/replaceCodecImports.sh new file mode 100644 index 0000000..1b50f50 --- /dev/null +++ b/src/modules/WattecoDecoderModule/replaceCodecImports.sh @@ -0,0 +1,9 @@ +#!/bin/sh + +sed -i 's/from ZCL/from .ZCL/' ./Standard/srcWatteco/Decoding_Functions.py +sed -i 's/from ZCL/from .ZCL/' ./Standard/srcWatteco/ZCL_FRAME.py +sed -i 's/from ZCL/from .ZCL/' ./Standard/srcWatteco/ZCL.py +sed -i 's/from WTC_CodecTools/from .WTC_CodecTools/' ./Standard/srcWatteco/ZCL.py +sed -i 's/from TICs/from .TICs/' ./Standard/srcWatteco/ZCL.py +sed -i 's/from WTC_CodecTools/from ..WTC_CodecTools/' ./Standard/srcWatteco/TICs/_TIC_Tools.py +sed -i 's/import constants/from . import constants/' ./Batch/br_uncompress.py \ No newline at end of file diff --git a/src/modules/WattecoDecoderModule/requirements-dev.txt b/src/modules/WattecoDecoderModule/requirements-dev.txt new file mode 100644 index 0000000..32bf58f --- /dev/null +++ b/src/modules/WattecoDecoderModule/requirements-dev.txt @@ -0,0 +1,3 @@ +requests==2.26.0 +pytest==6.2.5 +pytest-cov==3.0.0 \ No newline at end of file diff --git a/src/modules/WattecoDecoderModule/test_main.py b/src/modules/WattecoDecoderModule/test_main.py new file mode 100644 index 0000000..b6c2f90 --- /dev/null +++ b/src/modules/WattecoDecoderModule/test_main.py @@ -0,0 +1,97 @@ +from fastapi.testclient import TestClient + +from .main import app + +client = TestClient(app) + +def test_vaqaoplus(): + response = client.get("/api/vaqaoplus?payload=cEQABqw8ABnA7s4BIGEpaCPjgWxsEdBJGyY%2B0d0bABSCAu1eqN2yDAAFtJuXArCAdsuyBigAOA%3D%3D&devEUI=70B3D5E75E009F8F&fport=125") + assert response.status_code == 200 + json = response.json() + json.pop('timestamp') + + assert json == {"Occupancy":1,"Temperature":19.7,"RelativeHumidity":54.0,"CO2":690.0,"COV":50.0,"LUX":10,"Pressure":9790} + +def test_vaqao(): + response = client.get("/api/vaqao?payload=QjOAgKhPAR2g6ADckf2BU2j3QgYOUWgv%2BmYm%2BtaSFn1rSYu%2BmESxRVEUFXFoniAUmxk%3D&devEUI=70B3D5E75E009F8F&fport=125") + assert response.status_code == 200 + json = response.json() + json.pop('timestamp') + + assert json == {"Temperature":19.6,"RelativeHumidity":30.0,"CO2":500.0,"COV":250.0} + +def test_thr(): + response = client.get("/api/thr?payload=UgAAgIGVBLDIPoIytA8CBQAI3hdwYxMAQBBAugbREiuK%2BSgM2REAgCIS&devEUI=70B3D5E75E009F8F&fport=125") + assert response.status_code == 200 + json = response.json() + json.pop('timestamp') + + assert json == {"Temperature":24.2,"RelativeHumidity":54.0,"Illuminance":320.0, "DisposableBatteryVoltage": 0, "RechargeableBatteryVoltage": 3.0} + +def test_s0(): + response = client.get("/api/s0?payload=EQoADwBVEAA%3D&devEUI=70B3D5E75E009F8F&fport=125") + assert response.status_code == 200 + json = response.json() + + assert json == {"State": False} + + response = client.get("/api/s0?payload=EQoADwQCIwAAAAE%3D&devEUI=70B3D5E75E009F8F&fport=125") + assert response.status_code == 200 + json = response.json() + + assert json == {"Pulse": 1} + + response = client.get("/api/s0?payload=JhUAIOBgAdceAACgZQ8%3D&devEUI=70B3D5E75E009F8F&fport=125") + assert response.status_code == 200 + json = response.json() + json.pop('timestamp') + + assert json == {"Pulse": 45, "DisposableBatteryVoltage": 3.0} + +def test_senso(): + response = client.get("/api/senso?payload=EQqAAgAAKwAAAB0%3D&devEUI=70B3D5E75E009F8F&fport=125") + assert response.status_code == 200 + json = response.json() + + assert json == {"Volume": 29} + + response = client.get("/api/senso?payload=EQqAAwAAGGA%3D&devEUI=70B3D5E75E009F8F&fport=125") + assert response.status_code == 200 + json = response.json() + + assert json == { 'Status': { "Freeze": False, "Installation": True, 'Battery': True, 'Fraud': False, 'BackWaterLevel3': False, 'BackWaterLevel2': False, 'BackWaterLevel1': False, 'Leak': False }} + + response = client.get("/api/senso?payload=JhUAIOBgAdceAACgZQ8%3D&devEUI=70B3D5E75E009F8F&fport=125") + assert response.status_code == 200 + json = response.json() + json.pop('timestamp') + + assert json == {'DisposableBatteryVoltage': 3.0, 'Volume': 45} + +def test_atmo(): + response = client.get("/api/atmo?payload=VgAAAAGTBNDsEyi0H6DfHgAAAIB7AAAAgAU%3D&devEUI=70B3D5E75E009F8F&fport=125") + assert response.status_code == 200 + json = response.json() + json.pop('timestamp') + + assert json == {"Temperature":24.64,"RelativeHumidity":23.24,"Pressure":1012} + +def test_presso(): + response = client.get("/api/presso?payload=EQoADABVOUFQAAA%3D&devEUI=70B3D5E75E009F8F&fport=125") + assert response.status_code == 200 + json = response.json() + + assert json == {"mA":13.0} + + response = client.get("/api/presso?payload=MQoADABVOUYU0AA%3D&devEUI=70B3D5E75E009F8F&fport=125") + assert response.status_code == 200 + json = response.json() + + assert json == {"V":9.524} + + response = client.get("/api/presso?payload=IBUAgAH0ok5wgNLeAUISEPmuKVVAu2VpBA%3D%3D&devEUI=70B3D5E75E009F8F&fport=125") + assert response.status_code == 200 + json = response.json() + json.pop('timestamp') + + assert json == {"BatteryLevel":3.5,"V":7.52} \ No newline at end of file