# Path: fluxghost/api/misc.py
# class BinaryUploadHelper(object):
#     def __init__(self, length, callback, *args, **kwargs):
#         self.length = length
#         self.callback = callback
#         self.buf = BytesIO()
#         self.buffered = 0
# 
#         self.args = args
#         self.kwargs = kwargs
# 
#         self.last_update = time()
# 
#     def feed(self, buf):
#         l = self.buf.write(buf)
#         self.buffered += l
#         self.last_update = time()
# 
#         if self.buffered < self.length:
#             return False
#         elif self.buffered == self.length:
#             self.callback(self.buf.getvalue(), *self.args, **self.kwargs)
#             return True
#         else:
#             raise RuntimeError("BAD_LENGTH" + " recive too many binary data ("
#                                "should be %i but get %i" %
#                                (self.length, self.buffered),
#                                "recive too many binary data ("
#                                "should be %i but get %i" %
#                                (self.length, self.buffered))
# 
# class BinaryHelperMixin(object):
#     _binary_helper = None
# 
#     def has_binary_helper(self):
#         return self._binary_helper is not None
# 
#     def set_binary_helper(self, helper):
#         self._binary_helper = helper
# 
#     def on_binary_message(self, buf):
#         try:
#             if self._binary_helper:
#                 if self._binary_helper.feed(buf) is True:
#                     self._binary_helper = None
#             else:
#                 raise RuntimeError("BAD_PROTOCOL", "no binary accept")
#         except RuntimeError as e:
#             logger.error(e)
#             self.send_fatal(e.args[0])
# 
# class OnTextMessageMixin(object):
#     def on_text_message(self, message):
#         try:
#             if not self.has_binary_helper():
#                 message = message.rstrip().split(maxsplit=1)
#                 if len(message) == 1:
#                     cmd = message[0]
#                     params = ''
#                 else:
#                     cmd = message[0]
#                     params = message[1]
# 
#                 if cmd in self.cmd_mapping:
#                     self.cmd_mapping[cmd][0](params,
#                                              *self.cmd_mapping[cmd][1:])
#                 else:
#                     logger.exception("Received message: %s" % (message))
#                     raise ValueError('Undefined Command %s' % (cmd))
#             else:
#                 logger.exception("Received Message: %s" % (message))
#                 raise RuntimeError("PROTOCOL_ERROR", "under uploading mode")
# 
#         except ValueError:
#             logger.exception("Received Message: %s" % (message))
#             self.send_json(status='Error', message='BAD_PARAM_TYPE')
# 
#         except RuntimeError as e:
#             logger.exception("Received Message: %s" % (message))
#             self.send_fatal(e.args[0])


from time import time
from fluxclient.toolpath.bitmap_factory import BitmapImage, BitmapFactory
from fluxclient.toolpath.laser import bitmap2laser, laserCalibration
from fluxclient.toolpath import FCodeV1MemoryWriter, GCodeMemoryWriter
from .misc import BinaryUploadHelper, BinaryHelperMixin, OnTextMessageMixin
import logging
                length, complete, (width, height), (x1, y1), (x2, y2),
                rotation, thres)
            self.set_binary_helper(helper)
            self.send_json(status="continue")

        def cmd_set_fcode_metadata(self, params):
            key, value = params.split()
            logger.info('Set fcode metadata {}'.format(key))
            self.fcode_metadata[key] = value
            self.send_ok()

    return BitmapBaseApi


