Skip to content

Commit cd873fa

Browse files
authored
Merge pull request #1948 from Andry925/refactor/add-more-robust-handling-for-application-section
Added more robust error handling for incorrect values inside application section
2 parents 25cbee5 + f42d266 commit cd873fa

File tree

3 files changed

+69
-5
lines changed

3 files changed

+69
-5
lines changed

thingsboard_gateway/connectors/bacnet/application.py

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -121,10 +121,19 @@ async def confirmation_handler(self):
121121
self.__log.error("APDU confirmation error: %s", e)
122122

123123
async def do_who_is(self, device_address):
124-
devices = await self.who_is(address=Address(device_address),
125-
timeout=self.__device_object_config.device_discovery_timeout)
126-
if len(devices):
127-
return devices[0]
124+
try:
125+
devices = await self.who_is(address=Address(device_address),
126+
timeout=self.__device_object_config.device_discovery_timeout)
127+
if len(devices):
128+
return devices[0]
129+
130+
except ValueError as e:
131+
self.__log.error("Incorrect data format is used %s", str(e))
132+
self.__log.debug("Error %s", e, exc_info=e)
133+
134+
except Exception as e:
135+
self.__log.error("An unexpected error occurred while device look up process %s", str(e))
136+
self.__log.debug("Error %s", e, exc_info=e)
128137

129138
async def get_object_identifiers_with_segmentation(self, device) -> List[ObjectIdentifier]:
130139
object_list = await self.__send_request_wrapper(self.read_property,

thingsboard_gateway/connectors/bacnet/bacnet_connector.py

Lines changed: 55 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
# limitations under the License.
1414

1515
from re import match, compile
16+
from ipaddress import IPv4Network
1617
import asyncio
1718
from asyncio import Queue, CancelledError, QueueEmpty
1819
from copy import deepcopy
@@ -24,7 +25,7 @@
2425
from typing import TYPE_CHECKING, Tuple, Any
2526
from concurrent.futures import TimeoutError
2627

27-
from thingsboard_gateway.connectors.bacnet.constants import SUPPORTED_OBJECTS_TYPES
28+
from thingsboard_gateway.connectors.bacnet.constants import SUPPORTED_OBJECTS_TYPES, ALLOWED_APDU
2829
from typing import TYPE_CHECKING
2930
from ast import literal_eval
3031

@@ -206,6 +207,10 @@ async def __rescan_devices(self):
206207
await asyncio.sleep(.1)
207208

208209
async def __start(self):
210+
if not self.__is_valid_application_device_section():
211+
self.__log.error('Can not start connector due to invalid application section in config.')
212+
return
213+
209214
if self.__config.get('foreignDevice', {}).get('address', ''):
210215
self.__application = Application(DeviceObjectConfig(
211216
self.__config['application']), self.__handle_indication, self.__log,
@@ -226,6 +231,55 @@ async def __start(self):
226231
self.indication_callback(),
227232
self.__application.confirmation_handler())
228233

234+
def __is_valid_application_device_section(self) -> bool:
235+
app = self.__config.get('application')
236+
if not isinstance(app, dict):
237+
self.__log.error("Missing or invalid 'application' section in config.")
238+
return False
239+
240+
host = app.get('host')
241+
if not host:
242+
self.__log.error("Missing IPv4 address: 'application.address' (or 'application.host').")
243+
return False
244+
try:
245+
IPv4Address(str(host))
246+
except Exception:
247+
self.__log.error("Invalid IPv4 address in application section: %s", host)
248+
return False
249+
250+
port = app.get('port')
251+
if not (1 <= port <= 65535):
252+
self.__log.error(
253+
"The port inside application section must be in range [1, 65535], but got %d.",
254+
port
255+
)
256+
return False
257+
258+
apdu = app.get('maxApduLengthAccepted', 1476)
259+
if apdu not in ALLOWED_APDU:
260+
self.__log.warning(
261+
"Unsupported value for 'maxApduLengthAccepted': %d. Allowed values are %s. Using default - 1476.",
262+
apdu, ALLOWED_APDU
263+
)
264+
app['maxApduLengthAccepted'] = 1476
265+
266+
mask = app.get('mask', "24")
267+
try:
268+
if mask.isdigit() and not (0 <= int(mask) <= 32):
269+
self.__log.warning(
270+
"The mask inside application section must be in range [0, 32], but got %s., using default - 24",
271+
mask)
272+
app['mask'] = "24"
273+
return True
274+
else:
275+
IPv4Network(f"{host}/{mask}")
276+
return True
277+
except Exception:
278+
app['mask'] = "24"
279+
self.__log.warning("Invalid subnet mask inside application section : %s using default - 24", mask)
280+
281+
return True
282+
229283
def __handle_indication(self, apdu):
230284
self.__indication_queue.put_nowait(apdu)
231285

thingsboard_gateway/connectors/bacnet/constants.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
DEFAULT_POLL_PERIOD = 10000
2121
EDE_FILE_PATH_PARAMETER = 'edeFilePath'
2222
EDE_CONFIG_PARAMETER = 'edeConfig'
23+
ALLOWED_APDU = (50, 128, 206, 480, 1024, 1476)
2324
SUPPORTED_OBJECTS_TYPES = {
2425
'0': 'analogInput',
2526
'1': 'analogOutput',

0 commit comments

Comments
 (0)