Skip to content
This repository has been archived by the owner on Apr 10, 2018. It is now read-only.

Commit

Permalink
Add 'credit-only' mode. Adds #7
Browse files Browse the repository at this point in the history
  • Loading branch information
turt2live committed Jun 24, 2015
1 parent 3387244 commit 319272d
Show file tree
Hide file tree
Showing 4 changed files with 152 additions and 14 deletions.
55 changes: 45 additions & 10 deletions pi/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ class PopPi:
# State information
__acceptingFob = False
__acceptingFunds = False
__creditOnlyMode = False
__lastCreditButtonState = 0
__memberFob = None
__memberCredit = None
__deposited = None
Expand All @@ -34,7 +36,9 @@ def __init__(self):
self.__obs.on("CoinAccepted", self.__onCoinAccepted)
self.__obs.on("MemberNotFound", self.__onMemberNotFound)
self.__obs.on("PopPaid", self.__onPopPaid)
self.__obs.on("CreditCompleted", self.__onCreditCompleted)
self.__creditOnlyPin = conf.general.creditOnlyPin
GPIO.setup(self.__creditOnlyPin, GPIO.IN)

def start(self):
self.__fobThread = threading.Thread(target=self.__readCardThread)
Expand All @@ -43,6 +47,9 @@ def start(self):
self.__coinThread = threading.Thread(target=self.__readCoinThread)
self.__coinThread.daemon = True
self.__coinThread.start()
self.__creditOnlyThread = threading.Thread(target=self.__readCreditOnlyButton)
self.__creditOnlyThread.daemon = True
self.__creditOnlyThread.start()
self.__resetStates()
self.__acceptingFob = True

Expand All @@ -63,6 +70,7 @@ def __onCardRead(self, card):
print("Fob swiped while not accepting fobs: Ignoring fob " + str(card))
return
self.__acceptingFob = False
self.__webService.onSwipeStart()
print("Fob " + str(card) + " swiped. Finding member...")
self.__memberCredit = self.__memberService.getCredit(card)
if self.__memberCredit is None:
Expand All @@ -76,8 +84,7 @@ def __onCardRead(self, card):
self.__webService.onSwipe(self.__memberCredit, self.__popCost)
requiredFunds = self.__getRequiredFunds()
print("Member " + str(card) + " needs to supply " + str(requiredFunds) + " cents")
if self.__getRequiredFunds() <= 0:
self.__obs.trigger("PopPaid")
self.__checkRequiredFunds()

def __onCoinAccepted(self, coin):
if not self.__acceptingFunds:
Expand All @@ -86,8 +93,7 @@ def __onCoinAccepted(self, coin):
self.__deposited += coin
self.__webService.onDeposit(coin)
print("Member inserted " + str(coin) + " cents")
if self.__getRequiredFunds() <= 0:
self.__obs.trigger("PopPaid")
self.__checkRequiredFunds()

def __onPopPaid(self):
self.__acceptor.inhibit(True)
Expand All @@ -100,6 +106,15 @@ def __onPopPaid(self):
print("Pop awarded to member")
self.__resetStates()

def __onCreditCompleted(self):
self.__acceptor.inhibit(True)
self.__acceptingFunds = False
newCredit = self.__memberCredit + self.__deposited
self.__memberService.setCredit(self.__memberFob, newCredit)
print("Member's new credit is " + str(newCredit) + " cents")
self.__webService.onCreditCompleted(newCredit)
self.__resetStates()

def __onMemberNotFound(self, card):
print("Member not found: " + str(card))
self.__resetStates()
Expand All @@ -108,28 +123,48 @@ def __onMemberNotFound(self, card):
def __resetStates(self):
self.__acceptingFob = True
self.__acceptingFunds = False
self.__creditOnlyMode = False
self.__memberFob = None
self.__memberCredit = None
self.__deposited = None
self.__acceptor.inhibit(True)
print("Waiting for member")

def __checkRequiredFunds(self):
if self.__getRequiredFunds() <= 0 and not self.__creditOnlyMode:
self.__obs.trigger("PopPaid")

def __getRequiredFunds(self):
totalDeposit = self.__memberCredit + self.__deposited
return self.__popCost - totalDeposit

