Skip to content

Commit

Permalink
Fix the MAC address properties (#300)
Browse files Browse the repository at this point in the history
* Fix the `CMD_MAC_*` commands

* Fix

* Get the MAC addresses in separate ADB commands
  • Loading branch information
JeffLIrion committed Feb 4, 2022
1 parent be393dc commit cfd9b0d
Show file tree
Hide file tree
Showing 8 changed files with 90 additions and 67 deletions.
44 changes: 27 additions & 17 deletions androidtv/basetv/basetv.py
Expand Up @@ -286,7 +286,7 @@ def _parse_device_properties(self, properties):
The output of the ADB command that retrieves the device properties
This method fills in the ``device_properties`` attribute, which is a dictionary with keys
``'wifimac'``, ``'ethmac'``, ``'serialno'``, ``'manufacturer'``, ``'model'``, and ``'sw_version'``
``'serialno'``, ``'manufacturer'``, ``'model'``, and ``'sw_version'``
"""
_LOGGER.debug("%s:%d `get_device_properties` response: %s", self.host, self.port, properties)
Expand All @@ -296,37 +296,47 @@ def _parse_device_properties(self, properties):
return

lines = properties.strip().splitlines()
if len(lines) != 6:
if len(lines) != 4:
self.device_properties = {}
return

manufacturer, model, serialno, version, mac_wlan0_output, mac_eth0_output = lines
manufacturer, model, serialno, version = lines

if not serialno.strip():
_LOGGER.warning("Could not obtain serialno for %s:%d, got: '%s'", self.host, self.port, serialno)
serialno = None

mac_wlan0_matches = re.findall(constants.MAC_REGEX_PATTERN, mac_wlan0_output)
if mac_wlan0_matches:
wifimac = mac_wlan0_matches[0]
else:
wifimac = None

mac_eth0_matches = re.findall(constants.MAC_REGEX_PATTERN, mac_eth0_output)
if mac_eth0_matches:
ethmac = mac_eth0_matches[0]
else:
ethmac = None

self.device_properties = {
"manufacturer": manufacturer,
"model": model,
"serialno": serialno,
"sw_version": version,
"wifimac": wifimac,
"ethmac": ethmac,
}

@staticmethod
def _parse_mac_address(mac_response):
"""Parse a MAC address from the ADB shell response.
Parameters
----------
mac_response : str, None
The response from the MAC address ADB shell command
Returns
-------
str, None
The parsed MAC address, or ``None`` if it could not be determined
"""
if not mac_response:
return None

mac_matches = re.findall(constants.MAC_REGEX_PATTERN, mac_response)
if mac_matches:
return mac_matches[0]

return None

# ======================================================================= #
# #
# Custom state detection #
Expand Down
6 changes: 6 additions & 0 deletions androidtv/basetv/basetv_async.py
Expand Up @@ -203,6 +203,12 @@ async def get_device_properties(self):
properties = await self._adb.shell(constants.CMD_DEVICE_PROPERTIES)

self._parse_device_properties(properties)

ethmac_response = await self._adb.shell(constants.CMD_MAC_ETH0)
wifimac_response = await self._adb.shell(constants.CMD_MAC_WLAN0)
self.device_properties["ethmac"] = self._parse_mac_address(ethmac_response)
self.device_properties["wifimac"] = self._parse_mac_address(wifimac_response)

return self.device_properties

# ======================================================================= #
Expand Down
6 changes: 6 additions & 0 deletions androidtv/basetv/basetv_sync.py
Expand Up @@ -203,6 +203,12 @@ def get_device_properties(self):
properties = self._adb.shell(constants.CMD_DEVICE_PROPERTIES)

self._parse_device_properties(properties)

ethmac_response = self._adb.shell(constants.CMD_MAC_ETH0)
wifimac_response = self._adb.shell(constants.CMD_MAC_WLAN0)
self.device_properties["ethmac"] = self._parse_mac_address(ethmac_response)
self.device_properties["wifimac"] = self._parse_mac_address(wifimac_response)

return self.device_properties

# ======================================================================= #
Expand Down
14 changes: 1 addition & 13 deletions androidtv/constants.py
Expand Up @@ -167,19 +167,7 @@ class DeviceEnum(IntEnum):
CMD_MAC_ETH0 = "ip addr show eth0 | grep -m 1 ether"

#: The command used for getting the device properties
CMD_DEVICE_PROPERTIES = (
CMD_MANUFACTURER
+ " && "
+ CMD_MODEL
+ " && "
+ CMD_SERIALNO
+ " && "
+ CMD_VERSION
+ " && "
+ CMD_MAC_WLAN0
+ " && "
+ CMD_MAC_ETH0
)
CMD_DEVICE_PROPERTIES = CMD_MANUFACTURER + " && " + CMD_MODEL + " && " + CMD_SERIALNO + " && " + CMD_VERSION


# ADB key event codes
Expand Down
69 changes: 41 additions & 28 deletions tests/test_basetv_sync.py
Expand Up @@ -19,10 +19,11 @@
AFTT
SERIALNO
5.1.1
link/ether ab:cd:ef:gh:ij:kl brd ff:ff:ff:ff:ff:ff
Device "eth0" does not exist.
"""

WIFIMAC_OUTPUT1 = " link/ether ab:cd:ef:gh:ij:kl brd ff:ff:ff:ff:ff:ff"
ETHMAC_OUTPUT1 = 'Device "eth0" does not exist.'

DEVICE_PROPERTIES_DICT1 = {
"manufacturer": "Amazon",
"model": "AFTT",
Expand All @@ -36,8 +37,6 @@
AFTT
5.1.1
link/ether ab:cd:ef:gh:ij:kl brd ff:ff:ff:ff:ff:ff
Device "eth0" does not exist.
"""

DEVICE_PROPERTIES_DICT2 = {
Expand All @@ -53,27 +52,40 @@
AFTT
SERIALNO
5.1.1
Device "wlan0" does not exist.
link/ether ab:cd:ef:gh:ij:kl brd ff:ff:ff:ff:ff:ff
"""

WIFIMAC_OUTPUT3 = 'Device "wlan0" does not exist.'
ETHMAC_OUTPUT3 = " link/ether ab:cd:ef:gh:ij:kl brd ff:ff:ff:ff:ff:ff"

DEVICE_PROPERTIES_DICT3 = {
"manufacturer": "Not Amazon",
"model": "AFTT",
"serialno": "SERIALNO",
"sw_version": "5.1.1",
"wifimac": None,
"ethmac": "ab:cd:ef:gh:ij:kl",
}


# Source: https://community.home-assistant.io/t/new-chromecast-w-android-tv-integration-only-showing-as-off-or-idle/234424/15
DEVICE_PROPERTIES_GOOGLE_TV = """Google
Chromecast
SERIALNO
10
link/ether ab:cd:ef:gh:ij:kl brd ff:ff:ff:ff:ff:ff
Device "eth0" does not exist.
"""

WIFIMAC_GOOGLE = " link/ether ab:cd:ef:gh:ij:kl brd ff:ff:ff:ff:ff:ff"
ETHMAC_GOOGLE = 'Device "eth0" does not exist.'

DEVICE_PROPERTIES_OUTPUT_SONY_TV = """Sony
BRAVIA 4K GB
SERIALNO
8.0.0
link/ether 11:22:33:44:55:66 brd ff:ff:ff:ff:ff:ff
link/ether ab:cd:ef:gh:ij:kl brd ff:ff:ff:ff:ff:ff
"""

WIFIMAC_SONY = " link/ether 11:22:33:44:55:66 brd ff:ff:ff:ff:ff:ff"
ETHMAC_SONY = " link/ether ab:cd:ef:gh:ij:kl brd ff:ff:ff:ff:ff:ff"

DEVICE_PROPERTIES_DICT_SONY_TV = {
"manufacturer": "Sony",
"model": "BRAVIA 4K GB",
Expand All @@ -92,15 +104,6 @@
"org.example.launcher",
]

DEVICE_PROPERTIES_DICT3 = {
"manufacturer": "Not Amazon",
"model": "AFTT",
"serialno": "SERIALNO",
"sw_version": "5.1.1",
"wifimac": None,
"ethmac": "ab:cd:ef:gh:ij:kl",
}

MEDIA_SESSION_STATE_OUTPUT = "com.amazon.tv.launcher\nstate=PlaybackState {state=2, position=0, buffered position=0, speed=0.0, updated=65749, actions=240640, custom actions=[], active item id=-1, error=null}"

STATE_DETECTION_RULES1 = {"com.amazon.tv.launcher": ["off"]}
Expand Down Expand Up @@ -442,27 +445,35 @@ def test_keys(self):

def test_get_device_properties(self):
"""Check that ``get_device_properties`` works correctly."""
with patchers.patch_shell(DEVICE_PROPERTIES_OUTPUT1)[self.PATCH_KEY]:
with patch.object(
self.btv._adb, "shell", side_effect=(DEVICE_PROPERTIES_OUTPUT1, ETHMAC_OUTPUT1, WIFIMAC_OUTPUT1)
):
device_properties = self.btv.get_device_properties()
self.assertDictEqual(DEVICE_PROPERTIES_DICT1, device_properties)

with patchers.patch_shell(DEVICE_PROPERTIES_OUTPUT2)[self.PATCH_KEY]:
with patch.object(
self.btv._adb, "shell", side_effect=(DEVICE_PROPERTIES_OUTPUT2, ETHMAC_OUTPUT1, WIFIMAC_OUTPUT1)
):
device_properties = self.btv.get_device_properties()
self.assertDictEqual(DEVICE_PROPERTIES_DICT2, device_properties)

with patchers.patch_shell(DEVICE_PROPERTIES_OUTPUT3)[self.PATCH_KEY]:
with patch.object(
self.btv._adb, "shell", side_effect=(DEVICE_PROPERTIES_OUTPUT3, ETHMAC_OUTPUT3, WIFIMAC_OUTPUT3)
):
device_properties = self.btv.get_device_properties()
self.assertDictEqual(DEVICE_PROPERTIES_DICT3, device_properties)

with patchers.patch_shell("manufacturer")[self.PATCH_KEY]:
with patch.object(self.btv._adb, "shell", side_effect=("manufacturer", None, "No match")):
device_properties = self.btv.get_device_properties()
self.assertDictEqual({}, device_properties)
self.assertDictEqual({"ethmac": None, "wifimac": None}, device_properties)

with patchers.patch_shell("")[self.PATCH_KEY]:
with patch.object(self.btv._adb, "shell", side_effect=("", None, "No match")):
device_properties = self.btv.get_device_properties()
self.assertDictEqual({}, device_properties)
self.assertDictEqual({"ethmac": None, "wifimac": None}, device_properties)

with patchers.patch_shell(DEVICE_PROPERTIES_GOOGLE_TV)[self.PATCH_KEY]:
with patch.object(
self.btv._adb, "shell", side_effect=(DEVICE_PROPERTIES_GOOGLE_TV, ETHMAC_GOOGLE, WIFIMAC_GOOGLE)
):
self.btv = AndroidTVSync.from_base(self.btv)
device_properties = self.btv.get_device_properties()
assert "Chromecast" in self.btv.device_properties.get("model", "")
Expand All @@ -481,7 +492,9 @@ def test_get_device_properties(self):
constants.CMD_LAUNCH_APP_GOOGLE_TV.format("TEST"),
)

with patchers.patch_shell(DEVICE_PROPERTIES_OUTPUT_SONY_TV)[self.PATCH_KEY]:
with patch.object(
self.btv._adb, "shell", side_effect=(DEVICE_PROPERTIES_OUTPUT_SONY_TV, ETHMAC_SONY, WIFIMAC_SONY)
):
device_properties = self.btv.get_device_properties()
self.assertDictEqual(DEVICE_PROPERTIES_DICT_SONY_TV, device_properties)

Expand Down
2 changes: 1 addition & 1 deletion tests/test_constants.py
Expand Up @@ -98,7 +98,7 @@ def test_constants(self):
# CMD_DEVICE_PROPERTIES
self.assertCommand(
constants.CMD_DEVICE_PROPERTIES,
r"getprop ro.product.manufacturer && getprop ro.product.model && getprop ro.serialno && getprop ro.build.version.release && ip addr show wlan0 | grep -m 1 ether && ip addr show eth0 | grep -m 1 ether",
r"getprop ro.product.manufacturer && getprop ro.product.model && getprop ro.serialno && getprop ro.build.version.release",
)

# CMD_HDMI_INPUT
Expand Down
8 changes: 4 additions & 4 deletions tests/test_setup_async.py
Expand Up @@ -13,24 +13,24 @@
from .async_wrapper import awaiter


DEVICE_PROPERTIES_OUTPUT1 = "Amazon\n\n\n\n\n."
DEVICE_PROPERTIES_OUTPUT1 = "Amazon\n\n\n123"

DEVICE_PROPERTIES_DICT1 = {
"manufacturer": "Amazon",
"model": "",
"serialno": None,
"sw_version": "",
"sw_version": "123",
"wifimac": None,
"ethmac": None,
}

DEVICE_PROPERTIES_OUTPUT2 = "Not Amazon\n\n\n\n\n."
DEVICE_PROPERTIES_OUTPUT2 = "Not Amazon\n\n\n456"

DEVICE_PROPERTIES_DICT2 = {
"manufacturer": "Not Amazon",
"model": "",
"serialno": None,
"sw_version": "",
"sw_version": "456",
"wifimac": None,
"ethmac": None,
}
Expand Down
8 changes: 4 additions & 4 deletions tests/test_setup_sync.py
Expand Up @@ -17,24 +17,24 @@
from . import patchers


DEVICE_PROPERTIES_OUTPUT1 = "Amazon\n\n\n\n\n."
DEVICE_PROPERTIES_OUTPUT1 = "Amazon\n\n\n123"

DEVICE_PROPERTIES_DICT1 = {
"manufacturer": "Amazon",
"model": "",
"serialno": None,
"sw_version": "",
"sw_version": "123",
"wifimac": None,
"ethmac": None,
}

DEVICE_PROPERTIES_OUTPUT2 = "Not Amazon\n\n\n\n\n."
DEVICE_PROPERTIES_OUTPUT2 = "Not Amazon\n\n\n456"

DEVICE_PROPERTIES_DICT2 = {
"manufacturer": "Not Amazon",
"model": "",
"serialno": None,
"sw_version": "",
"sw_version": "456",
"wifimac": None,
"ethmac": None,
}
Expand Down

0 comments on commit cfd9b0d

Please sign in to comment.