Esempio n. 1
0
    def hpai_body(self):
        """ Create a body with HPAI information.

        This is used for disconnect and connection state requests.
        """
        body = []
        # ============ IP Body ==========
        body.extend([self.channel])  # Communication Channel Id
        body.extend([0x00])  # Reserverd
        # =========== Client HPAI ===========
        body.extend([0x08])  # HPAI Length
        body.extend([0x01])  # Host Protocol
        # Tunnel Client Socket IP
        body.extend(ip_to_array(self.control_socket.getsockname()[0]))
        # Tunnel Client Socket Port
        body.extend(int_to_array(self.control_socket.getsockname()[1]))

        return body
Esempio n. 2
0
File: ip.py Progetto: daBONDi/pknx
    def hpai_body(self):
        """ Create a body with HPAI information.

        This is used for disconnect and connection state requests.
        """
        body = []
        # ============ IP Body ==========
        body.extend([self.channel])  # Communication Channel Id
        body.extend([0x00])  # Reserverd
        # =========== Client HPAI ===========
        body.extend([0x08])  # HPAI Length
        body.extend([0x01])  # Host Protocol
        # Tunnel Client Socket IP
        body.extend(ip_to_array(self.control_socket.getsockname()[0]))
        # Tunnel Client Socket Port
        body.extend(int_to_array(self.control_socket.getsockname()[1]))

        return body
Esempio n. 3
0
        def _build_search_request_data(requestor_ipaddress, requestor_port):
            """
            Build a KNX IP Search Request Broadcast Package

            :param requestor_ipaddress: IP Address of the Search Request
                Response Receiver
            :param requestor_port: Port of the Search Request Response Receiver
            :return: Complete Search Request Broadcast Package
            :rtype: bytes
            """
            req = []
            req.extend([0x06])  # HeaderSize
            req.extend([0x10])  # KNXNetIP Version
            req.extend([0x02, 0x01])  # Search Reques°t
            req.extend([0x00, 0x0E])  # HEADER_SIZE_10 + sizeof(HPAI)
            # ==== Discovery Endpoint HPAI ====
            req.extend([0x08])  # Struct Length
            req.extend([0x01])  # Host Protocol Code = 0x01 = IPV4_UDP
            req.extend(ip_to_array(requestor_ipaddress))
            req.extend(int_to_array(requestor_port))
            return bytes(req)
Esempio n. 4
0
        def _build_search_request_data(requestor_ipaddress, requestor_port):
            """
            Build a KNX IP Search Request Broadcast Package

            :param requestor_ipaddress: IP Address of the Search Request
                Response Receiver
            :param requestor_port: Port of the Search Request Response Receiver
            :return: Complete Search Request Broadcast Package
            :rtype: bytes
            """
            req = []
            req.extend([0x06])  # HeaderSize
            req.extend([0x10])  # KNXNetIP Version
            req.extend([0x02, 0x01])  # Search Reques°t
            req.extend([0x00, 0x0E])  # HEADER_SIZE_10 + sizeof(HPAI)
            # ==== Discovery Endpoint HPAI ====
            req.extend([0x08])  # Struct Length
            req.extend([0x01])  # Host Protocol Code = 0x01 = IPV4_UDP
            req.extend(ip_to_array(requestor_ipaddress))
            req.extend(int_to_array(requestor_port))
            return bytes(req)
