Add support for using BSSIDs for internal connection (#2883)

* Add support for using BSSIDs for internal connection

 - Add support for entering BSSIDs to use for detecting when the internal connection URL should be used. These are saved like any regular SSID, but contain the prefix "BSSID:".

* Add link to documentation
This commit is contained in:
Joris Pelgröm 2022-09-24 21:55:36 +02:00 committed by GitHub
parent 9fa983c6dc
commit 80816df6f5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 67 additions and 14 deletions

View file

@ -1,7 +1,10 @@
package io.homeassistant.companion.android.settings.ssid
import android.content.Intent
import android.net.Uri
import android.os.Bundle
import android.view.LayoutInflater
import android.view.Menu
import android.view.View
import android.view.ViewGroup
import androidx.compose.ui.platform.ComposeView
@ -9,6 +12,7 @@ import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
import com.google.android.material.composethemeadapter.MdcTheme
import dagger.hilt.android.AndroidEntryPoint
import io.homeassistant.companion.android.R
import io.homeassistant.companion.android.settings.ssid.views.SsidView
import io.homeassistant.companion.android.common.R as commonR
@ -19,7 +23,16 @@ class SsidFragment : Fragment() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setHasOptionsMenu(false)
setHasOptionsMenu(true)
}
override fun onPrepareOptionsMenu(menu: Menu) {
super.onPrepareOptionsMenu(menu)
menu.findItem(R.id.get_help)?.let {
it.isVisible = true
it.intent = Intent(Intent.ACTION_VIEW, Uri.parse("https://companion.home-assistant.io/docs/troubleshooting/networking#setting-up-the-app"))
}
}
override fun onCreateView(
@ -34,6 +47,7 @@ class SsidFragment : Fragment() {
wifiSsids = viewModel.wifiSsids,
prioritizeInternal = viewModel.prioritizeInternal,
activeSsid = viewModel.activeSsid,
activeBssid = viewModel.activeBssid,
onAddWifiSsid = viewModel::addHomeWifiSsid,
onRemoveWifiSsid = viewModel::removeHomeWifiSsid,
onSetPrioritize = viewModel::setPrioritize

View file

@ -26,7 +26,10 @@ class SsidViewModel @Inject constructor(
var prioritizeInternal by mutableStateOf(false)
private set
var activeSsid by mutableStateOf("")
var activeSsid by mutableStateOf<String?>(null)
private set
var activeBssid by mutableStateOf<String?>(null)
private set
init {
@ -34,7 +37,8 @@ class SsidViewModel @Inject constructor(
wifiSsids.clear()
wifiSsids.addAll(urlRepository.getHomeWifiSsids())
prioritizeInternal = urlRepository.isPrioritizeInternal()
activeSsid = wifiHelper.getWifiSsid().removeSurrounding("\"")
activeSsid = wifiHelper.getWifiSsid()?.removeSurrounding("\"")
activeBssid = wifiHelper.getWifiBssid()
}
}

View file

@ -47,9 +47,11 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalSoftwareKeyboardController
import androidx.compose.ui.res.colorResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.input.ImeAction
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import io.homeassistant.companion.android.common.data.url.UrlRepository
import io.homeassistant.companion.android.common.R as commonR
@OptIn(
@ -61,7 +63,8 @@ import io.homeassistant.companion.android.common.R as commonR
fun SsidView(
wifiSsids: List<String>,
prioritizeInternal: Boolean,
activeSsid: String,
activeSsid: String?,
activeBssid: String?,
onAddWifiSsid: (String) -> Boolean,
onRemoveWifiSsid: (String) -> Unit,
onSetPrioritize: (Boolean) -> Unit
@ -125,7 +128,7 @@ fun SsidView(
}
if (
activeSsid.isNotBlank() &&
activeSsid?.isNotBlank() == true &&
wifiSsids.none { it == activeSsid } &&
(Build.VERSION.SDK_INT < Build.VERSION_CODES.R || activeSsid !== WifiManager.UNKNOWN_SSID)
) {
@ -147,7 +150,9 @@ fun SsidView(
}
}
items(wifiSsids, key = { "ssid.item.$it" }) {
val connected = it == activeSsid
val connected = remember(it, activeSsid, activeBssid) {
it == activeSsid || (it.startsWith(UrlRepository.BSSID_PREFIX) && it.removePrefix(UrlRepository.BSSID_PREFIX).equals(activeBssid, ignoreCase = true))
}
Row(
modifier = Modifier
.heightIn(min = 56.dp)
@ -163,7 +168,12 @@ fun SsidView(
else LocalContentColor.current.copy(alpha = LocalContentAlpha.current)
)
Text(
text = it,
text =
if (it.startsWith(UrlRepository.BSSID_PREFIX)) it.removePrefix(UrlRepository.BSSID_PREFIX)
else it,
fontFamily =
if (it.startsWith(UrlRepository.BSSID_PREFIX)) FontFamily.Monospace
else null,
modifier = Modifier
.padding(horizontal = 16.dp)
.weight(1f)
@ -240,6 +250,7 @@ private fun PreviewSsidViewEmpty() {
wifiSsids = emptyList(),
prioritizeInternal = false,
activeSsid = "home-assistant-wifi",
activeBssid = "02:00:00:00:00:00",
onAddWifiSsid = { true },
onRemoveWifiSsid = {},
onSetPrioritize = {}
@ -250,9 +261,10 @@ private fun PreviewSsidViewEmpty() {
@Composable
private fun PreviewSsidViewItems() {
SsidView(
wifiSsids = listOf("home-assistant-wifi", "wifi-one", "wifi-two"),
wifiSsids = listOf("home-assistant-wifi", "wifi-one", "BSSID:1A:2B:3C:4D:5E:6F"),
prioritizeInternal = false,
activeSsid = "home-assistant-wifi",
activeBssid = "02:00:00:00:00:00",
onAddWifiSsid = { true },
onRemoveWifiSsid = {},
onSetPrioritize = {}

View file

@ -4,6 +4,11 @@ import java.net.URL
interface UrlRepository {
companion object {
const val BSSID_PREFIX = "BSSID:"
const val INVALID_BSSID = "02:00:00:00:00:00"
}
suspend fun getWebhookId(): String?
suspend fun getApiUrls(): Array<URL>

View file

@ -1,5 +1,7 @@
package io.homeassistant.companion.android.common.data.url
import android.net.wifi.WifiManager
import android.os.Build
import android.util.Log
import io.homeassistant.companion.android.common.data.LocalStorage
import io.homeassistant.companion.android.common.data.MalformedHttpUrlException
@ -125,9 +127,21 @@ class UrlRepositoryImpl @Inject constructor(
}
override suspend fun isHomeWifiSsid(): Boolean {
val formattedSsid = wifiHelper.getWifiSsid().removeSurrounding("\"")
val formattedSsid = wifiHelper.getWifiSsid()?.removeSurrounding("\"")
val formattedBssid = wifiHelper.getWifiBssid()
val wifiSsids = getHomeWifiSsids()
return formattedSsid in wifiSsids
return (
formattedSsid != null &&
(Build.VERSION.SDK_INT < Build.VERSION_CODES.R || formattedSsid !== WifiManager.UNKNOWN_SSID) &&
formattedSsid in wifiSsids
) || (
formattedBssid != null &&
formattedBssid != UrlRepository.INVALID_BSSID &&
wifiSsids.any {
it.startsWith(UrlRepository.BSSID_PREFIX) &&
it.removePrefix(UrlRepository.BSSID_PREFIX).equals(formattedBssid, ignoreCase = true)
}
)
}
override suspend fun isInternal(): Boolean {

View file

@ -1,5 +1,6 @@
package io.homeassistant.companion.android.common.data.wifi
interface WifiHelper {
fun getWifiSsid(): String
fun getWifiSsid(): String?
fun getWifiBssid(): String?
}

View file

@ -3,10 +3,13 @@ package io.homeassistant.companion.android.common.data.wifi
import android.net.wifi.WifiManager
import javax.inject.Inject
@Suppress("DEPRECATION")
class WifiHelperImpl @Inject constructor(
private val wifiManager: WifiManager
) : WifiHelper {
override fun getWifiSsid(): String {
return wifiManager.connectionInfo?.ssid.toString()
}
override fun getWifiSsid(): String? =
wifiManager.connectionInfo.ssid
override fun getWifiBssid(): String? =
wifiManager.connectionInfo.bssid
}