def __readCardThread(self):
while True:
if self.__rfid is None:
sleep(1)
continue
card = self.__rfid.readCard()
self.__obs.trigger("CardSwiped", card)

def __readCoinThread(self):
while True:
if self.__acceptor is None:
sleep(1)
continue
coin = self.__acceptor.readCoin()
self.__obs.trigger("CoinAccepted", coin)

def __readCreditOnlyButton(self):
sleepTime = 0.1 # 100ms
while True:
pressed = GPIO.input(self.__creditOnlyPin)
if self.__lastCreditButtonState == pressed:
sleep(sleepTime)
continue # Ignore: Already handled this state
self.__lastCreditButtonState = pressed
if not self.__acceptingFunds:
sleep(sleepTime)
continue # Ignore button: Don't care about this state
if pressed == 1:
if not self.__creditOnlyMode:
self.__creditOnlyMode = True
self.__webService.onCreditOnly()
print("Member requested credit-only mode")
else:
print("Credit-only mode completed")
self.__obs.trigger("CreditCompleted")
sleep(sleepTime)
9 changes: 9 additions & 0 deletions pi/web.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,9 @@ def __broadcast(self, eventName, *args):
socket.send_packet(pkt)

# TODO: These "on" methods should be handled by Observer...
def onSwipeStart(self):
self.__broadcast("member-swipe-start")

def onSwipe(self, credit, cost):
self.__broadcast("member-swipe", credit, cost)

Expand All @@ -82,5 +85,11 @@ def onPaid(self, newCredit):
def onNotFound(self):
self.__broadcast("not-found")

def onCreditOnly(self):
self.__broadcast("credit-only")

def onCreditCompleted(self, newCredit):
self.__broadcast("credit-completed", newCredit)

