Пример #1
0
def validate_timestamp(timestamp, polling_interval):
    """Validate timestamp to be a multiple of 'polling_interval' seconds.

    Args:
        timestamp: epoch timestamp in seconds
        polling_interval: Polling interval for data

    Returns:
        valid: True if valid

    """
    # Initialize key variables
    valids = []
    valid = False

    # Evaluate validity of the parameters
    valids.append(bool(polling_interval))
    valids.append(data.is_numeric(timestamp))
    valids.append(data.is_numeric(polling_interval))
    valids.append(isinstance(polling_interval, (int, float)))

    # Process data
    if False not in valids:
        test = (int(timestamp) // polling_interval) * polling_interval
        if test == timestamp:
            valid = True

    # Return
    return valid
Пример #2
0
    def test_is_numeric(self):
        """Testing function is_numeric."""
        # Test False
        items = [None, True, False, 'False']
        for item in items:
            result = data.is_numeric(item)
            self.assertFalse(result)

        # Test True
        items = [1, 1.1, '1.1']
        for item in items:
            result = data.is_numeric(item)
            self.assertTrue(result)
Пример #3
0
def normalized_timestamp(_pi, timestamp=None):
    """Normalize timestamp to a multiple of 'polling_interval' seconds.

    Args:
        timestamp: epoch style timestamp in millseconds
        _pi: Polling interval for data in milliseconds. Defaults to assuming
            1000 if 'None'.

    Returns:
        value: Normalized value

    """
    # Initialize key variables
    if bool(_pi) is True:
        if isinstance(_pi, int) is False:
            log_message = ('''\
Invalid non-integer "polling_interval" value of {}'''.format(_pi))
            log.log2die(1029, log_message)
        else:
            polling_interval = abs(_pi)
    else:
        # Don't allow 0 values for polling_interval
        polling_interval = 1000

    # Process data
    if (timestamp is None) or (data.is_numeric(timestamp) is False):
        value = (int(time.time() * 1000) //
                 polling_interval) * polling_interval
    else:
        value = (int(timestamp) // polling_interval) * polling_interval

    # Return
    return value
Пример #4
0
    def _get_target_datapoints(self, item):
        """Poll each spoke in parallel.

        Args:
            item: TargetPollingPoints object

        Returns:
            ddv: TargetDataPoints for the SNMPVariable target

        """
        # Intialize data gathering
        ip_target = item.target
        ddv = TargetDataPoints(ip_target)

        # BAC0 only works with IP addresses
        ip_address = network.get_ipaddress(ip_target)
        if bool(ip_address) is False:
            return ddv

        # Get list of type DataPoint
        datapoints = []
        for polltarget in item.data:
            # Get polling results
            value = poll_target_address(ip_address, polltarget.address,
                                        'presentValue', self._bacnet)
            name = poll_target_address(ip_address, polltarget.address,
                                       'objectName', self._bacnet)

            # Skip if invalid data is received
            if value is None:
                continue

            # Do multiplication
            if data.is_numeric(value) is True:
                value = float(value) * polltarget.multiplier
                data_type = DATA_FLOAT
            else:
                data_type = DATA_STRING

            # Update datapoints
            datapoint = DataPoint('analog_value_point_{}'.format(
                polltarget.address),
                                  value,
                                  data_type=data_type)
            datapoint.add(DataPointMetadata('target', ip_target))
            if name is not None:
                datapoint.add(DataPointMetadata('object_name', name))
            datapoints.append(datapoint)

        # Return
        ddv.add(datapoints)
        return ddv
Пример #5
0
    def valid_format(self):
        """Determine whether the format of the oid is correct.

        Args:
            None

        Returns:
            invalid: False if OK

        """
        # Initialize key variables
        oid = self.oid
        valid = True

        # oid cannot be boolean
        if oid is True:
            valid = False
        if oid is False:
            valid = False
        if oid is None:
            valid = False

        # oid cannot be numeric
        if isinstance(oid, str) is False:
            valid = False

        # Make sure the oid is not blank
        stripped_oid = oid.strip()
        if len(stripped_oid) == 0:
            valid = False
            return valid

        # Must start with a '.'
        if oid[0] != '.':
            valid = False

        # Must not end with a '.'
        if oid[-1] == '.':
            valid = False

        # Test each node to be numeric
        nodes = oid.split('.')

        # Remove the first element of the list
        nodes.pop(0)
        for value in nodes:
            if data.is_numeric(value) is False:
                valid = False

        # Otherwise valid
        return valid
Пример #6
0
    def __init__(self, register=None, count=1, unit=0, multiplier=1):
        """Initialize the class.

        Args:
            register: Register number
            count: The number of registers to read
            unit: The slave unit this request is targeting
            multiplier: Value to multiply register results by

        Returns:
            None

        """
        # Initialize key variables
        self.address = None

        # Apply the multiplier
        if bool(multiplier) is False:
            self.multiplier = 1
        elif data.is_numeric(multiplier) is True:
            self.multiplier = float(multiplier)
        else:
            self.multiplier = 1

        # Set object as being.valid
        valid = False not in [
            isinstance(register, int),
            bool(register), register is not False, register is not True,
            register is not None,
            isinstance(count, int), count is not False, count is not True,
            count is not None,
            isinstance(unit, int) is True, unit is not False, unit is not True,
            unit is not None
        ]
        # This part is separate as we need to do some mathematical functions
        # that are based on the validity of the previous tests
        if valid is True:
            self.valid = False not in [
                valid, 0 <= unit <= 246, 0 < count < 2008
            ]
        else:
            self.valid = False

        # Assign values
        self.count = count
        self.unit = unit
        self.register = register
Пример #7
0
    def __init__(self, oid):
        """Initialize the class.

        Args:
            oid: OID to process

        Returns:
            None

        """
        # Initialize key variables
        self.oid = str(oid)

        # OID must be string
        if data.is_numeric(self.oid):
            log_message = ('OID value {} is not a string.'.format(self.oid))
            log.log2die(51380, log_message)
    def __init__(self, address=None, multiplier=1):
        """Initialize the class.

        Args:
            address: Address to poll
            multiplier: Multiplier to use when polled

        Returns:
            None

        """
        # Initialize variables
        self.address = address
        if data.is_numeric(multiplier) is True:
            self.multiplier = multiplier
        else:
            self.multiplier = 1
        self.valid = address is not None

        # Create checksum
        seed = '{}{}'.format(address, multiplier)
        self.checksum = data.hashstring(seed)
Пример #9
0
def _get_unit(data):
    """Get the unit to be polled in the polling_group.

    Args:
        data: Configuration dict for the polling_group

    Returns:
        result: unit value

    """
    # Ignore invalid non-dicts
    if isinstance(data, dict) is False:
        result = 0
        return result

    # Default value
    if 'unit' not in data:
        result = 0
        return result

    # Non integer values got to default
    unit = data['unit']
    valid = False in [
        lib_data.is_numeric(unit) is False,
        isinstance(unit, str) is True, unit is False, unit is True,
        unit is None
    ]
    if valid is False:
        result = 0
        return result

    # Convert float values to integer values
    if isinstance(unit, float) is True:
        result = int(unit)
    else:
        result = unit

    # Return
    return result
    def __init__(self, key, value, data_type=DATA_INT, timestamp=None):
        """Initialize the class.

        Args:
            key: Key related to data value
            value: Data value
            data_type: This MUST be one of the types listed in constants.py
            timestamp: Integer EPOCH timestamp in milliseconds

        Returns:
            None

        Variables:
            self.timestamp: Integer of epoch milliseconds
            self.valid: True if the object has a valid data_type
            self.checksum: Hash of self.key, self.data_type and metadata to
                ensure uniqueness when assigned to a target.

        """
        # Initialize variables
        (self.key, self.value, self.valid) = _key_value_valid(key,
                                                              value,
                                                              metadata=False)
        self.data_type = data_type
        self.metadata = {}
        self._metakeys = []

        # Round timestamp to the nearest millisecond.
        if data.is_numeric(timestamp) is False:
            self.timestamp = int(round(time(), 3) * 1000)
        else:
            self.timestamp = int(timestamp)

        # False validity if value is not of the right type
        self.valid = False not in [
            data_type in [
                DATA_INT, DATA_FLOAT, DATA_COUNT64, DATA_COUNT, DATA_STRING,
                DATA_NONE
            ], data_type is not False, data_type is not True, data_type
            is not None, self.valid is True
        ]

        # Validity check: Make sure numeric data_types have numeric values
        if False not in [
                data_type in [DATA_INT, DATA_FLOAT, DATA_COUNT64, DATA_COUNT],
                self.valid is True,
                data.is_numeric(value) is False
        ]:
            self.valid = False

        # Convert floatable strings to float, and integers to ints
        if False not in [
                self.valid is True,
                data.is_numeric(value) is True,
                isinstance(value, str) is True
        ]:
            if data_type in [DATA_FLOAT, DATA_COUNT64, DATA_COUNT]:
                self.value = float(value)
            elif data_type in [DATA_INT]:
                self.value = int(float(value))

        # Convert strings to string
        if data_type in [DATA_STRING]:
            self.value = str(value)

        # Create checksum
        self.checksum = data.hashstring('{}{}'.format(self.key,
                                                      self.data_type))
Пример #11
0
async def _serial_poller_async(tpp):
    """Poll OPCUA agent data.

    Args:
        tpp: TargetDataPoints object

    Returns:
        target_datapoints: TargetDataPoints object

    """
    # Initialize key variables
    connected = False

    # Test for validity
    if isinstance(tpp, TargetPollingPoints) is False:
        return None
    if isinstance(tpp.target, OPCUAauth) is False:
        return None
    if tpp.valid is False:
        return None

    # Create URL for polling
    ip_target = tpp.target.ip_target
    ip_port = tpp.target.ip_port
    username = tpp.target.username
    password = tpp.target.password
    url = 'opc.tcp://{}:{}'.format(ip_target, ip_port)

    # Intialize data gathering
    target_datapoints = TargetDataPoints(ip_target)

    # Create a client object to connect to OPCUA server
    client = Client(url=url)
    client.set_user(username)
    client.set_password(password)

    # Connect
    try:
        await client.connect()
        connected = True
    except:
        log_message = (
            'Authentication for polling target {} is incorrect'.format(url))
        log.log2warning(51011, log_message)
        pass

    if connected is True:
        for point in tpp.data:
            # Make sure we have the right data type
            if isinstance(point, PollingPoint) is False:
                log_message = ('''\
Invalid polling point {} for OPC UA URL {}'''.format(point, url))
                log.log2info(51012, log_message)
                continue

            # Get data
            address = point.address
            try:
                node = client.get_node(address)
                value = await node.read_value()
            except BadNodeIdUnknown:
                log_message = ('''\
OPC UA node {} not found on server {}'''.format(address, url))
                log.log2warning(51015, log_message)
                continue
            except:
                _exception = sys.exc_info()
                log_message = ('OPC UA server communication error')
                log.log2exception(51014, _exception, message=log_message)
                log_message = ('''\
Cannot get value from polling point {} for OPC UA URL {}\
'''.format(address, url))
                log.log2info(51013, log_message)
                continue

            # Create datapoint
            if bool(point.multiplier) is True:
                if is_numeric(value) is True and (is_numeric(point.multiplier)
                                                  is True):
                    value = value * point.multiplier
            else:
                value = 0
            datapoint = DataPoint(address, value)
            datapoint.add(DataPointMetadata('OPCUA Server', ip_target))
            target_datapoints.add(datapoint)

        # Disconnect client
        await client.disconnect()

    return target_datapoints