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
54 changes: 46 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,47 @@
# 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

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.


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 +56,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)

21 changes: 12 additions & 9 deletions machine_controller/vend.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,12 @@ class Merch:
ROW = [21, 20, 16]
COL = [19, 13]
MAX_LETTER = 'F'
MAX_NUMBER = '0'
MAX_NUMBER = 9

class VendError(Exception):
pass

InvalidLocationError = VendError("Invalid location")

def __init__(self, debug=False):
self.debug = debug
Expand Down Expand Up @@ -93,22 +98,20 @@ def vend(self, letter, number):
try:
char = ord(letter)
except TypeError:
raise TypeError('Letter %s does not represent a character' %
str(letter))
raise self.InvalidLocationError

# Maybe we should use the actual keypad value?
if char < ord('A') or char > ord('Z'):
raise ValueError('Invalid Letter: %s' % str(letter))
if char < ord('A') or char > ord(self.MAX_LETTER):
raise self.InvalidLocationError

num = 0
try:
num = int(number)
except TypeError:
raise TypeError('Number %s is not convertible to an integer' %
str(num))
raise self.InvalidLocationError

if num < 0 or num > 10:
raise ValueError('Number %d is not in the range 1-10' % num)
if num < 1 or num > MAX_NUMBER:
raise self.InvalidLocationError

self.__vend(letter, str(number))

Expand Down