# Algoritmo de trabajo del marco de Python

El script del marco de Python que se ejecuta mediante el Programador de Windows debe seguir el siguiente algoritmo:

1. Realizar una solicitud HTTP POST al script `/api/robot/heartbeat` del Orquestador. Pasar como parámetros:
   1. GUID de este Robot (RobotGUID),
   2. nombre de la computadora (Machine),
   3. dirección IP de la máquina (IP),
   4. dirección MAC de la máquina (MAC),
   5. estado actual del Robot (Status),
   6. GUID del Trabajo que se está ejecutando actualmente (JobGUID),
   7. nombre del Trabajo que se está ejecutando actualmente (JobName),
   8. tipo de Trabajo (JobType, siempre debe tener el tipo Orchestrated, valor 1).

Los datos de salida (en formato JSON):

* HeartbeatErrorCode,
* ErrorText,
* HasNewJob.

El script puede devolver en la respuesta otros parámetros que no se utilizan en el contexto de la Tarea actual.

Referencia de estados de los Robots:

```
Status_Disconnected = 0; # robot desconectado
Status_Unlicensed     = 1; # robot no licenciado
Status_Ready        = 2; # robot no está realizando trabajos y está listo para recibir nuevos trabajos
Status_Working    = 3; # robot está realizando el trabajo actual
```

Referencia de valores de ErrorCode:

```
HeartbeatErrorCode_NoError = 0;  # sin errores
HeartbeatErrorCode_RobotNotFound = 101;  # robot con el GUID especificado no encontrado
HeartbeatErrorCode_JobAborting = 10;   # el orquestador solicitó una detención forzada de este script (Abort)
HeartbeatErrorCode_JobStopping = 20;   # el orquestador solicitó una detención suave de este script (Stop)
```

Referencia de valores de HasNewJob:

```
HasNewJob_NoJob = 0 # no hay nuevos trabajos para este robot
HasNewJob_JobFound = 1 # hay nuevos trabajos para este robot que deben ser obtenidos mediante la llamada ConsumeNextJob
```

En la primera ejecución del script, se debe pasar el valor `Status = 2` (Status\_Ready). También en la primera ejecución, cuando el nombre y el GUID del trabajo que se está ejecutando aún son desconocidos, estos campos pueden permanecer vacíos.

Ejemplo de llamada:

```
import requests
import base64
import json

from requests.packages.urllib3.exceptions import InsecureRequestWarning
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
host = 'http://192.168.1.111:4500' #host del orquestador
robot_guid = 'da8bc2f0-8065-4385-b867-405e66b8e151' #GUID del robot
headers = {
    'Authorization': 'Basic ' + base64.b64encode(robot_guid.encode('utf-8')).decode('utf-8')
}
req = {
    'RobotGUID': robot_guid,   #GUID del robot
    'Machine': robot_machine,   #Nombre de la máquina
    'IP': robot_ip,   #Dirección IP del robot
    'MAC': robot_mac,   #Dirección MAC del robot
    'Status': 2,   #estado del robot
    'JobGUID': '',  #GUID del trabajo
    'JobName': '',   #nombre del script que se está ejecutando, es decir, python_script_name a continuación
    'JobType': 1   #tipo de trabajo, siempre valor 1
}
r = requests.post(host + '/api/robot/heartbeat', data=req, headers=headers, verify=False)
heartbeat_results = json.loads(r.text)
print(heartbeat_results ['HeartbeatErrorCode'])
print(heartbeat_results ['ErrorText'])
print(heartbeat_results ['HasNewJob'])
```

