Skip to content
Snippets Groups Projects
Commit 61f7f237 authored by Taya Snijder's avatar Taya Snijder
Browse files

merged with most up to date version

parents 45c97c53 408d24aa
No related branches found
No related tags found
1 merge request!26Resolve #2021 "04 16 branched from master snmp device"
# -*- coding: utf-8 -*-
#
# This file is part of the SDP project
#
#
#
# Distributed under the terms of the APACHE license.
# See LICENSE.txt for more info.
""" SDP Device Server for LOFAR2.0
"""
# PyTango imports
from tango.server import run
from tango.server import device_property
from tango import AttrWriteType
#attribute extention and hardware device imports
from src.attribute_wrapper import attribute_wrapper
from src.hardware_device import hardware_device
import numpy
# Additional import
from clients.opcua_connection import OPCUAConnection
__all__ = ["APSCTL", "main"]
class APSCTL(hardware_device):
"""
**Properties:**
- Device Property
OPC_Server_Name
- Type:'DevString'
OPC_Server_Port
- Type:'DevULong'
OPC_Time_Out
- Type:'DevDouble'
"""
# -----------------
# Device Properties
# -----------------
OPC_Server_Name = device_property(
dtype='DevString',
mandatory=True
)
OPC_Server_Port = device_property(
dtype='DevULong',
mandatory=True
)
OPC_Time_Out = device_property(
dtype='DevDouble',
mandatory=True
)
# ----------
# Attributes
# ----------
N_unb = 2
N_fpga = 4
N_ddr = 2
N_qsfp = 6
# Central CP per Uniboard
UNB2_Power_ON_OFF_RW = attribute_wrapper(comms_annotation=["2:PCC", "2:UNB2_Power_ON_OFF_RW"], datatype=numpy.bool_, dims=(N_unb,), access=AttrWriteType.READ_WRITE)
UNB2_Front_Panel_LED_RW = attribute_wrapper(comms_annotation=["2:PCC", "2:UNB2_Front_Panel_LED_RW"], datatype=numpy.uint8, dims=(N_unb,), access=AttrWriteType.READ_WRITE)
UNB2_Mask_RW = attribute_wrapper(comms_annotation=["2:PCC", "2:UNB2_Mask_RW"], datatype=numpy.bool_, dims=(N_unb,), access=AttrWriteType.READ_WRITE)
# Central MP per Uniboard
UNB2_I2C_bus_OK_R = attribute_wrapper(comms_annotation=["2:PCC", "2:UNB2_I2C_bus_OK_R"], datatype=numpy.bool_, dims=(N_unb,))
UNB2_Front_Panel_LED_R = attribute_wrapper(comms_annotation=["2:PCC", "2:UNB2_Front_Panel_LED_R"], datatype=numpy.uint8, dims=(N_unb,))
UNB2_EEPROM_Serial_Number_R = attribute_wrapper(comms_annotation=["2:PCC", "2:UNB2_EEPROM_Serial_Number_R"], datatype=numpy.str, dims=(N_unb,))
UNB2_EEPROM_Unique_ID_R = attribute_wrapper(comms_annotation=["2:PCC", "2:UNB2_EEPROM_Unique_ID_R"], datatype=numpy.uint32, dims=(N_unb,))
UNB2_DC_DC_48V_12V_VIN_R = attribute_wrapper(comms_annotation=["2:PCC", "2:UNB2_DC_DC_48V_12V_VIN_R"], datatype=numpy.double, dims=(N_unb,))
UNB2_DC_DC_48V_12V_VOUT_R = attribute_wrapper(comms_annotation=["2:PCC", "2:UNB2_DC_DC_48V_12V_VOUT_R"], datatype=numpy.double, dims=(N_unb,))
UNB2_DC_DC_48V_12V_IOUT_R = attribute_wrapper(comms_annotation=["2:PCC", "2:UNB2_DC_DC_48V_12V_IOUT_R"], datatype=numpy.double, dims=(N_unb,))
UNB2_DC_DC_48V_12V_TEMP_R = attribute_wrapper(comms_annotation=["2:PCC", "2:UNB2_DC_DC_48V_12V_TEMP_R"], datatype=numpy.double, dims=(N_unb,))
UNB2_POL_QSFP_N01_VOUT_R = attribute_wrapper(comms_annotation=["2:PCC", "2:UNB2_POL_QSFP_N01_VOUT_R"], datatype=numpy.double, dims=(N_unb,))
UNB2_POL_QSFP_N01_IOUT_R = attribute_wrapper(comms_annotation=["2:PCC", "2:UNB2_POL_QSFP_N01_IOUT_R"], datatype=numpy.double, dims=(N_unb,))
UNB2_POL_QSFP_N01_TEMP_R = attribute_wrapper(comms_annotation=["2:PCC", "2:UNB2_POL_QSFP_N01_TEMP_R"], datatype=numpy.double, dims=(N_unb,))
UNB2_POL_QSFP_N23_VOUT_R = attribute_wrapper(comms_annotation=["2:PCC", "2:UNB2_POL_QSFP_N23_VOUT_R"], datatype=numpy.double, dims=(N_unb,))
UNB2_POL_QSFP_N23_IOUT_R = attribute_wrapper(comms_annotation=["2:PCC", "2:UNB2_POL_QSFP_N23_IOUT_R"], datatype=numpy.double, dims=(N_unb,))
UNB2_POL_QSFP_N23_TEMP_R = attribute_wrapper(comms_annotation=["2:PCC", "2:UNB2_POL_QSFP_N23_TEMP_R"], datatype=numpy.double, dims=(N_unb,))
UNB2_POL_SWITCH_1V2_VOUT_R = attribute_wrapper(comms_annotation=["2:PCC", "2:UNB2_POL_SWITCH_1V2_VOUT_R"], datatype=numpy.double, dims=(N_unb,))
UNB2_POL_SWITCH_1V2_IOUT_R = attribute_wrapper(comms_annotation=["2:PCC", "2:UNB2_POL_SWITCH_1V2_IOUT_R"], datatype=numpy.double, dims=(N_unb,))
UNB2_POL_SWITCH_1V2_TEMP_R = attribute_wrapper(comms_annotation=["2:PCC", "2:UNB2_POL_SWITCH_1V2_TEMP_R"], datatype=numpy.double, dims=(N_unb,))
UNB2_POL_SWITCH_PHY_VOUT_R = attribute_wrapper(comms_annotation=["2:PCC", "2:UNB2_POL_SWITCH_PHY_VOUT_R"], datatype=numpy.double, dims=(N_unb,))
UNB2_POL_SWITCH_PHY_IOUT_R = attribute_wrapper(comms_annotation=["2:PCC", "2:UNB2_POL_SWITCH_PHY_IOUT_R"], datatype=numpy.double, dims=(N_unb,))
UNB2_POL_SWITCH_PHY_TEMP_R = attribute_wrapper(comms_annotation=["2:PCC", "2:UNB2_POL_SWITCH_PHY_TEMP_R"], datatype=numpy.double, dims=(N_unb,))
UNB2_POL_CLOCK_VOUT_R = attribute_wrapper(comms_annotation=["2:PCC", "2:UNB2_POL_CLOCK_VOUT_R"], datatype=numpy.double, dims=(N_unb,))
UNB2_POL_CLOCK_IOUT_R = attribute_wrapper(comms_annotation=["2:PCC", "2:UNB2_POL_CLOCK_IOUT_R"], datatype=numpy.double, dims=(N_unb,))
UNB2_POL_CLOCK_TEMP_R = attribute_wrapper(comms_annotation=["2:PCC", "2:UNB2_POL_CLOCK_TEMP_R"], datatype=numpy.double, dims=(N_unb,))
# monitor points per FPGA
UNB2_FPGA_DDR4_SLOT_TEMP_R = attribute_wrapper(comms_annotation=["2:PCC", "2:UNB2_FPGA_DDR4_SLOT_TEMP_R"], datatype=numpy.double, dims=(N_unb,N_fpga))
UNB2_FPGA_DDR4_SLOT_PART_NUMBER_R = attribute_wrapper(comms_annotation=["2:PCC", "2:UNB2_FPGA_DDR4_SLOT_PART_NUMBER_R"], datatype=numpy.str, dims=(N_unb * N_qsfp,N_fpga))
UNB2_FPGA_QSFP_CAGE_0_TEMP_R = attribute_wrapper(comms_annotation=["2:PCC", "2:UNB2_FPGA_QSFP_CAGE_0_TEMP_R"], datatype=numpy.double, dims=(N_unb,N_fpga))
UNB2_FPGA_QSFP_CAGE_1_TEMP_R = attribute_wrapper(comms_annotation=["2:PCC", "2:UNB2_FPGA_QSFP_CAGE_1_TEMP_R"], datatype=numpy.double, dims=(N_unb,N_fpga))
UNB2_FPGA_QSFP_CAGE_2_TEMP_R = attribute_wrapper(comms_annotation=["2:PCC", "2:UNB2_FPGA_QSFP_CAGE_2_TEMP_R"], datatype=numpy.double, dims=(N_unb,N_fpga))
UNB2_FPGA_QSFP_CAGE_3_TEMP_R = attribute_wrapper(comms_annotation=["2:PCC", "2:UNB2_FPGA_QSFP_CAGE_3_TEMP_R"], datatype=numpy.double, dims=(N_unb,N_fpga))
UNB2_FPGA_QSFP_CAGE_4_TEMP_R = attribute_wrapper(comms_annotation=["2:PCC", "2:UNB2_FPGA_QSFP_CAGE_4_TEMP_R"], datatype=numpy.double, dims=(N_unb,N_fpga))
UNB2_FPGA_QSFP_CAGE_5_TEMP_R = attribute_wrapper(comms_annotation=["2:PCC", "2:UNB2_FPGA_QSFP_CAGE_5_TEMP_R"], datatype=numpy.double, dims=(N_unb,N_fpga))
UNB2_FPGA_QSFP_CAGE_0_LOS_R = attribute_wrapper(comms_annotation=["2:PCC", "2:UNB2_FPGA_QSFP_CAGE_0_LOS_R"], datatype=numpy.uint8, dims=(N_unb,N_fpga))
UNB2_FPGA_QSFP_CAGE_1_LOS_R = attribute_wrapper(comms_annotation=["2:PCC", "2:UNB2_FPGA_QSFP_CAGE_1_LOS_R"], datatype=numpy.uint8, dims=(N_unb,N_fpga))
UNB2_FPGA_QSFP_CAGE_2_LOS_R = attribute_wrapper(comms_annotation=["2:PCC", "2:UNB2_FPGA_QSFP_CAGE_2_LOS_R"], datatype=numpy.uint8, dims=(N_unb,N_fpga))
UNB2_FPGA_QSFP_CAGE_3_LOS_R = attribute_wrapper(comms_annotation=["2:PCC", "2:UNB2_FPGA_QSFP_CAGE_3_LOS_R"], datatype=numpy.uint8, dims=(N_unb,N_fpga))
UNB2_FPGA_QSFP_CAGE_4_LOS_R = attribute_wrapper(comms_annotation=["2:PCC", "2:UNB2_FPGA_QSFP_CAGE_4_LOS_R"], datatype=numpy.uint8, dims=(N_unb,N_fpga))
UNB2_FPGA_QSFP_CAGE_5_LOS_R = attribute_wrapper(comms_annotation=["2:PCC", "2:UNB2_FPGA_QSFP_CAGE_5_LOS_R"], datatype=numpy.uint8, dims=(N_unb,N_fpga))
UNB2_FPGA_POL_CORE_VOUT_R = attribute_wrapper(comms_annotation=["2:PCC", "2:UNB2_FPGA_POL_CORE_VOUT_R"], datatype=numpy.double, dims=(N_unb,N_fpga))
UNB2_FPGA_POL_CORE_IOUT_R = attribute_wrapper(comms_annotation=["2:PCC", "2:UNB2_FPGA_POL_CORE_IOUT_R"], datatype=numpy.double, dims=(N_unb,N_fpga))
UNB2_FPGA_POL_CORE_TEMP_R = attribute_wrapper(comms_annotation=["2:PCC", "2:UNB2_FPGA_POL_CORE_TEMP_R"], datatype=numpy.double, dims=(N_unb,N_fpga))
UNB2_FPGA_POL_ERAM_VOUT_R = attribute_wrapper(comms_annotation=["2:PCC", "2:UNB2_FPGA_POL_ERAM_VOUT_R"], datatype=numpy.double, dims=(N_unb,N_fpga))
UNB2_FPGA_POL_ERAM_IOUT_R = attribute_wrapper(comms_annotation=["2:PCC", "2:UNB2_FPGA_POL_ERAM_IOUT_R"], datatype=numpy.double, dims=(N_unb,N_fpga))
UNB2_FPGA_POL_ERAM_TEMP_R = attribute_wrapper(comms_annotation=["2:PCC", "2:UNB2_FPGA_POL_ERAM_TEMP_R"], datatype=numpy.double, dims=(N_unb,N_fpga))
UNB2_FPGA_POL_RXGXB_VOUT_R = attribute_wrapper(comms_annotation=["2:PCC", "2:UNB2_FPGA_POL_RXGXB_VOUT_R"], datatype=numpy.double, dims=(N_unb,N_fpga))
UNB2_FPGA_POL_RXGXB_IOUT_R = attribute_wrapper(comms_annotation=["2:PCC", "2:UNB2_FPGA_POL_RXGXB_IOUT_R"], datatype=numpy.double, dims=(N_unb,N_fpga))
UNB2_FPGA_POL_RXGXB_TEMP_R = attribute_wrapper(comms_annotation=["2:PCC", "2:UNB2_FPGA_POL_RXGXB_TEMP_R"], datatype=numpy.double, dims=(N_unb,N_fpga))
UNB2_FPGA_POL_TXGXB_VOUT_R = attribute_wrapper(comms_annotation=["2:PCC", "2:UNB2_FPGA_POL_TXGXB_VOUT_R"], datatype=numpy.double, dims=(N_unb,N_fpga))
UNB2_FPGA_POL_TXGXB_IOUT_R = attribute_wrapper(comms_annotation=["2:PCC", "2:UNB2_FPGA_POL_TXGXB_IOUT_R"], datatype=numpy.double, dims=(N_unb,N_fpga))
UNB2_FPGA_POL_TXGXB_TEMP_R = attribute_wrapper(comms_annotation=["2:PCC", "2:UNB2_FPGA_POL_TXGXB_TEMP_R"], datatype=numpy.double, dims=(N_unb,N_fpga))
UNB2_FPGA_POL_HGXB_VOUT_R = attribute_wrapper(comms_annotation=["2:UNB2_FPGA_POL_HGXB_VOUT_R"], datatype=numpy.double, dims=(N_unb,N_fpga))
UNB2_FPGA_POL_HGXB_IOUT_R = attribute_wrapper(comms_annotation=["2:UNB2_FPGA_POL_HGXB_IOUT_R"], datatype=numpy.double, dims=(N_unb,N_fpga))
UNB2_FPGA_POL_HGXB_TEMP_R = attribute_wrapper(comms_annotation=["2:UNB2_FPGA_POL_HGXB_TEMP_R"], datatype=numpy.double, dims=(N_unb,N_fpga))
UNB2_FPGA_POL_PGM_VOUT_R = attribute_wrapper(comms_annotation=["2:UNB2_FPGA_POL_PGM_VOUT_R"], datatype=numpy.double, dims=(N_unb,N_fpga))
UNB2_FPGA_POL_PGM_IOUT_R = attribute_wrapper(comms_annotation=["2:UNB2_FPGA_POL_PGM_IOUT_R"], datatype=numpy.double, dims=(N_unb,N_fpga))
UNB2_FPGA_POL_PGM_TEMP_R = attribute_wrapper(comms_annotation=["2:UNB2_FPGA_POL_PGM_TEMP_R"], datatype=numpy.double, dims=(N_unb,N_fpga))
def delete_device(self):
"""Hook to delete resources allocated in init_device.
This method allows for any memory or other resources allocated in the
init_device method to be released. This method is called by the device
destructor and by the device Init command (a Tango built-in).
"""
self.debug_stream("Shutting down...")
self.Off()
self.debug_stream("Shut down. Good bye.")
# --------
# overloaded functions
# --------
def off(self):
""" user code here. is called when the state is set to OFF """
# Stop keep-alive
self.opcua_connection.stop()
def initialise(self):
""" user code here. is called when the sate is set to INIT """
"""Initialises the attributes and properties of the PCC."""
# set up the OPC ua client
self.OPCua_client = OPCUAConnection("opc.tcp://{}:{}/".format(self.OPC_Server_Name, self.OPC_Server_Port), "http://lofar.eu", self.OPC_Time_Out, self.Fault, self)
# map an access helper class
for i in self.attr_list():
try:
i.set_comm_client(self.OPCua_client)
except:
self.debug_stream("error in getting APSCTL attribute: {} from client".format(i))
self.OPCua_client.start()
# --------
# Commands
# --------
# ----------
# Run server
# ----------
def main(args=None, **kwargs):
"""Main function of the SDP module."""
return run((APSCTL,), args=args, **kwargs)
if __name__ == '__main__':
main()
# -*- coding: utf-8 -*-
#
# This file is part of the PCC project
#
#
#
# Distributed under the terms of the APACHE license.
# See LICENSE.txt for more info.
""" PCC Device Server for LOFAR2.0
"""
# PyTango imports
from tango.server import run
from tango.server import device_property
# Additional import
from clients.SNMP_client import SNMP_client
from src.attribute_wrapper import *
from src.hardware_device import *
__all__ = ["example_device", "main"]
class example_device(hardware_device):
"""
**Properties:**
- Device Property
SNMP_community
- Type:'DevString'
SNMP_host
- Type:'DevULong'
SNMP_timeout
- Type:'DevDouble'
"""
# -----------------
# Device Properties
# -----------------
# SNMP_community = device_property(
# dtype='DevString',
# mandatory=True
# )
#
# SNMP_host = device_property(
# dtype='DevString',
# mandatory=True
# )
#
# SNMP_timeout = device_property(
# dtype='DevDouble',
# mandatory=True
# )
SNMP_community = b"public"
SNMP_host = "127.0.0.1"
SNMP_timeout = 5.0
# ----------
# Attributes
# ----------
# simple scalar - description
attr1 = attribute_wrapper(comms_annotation={"oids": "1.3.6.1.2.1.1.1.0"}, datatype=numpy.str_, access=AttrWriteType.READ_WRITE)
# simple scalar uptime
attr2 = attribute_wrapper(comms_annotation={"oids": "1.3.6.1.2.1.1.3.0"}, datatype=numpy.int64, access=AttrWriteType.READ_WRITE)
# simple scalar with name
attr3 = attribute_wrapper(comms_annotation={"oids": "1.3.6.1.2.1.1.5.0"}, datatype=numpy.str_, access=AttrWriteType.READ_WRITE)
#spectrum with all elements
attr4 = attribute_wrapper(comms_annotation={"oids": ["1.3.6.1.2.1.2.2.1.1.1", "1.3.6.1.2.1.2.2.1.1.2", "1.3.6.1.2.1.2.2.1.1.3"]}, dims=(3,), datatype=numpy.int64)
#inferred spectrum
attr5 = attribute_wrapper(comms_annotation={"oids": ".1.3.6.1.2.1.2.2.1.1"}, dims=(3,), datatype=numpy.int64)
def always_executed_hook(self):
"""Method always executed before any TANGO command is executed."""
pass
def delete_device(self):
"""Hook to delete resources allocated in init_device.
This method allows for any memory or other resources allocated in the
init_device method to be released. This method is called by the device
destructor and by the device Init command (a Tango built-in).
"""
self.debug_stream("Shutting down...")
self.Off()
self.debug_stream("Shut down. Good bye.")
# --------
# overloaded functions
# --------
def initialise(self):
""" user code here. is called when the state is set to STANDBY """
# set up the SNMP ua client
self.snmp_manager = SNMP_client(self.SNMP_community, self.SNMP_host, self.SNMP_timeout, self.Fault, self)
# map the attributes to the OPC ua comm client
for i in self.attr_list():
i.set_comm_client(self.snmp_manager)
self.snmp_manager.start()
# --------
# Commands
# --------
# ----------
# Run server
# ----------
def main(args=None, **kwargs):
"""Main function of the PCC module."""
return run((example_device,), args=args, **kwargs)
if __name__ == '__main__':
main()
from .v1 import SNMPv1
versions = {
1: SNMPv1,
}
def Manager(*args, version=1, **kwargs):
try:
cls = versions[version]
except KeyError as e:
msg = "'version' must be one of {}".format(list(versions.keys()))
raise ValueError(msg) from e
return cls(*args, **kwargs)
# used to indicate that a string cannot be decoded because it violates encoding rules
class EncodingError(Exception):
pass
# used to indicate that a response violates the protocol in some way
class ProtocolError(Exception):
pass
class Timeout(Exception):
pass
__all__ = ['RWLock']
from threading import Lock
# returns a pair of objects, (r, w), which constitute a
# writer-preferred reader/writer lock
def RWLock():
r = Lock()
w = Lock()
return RLock(r, w), WLock(r, w)
class ContextLock:
def __enter__(self):
self.acquire()
def __exit__(self, *args, **kwargs):
self.release()
class RLock(ContextLock):
def __init__(self, r, w):
self.r = r
self.w = w
self.mutex = Lock()
self.queue = Lock()
self.count = 0
def acquire(self):
with self.queue:
with self.r:
with self.mutex:
if not self.count:
self.w.acquire()
self.count += 1
def release(self):
with self.mutex:
self.count -= 1
if not self.count:
self.w.release()
class WLock(ContextLock):
def __init__(self, r, w):
self.r = r
self.w = w
self.mutex = Lock()
self.count = 0
def acquire(self):
with self.mutex:
if not self.count:
self.r.acquire()
self.count += 1
self.w.acquire()
def release(self):
self.w.release()
with self.mutex:
self.count -= 1
if not self.count:
self.r.release()
__all__ = [
'ASN1', 'INTEGER', 'OCTET_STRING', 'NULL', 'OID', 'SEQUENCE', 'UNSIGNED',
'Counter32', 'Gauge32', 'TimeTicks', 'Integer32', 'Counter64', 'IpAddress',
'VarBind', 'VarBindList', 'PDU', 'GetRequestPDU', 'GetNextRequestPDU',
'GetResponsePDU', 'SetRequestPDU', 'Message',
]
from copy import copy
import socket
from .exceptions import EncodingError, ProtocolError
def unpack(obj):
if len(obj) < 2:
raise EncodingError("object encoding is too short")
dtype = obj[0]
l = obj[1]
index = 2
if l & 0x80:
index += l & 0x7f
if len(obj) < index:
raise EncodingError("Long form length field is incomplete")
l = 0
for num in obj[2:index]:
l <<= 8
l += num
if len(obj) < index + l:
raise EncodingError("Invalid length field: object encoding too short")
return dtype, obj[index:index+l], obj[index+l:]
def length(l):
if l < 0x80:
return bytes([l])
bytearr = bytearray()
while l:
bytearr.append(l & 0xff)
l >>= 8
# this works as long as (l < 2^1008), which is super big
bytearr.append(len(bytearr) | 0x80)
return bytes(reversed(bytearr))
class ASN1:
def __init__(self, value=None, encoding=None):
self._encoding = encoding
self._value = value
def __repr__(self):
return "{}({})".format(self.__class__.__name__, self)
@classmethod
def copy(cls, obj):
return cls(encoding=obj.encoding)
@staticmethod
def deserialize(obj, cls=None, leftovers=False):
dtype, encoding, tail = unpack(obj)
if tail and not leftovers:
raise EncodingError("Unexpected trailing bytes")
if cls is None:
try:
cls = types[dtype]
except KeyError as e:
message = "Unknown type: '0x{:02x}'".format(dtype)
raise ProtocolError(message) from e
elif dtype != cls.TYPE:
message = "Expected type '0x{:02x}'; got '0x{:02x}'"
message = message.format(cls.TYPE, dtype)
raise ProtocolError(message)
obj = cls(encoding=encoding)
return (obj, tail) if leftovers else obj
def serialize(self):
return bytes([self.TYPE]) + length(len(self.encoding)) + self.encoding
# The following methods must be overwritten for sequence types
def __bool__(self):
return bool(self.value)
def __eq__(self, other):
return self.value == other
def __ge__(self, other):
return self.value >= other
def __gt__(self, other):
return self.value > other
def __le__(self, other):
return self.value <= other
def __lt__(self, other):
return self.value < other
def __ne__(self, other):
return self.value != other
def __str__(self):
return repr(self.value)
def poke(self):
self.value
### Primitive types ###
class INTEGER(ASN1):
SIGNED = True
@property
def encoding(self):
if self._encoding is None:
encoding = bytearray()
x = self._value
# do - while
while True:
encoding.append(x & 0xff)
x >>= 8
if x in (0, -1):
break
self._encoding = bytes(reversed(encoding))
return self._encoding
@property
def value(self):
if self._value is None:
negative = self.SIGNED and bool(self._encoding[0] & 0x80)
x = 0
for byte in self._encoding:
x <<= 8
x |= byte
if negative:
bits = 8 * len(self._encoding)
self._value = -(~x + (1 << bits) + 1)
else:
self._value = x
return self._value
class OCTET_STRING(ASN1):
@property
def encoding(self):
if self._encoding is None:
self._encoding = self._value
return self._encoding
@property
def value(self):
if self._value is None:
self._value = self._encoding
return self._value
class NULL(ASN1):
def __init__(self, value=None, encoding=None):
if encoding:
raise EncodingError("Non-null encoding for NULL type")
elif value is not None:
raise ValueError("NULL cannot have non-null value")
def __str__(self):
return ""
@property
def encoding(self):
return b''
@property
def value(self):
return None
class OID(ASN1):
@property
def encoding(self):
if self._encoding is None:
if self._value[0] == '.':
self._value = self.value[1:]
segments = [int(segment) for segment in self._value.split('.')]
if len(segments) > 1:
segments[1] += segments[0] * 40
segments = segments[1:]
encoding = bytearray()
for num in segments:
bytearr = bytearray()
while num > 0x7f:
bytearr.append(num & 0x7f)
num >>= 7
bytearr.append(num)
for i in range(1, len(bytearr)):
bytearr[i] |= 0x80
bytearr.reverse()
encoding += bytearr
self._encoding = bytes(encoding)
return self._encoding
@property
def value(self):
if self._value is None:
encoding = self._encoding
first = encoding[0]
oid = [str(num) for num in divmod(first, 40)]
val = 0
for byte in encoding[1:]:
val |= byte & 0x7f
if byte & 0x80:
val <<= 7
else:
oid.append(str(val))
val = 0
if val:
raise EncodingError("OID ended in a byte with bit 7 set")
self._value = '.'.join(oid)
return self._value
class SEQUENCE(ASN1):
EXPECTED = None
def __init__(self, *values, encoding=None):
self.expected = copy(self.EXPECTED)
self._encoding = encoding
self._values = values or None
def __bool__(self):
return bool(self.values)
def __eq__(self, other):
return self.values == other
def __ge__(self, other):
return self.values >= other
def __gt__(self, other):
return self.values > other
def __le__(self, other):
return self.values <= other
def __lt__(self, other):
return self.values < other
def __ne__(self, other):
return self.values != other
def __str__(self):
return repr(self)
def __repr__(self, depth=0):
string = "{}{}:\n".format('\t'*depth, self.__class__.__name__)
depth += 1
for entry in self.values:
if isinstance(entry, SEQUENCE):
string += entry.__repr__(depth=depth)
else:
string += "{}{}: {}\n".format(
'\t'*depth,
entry.__class__.__name__,
entry
)
return string
def poke(self):
for val in self.values:
val.poke()
@property
def encoding(self):
if self._encoding is None:
encodings = [None] * len(self.values)
for i in range(len(self.values)):
encodings[i] = self.values[i].serialize()
self._encoding = b''.join(encodings)
return self._encoding
@property
def values(self):
if self._values is None:
definite = isinstance(self.expected, list)
sequence = []
encoding = self._encoding
while encoding:
if definite:
try:
cls = self.expected[len(sequence)]
except IndexError as e:
message = "{} has too many elements"
message = message.format(self.__class__.__name__)
raise ProtocolError(message) from e
else:
cls = self.expected
obj, encoding = ASN1.deserialize(encoding, cls=cls, leftovers=True)
sequence.append(obj)
if definite and len(sequence) < len(self.expected):
message = "{} has too few elements"
message = message.format(self.__class__.__name__)
raise ProtocolError(message)
self._values = tuple(sequence)
return self._values
### Composed types ###
class UNSIGNED(INTEGER):
SIGNED = False
class Counter32(UNSIGNED):
pass
class Gauge32(UNSIGNED):
pass
class TimeTicks(UNSIGNED):
pass
class Integer32(INTEGER):
pass
class Counter64(UNSIGNED):
pass
class IpAddress(OCTET_STRING):
@property
def encoding(self):
if self._encoding is None:
self._encoding = socket.inet_aton(self._value)
return self._encoding
@property
def value(self):
if self._value is None:
if len(self._encoding) == 4:
self._value = socket.inet_ntoa(self._encoding)
else:
raise ProtocolError("IP Address must be 4 bytes long")
return self._value
class VarBind(SEQUENCE):
EXPECTED = [
OID,
None,
]
def __init__(self, *args, **kwargs):
super(VarBind, self).__init__(*args, **kwargs)
self.error = None
@property
def name(self):
return self.values[0]
@property
def value(self):
return self.values[1]
class VarBindList(SEQUENCE):
EXPECTED = VarBind
def __getitem__(self, index):
return self.values[index]
def __iter__(self):
return iter(self.values)
def __len__(self):
return len(self.values)
class PDU(SEQUENCE):
EXPECTED = [
INTEGER,
INTEGER,
INTEGER,
VarBindList,
]
def __init__(self, request_id=0, error_status=0, error_index=0, vars=None, encoding=None):
values = (
INTEGER.copy(UNSIGNED(request_id)),
INTEGER(error_status),
INTEGER(error_index),
vars,
) if encoding is None else ()
super(PDU, self).__init__(*values, encoding=encoding)
@property
def request_id(self):
return self.values[0]
@property
def error_status(self):
return self.values[1]
@property
def error_index(self):
return self.values[2]
@property
def vars(self):
return self.values[3]
class GetRequestPDU(PDU):
pass
class GetNextRequestPDU(PDU):
pass
class GetResponsePDU(PDU):
pass
class SetRequestPDU(PDU):
pass
class Message(SEQUENCE):
EXPECTED = [
INTEGER,
OCTET_STRING,
GetResponsePDU,
]
def __init__(self, version=0, community=b'public', data=None, encoding=None):
values = (
INTEGER(version),
OCTET_STRING(community),
data,
) if encoding is None else ()
super(Message, self).__init__(*values, encoding=encoding)
@property
def version(self):
return self.values[0]
@property
def community(self):
return self.values[1]
@property
def data(self):
return self.values[2]
types = {
0x02: INTEGER,
0x04: OCTET_STRING,
0x05: NULL,
0x06: OID,
0x30: SEQUENCE,
0x40: IpAddress,
0x41: Counter32,
0x42: Gauge32,
0x43: TimeTicks,
0x44: Integer32,
0x46: Counter64,
0xa0: GetRequestPDU,
0xa1: GetNextRequestPDU,
0xa2: GetResponsePDU,
0xa3: SetRequestPDU,
}
for dtype, cls in types.items():
cls.TYPE = dtype
This diff is collapsed.
class StatusError(Exception):
pass
class TooBig(StatusError):
pass
class NoSuchName(StatusError):
pass
class BadValue(StatusError):
pass
class ReadOnly(StatusError):
pass
class GenErr(StatusError):
pass
get:
create main event
get pend table for host or create one
get data table for host or create dummy
with pend table lock
for each oid in the request
if not refresh
if pending
continue
if found in cache
grab cached result
continue
add main event to the pend table
add oid to request
if there are oids to be sent
construct message
add message to requests table
send message
if an oid had an error
raise it now
if not waiting for response
return the values you do have
wait for all events
with data table read lock
for each oid
grab the value
- make sure it is present
- make sure there are no errors
return the values
listen thread:
check port number
decode message
pull request id
find the corresponding request
make sure it has the right number of varbinds
remove request from table
check error status
with data table write lock
get/create entry for host
for each varbind
give it the error found in the request error field
find the oid requested
make sure it matches the request
save varbind to data table
set the request event
monitor thread:
wait for next stale request, done, or 1 second (whichever comes first)
grab next request
if it is stale
if it has not timed out
resend it
else
set varbind error to timeout
signal event
...@@ -13,63 +13,83 @@ ...@@ -13,63 +13,83 @@
# PyTango imports # PyTango imports
from tango.server import run from tango.server import run
from tango.server import device_property from tango.server import device_property
from tango import DevState
# Additional import # Additional import
<<<<<<< HEAD
from clients.SNMP_client import SNMP_client
from src.attribute_wrapper import *
from src.hardware_device import *
=======
from clients.test_client import test_client from clients.test_client import test_client
from util.attribute_wrapper import * from util.attribute_wrapper import *
from util.hardware_device import * from util.hardware_device import *
>>>>>>> master
__all__ = ["test_device", "main"] __all__ = ["example_device", "main"]
class example_device(hardware_device):
class test_device(hardware_device):
# ----------------- # -----------------
# Device Properties # Device Properties
# ----------------- # -----------------
OPC_Server_Name = device_property( SNMP_community = b"public"
dtype='DevString', SNMP_host = "127.0.0.1"
) SNMP_timeout = 5.0
OPC_Server_Port = device_property(
dtype='DevULong',
)
OPC_Time_Out = device_property(
dtype='DevDouble',
)
# ---------- # ----------
# Attributes # Attributes
# ---------- # ----------
bool_scalar_R = attribute_wrapper(comms_annotation="numpy.bool_ type read scalar", datatype=numpy.bool_)
bool_scalar_RW = attribute_wrapper(comms_annotation="numpy.bool_ type read/write scalar", datatype=numpy.bool_, access=AttrWriteType.READ_WRITE)
int32_spectrum_R = attribute_wrapper(comms_annotation="numpy.int32 type read spectrum (len = 8)", datatype=numpy.int32, dims=(8,)) # simple scalar
int32_spectrum_RW = attribute_wrapper(comms_annotation="numpy.int32 type read spectrum (len = 8)", datatype=numpy.int32, dims=(8,), attr1 = attribute_wrapper(comms_annotation={"oids": "1.3.6.1.2.1.1.6.0"}, datatype=numpy.bool_, access=AttrWriteType.READ_WRITE)
access=AttrWriteType.READ_WRITE) # simple scalar with host
attr2 = attribute_wrapper(comms_annotation={"oids": "1.3.6.1.2.1.1.5.0"}, datatype=numpy.bool_, access=AttrWriteType.READ_WRITE)
#spectrum with all elements
attr3 = attribute_wrapper(comms_annotation={"oids": ["1.3.6.1.2.1.1.5.1", "1.3.6.1.2.1.1.5.2", "1.3.6.1.2.1.1.5.3"]}, dims=(3,), datatype=numpy.bool_)
#inferred spectrum
attr4 = attribute_wrapper(comms_annotation={"oids": ["1.3.6.1.2.1.1.5.0"]}, dims=(3,), datatype=numpy.bool_)
double_image_R = attribute_wrapper(comms_annotation="numpy.double type read image (dims = 2x8)", datatype=numpy.double, dims=(2, 8)) def always_executed_hook(self):
double_image_RW = attribute_wrapper(comms_annotation="numpy.double type read/write image (dims = 8x2)", datatype=numpy.double, dims=(8, 2), """Method always executed before any TANGO command is executed."""
access=AttrWriteType.READ_WRITE) pass
int32_scalar_R = attribute_wrapper(comms_annotation="numpy.int32 type read scalar", datatype=numpy.int32) def delete_device(self):
uint16_spectrum_RW = attribute_wrapper(comms_annotation="numpy.uint16 type read/write spectrum (len = 8)", datatype=numpy.uint16, dims=(8,), """Hook to delete resources allocated in init_device.
access=AttrWriteType.READ_WRITE)
float32_image_R = attribute_wrapper(comms_annotation="numpy.float32 type read image (dims = 8x2)", datatype=numpy.float32, dims=(8, 2)) This method allows for any memory or other resources allocated in the
uint8_image_RW = attribute_wrapper(comms_annotation="numpy.uint8 type read/write image (dims = 2x8)", datatype=numpy.uint8, dims=(2, 8), init_device method to be released. This method is called by the device
access=AttrWriteType.READ_WRITE) destructor and by the device Init command (a Tango built-in).
"""
self.debug_stream("Shutting down...")
self.Off()
self.debug_stream("Shut down. Good bye.")
# -------- # --------
# overloaded functions # overloaded functions
# -------- # --------
def initialise(self): def initialise(self):
""" user code here. is called when the sate is set to INIT """ """ user code here. is called when the state is set to STANDBY """
"""Initialises the attributes and properties of the PCC."""
# set up the SNMP ua client
self.snmp_manager = SNMP_client(self.SNMP_community, self.SNMP_host, self.SNMP_timeout, self.Fault, self)
<<<<<<< HEAD
# map the attributes to the OPC ua comm client
for i in self.attr_list():
i.set_comm_client(self.snmp_manager)
self.set_state(DevState.INIT) self.snmp_manager.start()
# --------
# Commands
# --------
=======
# set up the test client # set up the test client
self.test_client = test_client(self.Fault, self) self.test_client = test_client(self.Fault, self)
...@@ -78,14 +98,15 @@ class test_device(hardware_device): ...@@ -78,14 +98,15 @@ class test_device(hardware_device):
i.set_comm_client(self.test_client) i.set_comm_client(self.test_client)
self.test_client.start() self.test_client.start()
>>>>>>> master
# ---------- # ----------
# Run server # Run server
# ---------- # ----------
def main(args=None, **kwargs): def main(args=None, **kwargs):
"""Main function of the example module.""" """Main function of the PCC module."""
return run((test_device,), args=args, **kwargs) return run((example_device,), args=args, **kwargs)
if __name__ == '__main__': if __name__ == '__main__':
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment