Skip to content

Commit 3b0ca68

Browse files
author
Russell Green
committed
chore: adds pin history
1 parent 33dc5f0 commit 3b0ca68

File tree

3 files changed

+68
-35
lines changed

3 files changed

+68
-35
lines changed

.github/workflows/docker-publish.yml

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
name: Create and publish a Docker image
22

33
on:
4-
push:
5-
branches: ["main"]
4+
release:
5+
types: [published]
66

77
env:
88
REGISTRY: ghcr.io

.vscode/settings.json

+3-2
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
"git.ignoreLimitWarning": true,
3535
"cSpell.words": [],
3636
"[python]": {
37-
"editor.defaultFormatter": "ms-python.python"
38-
}
37+
"editor.defaultFormatter": "ms-python.black-formatter"
38+
},
39+
"python.formatting.provider": "none"
3940
}

src/server.py

+63-31
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
import sys
2020
import os
21+
import datetime
2122
from enum import Enum
2223
import logging as log
2324
import RPi.GPIO as GPIO
@@ -41,35 +42,35 @@ class InitialPinBehavior(Enum):
4142
UNMODIFIED = 3
4243

4344

44-
host = os.getenv('SERVER_HOST') or '0.0.0.0'
45-
port = os.getenv('SERVER_PORT') or 5000
46-
log_level = os.getenv('SERVER_LOG_LEVEL') or log.INFO
45+
host = os.getenv("SERVER_HOST") or "0.0.0.0"
46+
port = os.getenv("SERVER_PORT") or 5000
47+
log_level = os.getenv("SERVER_LOG_LEVEL") or log.WARN
4748
debug = False
4849
gpio_pins = (7, 11, 12, 13, 15, 16, 18, 22, 29, 31, 32, 33, 35, 36, 37, 38, 40)
50+
gpio_pin_history = {}
4951
initial_pin_state = InitialPinBehavior.DEFAULT
5052
app = Flask(__name__)
5153
CORS(app)
5254
app.url_map.strict_slashes = False
5355

56+
5457
log.basicConfig(
5558
level=log_level,
5659
format="%(asctime)s [%(levelname)s] %(message)s",
57-
handlers=[
58-
log.StreamHandler(sys.stdout)
59-
]
60+
handlers=[log.StreamHandler(sys.stdout)],
6061
)
6162

6263

63-
@app.route('/healthz')
64+
@app.route("/healthz")
6465
def health_check():
6566
"""Health check
6667
6768
Returns a value to ensure the service is up.
6869
"""
69-
return 'healthy'
70+
return "healthy"
7071

7172

72-
@app.route('/version')
73+
@app.route("/version")
7374
def version():
7475
"""Version
7576
@@ -78,22 +79,24 @@ def version():
7879
return __version__
7980

8081

81-
@app.route('/pins')
82+
@app.route("/pins")
8283
def get_all_pins():
8384
"""Get pins
8485
8586
Retries a list of all GPIO pins and their current values.
8687
"""
8788
result = []
8889
for pin in gpio_pins:
89-
pin_result = {'pin': pin, 'value': get_pin_value(pin)}
90+
pin_result = {"pin": pin, "value": get_pin_value(pin)}
91+
history = get_pin_history(pin)
92+
pin_result.update(history)
9093
result.append(pin_result)
9194

9295
log.info("Retrieved values for all pins")
9396
return jsonify(result)
9497

9598

96-
@app.route('/pins/all/<int:value>')
99+
@app.route("/pins/all/<int:value>")
97100
def set_all_pins(value):
98101
"""Set pins to value
99102
@@ -103,45 +106,50 @@ def set_all_pins(value):
103106
for pin in gpio_pins:
104107
new_value = set_get_pin_value(pin, value)
105108
changed = value != new_value
106-
pin_result = {'pin': pin, 'value': get_pin_value(
107-
pin), 'changed': changed}
109+
pin_result = {"pin": pin, "value": get_pin_value(pin), "changed": changed}
110+
111+
history = get_pin_history(pin)
112+
pin_result.update(history)
108113
result.append(pin_result)
109114

110115
log.info("Set value of all pins to {}".format(value))
111116
return jsonify(result)
112117

113118

114-
@app.route('/pins/<int:pin>')
119+
@app.route("/pins/<int:pin>")
115120
def get_pin(pin):
116121
"""Get pin value
117122
118123
Gets the current value for a given GPIO pin.
119124
"""
120125
pin_value = get_pin_value(pin)
121-
log.info("Retrieved value for pin '{}' (value: {})".format(
122-
str(pin), str(pin_value)))
126+
log.info(
127+
"Retrieved value for pin '{}' (value: {})".format(str(pin), str(pin_value))
128+
)
129+
123130
return str(pin_value)
124131