2. En caso de recibir la respuesta `HasNewJob == 0`, finalizar la ejecución del script del marco y cerrar la sesión de Windows mediante Log off.\
   \
   En caso de recibir la respuesta `HasNewJob == 1`, realizar una solicitud HTTP POST al script `/api/robot/consumeNextJob` del Orquestador.\
   \
   Datos de entrada:

   1. GUID del Robot (RobotGUID),
   2. estado actual del Robot (Status).

   \
   Datos de salida (en formato JSON):

   1. ConsumeJobErrorCode,
   2. ErrorText,
   3. Job,
   4. ProcessVersion,
   5. Task.

   Referencia de valores de ConsumeJobErrorCode:\
   \
   `ConsumeJobErrorCode = 0; # sin errores`\
   `ConsumeJobErrorCode = 101; # robot con el GUID especificado no encontrado`\
   `ConsumeJobErrorCode = 102; # nuevo trabajo no encontrado`\
   \
   Ejemplo de llamada:\
   \
   `import requests`\
   `import base64`\
   `import json`\
   \
   `from requests.packages.urllib3.exceptions import InsecureRequestWarning`\
   `requests.packages.urllib3.disable_warnings(InsecureRequestWarning)`\
   \
   `host = 'http://192.168.1.111:4500' #host del orquestador`\
   `robot_guid = 'da8bc2f0-8065-4385-b867-405e66b8e151' #GUID del robot`\
   \
   `headers = {`\
   `'Authorization': 'Basic ' + base64.b64encode(robot_guid.encode('utf-8')).decode('utf-8')`\
   `}`\
   \
   `cnj = {`\
   `'RobotGUID': robot_guid #GUID del robot`\
   `}`\
   \
   `r = requests.post(host + '/api/robot/consumeNextJob', data=cnj, headers=headers, verify=False)`\
   `consume_result = json.loads(r.text)`\
   `print(consume_result['ConsumeJobErrorCode'])`\
   `print(consume_result['ErrorText'])`\
   `new_job = json.loads(consume_result['Job'])`\
   `job_guid = new_job['GUID']`\
   `process_version = json.loads(consume_result['ProcessVersion'])`\
   `python_script_name = process_version['Name'] #Convenimos que el nombre del script del robot que debe ejecutarse se pasa en el nombre de la versión del proceso`\
   `task = json.loads(consume_result[' Task '])`<br>
3. En caso de recibir exitosamente un nuevo Trabajo del Orquestador, realizar una solicitud HTTP PUT al script `/api/job/update` del Orquestador. Pasar como parámetros el GUID del Trabajo recibido (guid) y el nuevo estado del Trabajo `Status_In_Progress`.\
   \
   Referencia de valores de estados de los Trabajos:\
   \
   `Status_Created = 0; #Trabajo creado`\
   `Status_Pending = 1; #Trabajo pendiente, esperando que el robot lo tome`\
   `Status_Aborting = 2; #Trabajo en proceso de detención forzada (interrupción)`\
   `Status_Aborted = 3; #Trabajo interrumpido exitosamente`\
   `Status_Success = 4; #Trabajo completado exitosamente`\
   `Status_Failed = 5; #Trabajo no completado exitosamente`\
   `Status_Stopping = 6; #Trabajo en proceso de detención suave`\
   `Status_Stopped = 7; #Trabajo detenido exitosamente tras la solicitud de detención suave`\
   `Status_In_Progress = 8; #Trabajo en ejecución`\
   \
   Ejemplo de llamada:\
   \
   `import requests`\
   `import base64`\
   `import json`\
   \
   `from requests.packages.urllib3.exceptions import InsecureRequestWarning`\
   `requests.packages.urllib3.disable_warnings(InsecureRequestWarning)`\
   `host = 'http://192.168.1.111:4500' #host del orquestador`\
   `robot_guid = 'da8bc2f0-8065-4385-b867-405e66b8e151' #GUID del robot`\
   \
   `headers = {`\
   `'Authorization': 'Basic ' + base64.b64encode(robot_guid.encode('utf-8')).decode('utf-8')`\
   `}`\
   \
   `job = {`\
   `'guid': job_guid, #GUID del trabajo actual`\
   `'status': 8 #nuevo estado del trabajo`\
   `}`\
   \
   `r = requests.put(host + '/api/job/update', data=job, headers=headers, verify=False)`\
   `print(r.text)`<br>
4. Proceder a ejecutar el script de Python del Robot con el nombre igual a `python_script_name`. Siempre que sea posible, repetir periódicamente las solicitudes al script `/api/robot/heartbeat` con el valor correcto de `JobGUID` y `Status = 3 (Status_Working)`.\
   \
   Se recomienda enviar esta solicitud no más de una vez cada 10 segundos. En caso de recibir en respuesta el estado `HeartbeatErrorCode == 10`, se debe interrumpir inmediatamente la ejecución del script de Python del Robot.\
   \
   En caso de recibir en respuesta el estado `HeartbeatErrorCode == 20`, se debe realizar una finalización correcta del script de Python del Robot.
5. Después de finalizar el script de Python del Robot, realizar una solicitud HTTP PUT al script `/api/job/update` del Orquestador. Pasar como parámetros el GUID del Trabajo actual del Robot (guid) y el nuevo estado del Trabajo según el resultado de su finalización de acuerdo con la referencia proporcionada anteriormente.
6. Luego, realizar una solicitud HTTP POST al script `/api/robot/heartbeat` del Orquestador con el estado `Status = 2 (Status_Ready)` y proceder al paso 2 del algoritmo del marco.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.sherparpa.ru/es/sherpa-rpa/sherpa-orchestrator/python-sherpa-framework/algoritm-raboty-python-freimvorka.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
