Skip to content

Add ssltransport for robovacs #943

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 25 commits into from
Dec 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
c6f8b6c
Add cleartexttransport seen on robovacs
rytilahti Jun 2, 2024
10a35b9
Skip SSL verification
rytilahti May 26, 2024
abd784f
Use https, uppercase password hash and add some logging
rytilahti Jun 2, 2024
0f87b76
Convert response to json
rytilahti Jun 2, 2024
d688fe6
Result is not stored inside response
rytilahti Jun 2, 2024
fc9b0da
Return full response dict to caller
rytilahti Jun 2, 2024
669a672
Set _session_expire_at
rytilahti Jun 2, 2024
9b217cc
Minor cleanups
rytilahti Jun 3, 2024
8886600
Rename cleartexttransport to ssltransport, move into transports package
rytilahti Nov 28, 2024
e88a666
slight cleanup
rytilahti Nov 28, 2024
b58685e
Initial tests
rytilahti Nov 28, 2024
4aaf864
use kasa.json for json.dumps to fix tests (separator issue)
rytilahti Nov 28, 2024
ab1a756
Apply suggestions from code review
rytilahti Nov 29, 2024
1c4d911
Add device type for vacuum
rytilahti Nov 29, 2024
dd2649b
Fix tests
rytilahti Nov 29, 2024
67f34c1
minor cleanups
rytilahti Nov 29, 2024
91ab794
Update get_protocol for login_version
sdb9696 Nov 29, 2024
946bf33
Fix smartcam protocol
sdb9696 Nov 29, 2024
fec4b3f
Merge remote-tracking branch 'upstream/master' into feat/tokentransport
sdb9696 Nov 29, 2024
a6b2c8e
Merge branch 'master' into feat/tokentransport
rytilahti Nov 29, 2024
e3badf4
Reset app_url when the state changes to login required
rytilahti Nov 29, 2024
964b0f1
camelCase vacuum commands
rytilahti Nov 29, 2024
d1713df
Typefix
rytilahti Nov 29, 2024
562f6a6
Improve tests
rytilahti Nov 30, 2024
8d78a29
Make test logging less verbose
rytilahti Nov 30, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 12 additions & 12 deletions devtools/helpers/smartrequests.py
Original file line number Diff line number Diff line change
Expand Up @@ -427,25 +427,25 @@ def get_component_requests(component_id, ver_code):
"overheat_protection": [],
# Vacuum components
"clean": [
SmartRequest.get_raw_request("get_clean_records"),
SmartRequest.get_raw_request("get_vac_state"),
SmartRequest.get_raw_request("getCleanRecords"),
SmartRequest.get_raw_request("getVacStatus"),
],
"battery": [SmartRequest.get_raw_request("get_battery_info")],
"consumables": [SmartRequest.get_raw_request("get_consumables_info")],
"battery": [SmartRequest.get_raw_request("getBatteryInfo")],
"consumables": [SmartRequest.get_raw_request("getConsumablesInfo")],
"direction_control": [],
"button_and_led": [],
"speaker": [
SmartRequest.get_raw_request("get_support_voice_language"),
SmartRequest.get_raw_request("get_current_voice_language"),
SmartRequest.get_raw_request("getSupportVoiceLanguage"),
SmartRequest.get_raw_request("getCurrentVoiceLanguage"),
],
"map": [
SmartRequest.get_raw_request("get_map_info"),
SmartRequest.get_raw_request("get_map_data"),
SmartRequest.get_raw_request("getMapInfo"),
SmartRequest.get_raw_request("getMapData"),
],
"auto_change_map": [SmartRequest.get_raw_request("get_auto_change_map")],
"dust_bucket": [SmartRequest.get_raw_request("get_auto_dust_collection")],
"mop": [SmartRequest.get_raw_request("get_mop_state")],
"do_not_disturb": [SmartRequest.get_raw_request("get_do_not_disturb")],
"auto_change_map": [SmartRequest.get_raw_request("getAutoChangeMap")],
"dust_bucket": [SmartRequest.get_raw_request("getAutoDustCollection")],
"mop": [SmartRequest.get_raw_request("getMopState")],
"do_not_disturb": [SmartRequest.get_raw_request("getDoNotDisturb")],
"charge_pose_clean": [],
"continue_breakpoint_sweep": [],
"goto_point": [],
Expand Down
1 change: 1 addition & 0 deletions kasa/cli/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,7 @@ async def cli(
if type == "camera":
encrypt_type = "AES"
https = True
login_version = 2
device_family = "SMART.IPCAMERA"

from kasa.device import Device
Expand Down
16 changes: 14 additions & 2 deletions kasa/device_factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
BaseTransport,
KlapTransport,
KlapTransportV2,
SslTransport,
XorTransport,
)
from .transports.sslaestransport import SslAesTransport
Expand Down Expand Up @@ -155,6 +156,7 @@ def get_device_class_from_family(
"SMART.KASAHUB": SmartDevice,
"SMART.KASASWITCH": SmartDevice,
"SMART.IPCAMERA.HTTPS": SmartCamDevice,
"SMART.TAPOROBOVAC": SmartDevice,
"IOT.SMARTPLUGSWITCH": IotPlug,
"IOT.SMARTBULB": IotBulb,
}
Expand All @@ -176,20 +178,30 @@ def get_protocol(
"""Return the protocol from the connection name."""
protocol_name = config.connection_type.device_family.value.split(".")[0]
ctype = config.connection_type

protocol_transport_key = (
protocol_name
+ "."
+ ctype.encryption_type.value
+ (".HTTPS" if ctype.https else "")
+ (
f".{ctype.login_version}"
if ctype.login_version and ctype.login_version > 1
else ""
)
)

_LOGGER.debug("Finding transport for %s", protocol_transport_key)
supported_device_protocols: dict[
str, tuple[type[BaseProtocol], type[BaseTransport]]
] = {
"IOT.XOR": (IotProtocol, XorTransport),
"IOT.KLAP": (IotProtocol, KlapTransport),
"SMART.AES": (SmartProtocol, AesTransport),
"SMART.KLAP": (SmartProtocol, KlapTransportV2),
"SMART.AES.HTTPS": (SmartCamProtocol, SslAesTransport),
"SMART.AES.2": (SmartProtocol, AesTransport),
"SMART.KLAP.2": (SmartProtocol, KlapTransportV2),
"SMART.AES.HTTPS.2": (SmartCamProtocol, SslAesTransport),
"SMART.AES.HTTPS": (SmartProtocol, SslTransport),
}
if not (prot_tran_cls := supported_device_protocols.get(protocol_transport_key)):
return None
Expand Down
1 change: 1 addition & 0 deletions kasa/device_type.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ class DeviceType(Enum):
Hub = "hub"
Fan = "fan"
Thermostat = "thermostat"
Vacuum = "vacuum"
Unknown = "unknown"

@staticmethod
Expand Down
1 change: 1 addition & 0 deletions kasa/deviceconfig.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ class DeviceFamily(Enum):
SmartTapoHub = "SMART.TAPOHUB"
SmartKasaHub = "SMART.KASAHUB"
SmartIpCamera = "SMART.IPCAMERA"
SmartTapoRobovac = "SMART.TAPOROBOVAC"


class _DeviceConfigBaseMixin(DataClassJSONMixin):
Expand Down
11 changes: 10 additions & 1 deletion kasa/discover.py
Original file line number Diff line number Diff line change
Expand Up @@ -598,10 +598,12 @@ async def try_connect_all(
for encrypt in Device.EncryptionType
for device_family in main_device_families
for https in (True, False)
for login_version in (None, 2)
if (
conn_params := DeviceConnectionParameters(
device_family=device_family,
encryption_type=encrypt,
login_version=login_version,
https=https,
)
)
Expand Down Expand Up @@ -768,6 +770,13 @@ def _get_device_instance(
):
encrypt_type = encrypt_info.sym_schm

if (
not (login_version := encrypt_schm.lv)
and (et := discovery_result.encrypt_type)
and et == ["3"]
):
login_version = 2

if not encrypt_type:
raise UnsupportedDeviceError(
f"Unsupported device {config.host} of type {type_} "
Expand All @@ -778,7 +787,7 @@ def _get_device_instance(
config.connection_type = DeviceConnectionParameters.from_values(
type_,
encrypt_type,
encrypt_schm.lv,
login_version,
encrypt_schm.is_support_https,
)
except KasaException as ex:
Expand Down
2 changes: 2 additions & 0 deletions kasa/smart/smartdevice.py
Original file line number Diff line number Diff line change
Expand Up @@ -802,6 +802,8 @@
return DeviceType.Sensor
if "ENERGY" in device_type:
return DeviceType.Thermostat
if "ROBOVAC" in device_type:
return DeviceType.Vacuum

Check warning on line 806 in kasa/smart/smartdevice.py

View check run for this annotation

Codecov / codecov/patch

kasa/smart/smartdevice.py#L806

Added line #L806 was not covered by tests
_LOGGER.warning("Unknown device type, falling back to plug")
return DeviceType.Plug

Expand Down
2 changes: 2 additions & 0 deletions kasa/transports/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@
from .aestransport import AesEncyptionSession, AesTransport
from .basetransport import BaseTransport
from .klaptransport import KlapTransport, KlapTransportV2
from .ssltransport import SslTransport
from .xortransport import XorEncryption, XorTransport

__all__ = [
"AesTransport",
"AesEncyptionSession",
"SslTransport",
"BaseTransport",
"KlapTransport",
"KlapTransportV2",
Expand Down
Loading
Loading