125132

126-
@app.route('/pins/<int:pin>/<int:value>')
133+
@app.route("/pins/<int:pin>/<int:value>")
127134
def set_pin(pin, value):
128135
"""Set pin value
129136
130137
Sets a GPIO pin to a specified value.
131138
"""
132139
pin_value = set_get_pin_value(pin, value)
133140

134-
if (value != pin_value):
141+
if value != pin_value:
135142
msg = "Failed to set pin '{}'. Expected {} to be {}".format(
136-
pin, pin_value, value)
143+
pin, pin_value, value
144+
)
137145
log.exception(msg)
138146
raise Exception(msg)
139147

140148
log.info("Set value for pin '{}' (value: {})".format(pin, pin_value))
141149
return str(pin_value)
142150

143151

144-
@app.route('/sensors/dht11/<int:pin>')
152+
@app.route("/sensors/dht11/<int:pin>")
145153
def get_sensor_dht11(pin):
146154
"""Get DHT11 sensor reading
147155
@@ -154,20 +162,27 @@ def get_sensor_dht11(pin):
154162
return jsonify(result.to_dict())
155163

156164

157-
@app.route('/sensors/hcsr04/<int:trigger_pin>/<int:echo_pin>')
165+
@app.route("/sensors/hcsr04/<int:trigger_pin>/<int:echo_pin>")
158166
def get_sensor_hcsr04(trigger_pin, echo_pin):
159167
"""Get HC-SR04 sensor reading
160168
Gets a reading for a HC-SR04 ultrasonic sonar distance sensor.
161169
See: https://adafru.it/3942
162170
"""
163171
log.info(
164-
"Reading HC-SR04 sensor for pin 'trigger: {}, echo: {}'".format(trigger_pin, echo_pin))
165-
args = {'trigger_pin': trigger_pin, 'echo_pin': echo_pin}
172+
"Reading HC-SR04 sensor for pin 'trigger: {}, echo: {}'".format(
173+
trigger_pin, echo_pin
174+
)
175+
)
176+
args = {"trigger_pin": trigger_pin, "echo_pin": echo_pin}
166177
args.update(request.args)
167178

168179
sensor = HCSR04(**args)
169180
result = sensor.read()
170-
log.info("Retrieved HC-SR04 sensor reading for pin 'trigger: {}, echo: {}'".format(trigger_pin, echo_pin))
181+
log.info(
182+
"Retrieved HC-SR04 sensor reading for pin 'trigger: {}, echo: {}'".format(
183+
trigger_pin, echo_pin
184+
)
185+
)
171186
return jsonify(result)
172187

173188

@@ -194,6 +209,7 @@ def set_pin_value(pin, value):
194209
Sets a GPIO pin value.
195210
"""
196211
GPIO.output(pin, value)
212+
set_pin_history(pin)
197213

198214

199215
def set_get_pin_value(pin, value):
@@ -205,6 +221,19 @@ def set_get_pin_value(pin, value):
205221
return get_pin_value(pin)
206222

207223

224+
def get_pin_history(pin):
225+
return gpio_pin_history[pin] or {"lastValue": None}
226+
227+
228+
def set_pin_history(pin):
229+
history = {"lastChange": datetime.datetime.now()}
230+
if not gpio_pin_history[pin]:
231+
gpio_pin_history[pin] = history
232+
233+
record = gpio_pin_history[pin]
234+
record.update(history)
235+
236+
208237
def setup_gpio():
209238
"""Sets up the GPIO pins
210239
@@ -236,15 +265,18 @@ def set_initial_state(pin):
236265
GPIO.output(pin, state)
237266

238267

239-
if __name__ == '__main__':
240-
log.info('Starting app at {}:{} (debug:{}). Version {}'.format(
241-
host, port, debug, __version__))
268+
if __name__ == "__main__":
269+
log.info(
270+
"Starting app at {}:{} (debug:{}). Version {}".format(
271+
host, port, debug, __version__
272+
)
273+
)
242274
try:
243275
setup_gpio()
244276
app.run(debug=debug, host=host, port=port)
245277
except Exception as e:
246-
log.error('Fatal application error occurred: {}'.format(e))
278+
log.error("Fatal application error occurred: {}".format(e))
247279
finally:
248-
log.debug('App is shutting down, cleaning up GPIO')
280+
log.debug("App is shutting down, cleaning up GPIO")
249281
GPIO.cleanup()
250-
log.info('GPIO has been cleaned up')
282+
log.info("GPIO has been cleaned up")

0 commit comments

Comments
 (0)