Skip to content

Commit

Permalink
Fix repeater mode and access point mode
Browse files Browse the repository at this point in the history
  • Loading branch information
Dmitry Mamontov committed Mar 13, 2021
1 parent 2b50dbe commit 7aa0453
Show file tree
Hide file tree
Showing 8 changed files with 95 additions and 37 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -127,3 +127,5 @@ dmypy.json

# Pyre type checker
.pyre/

.DS_Store
12 changes: 8 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,18 @@ A. The integration creates sensors to track the number of connected devices thro

A. This is a legacy device tracking option. But the integration allows importing names, dev_id, icon from the file `known_devices.yaml` and associating with new devices by mac-address. To do this, simply create or rename the file to `legacy_known_devices.yaml`

**Q. Does the integration support routers connected in `repeater mode`?**
**Q. Does the integration support routers connected in `repeater mode` or `access point mode`?**

A. Yes, the integration supports devices connected in `repeater mode`. But to get the number of devices and their tracking, you will also need to connect and configure the parent router.
A. Yes, the integration supports devices connected in `repeater mode` or `access point mode`. But to get the number of devices and their tracking, you will also need to connect and configure the parent router.

**Q. Can I use the router in repeater mode without a parent MiWiFi device?**

A. It is possible with the `force_load_repeater_devices` option enabled. But there is a limitation. You will not see IP, uptime, and connection type, but the name will be the mac-address.

**Q. Is a reboot required after changing the [PRO] settings?**

A. Reboot is required

