Example #1
0
    def write(self, client: Client) -> None:
        """
        Write current data to db in plc
        """
        if not isinstance(self._bytearray, DB):
            raise TypeError(
                f"Value self._bytearray: {self._bytearray} is not from type DB."
            )
        if self.row_size < 0:
            raise ValueError("row_size must be greater equal zero.")

        db_nr = self._bytearray.db_number
        offset = self.db_offset
        data = self.get_bytearray()[offset:offset + self.row_size]
        db_offset = self.db_offset

        # indicate start of write only area of row!
        if self.row_offset:
            data = data[self.row_offset:]
            db_offset += self.row_offset

        if self.area == Areas.DB:
            client.db_write(db_nr, db_offset, data)
        else:
            client.write_area(self.area, 0, db_offset, data)
Example #2
0
    def write(self, client: Client) -> None:
        """Write current data to db in plc

        Args:
            client: :obj:`Client` snap7 instance.

        Raises:
            :obj:`TypeError`: if the `_bytearray` is not an instance of :obj:`DB` class.
            :obj:`ValueError`: if the `row_size` is less than 0.
        """
        if not isinstance(self._bytearray, DB):
            raise TypeError(
                f"Value self._bytearray: {self._bytearray} is not from type DB."
            )
        if self.row_size < 0:
            raise ValueError("row_size must be greater equal zero.")

        db_nr = self._bytearray.db_number
        offset = self.db_offset
        data = self.get_bytearray()[offset:offset + self.row_size]
        db_offset = self.db_offset

        # indicate start of write only area of row!
        if self.row_offset:
            data = data[self.row_offset:]
            db_offset += self.row_offset

        if self.area == Areas.DB:
            client.db_write(db_nr, db_offset, data)
        else:
            client.write_area(self.area, 0, db_offset, data)
Example #3
0
    def read(self, client: Client) -> None:
        """Read current data of db row from plc.

        Args:
            client: :obj:`Client` snap7 instance.

        Raises:
            :obj:`TypeError`: if the `_bytearray` is not an instance of :obj:`DB` class.
            :obj:`ValueError`: if the `row_size` is less than 0.
        """
        if not isinstance(self._bytearray, DB):
            raise TypeError(
                f"Value self._bytearray:{self._bytearray} is not from type DB."
            )
        if self.row_size < 0:
            raise ValueError("row_size must be greater equal zero.")
        db_nr = self._bytearray.db_number
        if self.area == Areas.DB:
            bytearray_ = client.db_read(db_nr, self.db_offset, self.row_size)
        else:
            bytearray_ = client.read_area(self.area, 0, 0, self.row_size)

        data = self.get_bytearray()
        # replace data in bytearray
        for i, b in enumerate(bytearray_):
            data[i + self.db_offset] = b
    def setUp(self):
        self.databus = conpot_core.get_databus()
        self.databus.initialize('conpot/templates/snap7_server/template.xml')
        args = namedtuple('FakeArgs', '')
        logger.setLevel(logging.WARNING)
        self.snap7_instance = Snap7Server(
            'conpot/templates/snap7_server/snap7/snap7.xml', 'none', args)
        gevent.spawn(self.snap7_instance.start, '127.0.0.1', 60102)
        gevent.sleep(0.5)
        self.server_port = 60102

        self.client = Client()
        self.client.create()
        self.client.connect("127.0.0.1", 0, 0, tcpport=self.server_port)
Example #5
0
def plc_connect(plc):
    client = Client()
    try:
        client.connect(
            address=plc['ip'],
            rack=plc['rack'],
            slot=plc['slot'],
        )
    except Snap7Exception as e:
        logging.warning('PLC连接失败 ip:{} rack:{} slot:{}'.format(plc['ip'], plc['rack'], plc['slot']) + str(e))
        id_num = r.get('id_num')
        connect_plc_err(
            id_num,
            plc_id=plc['id'],
        )

    return client
