API de ProEye-X

Cómo leer y escribir datos de análisis de trabajo de la instancia de su empresa (https://empresa.proeye-x.com) desde sistemas externos como MES, ERP o BI. Todas las llamadas usan JSON-RPC 2.0 y se envían por POST a un único punto: /jsonrpc.

Primeros pasos

Punto de acceso

La dirección es distinta para cada instancia. El nombre de la base de datos es la primera parte de la dirección de su empresa (empresa).

POST https://company.proeye-x.com/jsonrpc

Crear una clave API

Inicie sesión en su instancia → menú de usuario (arriba a la derecha) › Mi perfil (Preferencias) › Seguridad de la cuenta › «Nueva clave API». Use la clave en lugar de la contraseña; solo se muestra una vez. Guárdela solo en programas del servidor, nunca en código del navegador.

Autenticación (obtener uid)

Intercambie su correo de inicio de sesión y la clave API por un número de usuario (uid) y envíe base de datos, uid y clave API en cada llamada.

curl
curl -s https://company.proeye-x.com/jsonrpc \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc": "2.0", "method": "call", "params": {
        "service": "common", "method": "authenticate",
        "args": ["company", "you@company.com", "YOUR_API_KEY", {}]}}'

# → {"jsonrpc": "2.0", "id": null, "result": 7}      (7 = uid)

Función auxiliar en Python

Los ejemplos siguientes usan esta función auxiliar model().

Python
import requests

URL = "https://company.proeye-x.com/jsonrpc"
DB, LOGIN, KEY = "company", "you@company.com", "YOUR_API_KEY"

def call(service, method, *args):
    r = requests.post(URL, json={"jsonrpc": "2.0", "method": "call",
                                 "params": {"service": service, "method": method, "args": args}}, timeout=30)
    r.raise_for_status()
    body = r.json()
    if body.get("error"):
        raise RuntimeError(body["error"]["data"]["message"])
    return body.get("result")          # no "result" key when the method returns nothing

UID = call("common", "authenticate", DB, LOGIN, KEY, {})

def model(name, method, args, kw=None):
    return call("object", "execute_kw", DB, UID, KEY, name, method, args, kw or {})

Idioma

Indique lang en context para recibir los nombres de trabajos y elementos en ese idioma (si hay traducción). Ejemplo: {"context": {"lang": "es_ES"}} · en_US · ja_JP · zh_CN · zh_TW · vi_VN · th_TH · id_ID · de_DE · ko_KR.

Errores

Si falla, recibe HTTP 200 con un objeto "error"; error.data.message indica el motivo (sin permisos, falta un campo obligatorio, …).

Lista de API

element_type es la clave de una casilla de tipo de trabajo (va = casilla 1, nva = casilla 2, wait = casilla 3, casillas propias c4 …). El tiempo VA/NVA se calcula a partir de los intervalos de segment_data.

1. Lista de análisis

Modelo · wa.sessionMétodo · search_read

Devuelve los análisis de trabajo (sesiones) con tiempo de ciclo medio, porcentaje VA y número de elementos.

Python
rows = model("wa.session", "search_read", [[]], {
    "fields": ["o_no", "name", "process_name", "cycle_time_avg", "va_ratio", "element_count"],
    "order": "date desc", "limit": 20,
    "context": {"lang": "en_US"},       # names in English (optional)
})
curl
curl -s https://company.proeye-x.com/jsonrpc -H "Content-Type: application/json" -d '{
  "jsonrpc": "2.0", "method": "call", "params": {"service": "object", "method": "execute_kw",
  "args": ["company", 7, "YOUR_API_KEY", "wa.session", "search_read", [[]],
           {"fields": ["o_no", "name", "cycle_time_avg", "va_ratio"], "limit": 20}]}}'
Respuesta de ejemplo
[{"id": 6, "o_no": "O-ENG-NOVICE-01", "name": "Engine Assembly - Novice",
  "process_name": "Engine Assembly Work", "cycle_time_avg": 165.33, "va_ratio": 63.7, "element_count": 14}]

2. Obtener elementos de trabajo

Modelo · wa.elementMétodo · search_read

Devuelve los elementos de un análisis por ciclo: inicio/fin (s), tiempo estándar, tiempo VA y NVA. cycle_no indica el ciclo al que pertenece el elemento (1, 2, 3 …).

Python
elements = model("wa.element", "search_read",
    [[["session_id", "=", 6], ["cycle_no", "=", 1]]],
    {"fields": ["cycle_no", "sequence", "name", "element_type", "video_start_time", "video_end_time",
                "standard_time", "va_time", "nva_time"], "order": "cycle_no, sequence"})