Esempio n. 5
0
    def connect(self, timeout=2):
        """Connect to the KNX/IP tunnelling interface.

        If the remote address is "0.0.0.0", it will use the Gateway scanner
        to automatically detect a KNX gateway and it will connect to it if one
        has been found.

        Returns true if a connection could be established, false otherwise
        """

        if self.connected:
            logging.info("KNXIPTunnel connect request ignored, "
                         "already connected")
            return True

        if self.remote_ip == "0.0.0.0":
            scanner = GatewayScanner()
            try:
                ipaddr, port = scanner.start_search()
                logging.info("Found KNX gateway %s/%s", ipaddr, port)
                self.remote_ip = ipaddr
                self.remote_port = port
            except TypeError:
                logging.error("No KNX/IP gateway given and no gateway "
                              "found by scanner, aborting %s")

        # Clean up cache
        self.value_cache.clear()

        # Find my own IP
        sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        sock.connect((self.remote_ip, self.remote_port))
        local_ip = sock.getsockname()[0]

        if self.data_server:
            logging.info("Data server already running, not starting again")
        else:
            self.data_server = DataServer((local_ip, 0), DataRequestHandler,
                                          self)
            dummy_ip, self.data_port = self.data_server.server_address
            data_server_thread = threading.Thread(
                target=self.data_server.serve_forever)
            data_server_thread.daemon = True
            data_server_thread.start()
            logging.debug("Started data server on UDP port %s", self.data_port)

        self.control_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        self.control_socket.bind((local_ip, 0))
        self.control_socket.settimeout(timeout)

        # Connect packet
        frame = KNXIPFrame(KNXIPFrame.CONNECT_REQUEST)

        # Control endpoint
        body = []
        body.extend([0x08, 0x01])  # length 8 bytes, UPD
        dummy_ip, port = self.control_socket.getsockname()
        body.extend(ip_to_array(local_ip))
        body.extend(int_to_array(port, 2))

        # Data endpoint
        body.extend([0x08, 0x01])  # length 8 bytes, UPD
        body.extend(ip_to_array(local_ip))
        body.extend(int_to_array(self.data_port, 2))

        #
        body.extend([0x04, 0x04, 0x02, 0x00])
        frame.body = body

        try:
            self.control_socket.sendto(bytes(frame.to_frame()),
                                       (self.remote_ip, self.remote_port))
            received = self.control_socket.recv(1024)
        except socket.error:
            self.control_socket.close()
            self.control_socket = None
            logging.error("KNX/IP gateway did not respond to connect request")
            return False

        # Check if the response is an TUNNELING ACK
        r_sid = received[2] * 256 + received[3]

        if r_sid == KNXIPFrame.CONNECT_RESPONSE:
            self.channel = received[6]
            status = received[7]
            if status == 0:
                hpai = received[8:10]
                logging.debug("Connected KNX IP tunnel " +
                              "(Channel: {}, HPAI: {} {})".format(
                                  self.channel, hpai[0], hpai[1]))
            else:
                logging.error(
                    "KNX IP tunnel connect error:" +
                    "(Channel: {}, Status: {})".format(self.channel, status))
                return False

        else:
            logging.error("Could not initiate tunnel connection, STI = {0:%s}",
                          r_sid)
            return False

        self.connected = True

        return True
Esempio n. 6
0
File: ip.py Progetto: daBONDi/pknx
    def connect(self, timeout=2):
        """Connect to the KNX/IP tunnelling interface.

        If the remote address is "0.0.0.0", it will use the Gateway scanner
        to automatically detect a KNX gateway and it will connect to it if one
        has been found.

        Returns true if a connection could be established, false otherwise
        """

        if self.connected:
            logging.info("KNXIPTunnel connect request ignored, "
                         "already connected")
            return True

        if self.remote_ip == "0.0.0.0":
            scanner = GatewayScanner()
            try:
                ipaddr, port = scanner.start_search()
                logging.info("Found KNX gateway %s/%s", ipaddr, port)
                self.remote_ip = ipaddr
                self.remote_port = port
            except TypeError:
                logging.error("No KNX/IP gateway given and no gateway "
                              "found by scanner, aborting %s")

        # Clean up cache
        self.value_cache.clear()

        # Find my own IP
        sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        sock.connect((self.remote_ip, self.remote_port))
        local_ip = sock.getsockname()[0]

        if self.data_server:
            logging.info("Data server already running, not starting again")
        else:
            self.data_server = DataServer((local_ip, 0),
                                          DataRequestHandler,
                                          self)
            dummy_ip, self.data_port = self.data_server.server_address
            data_server_thread = threading.Thread(
                target=self.data_server.serve_forever)
            data_server_thread.daemon = True
            data_server_thread.start()
            logging.debug(
                "Started data server on UDP port %s", self.data_port)

        self.control_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        self.control_socket.bind((local_ip, 0))
        self.control_socket.settimeout(timeout)

        # Connect packet
        frame = KNXIPFrame(KNXIPFrame.CONNECT_REQUEST)

        # Control endpoint
        body = []
        body.extend([0x08, 0x01])  # length 8 bytes, UPD
        dummy_ip, port = self.control_socket.getsockname()
        body.extend(ip_to_array(local_ip))
        body.extend(int_to_array(port, 2))

        # Data endpoint
        body.extend([0x08, 0x01])  # length 8 bytes, UPD
        body.extend(ip_to_array(local_ip))
        body.extend(int_to_array(self.data_port, 2))

        #
        body.extend([0x04, 0x04, 0x02, 0x00])
        frame.body = body

        try:
            self.control_socket.sendto(bytes(frame.to_frame()),
                                       (self.remote_ip, self.remote_port))
            received = self.control_socket.recv(1024)
        except socket.error:
            self.control_socket = None
            logging.error("KNX/IP gateway did not respond to connect request")
            return False

        # Check if the response is an TUNNELING ACK
        r_sid = received[2] * 256 + received[3]

        if r_sid == KNXIPFrame.CONNECT_RESPONSE:
            self.channel = received[6]
            status = received[7]
            if status == 0:
                hpai = received[8:10]
                logging.debug("Connected KNX IP tunnel " +
                              "(Channel: {}, HPAI: {} {})".format(
                                  self.channel, hpai[0], hpai[1]))
            else:
                logging.error("KNX IP tunnel connect error:" +
                              "(Channel: {}, Status: {})".format(
                                  self.channel, status))
                return False

        else:
            logging.error(
                "Could not initiate tunnel connection, STI = {0:%s}", r_sid)
            return False

        self.connected = True

        return True