T3 — Finite State Machine và Harel Statechart - congsinhv/fluxion GitHub Wiki
Issue: #15 — Nghiên cứu Finite State Machine (Harel Statechart) Tuần: 3 | 07/04 – 13/04/2026 Numbering chính thức: Mục 2.7 theo Master TOC (Chương 2)
Finite State Machine (FSM) — hay còn gọi là Finite Automaton — là mô hình tính toán toán học mô tả hành vi của một hệ thống thông qua một tập hữu hạn các trạng thái (states), chuyển đổi (transitions), và sự kiện kích hoạt (triggers/events).
Một FSM được định nghĩa hình thức bởi bộ 5 thành phần (quintuple) [1]:
M = (Q, Σ, δ, q₀, F)
Trong đó:
- Q — tập hữu hạn các trạng thái
- Σ — tập bảng chữ cái đầu vào (input alphabet / triggers)
- δ: Q × Σ → Q — hàm chuyển đổi trạng thái
- q₀ ∈ Q — trạng thái khởi đầu
- F ⊆ Q — tập các trạng thái kết thúc (terminal states)
Trong kỹ thuật phần mềm, FSM được sử dụng rộng rãi để mô hình hoá lifecycle của các thực thể có trạng thái rõ ràng — giao thức mạng, quy trình nghiệp vụ, và vòng đời thiết bị trong hệ thống MDM.
Hai loại FSM chính:
- Mealy Machine: Output phụ thuộc vào cả trạng thái hiện tại và input
- Moore Machine: Output chỉ phụ thuộc vào trạng thái hiện tại
Áp dụng trong Fluxion: Fluxion DeviceFSM là Moore Machine — trạng thái của thiết bị xác định các hành động có thể thực hiện, không phụ thuộc vào input cụ thể tại thời điểm truy vấn.
| Thuộc tính | Mô tả | Lợi ích trong Fluxion |
|---|---|---|
| Deterministic | Mỗi (state, trigger) → duy nhất một state tiếp theo | Không có trạng thái mơ hồ — device không thể ở "active" và "locked" cùng lúc |
| Auditable | Mọi transition đều có thể log lại | Audit trail đầy đủ lịch sử thay đổi trạng thái thiết bị |
| Visualizable | State diagram dễ đọc, dễ communicate | Stakeholder không kỹ thuật hiểu được lifecycle |
| Testable | Có thể test từng transition độc lập | Unit test cho từng trigger rõ ràng |
| Guard conditions | Chỉ cho phép transition khi điều kiện thoả mãn | Tránh lock thiết bị chưa enrolled
|
Bảng 2.7.1: Ưu điểm FSM cho device lifecycle management
David Harel công bố Statecharts: A Visual Formalism for Complex Systems năm 1987 trên tạp chí Science of Computer Programming [5]. Statechart là mở rộng của FSM truyền thống với ba đặc điểm chính:
1. Hierarchical States (Trạng thái phân cấp) Statechart cho phép states lồng nhau (nested states) — một state "cha" có thể chứa nhiều states "con". Khi ở trong bất kỳ state con nào, thiết bị cũng được coi là đang ở state cha. Điều này giảm đáng kể số lượng transitions cần định nghĩa.
2. Parallel States (Trạng thái song song)
Thiết bị có thể ở nhiều "region" song song cùng lúc — ví dụ: region connectivity (online/offline) song song với region management_state (enrolled/locked).
3. Guard Conditions (Điều kiện bảo vệ)
Transitions chỉ xảy ra khi một biểu thức boolean (guard) là true. Ví dụ: transition enroll_complete chỉ valid khi device.certificate_valid == true.
| Đặc điểm | FSM truyền thống | Harel Statechart |
|---|---|---|
| States | Phẳng (flat) | Phân cấp (hierarchical) |
| Parallel regions | Không | Có |
| Guard conditions | Không (hoặc manual) | Tích hợp sẵn |
| Lịch sử (History) | Không | Deep/Shallow history states |
| Complexity | Tăng theo bình phương số states | Tăng tuyến tính nhờ hierarchy |
| Phù hợp cho | Systems đơn giản, ít states | Systems phức tạp, nhiều states lồng nhau |
Bảng 2.7.2: So sánh FSM và Harel Statechart
DeviceFSM của Fluxion sử dụng FSM phẳng (flat FSM) với guard conditions — đủ để mô hình hoá 6 trạng thái thiết bị mà không cần độ phức tạp của full Statechart. Quyết định này tuân theo nguyên tắc KISS: Statechart mang lợi ích rõ ràng khi số lượng states và transitions tăng lên đáng kể.
Quyết định triển khai: Fluxion implement FSM theo hướng DB-driven — states và transitions được lưu trong database (bảng
state,policy,action) thay vì hardcode trong code. Xem chi tiết schema tại mục 2.7.4.2.
| State | Mô tả | Các action được phép |
|---|---|---|
| Idle | Thiết bị được upload vào hệ thống, chưa đăng ký | Register |
| Registered | Đã đăng ký MDM, chưa hoàn tất enrollment | Checkin |
| Enrolled | Đang trong quá trình enrollment | Activate |
| Active | Đã enrolled đầy đủ, đang hoạt động bình thường |
Lock, Send Message, Release, Deregister
|
| Locked | Bị khóa bởi admin (khách trốn trả trả góp / mất / trộm) |
Unlock, Lock Message, Release, Deregister
|
| Released | Đã unenroll MDM — trigger khi khách hoàn thành hợp đồng trả góp (positive outcome). Data của khách giữ nguyên, máy trở thành 100% sở hữu khách | (terminal — không có transition ra) |
Bảng 2.7.3: DeviceFSM states trong Fluxion
Transitions không hardcode trong code. Chúng được biểu diễn implicit qua quan hệ giữa 3 bảng DB:
| Bảng | Vai trò trong FSM |
|---|---|
state |
Định nghĩa các trạng thái hợp lệ |
action |
from_state_id = source state, apply_policy_id = destination (via policy) |
policy |
state_id = state mà policy đại diện → destination state |
action.from_state_id ──→ state (source)
action.apply_policy_id ──→ policy.state_id ──→ state (destination)
| Action | Source State | Destination Policy → State |
|---|---|---|
| Upload | NULL (initial) | Idle → Idle |
| Register | Idle | Registered → Registered |
| Checkin | Registered | Enrolled → Enrolled |
| Activate | Enrolled | Active → Active |
| Lock | Active | Locked → Locked |
| Unlock | Locked | Active → Active |
| Send Message | Active | Active → Active (internal) |
| Lock Message | Locked | Locked → Locked (internal) |
| Release | Active, Locked | Released → Released |
| Deregister | Active, Locked | Idle → Idle |
Lưu ý thiết kế:
-
Uploadlà initial action (from_state_id = NULL) — device được tạo với policy Idle -
Releasecó 2 entries riêng cho Active và Locked (không dùng wildcard) -
Deregisterđưa device về Idle — cho phép re-enroll (khác với Release là terminal) -
Send MessagevàLock Messagelà internal transitions —apply_policy_idtrỏ về cùng state - Xem chi tiết schema tại T5 — Thiết kế DeviceFSM mục 3.18
stateDiagram-v2
[*] --> idle: device created
idle --> registered: register_complete
idle --> active: enroll_complete\n(fast-path DEP)
registered --> enrolled: enroll_start
registered --> active: enroll_complete\n(fast-path)
enrolled --> active: enroll_complete
active --> locked: lock\n[admin action]
active --> released: release
locked --> active: unlock
locked --> released: release
enrolled --> released: release
registered --> released: release
idle --> released: release
released --> [*]
note right of active
Lệnh được phép:
lock, notify, release
end note
note right of locked
Lệnh được phép:
unlock, release
end note
note right of released
Terminal state
Không có transition ra
end note
Hình 2.5: DeviceFSM state diagram trong Fluxion
Guard conditions đảm bảo transitions chỉ xảy ra khi điều kiện thoả mãn:
| Transition | Guard | Mô tả |
|---|---|---|
enroll_complete |
device.mdm_certificate_valid == true |
Certificate hợp lệ trước khi active |
lock |
device.state == 'active' |
Chỉ lock thiết bị đang active |
unlock |
admin.has_permission('unlock_device') |
Chỉ admin có quyền mới unlock được |
release |
device.pending_actions == 0 |
Không có lệnh đang chờ trước khi release |
notify |
device.state == 'active' |
Internal transition — chỉ cho phép khi device đang active; không thay đổi state, không được phép khi locked
|
| Custom FSM | Library (transitions) | |
|---|---|---|
| Kiểm soát | Toàn quyền | Phụ thuộc API của lib |
| Boilerplate | Nhiều (if/else chains) | Ít (declarative config) |
| Guard conditions | Tự implement | Built-in |
| Callbacks | Tự implement | Built-in (on_enter, on_exit) |
| Logging/audit | Tự implement | Có thể hook vào transitions |
| Visualize | Không | Có (graphviz export) |
| Phù hợp cho | FSM đơn giản ≤3 states | FSM phức tạp ≥5 states |
Bảng 2.7.4: Custom FSM vs transitions library
⚠️ Fluxion không sử dụng thư viện này. Mục này giữ lại như tham khảo học thuật. Implementation thực tế dùng DB-driven FSM — xem schema bên dưới.
transitions là thư viện FSM Python phổ biến, hỗ trợ:
- Declarative state/transition definition
- Callbacks:
on_enter_<state>,on_exit_<state>,before_<trigger>,after_<trigger> - Guard conditions via
conditionsparameter - Hierarchical states (HierarchicalMachine)
Ưu điểm: Nhanh, ít boilerplate, visualize được. Nhược điểm: States hardcoded trong code — không linh hoạt khi cần quản lý qua UI hoặc đa tenant.
Fluxion lưu trữ toàn bộ FSM definition trong database — states và transitions là dữ liệu, không phải code:
| Bảng | Vai trò |
|---|---|
services |
Loại dịch vụ (id smallint, name, is_enabled) |
states |
Định nghĩa các trạng thái (id smallint, name) |
policies |
Quy tắc áp dụng, gắn với state (id smallint, name, service_type_id, state_id, color) |
actions |
Hành động kích hoạt transition (id uuid, name, action_type_id, from_state_id, service_type_id, apply_policy_id, configuration jsonb, ext_fields jsonb) |
milestones |
Lịch sử thực thi — device history (id uuid, device_id, assigned_action_id, policy_id, ext_fields) |
Lợi ích so với transitions library:
- States/transitions có thể thay đổi mà không cần redeploy code
- Hỗ trợ audit trail tự nhiên qua bảng
milestone -
action.configuration(JSONB) cho phép tham số hoá từng hành động
Device state (via current_policy_id) và action_executions FSM (command execution — mục 2.5.7) là hai FSM độc lập nhưng liên kết:
Admin gửi lệnh "Lock Device"
→ action_executions FSM: ACTION_PENDING → ACTION_SENT → ACTION_COMPLETED
→ (khi ACTION_COMPLETED) → Device: current_policy_id = action.apply_policy_id (locked)
Action Execution Flow (3-Layer):
-
BE
action-resolver: Validateassigned_action_id IS NULL+action.from_state_id == device.state_id -
BE
action-trigger: INSERTaction_executions(ACTION_PENDING), publish command → SNS -
OEM
apns-sender: Cache command + send APNS silent push (wake device) -
OEM
mdm-handler: Device polls → serve command from cache → device executes → device sends result → publish event → SNS -
BE
checkin-handler: NhậnACTION_COMPLETEDevent →- UPDATE
devicesSETcurrent_policy_id = action.apply_policy_id,assigned_action_id = NULL - INSERT
milestones - UPDATE
action_executionsSET status =ACTION_COMPLETED
- UPDATE
Nguyên tắc: BE chỉ biết DB, OEM chỉ biết 3rd party. Xem chi tiết tại T5 — Command Pipeline
| Khái niệm lý thuyết | Nguồn | Biểu hiện trong Fluxion |
|---|---|---|
| FSM quintuple (Q, Σ, δ, q₀, F) | [1] | 6 states, 12 actions, δ = implicit via action → policy → state
|
| Moore Machine | [1] | Device state (via current_policy_id) xác định actions được phép |
| Guard conditions | Harel [5] |
action.from_state_id == device.state_id + busy check |
| Initial action | — |
Upload: from_state_id = NULL — tạo device với Idle policy |
| Terminal state | [1] |
Released — không có transition ra |
| Non-terminal reset | — |
Deregister: Active/Locked → Idle — cho phép re-enroll |
| Two FSMs linked | — | action_executions FSM (ACTION_COMPLETED) → update device.current_policy_id
|
| DB-driven FSM | — | Transitions implicit qua services + states + actions + policies tables |
| Multi-service | — |
services table cho phép phân loại actions theo service type (Inventory, Postpaid) |
Bảng 2.7.5: Ánh xạ lý thuyết FSM — thực tiễn Fluxion
Finite State Machine (FSM) cung cấp nền tảng toán học chặt chẽ để mô hình hoá vòng đời thiết bị trong hệ thống MDM. Định nghĩa hình thức qua bộ 5 thành phần M = (Q, Σ, δ, q₀, F) của Hopcroft et al. (2006) không chỉ là công cụ lý thuyết mà còn là bản thiết kế trực tiếp ánh xạ thành schema cơ sở dữ liệu trong Fluxion: tập trạng thái Q tương ứng bảng states, hàm chuyển đổi δ tương ứng bảng actions với from_state_id/to_state_id, và trạng thái đầu q₀ tương ứng policy Idle được gán khi thiết bị upload lần đầu.
Mô hình Harel Statechart (1987) mở rộng FSM phẳng với khả năng phân cấp (hierarchical states), song song hoá (concurrent regions), và lịch sử trạng thái (history states). Tuy nhiên, sau phân tích yêu cầu nghiệp vụ, Fluxion chọn FSM phẳng (flat FSM) với 6 trạng thái và 12 hành động. Quyết định này phản ánh nguyên tắc YAGNI (You Aren't Gonna Need It): vòng đời thiết bị MDM trong phạm vi đồ án không có nhu cầu về trạng thái lồng nhau hay song song — mọi yêu cầu nghiệp vụ đều có thể biểu diễn đầy đủ bằng FSM phẳng với guard conditions tại tầng cơ sở dữ liệu.
Đóng góp quan trọng nhất của module FSM trong Fluxion là cách triển khai dưới dạng DB-driven FSM: logic chuyển đổi không được hard-code trong ứng dụng mà được lưu trữ trong các bảng states, actions, policies, và services. Thiết kế này cho phép thay đổi cấu hình vòng đời thiết bị mà không cần deploy lại code, đồng thời tạo nền tảng cho kiểm tra tính nhất quán trạng thái (guard: action.from_state_id == device.state_id) tại runtime — một yêu cầu an toàn quan trọng trong hệ thống MDM quản lý thiết bị thực tế.
[1] Hopcroft, J. E., Motwani, R., & Ullman, J. D. (2006). Introduction to Automata Theory, Languages, and Computation, 3rd ed. Pearson. https://www.pearson.com/en-us/subject-catalog/p/introduction-to-automata-theory-languages-and-computation/P200000003596
[5] Harel, D. (1987). Statecharts: A Visual Formalism for Complex Systems. Science of Computer Programming, 8(3), 231–274. Elsevier. https://www.sciencedirect.com/science/article/pii/0167642387900359
[6] pytransitions. (2024). transitions — A lightweight, object-oriented state machine library for Python. https://github.com/pytransitions/transitions
[7] Miro Samek. (2008). Practical UML Statecharts in C/C++: Event-Driven Programming for Embedded Systems, 2nd ed. Newnes. https://www.state-machine.com/qm/sm_intro.html
Các câu hỏi đã được giải đáp:
-
Notify transition ✅ —
notifylà internal transition: gửi push notification đến device mà không thay đổi state. Chỉ cho phép khidevice.state == 'active'. Đã thêm vào guard conditions (mục 2.7.3.4). -
Concurrent states ✅ — Khi device
locked, admin không được phép pushnotify. Guard conditiondevice.state == 'active'loại bỏ hoàn toàn trường hợp này — thiết bị bị lock là thiết bị mất/trộm/vi phạm, không cần gửi notification. -
History states ✅ —
releasedlà terminal state không thể quay lại. Trigger chính: khách hoàn thành hợp đồng trả góp → máy tự unenroll, trở thành sở hữu 100% của khách (graduation). Nếu sau này khách muốn mua máy trả góp tiếp, tạodevice_idmới. Không cần track history state.