summaryrefslogtreecommitdiff
path: root/src/state.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/state.go')
-rw-r--r--src/state.go94
1 files changed, 94 insertions, 0 deletions
diff --git a/src/state.go b/src/state.go
new file mode 100644
index 0000000..9c6ab66
--- /dev/null
+++ b/src/state.go
@@ -0,0 +1,94 @@
+// vim: shiftwidth=4 tabstop=4 noexpandtab
+
+package main
+
+import (
+ "log"
+ "time"
+)
+
+type Machine struct {
+ name string
+ initial string
+ current string
+ states StateMap
+ api chan string
+}
+
+type StateMap map[string]MachineState
+
+type MachineState struct {
+ on TransitionMap
+}
+
+type TransitionMap map[string]MachineTransition
+
+type MachineTransition struct {
+ to string
+}
+
+func (m Machine) GetState() string {
+ if m.current == "" {
+ return m.initial
+ }
+ return m.current
+}
+
+func (m *Machine) processEvent(event string) string {
+ current := m.GetState()
+ next := m.states[current].on[event].to
+ if next != "" {
+ log.Printf("State machine '%s' changes from '%s' to '%s'\n", m.name, current, next)
+ m.current = next
+ m.runHooks(current, next)
+ return next
+ }
+ return current
+}
+
+func (m *Machine) SendEvent(event string) {
+ m.api <- event // blocks until m.run() goroutine handles this event
+}
+
+func (m *Machine) run() {
+ var event string
+ for {
+ event = <-m.api // read api (blocking)
+ m.processEvent(event)
+ }
+}
+
+func (m *Machine) runHooks(last string, next string) {
+ if next == "single_picture" {
+ // TODO implement launch of python subprocess here
+ go func() {
+ time.Sleep(1 * time.Second)
+ m.SendEvent("single_picture_taken")
+ }()
+ }
+}
+
+func newCamStateMachine() Machine {
+ return Machine{
+ name: "camera",
+ initial: "idle",
+ states: StateMap{
+ "idle": MachineState{
+ on: TransitionMap{
+ "take_single_picture": MachineTransition{
+ to: "single_picture",
+ },
+ },
+ },
+ "single_picture": MachineState{
+ on: TransitionMap{
+ "single_picture_taken": MachineTransition{
+ to: "idle",
+ },
+ },
+ },
+ },
+ api: make(chan string),
+ }
+}
+