Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
UCC
UCC Snack Machine Server Code
Commits
060a7374
Commit
060a7374
authored
Mar 08, 2015
by
Mitchell Pomery
Committed by
Mark Tearle
Apr 05, 2015
Browse files
Rearranging file and adding comments
parent
3dbb7110
Changes
1
Hide whitespace changes
Inline
Side-by-side
VendServer/VendServer.py
View file @
060a7374
...
...
@@ -75,6 +75,33 @@ _last_card_id = -1
idlers
=
[]
idler
=
None
config_options
=
{
'DBServer'
:
(
'Database'
,
'Server'
),
'DBName'
:
(
'Database'
,
'Name'
),
'DBUser'
:
(
'VendingMachine'
,
'DBUser'
),
'DBPassword'
:
(
'VendingMachine'
,
'DBPassword'
),
'ServiceName'
:
(
'VendingMachine'
,
'ServiceName'
),
'ServicePassword'
:
(
'VendingMachine'
,
'Password'
),
'ServerName'
:
(
'DecServer'
,
'Name'
),
'ConnectPassword'
:
(
'DecServer'
,
'ConnectPassword'
),
'PrivPassword'
:
(
'DecServer'
,
'PrivPassword'
),
}
class
VendConfigFile
:
def
__init__
(
self
,
config_file
,
options
):
try
:
cp
=
ConfigParser
.
ConfigParser
()
cp
.
read
(
config_file
)
for
option
in
options
:
section
,
name
=
options
[
option
]
value
=
cp
.
get
(
section
,
name
)
self
.
__dict__
[
option
]
=
value
except
ConfigParser
.
Error
,
e
:
raise
SystemExit
(
"Error reading config file "
+
config_file
+
": "
+
str
(
e
))
class
DispenseDatabaseException
(
Exception
):
pass
...
...
@@ -106,7 +133,9 @@ class DispenseDatabase:
while
notifier
is
not
None
:
self
.
process_requests
()
notify
=
self
.
db
.
getnotify
()
"""
This class manages the current state of the vending machine.
"""
class
VendState
:
def
__init__
(
self
,
v
):
self
.
state_table
=
{}
...
...
@@ -124,22 +153,16 @@ class VendState:
def
change_state
(
self
,
newstate
,
newcounter
=
None
):
if
self
.
state
!=
newstate
:
#print "Changing state from: ",
#print self.state,
#print " to ",
#print newstate
self
.
state
=
newstate
if
newcounter
is
not
None
and
self
.
counter
!=
newcounter
:
#print "Changing counter from: ",
#print self.counter,
#print " to ",
#print newcounter
self
.
counter
=
newcounter
"""
Show information to the user as to what can be dispensed.
"""
def
scroll_options
(
username
,
mk
,
welcome
=
False
):
# If the user has just logged in, show them their balance
if
welcome
:
# Balance checking
acct
,
unused
=
Popen
([
'dispense'
,
'acct'
,
username
],
close_fds
=
True
,
stdout
=
PIPE
).
communicate
()
...
...
@@ -153,7 +176,7 @@ def scroll_options(username, mk, welcome = False):
msg
=
[]
choices
=
' '
*
10
+
'CHOICES: '
#
Get coke contents
#
Show what is in the coke machine
cokes
=
[]
for
i
in
range
(
0
,
7
):
args
=
(
'dispense'
,
'iteminfo'
,
'coke:%i'
%
i
)
...
...
@@ -168,23 +191,19 @@ def scroll_options(username, mk, welcome = False):
if
slot_name
==
'dead'
:
continue
choices
+=
'%s-(%sc)-%s8 '
%
(
slot_name
,
price
,
slot_num
)
# we don't want to print snacks for now since it'll be too large
# and there's physical bits of paper in the machine anyway - matt
# try:
# snacks = get_snacks()
# except:
# snacks = {}
#
# for slot, ( name, price ) in snacks.items():
# choices += '%s8-%s (%sc) ' % ( slot, name, price )
# Show the final few options
choices
+=
'55-DOOR '
choices
+=
'OR ANOTHER SNACK. '
choices
+=
'99 TO READ AGAIN. '
choices
+=
'CHOICE? '
msg
.
append
((
choices
,
False
,
None
))
# Send it to the display
mk
.
set_messages
(
msg
)
"""
Verify the users pin
"""
def
_check_pin
(
uid
,
pin
):
global
_pin_uid
global
_pin_uname
...
...
@@ -227,6 +246,9 @@ def _check_pin(uid, pin):
logging
.
info
(
"Pin incorrect for %d"
,
uid
)
return
pin
==
int
(
pinstr
)
"""
Check if the users account has been disabled
"""
def
acct_is_disabled
(
name
=
None
):
global
_pin_uname
if
name
==
None
:
...
...
@@ -240,9 +262,15 @@ def acct_is_disabled(name=None):
return
True
return
False
"""
Check that the user has a valid pin set
"""
def
has_good_pin
(
uid
):
return
_check_pin
(
uid
,
None
)
!=
None
"""
Verify the users pin.
"""
def
verify_user_pin
(
uid
,
pin
,
skip_pin_check
=
False
):
if
skip_pin_check
or
_check_pin
(
uid
,
pin
)
==
True
:
info
=
pwd
.
getpwuid
(
uid
)
...
...
@@ -258,7 +286,9 @@ def verify_user_pin(uid, pin, skip_pin_check=False):
logging
.
info
(
'refused pin for uid %d'
%
(
uid
))
return
None
"""
In here just for fun.
"""
def
cookie
(
v
):
seed
(
time
())
messages
=
[
' WASSUP! '
,
'PINK FISH '
,
' SECRETS '
,
' ESKIMO '
,
' FORTUNES '
,
'MORE MONEY'
]
...
...
@@ -283,10 +313,16 @@ def cookie(v):
s
+=
msg
[
i
]
v
.
display
(
s
)
"""
Format text so it will appear centered on the screen.
"""
def
center
(
str
):
LEN
=
10
return
' '
*
((
LEN
-
len
(
str
))
/
2
)
+
str
"""
Configure the things that will appear on screen whil the machine is idling.
"""
def
setup_idlers
(
v
):
global
idlers
,
idler
idlers
=
[
...
...
@@ -322,6 +358,9 @@ def setup_idlers(v):
disabled
=
[
]
"""
Go back to the default idler.
"""
def
reset_idler
(
v
,
vstatus
,
t
=
None
):
global
idlers
,
idler
idler
=
GreetingIdler
(
v
,
t
)
...
...
@@ -330,6 +369,9 @@ def reset_idler(v, vstatus, t = None):
vstatus
.
time_to_autologout
=
None
vstatus
.
change_state
(
STATE_IDLE
,
1
)
"""
Change to a random idler.
"""
def
choose_idler
():
global
idlers
,
idler
...
...
@@ -359,7 +401,9 @@ def choose_idler():
if
idler
:
idler
.
reset
()
"""
Run every step while the machine is idling.
"""
def
idle_step
(
vstatus
):
global
idler
if
idler
.
finished
():
...
...
@@ -370,8 +414,9 @@ def idle_step(vstatus):
nextidle
=
IDLE_SPEED
vstatus
.
time_of_next_idlestep
=
time
()
+
nextidle
"""
These next two events trigger no response in the code.
"""
def
handle_tick_event
(
event
,
params
,
v
,
vstatus
):
# don't care right now.
pass
...
...
@@ -380,11 +425,16 @@ def handle_switch_event(event, params, v, vstatus):
# don't care right now.
pass
"""
Don't do anything for this event.
"""
def
do_nothing
(
state
,
event
,
params
,
v
,
vstatus
):
print
"doing nothing (s,e,p)"
,
state
,
" "
,
event
,
" "
,
params
pass
"""
These next few entrie tell us to do nothing while we are idling
"""
def
handle_getting_uid_idle
(
state
,
event
,
params
,
v
,
vstatus
):
# don't care right now.
pass
...
...
@@ -393,6 +443,9 @@ def handle_getting_pin_idle(state, event, params, v, vstatus):
# don't care right now.
pass
"""
While logged in and waiting for user input, slowly get closer to logging out.
"""
def
handle_get_selection_idle
(
state
,
event
,
params
,
v
,
vstatus
):
global
_last_card_id
# don't care right now.
...
...
@@ -429,8 +482,9 @@ def handle_get_selection_idle(state, event, params, v, vstatus):
# need to check
vstatus
.
mk
.
update_display
()
"""
Triggered on user input while logged in.
"""
def
handle_get_selection_key
(
state
,
event
,
params
,
v
,
vstatus
):
global
_last_card_id
key
=
params
...
...
@@ -466,13 +520,15 @@ def handle_get_selection_key(state, event, params, v, vstatus):
vstatus
.
time_to_autologout
=
None
vstatus
.
last_timeout_refresh
=
None
"""
Triggered when the user has entered the id of something they would like to purchase.
"""
def
make_selection
(
v
,
vstatus
):
# should use sudo here
if
vstatus
.
cur_selection
==
'55'
:
vstatus
.
mk
.
set_message
(
'OPENSESAME'
)
logging
.
info
(
'dispensing a door for %s'
%
vstatus
.
username
)
if
geteuid
()
==
0
:
#ret = os.system('su - "%s" -c "dispense door"'%vstatus.username)
ret
=
os
.
system
(
'dispense -u "%s" door'
%
vstatus
.
username
)
else
:
ret
=
os
.
system
(
'dispense door'
)
...
...
@@ -503,8 +559,6 @@ def make_selection(v, vstatus):
price
,
shortname
,
name
=
get_snack
(
'--'
)
dollarprice
=
"$%.2f"
%
(
price
/
100.0
)
v
.
display
(
vstatus
.
cur_selection
+
' - %s'
%
dollarprice
)
# exitcode = os.system('dispense -u "%s" give \>snacksales %d "%s"'%(vstatus.username, price, name)) >> 8
# exitcode = os.system('dispense -u "%s" give \>sales\:snack %d "%s"'%(vstatus.username, price, name)) >> 8
exitcode
=
os
.
system
(
'dispense -u "%s" snack:%s'
%
(
vstatus
.
username
,
vstatus
.
cur_selection
))
>>
8
if
(
exitcode
==
0
):
# magic dispense syslog service
...
...
@@ -526,7 +580,9 @@ def make_selection(v, vstatus):
v
.
display
(
'UNK ERROR'
)
sleep
(
1
)
"""
Find the price of an item.
"""
def
price_check
(
v
,
vstatus
):
if
vstatus
.
cur_selection
[
1
]
==
'8'
:
args
=
(
'dispense'
,
'iteminfo'
,
'coke:'
+
vstatus
.
cur_selection
[
0
])
...
...
@@ -541,7 +597,9 @@ def price_check(v, vstatus):
dollarprice
=
"$%.2f"
%
(
price
/
100.0
)
v
.
display
(
vstatus
.
cur_selection
+
' - %s'
%
dollarprice
)
"""
Triggered when the user presses a button while entering their pin.
"""
def
handle_getting_pin_key
(
state
,
event
,
params
,
v
,
vstatus
):
#print "handle_getting_pin_key (s,e,p)", state, " ", event, " ", params
key
=
params
...
...
@@ -577,7 +635,9 @@ def handle_getting_pin_key(state, event, params, v, vstatus):
return
"""
Triggered when the user presses a button while entering their user id.
"""
def
handle_getting_uid_key
(
state
,
event
,
params
,
v
,
vstatus
):
#print "handle_getting_uid_key (s,e,p)", state, " ", event, " ", params
key
=
params
...
...
@@ -677,7 +737,9 @@ Wouldn't you prefer a nice game of chess?
vstatus
.
change_state
(
STATE_GETTING_PIN
)
return
"""
Triggered when a key is pressed and the machine is idling.
"""
def
handle_idle_key
(
state
,
event
,
params
,
v
,
vstatus
):
#print "handle_idle_key (s,e,p)", state, " ", event, " ", params
...
...
@@ -691,7 +753,9 @@ def handle_idle_key(state, event, params, v, vstatus):
vstatus
.
change_state
(
STATE_GETTING_UID
)
run_handler
(
event
,
key
,
v
,
vstatus
)
"""
What to do when there is nothing to do.
"""
def
handle_idle_tick
(
state
,
event
,
params
,
v
,
vstatus
):
### State idling
if
vstatus
.
mk
.
done
():
...
...
@@ -709,6 +773,9 @@ def handle_idle_tick(state, event, params, v, vstatus):
run_handler
(
event
,
params
,
v
,
vstatus
)
sleep
(
0.05
)
"""
Manages the beeps for the grandfather clock
"""
def
beep_on
(
when
,
before
=
0
):
start
=
int
(
when
-
before
)
end
=
int
(
when
)
...
...
@@ -813,6 +880,9 @@ def handle_grandfather_tick(state, event, params, v, vstatus):
if
go_idle
and
vstatus
.
mk
.
done
():
vstatus
.
change_state
(
STATE_IDLE
,
1
)
"""
What to do when the door is open.
"""
def
handle_door_idle
(
state
,
event
,
params
,
v
,
vstatus
):
def
twiddle
(
clock
,
v
,
wise
=
2
):
if
(
clock
%
4
==
0
):
...
...
@@ -832,7 +902,9 @@ def handle_door_idle(state, event, params, v, vstatus):
else
:
twiddle
(
now
,
v
,
wise
=
0
)
"""
What to do when the door is opened or closed.
"""
def
handle_door_event
(
state
,
event
,
params
,
v
,
vstatus
):
if
params
==
0
:
#door open
vstatus
.
change_state
(
STATE_DOOR_OPENING
)
...
...
@@ -848,7 +920,9 @@ def handle_door_event(state, event, params, v, vstatus):
logging
.
warning
(
'Leaving open door mode'
)
v
.
display
(
"-YUM YUM!-"
)
"""
Triggered when a user swipes their caed, and the machine is logged out.
"""
def
handle_mifare_event
(
state
,
event
,
params
,
v
,
vstatus
):
global
_last_card_id
card_id
=
params
...
...
@@ -895,6 +969,9 @@ def handle_mifare_event(state, event, params, v, vstatus):
reset_idler
(
v
,
vstatus
,
2
)
return
"""
Triggered when a user swipes their card and the machine is logged in.
"""
def
handle_mifare_add_user_event
(
state
,
event
,
params
,
v
,
vstatus
):
global
_last_card_id
card_id
=
params
...
...
@@ -927,6 +1004,9 @@ def handle_mifare_add_user_event(state, event, params, v, vstatus):
def
return_to_idle
(
state
,
event
,
params
,
v
,
vstatus
):
reset_idler
(
v
,
vstatus
)
"""
Maps what to do when the state changes.
"""
def
create_state_table
(
vstatus
):
vstatus
.
state_table
[(
STATE_IDLE
,
TICK
,
1
)]
=
handle_idle_tick
vstatus
.
state_table
[(
STATE_IDLE
,
KEY
,
1
)]
=
handle_idle_key
...
...
@@ -966,6 +1046,9 @@ def create_state_table(vstatus):
vstatus
.
state_table
[(
STATE_GRANDFATHER_CLOCK
,
KEY
,
2
)]
=
do_nothing
vstatus
.
state_table
[(
STATE_GRANDFATHER_CLOCK
,
MIFARE
,
1
)]
=
handle_mifare_event
"""
Get what to do on a state change.
"""
def
get_state_table_handler
(
vstatus
,
state
,
event
,
counter
):
return
vstatus
.
state_table
[(
state
,
event
,
counter
)]
...
...
@@ -989,17 +1072,6 @@ def run_forever(rfh, wfh, options, cf):
setup_idlers
(
v
)
reset_idler
(
v
,
vstatus
)
# This main loop was hideous and the work of the devil.
# This has now been fixed (mostly) - mtearle
#
#
# notes for later surgery
# (event, counter, ' ')
# V
# d[ ] = (method)
#
# ( return state - not currently implemented )
while
True
:
if
USE_DB
:
try
:
...
...
@@ -1013,14 +1085,14 @@ def run_forever(rfh, wfh, options, cf):
run_handler
(
event
,
params
,
v
,
vstatus
)
# logging.debug('Got event: ' + repr(e))
def
run_handler
(
event
,
params
,
v
,
vstatus
):
handler
=
get_state_table_handler
(
vstatus
,
vstatus
.
state
,
event
,
vstatus
.
counter
)
if
handler
:
handler
(
vstatus
.
state
,
event
,
params
,
v
,
vstatus
)
"""
Connect to the machine.
"""
def
connect_to_vend
(
options
,
cf
):
if
options
.
use_lat
:
...
...
@@ -1045,6 +1117,9 @@ def connect_to_vend(options, cf):
return
rfh
,
wfh
"""
Parse arguments from the command line
"""
def
parse_args
():
from
optparse
import
OptionParser
...
...
@@ -1068,34 +1143,6 @@ def parse_args():
return
options
config_options
=
{
'DBServer'
:
(
'Database'
,
'Server'
),
'DBName'
:
(
'Database'
,
'Name'
),
'DBUser'
:
(
'VendingMachine'
,
'DBUser'
),
'DBPassword'
:
(
'VendingMachine'
,
'DBPassword'
),
'ServiceName'
:
(
'VendingMachine'
,
'ServiceName'
),
'ServicePassword'
:
(
'VendingMachine'
,
'Password'
),
'ServerName'
:
(
'DecServer'
,
'Name'
),
'ConnectPassword'
:
(
'DecServer'
,
'ConnectPassword'
),
'PrivPassword'
:
(
'DecServer'
,
'PrivPassword'
),
}
class
VendConfigFile
:
def
__init__
(
self
,
config_file
,
options
):
try
:
cp
=
ConfigParser
.
ConfigParser
()
cp
.
read
(
config_file
)
for
option
in
options
:
section
,
name
=
options
[
option
]
value
=
cp
.
get
(
section
,
name
)
self
.
__dict__
[
option
]
=
value
except
ConfigParser
.
Error
,
e
:
raise
SystemExit
(
"Error reading config file "
+
config_file
+
": "
+
str
(
e
))
def
create_pid_file
(
name
):
try
:
pid_file
=
file
(
name
,
'w'
)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment