Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Take args from JSON post data #8

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
Open
53 changes: 45 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,46 @@
# Merch Embedded

# Merch Embedded

[![Join the chat at https://gitter.im/acm-uiuc/merch-development](https://badges.gitter.im/acm-uiuc/merch-development.svg)](https://gitter.im/acm-uiuc/merch-development?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)

Possible information sources:

This repository contains all of the code related to controlling the underlying merch hardware (the vending machine).
Merch runs an embedded webserver that can be accessed at merch.acm.illinois.edu.

## API

Every request through the API has a token in the header that is unique to groot.
This way, only groot can make requests to vend things.
The token is stored in the request header.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be something like

"Requests to the device must contain a valid token in the Authorization Header for a request to be processed.
As of now the only token will be given solely to the groot merch service, so if you wish to make merch requests go through groot. "

Also rename the header field from Token to Authorization, better match with web conventions (may require change by @sameetandpotatoes on the service side)

### Vend a location
To vend a list of items, POST a request to `/vend`.
The request is of the form
```json
{
"transaction_id": 1,
"items": ["A1", "B2", "C3"]
}
```

The machine will respond with
```json
{
"transaction_id": 1,
"items": [
{"location": "A1", "error": null},
{"location": "B2", "error": "some sort of error"},
{"location": "C3", "error": null},

]
}
```

The errors that can take place while vending are currently:
* `"Invalid location"`


## Some related datasheets

[http://bajavending.com/Manual-de-Operacion-BevMax.pdf](http://bajavending.com/Manual-de-Operacion-BevMax.pdf)
* Has the right picture of the main controller board, no programming information though

Expand All @@ -18,15 +55,15 @@ has some useful info about what commands are sent

## License

This project is licensed under the University of Illinois/NCSA Open Source License. For a full copy of this license take a look at the LICENSE file.
This project is licensed under the University of Illinois/NCSA Open Source License. For a full copy of this license take a look at the LICENSE file.

When contributing new files to this project, preappend the following header to the file as a comment:
When contributing new files to this project, preappend the following header to the file as a comment:

```
Copyright © 2017, ACM@UIUC

This file is part of the Merch Project.
The Merch Project is open source software, released under the University of Illinois/NCSA Open Source License.
This file is part of the Merch Project.

The Merch Project is open source software, released under the University of Illinois/NCSA Open Source License.
You should have received a copy of this license in a file with the distribution.
```
28 changes: 22 additions & 6 deletions machine_controller/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,28 @@
def hello_world():
if request.headers.get('TOKEN', '') != token_value:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Change this from TOKEN to Authorization

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@sameetandpotatoes Change this on service side as well ^

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

abort(401)
if 'item' not in request.args:
abort(400)
item = request.args['item']
merch.vend(item[0], int(item[1]))
return json.dumps({'success': True}), 200, {'ContentType': 'application/json'}
data = request.json()
items = data['items']
transaction_id = data['transaction_id']


statuses = []
for i, item in enumerate(items):
try:
merch.vend(item[0], int(item[1]))
statuses.append({'error': None, 'location': item})

except Exception as e:
# Some error occurred while vending
# I'd prefer to catch Merch.VendError's only, but if something else
# goes wrong, we still need to let the client know instead of
# throwing a 500
statuses.append({'error': str(e), 'location': item})

return jsonify(transaction_id=transaction_id, items=statuses)

if __name__ == '__main__':
app.run(debug=True, host='0.0.0.0')
# Make sure flask runs in a single thread. Otherwise concurrent requests
# may cause problems with vending
app.run(debug=True, host='0.0.0.0', threaded=False)

19 changes: 13 additions & 6 deletions machine_controller/vend.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,11 @@ class Merch:
MAX_LETTER = 'F'
MAX_NUMBER = '0'

class VendError(Exception):
pass

InvalidLocationError = VendError("Invalid location")

def __init__(self, debug=False):
self.debug = debug

Expand Down Expand Up @@ -93,22 +98,24 @@ def vend(self, letter, number):
try:
char = ord(letter)
except TypeError:
raise TypeError('Letter %s does not represent a character' %
str(letter))
raise Merch.VendError("Invalid location: %s" %
(str(letter) + str(number)))

# Maybe we should use the actual keypad value?
if char < ord('A') or char > ord('Z'):
raise ValueError('Invalid Letter: %s' % str(letter))
raise Merch.VendError("Invalid location: %s" %
(str(letter) + str(number)))

num = 0
try:
num = int(number)
except TypeError:
raise TypeError('Number %s is not convertible to an integer' %
str(num))
raise Merch.VendError("Invalid location: %s" %
(str(letter) + str(number)))

if num < 0 or num > 10:
raise ValueError('Number %d is not in the range 1-10' % num)
raise Merch.VendError("Invalid location: %s" %
(str(letter) + str(number)))

self.__vend(letter, str(number))

Expand Down