Esempio n. 1
0
    def test_encode_differences(self):
        colours = [Colour() for each in self.leds]
        colours[2] = Colour("#123456")
        colours[4] = Colour("#789abc")

        colours, leds = itf.encode_differences(self.colours_prev, colours,
                                               self.leds)

        assert colours == [Colour("#123456"), Colour("#789abc")]
        assert leds == [2, 4]
Esempio n. 2
0
 def clear_leds(self, verbose=False):
     if self.simulate:
         self.print_leds()
     else:
         self._send(('C'), verbose=verbose)
         self.apply_leds(verbose=verbose)
     self.led_colours = [Colour() for each in LEDS]
Esempio n. 3
0
    def draw_bbox(self, frame):
        frame = frame.copy()
        x_min, y_min, x_max, y_max = self.bbox

        if self.label is None: # if the tank is not marked yet
            # draw a thin white box
            colour = (255, 255, 255)
            box_thickness = 1
            cv2.rectangle(frame, (x_min, y_min), (x_max, y_max), colour, box_thickness)

        else:  # if the tank is marked
            if self.label == -1:  # no tank
                label_text = 'Not Tank'
                colour = (0, 0, 0)
                box_thickness = 1
                text_size = 0.5

            elif self.label == -2:  # tank on tank occlusion
                label_text = 'T-T Occ'
                colour = (0, 0, 255)
                box_thickness = 3
                text_size = 0.5

            else:  # the label is positive, meaning it is a proper tank
                label_text = 'ID: {}'.format(self.label)
                colour = Colour.choose_colour(self.label)
                box_thickness = 2
                text_size = 0.5

            text_colour = (255, 255, 255)
            cv2.rectangle(frame, (x_min, y_min), (x_max, y_max), colour, box_thickness)
            cv2.putText(frame, label_text, (x_min, y_min - 5), cv2.FONT_HERSHEY_SIMPLEX, text_size,
                        text_colour, 1, cv2.LINE_AA)

        return frame
Esempio n. 4
0
    def test_encode_groups_complex(self):
        colours = [Colour() for each in self.leds]
        colours[2] = Colour("#123456")
        colours[4] = Colour("#789abc")
        colours[5] = Colour("#789abc")
        colours[6] = Colour("#789abc")

        groups = itf.encode_groups(colours, self.leds)

        assert list(groups) == [
            (Colour(), [0, 1]),
            (Colour("#123456"), [2]),
            (Colour(), [3]),
            (Colour("#789abc"), [4, 5, 6]),
            (Colour(), [7, 8, 9]),
        ]
Esempio n. 5
0
def cloud_drift(
        arduino,
        sky_colour=Colour(0, 0, 0),
        leds=range(60),
        velocity=5,
):
    '''
    velocity: velocity of cloud shadow in LEDs / second
    '''
    CLOUD_WIDTH = 25

    start_position = leds[0] if velocity > 0 else leds[-1] + CLOUD_WIDTH

    cloud = Cloud(start_position, CLOUD_WIDTH, opacity=0.75)

    seconds = abs((len(leds) + CLOUD_WIDTH) / velocity)
    frames = int(ceil(FPS * seconds))

    print(seconds, frames)

    for each in range(frames):
        cloud.position += velocity / FPS

        colours = cloud.calc_colours(leds, sky_colour)
        arduino.set_leds_to_colours(colours, leds)

        time.sleep(1.0 / FPS)

    # restore sky to original colour
    arduino.set_leds_to_colours([sky_colour] * len(leds), leds)
Esempio n. 6
0
def handle_fade(json):
    global g

    colour_new = Colour(json['data'])
    # print(colour.rgb)

    get_arduino().fade_from_to(g['sky_colour'], colour_new, leds=LEDS, time=5.00)
    g['sky_colour'] = colour_new
Esempio n. 7
0
def handle_set(json):
    global g

    colour = Colour(json['data'])
    # print(colour.rgb)

    get_arduino().set_leds_to_colours([colour] * len(LEDS), LEDS)
    g['sky_colour'] = colour
