ProEye-X API
Cách đọc và ghi dữ liệu phân tích công việc trong phiên bản riêng của công ty (https://congty.proeye-x.com) từ hệ thống bên ngoài như MES, ERP, BI. Mọi lệnh gọi dùng JSON-RPC 2.0, gửi POST đến một địa chỉ duy nhất: /jsonrpc.
Bắt đầu
Địa chỉ gọi
Địa chỉ khác nhau cho mỗi phiên bản công ty. Tên cơ sở dữ liệu là phần đầu của địa chỉ công ty (congty).
POST https://company.proeye-x.com/jsonrpc
Tạo khóa API
Đăng nhập phiên bản → menu người dùng (góc trên phải) › Hồ sơ của tôi (Tùy chọn) › Bảo mật tài khoản › “Khóa API mới”. Dùng khóa thay cho mật khẩu; khóa chỉ hiển thị một lần. Chỉ lưu khóa trong chương trình phía máy chủ, không đặt trong mã trình duyệt.
Xác thực (lấy uid)
Đổi email đăng nhập và khóa API lấy mã người dùng (uid), sau đó gửi kèm cơ sở dữ liệu, uid và khóa API trong mọi lệnh gọi.
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)Hàm hỗ trợ Python
Các ví dụ bên dưới dùng hàm hỗ trợ model() này.
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 {})Ngôn ngữ
Truyền lang trong context để nhận tên công việc và tên phần tử bằng ngôn ngữ đó (khi có bản dịch). Ví dụ: {"context": {"lang": "vi_VN"}} · en_US · ja_JP · zh_CN · zh_TW · th_TH · id_ID · es_ES · de_DE · ko_KR.
Lỗi
Khi thất bại, bạn nhận HTTP 200 kèm đối tượng "error"; error.data.message cho biết lý do (không có quyền, thiếu trường bắt buộc, …).
Danh sách API
element_type là khóa của ô loại công việc (va = ô 1, nva = ô 2, wait = ô 3, ô tự định nghĩa c4 …). Thời gian VA/NVA được tính từ các khoảng segment_data.
1. Danh sách phân tích
Lấy danh sách phân tích công việc (phiên) cùng thời gian chu kỳ trung bình, tỷ lệ VA và số phần tử.
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 -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}]}}'[{"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. Lấy phần tử công việc
Lấy các phần tử công việc của một phân tích theo chu kỳ: thời gian bắt đầu/kết thúc (giây), thời gian tiêu chuẩn, thời gian VA và NVA. cycle_no là chu kỳ chứa phần tử đó (1, 2, 3 …).
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[{"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. Lấy LOSS
Lấy nội dung đã nhập ở tab LOSS. Với mỗi đoạn NVA của phần tử (mục segment_data có type = nva), nội dung LOSS (loss_data) và mã loại lãng phí (loss_type_data) được lưu thành mảng JSON cùng thứ tự — ghép như bên dưới để có các dòng chu kỳ · phần tử · thời gian đoạn · loại lãng phí · nội dung LOSS.
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 ""})# 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 defects4. Tạo phân tích
Tạo phân tích công việc mới. O-No (mã duy nhất) là bắt buộc và không được trùng. Trả về ID mới.
session_id = model("wa.session", "create", [{
"o_no": "O-2026-LINE3-01", # required, unique
"name": "Line 3 sub-assembly",
"process_name": "Sub-assembly",
}])21
5. Thêm phần tử công việc
Thêm nhiều phần tử cùng lúc theo khoảng thời gian video. Các tổng như thời gian chu kỳ, tỷ lệ VA được tính lại tự động.
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"]})[205, 206]
[{"id": 18, "element_count": 2, "cycle_time_avg": 9.8, "va_ratio": 100.0}]6. Sửa / xóa phần tử
Đổi tên, thời gian hoặc loại công việc (write), hoặc xóa (unlink).
model("wa.element", "write", [[205], {"name": "Pick and place", "video_end_time": 4.6}])
model("wa.element", "unlink", [[206]])true true
7. Ghi LOSS
Ghi nội dung LOSS và mã loại lãng phí cho từng đoạn NVA dưới dạng mảng JSON theo thứ tự thời gian. Giá trị thứ n thuộc đoạn NVA thứ n. Mã: w1 sản xuất thừa · w2 chờ đợi · w3 vận chuyển · w4 gia công thừa · w5 tồn kho · w6 thao tác · w7 lỗi.
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"]),
}])true
8. Lấy chu kỳ
Lấy các chu kỳ đã đo với thời điểm bắt đầu, kết thúc và thời gian chu kỳ.
cycles = model("wa.cycle", "search_read", [[["session_id", "=", 4]]],
{"fields": ["sequence", "video_start", "video_end", "cycle_time"], "order": "sequence"})[{"id": 4, "sequence": 1, "video_start": 0.767, "video_end": 17.15, "cycle_time": 16.383}, ...]9. So sánh (trước / sau)
Ghép hai phân tích thành một so sánh, tạo các dòng so sánh và lấy mức giảm thời gian chu kỳ, cải thiện VA và chênh lệch từng phần tử.
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"})[{"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. Cân bằng chuyền
Lấy takt time, hiệu suất chuyền, công đoạn nút thắt cùng thời gian chu kỳ và tải của từng công đoạn.
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"})[{"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
Lấy biểu đồ người-máy (MMC) và biểu đồ đa hoạt động (MAC) với cơ cấu thời gian và hiệu suất sử dụng.
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"]})[{"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}]Xem mọi trường bằng fields_get: model("wa.session", "fields_get", [], {"attributes": ["string", "type"]})