Skip to content

Commit

Permalink
Merge pull request #2 from AlexxIT/master
Browse files Browse the repository at this point in the history
Merge  AlexxIT/XiaomiGateway3
  • Loading branch information
nesror authored Nov 1, 2023
2 parents 283ab98 + 9f29521 commit de41d98
Show file tree
Hide file tree
Showing 10 changed files with 831 additions and 55 deletions.
18 changes: 18 additions & 0 deletions .github/workflows/hacs.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
name: HACS validation

on:
push:
pull_request:

jobs:
hacs:
runs-on: "ubuntu-latest"
steps:
- uses: "actions/checkout@v2"
- uses: "hacs/action@main"
with: { category: "integration" }
hassfest:
runs-on: "ubuntu-latest"
steps:
- uses: "actions/checkout@v3"
- uses: "home-assistant/actions/hassfest@master"
17 changes: 0 additions & 17 deletions .github/workflows/validate.yml

This file was deleted.

764 changes: 750 additions & 14 deletions custom_components/xiaomi_gateway3/core/converters/devices.py

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,10 @@ def decode(self, device: "XDevice", payload: dict, value: dict):
payload["opening"] = bool(data[0] == 0)

elif eid == 0x1010 and len(data) == 2: # 4112
payload["formaldehyde"] = int.from_bytes(data, "little") / 100.0
if device.model == 1809:
payload["formaldehyde"] = int.from_bytes(data, "little") / 1000.0
else:
payload["formaldehyde"] = int.from_bytes(data, "little") / 100.0

elif eid == 0x1012 and len(data) == 1: # 4114
# hass: On means open, Off means closed
Expand Down
7 changes: 7 additions & 0 deletions custom_components/xiaomi_gateway3/core/entity.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
"reverse": BinarySensorDeviceClass.LOCK,
"square": BinarySensorDeviceClass.LOCK,
"water_leak": BinarySensorDeviceClass.MOISTURE,
"realtime_current_in": SensorDeviceClass.CURRENT,
}

ICONS = {
Expand Down Expand Up @@ -129,6 +130,12 @@
"turn_off_transit_sec": EntityCategory.CONFIG,
"change_transit_sec": EntityCategory.CONFIG,
"min_brightness": EntityCategory.CONFIG,
# Linptech Mesh Triple Wall Switch (no N)
"compatible_mode": EntityCategory.CONFIG,
# Linptech Sliding Window Driver WD1
"security_mode": EntityCategory.CONFIG,
"power_replenishment": EntityCategory.DIAGNOSTIC,
"realtime_current_in": EntityCategory.DIAGNOSTIC,
}

STATE_TIMEOUT = timedelta(minutes=10)
Expand Down
2 changes: 1 addition & 1 deletion custom_components/xiaomi_gateway3/core/shell/shell_arm.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ async def login(self):
await asyncio.sleep(0.1)
self.writer.write(b"\n") # empty password

coro = self.reader.readuntil(b"/ # ")
coro = self.reader.readuntil(b" # ")
await asyncio.wait_for(coro, timeout=3)

async def prepare(self):
Expand Down
40 changes: 24 additions & 16 deletions custom_components/xiaomi_gateway3/core/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -154,39 +154,47 @@ async def check_port(host: str, port: int) -> bool:
s.close()


# 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"
# firmware with support telnet ONLY with key
TELNET_KEY = {
"lumi.gateway.mgl03": "1.5.5",
"lumi.gateway.aqcn02": "4.0.4",
"lumi.gateway.aqcn03": "4.0.4",
"lumi.gateway.mcn001": "1.0.7",
"lumi.gateway.mgl001": "1.0.7",
}


async def enable_telnet(miio: AsyncMiIO, key: str = None) -> dict:
# Strategy:
# 1. Get miio info
# 2. Send common open telnet cmd if we can't get miio info
# 3. Send different telnet cmd based on gateway model and firmware
# 4. Return miio info and response on open telnet cmd
method = params = None

method = None
miio_info = await miio.info()

