Skip to content

Commit

Permalink
Merge pull request #3 from bencobley/charlie
Browse files Browse the repository at this point in the history
Charlie
  • Loading branch information
bencobley committed Jun 2, 2020
2 parents b81dd69 + d75f9ed commit a1a5f0a
Show file tree
Hide file tree
Showing 24 changed files with 2,065 additions and 322 deletions.
30 changes: 23 additions & 7 deletions API.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,13 @@ def index():
logger.debug("set_chosen_labels called")
return bot.set_chosen_labels(request.form["value"])

if request.form["action"] == "set_active_label":
logger.debug("set_active_label called")
return bot.set_active_label(request.form["value"])
if request.form["action"] == "set_label":
logger.debug("set_label called")
return bot.set_label(request.form["value"])

if request.form["action"] == "set_no_label":
logger.debug("set_no_label called")
return bot.set_no_label()

if request.form["action"] == "set_active_model":
logger.debug("set_active_model called")
Expand All @@ -77,6 +81,10 @@ def index():
logger.debug("set_temperature_target called")
return bot.set_temperature_target(request.form["value"])

if request.form["action"] == "set_temperature_hold":
logger.debug("set_temperature_hold called")
return bot.set_temperature_hold()

if request.form["action"] == "set_hob_off":
logger.debug("set_hob_off called")
return bot.set_hob_off()
Expand All @@ -101,9 +109,9 @@ def index():
logger.debug("set_pid_reset called")
return bot.set_pid_reset()

if request.form["action"] == "set_camera_sleep":
logger.debug("set_camera_sleep called")
return bot.set_camera_sleep(request.form["value"])
if request.form["action"] == "set_frame_interval":
logger.debug("set_frame_interval called")
return bot.set_frame_interval(request.form["value"])

if request.form["action"] == "get_all_labels":
logger.debug("get_all_labels called")
Expand All @@ -113,8 +121,16 @@ def index():
logger.debug("get_all_models called")
return bot.get_all_models()

if request.form["action"] == "pi-restart":
os.system("sudo reboot")

if request.form["action"] == "pi-shutdown":
os.system("sudo shutdown now")

if request.form["action"] == "restart":
os.system(". ~/onionbot/runonion")

if request.form["action"] == "quit":
logger.debug("quit called")
bot.quit()
logger.info("Shutting down server")
server_quit = request.environ.get("werkzeug.server.shutdown")
Expand Down
100 changes: 100 additions & 0 deletions classification.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
from edgetpu.classification.engine import ClassificationEngine
from edgetpu.utils import dataset_utils
from PIL import Image
from threading import Thread, Event
from queue import Queue, Empty


import logging

logger = logging.getLogger(__name__)


class Classify(object):
"""Save image to file"""

def __init__(self):

self.tests = {
"pasta": {
"labels": dataset_utils.read_label_file("models/pasta.txt"),
"model": ClassificationEngine("models/pasta.tflite"),
"threshold": 0.8,
},
"sauce": {
"labels": dataset_utils.read_label_file("models/sauce.txt"),
"model": ClassificationEngine("models/sauce.tflite"),
"threshold": 0.8,
},
"pan_on_off": {
"labels": dataset_utils.read_label_file("models/pan_on_off.txt"),
"model": ClassificationEngine("models/pan_on_off.tflite"),
"threshold": 0.5,
},
}

self.quit_event = Event()
self.file_queue = Queue()
self.data = None

def _worker(self):

logger.info("Initialising upload worker")

while True:
try: # Timeout raises queue.Empty

image = self.file_queue.get(block=True, timeout=0.1)
image = Image.open(image)

output = {}

for name, t in self.tests.items():

logger.info("Starting test %s " % (name))

engine = t["model"]
labels = t["labels"]
threshold = t["threshold"]

result = engine.classify_with_image(
image, top_k=1, threshold=threshold
)
logger.info(result)

try:
result = result[0]
output[name] = {
"label": labels[result[0]],
"confidence": str(result[1]),
}
except TypeError:
logger.info("TypeError")
except IndexError:
logger.info("IndexError")
logger.info(output)
self.data = output
self.file_queue.task_done()

except Empty:
if self.quit_event.is_set():
logger.info("Quitting thread...")
break

def start(self, file_path):
logger.info("Calling start")
self.file_queue.put(file_path)

def join(self):
logger.info("Calling join")
self.file_queue.join()

def launch(self):
logger.info("Initialising worker")
self.thread = Thread(target=self._worker, daemon=True)
self.thread.start()

def quit(self):
self.quit_event.set()
logger.info("Waiting for classification thread to finish uploading")
self.thread.join()
39 changes: 26 additions & 13 deletions cloud.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import os
from os import environ, path
from google.cloud import storage
from threading import Thread, Event
from queue import Queue, Empty
Expand All @@ -7,9 +7,10 @@

logger = logging.getLogger(__name__)

os.environ["GOOGLE_APPLICATION_CREDENTIALS"] = "/home/pi/onionbot-819a387e4e79.json"
environ["GOOGLE_APPLICATION_CREDENTIALS"] = "/home/pi/onionbot-819a387e4e79.json"

