示例#1
0
        self.matrix = self._transpose_matrix(new_matrix)

    def iterate(self):
        """Perform one iteration of Jacobi's method."""
        row, column, theta = self._select_pivot()
        srot, crot = sin(theta), cos(theta)
        # update columns according to the rotation
        self._rotate_column(row, column, srot, crot)
        # update rows according to the rotation
        self._rotate_row(row, column, srot, crot)
        return self.theta()


JACOBI = JacobiIteration()

# create the Timebox object
TIMEBOX = TimeBox()
# open the connection to the Timebox
TIMEBOX.connect()

while True:
    JACOBI.randomize_matrix()

    THETA = 1
    while abs(THETA) > 0.05:
        THETA = JACOBI.iterate()
        IMAGE = JACOBI.as_image()
        TIMEBOX.set_static_image(IMAGE)
        sleep(0.5)
        TIMEBOX.clear_input_buffer()
示例#2
0
class TimeBoxNotificationService(BaseNotificationService):
    """Implement the notification service for TimeBox."""
    def __init__(self, mac, image_dir):
        from timebox import TimeBox
        self._mac = mac
        self._image_dir = image_dir
        self._timebox = TimeBox()
        self._timebox.connect(host=mac)
        if not os.path.isdir(image_dir):
            _LOGGER.error(
                "image_dir {0} does not exist, timebox will not work".format(
                    image_dir))
        from timeboximage import TimeBoxImage
        self._state_image = TimeBoxImage()
        self.display_image_file('ha-logo')

    def display_image_file(self, fn):
        image_data = self.load_image_file(fn)
        if image_data is not None:
            self.display_image(image_data)

    def display_image(self, image_data):
        if self.valid_image(image_data):
            from timeboximage import TimeBoxImage
            image = TimeBoxImage()
            image.image = image_data
            self._timebox.set_static_image(image)
        else:
            _LOGGER.error("Invalid image data received")

    def valid_color(self, color):
        """Verifies a color is valid
        (Array of three ints, range 0-15)"""
        valid = False
        if (isinstance(color, list) and len(color) == 3):
            valid = True
            for chan in color:
                valid = valid and (0 <= chan <= 15)
        if not valid:
            _LOGGER.warn("{0} was not a valid color".format(color))
        return valid

    def valid_image(self, image):
        """Verifies an image array is valid.
        An image should consist of a 2D array, 11x11. Each array
        element is again an arry, containing a valid colour
        (see valid_color())."""
        valid = False
        if (isinstance(image, list) and len(image) == 11):
            valid = True
            for row in image:
                if (isinstance(row, list) and len(row) == 11):
                    for pixel in row:
                        if not self.valid_color(pixel):
                            valid = False
                            break
                else:
                    valid = False
                    break
        if not valid:
            _LOGGER.error("Invalid image data received")
        return valid

    def load_image_file(self, image_file_name):
        """Loads image data from a file and returns it."""
        fn = os.path.join(self._image_dir, "{0}.json".format(image_file_name))
        try:
            fh = open(fn)
        except:
            _LOGGER.error("Unable to open {0}".format(fn))
            return None
        try:
            image = json.load(fh)
            return image
        except Exception as e:
            _LOGGER.error(
                "{0} does not contain a valid image in JSON format".format(fn))
            _LOGGER.error(e)
            return None

    def convert_color(self, color):
        """We expect all colors passed in to be in the range 0-15.
        But some parts of the timebox API expect 0-255. This function
        converts a passed in color array to something the API can
        work with. Does not do validation itself."""
        return [color[0] * 16, color[1] * 16, color[2] * 16]

    def send_message(self, message="", **kwargs):
        if kwargs.get(ATTR_DATA) is None:
            _LOGGER.error("Service call needs a message type")
            return False
        data = kwargs.get(ATTR_DATA)
        mode = data.get(PARAM_MODE)
        # HA used to internally cast "off" to a boolean False.
        # Apparently it doesn't any more?
        if mode == False or mode == 'off':
            self.display_image_file('blank')

        elif mode == "clock":
            color = data.get(PARAM_COLOR)
            if self.valid_color(color):
                color = self.convert_color(color)
            else:
                color = [255, 255, 255]
            self._timebox.show_clock(color=color)

        elif mode == "temp":
            color = data.get(PARAM_COLOR)
            if self.valid_color(color):
                color = self.convert_color(color)
            else:
                color = [255, 255, 255]
            self._timebox.show_temperature(color=color)

        elif mode == "image":
            image_data = data.get(PARAM_IMAGE)
            self.display_image(image_data)

        elif mode == "image-file":
            image_filename = data.get(PARAM_FILE_NAME)
            self.display_image_file(image_filename)

        elif mode == "sync-clock":
            dt = datetime.datetime.now()
            head = [
                0x0A, 0x00, 0x18, dt.year % 100,
                int(dt.year / 100), dt.month, dt.day, dt.hour, dt.minute,
                dt.second
            ]
            self._timebox.send_payload(head)

        elif mode == "show-states":
            self._timebox.set_static_image(self._state_image)

        elif mode == "set-state":
            color = data.get(PARAM_COLOR)
            x = data.get(PARAM_X)
            y = data.get(PARAM_Y)
            show_state = data.get(PARAM_SHOW_STATE)
            self._state_image.put_pixel(x, y, color[0], color[1], color[2])
            if show_state == True:
                self._timebox.set_static_image(self._state_image)

        elif mode == "set-state-lerp":
            x = data.get(PARAM_X)
            x = int(x)
            y = data.get(PARAM_Y)
            y = int(y)
            _LOGGER.info("x: " + str(x) + " y:" + str(y))
            start_color = data.get(PARAM_START_COLOR)
            end_color = data.get(PARAM_END_COLOR)
            start_color = [int(x) for x in start_color]
            end_color = [int(x) for x in end_color]

            value = data.get(PARAM_VALUE)
            value = float(value)
            min_value = data.get(PARAM_MIN_VALUE)
            min_value = float(min_value)
            max_value = data.get(PARAM_MAX_VALUE)
            max_value = float(max_value)
            _LOGGER.debug("val: " + str(value) + " min:" + str(min_value) +
                          " max:" + str(max_value))
            _LOGGER.debug("start_col: " + str(start_color) + " end: " +
                          str(end_color))

            show_state = data.get(PARAM_SHOW_STATE)
            color = calculate_lerp_color(start_color, end_color, value,
                                         min_value, max_value)
            _LOGGER.info("calc_col: " + str(color))

            self._state_image.put_pixel(x, y, color[0], color[1], color[2])
            if show_state == True or show_state.lower() == "true":
                self._timebox.set_static_image(self._state_image)

        elif mode == "animation":
            # TODO
            pass

        else:
            _LOGGER.error(
                "Invalid mode '{0}', must be one of 'off', 'clock', 'temp', 'image', 'animation'"
                .format(mode))
            return False

        return True