-
Notifications
You must be signed in to change notification settings - Fork 2
/
PiServer.py
221 lines (188 loc) · 4.86 KB
/
PiServer.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
#!/usr/bin/env python3
"""
PiServer.py
Listens for incoming connections and orchestrates the server commands.
"""
from flask import Flask, jsonify
from flask_cors import CORS
from BoardController import BoardController
from constants import *
app = Flask(__name__)
CORS(app)
bc = BoardController()
def validate_pin(pin):
"""
Checks that the specified pin exists
Parameters
----------
pin: int
The pin number as defined by the Raspberry Pi GPIO reference
"""
if pin not in VALID_PINS:
raise ValueError("Pin {} is not in the list of valid pins: {}".format(pin, VALID_PINS))
@app.route("/")
def hello_world():
"""
Simple API to indicate that this server is running.
Returns
-------
dict
"""
return jsonify({"message": "Server is on"})
@app.route("/get-pin-mode/<int:pin>", methods=["GET"])
def get_pin_mode(pin):
"""
Gets the GPIO pin configuration for the specified pin
Parameters
----------
pin: int
The pin number as defined by the Raspberry Pi GPIO reference
Returns
-------
dict
"""
validate_pin(pin)
mode = bc.get_pin_mode(pin)
return jsonify({
'pin': pin,
'mode': MODE_MAP[mode]
})
@app.route("/set-pin-mode/<int:pin>/<string:mode>", methods=["POST"])
def set_pin_mode(pin, mode):
"""
Sets GPIO pin as either an input or output pin.
An input pin is one that detects logical high or low values.
An output pin is one that produces a variable average voltage with
pulse width modulation (PWM).
Parameters
----------
pin: int
The pin number as defined by the Raspberry Pi GPIO reference
mode: str
The pin mode. Can be either 'IN' or 'OUT'
Returns
-------
dict
"""
validate_pin(pin)
if mode not in VALID_MODES:
raise ValueError("Mode {} not in valid modes: {}".format(mode, VALID_MODES))
pin_mode = bc.set_pin_mode(pin, MODE_MAP[mode])
return jsonify({
'pin': pin,
'mode': MODE_MAP[pin_mode]
})
@app.route("/get-pin-pwm/<int:pin>", methods=["GET"])
def get_pin_pwm(pin):
"""
Gets the PWM config for an output pin
Parameters
----------
pin: int
The pin number as defined by the Raspberry Pi GPIO reference
Returns
-------
dict
"""
validate_pin(pin)
duty, freq = bc.get_pin_pwm(pin)
return jsonify({
'pin': pin,
'duty': duty,
'freq': freq
})
@app.route("/set-pin-pwm/<int:pin>/<float:duty>", methods=["POST"])
@app.route("/set-pin-pwm/<int:pin>/<float:duty>/<float:freq>", methods=["POST"])
def set_pin_pwm(pin, duty, freq=100):
"""
Sets the PWM config for an output pin
Parameters
----------
pin: int
The pin number as defined by the Raspberry Pi GPIO reference
duty: float
The duty cycle of the PWM. Must be value constrained to 0.0 <= n <= 100.0
freq: float, optional
The PWM frequency, in Hertz. Must be value greater than 0.0.
Returns
-------
dict
"""
validate_pin(pin)
duty, freq = bc.set_pin_pwm(pin, duty, freq)
return jsonify({
'pin': pin,
'duty': duty,
'freq': freq
})
@app.route("/get-pin-value/<int:pin>", methods=["GET"])
def get_pin_value(pin):
"""
Gets the value, either "HIGH" or "LOW," for an input pin.
Parameters
----------
pin: int
The pin number as defined by the Raspberry Pi GPIO reference
Returns
-------
dict
"""
validate_pin(pin)
if not bc.get_pin_mode(pin) == IN:
raise RuntimeError("Pin {} is not in IN mode".format(pin))
return jsonify({
'pin': pin,
'value': bc.get_pin_value(pin)
})
@app.route("/set-pin-value/<int:pin>/<int:value>", methods=["POST"])
def set_pin_value(pin, value):
"""
Sets the value, either "HIGH" or "LOW," for an output pin.
Parameters
----------
pin: int
The pin number as defined by the Raspberry Pi GPIO reference
value: int
The 1 (HIGH) or 0 (LOW) value to set the pin
Returns
-------
dict
"""
validate_pin(pin)
if not bc.get_pin_mode(pin) == OUT:
raise RuntimeError("Pin {} is not in OUT mode".format(pin))
if not value in VALID_VOLTAGES:
raise ValueError("Value {} not in valid voltages: {}".format(value, VALID_VOLTAGES))
return jsonify({
'pin': pin,
'value': bc.set_pin_value(pin, value)
})
# Error handling
@app.errorhandler(404)
def handle_not_found(e):
return jsonify({
"Error": "Method not found",
"Message": str(e)
}), 404
@app.errorhandler(NotImplementedError)
def handle_not_implemented_error(e):
return jsonify({
"Error": "Method not implemented",
"Message": str(e)
}), 501
@app.errorhandler(RuntimeError)
def handle_runtime_error(e):
return jsonify({
"Error": "Method and pin mode do not match",
"Message": str(e)
}), 400
@app.errorhandler(ValueError)
def handle_value_error(e):
return jsonify({
"Error": "Value failed validation",
"Message": str(e)
}), 400
# Run the server. Flask will default to port 5000.
if __name__ == "__main__":
app.run(debug = True,
host = "0.0.0.0")