def laser_bitmap_api_mixin(cls):
    class LaserBitmapApi(OnTextMessageMixin, bitmap_base_api_mixin(cls)):
        one_way = True
        calibration = False
        object_height = 0.0
        height_offset = 0.0
        engraving_speed = 0
        max_engraving_strength = 1.0

        def __init__(self, *args):
            super().__init__(*args)
            self.cmd_reset()
            self.cmd_mapping = {
                'upload': [self.cmd_upload_bitmap],
                'go': [self.cmd_process],
                'set_params': [self.cmd_set_params],

# Path: fluxghost/api/misc.py
# class BinaryUploadHelper(object):
#     def __init__(self, length, callback, *args, **kwargs):
#         self.length = length
#         self.callback = callback
#         self.buf = BytesIO()
#         self.buffered = 0
# 
#         self.args = args
#         self.kwargs = kwargs
# 
#         self.last_update = time()
# 
#     def feed(self, buf):
#         l = self.buf.write(buf)
#         self.buffered += l
#         self.last_update = time()
# 
#         if self.buffered < self.length:
#             return False
#         elif self.buffered == self.length:
#             self.callback(self.buf.getvalue(), *self.args, **self.kwargs)
#             return True
#         else:
#             raise RuntimeError("BAD_LENGTH" + " recive too many binary data ("
#                                "should be %i but get %i" %
#                                (self.length, self.buffered),
#                                "recive too many binary data ("
#                                "should be %i but get %i" %
#                                (self.length, self.buffered))
# 
# class BinaryHelperMixin(object):
#     _binary_helper = None
# 
#     def has_binary_helper(self):
#         return self._binary_helper is not None
# 
#     def set_binary_helper(self, helper):
#         self._binary_helper = helper
# 
#     def on_binary_message(self, buf):
#         try:
#             if self._binary_helper:
#                 if self._binary_helper.feed(buf) is True:
#                     self._binary_helper = None
#             else:
#                 raise RuntimeError("BAD_PROTOCOL", "no binary accept")
#         except RuntimeError as e:
#             logger.error(e)
#             self.send_fatal(e.args[0])
# 
# class OnTextMessageMixin(object):
#     def on_text_message(self, message):
#         try:
#             if not self.has_binary_helper():
#                 message = message.rstrip().split(maxsplit=1)
#                 if len(message) == 1:
#                     cmd = message[0]
#                     params = ''
#                 else:
#                     cmd = message[0]
#                     params = message[1]
# 
#                 if cmd in self.cmd_mapping:
#                     self.cmd_mapping[cmd][0](params,
#                                              *self.cmd_mapping[cmd][1:])
#                 else:
#                     logger.exception("Received message: %s" % (message))
#                     raise ValueError('Undefined Command %s' % (cmd))
#             else:
#                 logger.exception("Received Message: %s" % (message))
#                 raise RuntimeError("PROTOCOL_ERROR", "under uploading mode")
# 
#         except ValueError:
#             logger.exception("Received Message: %s" % (message))
#             self.send_json(status='Error', message='BAD_PARAM_TYPE')
# 
#         except RuntimeError as e:
#             logger.exception("Received Message: %s" % (message))
#             self.send_fatal(e.args[0])


# Path: fluxghost/api/bitmap_toolpath.py
from time import time
from fluxclient.toolpath.bitmap_factory import BitmapImage, BitmapFactory
from fluxclient.toolpath.laser import bitmap2laser, laserCalibration
from fluxclient.toolpath import FCodeV1MemoryWriter, GCodeMemoryWriter
from .misc import BinaryUploadHelper, BinaryHelperMixin, OnTextMessageMixin
import logging

                length, complete, (width, height), (x1, y1), (x2, y2),
                rotation, thres)
            self.set_binary_helper(helper)
            self.send_json(status="continue")

        def cmd_set_fcode_metadata(self, params):
            key, value = params.split()
            logger.info('Set fcode metadata {}'.format(key))
            self.fcode_metadata[key] = value
            self.send_ok()

    return BitmapBaseApi


def laser_bitmap_api_mixin(cls):
    class LaserBitmapApi(OnTextMessageMixin, bitmap_base_api_mixin(cls)):
        one_way = True
        calibration = False
        object_height = 0.0
        height_offset = 0.0
        engraving_speed = 0
        max_engraving_strength = 1.0

        def __init__(self, *args):
            super().__init__(*args)
            self.cmd_reset()
            self.cmd_mapping = {
                'upload': [self.cmd_upload_bitmap],
                'go': [self.cmd_process],
                'set_params': [self.cmd_set_params],

                'clear_imgs': [self.cmd_reset],