Example #6
0
class PLC:

    online = False
    debug = False
    camera_number: int

    def __init__(self, camera_number, config_file='config.yml') -> None:
        self.load_config(config_file)
        self.camera_number = camera_number
        self.client = Client()

    def load_config(self, config_file='config.yml') -> None:
        with open(config_file) as file:
            config = yaml.safe_load(file)['plc']
        self.enabled = config['enabled']
        self.ip = config['ip']
        self.rack = config['rack']
        self.slot = config['slot']
        self.db_read: dict = config['db_read']
        self.db_write: dict = config['db_write']
        self.update_time = config['update_time']
        self.debug = config['debug']

    def connect(self) -> None:

        if not self.enabled:
            return logger.info(
                'PLC is Disabled, change config file to start communication')

        if self.client:
            try:
                self.client.connect(self.ip, self.rack, self.slot)
                self.online = True
                logging.info(
                    f"PLC Connected to {self.ip} Rack {self.rack} Slot {self.slot}"
                )
            except Exception as e:
                logging.exception(
                    f"connect::Failed to connect to PLC {self.ip} " + str(e))

    def read(self) -> bytearray:
        try:
            db = self.db_read
            start = db['size'] * self.camera_number
            return self.client.db_read(db['number'], start, db['size'])
        except Exception as e:
            logger.exception(e)

    def write(self, _bytearray: bytearray) -> None:
        try:
            db = self.db_write
            start = db['size'] * self.camera_number
            self.client.db_write(db['number'], start, _bytearray)
        except Exception as e:
            logger.exception(e)

    def disconnect(self):
        self.online = False
        self.client.disconnect()
Example #7
0
    def read(self, client: Client) -> None:
        """
        read current data of db row from plc
        """
        if not isinstance(self._bytearray, DB):
            raise TypeError(
                f"Value self._bytearray:{self._bytearray} is not from type DB."
            )
        if self.row_size < 0:
            raise ValueError("row_size must be greater equal zero.")
        db_nr = self._bytearray.db_number
        if self.area == Areas.DB:
            bytearray_ = client.db_read(db_nr, self.db_offset, self.row_size)
        else:
            bytearray_ = client.read_area(self.area, 0, 0, self.row_size)

        data = self.get_bytearray()
        # replace data in bytearray
        for i, b in enumerate(bytearray_):
            data[i + self.db_offset] = b
Example #8
0
 def __init__(self, ip='192.168.0.1'):
     self.ip = ip
     self.INByteArray = bytearray([0, 0])
     self.MKByteArray = bytearray([0, 0])
     self.threadStatus = False
     self.varsdict = {}
     self.threads = {}
     self.plc = PlcClient()
     self.subNodes = []
     self.subNodesD = {}
     self.keysDict = {}
     self.inNodes = {}
Example #9
0
class SiemensPlc(SmartTags):
    def __init__(self, ipaddr, name=None):
        self.ipaddr = ipaddress.IPv4Address(ipaddr)
        self.name = name
        self._port = 102
        self._client = Client()
        self.SmartTags = SmartTags(self)

    def connect(self):
        return self._client.connect(self.ipaddr, 0, 0, self.port)

    def get_connected(self):
        return self._client.get_connected()

    def disconnect(self):
        return self._client.disconnect()

    def get_plc_state(self):
        return self._client.get_cpu_state()

    def get_plc_info(self):
        return self._client.get_cpu_info()

    def get_datetime(self):
        return self._client.get_plc_datetime()
Example #10
0
def plc_client(ip, rack, slot, plc_id):
    """
    建立plc连接的上下文管理器
    :param ip: 
    :param rack: 
    :param slot: 
    :return: 
    """
    client = Client()
    try:
        client.connect(ip, rack, slot)
    except Snap7Exception as e:
        logging.warning('连接plc失败' + str(e))
        session = Session()
        id_num = r.get('id_num')
        alarm = connect_plc_err(id_num, plc_id)
        session.add(alarm)
        session.commit()
    yield client
    client.disconnect()
    client.destroy()
Example #11
0
from snap7.client import Client
from snap7.util import *
from snap7.snap7exceptions import Snap7Exception
from snap7.snap7types import *

IP = '127.0.0.1'
PORT = 8088
RACK = 0
SLOT = 0
client = Client()
client.connect(IP, RACK, SLOT, PORT)
with open('lecturas/db0.txt', 'r') as f:
    layout = f.read()

db_number = 0
all_data = client.db_get(db_number)

db1 = DB(
    db_number,  # the db we use
    all_data,  # bytearray from the plc
    layout,  # layout specification DB variable data
    6 + 2,  # size of the specification 17 is start
    1,  # number of row's / specifications
)

[print(db) for db in db1]

