summaryrefslogtreecommitdiff
path: root/include/py/homekit/util.py
diff options
context:
space:
mode:
Diffstat (limited to 'include/py/homekit/util.py')
-rw-r--r--include/py/homekit/util.py67
1 files changed, 56 insertions, 11 deletions
diff --git a/include/py/homekit/util.py b/include/py/homekit/util.py
index 22bba86..2b06600 100644
--- a/include/py/homekit/util.py
+++ b/include/py/homekit/util.py
@@ -9,6 +9,8 @@ import logging
import string
import random
import re
+import os
+import ipaddress
from enum import Enum
from datetime import datetime
@@ -36,6 +38,14 @@ def validate_ipv4_or_hostname(address: str, raise_exception: bool = False) -> bo
return False
+def validate_ipv4(address: str) -> bool:
+ try:
+ ipaddress.IPv6Address(address)
+ return True
+ except ipaddress.AddressValueError:
+ return False
+
+
def validate_mac_address(mac_address: str) -> bool:
mac_pattern = r'^([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})$'
if re.match(mac_pattern, mac_address):
@@ -52,17 +62,21 @@ class Addr:
self.host = host
self.port = port
- @staticmethod
- def fromstring(addr: str) -> Addr:
- colons = addr.count(':')
- if colons != 1:
- raise ValueError('invalid host:port format')
-
- if not colons:
- host = addr
- port = None
+ @classmethod
+ def fromstring(cls, addr: str, port_required=True) -> Addr:
+ if port_required:
+ colons = addr.count(':')
+ if colons != 1:
+ raise ValueError('invalid host:port format')
+
+ if not colons:
+ host = addr
+ port = None
+ else:
+ host, port = addr.split(':')
else:
- host, port = addr.split(':')
+ port = None
+ host = addr
validate_ipv4_or_hostname(host, raise_exception=True)
@@ -73,12 +87,19 @@ class Addr:
return Addr(host, port)
+ @classmethod
+ def fromipstring(cls, addr: str) -> Addr:
+ return cls.fromstring(addr, port_required=False)
+
def __str__(self):
buf = self.host
if self.port is not None:
buf += ':'+str(self.port)
return buf
+ def __repr__(self):
+ return self.__str__()
+
def __iter__(self):
yield self.host
yield self.port
@@ -243,6 +264,24 @@ def filesize_fmt(num, suffix="B") -> str:
return f"{num:.1f} Yi{suffix}"
+def seconds_to_human_readable_string(seconds: int) -> str:
+ days, remainder = divmod(seconds, 86400)
+ hours, remainder = divmod(remainder, 3600)
+ minutes, seconds = divmod(remainder, 60)
+
+ parts = []
+ if days > 0:
+ parts.append(f"{int(days)} day{'s' if days > 1 else ''}")
+ if hours > 0:
+ parts.append(f"{int(hours)} hour{'s' if hours > 1 else ''}")
+ if minutes > 0:
+ parts.append(f"{int(minutes)} minute{'s' if minutes > 1 else ''}")
+ if seconds > 0:
+ parts.append(f"{int(seconds)} second{'s' if seconds > 1 else ''}")
+
+ return ' '.join(parts)
+
+
class HashableEnum(Enum):
def hash(self) -> int:
return adler32(self.name.encode())
@@ -252,4 +291,10 @@ def next_tick_gen(freq):
t = time.time()
while True:
t += freq
- yield max(t - time.time(), 0) \ No newline at end of file
+ yield max(t - time.time(), 0)
+
+
+def homekit_path(*args) -> str:
+ return os.path.realpath(
+ os.path.join(os.path.dirname(__file__), '..', '..', '..', *args)
+ )