diff --git a/wirepas_provisioning_server/data.py b/wirepas_provisioning_server/data.py index 15a6c45..b12b6de 100644 --- a/wirepas_provisioning_server/data.py +++ b/wirepas_provisioning_server/data.py @@ -10,14 +10,62 @@ import cbor2 import yaml import logging - from typing import Final, Optional +import dataclasses from wirepas_provisioning_server.helpers import convert_to_bytes, convert_to_int, ProvisioningDataException from wirepas_provisioning_server.message import ProvisioningMethod from wirepas_provisioning_server.migrate_config import ConfigFileMigration +@dataclasses.dataclass(frozen=True) +class ProvisioningDataEndpoints: + """Endpoints for provisioning data packets""" + + req_ep: tuple[int, int] + resp_ep: tuple[int, int] + + +class ProvisioningDataConf: + """Configuration class for provisioning data packets endpoints settings. Maps the networks + to profiles provisioning data packet endpoints.""" + + DATA_EPS: list[ProvisioningDataEndpoints] = [ + ProvisioningDataEndpoints(req_ep=(246, 255), resp_ep=(255, 246)), + ProvisioningDataEndpoints(req_ep=(160, 39), resp_ep=(160, 40)), + ] + PROFILE_EP_MAP: dict[str, ProvisioningDataEndpoints] # initialization made after class definition + + def __init__(self, profiles: set[str] = set()) -> None: + self.data_endpoints: set[ProvisioningDataEndpoints] = set() + self.profiles: set[str] = set() + for profile in profiles: + self.add_profile(profile) + + def add_profile(self, profile: str) -> None: + if profile in ProvisioningDataConf.PROFILE_EP_MAP.keys(): + self.profiles.add(profile) + self.data_endpoints.add(ProvisioningDataConf.PROFILE_EP_MAP[profile]) + else: + raise KeyError( + "Profile {} not not supported. Supported values are {}.".format(profile, self.PROFILE_EP_MAP.keys()) + ) + + def get_resp_ep_by_req_ep(self, req_ep: tuple[int, int]) -> tuple[int, int]: + for data_ep in self.data_endpoints: + if req_ep == data_ep.req_ep: + return data_ep.resp_ep + + raise KeyError("End point not found error: {}.".format(req_ep)) + + +ProvisioningDataConf.PROFILE_EP_MAP = { + "2.4G": ProvisioningDataConf.DATA_EPS[0], + "SubG": ProvisioningDataConf.DATA_EPS[0], + "5GMesh": ProvisioningDataConf.DATA_EPS[1], +} + + def _generate_extended_uid( authenticator_uid_type_raw: str | int, authenticator_uid_raw: str | int, @@ -51,6 +99,8 @@ def __init__(self, config: Optional[str] = None): super(ProvisioningData, self).__init__() + self.provisioning_data_conf = ProvisioningDataConf(profiles={"2.4G", "SubG", "5GMesh"}) + if config is not None: migration = ConfigFileMigration(config) migration.update() @@ -195,7 +245,7 @@ def append( if factory_key is not None: self[uid]["factory_key"] = factory_key - logging.info("Append new UID: %s", uid.hex()) + logging.info("Append new UID#: %s", uid.hex()) logging.debug(" - method: %s", method) logging.debug(" - factory_key: %s", factory_key) logging.debug(" - encryption_key: %s", encryption_key) diff --git a/wirepas_provisioning_server/provisioning_server.py b/wirepas_provisioning_server/provisioning_server.py index 3d341cc..7fed10c 100644 --- a/wirepas_provisioning_server/provisioning_server.py +++ b/wirepas_provisioning_server/provisioning_server.py @@ -41,8 +41,9 @@ def __init__( self.sessions: dict[tuple[Optional[int], bytes, int], ProvisioningSession] = {} self.data = ProvisioningData(settings) - # Register for packets on Provisioning Endpoints [246:255] - interface.register_data_cb(self.on_data_received, src_ep=246, dst_ep=255) + # Register for data packets to provisioning endpoints + for ep in self.data.provisioning_data_conf.data_endpoints: + interface.register_uplink_traffic_cb(self.on_data_received, src_ep=ep.req_ep[0], dst_ep=ep.req_ep[1]) def on_session_finish(self, key: tuple[int, bytes, int], status: ProvisioningStatus) -> None: logging.info( @@ -55,6 +56,7 @@ def on_session_finish(self, key: tuple[int, bytes, int], status: ProvisioningSta def on_data_received(self, data: ReceivedDataEvent) -> None: try: msg_data = ProvisioningMessageFactory.map(data) + req_ep = (data.source_endpoint, data.destination_endpoint) except ProvisioningMessageException as e: print(e) return @@ -65,9 +67,12 @@ def on_data_received(self, data: ReceivedDataEvent) -> None: self.sessions[msg_data.msg_id].event_q.put(ev) logging.debug("Found SM with id: %s.", msg_data) except KeyError: - logging.info("Create new SM with id: %s.", msg_data) + resp_ep = self.data.provisioning_data_conf.get_resp_ep_by_req_ep(req_ep) + + logging.info("Create new SM with id: %s, ep:%d,%d.", msg_data, resp_ep[0], resp_ep[1]) self.sessions[msg_data.msg_id] = ProvisioningSession( self.interface.send_message, + resp_ep, msg_data.msg_id, self.data, self.on_session_finish, diff --git a/wirepas_provisioning_server/session.py b/wirepas_provisioning_server/session.py index 199487f..b3c1694 100644 --- a/wirepas_provisioning_server/session.py +++ b/wirepas_provisioning_server/session.py @@ -61,6 +61,7 @@ class ProvisioningSession(threading.Thread): def __init__( self, send_func: Callable, + resp_ep: tuple[int, int], session_id: tuple[Optional[int], bytes, int], data: ProvisioningData, on_session_finish: Callable, @@ -70,6 +71,7 @@ def __init__( super(ProvisioningSession, self).__init__() self.send_func = send_func + self.resp_ep = resp_ep self.session_id = session_id self.data = data self.retry = retry @@ -127,7 +129,13 @@ def _send_packet(self, payload: bytes) -> GatewayResultCode: logging.debug(" - Sending packet (%s).", payload) try: return self.send_func( - gw_id=self.gw_id, sink_id=self.sink_id, dest=self.session_id[0], src_ep=255, dst_ep=246, qos=1, payload=payload + gw_id=self.gw_id, + sink_id=self.sink_id, + dest=self.session_id[0], + src_ep=self.resp_ep[0], + dst_ep=self.resp_ep[1], + qos=1, + payload=payload, ) except TimeoutError: logging.warning(" - Sending packet failed with timeout exception.") @@ -205,6 +213,8 @@ def _process_start(self, msg: ProvisioningMessageSTART) -> None: self.state = ProvisioningStates.WAIT_RESPONSE self._timer_start(self.timeout) break + else: + logging.debug(" - DATA packet not sent: res:{}.".format(res)) self.retry -= 1 if self.retry >= 0: @@ -215,6 +225,7 @@ def _process_start(self, msg: ProvisioningMessageSTART) -> None: logging.error(" - %s - Too many retry - Provisioning FAILURE.", msg) self._timer_cancel() self.status = ProvisioningStatus.ERROR_SENDING_DATA + return else: self.status = ProvisioningStatus.ERROR_NOT_AUTHORIZED