Exemplo n.º 1
0
    def request_work(self,
                     onlynewwho: bool = False,
                     throttle: bool = False) -> None:
        """Request work from order manager."""
        # Allow requesting work only once every 10 seconds when throttling
        if self._requested_work_time and throttle is True:
            time_elapsed = time.time() - self._requested_work_time
            if time_elapsed < 10:
                return

        self._requested_work_time = time.time()

        if onlynewwho:
            request = RequestFromRobot(self.lgnum,
                                       self.rsrc,
                                       requestnewwho=True)
        else:
            request = RequestFromRobot(self.lgnum, self.rsrc, requestwork=True)

        _LOGGER.info('Requesting work from order manager')

        dtype = create_robcoewmtype_str(request)
        success = self.send_robot_request(dtype, unstructure(request))

        if success is True:
            _LOGGER.info('Requested work from order manager')
        else:
            _LOGGER.error(
                'Error requesting work from order manager. Try again')
            raise ConnectionError
Exemplo n.º 2
0
 def check_robotrequest_processed(self, requestident: str,
                                  robotrequest: RequestFromRobot) -> bool:
     """Check if robotrequest was processed before."""
     processed_request = self.robotrequests.get(
         requestident,
         RequestFromRobot(robotrequest.lgnum, robotrequest.rsrc))
     return bool(robotrequest != processed_request)
Exemplo n.º 3
0
    def notify_who_completion(self, who: str) -> None:
        """
        Send a  warehouse order completion request to EWM Order Manager.

        It notifies the robot when the warehouse order was completed.
        """
        request = RequestFromRobot(self.lgnum,
                                   self.rsrc,
                                   notifywhocompletion=who)

        _LOGGER.info(
            'Requesting warehouse order completion notification for %s from order manager',
            who)

        dtype = create_robcoewmtype_str(request)
        success = self.send_robot_request(dtype, unstructure(request))

        if success is True:
            _LOGGER.info(
                'Requested warehouse order completion notification from order manager'
            )
        else:
            _LOGGER.error(
                'Error requesting warehouse order completion notification from order manager. '
                'Try again')
            raise ConnectionError
import sys
import traceback
import logging

from typing import Dict

from robcoewmtypes.helper import create_robcoewmtype_str, get_sample_cr
from robcoewmtypes.robot import RequestFromRobot, RequestFromRobotStatus

from robcoewminterface.exceptions import NoOrderFoundError, RobotHasOrderError

from k8scrhandler.k8scrhandler import K8sCRHandler, k8s_cr_callback

_LOGGER = logging.getLogger(__name__)

ROBOTREQUEST_TYPE = create_robcoewmtype_str(RequestFromRobot('lgnum', 'rsrc'))


class RobotRequestController(K8sCRHandler):
    """Handle K8s custom resources."""
    def __init__(self) -> None:
        """Constructor."""
        template_cr = get_sample_cr('robotrequest')

        labels = {}
        super().__init__('sap.com', 'v1', 'robotrequests', 'default',
                         template_cr, labels)

    @k8s_cr_callback
    def _callback(self, name: str, labels: Dict, operation: str,
                  custom_res: Dict) -> None:
Exemplo n.º 5
0
    def robotrequest_callback(self, dtype: str, name: str, data: Dict,
                              statusdata: Dict) -> None:
        """
        Handle robotrequest messages.

        Used for K8S CR handler.
        """
        cls = self.__class__

        # Structure the request data
        robcoewmdata = self._structure_callback_data(
            dtype, data, cls.ROBOTREQUEST_MSG_TYPES)
        if not robcoewmdata:
            return
        # Get statusdata if available
        if statusdata:
            robcoewmstatusdata = self._structure_callback_data(
                dtype, statusdata, cls.ROBOTREQUEST_MSG_TYPES)
        else:
            robcoewmstatusdata = [
                RequestFromRobot(robcoewmdata[0].lgnum, robcoewmdata[0].rsrc),
            ]

        if len(robcoewmdata) > 1 or len(robcoewmstatusdata) > 1:
            raise ValueError('Robot request must include only one dataset')

        # Process the dataset
        request = robcoewmdata[0]
        status = robcoewmstatusdata[0]

        # Return if request was already processed
        if self.msg_mem.check_robotrequest_processed(name, status):
            _LOGGER.info('Robot request "%s" already processed before - skip',
                         name)
            return

        robotident = RobotIdentifier(request.lgnum, request.rsrc)
        # Determine if it is the first request
        request_no = self.msg_mem.request_count[robotident]
        firstrequest = bool(request_no == 0)
        # Request work, when robot is asking
        if request.requestnewwho and not status.requestnewwho:
            # Get a new warehouse order for the robot
            success = self.get_and_send_robot_whos(robotident,
                                                   firstrequest=firstrequest,
                                                   newwho=True,
                                                   onlynewwho=True)
            if success:
                status.requestnewwho = True
                status.requestwork = request.requestwork
        elif request.requestwork and not status.requestwork:
            # Get existing warehouse orders for the robot. If no exists, get a new warehouse order
            success = self.get_and_send_robot_whos(robotident,
                                                   firstrequest=firstrequest,
                                                   newwho=True,
                                                   onlynewwho=False)
            if success:
                status.requestwork = True

        # Check if warehouse order was completed
        if request.notifywhocompletion and not status.notifywhocompletion:
            try:
                self.ewmwho.get_robot_warehouseorders(robotident.lgnum,
                                                      robotident.rsrc)
            except NoOrderFoundError:
                status.notifywhocompletion = request.notifywhocompletion
                _LOGGER.info(
                    'Warehouse order %s was confirmed, notifying robot "%s"',
                    request.notifywhocompletion, robotident.rsrc)

        # Raise exception if request was not complete
        if request == status:
            self.update_robotrequest_status(name,
                                            create_robcoewmtype_str(status),
                                            unstructure(status),
                                            process_complete=True)
            self.msg_mem.memorize_robotrequest(name, status)
            self.msg_mem.delete_robotrequest_from_memory(name, status)
        else:
            self.update_robotrequest_status(name,
                                            create_robcoewmtype_str(status),
                                            unstructure(status),
                                            process_complete=False)
            self.msg_mem.memorize_robotrequest(name, status)
            if request.notifywhocompletion:
                raise RobotHasOrderError
            else:
                raise NoOrderFoundError
