Skip to content

Conversation

@damacus
Copy link
Owner

@damacus damacus commented Jan 6, 2026

  • feat: add Protocol 3.5 encryption and message format support
  • docs: Add instructions for adding new robovacs
  • docs: Update docs

Implement core Protocol 3.5 (Tuya v3.5) support in tuyalocalapi:

- Add AES-GCM encryption/decryption methods to TuyaCipher
- Add is_gcm_mode property to detect Protocol 3.5
- Add generate_iv() for 12-byte random IV generation
- Add encrypt_gcm() and decrypt_gcm() methods
- Add Protocol 3.5 message constants (0x6699 prefix, 0x9966 suffix)
- Update Message.to_bytes() to generate v3.5 format messages
- Add Message._to_bytes_v35() for v3.5 message serialization
- Update Message.from_bytes() to detect and parse v3.5 messages
- Add Message._from_bytes_v35() for v3.5 message parsing
- Add 23 comprehensive tests for cipher and message format

Protocol 3.5 uses AES-GCM instead of AES-ECB with HMAC-SHA256,
providing authenticated encryption with per-packet IVs.
Signed-off-by: Dan Webb <dan.webb@damacus.io>
Signed-off-by: Dan Webb <dan.webb@damacus.io>
Copilot AI review requested due to automatic review settings January 6, 2026 16:00
@damacus damacus enabled auto-merge (squash) January 6, 2026 16:00
@damacus damacus merged commit 63bb62b into main Jan 6, 2026
12 checks passed
@damacus damacus deleted the feat/protocol-35-support branch January 6, 2026 16:04
@codecov
Copy link

codecov bot commented Jan 6, 2026

Codecov Report

❌ Patch coverage is 88.46154% with 9 lines in your changes missing coverage. Please review.
✅ Project coverage is 72.23%. Comparing base (957613d) to head (9dfa039).
⚠️ Report is 3 commits behind head on main.

Files with missing lines Patch % Lines
custom_components/robovac/tuyalocalapi.py 88.46% 9 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #296      +/-   ##
==========================================
+ Coverage   71.47%   72.23%   +0.75%     
==========================================
  Files          55       55              
  Lines        1774     1851      +77     
==========================================
+ Hits         1268     1337      +69     
- Misses        506      514       +8     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds support for Tuya Protocol 3.5 with AES-GCM encryption, enhances documentation with comprehensive model listings, and provides detailed instructions for adding new vacuum models to the integration.

  • Implements Protocol 3.5 encryption using AES-GCM with 12-byte IVs and 16-byte authentication tags
  • Adds comprehensive test coverage for Protocol 3.5 cipher and message format operations
  • Creates detailed documentation for supported models and contributing new device support

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
custom_components/robovac/tuyalocalapi.py Adds Protocol 3.5 encryption/decryption methods, message format handling, and magic constants for the new protocol
tests/test_vacuum/test_protocol_35_cipher.py Comprehensive test suite for Protocol 3.5 AES-GCM cipher operations including encryption, decryption, IV generation, and AAD support
tests/test_vacuum/test_protocol_35_message.py Tests for Protocol 3.5 message format structure, parsing, and validation including prefix/suffix verification
site_docs/supported-models.md New comprehensive table of all supported RoboVac models with protocol versions and series groupings
site_docs/configuration.md Updated to reference the new dedicated supported models page instead of inline listing
site_docs/index.md Added navigation links to new documentation pages for supported models and adding new vacuums
site_docs/adding-new-vacuum.md Complete step-by-step guide for contributors to add support for new vacuum models including code examples and testing instructions

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

- **G30**: T2190, T2250, T2251, T2252, T2253, T2273
- **G32**: T2270
- **G35**: T2255
- **G40**: T1250, T2259, T2277, T2278, T2280
Copy link

Copilot AI Jan 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Model T2277 is listed as "eufy Clean L60 SES" in the compatibility table (line 42), which is an L60 series device, not a G40 series device. It should not be included in the G40 series list. Remove T2277 from this line since it belongs only to the L60 series (line 68).

Suggested change
- **G40**: T1250, T2259, T2277, T2278, T2280
- **G40**: T1250, T2259, T2278, T2280

Copilot uses AI. Check for mistakes.
raise InvalidMessage("Invalid IV length in v3.5 message.")

# Extract ciphertext (between IV and tag)
# payload_size = IV(12) + ciphertext + tag(16)
Copy link

Copilot AI Jan 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The ciphertext_len calculation on line 974 could potentially be negative if payload_size is less than 28 (12 + 16). This would cause issues with data extraction. Add validation to ensure payload_size is at least 28 bytes before calculating ciphertext_len, and raise InvalidMessage with a descriptive error if it's too small.

Suggested change
# payload_size = IV(12) + ciphertext + tag(16)
# payload_size = IV(12) + ciphertext + tag(16)
if payload_size < 28:
raise InvalidMessage(
"Invalid v3.5 message payload size; must be at least 28 bytes "
"to contain IV and GCM tag."
)

Copilot uses AI. Check for mistakes.
Comment on lines +1001 to +1003
except Exception as e:
device._LOGGER.debug(f"v3.5 decryption failed: {e}")
raise InvalidMessage("GCM decryption/verification failed") from e
Copy link

Copilot AI Jan 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using a bare except Exception clause is too broad and could catch unexpected errors like KeyboardInterrupt or SystemExit (though these inherit from BaseException). Consider catching more specific exceptions like cryptography.exceptions.InvalidTag, UnicodeDecodeError, and json.JSONDecodeError to provide more precise error handling and allow other exceptions to propagate properly.

Copilot uses AI. Check for mistakes.
is_v35 = self.device is not None and self.device.version >= (3, 5)
is_v34 = self.device is not None and self.device.version >= (3, 4)

if is_v35 and self.device is not None:
Copy link

Copilot AI Jan 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The check is_v35 and self.device is not None on line 705 is redundant because is_v35 already includes the check self.device is not None from line 702. The condition can be simplified to just if is_v35: for better readability and maintainability.

Suggested change
if is_v35 and self.device is not None:
if is_v35:

Copilot uses AI. Check for mistakes.

import struct
import pytest
from unittest.mock import MagicMock, patch
Copy link

Copilot AI Jan 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Import of 'patch' is not used.

Suggested change
from unittest.mock import MagicMock, patch
from unittest.mock import MagicMock

Copilot uses AI. Check for mistakes.
Comment on lines +10 to +12
TuyaDevice,
MAGIC_PREFIX,
MAGIC_SUFFIX,
Copy link

Copilot AI Jan 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Import of 'TuyaDevice' is not used.
Import of 'MAGIC_SUFFIX' is not used.

Suggested change
TuyaDevice,
MAGIC_PREFIX,
MAGIC_SUFFIX,
MAGIC_PREFIX,

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant