Example #1
0
 def _get_request_length(self, mbap):
     """Parse the mbap and returns the number of bytes to be read"""
     if len(mbap) < 6:
         raise ModbusInvalidRequestError("The mbap is only %d bytes long",
                                         len(mbap))
     length = struct.unpack(">HHH", mbap[:6])[2]
     return length
Example #2
0
 def parse_request(self, request):
     """Extract the pdu from a modbus request"""
     if len(request) > 6:
         mbap, pdu = request[:7], request[7:]
         self._request_mbap.unpack(mbap)
         error_str = self._request_mbap.check_length(len(pdu))
         if len(error_str) > 0:
             raise ModbusInvalidMbapError(error_str)
         return self._request_mbap.unit_id, pdu
     else:
         raise ModbusInvalidRequestError("Request length is only {0} bytes. ".format(len(request)))
Example #3
0
    def handle_request(self, request_pdu, broadcast=False):
        """
        parse the request pdu, makes the corresponding action
        and returns the response pdu
        """

        logger.debug("Slave (ID: %d) is handling request" % self._id)

        with self._data_lock:  # thread-safe
            try:
                # get the function code
                (self.function_code, ) = struct.unpack(">B", request_pdu[:1])

                # check if the function code is valid. If not returns error response
                if not self.function_code in self._fn_code_map:
                    raise ModbusError(defines.ILLEGAL_FUNCTION)

                can_broadcast = [
                    defines.WRITE_MULTIPLE_COILS,
                    defines.WRITE_MULTIPLE_REGISTERS,
                    defines.WRITE_SINGLE_COIL,
                    defines.WRITE_SINGLE_REGISTER,
                ]
                if broadcast and (self.function_code not in can_broadcast):
                    raise ModbusInvalidRequestError(
                        "Function %d can not be broadcasted" %
                        self.function_code)

                # execute the corresponding function
                try:
                    response_pdu = self._fn_code_map[self.function_code](
                        request_pdu)
                except struct.error:
                    raise ModbusError(exception_code=3)
                if response_pdu:
                    if broadcast:
                        # not really sure whats going on here - better log it!
                        logger.info("Modbus broadcast: %s" %
                                    (utils.get_log_buffer("!!", response_pdu)))
                        return ""
                    else:
                        return struct.pack(">B",
                                           self.function_code) + response_pdu
                raise Exception("No response for function %d" %
                                self.function_code)

            except ModbusError as e:
                logger.error(
                    "Exception caught: %s. (A proper response will be sent to the peer)",
                    e,
                )
                return struct.pack(">BB", self.function_code + 128,
                                   e.get_exception_code())
Example #4
0
    def handle_request(self, request_pdu, broadcast=False):
        """
        parse the request pdu, makes the corresponding action
        and returns the response pdu
        """
        with self._data_lock:  # thread-safe
            try:
                # get the function code
                (self.function_code, ) = struct.unpack(">B", request_pdu[0])

                # check if the function code is valid. If not returns error response
                if not self.function_code in self._fn_code_map:
                    raise ModbusError(defines.ILLEGAL_FUNCTION)

                # if read query is broadcasted raises an error
                cant_be_broadcasted = (defines.READ_COILS,
                                       defines.READ_DISCRETE_INPUTS,
                                       defines.READ_INPUT_REGISTERS,
                                       defines.READ_HOLDING_REGISTERS)
                if broadcast and (self.function_code in cant_be_broadcasted):
                    raise ModbusInvalidRequestError(
                        "Function %d can not be broadcasted" %
                        self.function_code)

                # execute the corresponding function
                response_pdu = self._fn_code_map[self.function_code](
                    request_pdu)
                if response_pdu:
                    if broadcast:
                        #not really sure whats going on here - better log it!
                        logger.info("broadcast: %s" %
                                    (utils.get_log_buffer("!!", response_pdu)))
                        return ""
                    else:
                        return struct.pack(">B",
                                           self.function_code) + response_pdu
                raise Exception("No response for function %d" %
                                self.function_code)

            except ModbusError as e:
                logger.error(
                    'Exception caught: {0}. (A proper response will be sent to the peer)'
                    .format(e))
                return struct.pack(">BB", self.function_code + 128,
                                   e.get_exception_code())