Ứng dụng Flutter này được thiết kế để chạy trước tiên trên Windows, phục vụ nhân viên sản xuất và bảo trì trong việc:
- Giám sát trạng thái hoạt động của OHT.
- Kiểm tra trạng thái động cơ, cảm biến và kết nối.
- Điều khiển OHT ở chế độ manual khi cần kiểm tra, căn chỉnh hoặc bảo trì.
- Hiển thị cảnh báo an toàn khi OHT gặp lỗi, mất kết nối hoặc phát hiện vật cản.
OHT trong hệ thống có tổng cộng 6 động cơ và nhiều nhóm cảm biến an toàn. App không thay thế hoàn toàn bộ điều khiển an toàn phần cứng, mà đóng vai trò giao diện vận hành, giám sát và gửi lệnh manual đến bộ điều khiển OHT.
OHT có 6 động cơ, chia thành 3 nhóm chính:
| Nhóm | Số lượng | Chức năng |
|---|---|---|
| Steering Motor | 2 | Rẽ hướng trước và sau |
| Traveling Motor | 2 | Di chuyển trước và sau |
| Hoisting Motor | 2 | Nâng/hạ trước và sau |
Chi tiết:
steer_front: động cơ rẽ hướng phía trước.steer_rear: động cơ rẽ hướng phía sau.travel_front: động cơ di chuyển phía trước.travel_rear: động cơ di chuyển phía sau.hoist_front: động cơ nâng phía trước.hoist_rear: động cơ nâng phía sau.
| Nhóm cảm biến | Số lượng | Chức năng |
|---|---|---|
| Steering position sensors | 4 | Xác định vị trí trái/phải cho 2 động cơ rẽ hướng |
| Hoist upper limit sensors | 2 | Giới hạn trên cho 2 động cơ nâng |
| Pumper sensors | 2 | Phát hiện trạng thái pumper trước/sau |
| Step lidar sensors | 2 | Phát hiện vật cản phía trước OHT theo 2 mức cảnh báo |
Chi tiết:
-
Cảm biến rẽ hướng:
steer_front_leftsteer_front_rightsteer_rear_leftsteer_rear_right
-
Cảm biến giới hạn trên:
hoist_front_upper_limithoist_rear_upper_limit
-
Cảm biến pumper:
pumper_frontpumper_rear
-
Cảm biến lidar dạng bậc:
lidar_upperlidar_lower
Mỗi lidar có 3 trạng thái logic:
| Giá trị | Ý nghĩa |
|---|---|
| 0 | Không phát hiện vật cản |
| 1 | Vùng cảnh báo |
| 2 | Vùng nguy hiểm |
App giao tiếp với bộ điều khiển OHT qua Wi-Fi. Giao thức có thể dùng một trong hai phương án:
- WebSocket
- MQTT
Trong giai đoạn triển khai Windows đầu tiên, nên thiết kế tầng giao tiếp theo dạng interface chung để có thể chuyển đổi giữa WebSocket và MQTT mà không phải sửa toàn bộ giao diện.
Ví dụ cấu trúc service:
CommunicationService
├── WebSocketCommunicationService
└── MqttCommunicationService
App chỉ gọi các hàm chung như:
connect()
disconnect()
sendCommand()
listenTelemetry()
Phần giao thức cụ thể WebSocket hoặc MQTT được xử lý bên trong service tương ứng.
Bộ điều khiển OHT gửi dữ liệu trạng thái định kỳ về app, ví dụ mỗi 100 ms đến 500 ms.
Dữ liệu nhận về gồm:
- Trạng thái kết nối.
- Chế độ hoạt động: manual, auto, maintenance, error.
- Trạng thái 6 động cơ.
- Trạng thái toàn bộ cảm biến.
- Mức cảnh báo lidar.
- Mã lỗi nếu có.
- Trạng thái emergency stop nếu có.
- Timestamp của gói dữ liệu.
App nhận dữ liệu, parse thành model nội bộ, sau đó cập nhật UI theo thời gian thực.
Khi người dùng nhấn nút điều khiển manual, app gửi lệnh xuống bộ điều khiển OHT.
Ví dụ các nhóm lệnh:
- Di chuyển tiến/lùi.
- Dừng di chuyển.
- Rẽ trái/phải.
- Dừng rẽ.
- Nâng/hạ.
- Dừng nâng/hạ.
- Reset lỗi.
- Bật/tắt chế độ manual.
- Emergency stop.
Lệnh gửi xuống nên có cấu trúc rõ ràng, ví dụ:
{
"type": "command",
"command": "travel_forward",
"target": "both",
"speed": 30,
"requestId": "cmd_0001",
"timestamp": 1710000000000
}Bộ điều khiển OHT nên phản hồi lại kết quả thực hiện lệnh:
{
"type": "ack",
"requestId": "cmd_0001",
"success": true,
"message": "Command accepted"
}Ứng dụng phải ưu tiên an toàn khi vận hành OHT. Các nguyên tắc chính:
- Chỉ cho phép điều khiển khi OHT đang ở chế độ manual.
- Nếu mất kết nối, app phải tự động chuyển UI sang trạng thái không cho gửi lệnh.
- Nếu lidar báo vùng nguy hiểm, app phải hiển thị cảnh báo rõ ràng và không cho phép tiếp tục di chuyển về phía nguy hiểm.
- Nếu cảm biến giới hạn trên của motor nâng đang kích hoạt, không cho phép tiếp tục nâng theo hướng vượt giới hạn.
- Các nút điều khiển nên hoạt động theo kiểu nhấn giữ, thả ra thì gửi lệnh dừng.
- Lệnh emergency stop phải luôn hiển thị rõ ràng, dễ nhấn và có độ ưu tiên cao nhất.
- Tất cả lệnh manual nên có timeout hoặc heartbeat để tránh trường hợp OHT tiếp tục chạy khi app bị treo hoặc mất mạng.
Màn hình chính nên chia thành các vùng chức năng:
Hiển thị:
- Tên hệ thống.
- Trạng thái kết nối.
- IP hoặc broker đang kết nối.
- Chế độ hiện tại của OHT.
- Nút Connect/Disconnect.
- Nút Emergency Stop.
Gồm các nhóm nút:
-
Travel Control:
- Forward
- Backward
- Stop
-
Steering Control:
- Front Left
- Front Right
- Rear Left
- Rear Right
- Stop Steering
-
Hoist Control:
- Front Up
- Front Down
- Rear Up
- Rear Down
- Stop Hoist
Có thể thêm slider điều chỉnh tốc độ hoặc phần trăm công suất.
Hiển thị 6 card động cơ:
- Tên động cơ.
- Trạng thái running/stopped/error.
- Chiều chuyển động.
- Tốc độ hiện tại.
- Dòng điện hoặc lỗi nếu dữ liệu có sẵn.
Hiển thị toàn bộ cảm biến theo dạng đèn trạng thái:
- Xanh: bình thường.
- Vàng: cảnh báo.
- Đỏ: nguy hiểm hoặc lỗi.
- Xám: không có dữ liệu hoặc mất kết nối.
Hiển thị:
- Cảnh báo lidar.
- Cảnh báo giới hạn hành trình.
- Lỗi mất kết nối.
- Log các lệnh đã gửi.
- Log phản hồi từ OHT.
Cấu trúc thư mục Flutter nên tách rõ theo chức năng:
lib/
├── main.dart
├── app.dart
├── core/
│ ├── constants/
│ ├── enums/
│ ├── theme/
│ └── utils/
├── features/
│ └── oht_manual/
│ ├── data/
│ │ ├── models/
│ │ └── services/
│ ├── domain/
│ │ ├── entities/
│ │ └── repositories/
│ └── presentation/
│ ├── screens/
│ ├── widgets/
│ └── controllers/
└── mock/
└── mock_oht_data.dart
Trong giai đoạn đầu, nên có chế độ mock/simulation để test UI khi chưa kết nối OHT thật.
{
"type": "telemetry",
"mode": "manual",
"connected": true,
"emergencyStop": false,
"motors": {
"steerFront": {"state": "stopped", "direction": "left", "speed": 0},
"steerRear": {"state": "stopped", "direction": "right", "speed": 0},
"travelFront": {"state": "running", "direction": "forward", "speed": 30},
"travelRear": {"state": "running", "direction": "forward", "speed": 30},
"hoistFront": {"state": "stopped", "direction": "up", "speed": 0},
"hoistRear": {"state": "stopped", "direction": "up", "speed": 0}
},
"sensors": {
"steerFrontLeft": false,
"steerFrontRight": true,
"steerRearLeft": false,
"steerRearRight": true,
"hoistFrontUpperLimit": false,
"hoistRearUpperLimit": false,
"pumperFront": false,
"pumperRear": false,
"lidarUpper": 0,
"lidarLower": 1
},
"errors": [],
"timestamp": 1710000000000
}{
"type": "command",
"command": "travel_forward",
"target": "both",
"speed": 30,
"requestId": "cmd_0001",
"timestamp": 1710000000000
}App cần kiểm tra heartbeat hoặc timestamp của telemetry.
Nếu quá một khoảng thời gian nhất định không nhận được dữ liệu mới, ví dụ 2 giây:
- Đánh dấu trạng thái là disconnected.
- Disable toàn bộ nút điều khiển manual.
- Hiển thị cảnh báo mất kết nối.
- Ghi log sự kiện.
- Yêu cầu người dùng kết nối lại trước khi điều khiển tiếp.
- Tạo giao diện chính.
- Tạo model dữ liệu OHT.
- Tạo mock telemetry.
- Hiển thị trạng thái động cơ và cảm biến.
- Cho phép nhấn nút manual nhưng chỉ ghi log, chưa gửi xuống OHT thật.
- Thêm WebSocket service.
- Kết nối đến IP của bộ điều khiển OHT.
- Nhận telemetry thật.
- Gửi command thật.
- Xử lý ACK/NACK.
- Thêm MQTT service nếu cần.
- Thiết kế topic:
oht/telemetryoht/commandoht/ackoht/error
- Thêm rule interlock.
- Thêm cảnh báo chi tiết.
- Thêm log lưu file local.
- Thêm màn hình cấu hình kết nối.
- Thêm màn hình diagnostic cho bảo trì.
UI cần rõ ràng, dễ nhìn trong môi trường sản xuất:
- Ưu tiên chữ lớn.
- Màu trạng thái rõ ràng.
- Nút điều khiển lớn, dễ bấm.
- Emergency Stop luôn nổi bật.
- Không nhồi quá nhiều thông tin vào một màn hình nhỏ.
- Trạng thái lỗi phải dễ nhận biết trong vài giây.
- Có chế độ dark theme để dùng trong khu vực nhà máy.
Trong phiên bản đầu tiên, app nên chạy ổn định trên Windows trước. Sau khi hoàn thành logic và giao diện desktop, có thể mở rộng sang Android tablet hoặc thiết bị khác nếu cần.
Các phần cần ưu tiên trước:
- Kiến trúc project sạch.
- UI dashboard manual dễ dùng.
- Mock data để test nhanh.
- Tầng giao tiếp có thể thay WebSocket/MQTT.
- Safety interlock cơ bản.
- Log điều khiển và cảnh báo.