Skip to content
Snippets Groups Projects
Commit 591889c8 authored by bav6096's avatar bav6096
Browse files

refactored exceptions

parent e760468d
No related branches found
No related tags found
No related merge requests found
......@@ -4,32 +4,21 @@ import re
import importlib.resources
from . import animations
from visualising.exception import VisualiseException
class Animation:
def __init__(self, frames, frame_time, num_iter):
num_frames = len(frames)
source = "animation.py" # Name of the file that contains the Animation class definition.
if num_frames % 2 != 0:
raise ValueError("Number of frames must be even!")
def __init__(self, frames, frame_time, num_iter):
# Set frames, number of frames and number of ensembles.
try:
animation_len = len(frames)
except TypeError:
raise VisualiseException(source, "The animation is empty!")
if animation_len % 2 != 0:
raise VisualiseException(source, "Animation must contain an even number of frames!")
else:
for frame in frames:
try:
frame_len = len(frame)
except TypeError:
raise VisualiseException(source, "At least one frame is empty!")
num_values = len(frame)
if num_values != 48:
raise ValueError("All frames must have exactly 48 values!")
if frame_len != 48:
raise VisualiseException(source, "At least one frame doesn't have exactly 48 values!")
else:
is_numeric = True
is_positive = True
is_small = True
......@@ -40,46 +29,38 @@ class Animation:
is_small = is_small and value < 256
if not is_numeric:
raise VisualiseException(source, "Not all values in the animation are integers!")
elif not is_positive:
raise VisualiseException(source, "Not all values in the animation are positive!")
elif not is_small:
raise VisualiseException(source, "One or more values in the animation are to large!")
else:
raise TypeError("All frame values must be integers!")
if not is_positive:
raise ValueError("All frame values must be positive!")
if not is_small:
raise ValueError("All frame values must be smaller than 256!")
self.frames = frames
self.num_frames = animation_len
self.num_ensembles = int(animation_len / 2)
self.num_frames = num_frames
self.num_ensembles = int(num_frames / 2)
# Set frame time.
if not isinstance(frame_time, int):
raise VisualiseException(source, "Frame time must be an integer!")
elif frame_time < 0:
raise VisualiseException(source, "Frame time must be positive!")
elif frame_time > 4294967295:
raise VisualiseException(source, "Animation delay is to high!")
else:
raise TypeError("Frame time must be an integer!")
if not frame_time < 0:
raise ValueError("Frame time must be positive!")
if not frame_time > 4294967295:
raise ValueError("Frame time is to high!")
# The frame time is given in milliseconds.
self.frame_time = frame_time
# Set number of iterations.
if not isinstance(num_iter, int):
raise VisualiseException(source, "Number of iterations must be an integer!")
elif num_iter > 255:
raise VisualiseException(source, "Animation has to many iterations!")
elif num_iter <= 0:
raise VisualiseException(source, "Animation must have at least one iteration!")
else:
raise TypeError("Number of iterations must be an integer!")
if num_iter > 255:
raise ValueError("Animation has to many iterations!")
if num_iter <= 0:
raise ValueError("Animation must have at least one iteration!")
self.num_iter = num_iter
@staticmethod
def read_frames_from_file(filename):
try:
file = importlib.resources.open_text(animations, filename)
except AttributeError:
raise VisualiseException(source, "The file is incorrectly formatted!")
except FileNotFoundError:
raise VisualiseException(source, "The specified file does not exist!")
except TypeError:
raise VisualiseException(source, "No animation file was specified!")
animation = []
for line in file:
......@@ -100,23 +81,17 @@ class Animation:
@staticmethod
def set_pixel_color(ensemble, pixel, r, g, b):
try:
ensemble_len = len(ensemble)
except TypeError:
raise VisualiseException(source, "Ensemble is empty!")
if ensemble_len != 2:
raise VisualiseException(source, "Ensemble doesn't contain exactly two frames!")
else:
raise ValueError("Ensemble must contain exactly two frames!")
for frame in ensemble:
try:
frame_len = len(frame)
except TypeError:
raise VisualiseException(source, "At least one frame is empty!")
num_values = len(frame)
if num_values != 48:
raise ValueError("All frames must have exactly 48 values!")
if frame_len != 48:
raise VisualiseException(source, "At least one frame doesn't have exactly 48 values!")
else:
is_numeric = True
is_positive = True
is_small = True
......@@ -127,24 +102,21 @@ class Animation:
is_small = is_small and value < 256
if not is_numeric:
raise VisualiseException(source, "Not all values in the ensemble are integers!")
elif not is_positive:
raise VisualiseException(source, "Not all values in the ensemble are positive!")
elif not is_small:
raise VisualiseException(source, "One or more values in the ensemble are to large!")
else:
raise TypeError("All frame values must be integers!")
if not is_positive:
raise ValueError("All frame values must be positive!")
if not is_small:
raise ValueError("All frame values must be smaller than 256!")
if not isinstance(pixel, int):
raise TypeError("Pixel must be an integer!")
if not (0 < pixel < 33):
raise VisualiseException(source, "Pixel has to be in the range of 1 to 32!")
elif not (0 < r < 256):
raise VisualiseException(source, "Red channel value has to be in the range of 1 "
"to 255!")
elif not (0 < g < 256):
raise VisualiseException(source, "Green channel value has to be in the range of 1 "
"to 255!")
elif not (0 < b < 256):
raise VisualiseException(source, "Blue channel value has to be in the range of 1 "
"to 255!")
else:
raise ValueError("Pixel must be in the range of 1 to 32!")
if not (isinstance(r, int) and isinstance(g, int) and isinstance(b, int)):
raise TypeError("Color values must be integers!")
if not ((0 < r < 256) and (0 < g < 256) and (0 < b < 256)):
raise ValueError("Color values must be in the range of 1 to 255!")
if pixel < 16:
index = 0
else:
......
......@@ -4,57 +4,58 @@ import time
from visualising.message import FrameMsg, InstrMsg
from visualising.animation import Animation
from visualising.exception import VisualiseException
from visualising.connection import ArduinoException
class Arduino:
source = "arduino.py" # Name of the file that contains the Arduino class definition.
resend = 5 # Number of times a message is resend to the Arduino.
def __init__(self, connection):
self.connection = connection
# Creates one instruction messages and multiple frame messages to load an animation
# onto the Arduino.
def load_animation(self, animation):
if animation.num_ensembles > 16:
raise VisualiseException(source, "Animation hast to many frames!")
else:
try:
self.connection.confirm_msg(InstrMsg('A', animation).create_msg(), [b'\x0f'], resend)
except VisualiseException:
raise
for frame in animation.frames:
try:
self.connection.confirm_msg(FrameMsg(frame).create_msg(), [b'\x2f', b'\x3f'], resend)
except VisualiseException:
raise
# Creates instruction message and sends it to the Arduino,
# to play a loaded animation.
def start_playback(self):
try:
self.connection.confirm_msg(InstrMsg('B').create_msg(), [b'\x1f'], resend)
except VisualiseException:
raise
# Creates instruction message and sends it to the Arduino,
# to pause a playing animation.
def pause_playback(self):
try:
self.connection.confirm_msg(InstrMsg('C').create_msg(), [b'\x5f'], resend)
except VisualiseException:
raise
# Creates instruction message and sends it to the Arduino,
# to resume playback of a loaded animation.
def resume_playback(self):
try:
self.connection.confirm_msg(InstrMsg('D').create_msg(), [b'\x6f'], resend)
except VisualiseException:
raise
# Creates one instruction messages and multiple frame messages to load an animation
# onto the Arduino.
def load_animation(self, animation):
if animation.num_ensembles > 16:
raise ValueError("Animation has to many frames!")
else:
self.connection.confirm_msg(InstrMsg('A', animation).create_msg(), [b'\x0f'], resend)
for frame in animation.frames:
self.connection.confirm_msg(FrameMsg(frame).create_msg(), [b'\x2f', b'\x3f'], resend)
# First, an animation is loaded onto the Arduino. The playback of this
# animation is then started. In addition, it is checked whether the
# animation was played successfully.
def play_animation(self, animation):
self.load_animation(animation)
self.start_playback()
# Estimated playback time in seconds.
playback_time = animation.frame_time * animation.num_ensembles * 0.001
# Current time in seconds.
current_time = time.time()
while bytes(self.connection.receive_msg()) != bytes(b'\x4f'):
# Wait 10 times the estimated animation playback time for a response.
if time.time() > current_time + playback_time * 10:
raise ArduinoException("Successful playback of animation can't be confirmed!")
# Streams an animation to the Arduino. For this purpose, two frames of
# the animation are repeatedly sent to the Arduino. The Arduino plays
......@@ -64,11 +65,4 @@ class Arduino:
for _ in range(animation.num_iter):
for i in range(animation.num_ensembles):
ensemble = [animation.frames[2 * i + 0], animation.frames[2 * i + 1]]
self.load_animation(Animation(ensemble, animation.frame_time, 1))
self.start_playback()
curr_time = time.time() # Current time in milliseconds.
# Waits 10 times the animation delay for a response.
while bytes(self.connection.receive_msg()) != bytes(b'\x4F'):
if time.time() > curr_time + animation.frame_time / 100:
raise ArduinoException("P: -- ERROR -- Arduino is not responding!")
self.play_animation(Animation(ensemble, animation.frame_time, 1))
......@@ -7,22 +7,19 @@ from visualising.exception import VisualiseException
from serial.serialutil import SerialException
class Connection:
class ArduinoException(Exception):
def __init__(self, desc):
self.desc = desc
source = "connection.py" # Name of the file that contains the Connection class definition.
class Connection:
def __init__(self, port, baud):
self.connection = serial.Serial()
self.connection.port = port
self.connection.baudrate = baud
self.connection.timeout = 1
try:
self.connection.open() # Establishes a serial connection.
except SerialException:
raise VisualiseException(source, "No serial connection established!")
except FileNotFoundError:
raise VisualiseException(source, "The specified port does not exist!")
time.sleep(2) # Prevents errors regarding pyserial.
......@@ -78,29 +75,31 @@ class Connection:
# If the response is not as expected, try again as often as
# specified. In case any response wasn't even once one of the
# expected responses raise an exception.
def confirm_msg(self, msg, expected_responses, resend):
def confirm_msg(self, msg, expected_responses, num_resend):
def evaluate():
bool = resend > 0
bool = num_resend > 0
for element in expected_responses:
bool = bool and (bytes(element) != bytes(response))
return bool
if not isinstance(expected_responses, list):
raise VisualiseException(source, "Expected responses must be given as a list!")
elif not expected_responses:
raise VisualiseException(source, "There must be at least one expected response!")
elif not resend > 0:
raise VisualiseException(source, "Number of resends must be greater than zero!")
else:
raise TypeError("Expected responses must be given as a list!")
if not expected_responses:
raise ValueError("There must be at least one expected response!")
if not isinstance(num_resend, int):
raise TypeError("Number of resends must be an integer!")
if not num_resend > 0:
raise ValueError("Number of resends must be greater than zero!")
self.connection.send_msg(msg)
response = self.connection.receive_msg()
condition = evaluate()
while condition:
resend = resend - 1
num_resend = num_resend - 1
self.connection.send_msg(msg)
response = self.connection.receive_msg()
condition = evaluate()
if not resend > 0:
raise VisualiseException("Arduino", Connection.translate_msg(response))
if not num_resend > 0:
raise ArduinoException(Connection.translate_msg(response))
#!/usr/bin/env python
class Error(Exception):
pass
class VisualiseException(Error):
def __init__(self, source, description):
self.source = source
self.description = description
#!/usr/bin/env python
import rospy
from monitoring.watchdog import Watchdog
from visualising.exception import *
from visualising.arduino import Arduino
from visualising.connection import Connection
from visualising.connection import Connection, ArduinoException
from visualising.animation import Animation
......@@ -40,9 +40,6 @@ class Visualiser:
else:
self.stream_animation(happy)
def info_mode(self):
print("Hallo!")
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment