bitcoin-atm
bitcoin atm for pyc inc.
git clone https://9o.is/git/bitcoin-atm.git
Acceptor.scala
(2544B)
1 package inc.pyc.chimera
2
3 import akka.actor._
4 import inc.pyc._
5 import bill._
6 import acceptor._
7 import Events._
8 import Commands._
9 import States.Disconnected
10 import concurrent._
11 import duration._
12 import net.liftweb.util.Props.{devMode, productionMode}
13
14 /**
15 * Overlord's extension for the Bill Acceptor.
16 */
17 trait Acceptor {
18 this: Overlord with FSM[State, Data] =>
19
20 /*
21 * Uses the fake bill acceptor in dev mode.
22 */
23 private def props: Props = {
24 if(productionMode) BillAcceptor.props(context.system)
25 else Props[snippet.FakeBillAcceptor]
26 }
27
28 /** The bill acceptor */
29 lazy val acceptor: ActorRef = context.actorOf(props, "Acceptor")
30
31
32 when (Uninitialized) {
33 case Event(Ready, _) =>
34 acceptor ! UnInhibit
35 goto(Idle)
36 }
37
38 when (Malfunctioning) {
39 case Event(Disconnected, _) =>
40 stay
41
42 case Event(Listen, _) =>
43 acceptor forward Listen
44 stay
45
46 case Event(Ready, _) =>
47 log info "Bill acceptor is operating again"
48 cancelTimer("poll-acceptor")
49 goto (Idle) using NullData
50 }
51
52 /**
53 * Initiates the bill acceptor
54 */
55 def initAcceptor {
56 watchTransitions(acceptor)
57 acceptor ! Listen
58 }
59
60 /**
61 * Shuts down the bill acceptor
62 */
63 def stopAcceptor {
64 unwatchTransitions(acceptor)
65 acceptor ! UnListen
66 acceptor ! PoisonPill
67 }
68
69 /**
70 * State handler.
71 */
72 def handleAcceptor: StateFunction = {
73 case Event(Disconnected, _) =>
74 log error "Bill acceptor not operating"
75 setTimer ("poll-acceptor", Listen, 1 minute, true)
76 gotoMalfunctioning(Reason(Msg.hardwareMalfunction))
77 }
78
79 /**
80 * Transition handler.
81 */
82 def acceptorTransitions: TransitionHandler = {
83 case TxCreate -> CashInsert =>
84 acceptor ! Inhibit
85
86 case CashInsert -> Sending =>
87 acceptor ! UnInhibit
88
89 case _ -> Malfunctioning =>
90 log error ("Malfunctioning: {}/{}", stateName, stateData)
91
92 case Malfunctioning -> Idle =>
93 log info ("Operational: Idle/{}", nextStateData)
94 }
95
96 /**
97 * Before it transitions to Malfunctioning state, it checks
98 * if the current state of the machine has an active
99 * transaction. If it does, go to error state.
100 */
101 def gotoMalfunctioning(reason: Reason): State = {
102 if (sensitiveState) goto(ErrorState) using stateData
103 else goto(Malfunctioning) using reason
104 }
105 }