Exemplo n.º 6
0
    def process_robotrequest_cr(self, name: str, custom_res: Dict) -> None:
        """
        Process a robotrequest custom resource.

        Used for K8S CR handler.
        """
        cls = self.__class__

        if custom_res.get(
                'status',
            {}).get('status') == RequestFromRobotStatus.STATE_PROCESSED:
            return

        # Structure the request data
        robcoewmdata = self._structure_callback_data(
            ROBOTREQUEST_TYPE, custom_res['spec'], cls.ROBOTREQUEST_MSG_TYPES)
        if not robcoewmdata:
            return
        # Get statusdata if available
        if custom_res.get('status', {}).get('data'):
            robcoewmstatusdata = self._structure_callback_data(
                ROBOTREQUEST_TYPE, custom_res['status']['data'],
                cls.ROBOTREQUEST_MSG_TYPES)
        else:
            robcoewmstatusdata = [
                RequestFromRobot(robcoewmdata[0].lgnum, robcoewmdata[0].rsrc),
            ]

        if len(robcoewmdata) > 1 or len(robcoewmstatusdata) > 1:
            raise ValueError('Robot request must include only one dataset')

        # Process the dataset
        request = robcoewmdata[0]
        status = robcoewmstatusdata[0]

        # Return if request was already processed
        if self.msg_mem.check_robotrequest_processed(name, status):
            _LOGGER.info('Robot request "%s" already processed before - skip',
                         name)
            return

        robotident = RobotIdentifier(request.lgnum, request.rsrc)
        # Determine if it is the first request
        self.msg_mem.request_count[name] += 1
        firstrequest = bool(self.msg_mem.request_count[name] == 1)
        # Request work, when robot is asking
        if request.requestnewwho and not status.requestnewwho:
            # Get a new warehouse order for the robot
            success = self.get_and_send_robot_whos(robotident,
                                                   firstrequest=firstrequest,
                                                   newwho=True,
                                                   onlynewwho=True)
            if success:
                status.requestnewwho = True
                status.requestwork = request.requestwork
        elif request.requestwork and not status.requestwork:
            # Get existing warehouse orders for the robot. If no exists, get a new warehouse order
            success = self.get_and_send_robot_whos(robotident,
                                                   firstrequest=firstrequest,
                                                   newwho=True,
                                                   onlynewwho=False)
            if success:
                status.requestwork = True

        # Check if warehouse order was completed
        if request.notifywhocompletion and not status.notifywhocompletion:
            notfound = False
            try:
                who = self.ewmwho.get_warehouseorder(
                    lgnum=robotident.lgnum, who=request.notifywhocompletion)
            except NotFoundError:
                notfound = True
            else:
                if who.status not in ['D', '']:
                    notfound = True
            if notfound:
                status.notifywhocompletion = request.notifywhocompletion
                _LOGGER.info(
                    'Warehouse order %s was confirmed, notifying robot "%s"',
                    request.notifywhocompletion, robotident.rsrc)
                # Warehouse orders are completed in EWM, thus ensure that they are marked PROCESSED
                self.cleanup_who(
                    WhoIdentifier(robotident.lgnum,
                                  request.notifywhocompletion))

        # Check if warehouse task was completed
        if request.notifywhtcompletion and not status.notifywhtcompletion:
            try:
                self.ewmwho.get_openwarehousetask(robotident.lgnum,
                                                  request.notifywhtcompletion)
            except NotFoundError:
                status.notifywhtcompletion = request.notifywhtcompletion
                _LOGGER.info(
                    'Warehouse task %s was confirmed, notifying robot "%s"',
                    request.notifywhtcompletion, robotident.rsrc)

        # Raise exception if request was not complete
        if request == status:
            self.robotrequestcontroller.update_status(
                name,
                create_robcoewmtype_str(status),
                unstructure(status),
                process_complete=True)
            self.msg_mem.memorize_robotrequest(name, status)
            self.msg_mem.delete_robotrequest_from_memory(name, status)
        else:
            self.robotrequestcontroller.update_status(
                name,
                create_robcoewmtype_str(status),
                unstructure(status),
                process_complete=False)
            self.msg_mem.memorize_robotrequest(name, status)
            if request.notifywhocompletion:
                raise RobotHasOrderError
            else:
                raise NoOrderFoundError