# Path: BAC0/core/io/IOExceptions.py
# class NetworkInterfaceException(Exception):
#     """
#     This exception covers different network related exc eption (like finding IP
#     or subnet mask...)
#     """
# 
#     pass
# 
# Path: BAC0/core/utils/notes.py
# def note_and_log(cls):
#     """
#     This will be used as a decorator on class to activate
#     logging and store messages in the variable cls._notes
#     This will allow quick access to events in the web app.
#     A note can be added to cls._notes without logging if passing
#     the argument log=false to function note()
#     Something can be logged without addind a note using function log()
#     """
#     if hasattr(cls, "DEBUG_LEVEL"):
#         if cls.DEBUG_LEVEL == "debug":
#             file_level = logging.DEBUG
#             console_level = logging.DEBUG
#         elif cls.DEBUG_LEVEL == "info":
#             file_level = logging.INFO
#             console_level = logging.INFO
#     else:
#         file_level = logging.WARNING
#         console_level = logging.INFO
#     # Notes object
#     cls._notes = namedtuple("_notes", ["timestamp", "notes"])
#     cls._notes.timestamp = []
#     cls._notes.notes = []
# 
#     # Defining log object
#     cls.logname = "{} | {}".format(cls.__module__, cls.__name__)
#     cls._log = logging.getLogger("BAC0_Root.{}.{}".format(cls.__module__, cls.__name__))
# 
#     # Set level to debug so filter is done by handler
#     cls._log.setLevel(logging.DEBUG)
# 
#     # Console Handler
#     ch = logging.StreamHandler(sys.stderr)
#     ch.set_name("stderr")
#     ch.setLevel(logging.CRITICAL)
# 
#     ch2 = logging.StreamHandler(sys.stdout)
#     ch2.set_name("stdout")
#     ch2.setLevel(console_level)
# 
#     formatter = logging.Formatter("{asctime} - {levelname:<8}| {message}", style="{")
# 
#     # File Handler
#     _PERMISSION_TO_WRITE = True
#     logUserPath = expanduser("~")
#     logSaveFilePath = join(logUserPath, ".BAC0")
# 
#     logFile = join(logSaveFilePath, "BAC0.log")
#     try:
#         if not os.path.exists(logSaveFilePath):
#             os.makedirs(logSaveFilePath)
#         fh = FileHandler(logFile)
#         fh.set_name("file_handler")
#         fh.setLevel(file_level)
#         fh.setFormatter(formatter)
# 
#     except OSError:
#         _PERMISSION_TO_WRITE = False
# 
#     ch.setFormatter(formatter)
#     ch2.setFormatter(formatter)
#     # Add handlers the first time only...
#     if not len(cls._log.handlers):
#         if _PERMISSION_TO_WRITE:
#             cls._log.addHandler(fh)
#         cls._log.addHandler(ch)
#         cls._log.addHandler(ch2)
# 
#     LogList.LOGGERS.append(cls._log)
# 
#     def log_title(self, title, args=None, width=35):
#         cls._log.debug("")
#         cls._log.debug("#" * width)
#         cls._log.debug("# {}".format(title))
#         cls._log.debug("#" * width)
#         if args:
#             cls._log.debug("{!r}".format(args))
#             cls._log.debug("#" * 35)
# 
#     def log_subtitle(self, subtitle, args=None, width=35):
#         cls._log.debug("")
#         cls._log.debug("=" * width)
#         cls._log.debug("{}".format(subtitle))
#         cls._log.debug("=" * width)
#         if args:
#             cls._log.debug("{!r}".format(args))
#             cls._log.debug("=" * width)
# 
#     def log(self, note, *, level=logging.DEBUG):
#         """
#         Add a log entry...no note
#         """
#         if not note:
#             raise ValueError("Provide something to log")
#         note = "{} | {}".format(cls.logname, note)
#         cls._log.log(level, note)
# 
#     def note(self, note, *, level=logging.INFO, log=True):
#         """
#         Add note to the object. By default, the note will also
#         be logged
#         :param note: (str) The note itself
#         :param level: (logging.level)
#         :param log: (boolean) Enable or disable logging of note
#         """
#         if not note:
#             raise ValueError("Provide something to log")
#         note = "{} | {}".format(cls.logname, note)
#         cls._notes.timestamp.append(datetime.now().astimezone())
#         cls._notes.notes.append(note)
#         if log:
#             cls.log(level, note)
# 
#     @property
#     def notes(self):
#         """
#         Retrieve notes list as a Pandas Series
#         """
#         if not _PANDAS:
#             return dict(zip(self._notes.timestamp, self._notes.notes))
#         return pd.Series(self._notes.notes, index=self._notes.timestamp)
# 
#     def clear_notes(self):
#         """
#         Clear notes object
#         """
#         cls._notes.timestamp = []
#         cls._notes.notes = []
# 
#     # Add the functions to the decorated class
#     cls.clear_notes = clear_notes
#     cls.note = note
#     cls.notes = notes
#     cls.log = log
#     cls.log_title = log_title
#     cls.log_subtitle = log_subtitle
#     return cls