def shutdown(self):
return # Nothing to do
28 changes: 26 additions & 2 deletions www/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,36 @@
<div id='idle' style='display: none;'>
<h1>Please swipe fob to begin</h1>
</div>
<!-- When the member has just swiped their card -->
<div id='lookup-started' style='display: none;'>
<h1>Looking up fob...</h1>
<h2>Please be patient. I'm just a Raspberry Pi</h2>
</div>
<!-- When the user is paying for pop -->
<div id='paying' style='display: none;'>
<div class='amount-due' id='paying-amount-due'>
$0.00
</div>
<div class='text-small' style='border-bottom: 1px solid rgb(173, 173, 173); padding-bottom: 15px; width: 100%;'>remaining cost</div>
<div class='amount-credit'>
<span id='paying-credit'>$0.00</span> <span class='text-small'>credit</span>
<span class='paying-credit'>$0.00</span> <span class='text-small'>credit</span>
</div>
<div class='amount-entered'>
<span class='text-small'>deposited</span> <span id='paying-deposited'>$0.00</span>
<span class='text-small'>deposited</span> <span class='paying-deposited'>$0.00</span>
</div>
<p class='credit-warning'>Any extra funds will be applied to your credit for next time</p>
</div>
<!-- When the user is adding credit -->
<div id='credit-only' style='display: none;'>
<div class='amount-due' id='deposited-credit'>
$0.00
</div>
<div class='text-small' style='border-bottom: 1px solid rgb(173, 173, 173); padding-bottom: 15px; width: 100%;'>new credit amount</div>
<div class='amount-credit'>
<span class='paying-credit'>$0.00</span> <span class='text-small'>past credit</span>
</div>
<div class='amount-entered'>
<span class='text-small'>deposited</span> <span class='paying-deposited'>$0.00</span>
</div>
<p class='credit-warning'>Any extra funds will be applied to your credit for next time</p>
</div>
Expand All @@ -32,6 +51,11 @@ <h1>Thank you!</h1>
<h2>Please press the pop button of your choice.</h2>
<h3>Your new credit is <span id="new-credit">$0.00</span></h3>
</div>
<!-- "Credit completed" state -->
<div id='credit-completed' style='display: none;'>
<h1>Thank you!</h1>
<h3>Your new credit is <span id="completed-credit">$0.00</span></h3>
</div>
<!-- Member not found state -->
<div id='not-a-member' style='display: none;'>
<h1>404</h1>
Expand Down
74 changes: 72 additions & 2 deletions www/static/script.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,12 @@ var timeoutTime = 15000; // ms
$(document).ready(function(){
var socket = io.connect('/pop');
socket.on('connect', onConnect);
socket.on('member-swipe-start', onSwipeStart)
socket.on('member-swipe', function(credit, cost){
member.credit = credit;
member.cost = cost;
member.deposited = 0;
member.newCredit = 0;
onSwipe();
});
socket.on('deposit', function(amountDeposited){
Expand All @@ -29,16 +31,66 @@ $(document).ready(function(){
onPaid();
});
socket.on('not-found', onMemberNotFound);
socket.on('credit-only', onCreditOnly);
socket.on('credit-completed', function(newCredit){
member.newCredit = newCredit;
onCreditCompleted();
});
});

// SOCKET FUNCTIONS
// ===============================

// TODO: Find a better way to do states. Angular?

function onCreditOnly(){
$("#idle").hide();
$("#paying").hide();
$("#thanks").hide();
$("#not-a-member").hide();
$("#lookup-started").hide();
$("#credit-completed").hide();
$("#credit-only").show();

$(".paying-credit").html(toCurrency(member.credit));
updateAmountDue();
updateDeposited();
updateNewCredit();

if (toIdleTimer)
clearTimeout(toIdleTimer);
}

function onCreditCompleted(){
$("#idle").hide();
$("#paying").hide();
$("#thanks").hide();
$("#not-a-member").hide();
$("#lookup-started").hide();
$("#credit-completed").show();
$("#credit-only").hide();
$("#completed-credit").html(toCurrency(member.newCredit))
toIdleTimer = setTimeout(toIdle, timeoutTime);
}

function onSwipeStart(){
$("#idle").hide();
$("#paying").hide();
$("#thanks").hide();
$("#not-a-member").hide();
$("#lookup-started").show();
$("#credit-completed").hide();
$("#credit-only").hide();
}

function onPaid(){
$("#idle").hide();
$("#paying").hide();
$("#thanks").show();
$("#not-a-member").hide();
$("#lookup-started").hide();
$("#credit-completed").hide();
$("#credit-only").hide();
$("#new-credit").html(toCurrency(member.newCredit))
toIdleTimer = setTimeout(toIdle, timeoutTime);
}
Expand All @@ -48,29 +100,40 @@ function toIdle(){
$("#paying").hide();
$("#thanks").hide();
$("#not-a-member").hide();
$("#lookup-started").hide();
$("#credit-completed").hide();
$("#credit-only").hide();
}

function onConnect(){
$("#idle").show();
$("#paying").hide();
$("#thanks").hide();
$("#not-a-member").hide();
$("#lookup-started").hide();
$("#credit-completed").hide();
$("#credit-only").hide();
}

function onDeposit(){
updateDeposited();
updateAmountDue();
updateNewCredit();
}

function onSwipe(){
$("#idle").hide();
$("#paying").show();
$("#thanks").hide();
$("#not-a-member").hide();
$("#lookup-started").hide();
$("#credit-completed").hide();
$("#credit-only").hide();

$("#paying-credit").html(toCurrency(member.credit));
$(".paying-credit").html(toCurrency(member.credit));
updateAmountDue();
updateDeposited();
updateNewCredit();

if (toIdleTimer)
clearTimeout(toIdleTimer);
Expand All @@ -81,14 +144,21 @@ function onMemberNotFound(){
$("#paying").hide();
$("#thanks").hide();
$("#not-a-member").show();
$("#lookup-started").hide();
$("#credit-completed").hide();
$("#credit-only").hide();
toIdleTimer = setTimeout(toIdle, timeoutTime);
}

// HELPERS
// ===============================

function updateNewCredit(){
$("#deposited-credit").html(toCurrency(member.deposited + member.credit))
}

function updateDeposited(){
$("#paying-deposited").html(toCurrency(member.deposited));
$(".paying-deposited").html(toCurrency(member.deposited));
}

function updateAmountDue(){
Expand Down

0 comments on commit 319272d

Please sign in to comment.