Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
14 changes: 14 additions & 0 deletions custom_components/glinet/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -493,3 +493,17 @@ def set_wifi_config(self, config: Dict[str, Any]) -> Optional[Dict]:
def get_wifi_status(self) -> Optional[Dict]:
"""Get WiFi device status."""
return self._make_rpc_call("wifi", "get_status")

def get_tethering_status(self) -> Optional[Dict]:
"""Get Tethering status."""
return self._make_rpc_call("tethering", "get_status")

def set_tethering_connect(self) -> Optional[Dict]:
"""Set Tethering status."""
params = {}
params["device"]="usb0"
return self._make_rpc_call("tethering", "set_connect",params)

def set_tethering_disconnect(self) -> Optional[Dict]:
"""Set Tethering status."""
return self._make_rpc_call("tethering", "disconnect",)
20 changes: 20 additions & 0 deletions custom_components/glinet/coordinator.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,9 @@ async def _async_update_data(self) -> Dict[str, Any]:
wifi_config = await self.hass.async_add_executor_job(self.api.get_wifi_config)
wifi_status_detail = await self.hass.async_add_executor_job(self.api.get_wifi_status)
clients = await self.hass.async_add_executor_job(self.api.get_clients)

#Tethering
tethering_status = await self.hass.async_add_executor_job(self.api.get_tethering_status)

return {
"vpn_status": vpn_status,
Expand All @@ -83,6 +86,7 @@ async def _async_update_data(self) -> Dict[str, Any]:
"ovpn_server_status": ovpn_server_status,
"wifi_config": wifi_config,
"wifi_status_detail": wifi_status_detail,
"tethering_status": tethering_status,
"clients": clients,
}

Expand Down Expand Up @@ -180,6 +184,22 @@ async def async_set_wifi_enabled(self, iface_name: str, enabled: bool) -> bool:
return True
return False

# Tethering methods
async def async_start_tethering(self) -> bool:
"""Start Tethering."""
result = await self.hass.async_add_executor_job(self.api.set_tethering_connect)
if result and not result.get("err_code"):
await self.async_request_refresh()
return True
return False

async def async_stop_tethering(self) -> bool:
"""Stop Tethering."""
result = await self.hass.async_add_executor_job(self.api.set_tethering_disconnect)
if result and not result.get("err_code"):
await self.async_request_refresh()
return True
return False

# Create an alias for backward compatibility
GLiNetCoordinator = GLiNetDataUpdateCoordinator
68 changes: 68 additions & 0 deletions custom_components/glinet/switch.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@ async def async_setup_entry(
for iface in device_config.get("ifaces", []):
entities.append(GLiNetWiFiSwitch(coordinator, iface, device_config, entry))

#Tethering switches
entities.append(GLiNetTetheringSwitch(coordinator, entry))

async_add_entities(entities)

# Register firewall services
Expand Down Expand Up @@ -348,3 +351,68 @@ async def async_turn_off(self, **kwargs: Any) -> None:
success = await self.coordinator.async_set_wifi_enabled(self.iface_name, False)
if not success:
_LOGGER.error("Failed to disable WiFi: %s", self.ssid)

class GLiNetTetheringSwitch(CoordinatorEntity, SwitchEntity):
"""Representation of a GL.iNet tethering switch."""

def __init__(
self,
coordinator: GLiNetDataUpdateCoordinator,
entry: ConfigEntry,
) -> None:
"""Initialize the switch."""
super().__init__(coordinator)
self._attr_name = "Tethering"
self._attr_unique_id = f"{entry.entry_id}_tethering"
self._attr_icon = "mdi:cellphone"
self._attr_state = "on" if self.coordinator.data.get("tethering_status", {}).get("status", 0) == 1 else "off"
self._attr_device_info = {
"identifiers": {(DOMAIN, entry.entry_id)},
"name": entry.title,
"manufacturer": MANUFACTURER,
"model": coordinator.data.get("system_info", {}).get("model", "Unknown"),
"sw_version": coordinator.data.get("system_info", {}).get("firmware_version", "Unknown"),
}

@property
def is_on(self) -> bool:
"""Return true if the Tethering is running."""
tethering_status = self.coordinator.data.get("tethering_status", {})
return tethering_status.get("status", 0) == 1

@property
def available(self) -> bool:
"""Return if entity is available."""
return self.coordinator.last_update_success

@property
def extra_state_attributes(self) -> dict[str, Any]:
"""Return the state attributes."""
tethering_status = self.coordinator.data.get("tethering_status", {})
tethering_ipv4 = tethering_status.get("ipv4")
attrs = {}
if tethering_ipv4 is not None:
attrs = {
"ip": tethering_ipv4.get("ip"),
"gateway": tethering_ipv4.get("gateway"),
}

return attrs

async def async_turn_on(self, **kwargs: Any) -> None:
"""Turn on Tethering."""
_LOGGER.debug("Starting Tethering")
success = await self.coordinator.async_start_tethering()
if not success:
_LOGGER.error("Failed to start Tethering")
self.async_write_ha_state()
await self.coordinator.async_request_refresh()

async def async_turn_off(self, **kwargs: Any) -> None:
"""Turn off Tethering."""
_LOGGER.debug("Stopping Tethering")
success = await self.coordinator.async_stop_tethering()
if not success:
_LOGGER.error("Failed to stop Tethering")
self.async_write_ha_state()
await self.coordinator.async_request_refresh()