BUCKET_NAME = "onionbucket" # NOTE: Hard coded in data file
BUCKET = "onion_bucket"
PATH = path.dirname(__file__)


class Cloud(object):
Expand All @@ -22,22 +23,24 @@ def __init__(self):
self.quit_event = Event()
self.thermal_file_queue = Queue()
self.camera_file_queue = Queue()
self.bucket = BUCKET

def _camera_worker(self):

logger.debug("Initialising upload worker for camera")

client = storage.Client()
bucket = client.get_bucket(BUCKET_NAME)
bucket = client.get_bucket(BUCKET)

while True:
try: # Timeout raises queue.Empty
path = self.camera_file_queue.get(block=True, timeout=0.1)
local_path = self.camera_file_queue.get(block=True, timeout=0.1)
cloud_path = local_path.replace(PATH + "/" + BUCKET + "/", "")

blob = bucket.blob(path)
blob.upload_from_filename(path)
blob = bucket.blob(cloud_path)
blob.upload_from_filename(local_path)
blob.make_public()
logger.debug("Uploaded camera file to cloud: %s" % (path))
logger.debug("Uploaded camera file to cloud: %s" % (local_path))
logger.debug("Blob is publicly accessible at %s" % (blob.public_url))

self.camera_file_queue.task_done()
Expand Down Expand Up @@ -65,16 +68,17 @@ def _thermal_worker(self):
logger.debug("Initialising upload worker for thermal")

client = storage.Client()
bucket = client.get_bucket(BUCKET_NAME)
bucket = client.get_bucket(BUCKET)

while True:
try: # Timeout raises queue.Empty
path = self.thermal_file_queue.get(block=True, timeout=0.1)
local_path = self.thermal_file_queue.get(block=True, timeout=0.1)
cloud_path = local_path.replace(PATH + "/" + BUCKET + "/", "")

blob = bucket.blob(path)
blob.upload_from_filename(path)
blob = bucket.blob(cloud_path)
blob.upload_from_filename(local_path)
blob.make_public()
logger.debug("Uploaded to cloud: %s" % (path))
logger.debug("Uploaded thermal file to cloud: %s" % (local_path))
logger.debug("Blob is publicly accessible at %s" % (blob.public_url))

self.thermal_file_queue.task_done()
Expand All @@ -97,6 +101,15 @@ def launch_thermal(self):
self.thermal_thread = Thread(target=self._thermal_worker, daemon=True)
self.thermal_thread.start()

def get_public_path(self, local_path):
if local_path:
local_path = local_path.replace(PATH + "/", "")
cloud_location = "https://storage.googleapis.com"

return f"{cloud_location}/{local_path}"
else:
return None

def quit(self):
self.quit_event.set()
logger.debug("Waiting for camera cloud thread to finish uploading")
Expand Down
9 changes: 1 addition & 8 deletions config.json
Original file line number Diff line number Diff line change
@@ -1,8 +1 @@
{
"camera_sleep": 0,
"Kp": 0.5,
"Ki": 0,
"Kd": 0,
"sample_time": 0.01,
"output_limit": 100
}
{"frame_interval": "10", "Kp": 1.5, "Ki": 0.03, "Kd": 0.0, "sample_time": 0.01, "output_limit": 75}
5 changes: 2 additions & 3 deletions config.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import json
from os import path

FILE = path.dirname(__file__) + "/config.json"
FILE = "/home/pi/onionbot/config.json"


class Config(object):
Expand All @@ -24,7 +23,7 @@ def set_config(self, key, value):

# Close file then dump new version of config
json_data_file.close()
with open("config.json", "w") as outfile:
with open(FILE, "w") as outfile:
json.dump(config, outfile)
else:
raise KeyError("Config key not found")
16 changes: 12 additions & 4 deletions control.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
knob = Knob()


DEADBAND_THRESHOLD = 5
DEADBAND_THRESHOLD = 0


class Control(object):
Expand All @@ -48,12 +48,13 @@ def __init__(self):
"servo_achieved": None,
"servo_achieved_history": None,
"temperature_target": None,
"pid_enabled": None,
"p_coefficient": None,
"i_coefficient": None,
"d_coefficient": None,
"p_component": None,
"i_component": None,
"d_component": None,
"p_component": 0,
"i_component": 0,
"d_component": 0,
}

def _worker(self):
Expand Down Expand Up @@ -98,6 +99,13 @@ def update_temperature_target(self, setpoint):
self.set_pid_enabled(True)
self.fixed_setpoint = None

def hold_temperature(self):
setpoint = str(self.temperature)
logger.debug("Updating self.temperature_target to hold at %s degrees " % (setpoint))
self.temperature_target = float(setpoint)
self.set_pid_enabled(True)
self.fixed_setpoint = None

def set_pid_enabled(self, enabled):
pid.set_is_enabled(enabled, last_output=knob.get_setpoint())

Expand Down
Loading

0 comments on commit a1a5f0a

Please sign in to comment.