<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def _recv_mbus(self):
 """Receive a modbus frame :returns: modbus frame body or None if error :rtype: str (Python2) or class bytes (Python3) or None """

        # receive
        # modbus TCP receive
        if self.__mode == const.MODBUS_TCP:
            # 7 bytes header (mbap)
            rx_buffer = self._recv_all(7)
            # check recv
            if not (rx_buffer and len(rx_buffer) == 7):
                self.__last_error = const.MB_RECV_ERR
                self.__debug_msg('_recv MBAP error')
                self.close()
                return None
            rx_frame = rx_buffer
            # decode header
            (rx_hd_tr_id, rx_hd_pr_id,
             rx_hd_length, rx_hd_unit_id) = struct.unpack('>HHHB', rx_frame)
            # check header
            if not ((rx_hd_tr_id == self.__hd_tr_id) and
                    (rx_hd_pr_id == 0) and
                    (rx_hd_length < 256) and
                    (rx_hd_unit_id == self.__unit_id)):
                self.__last_error = const.MB_RECV_ERR
                self.__debug_msg('MBAP format error')
                if self.__debug:
                    rx_frame += self._recv_all(rx_hd_length - 1)
                    self._pretty_dump('Rx', rx_frame)
                self.close()
                return None
            # end of frame
            rx_buffer = self._recv_all(rx_hd_length - 1)
            if not (rx_buffer and
                    (len(rx_buffer) == rx_hd_length - 1) and
                    (len(rx_buffer) >= 2)):
                self.__last_error = const.MB_RECV_ERR
                self.__debug_msg('_recv frame body error')
                self.close()
                return None
            rx_frame += rx_buffer
            # dump frame
            if self.__debug:
                self._pretty_dump('Rx', rx_frame)
            # body decode
            rx_bd_fc = struct.unpack('B', rx_buffer[0:1])[0]
            f_body = rx_buffer[1:]
        # modbus RTU receive
        elif self.__mode == const.MODBUS_RTU:
            # receive modbus RTU frame (max size is 256 bytes)
            rx_buffer = self._recv(256)
            # on _recv error
            if not rx_buffer:
                return None
            rx_frame = rx_buffer
            # dump frame
            if self.__debug:
                self._pretty_dump('Rx', rx_frame)
            # RTU frame min size is 5 bytes
            if len(rx_buffer) < 5:
                self.__last_error = const.MB_RECV_ERR
                self.__debug_msg('short frame error')
                self.close()
                return None
            # check CRC
            if not self._crc_is_ok(rx_frame):
                self.__last_error = const.MB_CRC_ERR
                self.__debug_msg('CRC error')
                self.close()
                return None
            # body decode
            (rx_unit_id, rx_bd_fc) = struct.unpack("BB", rx_frame[:2])
            # check
            if not (rx_unit_id == self.__unit_id):
                self.__last_error = const.MB_RECV_ERR
                self.__debug_msg('unit ID mismatch error')
                self.close()
                return None
            # format f_body: remove unit ID, function code and CRC 2 last bytes
            f_body = rx_frame[2:-2]
        # for auto_close mode, close socket after each request
        if self.__auto_close:
            self.close()
        # check except
        if rx_bd_fc > 0x80:
            # except code
            exp_code = struct.unpack('B', f_body[0:1])[0]
            self.__last_error = const.MB_EXCEPT_ERR
            self.__last_except = exp_code
            self.__debug_msg('except (code ' + str(exp_code) + ')')
            return None
        else:
            # return
            return f_body