forked from platypush/platypush
[#398] Refactored esp
plugin.
- Converted `Response` objects into `Schema`s. - Removed the last references to the deprecated `Mapping` object. - Fixed all errors and warnings in the plugin.
This commit is contained in:
parent
55e230c361
commit
20f3eaf375
5 changed files with 674 additions and 451 deletions
|
@ -30,6 +30,11 @@ class Message:
|
|||
"""
|
||||
|
||||
class Encoder(json.JSONEncoder):
|
||||
"""
|
||||
JSON encoder that can serialize custom types commonly handled in
|
||||
Platypush messages.
|
||||
"""
|
||||
|
||||
@staticmethod
|
||||
def parse_numpy(obj):
|
||||
try:
|
||||
|
@ -57,50 +62,50 @@ class Message:
|
|||
if isinstance(obj, (datetime.datetime, datetime.date, datetime.time)):
|
||||
return obj.isoformat()
|
||||
|
||||
def default(self, obj):
|
||||
def default(self, o):
|
||||
from platypush.procedure import Procedure
|
||||
|
||||
value = self.parse_datetime(obj)
|
||||
value = self.parse_datetime(o)
|
||||
if value is not None:
|
||||
return value
|
||||
|
||||
if isinstance(obj, set):
|
||||
return list(obj)
|
||||
if isinstance(o, set):
|
||||
return list(o)
|
||||
|
||||
if isinstance(obj, UUID):
|
||||
return str(obj)
|
||||
if isinstance(o, UUID):
|
||||
return str(o)
|
||||
|
||||
value = self.parse_numpy(obj)
|
||||
value = self.parse_numpy(o)
|
||||
if value is not None:
|
||||
return value
|
||||
|
||||
if isinstance(obj, JSONAble):
|
||||
return obj.to_json()
|
||||
if isinstance(o, JSONAble):
|
||||
return o.to_json()
|
||||
|
||||
if isinstance(obj, Procedure):
|
||||
return obj.to_dict()
|
||||
if isinstance(o, Procedure):
|
||||
return o.to_dict()
|
||||
|
||||
if isinstance(obj, Enum):
|
||||
return obj.value
|
||||
if isinstance(o, Enum):
|
||||
return o.value
|
||||
|
||||
if isinstance(obj, Exception):
|
||||
return f'<{obj.__class__.__name__}>' + (f' {obj}' if obj else '')
|
||||
if isinstance(o, Exception):
|
||||
return f'<{o.__class__.__name__}>' + (f' {o}' if o else '')
|
||||
|
||||
if is_dataclass(obj):
|
||||
return asdict(obj)
|
||||
if is_dataclass(o):
|
||||
return asdict(o)
|
||||
|
||||
if isinstance(obj, Message):
|
||||
return obj.to_dict(obj)
|
||||
if isinstance(o, Message):
|
||||
return o.to_dict(o)
|
||||
|
||||
# Don't serialize I/O wrappers/objects
|
||||
if isinstance(obj, io.IOBase):
|
||||
if isinstance(o, io.IOBase):
|
||||
return None
|
||||
|
||||
try:
|
||||
return super().default(obj)
|
||||
return super().default(o)
|
||||
except Exception as e:
|
||||
_logger.warning(
|
||||
'Could not serialize object type %s: %s: %s', type(obj), e, obj
|
||||
'Could not serialize object type %s: %s: %s', type(o), e, o
|
||||
)
|
||||
|
||||
def __init__(self, *_, timestamp=None, logging_level=logging.INFO, **__):
|
||||
|
@ -205,62 +210,4 @@ class Message:
|
|||
return msgtype.build(msg)
|
||||
|
||||
|
||||
class Mapping(dict):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
for k, v in kwargs.items():
|
||||
self.__setattr__(k, v)
|
||||
|
||||
def __setitem__(self, key, item):
|
||||
self.__dict__[key] = item
|
||||
|
||||
def __getitem__(self, key):
|
||||
return self.__dict__[key]
|
||||
|
||||
def __repr__(self):
|
||||
return repr(self.__dict__)
|
||||
|
||||
def __len__(self):
|
||||
return len(self.__dict__)
|
||||
|
||||
def __delitem__(self, key):
|
||||
del self.__dict__[key]
|
||||
|
||||
def clear(self):
|
||||
return self.__dict__.clear()
|
||||
|
||||
def copy(self):
|
||||
return self.__dict__.copy()
|
||||
|
||||
def has_key(self, k):
|
||||
return k in self.__dict__
|
||||
|
||||
def update(self, *args, **kwargs):
|
||||
return self.__dict__.update(*args, **kwargs)
|
||||
|
||||
def keys(self):
|
||||
return self.__dict__.keys()
|
||||
|
||||
def values(self):
|
||||
return self.__dict__.values()
|
||||
|
||||
def items(self):
|
||||
return self.__dict__.items()
|
||||
|
||||
def pop(self, *args):
|
||||
return self.__dict__.pop(*args)
|
||||
|
||||
def __cmp__(self, dict_):
|
||||
return self.__cmp__(dict_)
|
||||
|
||||
def __contains__(self, item):
|
||||
return item in self.__dict__
|
||||
|
||||
def __iter__(self):
|
||||
return iter(self.__dict__)
|
||||
|
||||
def __str__(self):
|
||||
return str(self.__dict__)
|
||||
|
||||
|
||||
# vim:sw=4:ts=4:et:
|
||||
|
|
|
@ -1,50 +0,0 @@
|
|||
from typing import Optional
|
||||
|
||||
from platypush.message import Mapping
|
||||
|
||||
|
||||
class EspWifiScanResult(Mapping):
|
||||
def __init__(self,
|
||||
essid: str,
|
||||
bssid: str,
|
||||
channel: int,
|
||||
rssi: int,
|
||||
auth_mode: int,
|
||||
hidden: bool,
|
||||
*args,
|
||||
**kwargs):
|
||||
self.essid = essid
|
||||
self.bssid = bssid
|
||||
self.channel = channel
|
||||
self.rssi = rssi
|
||||
self.auth_mode = auth_mode
|
||||
self.hidden = hidden
|
||||
super().__init__(*args, **dict(self), **kwargs)
|
||||
|
||||
|
||||
class EspWifiConfigResult(Mapping):
|
||||
def __init__(self,
|
||||
ip: str,
|
||||
netmask: str,
|
||||
gateway: str,
|
||||
dns: str,
|
||||
mac: str,
|
||||
active: bool,
|
||||
essid: Optional[str] = None,
|
||||
channel: Optional[int] = None,
|
||||
hidden: Optional[bool] = None,
|
||||
*args,
|
||||
**kwargs):
|
||||
self.ip = ip
|
||||
self.netmask = netmask
|
||||
self.gateway = gateway
|
||||
self.dns = dns
|
||||
self.mac = mac
|
||||
self.active = active
|
||||
self.essid = essid
|
||||
self.channel = channel
|
||||
self.hidden = hidden
|
||||
super().__init__(*args, **dict(self), **kwargs)
|
||||
|
||||
|
||||
# vim:sw=4:ts=4:et:
|
File diff suppressed because it is too large
Load diff
|
@ -1,30 +1,44 @@
|
|||
from dataclasses import dataclass
|
||||
from typing import Optional, List, Union
|
||||
|
||||
from platypush.message import Mapping
|
||||
|
||||
|
||||
class Pin(Mapping):
|
||||
@dataclass
|
||||
class Pin:
|
||||
"""
|
||||
This class models the configuration for the PIN of a device.
|
||||
"""
|
||||
def __init__(self, number: int, name: Optional[str] = None, pwm: bool = False, pull_up: bool = False):
|
||||
super().__init__(number=number, name=name, pwm=pwm, pull_up=pull_up)
|
||||
|
||||
number: int
|
||||
name: Optional[str] = None
|
||||
pwm: bool = False
|
||||
pull_up: bool = False
|
||||
|
||||
|
||||
class Device(Mapping):
|
||||
@dataclass
|
||||
class Device:
|
||||
"""
|
||||
This class models the properties of a configured ESP device.
|
||||
"""
|
||||
def __init__(self, host: str, port: int = 8266, password: Optional[str] = None,
|
||||
name: Optional[str] = None, pins: List[Union[Pin, dict]] = None):
|
||||
pins = [
|
||||
pin if isinstance(pin, Pin) else Pin(**pin)
|
||||
for pin in (pins or [])
|
||||
|
||||
host: str
|
||||
port: int = 8266
|
||||
password: Optional[str] = None
|
||||
name: Optional[str] = None
|
||||
pins: Optional[List[Union[Pin, dict]]] = None
|
||||
|
||||
@property
|
||||
def _pins(self):
|
||||
return [
|
||||
pin if isinstance(pin, Pin) else Pin(**pin) for pin in (self.pins or [])
|
||||
]
|
||||
|
||||
super().__init__(host=host, port=port, password=password, pins=pins, name=name)
|
||||
self._pin_by_name = {pin['name']: pin for pin in self['pins'] if pin['name']}
|
||||
self._pin_by_number = {pin['number']: pin for pin in self['pins']}
|
||||
@property
|
||||
def _pins_by_name(self):
|
||||
return {pin.name: pin for pin in self._pins if pin.name}
|
||||
|
||||
@property
|
||||
def _pins_by_number(self):
|
||||
return {pin.number: pin for pin in self._pins}
|
||||
|
||||
def get_pin(self, pin) -> int:
|
||||
try:
|
||||
|
@ -32,8 +46,9 @@ class Device(Mapping):
|
|||
except ValueError:
|
||||
pass
|
||||
|
||||
assert pin in self._pin_by_name, 'No such PIN configured: {}'.format(pin)
|
||||
return self._pin_by_name[pin]['number']
|
||||
pin_obj = self._pins_by_name.get(pin)
|
||||
assert pin_obj, f'No such PIN configured: {pin}'
|
||||
return pin_obj.number
|
||||
|
||||
|
||||
# vim:sw=4:ts=4:et:
|
||||
|
|
148
platypush/schemas/esp.py
Normal file
148
platypush/schemas/esp.py
Normal file
|
@ -0,0 +1,148 @@
|
|||
from marshmallow import EXCLUDE, fields
|
||||
from marshmallow.schema import Schema
|
||||
|
||||
|
||||
class WifiScanResultSchema(Schema):
|
||||
"""
|
||||
Schema for Wi-Fi scan results.
|
||||
"""
|
||||
|
||||
class Meta: # type: ignore
|
||||
"""
|
||||
Exclude unknown fields.
|
||||
"""
|
||||
|
||||
unknown = EXCLUDE
|
||||
|
||||
essid = fields.Str(
|
||||
required=True,
|
||||
metadata={
|
||||
"description": "ESSID of the Wi-Fi network.",
|
||||
"example": "MyNetwork",
|
||||
},
|
||||
)
|
||||
|
||||
bssid = fields.Str(
|
||||
required=True,
|
||||
metadata={
|
||||
"description": "BSSID of the Wi-Fi network.",
|
||||
"example": "00:11:22:33:44:55",
|
||||
},
|
||||
)
|
||||
|
||||
channel = fields.Int(
|
||||
required=True,
|
||||
metadata={
|
||||
"description": "Channel of the Wi-Fi network.",
|
||||
"example": 6,
|
||||
},
|
||||
)
|
||||
|
||||
rssi = fields.Int(
|
||||
required=True,
|
||||
metadata={
|
||||
"description": "RSSI of the Wi-Fi network.",
|
||||
"example": -50,
|
||||
},
|
||||
)
|
||||
|
||||
auth_mode = fields.Int(
|
||||
required=True,
|
||||
metadata={
|
||||
"description": "Authentication mode of the Wi-Fi network.",
|
||||
"example": 3,
|
||||
},
|
||||
)
|
||||
|
||||
hidden = fields.Bool(
|
||||
required=True,
|
||||
metadata={
|
||||
"description": "Whether the Wi-Fi network is hidden.",
|
||||
"example": False,
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
class WifiConfigSchema(Schema):
|
||||
"""
|
||||
Schema for Wi-Fi configuration.
|
||||
"""
|
||||
|
||||
class Meta: # type: ignore
|
||||
"""
|
||||
Exclude unknown fields.
|
||||
"""
|
||||
|
||||
unknown = EXCLUDE
|
||||
|
||||
ip = fields.Str(
|
||||
required=True,
|
||||
metadata={
|
||||
"description": "IP address of the Wi-Fi interface.",
|
||||
"example": "192.168.1.10",
|
||||
},
|
||||
)
|
||||
|
||||
netmask = fields.Str(
|
||||
required=True,
|
||||
metadata={
|
||||
"description": "Netmask of the Wi-Fi network.",
|
||||
"example": "255.255.255.0",
|
||||
},
|
||||
)
|
||||
|
||||
gateway = fields.Str(
|
||||
required=True,
|
||||
metadata={
|
||||
"description": "Gateway of the Wi-Fi network.",
|
||||
"example": "192.168.1.1",
|
||||
},
|
||||
)
|
||||
|
||||
dns = fields.Str(
|
||||
required=True,
|
||||
metadata={
|
||||
"description": "DNS server of the Wi-Fi network.",
|
||||
"example": "1.1.1.1",
|
||||
},
|
||||
)
|
||||
|
||||
mac = fields.Str(
|
||||
required=True,
|
||||
metadata={
|
||||
"description": "MAC address of the Wi-Fi network.",
|
||||
"example": "00:11:22:33:44:55",
|
||||
},
|
||||
)
|
||||
|
||||
active = fields.Bool(
|
||||
required=True,
|
||||
metadata={
|
||||
"description": "Whether the Wi-Fi network is active.",
|
||||
"example": True,
|
||||
},
|
||||
)
|
||||
|
||||
essid = fields.Str(
|
||||
required=True,
|
||||
metadata={
|
||||
"description": "ESSID of the Wi-Fi network.",
|
||||
"example": "MyNetwork",
|
||||
},
|
||||
)
|
||||
|
||||
channel = fields.Int(
|
||||
required=True,
|
||||
metadata={
|
||||
"description": "Channel of the Wi-Fi network.",
|
||||
"example": 6,
|
||||
},
|
||||
)
|
||||
|
||||
hidden = fields.Bool(
|
||||
required=True,
|
||||
metadata={
|
||||
"description": "Whether the Wi-Fi network is hidden.",
|
||||
"example": False,
|
||||
},
|
||||
)
|
Loading…
Reference in a new issue