Esempio n. 8
0
 def _line(self, pieces, line):
 
     if len(pieces) != 7:
         raise PartError, "Invalid line data in %s at line %i" % (self.path, line)
     
     colour = int(pieces[0])
     p1 = map(float, pieces[1:4])
     p2 = map(float, pieces[4:7])
     
     return Line(Colour(colour), Vector(*p1), Vector(*p2))
Esempio n. 9
0
 def _triangle(self, pieces, line):
 
     if len(pieces) != 10:
         raise PartError, "Invalid triangle data in %s at line %i" % (self.path, line)
     
     colour = int(pieces[0])
     p1 = map(float, pieces[1:4])
     p2 = map(float, pieces[4:7])
     p3 = map(float, pieces[7:10])
     
     return Triangle(Colour(colour), Vector(*p1), Vector(*p2), Vector(*p3))
Esempio n. 10
0
    def test_set_leds_to_colours(self, patched_send):
        # check compression happens correctly
        new_colours = [Colour() for each in range(10)]
        new_colours[2] = Colour("#123456")
        new_colours[4] = Colour("#789abc")
        new_colours[5] = Colour("#789abc")
        new_colours[6] = Colour("#789abc")

        self.arduino.set_leds_to_colours(new_colours, range(10))

        calls = [
            call(ANY, ('G', 2, 2, 148, 201, 86), verbose=ANY),
            call(ANY, ('G', 4, 6, 148, 92, 188), verbose=ANY),
            call(ANY, ('A'), verbose=ANY),
        ]
        patched_send.assert_has_calls(calls, any_order=False)

        # check that previous led colours are remembered
        patched_send.reset_mock()
        new_colours[2] = Colour()

        self.arduino.set_leds_to_colours(new_colours, range(10))

        calls = [
            call(ANY, ('G', 2, 2, 0, 0, 0), verbose=ANY),
            call(ANY, ('A'), verbose=ANY),
        ]
        patched_send.assert_has_calls(calls, any_order=False)
Esempio n. 11
0
 def _optional_line(self, pieces, line):
 
     if len(pieces) != 13:
         raise PartError, "Invalid line data in %s at line %i" % (self.path, line)
     
     colour = int(pieces[0])
     p1 = map(float, pieces[1:4])
     p2 = map(float, pieces[4:7])
     p3 = map(float, pieces[7:10])
     p4 = map(float, pieces[10:13])
     
     return OptionalLine(Colour(colour), Vector(*p1), Vector(*p2),
                                         Vector(*p3), Vector(*p4))
Esempio n. 12
0
 def _quadrilateral(self, pieces, line):
 
     if len(pieces) != 13:
         raise PartError, "Invalid quadrilateral data in %s at line %i" % (self.path, line)
     
     colour = int(pieces[0])
     p1 = map(float, pieces[1:4])
     p2 = map(float, pieces[4:7])
     p3 = map(float, pieces[7:10])
     p4 = map(float, pieces[10:13])
     
     return Quadrilateral(Colour(colour), Vector(*p1), Vector(*p2),
                                          Vector(*p3), Vector(*p4))
Esempio n. 13
0
    def test_encode(self):
        colours = [Colour() for each in self.leds]
        colours[2] = Colour("#123456")
        colours[4] = Colour("#789abc")
        colours[5] = Colour("#789abc")
        colours[6] = Colour("#789abc")

        groups = itf.encode(self.colours_prev, colours, self.leds)

        assert list(groups) == [
            (Colour("#123456"), [2]),
            (Colour("#789abc"), [4, 5, 6]),
        ]
Esempio n. 14
0
 def _subfile(self, pieces, line):
 
     if len(pieces) != 14:
         raise PartError, "Invalid part data in %s at line %i" % (self.path, line)
     
     colour = int(pieces[0])
     position = map(float, pieces[1:4])
     rows = [map(float, pieces[4:7]),
             map(float, pieces[7:10]),
             map(float, pieces[10:13])]
     part = pieces[13].upper()
     if part.endswith(".DAT"):
         part = part[:-4]
     
     return Piece(Colour(colour), Vector(*position), Matrix(rows), part)
