homebridge-tuya-community 3.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/.eslintrc.js +29 -0
  2. package/.github/ISSUE_TEMPLATE/bug_report.md +40 -0
  3. package/.github/ISSUE_TEMPLATE/new-device.md +24 -0
  4. package/.github/workflows/codeql-analysis.yml +67 -0
  5. package/.github/workflows/eslint.yml +28 -0
  6. package/Changelog.md +87 -0
  7. package/LICENSE +21 -0
  8. package/Readme.MD +99 -0
  9. package/assets/Tuya-Plugin-Branding.png +0 -0
  10. package/bin/cli-decode.js +197 -0
  11. package/bin/cli-find.js +207 -0
  12. package/bin/cli.js +13 -0
  13. package/config-example.MD +43 -0
  14. package/config.schema.json +554 -0
  15. package/index.js +288 -0
  16. package/lib/AirConditionerAccessory.js +445 -0
  17. package/lib/AirPurifierAccessory.js +531 -0
  18. package/lib/BaseAccessory.js +292 -0
  19. package/lib/ConvectorAccessory.js +313 -0
  20. package/lib/CustomMultiLightAccessory.js +70 -0
  21. package/lib/CustomMultiOutletAccessory.js +111 -0
  22. package/lib/DehumidifierAccessory.js +301 -0
  23. package/lib/EnergyCharacteristics.js +86 -0
  24. package/lib/GarageDoorAccessory.js +307 -0
  25. package/lib/MultiLightAccessory.js +64 -0
  26. package/lib/MultiOutletAccessory.js +106 -0
  27. package/lib/OilDiffuserAccessory.js +480 -0
  28. package/lib/OutletAccessory.js +83 -0
  29. package/lib/RGBTWLightAccessory.js +234 -0
  30. package/lib/RGBTWOutletAccessory.js +296 -0
  31. package/lib/SimpleBlindsAccessory.js +298 -0
  32. package/lib/SimpleDimmer2Accessory.js +54 -0
  33. package/lib/SimpleDimmerAccessory.js +54 -0
  34. package/lib/SimpleFanAccessory.js +132 -0
  35. package/lib/SimpleFanLightAccessory.js +205 -0
  36. package/lib/SimpleHeaterAccessory.js +154 -0
  37. package/lib/SimpleLightAccessory.js +39 -0
  38. package/lib/SingleLightAccessory.js +45 -0
  39. package/lib/SwitchAccessory.js +106 -0
  40. package/lib/TWLightAccessory.js +91 -0
  41. package/lib/TuyaAccessory.js +744 -0
  42. package/lib/TuyaDiscovery.js +278 -0
  43. package/lib/ValveAccessory.js +150 -0
  44. package/package.json +49 -0