# every cycle: drop the ["cycle_no", "=", 1] condition — cycle_no tells which cycle each element belongs to
Respuesta de ejemplo
[{"id": 70, "cycle_no": 1, "sequence": 1, "name": "Fetch the tools and prepare.", "element_type": "wait",
  "video_start_time": 189.656, "video_end_time": 198.398, "standard_time": 8.742,
  "va_time": 4.104, "nva_time": 4.638}, ...]

3. Obtener LOSS

Modelo · wa.elementMétodo · search_read (LOSS)

Devuelve lo introducido en la pestaña LOSS. Para cada segmento NVA de un elemento (elementos de segment_data con type = nva), el texto LOSS (loss_data) y el código de tipo de desperdicio (loss_type_data) se guardan como arrays JSON en el mismo orden; emparéjalos como abajo para obtener filas de ciclo · elemento · tiempo del segmento · tipo de desperdicio · texto LOSS.

Python
import json

rows = model("wa.element", "search_read", [[["session_id", "=", session_id]]],
             {"fields": ["cycle_no", "sequence", "name", "segment_data", "loss_data", "loss_type_data"],
              "order": "cycle_no, sequence"})
losses = []
for e in rows:
    nva = [s for s in json.loads(e["segment_data"] or "[]") if s["type"] == "nva"]
    notes = json.loads(e["loss_data"] or "[]")          # LOSS text, one per NVA segment
    types = json.loads(e["loss_type_data"] or "[]")     # waste type code, one per NVA segment
    for i, seg in enumerate(nva):
        losses.append({"cycle_no": e["cycle_no"], "element": e["name"],
                       "start": seg["start"], "end": seg["end"], "dur": seg["dur"],
                       "loss_type": types[i] if i < len(types) else "",
                       "loss": notes[i] if i < len(notes) else ""})
Respuesta de ejemplo
# rows (raw)
[{"id": 207, "cycle_no": 1, "sequence": 1, "name": "Fasten bolt",
  "segment_data": "[{\"type\": \"va\", \"start\": 4.2, \"end\": 7.0, \"dur\": 2.8}, {\"type\": \"nva\", \"start\": 7.0, ...}]",
  "loss_data": "[\"Searching for the wrench\", \"Waiting for the jig\"]",
  "loss_type_data": "[\"w6\", \"w2\"]"}]

# losses
[{"cycle_no": 1, "element": "Fasten bolt", "start": 7.0, "end": 9.1, "dur": 2.1, "loss_type": "w6", "loss": "Searching for the wrench"},
 {"cycle_no": 1, "element": "Fasten bolt", "start": 11.0, "end": 12.6, "dur": 1.6, "loss_type": "w2", "loss": "Waiting for the jig"}]

# loss_type: w1 overproduction · w2 waiting · w3 transport · w4 over-processing · w5 inventory · w6 motion · w7 defects

4. Crear un análisis

Modelo · wa.sessionMétodo · create

Crea un nuevo análisis de trabajo. O-No (número único) es obligatorio y no puede repetirse. Devuelve el nuevo ID.

Python
session_id = model("wa.session", "create", [{
    "o_no": "O-2026-LINE3-01",          # required, unique
    "name": "Line 3 sub-assembly",
    "process_name": "Sub-assembly",
}])
Respuesta de ejemplo
21

5. Añadir elementos de trabajo

Modelo · wa.elementMétodo · create

Añade varios elementos a la vez por rango de tiempo del vídeo. Los totales como el tiempo de ciclo y el porcentaje VA se recalculan automáticamente.

Python
ids = model("wa.element", "create", [[
    {"session_id": session_id, "cycle_no": 1, "sequence": 1, "name": "Pick part",
     "element_type": "va", "video_start_time": 0.0, "video_end_time": 4.2},
    {"session_id": session_id, "cycle_no": 1, "sequence": 2, "name": "Fasten bolt",
     "element_type": "va", "video_start_time": 4.2, "video_end_time": 9.8},
]])
summary = model("wa.session", "read", [[session_id]],
                {"fields": ["element_count", "cycle_time_avg", "va_ratio"]})
Respuesta de ejemplo
[205, 206]
[{"id": 18, "element_count": 2, "cycle_time_avg": 9.8, "va_ratio": 100.0}]

6. Modificar / eliminar un elemento

Modelo · wa.elementMétodo · write / unlink

Cambie nombre, tiempos o tipo de trabajo (write) o elimínelo (unlink).

Python
model("wa.element", "write", [[205], {"name": "Pick and place", "video_end_time": 4.6}])
model("wa.element", "unlink", [[206]])
Respuesta de ejemplo
true
true

7. Escribir LOSS

Modelo · wa.elementMétodo · write (LOSS)

