Skip to content

Commit

Permalink
add telnet_password for ShellE1 and ShellMGW2
Browse files Browse the repository at this point in the history
  • Loading branch information
xiaodong-lx authored and xiaodong committed Aug 7, 2024
1 parent f7f44a0 commit 5769b85
Show file tree
Hide file tree
Showing 12 changed files with 34 additions and 24 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,7 @@ Only for Xiaomi Multimode Gateway 1:
- **Host** - gateway IP-address, should be fixed on your Wi-Fi router
- **Token** - gateway Mi Home token, changed only when you add gateway to Mi Home app
- **Key** - gateway secret key, [read more](https://github.com/AlexxIT/Blog/issues/13)
- **Telnet Password** - gateway(`Aqara_Hub_E1` or `Mijia_Hub_V2`) telnet password. Password will setup while adding integration(keep field empty if you don't want setup password), or you need change both integration config and password in telnet(`passwd` or `chpasswd`) later.
- **Add statistic sensors** - [read more](#statistics-table)
- **Debug logs** - enable different levels of logging ([read more](#debug-mode))

Expand Down
3 changes: 3 additions & 0 deletions custom_components/xiaomi_gateway3/config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ async def async_step_user(self, user_input: dict = None):
vol.Required("host", default=device["localip"]): str,
vol.Required("token", default=device["token"]): str,
vol.Optional("key"): str,
vol.Optional("telnet_password"): str,
}
),
)
Expand Down Expand Up @@ -121,6 +122,7 @@ async def async_step_token(self, user_input: dict = None):
vol.Required("host"): str,
vol.Required("token"): str,
vol.Optional("key"): str,
vol.Optional("telnet_password"): str,
},
user_input,
)
Expand Down Expand Up @@ -189,6 +191,7 @@ async def async_step_user(self, user_input: dict = None):
vol.Required("host"): str,
vol.Required("token"): str,
vol.Optional("key"): str,
vol.Optional("telnet_password"): str,
vol.Optional("stats"): vol.In(
{
False: "Disabled", # for backward compatibility
Expand Down
17 changes: 8 additions & 9 deletions custom_components/xiaomi_gateway3/core/core_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,14 @@ async def check_port(host: str, port: int) -> bool:
s.close()


async def gateway_info(host: str, token: str = None, key: str = None) -> dict | None:
async def gateway_info(host: str, token: str = None, key: str = None, telnet_password: str = None) -> dict | None:
# Strategy:
# 1. Check open telnet and return host, did, token, key
# 2. Try to enable telnet using host, token and (optionaly) key
# 3. Check open telnet again
# 4. Return error
try:
async with Session(host) as sh:
async with Session(host, telnet_password = telnet_password) as sh:
info = await sh.get_miio_info()
info["host"] = host
return info
Expand All @@ -41,24 +41,23 @@ async def gateway_info(host: str, token: str = None, key: str = None) -> dict |
return None

# try to enable telnet and return miio info
result = await enable_telnet(host, token, key)
result = await enable_telnet(host, token, key, telnet_password)

# waiting for telnet to start
await asyncio.sleep(1)

# call with empty token so only telnet will check
if info := await gateway_info(host):
if info := await gateway_info(host, telnet_password = telnet_password):
return info

# result ok, but telnet can't be opened
return {"error": "wrong_telnet" if result == "ok" else result}


# universal command for open telnet on all models
TELNET_CMD = "passwd -d $USER; riu_w 101e 53 3012 || echo enable > /sys/class/tty/tty/enable; telnetd"
TELNET_CMD = 'echo "$USER:%s" | chpasswd; riu_w 101e 53 3012 || echo enable > /sys/class/tty/tty/enable; telnetd;'


async def enable_telnet(host: str, token: str, key: str = None) -> str:
async def enable_telnet(host: str, token: str, key: str = None, telnet_password: str = None) -> str:
# Strategy:
# 1. Get miio info
miio = AsyncMiIO(host, token)
Expand Down Expand Up @@ -92,11 +91,11 @@ async def enable_telnet(host: str, token: str, key: str = None) -> str:
if method == "enable_telnet_service":
params = None
elif method == "set_ip_info":
params = {"ssid": '""', "pswd": "1; " + TELNET_CMD}
params = {"ssid": '""', "pswd": "1; " + TELNET_CMD % (telnet_password or "")}
elif method == "system_command":
params = {
"password": miio_password(miio.device_id, miio_info["mac"], key),
"command": TELNET_CMD,
"command": TELNET_CMD % (telnet_password or ""),
}
else:
raise NotImplementedError(method)
Expand Down
2 changes: 1 addition & 1 deletion custom_components/xiaomi_gateway3/core/gate/openmiio.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ def openmiio_on_timer(self, ts: float):

async def openmiio_restart(self):
try:
async with Session(self.host) as sh:
async with Session(self.host, telnet_password = self.options["telnet_password"]) as sh:
if await sh.only_one():
await self.openmiio_prepare_gateway(sh)
except Exception as e:
Expand Down
4 changes: 2 additions & 2 deletions custom_components/xiaomi_gateway3/core/gate/silabs.py
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ async def silabs_process_unknown(self, uid: str):
async def silabs_process_join(self, data: dict):
self.debug("silabs_process_join", data=data)
try:
async with Session(self.host) as sh:
async with Session(self.host, telnet_password = self.options["telnet_password"]) as sh:
# check if model should be prevented from unpairing
if self.force_pair or not data["model"].startswith(("lumi.", "ikea.")):
self.force_pair = False
Expand Down Expand Up @@ -287,7 +287,7 @@ async def silabs_process_neighbors(self, device: XDevice, data: dict):

async def silabs_restart(self):
try:
async with Session(self.host) as sh:
async with Session(self.host, telnet_password = self.options["telnet_password"]) as sh:
# names for all supported gateway models
await sh.exec("killall Lumi_Z3GatewayHost_MQTT mZ3GatewayHost_MQTT")
except Exception as e:
Expand Down
6 changes: 3 additions & 3 deletions custom_components/xiaomi_gateway3/core/gateway.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ async def enable_telnet(self) -> bool:
return False
try:
resp = await core_utils.enable_telnet(
self.host, token, self.options.get("key")
self.host, token, self.options.get("key"), self.options.get("telnet_password")
)
self.debug("enable_telnet", data=resp)
return resp == "ok"
Expand All @@ -73,7 +73,7 @@ async def enable_telnet(self) -> bool:

async def prepare_gateway(self) -> bool:
try:
async with Session(self.host) as sh:
async with Session(self.host, telnet_password = self.options["telnet_password"]) as sh:
if not await sh.only_one():
self.debug("Connection from a second Hass detected")
return False
Expand Down Expand Up @@ -167,7 +167,7 @@ async def send(self, device: XDevice, data: dict):
async def telnet_command(self, cmd: str) -> bool | None:
self.debug("telnet_command", data=cmd)
try:
async with Session(self.host) as sh:
async with Session(self.host, telnet_password = self.options["telnet_password"]) as sh:
if cmd == "run_ftp":
await sh.run_ftp()
return True
Expand Down
3 changes: 2 additions & 1 deletion custom_components/xiaomi_gateway3/core/shell/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@


class ShellBase:
def __init__(self, reader: asyncio.StreamReader, writer: asyncio.StreamWriter):
def __init__(self, reader: asyncio.StreamReader, writer: asyncio.StreamWriter, telnet_password: str = None):
self.reader = reader
self.writer = writer
self.telnet_password = telnet_password

async def close(self):
if not self.writer:
Expand Down
9 changes: 5 additions & 4 deletions custom_components/xiaomi_gateway3/core/shell/session.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,10 @@
class Session:
reader: asyncio.StreamReader
writer: asyncio.StreamWriter
telnet_password: str

def __init__(self, host: str, port=23):
def __init__(self, host: str, port=23, telnet_password: str = None):
self.telnet_password = telnet_password
self.coro = asyncio.open_connection(host, port, limit=1_000_000)

async def __aenter__(self):
Expand All @@ -29,13 +31,12 @@ async def close(self):
async def login(self) -> ShellMGW | ShellE1 | ShellMGW2:
coro = self.reader.readuntil(b"login: ")
resp: bytes = await asyncio.wait_for(coro, 3)

if b"rlxlinux" in resp:
shell = ShellMGW(self.reader, self.writer)
elif b"Aqara-Hub-E1" in resp or b"Aqara_Hub_E1" in resp:
shell = ShellE1(self.reader, self.writer)
shell = ShellE1(self.reader, self.writer, telnet_password = self.telnet_password)
elif b"Mijia_Hub_V2" in resp:
shell = ShellMGW2(self.reader, self.writer)
shell = ShellMGW2(self.reader, self.writer, telnet_password = self.telnet_password)
else:
raise Exception(f"Unknown response: {resp}")

Expand Down
4 changes: 3 additions & 1 deletion custom_components/xiaomi_gateway3/core/shell/shell_e1.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@ class ShellE1(ShellBase):
async def login(self):
self.writer.write(b"root\n")
await asyncio.sleep(0.1)
self.writer.write(b"\n") # empty password
if self.telnet_password:
self.writer.write(str.encode(self.telnet_password))
self.writer.write(b"\n")

coro = self.reader.readuntil(b" # ")
await asyncio.wait_for(coro, timeout=3)
Expand Down
3 changes: 2 additions & 1 deletion custom_components/xiaomi_gateway3/translations/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@
"data": {
"host": "Host",
"token": "Token",
"key": "Key"
"key": "Key",
"telnet_password": "Telnet Password"
}
}
}
Expand Down
3 changes: 2 additions & 1 deletion custom_components/xiaomi_gateway3/translations/zh-Hans.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@
"data": {
"host": "网关IP",
"token": "Token",
"key": "Key"
"key": "Key",
"telnet_password": "Telnet密码"
}
}
}
Expand Down
3 changes: 2 additions & 1 deletion custom_components/xiaomi_gateway3/translations/zh-Hant.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@
"data": {
"host": "網關IP",
"token": "Token",
"key": "Key"
"key": "Key",
"telnet_password": "Telnet密碼"
}
}
}
Expand Down

0 comments on commit 5769b85

Please sign in to comment.