Esempio n. 15
0
    def fade_from_to(
        self, colour_old, colour_new, leds: List[int] = LEDS, time=1.00, fps=10
    ):
        frames = int(ceil(fps * time))
        h_old, s_old, v_old = colour_old.hsv
        h_new, s_new, v_new = colour_new.hsv

        for h, s, v in zip(
            linspace(h_old, h_new, frames),
            linspace(s_old, s_new, frames),
            linspace(v_old, v_new, frames),
        ):
            # print(Colour().from_hsv(h, s, v).hsv)
            self.set_leds_to_colours([Colour().from_hsv(h, s, v)] * len(leds), leds)
            sleep(1.0 / fps)
Esempio n. 16
0
app = Flask(__name__)
app.config.from_object('config_default')
app.config.from_object('config')

if not app.config['SECRET_KEY']:
    raise ValueError(
        "Please set constant SECRET_KEY in 'app/config.py' for Flask application"
    )

effects.FPS = app.config['FPS']
PORT = app.config['PORT']
BAUD = app.config['BAUD']
LEDS = app.config['LEDS']

g = {'sky_colour': Colour(128, 128, 128)}

# turn the flask app into a socketio app
socketio = SocketIO(app, async_mode=None, logger=True, engineio_logger=True)


def get_arduino():
    global g

    if 'arduino' not in g:
        print(" *** Connecting to Arduino ***")
        g['arduino'] = Arduino()
        g['arduino'].connect(port=PORT, baud=BAUD, acknowledge=True)

    # for each in g:
    #     print(each)
Esempio n. 17
0
 def test_set_colour_block(self):
     self.arduino.set_colour_block(Colour("#12456"), range(10))
     assert hasattr(self.arduino, 'ser') is False
Esempio n. 18
0
 def test_set_leds_to_colours(self):
     new_colours = [Colour() for each in range(10)]
     self.arduino.set_leds_to_colours(new_colours, range(10))
     assert hasattr(self.arduino, 'ser') is False
Esempio n. 19
0
def lightning_flash(arduino, sky_colour=Colour(0, 0, 0), leds=range(60)):
    # Based on the Storm_Cloud Arduino sketch:

    flash_sequences = (
        [  # RGB
            Colour(255, 255, 255),  # white
            sky_colour,  # off
            Colour(100, 100, 150),  # slight blue
            sky_colour,  # off
            Colour(50, 50, 50),  # off
            sky_colour,  # off
            Colour(255, 255, 255),  # white
            sky_colour,  # off
            sky_colour,  # off
            sky_colour,  # off
            Colour(255, 120, 255),  # purple
        ],
        [
            Colour(100, 100, 150),  # slight blue
            sky_colour,  # off
            Colour(255, 255, 255),  # white
            sky_colour,  # off
            sky_colour,  # off
            Colour(255, 120, 255),  # purple
            sky_colour,  # off
            sky_colour,  # off
            Colour(255, 255, 255),  # white
            sky_colour,  # off
            Colour(50, 50, 50),  # off
        ],
        [
            Colour(255, 200, 120),  # orange
            sky_colour,  # off
            sky_colour,  # off
            sky_colour,  # off
            Colour(255, 255, 255),  # white
            sky_colour,  # off
            Colour(255, 120, 255),  # purple
            sky_colour,  # off
            Colour(50, 50, 50),  # off
            sky_colour,  # off
            Colour(200, 150, 100),  # slight orange
        ],
    )

    for i, each in enumerate(random.choice(flash_sequences)):
        arduino.set_leds_to_colours([each] * len(leds), leds)
        time.sleep(random.randrange(5, 100) / 1000)

    # restore sky to original colour
    arduino.set_leds_to_colours([sky_colour] * len(leds), leds)
Esempio n. 20
0
    def test_encode_groups_simple(self):
        groups = itf.encode_groups(self.colours_prev, self.leds)

        assert list(groups) == [(Colour(), list(range(10)))]