package/.eslintrc.js ADDED
@@ -0,0 +1,29 @@
1
+ module.exports = {
2
+ env: {
3
+ node: true,
4
+ es2021: true
5
+ },
6
+ extends: 'eslint:recommended',
7
+ parserOptions: {
8
+ ecmaVersion: 'latest',
9
+ sourceType: 'script'
10
+ },
11
+ rules: {
12
+ // Relaxed for legacy codebase - only critical errors
13
+ 'no-unused-vars': ['warn', { argsIgnorePattern: '^_', varsIgnorePattern: '^_' }],
14
+ 'no-console': 'off',
15
+ 'no-empty': 'warn',
16
+ 'no-constant-condition': 'warn',
17
+ 'no-prototype-builtins': 'off',
18
+ 'no-case-declarations': 'off',
19
+
20
+ // Disable style rules for legacy code
21
+ 'semi': 'off',
22
+ 'quotes': 'off',
23
+ 'indent': 'off',
24
+ 'comma-dangle': 'off',
25
+ 'no-trailing-spaces': 'off',
26
+ 'eol-last': 'off'
27
+ },
28
+ ignorePatterns: ['node_modules/', 'package-lock.json']
29
+ };
@@ -0,0 +1,40 @@
1
+ ---
2
+ name: Bug report
3
+ about: Create a report to help us improve
4
+ title: ''
5
+ labels: bug
6
+ assignees: iRayanKhan
7
+
8
+ ---
9
+
10
+ **Checklist**
11
+ - [ ] I have read the common issues wiki page
12
+ - [ ] I have checked to make sure the plugin is up to date
13
+
14
+
15
+
16
+ **Describe the bug**
17
+ A clear and concise description of what the bug is.
18
+
19
+ **To Reproduce**
20
+ Steps to reproduce the behavior:
21
+
22
+
23
+ **Expected behavior**
24
+ A clear and concise description of what you expected to happen.
25
+
26
+ **Screenshots**
27
+ If applicable, add screenshots to help explain your problem.
28
+
29
+ **Environment (please complete the following information):**
30
+ - OS:
31
+ - iOS version:
32
+ - Homehubs:
33
+ - Node Version:
34
+ - Plugin Version:
35
+ - Accessory Type
36
+
37
+
38
+
39
+ **Additional context**
40
+ Add any other context about the problem here.
@@ -0,0 +1,24 @@
1
+ ---
2
+ name: New Device
3
+ about: Question regarding support for a new device.
4
+ title: 'New Device: '
5
+ labels: 'newDevice'
6
+
7
+ ---
8
+
9
+ **Describe your device**
10
+ A clear and concise description of what your device is, such as accessory type, and product description.
11
+
12
+ Example: Generic Brand Lightbulb with Hex Color support, and 255 brightness.
13
+
14
+ **Partial Support?**
15
+ Does this device work in any fashion in the plugin?
16
+
17
+ **Device Schema**
18
+ Please print your devices schema below:
19
+
20
+
21
+ **Additional context**
22
+ Add any other context about the problem here.
23
+
24
+
@@ -0,0 +1,67 @@
1
+ # For most projects, this workflow file will not need changing; you simply need
2
+ # to commit it to your repository.
3
+ #
4
+ # You may wish to alter this file to override the set of languages analyzed,
5
+ # or to provide custom queries or build logic.
6
+ #
7
+ # ******** NOTE ********
8
+ # We have attempted to detect the languages in your repository. Please check
9
+ # the `language` matrix defined below to confirm you have the correct set of
10
+ # supported CodeQL languages.
11
+ #
12
+ name: "CodeQL"
13
+
14
+ on:
15
+ push:
16
+ branches: [ master ]
17
+ pull_request:
18
+ # The branches below must be a subset of the branches above
19
+ branches: [ master ]
20
+ schedule:
21
+ - cron: '31 12 * * 5'
22
+
23
+ jobs:
24
+ analyze:
25
+ name: Analyze
26
+ runs-on: ubuntu-latest
27
+
28
+ strategy:
29
+ fail-fast: false
30
+ matrix:
31
+ language: [ 'javascript' ]
32
+ # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ]
33
+ # Learn more:
34
+ # https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed
35
+
36
+ steps:
37
+ - name: Checkout repository
38
+ uses: actions/checkout@v2
39
+
40
+ # Initializes the CodeQL tools for scanning.
41
+ - name: Initialize CodeQL
42
+ uses: github/codeql-action/init@v1
43
+ with:
44
+ languages: ${{ matrix.language }}
45
+ # If you wish to specify custom queries, you can do so here or in a config file.
46
+ # By default, queries listed here will override any specified in a config file.
47
+ # Prefix the list here with "+" to use these queries and those in the config file.
48
+ # queries: ./path/to/local/query, your-org/your-repo/queries@main
49
+
50
+ # Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
51
+ # If this step fails, then you should remove it and run the build manually (see below)
52
+ - name: Autobuild
53
+ uses: github/codeql-action/autobuild@v1
54
+
55
+ # ℹ️ Command-line programs to run using the OS shell.
56
+ # 📚 https://git.io/JvXDl
57
+
58
+ # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
59
+ # and modify them (or add more) to build your code if your project
60
+ # uses a compiled language
61
+
62
+ #- run: |
63
+ # make bootstrap
64
+ # make release
65
+
66
+ - name: Perform CodeQL Analysis
67
+ uses: github/codeql-action/analyze@v1
@@ -0,0 +1,28 @@
1
+ name: ESLint
2
+
3
+ on:
4
+ push:
5
+ branches: [master, main]
6
+ pull_request:
7
+ branches: [master, main]
8
+
9
+ jobs:
10
+ eslint:
11
+ name: Run ESLint
12
+ runs-on: ubuntu-latest
13
+
14
+ steps:
15
+ - name: Checkout code
16
+ uses: actions/checkout@v4
17
+
18
+ - name: Setup Node.js
19
+ uses: actions/setup-node@v4
20
+ with:
21
+ node-version: '20'
22
+ cache: 'npm'
23
+
24
+ - name: Install dependencies
25
+ run: npm ci
26
+
27
+ - name: Run ESLint
28
+ run: npm run lint
package/Changelog.md ADDED
@@ -0,0 +1,87 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file. This project uses [semantic versioning](https://semver.org/).
4
+
5
+ ## 3.3.0 (2026-01-09)
6
+
7
+ ### Added
8
+ - **Light Switch support** - Multi-gang light switches with separate HomeKit accessories per gang
9
+ - `MultiLight` type for sequential DPs (1, 2, 3...)
10
+ - `CustomMultiLight` type for custom DP mappings with per-gang naming
11
+ - **v3.5 protocol support** - Added GCM decryption for newer Tuya devices
12
+
13
+ ### Fixed
14
+ - Fixed decryption issue in TuyaDiscovery (utf8 → binary encoding)
15
+ - Fixed multiple connection attempts when using multi-gang accessories
16
+
17
+
18
+ ## 3.2.0 (2026-01-09)
19
+
20
+ ### 🎉 New Maintainer
21
+ This plugin is now **homebridge-tuya-community**, a community-maintained fork of the original [homebridge-tuya](https://github.com/iRayanKhan/homebridge-tuya) by [@iRayanKhan](https://github.com/iRayanKhan).
22
+
23
+ Now maintained by [@AxelDreemurr](https://github.com/AxelDreemurr).
24
+
25
+ ### Added
26
+ - **Homebridge v2.0 support** - Full compatibility with Homebridge 2.0
27
+
28
+
29
+ ## 2.0.1 (2021-03-25)
30
+ This update includes the following changes:
31
+
32
+ [+] Fixes [#233](https://github.com/iRayanKhan/homebridge-tuya/issues/233#issue-833662092), where tempature divisor was not applying, thanks @xortuna [#238](https://github.com/iRayanKhan/homebridge-tuya/pull/238)
33
+
34
+ [!] Note: The next release of this plugin (2.1.0) will change the config to "Tuya", instead of "TuyaLan". No change is needed 'till 2.1.0 is released.
35
+ I am in need of beta testers for 2.1.0 once the next beta goes live, please stay tuned in the homebridge discord server for an announcement.
36
+
37
+ ## 2.0.0 (2021-03-12)
38
+ This update includes the following changes:
39
+
40
+ * [+] Verified by Homebridge. [#264](https://github.com/homebridge/verified/issues/264)
41
+ * [!] Note: The next release of this plugin (2.1.0) will change the config to "Tuya", instead of "TuyaLan". No change is needed 'till 2.1.0 is released.
42
+
43
+
44
+ ## 1.5.1 (2021-03-02)
45
+ This update includes the following changes:
46
+
47
+ * [+] Fix garage door accessory for Wofea devices, thanks @pelletip [#221](https://github.com/iRayanKhan/homebridge-tuya/pull/221)
48
+
49
+ * [+] Fix log prefix for the following device types: BaseAccessory, RGBTWLight, SimpleBlinds(1), SimpleBlinds2, SimpleFanLight, SimpleHeater, SimpleLight, TuyaAccessory, and ValveAccessory.
50
+
51
+ * [!] Warning: V2.0 will be released once this plugin is verified. The platform name will change from TuyaLan to just Tuya. Please be prepared once V2.0 comes out. No action is required at this time.
52
+
53
+ ## 1.5.0 (2021-02-28)
54
+ This update includes the following changes:
55
+
56
+ * Updated dependencies [#215](https://github.com/iRayanKhan/homebridge-tuya/pull/215) + [#216](https://github.com/iRayanKhan/homebridge-tuya/pull/216)
57
+ * Removed plugin prefix from Manufacturer (may have to clear cachedAccessories)
58
+ * Fix crash on launch for garage accessory "ReferenceError: dps is not defined" [#201](https://github.com/iRayanKhan/homebridge-tuya/pull/201) Thanks @longzheng
59
+ * Added dpStatus configuration for Wofea garage door [#202](https://github.com/iRayanKhan/homebridge-tuya/pull/202) Thanks @longzheng
60
+ * Allow more numbers and strings for cmdLow, and cmdHigh [#204](https://github.com/iRayanKhan/homebridge-tuya/pull/204) Thanks @fra-iesus
61
+ * Note: If you have custom logic or support for an unsupported accessory, please open a PR so it can be merged in!
62
+ * Note: Update to Homebridge v1.3.1 to fix "No Response" for TW/RGBTW Lights.
63
+
64
+ ## 1.4.0 (2021-02-14)
65
+ Happy Valentines day!
66
+ This update includes the following changes, courtesy of @davidh2075:
67
+
68
+ * CachedAccessories Displayname now sync with the configuration [#196](https://github.com/iRayanKhan/homebridge-tuya/pull/196)
69
+ * Fix for ECONNRESET spam [#197](https://github.com/iRayanKhan/homebridge-tuya/pull/197)
70
+ * Support for Kogan garage door accessory [#198](https://github.com/iRayanKhan/homebridge-tuya/pull/198)
71
+
72
+
73
+ ## 1.3.0 (2021-01-25)
74
+ * Added Adaptive Lighting to TW/RGBTW bulbs. Thanks @tom-23 [186]
75
+
76
+
77
+ ## 1.2.0 (2021-01-05)
78
+ * Fix UDP errors in log, thanks @Giocirque [#78]
79
+ * Merged fix for simpleFanLightAccessory DS-03 support, thanks @sholleman [#168]
80
+
81
+
82
+ ## 1.1 (2020-10-28)
83
+ * Added Changelog.md
84
+ * Added Oil Diffuser accessory, thanks @nitaybz (#144)
85
+ * Added Dehumidifier accessory, thanks @fra-iesus (#143)
86
+ * Added AirPurifier accessory, thanks @dhutchison (#139)
87
+
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2018 TuyAPI
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/Readme.MD ADDED
@@ -0,0 +1,99 @@
1
+ <p align="center">
2
+ <img src="https://raw.githubusercontent.com/iRayanKhan/homebridge-tuya/main/assets/Tuya-Plugin-Branding.png" height="100"><br>
3
+ </p>
4
+
5
+
6
+ <span align="center">
7
+
8
+ # Homebridge-Tuya
9
+
10
+
11
+ </span>
12
+
13
+
14
+
15
+ Control your supported Tuya accessories locally in HomeKit
16
+
17
+ * [Supported Device Types](#supported-device-types)
18
+ * [Installation Instructions](#installation-instructions)
19
+ * [Configuration](#configuration)
20
+ * [Known Issues](#known-issues)
21
+ * [Troubleshooting](#troubleshooting)
22
+ * [Credits](#credits)
23
+ * [License](#license)
24
+ * [Donating](#donating)
25
+
26
+ ## Supported Device Types
27
+ > Click the number next to your device to find the possible DataPoint "DP" values, then add as needed to your config.
28
+
29
+ * Air Conditioner<sup>[1](https://github.com/iRayanKhan/homebridge-tuya/wiki/Supported-Device-Types#air-conditioners)</sup>
30
+ * Air Purifiers<sup>[2]()</sup>
31
+ * Convectors<sup>[3](https://github.com/iRayanKhan/homebridge-tuya/wiki/Supported-Device-Types#heat-convectors)</sup>
32
+ * Dehumidifers<sup>[4](https://github.com/iRayanKhan/homebridge-tuya/wiki/Supported-Device-Types)</sup>
33
+ * Dimmers<sup>[5](https://github.com/iRayanKhan/homebridge-tuya/wiki/Supported-Device-Types#simple-dimmers)</sup>
34
+ * Fan<sup>[6](https://github.com/iRayanKhan/homebridge-tuya/wiki/Supported-Device-Types)</sup>
35
+ * Fan v2<sup>[7](https://github.com/iRayanKhan/homebridge-tuya/wiki/Supported-Device-Types)</sup>
36
+ * Garages<sup>[8](https://github.com/iRayanKhan/homebridge-tuya/wiki/Supported-Device-Types#garage-doors)</sup>
37
+ * Heaters<sup>[9](https://github.com/iRayanKhan/homebridge-tuya/wiki/Supported-Device-Types)</sup>
38
+ * Lights
39
+ * On/Off<sup>[10](https://github.com/iRayanKhan/homebridge-tuya/wiki/Supported-Device-Types)</sup>
40
+ * Brightness<sup>[11](https://github.com/iRayanKhan/homebridge-tuya/wiki/Supported-Device-Types#tunable-white-light-bulbs)</sup>
41
+ * Color<sup>[12](https://github.com/iRayanKhan/homebridge-tuya/wiki/Supported-Device-Types#white-and-color-light-bulbs)</sup> (Hue, Saturation, Adaptive Lighting)
42
+ * Light Switches (Multi-gang, each gang appears as separate accessory)
43
+ * Sequential (`MultiLight`) - uses DP 1, 2, 3...
44
+ * Custom (`CustomMultiLight`) - specify custom DPs per gang
45
+ * Oil Diffusers<sup>[13](https://github.com/iRayanKhan/homebridge-tuya/wiki/Supported-Device-Types)</sup>
46
+ * Outlets<sup>[14](https://github.com/iRayanKhan/homebridge-tuya/wiki/Supported-Device-Types#outlets)</sup>
47
+ * Switches<sup>[15](https://github.com/iRayanKhan/homebridge-tuya/wiki/Supported-Device-Types)</sup>
48
+
49
+ Note: Motion, and other sensor types don't behave well with responce requests, so they will not be added.
50
+
51
+
52
+ ## Installation Instructions
53
+
54
+ #### Option 1: Install via Homebridge Config UI X:
55
+
56
+ Search for "Tuya" in [homebridge-config-ui-x](https://github.com/oznu/homebridge-config-ui-x) and install `homebridge-tuya-community`.
57
+
58
+ #### Option 2: Manually Install:
59
+
60
+ ```
61
+ sudo npm install -g homebridge-tuya-community
62
+ ```
63
+
64
+ ## Configuration
65
+ > Homebridge UI
66
+
67
+ 1. Navigate to the Plugins page in [homebridge-config-ui-x](https://github.com/oznu/homebridge-config-ui-x).
68
+ 2. Click the **Settings** button for the Tuya plugin.
69
+ 3. Add your device types
70
+ 4. Add device parameters<sup>[10](apple.com/)</sup>
71
+ 5. Restart Homebridge or the plugin's child bridge for the changes to take effect.
72
+
73
+ > Manual Configuration
74
+
75
+ 1. Edit the config.json file to add your device types, and parameters.
76
+ 2. Restart Homebridge or the plugin's child bridge.
77
+
78
+
79
+ ## Known Issues
80
+
81
+ 1. If your devices add, but you can't control them, make sure you entered the DataPoint "DP" values for your device.
82
+
83
+ ## Troubleshooting
84
+ 1. Make sure the plugin is up-to date
85
+ 2. Check for existing issues
86
+
87
+
88
+ ## Contributing
89
+
90
+ If you have new accessory logic for a new device, please add a function defined by manufacturer, and describe your changes in the Readme file.
91
+
92
+ ## Credits
93
+
94
+ * [iRayanKhan](https://github.com/iRayanKhan) - original developer of the [homebridge-tuya](https://github.com/iRayanKhan/homebridge-tuya) plugin.
95
+ * [AMoo-Miki](https://github.com/AMoo-Miki) - developer of the [Tuya-Lan](https://github.com/AMoo-Miki/homebridge-tuya-lan) plugin which this plugin is based off.
96
+ * mxDanger - Plugin branding.
97
+ * [CodeTheWeb](https://github.com/CodeTheWeb) - developer of [TuyaApi](https://github.com/codetheweb/tuyapi), who gratiously provided this repo's name.
98
+ * [Oznu](https://github.com/oznu) - developer of Homebridge, added ```config.schema.json``` , fixed dependencies, and helped inspire this readME off his [gsh](https://github.com/oznu/homebridge-gsh) plugin.
99
+
Binary file
@@ -0,0 +1,197 @@
1
+ #!/usr/bin/env node
2
+
3
+ const YAML = require('yaml');
4
+ const fs = require('fs-extra');
5
+ const path = require('path');
6
+ const program = require('commander');
7
+ const crypto = require('crypto');
8
+ const readline = require('readline');
9
+ const async = require('async');
10
+
11
+ let file;
12
+
13
+ program
14
+ .name('tuya-lan decode')
15
+ .option('--key <key>', 'device key')
16
+ .option('--use <version>', 'override version string', '3.3')
17
+ .arguments('<file>')
18
+ .action(loc => {
19
+ file = loc;
20
+ })
21
+ .parse(process.argv);
22
+
23
+ const crc32LookupTable = [];
24
+ (() => {
25
+ for (let i = 0; i < 256; i++) {
26
+ let crc = i;
27
+ for (let j = 8; j > 0; j--) crc = (crc & 1) ? (crc >>> 1) ^ 3988292384 : crc >>> 1;
28
+ crc32LookupTable.push(crc);
29
+ }
30
+ })();
31
+
32
+ const getCRC32 = buffer => {
33
+ let crc = 0xffffffff;
34
+ for (let i = 0, len = buffer.length; i < len; i++) crc = crc32LookupTable[buffer[i] ^ (crc & 0xff)] ^ (crc >>> 8);
35
+ return ~crc;
36
+ };
37
+
38
+ const decodeLine = (key, input, log = true) => {
39
+ const encoding = (input.substr(0, 8) === '000055aa') ? 'hex' : 'base64';
40
+
41
+ let buffer = Buffer.from(input, encoding);
42
+ const raw = Buffer.from(input, encoding);
43
+ const len = buffer.length;
44
+ if (buffer.readUInt32BE(0) !== 0x000055aa || buffer.readUInt32BE(len - 4) !== 0x0000aa55) {
45
+ console.log("*** Input doesn't match the expected signature:", buffer.readUInt32BE(0).toString(16).padStart(8, '0'), buffer.readUInt32BE(len - 4).toString(16).padStart(8, '0'));
46
+ return rl.prompt();
47
+ }
48
+
49
+ // Try 3.3
50
+ const size = buffer.readUInt32BE(12);
51
+ const cmd = buffer.readUInt32BE(8);
52
+ const seq = buffer.readUInt32BE(4);
53
+ const crcIn = buffer.readInt32BE(len - 8);
54
+ const preHash = buffer.slice(0, len - 8);
55
+ if (log) {
56
+ console.log(`Cmd > ${cmd} \tLen > ${len}\tSize > ${size}\tSeq > ${seq}`);
57
+ console.log(`CRC > \t${crcIn === getCRC32(preHash) ? 'Pass' : `Fail ${crcIn} ≠ ${getCRC32(preHash)}`}`);
58
+ }
59
+ const flag = buffer.readUInt32BE(16) & 0xFFFFFF00;
60
+ buffer = buffer.slice(len - size + (flag ? 0 : 4), len - 8);
61
+ if (buffer.indexOf(program.use || '3.3') !== -1) buffer = buffer.slice(15 + buffer.indexOf(program.use || '3.3'));
62
+ else if (buffer.indexOf('3.2') !== -1) buffer = buffer.slice(15 + buffer.indexOf('3.2'));
63
+
64
+ switch (cmd) {
65
+ case 7:
66
+ case 8:
67
+ case 10:
68
+ case 13:
69
+ case 16:
70
+ if (buffer.length === 0) {
71
+ console.log(`${('' + seq).padEnd(4)} Decoded ${cmd}> Empty`);
72
+ break;
73
+ }
74
+ try {
75
+ const decipher = crypto.createDecipheriv('aes-128-ecb', key, '');
76
+ let decryptedMsg = decipher.update(buffer, 'buffer', 'utf8');
77
+ decryptedMsg += decipher.final('utf8');
78
+
79
+ console.log(`${('' + seq).padEnd(4)} Decoded ${cmd}>`, decryptedMsg);
80
+ if (log) console.log(`${('' + seq).padEnd(4)} Raw ${cmd}>`, raw.toString('hex'));
81
+ } catch (ex) {
82
+ console.log(`${('' + seq).padEnd(4)}*Failed ${cmd}>`, raw.toString('hex'));
83
+ }
84
+ break;
85
+
86
+ case 9:
87
+ console.log(`${('' + seq).padEnd(4)} Decoded ${cmd}>`, flag ? 'Ping' : 'Pong');
88
+ break;
89
+
90
+ case 19:
91
+ let decryptedMsg;
92
+ try {
93
+ const decipher = crypto.createDecipheriv('aes-128-ecb', key, '');
94
+ decryptedMsg = decipher.update(buffer, 'buffer', 'utf8');
95
+ decryptedMsg += decipher.final('utf8');
96
+ } catch (ex) {
97
+ decryptedMsg = '';
98
+ }
99
+
100
+ if (!decryptedMsg) {
101
+ try {
102
+ const decipher = crypto.createDecipheriv('aes-128-ecb', Buffer.from('6c1ec8e2bb9bb59ab50b0daf649b410a', 'hex'), '');
103
+ decryptedMsg = decipher.update(buffer, 'buffer', 'utf8');
104
+ decryptedMsg += decipher.final('utf8');
105
+ } catch (ex) {
106
+ decryptedMsg = '';
107
+ }
108
+ }
109
+
110
+ if (!decryptedMsg) decryptedMsg = buffer.toString('utf8');
111
+
112
+ try {
113
+ JSON.parse(decryptedMsg);
114
+ console.log(`${('' + seq).padEnd(4)} Decoded ${cmd}>`, decryptedMsg);
115
+ if (log) console.log(`${('' + seq).padEnd(4)} Raw ${cmd}>`, raw.toString('hex'));
116
+ } catch (ex) {
117
+ console.log(`${('' + seq).padEnd(4)}*Failed ${cmd}>`, raw.toString('hex'));
118
+ }
119
+ break;
120
+
121
+ default:
122
+ console.log(`Unknown ${cmd}>`, raw.toString('hex'));
123
+ }
124
+ };
125
+
126
+ async.auto({
127
+ Key: next => {
128
+ if (program.key) return next(null, program.key);
129
+
130
+ const rl = readline.createInterface({
131
+ input: process.stdin,
132
+ output: process.stdout,
133
+ prompt: '\nEnter the device key: ',
134
+ crlfDelay: Infinity
135
+ });
136
+
137
+ rl.prompt();
138
+
139
+ rl.on('line', line => {
140
+ const input = line.trim();
141
+ if (!input) return rl.prompt();
142
+
143
+ rl.close();
144
+ next(null, input);
145
+ });
146
+ },
147
+ File: ['Key', (data, next) => {
148
+ if (!file) return next();
149
+ let content;
150
+ try {
151
+ content = fs.readFileSync(path.resolve(file), 'utf8');
152
+ } catch (ex) {
153
+ console.error('Filed to read the file');
154
+ console.log(ex);
155
+ return next(true);
156
+ }
157
+
158
+ const packets = YAML.parseDocument(content);
159
+ if (Array.isArray(packets.errors) && packets.errors.length > 0) {
160
+ packets.errors.forEach(console.error);
161
+ return next(true);
162
+ }
163
+
164
+ const rows = packets.toJSON();
165
+
166
+ Object.keys(rows).forEach(key => {
167
+ decodeLine(data.Key, rows[key].replace(/\n/g, ''), false);
168
+ });
169
+
170
+ next();
171
+ }],
172
+ Line: ['File', (data, next) => {
173
+ if (file) return next();
174
+
175
+ console.log('\n\n*** Hit Ctrl+C or key in "exit" to end ***');
176
+
177
+ const rl = readline.createInterface({
178
+ input: process.stdin,
179
+ output: process.stdout,
180
+ prompt: '\nEnter the encrypted message: ',
181
+ crlfDelay: Infinity
182
+ });
183
+
184
+ rl.prompt();
185
+
186
+ rl.on('line', line => {
187
+ const input = line.trim();
188
+ if (input.toLowerCase() === 'exit') process.exit(0);
189
+
190
+ decodeLine(data.Key, input);
191
+
192
+ rl.prompt();
193
+ }).on('close', () => {
194
+ process.exit(0);
195
+ });
196
+ }]
197
+ });