Escribe el texto LOSS y el código de desperdicio de cada segmento NVA como arrays JSON en orden de tiempo. El n-ésimo valor corresponde al n-ésimo segmento NVA. Códigos: w1 sobreproducción · w2 espera · w3 transporte · w4 sobreprocesamiento · w5 inventario · w6 movimiento · w7 defectos.

Python
import json

# element with NVA segments 7.0–9.1 s and 11.0–12.6 s → one entry per NVA segment, in time order
model("wa.element", "write", [[207], {
    "loss_data": json.dumps(["Searching for the wrench", "Waiting for the jig"]),
    "loss_type_data": json.dumps(["w6", "w2"]),
}])
Respuesta de ejemplo
true

8. Obtener ciclos

Modelo · wa.cycleMétodo · search_read

Devuelve los ciclos medidos con inicio, fin y tiempo de ciclo.

Python
cycles = model("wa.cycle", "search_read", [[["session_id", "=", 4]]],
               {"fields": ["sequence", "video_start", "video_end", "cycle_time"], "order": "sequence"})
Respuesta de ejemplo
[{"id": 4, "sequence": 1, "video_start": 0.767, "video_end": 17.15, "cycle_time": 16.383}, ...]

9. Comparación (antes / después)

Modelo · wa.comparisonMétodo · create · action_build_lines · read

Une dos análisis en una comparación, genera las líneas y devuelve la reducción del tiempo de ciclo, la mejora VA y las diferencias por elemento.

Python
cid = model("wa.comparison", "create", [{
    "name": "Line 1 before / after", "session_a_id": 7, "session_b_id": 11}])
model("wa.comparison", "action_build_lines", [[cid]])
result = model("wa.comparison", "read", [[cid]],
               {"fields": ["ct_a", "ct_b", "ct_reduction", "ct_reduction_pct", "va_improvement"]})
lines = model("wa.comparison.line", "search_read", [[["comparison_id", "=", cid]]],
              {"fields": ["sequence", "step_name", "time_a", "time_b", "time_diff"], "order": "sequence"})
Respuesta de ejemplo
[{"id": 3, "ct_a": 22.72, "ct_b": 23.39, "ct_reduction": -0.67, "ct_reduction_pct": -2.9, "va_improvement": -6.4}]
[{"id": 49, "sequence": 1, "step_name": "UP", "time_a": 2.85, "time_b": 2.723, "time_diff": -0.127}, ...]

10. Balanceo de línea

Modelo · wa.linebalance · wa.lb.processMétodo · search_read

Devuelve takt time, eficiencia de línea, el proceso cuello de botella y el tiempo de ciclo y carga de cada proceso.

Python
lines = model("wa.linebalance", "search_read", [[]],
              {"fields": ["name", "takt_time", "lb_efficiency", "bottleneck_name", "max_ct"]})
processes = model("wa.lb.process", "search_read", [[["lb_id", "=", lines[0]["id"]]]],
                  {"fields": ["sequence", "process_name", "cycle_time", "load_ratio", "over_takt"],
                   "order": "sequence"})
Respuesta de ejemplo
[{"id": 1, "name": "LB_Robot Assembly Line MAC Analysis", "takt_time": 27.74,
  "lb_efficiency": 90.0, "bottleneck_name": "Robot Assembly Line (After Improvement)", "max_ct": 27.74}]
[{"id": 1, "sequence": 10, "process_name": "Robot Assembly Line (After Improvement)",
  "cycle_time": 23.39, "load_ratio": 84.3, "over_takt": false}, ...]

11. MMC · MAC

Modelo · wa.mmc · wa.macMétodo · search_read

Devuelve diagramas hombre-máquina (MMC) y diagramas de actividades múltiples (MAC) con desglose de tiempos y utilización.

Python
mmc = model("wa.mmc", "search_read", [[]],
            {"fields": ["name", "total_time", "machine_time", "walk_time", "wait_time", "load_ratio"]})
mac = model("wa.mac", "search_read", [[]],
            {"fields": ["name", "process_count", "takt_time", "avg_ct", "utilization", "balance_eff"]})
Respuesta de ejemplo
[{"id": 1, "name": "Engine Assembly Line", "total_time": 165.33, "machine_time": 0.0,
  "walk_time": 0.0, "wait_time": 0.0, "load_ratio": 100.0}]
[{"id": 1, "name": "Robot Assembly Line MAC Analysis", "process_count": 4, "takt_time": 0.0,
  "avg_ct": 24.97, "utilization": 0.0, "balance_eff": 90.0}]

Consulte todos los campos con fields_get: model("wa.session", "fields_get", [], {"attributes": ["string", "type"]})