Esempio n. 21
0
class Arduino:
    block_until = 0
    led_colours = [Colour() for each in LEDS]
    simulate = False

    def connect(self, port=None, baud=9600, acknowledge=False, verbose=False):
        if verbose:
            print(f"Connecting to '{PORT}' at {baud} baud...")

        if port is None:
            self.simulate = True

        if self.simulate:
            print("Connected to Arduino (simulated)")
        else:
            self.ser = Serial(port, baud, timeout=5)

            try:
                if b'ready' in self.ser.readline():
                    if acknowledge:
                        self.clear_leds()
                return True
            except self.ser.SerialTimeoutException:
                print("Data could not be read")

    def disconnect(self):
        if self.simulate:
            print("Closing connection")
        else:
            if self.ser:
                self.ser.close()

    def print_leds(self):
        output = ''
        for colour in self.led_colours:
            output += stylize(" ", bg(colour.hex))

        print(output)

    def _send_str(self, command: bytes, verbose=False, read_nack=False):
        """
        Commands:
        C: clear all lights to black
        A: apply all lights as set
        R: set a specific LED to a RGB colour
        H: set a specific LED to a HSV colour
        """
        if verbose:
            print(f"Sending {command}")

        self.ser.write(command)

        # Read back negative acknowledge, will use timeout
        # Data only provide if command not recognised
        if read_nack:
            try:
                print("Reading...")
                print(self.ser.readline())
            except self.ser.SerialTimeoutException:
                print("Data could not be read")

    def _send(self, command: Tuple, verbose=False):
        """
        Convert a command-tuple to a command-string
        eg: (R, 255, 0, 128) -> b"R\xFF\x00\x80"
        """
        # wait for strip to write previous command before sending next command
        while now() < self.block_until:
            sleep(TIME_BETWEEN_CMDS)

        try:
            self._send_str(
                b'<' + bytes((ord(command[0]),) + command[1:]) + b'>', verbose=verbose
            )
        except TypeError:  # for command letter only with no parameters
            self._send_str(b'<' + bytes([ord(command[0])]) + b'>', verbose=verbose)

    def apply_leds(self, verbose=False):
        if self.simulate:
            self.print_leds()
        else:
            self._send(('A'), verbose=verbose)
            self.block_until = now() + TIME_BETWEEN_APPLIES

    def clear_leds(self, verbose=False):
        if self.simulate:
            self.print_leds()
        else:
            self._send(('C'), verbose=verbose)
            self.apply_leds(verbose=verbose)
        self.led_colours = [Colour() for each in LEDS]

    def set_colour_block(self, colour: Colour, leds: List[int] = LEDS, verbose=False):
        '''
        Sends commands directly over serial
        '''
        if self.simulate:
            pass
        else:
            led_min = leds[0]
            led_max = leds[-1]
            self._send(('G', led_min, led_max, *colour.hsv), verbose=verbose)

    def set_leds_to_colours(
        self, new_colours: List[Colour], leds: List[int] = LEDS, verbose=False
    ):
        '''
        Encodes LED commands to reduce serial communications
        '''
        groups = encode(self.led_colours, new_colours, leds)
        for c, l in groups:
            self.set_colour_block(c, l, verbose=verbose)

        # remember colours for next command
        for n, l in zip(new_colours, leds):
            self.led_colours[l] = n

        self.apply_leds(verbose=verbose)

    def fade_from_to(
        self, colour_old, colour_new, leds: List[int] = LEDS, time=1.00, fps=10
    ):
        frames = int(ceil(fps * time))
        h_old, s_old, v_old = colour_old.hsv
        h_new, s_new, v_new = colour_new.hsv

        for h, s, v in zip(
            linspace(h_old, h_new, frames),
            linspace(s_old, s_new, frames),
            linspace(v_old, v_new, frames),
        ):
            # print(Colour().from_hsv(h, s, v).hsv)
            self.set_leds_to_colours([Colour().from_hsv(h, s, v)] * len(leds), leds)
            sleep(1.0 / fps)
Esempio n. 22
0
 def setup(self):
     self.leds = range(10)
     self.colours_prev = [Colour() for each in self.leds]
Esempio n. 23
0
 def test_set_colour_block(self, patched_send):
     self.arduino.set_colour_block(Colour("#12456"), range(10))
     patched_send.assert_called_with(ANY, ('G', 0, 9, 76, 232, 69),
                                     verbose=ANY)