if miio_info and miio_info.get("model") == "lumi.gateway.mgl03":
# we know it is Xiaomi Multimode Gateway 1
if miio_info["fw_ver"] < "1.4.7":
if miio_info and "model" in miio_info and "fw_ver" in miio_info:
if miio_info["model"] == "lumi.gateway.mgl03" and miio_info["fw_ver"] < "1.4.7":
method = "enable_telnet_service"
elif miio_info["fw_ver"] < "1.5.5":
elif miio_info["fw_ver"] < TELNET_KEY.get(miio_info["model"], "999"):
method = "set_ip_info"
params = {
"ssid": '""',
"pswd": "1; passwd -d $USER; echo enable > /sys/class/tty/tty/enable; telnetd",
}
elif key:
method = "system_command"
params = {
"password": miio_password(miio.device_id, miio_info["mac"], key),
"command": "passwd -d $USER; echo enable > /sys/class/tty/tty/enable; telnetd",
}
else:
# some universal cmd for all gateways
method = "set_ip_info"

if method == "set_ip_info":
params = {"ssid": '""', "pswd": "1; " + TELNET_CMD}
elif method == "system_command":
params = {
"ssid": '""',
"pswd": "1; passwd -d $USER; riu_w 101e 53 3012 || echo enable > /sys/class/tty/tty/enable; telnetd",
"password": miio_password(miio.device_id, miio_info["mac"], key),
"command": TELNET_CMD,
}
else:
params = None

if method:
res = await miio.send(method, params, tries=1)
Expand Down
12 changes: 6 additions & 6 deletions custom_components/xiaomi_gateway3/manifest.json
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
{
"domain": "xiaomi_gateway3",
"name": "Xiaomi Gateway 3",
"config_flow": true,
"documentation": "https://github.com/AlexxIT/XiaomiGateway3",
"issue_tracker": "https://github.com/AlexxIT/XiaomiGateway3/issues",
"codeowners": [
"@AlexxIT"
],
"config_flow": true,
"dependencies": [
"http"
],
"documentation": "https://github.com/AlexxIT/XiaomiGateway3",
"iot_class": "local_push",
"issue_tracker": "https://github.com/AlexxIT/XiaomiGateway3/issues",
"requirements": [
"zigpy>=0.44.1"
],
"version": "3.3.2",
"iot_class": "local_push"
}
"version": "3.3.4"
}
4 changes: 4 additions & 0 deletions custom_components/xiaomi_gateway3/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,11 +72,15 @@ def new_entity(gateway: XGateway, device: XDevice, conv: Converter) -> XEntity:
"distance": LENGTH_METERS,
"occupancy_duration": TIME_SECONDS,
"occupancy_distance": LENGTH_METERS,
"formaldehyde": CONCENTRATION_MILLIGRAMS_PER_CUBIC_METER,
# "link_quality": "lqi",
# "rssi": "dBm",
# "msg_received": "msg",
# "msg_missed": "msg",
# "unresponsive": "times"
"power_replenishment": "mAh",
# Deprecated: please use UnitOfElectricCurrent.MILLIAMPERE.
"realtime_current_in": ELECTRIC_CURRENT_MILLIAMPERE,
}

# https://developers.home-assistant.io/docs/core/entity/sensor/#long-term-statistics
Expand Down
17 changes: 17 additions & 0 deletions tests/test_conv_ble.py
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,23 @@ def test_6473():
assert p == {"action": "button_both_single"}


def test_9385():
# https://github.com/AlexxIT/XiaomiGateway3/issues/1169
device = XDevice(BLE, 9385, DID, MAC)
assert device.info.name == "Mijia Smart Timer"
device.setup_converters()

p = device.decode_miot(
[{"did": DID, "siid": 2, "eiid": 1025, "arguments": []}]
)
assert p == {"action": "timer1"}

p = device.decode_miot(
[{"did": DID, "siid": 3, "eiid": 1025, "arguments": []}]
)
assert p == {"action": "timer2"}


def test_10249():
device = XDevice(BLE, 10249, DID, MAC)
assert device.info.name == "Xiaomi Door Lock E10"
Expand Down

0 comments on commit de41d98

Please sign in to comment.