with open('lecturas/marcas.txt', 'r') as f:
    layout = f.read()
all_data = client.read_area(S7AreaMK, 0, 0, 10)
db2 = DB(
Example #12
0
class PLC:
    def __init__(self, ip='127.0.0.1', name='Default Plc'):
        self.ip = ip
        self.name = name
        self.read_client = Client()
        self.write_client = Client()
        self.SmartTags = SmartTags(self)

    def __repr__(self):
        return f"{self.name} @ {self.ip}"

    def __str__(self):
        return f"{self.name} @ {self.ip}"

    def connect(self):
        if self.read_client.get_connected(
        ) and self.write_client.get_connected():
            return True
        try:
            if not self.read_client.get_connected():
                self.read_client.connect(self.ip, 0, 0)

            if not self.write_client.get_connected():
                self.write_client.connect(self.ip, 0, 0)
        except Snap7Exception as e:
            logger.error(str(e))
            return False

        return self.read_client.get_connected(
        ) and self.write_client.get_connected()

    def disconnect(self):
        self.read_client.disconnect()
        self.write_client.disconnect()

    def read(self, db, start, length):
        try:
            return self.read_client.read_area(S7AreaDB, db, start, length)
        except Exception as e:
            if 'CLI : Job pending' in str(e):
                return self.read(db, start, length)
            else:
                raise e

    def write(self, db, start, data):
        try:
            return self.read_client.write_area(S7AreaDB, db, start, data)
        except Exception as e:
            if 'CLI : Job pending' in str(e):
                return self.write(db, start, data)
            else:
                raise e
Example #13
0
class TestBase(unittest.TestCase):
    def setUp(self):
        self.databus = conpot_core.get_databus()
        self.databus.initialize('conpot/templates/snap7_server/template.xml')
        args = namedtuple('FakeArgs', '')
        logger.setLevel(logging.WARNING)
        self.snap7_instance = Snap7Server(
            'conpot/templates/snap7_server/snap7/snap7.xml', 'none', args)
        gevent.spawn(self.snap7_instance.start, '127.0.0.1', 60102)
        gevent.sleep(0.5)
        self.server_port = 60102

        self.client = Client()
        self.client.create()
        self.client.connect("127.0.0.1", 0, 0, tcpport=self.server_port)

    def tearDown(self):
        self.client.disconnect()
        gevent.sleep(1)
        self.snap7_instance.stop()

    def test_info(self):
        expected = {
            'ModuleTypeName': 'Some CPU',
            'SerialNumber': '123456789',
            'ASName': 'Some system',
            'Copyright': 'Someone',
            'ModuleName': 'Some PLC'
        }

        info = self.client.get_cpu_info()
        param_list = [param[0] for param in info._fields_]
        result = {}
        for param in param_list:
            result[param] = getattr(info, param)

        self.assertSequenceEqual(expected.keys(), result.keys())
        for key, val in result.items():
            self.assertEquals(expected[key], val)

    def test_cpu_state(self):
        expected = "S7CpuStatusRun"
        state = self.client.get_cpu_state()
        self.assertEquals(state, expected)

    def test_cpu_stop(self):
        expected = "S7CpuStatusStop"
        self.client.plc_stop()
        state = self.client.get_cpu_state()
        self.assertEquals(state, expected)

    def test_cpu_start(self):
        expected = "S7CpuStatusRun"
        self.client.plc_stop()
        self.client.plc_cold_start()
        state = self.client.get_cpu_state()
        self.assertEquals(state, expected)

        self.client.plc_stop()
        self.client.plc_hot_start()
        self.assertEquals(state, expected)

    def test_read_db_default_values(self):
        # Read database 1, which has a default initialization of all zeroes
        db_data = self.client.db_read(1, 0, 2)

        self.assertSequenceEqual(db_data, [0, 0])

    def test_read_db_initialized_values(self):
        # Read database 2, which has configured initial values (1, 0 ,- ,1)
        db_data = self.client.db_read(2, 0, 4)

        self.assertSequenceEqual(db_data, [1, 0, 0, 1])

    def test_read_db_out_of_range_values(self):
        size = self.snap7_instance.event_handler.dbs['s7comm_db1']['size']
        with self.assertRaises(Snap7Exception):
            self.client.db_read(1, 0, size + 1)

    def test_write_read_db(self):
        expected = [1, 0]
        self.client.db_write(1, 1, bytearray([0]))
        self.client.db_write(1, 0, bytearray([1]))
        db_data = self.client.db_read(1, 0, 2)
        output_list = []
        for data in db_data:
            output_list.append(data)
        self.assertSequenceEqual(output_list, expected)
Example #14
0
 def __init__(self, ip='127.0.0.1', name='Default Plc'):
     self.ip = ip
     self.name = name
     self.read_client = Client()
     self.write_client = Client()
     self.SmartTags = SmartTags(self)
Example #15
0
from snap7.client import Client

SERVER_IP = '127.0.0.100'
SERVER_PORT = 102

client = Client()
client.connect('127.0.0.100', 0, 2, SERVER_PORT)

try:
    print(client.get_plc_datetime())
    client.get_cpu_info()
    print(client.list_blocks())
    print(str(client.db_read(1, 0, 100)))
    client.db_write(1, 0, bytearray(b"HELLO, SERVER!"))
    print(str(client.db_read(1, 0, 100)))
    client.disconnect()
    client.plc_stop()
except RuntimeError as ex:
    print(ex)
Example #16
0
from snap7.client import Client
from snap7.util import *
from snap7.snap7exceptions import Snap7Exception
from snap7.snap7types import *
from extras import *
IP = '127.0.0.1'
PORT = 8088
RACK = 0
SLOT = 0
client = Client()
client.connect(IP, RACK, SLOT, PORT)
with open('lecturas/db_small_int.txt', 'r') as f:
    layout = f.read()

db_number = 0
all_data = client.db_get(db_number)

db1 = DB_mixin(
    db_number,  # the db we use
    all_data,  # bytearray from the plc
    layout,  # layout specification DB variable data
    10,  # size of the specification 17 is start
    3,  # number of row's / specifications
)

[print(db) for db in db1]
'''
with open('lecturas/marcas.txt', 'r') as f:
    layout = f.read()
all_data = client.read_area(S7AreaMK, 0, 0, 10)
db2 = DB(
Example #17
0
class MyPlc:
    area = {'I': 0x81, 'Q': 0x82, 'M': 0x83, 'D': 0x84}
    szs = {'x': 1, 'X': 1, 'b': 1, 'B': 1, 'w': 2, 'W': 2, 'd': 4, 'D': 4}

    def __init__(self, ip='192.168.0.1'):
        self.ip = ip
        self.INByteArray = bytearray([0, 0])
        self.MKByteArray = bytearray([0, 0])
        self.threadStatus = False
        self.varsdict = {}
        self.threads = {}
        self.plc = PlcClient()
        self.subNodes = []
        self.subNodesD = {}
        self.keysDict = {}
        self.inNodes = {}

    def get_db(self, server_id):
        self.db_server = Server.query.get(server_id)
        self.connections()

    def connections(self):
        self.opc_ns_uri = self.db_server.server_namespace
        self.ep_url = 'opc.tcp://' + self.db_server.server_endpoint_url
        self.opclient = Client(self.ep_url)
        try:
            self.plc.connect(self.ip, 0, 1)
            # pass
        except Exception:
            self.conn_stat = "Could not connect to PLC"
        else:
            self.conn_stat = "PLC Connected Successfully"

        self.opclient.connect()
        self.root = self.opclient.get_root_node()
        self.idx = self.opclient.get_namespace_index(
            self.db_server.server_namespace)
        self.set_tags(self.db_server.server_objects)
        for key, val in self.varsdict.items():
            if re.search("^(M|m)([\d]+).[\d]*$", key) is not None:
                self.subNodes.append(val['obj'])
                self.subNodesD[key] = val
            else:
                self.inNodes[key] = val
        self.run_threads()
        handler = SubHandler(self)
        sub = self.opclient.create_subscription(200, handler)
        handle = sub.subscribe_data_change(self.subNodes)
        time.sleep(0.1)

    def set_tags(self, objs):
        for obj in objs:
            try:
                self.make_tag_dict(obj, obj.object_variables)
            except Exception:
                self.make_tags_dict(obj.object_variables)
            finally:
                for var in obj.object_variables:
                    self.keysDict[var.variable_name] = var.variable_address

    def make_tag_dict(self, obj, allvars):
        for var in allvars:
            self.varsdict[var.variable_address] = {
                'obj':
                self.root.get_child([
                    "0:Objects", "{}:{}".format(self.idx, obj.object_name),
                    "{}:{}".format(self.idx, var.variable_name)
                ]),
                'type':
                var.variable_type
            }

    def kill_threads(self):
        self.threadStatus = False

    def run_threads(self):
        self.threadStatus = True
        self.threads['update_server'] = threading.Thread(
            target=self.updateInputs)
        self.threads['update_server'].start()

    def getInputs(self):
        while self.threadStatus:
            self.INByteArray = self.plc.read_area(areas['PE'], 0, 0, 2)
            # self.INByteArray = bytearray([ randint(0,7), randint(0,7) ])
            time.sleep(.1)

    # def get_bool(_bytearray, byte_index, bool_index):
    def updateInputs(self):
        while self.threadStatus:
            for key, val in self.inNodes.items():
                self.update_server_vars(key)
                time.sleep(.01)

    def writetoPLC(self, value, node):
        key = self.keysDict[node.get_browse_name().to_string().split(':')[1]]
        self.write_to_plc(key, value)

    '''
        Get Data from the PLC and Update OPC Server variables
    '''

    def update_server_vars(self, addr_key):
        addr = addr_key.split('.')
        # Works with Boolean values from a Data Block
        if len(addr) == 3 and addr[0][0] == 'D':
            DBn = int(addr[0][2:])
            DBt = addr[1][2]
            byt = int(addr[1][3:])
            bit = int(addr[2])
            reading = self.plc.read_area(MyPlc.area['D'], DBn, byt, szs[DBt])
            if DBt == 'X' or DBt == 'x':
                self.varsdict[addr_key]['obj'].set_value(
                    get_bool(reading, 0, bit))
                # return get_bool( reading, 0, bit )
            else:
                self.varsdict[addr_key]['obj'].set_value(reading)
                # return reading

        # Works with other data types from a Data Block
        elif len(addr) == 2 and addr[0][0] == 'D':
            DBn = int(addr[0][2:])
            DBt = addr[1][2]
            byt = int(addr[1][3:])
            reading = self.plc.read_area(MyPlc.area['D'], DBn, byt, szs[DBt])
            if DBt == 'W' or DBt == 'w':
                self.varsdict[addr_key]['obj'].set_value(get_int(reading, 0))
                # return get_int(reading,0)
            elif DBt == 'D' or DBt == 'd':
                self.varsdict[addr_key]['obj'].set_value(get_real(reading, 0))
                # return get_real(reading,0)
            else:
                self.varsdict[addr_key]['obj'].set_value(reading)

        # Works with boolean values from Inputs,Merkels and Outputs
        elif len(addr) == 2:
            byt = int(addr[0][1:])
            bit = int(addr[1])
            reading = self.plc.read_area(MyPlc.area[addr[0][0]], 0, byt, 1)
            self.varsdict[addr_key]['obj'].set_value(get_bool(reading, 0, bit))
            # return get_bool(reading,0,bit)

        # Works with other data types from Inputs,Merkels ot Outputs eg MW2
        elif len(addr) == 1:
            byt = int(addr[0][2:])
            typ = addr[0][1]
            reading = self.plc.read_area(MyPlc.area[addr[0][0]], 0, byt, 2)
            if typ == 'w' or typ == 'W':
                self.varsdict[addr_key]['obj'].set_value(get_int(reading, 0))
                # return get_int(reading, 0)
            elif typ == 'd' or typ == 'D':
                self.varsdict[addr_key]['obj'].set_value(get_real(reading, 0))
                # return get_real(reading, 0)
            else:
                self.varsdict[addr_key]['obj'].set_value(reading)
                # return reading

    '''
        WRITE DATA TO PLC FROM SERVER
    '''

    def write_to_plc(self, addr_key, value):
        addr = addr_key.split('.')
        print("New data change on {} : {}".format(addr_key, value))

        # Works with Boolean values from a Data Block
        if len(addr) == 3 and addr[0][0] == 'D':
            DBn = int(addr[0][2:])
            DBt = addr[1][2]
            byt = int(addr[1][3:])
            bit = int(addr[2])
            reading = self.plc.read_area(MyPlc.area['D'], DBn, byt,
                                         MyPlc.szs[DBt])
            if DBt == 'X' or DBt == 'x':
                set_bool(reading, 0, bit, value)
            self.plc.write_area(MyPlc.area['D'], DBn, byt, reading)

        # Works with other data types from a Data Block
        elif len(addr) == 2 and addr[0][0] == 'D':
            DBn = int(addr[0][2:])
            DBt = addr[1][2]
            byt = int(addr[1][3:])
            reading = self.plc.read_area(MyPlc.area['D'], DBn, byt,
                                         MyPlc.szs[DBt])
            if DBt == 'W' or DBt == 'w':
                set_int(reading, 0, value)
            elif DBt == 'D' or DBt == 'd':
                set_real(reading, 0, value)
            self.plc.write_area(MyPlc.area['D'], DBn, byt, reading)

        # Works with boolean values from Inputs,Merkels ot Outputs
        elif len(addr) == 2:
            byt = int(addr[0][1:])
            bit = int(addr[1])
            reading = self.plc.read_area(MyPlc.area[addr[0][0]], 0, byt, 1)
            set_bool(reading, 0, bit, value)
            self.plc.write_area(MyPlc.area[addr[0][0]], 0, byt, reading)

        # Works with other data types from Inputs,Merkels ot Outputs eg MW2
        elif len(addr) == 1:
            byt = int(addr[0][2:])
            typ = addr[0][1]
            reading = self.plc.read_area(MyPlc.area[addr[0][0]], 0, byt, 2)
            if typ == 'w' or typ == 'W':
                set_int(reading, 0, value)
            elif typ == 'd' or typ == 'D':
                set_real(reading, 0, value)
            else:
                set_data(value)
            self.plc.write_area(MyPlc.area[addr[0][0]], 0, byt, reading)
        marca = DB_mixin(0, marca_data, layout_marca, LONGITUD_MARCAS, 1)
        indice = marca[0]['index'] - 1
        INDEX[0] = indice
        _db = db[indice]
        _db.read(client)
        if INDEX[0] != INDEX[1] or INDEX[
                0] is None:  # verifico si paso de indic para no repetir
            write_csv(_db.export())
            INDEX[1] = INDEX[0]
    except Exception as e:
        logging.error(e)


if __name__ == "__main__":

    client = Client()
    reconect(client)

    db_data = client.db_get(DB)
    marca_data = client.read_area(S7AreaMK, 0, 0, LONGITUD_MARCAS)

    db = DB_mixin(DB, db_data, layout, LONGITUD_STRUCT, LONGITUD_ARRAY)
    marca = DB_mixin(0, marca_data, layout_marca, LONGITUD_MARCAS, 1)

    #schedule.every(DELAY).seconds.do(main, client=client, db=db, marca=marca)

    while True:
        try:
            if not client.get_connected():
                reconect(client)
            main(client=client, db=db)
Example #19
0
 def __init__(self, camera_number, config_file='config.yml') -> None:
     self.load_config(config_file)
     self.camera_number = camera_number
     self.client = Client()
Example #20
0
 def client(self) -> Client:
     plc: Client = Client()
     plc.connect(self.ip, self.rack, self.slot, self.port)
     return plc
Example #21
0
except ImportError:
    import code

    def embed():
        vars = globals()
        vars.update(locals())
        shell = code.InteractiveConsole(vars)
        shell.interact()

opc_url = "opc.tcp://localhost:4840/elevator/pid/"
opc_client = Client( opc_url )
opc_uri = "http://thaintersect.com"
updateThread =  True

global plc
plc = SnapClient()

def updates():
    while True:
        # Set Speed Value on OPC Server
        lspd.set_value(get_real( plc.read_area(areas['MK'], 0, 40, 4), 0)) # MD4
        direction = get_bool( plc.read_area( areas['MK'], 0, 20,1 ),0,1 ) # M20.1
        goingup.set_value(direction) 
        # if direction:
        #     lspd.set_value(aspd.get_value() )
        # else:
        #     lspd.set_value( -aspd.get_value() )
            

        
        # Set Distance variable in the PLC
Example #22
0
from snap7.client import Client
import struct

plc = Client()
plc.connect('192.168.14.100', 0, 1)
data = plc.db_read('16', )
Example #23
0
 def __init__(self, ipaddr, name=None):
     self.ipaddr = ipaddress.IPv4Address(ipaddr)
     self.name = name
     self._port = 102
     self._client = Client()
     self.SmartTags = SmartTags(self)