## Install
Installed through the custom repository [HACS](https://hacs.xyz/) - `dmamontov/hass-miwifi`

Expand All @@ -56,7 +60,7 @@ For authorization, use the ip of your router and its password
miwifi:
ip_address: router_ip
password: router_pass
force_load_repeater_devices: False # PRO
force_load_repeater_devices: False # [PRO]
```
## Advanced config
Expand All @@ -71,7 +75,7 @@ The component supports automatic deletion of monitored devices after a specified
```yaml
miwifi:
...
last_activity_days: 30 # PRO
last_activity_days: 30 # [PRO]
```

## Services
Expand Down
3 changes: 2 additions & 1 deletion custom_components/miwifi/binary_sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry, asyn
sensors = []

for sensor, data in BINARY_SENSORS.items():
sensors.append(MiWiFiBinarySensor(hass, luci, sensor, data))
if sensor in luci.api.data["binary_sensor"]:
sensors.append(MiWiFiBinarySensor(hass, luci, sensor, data))

async_add_entities(sensors, True)

Expand Down
13 changes: 11 additions & 2 deletions custom_components/miwifi/core/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@

BINARY_SENSORS = {
"state": {"name": "State", "icon": "mdi:router-wireless", "skip_available": True},
"repeater_mode": {"name": "Repeater mode", "icon": "mdi:repeat"},
"wifi_state": {"name": "Wifi state", "icon": "mdi:wifi"},
"wan_state": {"name": "Wan state", "icon": "mdi:wan", "device_class": "connectivity"},
}
Expand All @@ -36,7 +35,9 @@
"devices_lan": {"name": "Devices (lan)", "icon": "mdi:counter", "unit": "pcs"},
"devices_5ghz": {"name": "Devices (5 Ghz)", "icon": "mdi:counter", "unit": "pcs"},
"devices_2_4ghz": {"name": "Devices (2.4 Ghz)", "icon": "mdi:counter", "unit": "pcs"},
"devices_guest": {"name": "Devices (guest)", "icon": "mdi:counter", "unit": "pcs"},
"uptime": {"name": "Uptime", "icon": "mdi:timer-sand", "unit": None},
"mode": {"name": "Mode", "icon": "mdi:transit-connection-variant", "unit": None}
}

LIGHTS = {
Expand All @@ -53,10 +54,18 @@
0: "devices_lan",
1: "devices_2_4ghz",
2: "devices_5ghz",
3: "devices_guest",
}

CONNECTION_RANGES = {
0: "Lan",
1: "2.4 Ghz",
2: "5 Ghz"
2: "5 Ghz",
3: "Guest",
}

MODE_MAP = {
0: "default",
1: "repeater",
2: "access_point"
}
81 changes: 64 additions & 17 deletions custom_components/miwifi/core/luci.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@
DEFAULT_MANUFACTURER,
CONNECTION_RANGES,
CONNECTION_TO_SENSOR,
DEVICES_LIST
DEVICES_LIST,
MODE_MAP
)

_LOGGER = logging.getLogger(__name__)
Expand Down Expand Up @@ -60,8 +61,11 @@ def __init__(
self._data = {
"switch": {"reboot": False},
"light": {"led": False},
"binary_sensor": {"state": False, "repeater_mode": False, "wifi_state": False, "wan_state": False},
"sensor": {"devices": 0, "devices_lan": 0, "devices_5ghz": 0, "devices_2_4ghz": 0, "uptime": "0:00:00"},
"binary_sensor": {"state": False, "wifi_state": False, "wan_state": False},
"sensor": {
"devices": 0, "devices_lan": 0, "devices_5ghz": 0, "devices_2_4ghz": 0, "devices_guest": 0,
"mode": "default", "uptime": "0:00:00"
},
}

self._device_data = None
Expand Down Expand Up @@ -161,20 +165,29 @@ async def set_entity_data(self) -> None:
uptime = wan_info["info"]["uptime"] if isinstance(wan_info["info"], dict) and "uptime" in wan_info["info"] else 0

self._data["light"]["led"] = led["status"] == 1 if "status" in led else False
self._data["binary_sensor"]["repeater_mode"] = self.is_repeater_mode
self._data["binary_sensor"]["wifi_state"] = wifi_state
self._data["binary_sensor"]["wan_state"] = uptime

if self.is_repeater_mode:
if "wan_state" in self._data["binary_sensor"]:
del self._data["binary_sensor"]["wan_state"]
else:
self._data["binary_sensor"]["wan_state"] = uptime > 0

self._data["sensor"]["mode"] = MODE_MAP[mode["mode"]] if mode["mode"] in MODE_MAP else "undefined"

async def set_devices_list(self) -> None:
wifi_connect_devices = await self.wifi_connect_devices()
self._signals = {}

force_devices = {}

if "list" in wifi_connect_devices:
for index, device in enumerate(wifi_connect_devices["list"]):
self._signals[device["mac"]] = device["signal"]
force_devices[device["mac"]] = device

if self.is_repeater_mode and self.is_force_load:
self.add_devices(self._signals)
if self.is_repeater_mode and self.is_force_load and len(force_devices) > 0:
await self.add_devices(force_devices, True)

if self.is_repeater_mode or DOMAIN not in self.hass.data:
return
Expand Down Expand Up @@ -207,26 +220,54 @@ async def set_devices_list(self) -> None:
continue

if ip == self._ip:
self.add_devices(devices_to_ip[ip])
await self.add_devices(devices_to_ip[ip])
elif not self.hass.data[DOMAIN][entities_map[ip]].api.is_force_load:
self.hass.data[DOMAIN][entities_map[ip]].api.add_devices(devices_to_ip[ip])
await self.hass.data[DOMAIN][entities_map[ip]].api.add_devices(devices_to_ip[ip])
await asyncio.sleep(1)
self.hass.data[DOMAIN][entities_map[ip]].update_devices()

def add_devices(self, devices: dict) -> None:
async def add_devices(self, devices: dict, is_force: bool = False) -> None:
if not self._device_data:
return

self._new_devices = []
self._current_devices = []

self._data["sensor"] = {
"devices": 0, "devices_lan": 0, "devices_5ghz": 0, "devices_2_4ghz": 0,
sensor_default = {
"devices": 0,
"devices_lan": 0,
"devices_5ghz": 0,
"devices_2_4ghz": 0,
"devices_guest": 0,
"mode": self._data["sensor"]["mode"],
"uptime": self._data["sensor"]["uptime"]
}

if is_force:
try:
new_status = await self.new_status()

if "2g" not in new_status:
del sensor_default["devices_2_4ghz"]
else:
sensor_default["devices_2_4ghz"] = new_status["2g"]["online_sta_count"]

if "5g" not in new_status:
del sensor_default["devices_5ghz"]
else:
sensor_default["devices_5ghz"] = new_status["5g"]["online_sta_count"]

del sensor_default["devices_lan"]
del sensor_default["devices_guest"]
except:
del sensor_default["devices_lan"]
del sensor_default["devices_5ghz"]
del sensor_default["devices_2_4ghz"]
del sensor_default["devices_guest"]

self._data["sensor"] = sensor_default
self._data["sensor"]["devices"] = len(devices)

new_devices = []
current_devices = []

for mac in devices:
devices[mac]["router_mac"] = self._device_data["mac"]
devices[mac]["signal"] = self._signals[mac] if mac in self._signals else 0
Expand All @@ -235,14 +276,17 @@ def add_devices(self, devices: dict) -> None:
devices[mac]["name"] = mac

if mac not in self._devices_list:
self._new_devices.append(mac)
new_devices.append(mac)

self._current_devices.append(mac)
current_devices.append(mac)
self._devices_list[mac] = devices[mac]

if "type" in devices[mac]:
self._data["sensor"][CONNECTION_TO_SENSOR[devices[mac]["type"]]] += 1

self._new_devices = new_devices
self._current_devices = current_devices

async def get_entities_map(self) -> dict:
entries_map = {}

Expand Down Expand Up @@ -279,6 +323,9 @@ async def init_info(self) -> dict:
async def status(self) -> dict:
return await self.get("misystem/status")

async def new_status(self) -> dict:
return await self.get("misystem/newstatus")

async def mode(self) -> dict:
return await self.get("xqnetwork/mode")

Expand Down
11 changes: 5 additions & 6 deletions custom_components/miwifi/device_tracker.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry, asyn
zone_home = hass.states.get(ENTITY_ID_HOME)

add_devices = []

for mac in luci._devices:
add_devices.append(MiWiFiDevice(hass, config_entry, luci, mac, luci._devices[mac], zone_home, False))

Expand All @@ -69,7 +68,7 @@ def update_devices() -> None:

new_device["last_activity"] = datetime.now().replace(microsecond=0).isoformat()

_LOGGER.debug("New device {} ({}) from {}".format(new_device["name"], mac, luci.api._ip))
_LOGGER.info("New device {} ({}) from {}".format(new_device["name"], mac, luci.api._ip))

new_devices.append(MiWiFiDevice(hass, config_entry, luci, mac, new_device, zone_home))
luci.add_device(mac, new_device)
Expand All @@ -86,7 +85,7 @@ def update_devices() -> None:
def _get_new_device(hass: HomeAssistant, device: dict, legacy_device: dict) -> dict:
return {
"ip": device["ip"][0]["ip"] if "ip" in device else "0:0:0:0",
"connection": device["connection"] if "connection" in device else "Not detected",
"connection": device["connection"] if "connection" in device else "undefined",
"router_mac": device["router_mac"],
"name": legacy_device["name"] if "name" in legacy_device else device["name"],
"icon": legacy_device["icon"] if "icon" in legacy_device else None,
Expand Down Expand Up @@ -260,9 +259,9 @@ async def async_update(self) -> None:
old_router_mac = self._device["router_mac"]
device = self.hass.data[DOMAIN][entry_id].api._devices_list[self._mac]

self._device["ip"] = device["ip"][0]["ip"]
self._device["online"] = device["ip"][0]["online"]
self._device["connection"] = device["connection"]
self._device["ip"] = device["ip"][0]["ip"] if "ip" in device else "0:0:0:0"
self._device["online"] = device["ip"][0]["online"] if "ip" in device else "0"
self._device["connection"] = device["connection"] if "connection" in device else "undefined"
self._device["signal"] = device["signal"]
self._device["router_mac"] = device["router_mac"]

Expand Down
2 changes: 1 addition & 1 deletion custom_components/miwifi/manifest.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"domain": "miwifi",
"name": "MiWiFi",
"version": "1.0.2",
"version": "1.0.4",
"documentation": "https://github.com/dmamontov/hass-miwifi",
"config_flow": true,
"requirements": [],
Expand Down
8 changes: 2 additions & 6 deletions custom_components/miwifi/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry, asyn
sensors = []

for sensor, data in SENSORS.items():
sensors.append(MiWiFiSensor(hass, luci, sensor, data))
if sensor in luci.api.data["sensor"]:
sensors.append(MiWiFiSensor(hass, luci, sensor, data))

async_add_entities(sensors, True)

Expand Down Expand Up @@ -94,11 +95,6 @@ async def will_remove_from_hass(self) -> None:

async def async_update(self) -> None:
try:
if "repeater_mode" in self._data and not self._data["repeater_mode"] and self.luci.api.data["binary_sensor"]["repeater_mode"]:
self._state = STATE_UNAVAILABLE

return

self._state = self.luci.api.data["sensor"][self._code]
except KeyError:
self._state = None

0 comments on commit 7aa0453

Please sign in to comment.