from bacpypes.pdu import Address
from ..io.IOExceptions import NetworkInterfaceException
from ...core.utils.notes import note_and_log
import socket
import subprocess
import ipaddress
import sys
import re
            import netifaces
#!/usr/bin/python
# -*- coding: utf-8 -*-
#
# Copyright (C) 2015 by Christian Tremblay, P.Eng <christian.tremblay@servisys.com>
#
# Licensed under LGPLv3, see file LICENSE in this source tree.
"""
Utility function to retrieve a functionnal IP and a correct broadcast IP
address.
Goal : not use 255.255.255.255 as a broadcast IP address as it is not
accepted by every devices (>3.8.38.1 bacnet.jar of Tridium Jace for example)

"""





# Path: BAC0/core/io/IOExceptions.py
# class NetworkInterfaceException(Exception):
#     """
#     This exception covers different network related exc eption (like finding IP
#     or subnet mask...)
#     """
# 
#     pass
# 
# Path: BAC0/core/utils/notes.py
# def note_and_log(cls):
#     """
#     This will be used as a decorator on class to activate
#     logging and store messages in the variable cls._notes
#     This will allow quick access to events in the web app.
#     A note can be added to cls._notes without logging if passing
#     the argument log=false to function note()
#     Something can be logged without addind a note using function log()
#     """
#     if hasattr(cls, "DEBUG_LEVEL"):
#         if cls.DEBUG_LEVEL == "debug":
#             file_level = logging.DEBUG
#             console_level = logging.DEBUG
#         elif cls.DEBUG_LEVEL == "info":
#             file_level = logging.INFO
#             console_level = logging.INFO
#     else:
#         file_level = logging.WARNING
#         console_level = logging.INFO
#     # Notes object
#     cls._notes = namedtuple("_notes", ["timestamp", "notes"])
#     cls._notes.timestamp = []
#     cls._notes.notes = []
# 
#     # Defining log object
#     cls.logname = "{} | {}".format(cls.__module__, cls.__name__)
#     cls._log = logging.getLogger("BAC0_Root.{}.{}".format(cls.__module__, cls.__name__))
# 
#     # Set level to debug so filter is done by handler
#     cls._log.setLevel(logging.DEBUG)
# 
#     # Console Handler
#     ch = logging.StreamHandler(sys.stderr)
#     ch.set_name("stderr")
#     ch.setLevel(logging.CRITICAL)
# 
#     ch2 = logging.StreamHandler(sys.stdout)
#     ch2.set_name("stdout")
#     ch2.setLevel(console_level)
# 
#     formatter = logging.Formatter("{asctime} - {levelname:<8}| {message}", style="{")
# 
#     # File Handler
#     _PERMISSION_TO_WRITE = True
#     logUserPath = expanduser("~")
#     logSaveFilePath = join(logUserPath, ".BAC0")
# 
#     logFile = join(logSaveFilePath, "BAC0.log")
#     try:
#         if not os.path.exists(logSaveFilePath):
#             os.makedirs(logSaveFilePath)
#         fh = FileHandler(logFile)
#         fh.set_name("file_handler")
#         fh.setLevel(file_level)
#         fh.setFormatter(formatter)
# 
#     except OSError:
#         _PERMISSION_TO_WRITE = False
# 
#     ch.setFormatter(formatter)
#     ch2.setFormatter(formatter)
#     # Add handlers the first time only...
#     if not len(cls._log.handlers):
#         if _PERMISSION_TO_WRITE:
#             cls._log.addHandler(fh)
#         cls._log.addHandler(ch)
#         cls._log.addHandler(ch2)
# 
#     LogList.LOGGERS.append(cls._log)
# 
#     def log_title(self, title, args=None, width=35):
#         cls._log.debug("")
#         cls._log.debug("#" * width)
#         cls._log.debug("# {}".format(title))
#         cls._log.debug("#" * width)
#         if args:
#             cls._log.debug("{!r}".format(args))
#             cls._log.debug("#" * 35)
# 
#     def log_subtitle(self, subtitle, args=None, width=35):
#         cls._log.debug("")
#         cls._log.debug("=" * width)
#         cls._log.debug("{}".format(subtitle))
#         cls._log.debug("=" * width)
#         if args:
#             cls._log.debug("{!r}".format(args))
#             cls._log.debug("=" * width)
# 
#     def log(self, note, *, level=logging.DEBUG):
#         """
#         Add a log entry...no note
#         """
#         if not note:
#             raise ValueError("Provide something to log")
#         note = "{} | {}".format(cls.logname, note)
#         cls._log.log(level, note)
# 
#     def note(self, note, *, level=logging.INFO, log=True):
#         """
#         Add note to the object. By default, the note will also
#         be logged
#         :param note: (str) The note itself
#         :param level: (logging.level)
#         :param log: (boolean) Enable or disable logging of note
#         """
#         if not note:
#             raise ValueError("Provide something to log")
#         note = "{} | {}".format(cls.logname, note)
#         cls._notes.timestamp.append(datetime.now().astimezone())
#         cls._notes.notes.append(note)
#         if log:
#             cls.log(level, note)
# 
#     @property
#     def notes(self):
#         """
#         Retrieve notes list as a Pandas Series
#         """
#         if not _PANDAS:
#             return dict(zip(self._notes.timestamp, self._notes.notes))
#         return pd.Series(self._notes.notes, index=self._notes.timestamp)
# 
#     def clear_notes(self):
#         """
#         Clear notes object
#         """
#         cls._notes.timestamp = []
#         cls._notes.notes = []
# 
#     # Add the functions to the decorated class
#     cls.clear_notes = clear_notes
#     cls.note = note
#     cls.notes = notes
#     cls.log = log
#     cls.log_title = log_title
#     cls.log_subtitle = log_subtitle
#     return cls


# Path: BAC0/core/functions/GetIPAddr.py
from bacpypes.pdu import Address
from ..io.IOExceptions import NetworkInterfaceException
from ...core.utils.notes import note_and_log
import socket
import subprocess
import ipaddress
import sys
import re
            import netifaces

#!/usr/bin/python
# -*- coding: utf-8 -*-
#
# Copyright (C) 2015 by Christian Tremblay, P.Eng <christian.tremblay@servisys.com>
#
# Licensed under LGPLv3, see file LICENSE in this source tree.
"""
Utility function to retrieve a functionnal IP and a correct broadcast IP
address.
Goal : not use 255.255.255.255 as a broadcast IP address as it is not
accepted by every devices (>3.8.38.1 bacnet.jar of Tridium Jace for example)

"""





@note_and_log