<commit_before>from recorder.recorderapp import RecorderApp
from recorder.redisindexer import WritableRedisIndexer

from recorder.warcwriter import MultiFileWARCWriter, SimpleTempWARCWriter
from recorder.filters import SkipDupePolicy
from recorder.filters import ExcludeSpecificHeaders

import redis
import time
import json
import glob

from webagg.utils import res_template, ParamFormatter, StreamIter, chunk_encode_iter

from bottle import Bottle, request, debug, response
import os
import shutil
from six import iteritems

import gevent

# ============================================================================
class WebRecRecorder(object):
    def __init__(self, config=None):
        self.upstream_url = os.environ['WEBAGG_HOST']

        self.record_root_dir = os.environ['RECORD_ROOT']

        self.warc_path_templ = config['file_path_templ']
        self.warc_path_templ = self.record_root_dir + self.warc_path_templ

        self.cdxj_key_templ = config['cdxj_key_templ']

        self.rec_page_key_templ = config['r_page_key_templ']

        self.info_keys = config['info_key_templ']

        self.warc_key_templ = config['warc_key_templ']

        self.warc_rec_prefix = config['warc_name_prefix']
        self.warc_name_templ = config['warc_name_templ']

        self.full_warc_prefix = config['full_warc_prefix']

        self.name = config['recorder_name']

        self.del_templ = config['del_templ']

        self.skip_key_templ = config['skip_key_templ']

        self.redis_base_url = os.environ['REDIS_BASE_URL']
        self.redis = redis.StrictRedis.from_url(self.redis_base_url)

        self.app = Bottle()
        self.recorder = self.init_recorder()

        self.app.mount('/record', self.recorder)
        self.app.get('/download', callback=self.download)
        debug(True)

        gevent.spawn(self.delete_listen_loop)

    def init_recorder(self):
        self.dedup_index = WebRecRedisIndexer(
            name=self.name,
            redis=self.redis,

            cdx_key_template=self.cdxj_key_templ,
            file_key_template=self.warc_key_templ,
            rel_path_template=self.warc_path_templ,

            full_warc_prefix=self.full_warc_prefix,

            dupe_policy=SkipDupePolicy(),

            size_keys=self.info_keys.values(),
            rec_info_key_templ=self.info_keys['rec'],
        )

        header_filter = ExcludeSpecificHeaders(['Set-Cookie', 'Cookie'])

        writer = SkipCheckingMultiFileWARCWriter(dir_template=self.warc_path_templ,
                                     filename_template=self.warc_name_templ,
                                     dedup_index=self.dedup_index,
                                     redis=self.redis,
                                     skip_key_templ=self.skip_key_templ,
                                     header_filter=header_filter)

        self.writer = writer
        recorder_app = RecorderApp(self.upstream_url,
                                   writer,
                                   accept_colls='live')

        return recorder_app

    def get_pagelist(self, user, coll, rec):
        page_key_pattern = self.rec_page_key_templ.format(user=user, coll=coll, rec=rec)

        pages = []
        for page_key in self.redis.scan_iter(match=page_key_pattern):
            for page in self.redis.hvals(page_key):
                pages.append(json.loads(page.decode('utf-8')))

        return pages

    def download(self):
        user = request.query.get('user', '')
        coll = request.query.get('coll', '*')
        rec = request.query.get('rec', '*')
        type = request.query.get('type')

        filename = request.query.get('filename', 'rec.warc.gz')

        #if not user:
        #    response.status = 400
        #    return {'error_message': 'No User Provided'}

        templ = self.warc_path_templ + '*.warc.gz'
        warcs = list(glob.glob(templ.format(user=user, coll=coll, rec=rec)))

        metadata = {'pages': self.get_pagelist(user, coll, rec)}

        part_of = coll
        if rec != '*':
            part_of += '/' + rec

        # warcinfo Record
        info = {'software': 'Webrecorder Platform v2.0',
                'format': 'WARC File Format 1.0',
                'json-metadata': json.dumps(metadata),
                'isPartOf': part_of,
                'creator': user,
               }

        title = request.query.get('rec_title')
        if title:
            info['title'] = title

        coll_title = request.query.get('coll_title')
        if coll_title:
            info['isPartOf'] = coll_title

        wi_writer = SimpleTempWARCWriter()
        wi_writer.write_record(wi_writer.create_warcinfo_record(filename, **info))
        warcinfo = wi_writer.get_buffer()

        key_templ = self.info_keys.get(type, '')
        key_pattern = key_templ.format(user=user, coll=coll, rec=rec)

        length = len(warcinfo)
        try:
            length += int(self.redis.hget(key_pattern, 'size'))
        except Exception as e:
            print(e)

        def read_all(warcinfo):
            yield warcinfo

            for warc in warcs:
                with open(warc, 'rb') as fh:
                    for chunk in StreamIter(fh):
                        yield chunk

        response.headers['Content-Type'] = 'application/octet-stream'
        response.headers['Content-Length'] = int(length)
        resp = read_all(warcinfo)
        #response.headers['Transfer-Encoding'] = 'chunked'
        #resp = chunk_encode_iter(resp)
        return resp

    def delete_listen_loop(self):
        self.pubsub = self.redis.pubsub()
        self.pubsub.subscribe('delete')

        print('Waiting for delete messages')

        for item in self.pubsub.listen():
            try:
                if item['type'] == 'message' and item['channel'] == b'delete':
                    self.handle_delete(item['data'].decode('utf-8'))
            except:
                import traceback
                traceback.print_exc()

    def handle_delete(self, data):
        data = json.loads(data)

        user = data['user']
        coll = data['coll']
        rec = data['rec']
        type = data['type']

        try:
            self.delete_files(type, user, coll, rec)
        except:
            import traceback
            traceback.print_exc()

        try:
            self.delete_redis_keys(type, user, coll, rec)
        except:
            import traceback
            traceback.print_exc()

    def delete_files(self, type, user, coll, rec):
        if type not in (('user', 'coll', 'rec')):
            print('Unknown delete type ' + str(type))
            return

        glob_path = self.warc_path_templ.format(user=user, coll=coll, rec=rec)

        for dirname in glob.glob(glob_path):
            self.recorder.writer.close_dir(dirname)

        if glob_path.endswith('/'):
            glob_path = os.path.dirname(glob_path)

        if type == 'rec':
            dir_to_delete = glob_path
        elif type == 'coll':
            dir_to_delete = os.path.dirname(glob_path)
        elif type == 'user':
            dir_to_delete = os.path.dirname(os.path.dirname(glob_path))

        try:
            print('Deleting Files in ' + dir_to_delete)
            shutil.rmtree(dir_to_delete)
        except Exception as e:
            print(e)

    def delete_redis_keys(self, type, user, coll, rec):
        key_templ = self.del_templ.get(type)
        if not key_templ:
            print('Unknown delete type ' + str(type))
            return

        key_pattern = key_templ.format(user=user, coll=coll, rec=rec)
        keys_to_del = list(self.redis.scan_iter(match=key_pattern))

        if type == 'rec':
            self._delete_rec_warc_key(user, coll, rec)
            self._delete_decrease_size(user, coll, rec)

        with redis.utils.pipeline(self.redis) as pi:
            for key in keys_to_del:
                pi.delete(key)

    def _delete_rec_warc_key(self, user, coll, rec):
        warc_key = self.warc_key_templ.format(user=user, coll=coll, rec=rec)
        allwarcs = self.redis.hgetall(warc_key)

        warc_rec_prefix = self.warc_rec_prefix.format(user=user, coll=coll, rec=rec)

        with redis.utils.pipeline(self.redis) as pi:
            for n, v in iteritems(allwarcs):
                n = n.decode('utf-8')
                if n.startswith(warc_rec_prefix):
                    pi.hdel(warc_key, n)

    def _delete_decrease_size(self, user, coll, rec):
        rec_info = self.info_keys['rec'].format(user=user, coll=coll, rec=rec)
        try:
            length = int(self.redis.hget(rec_info, 'size'))
        except:
            print('Error decreasing size')
            return

        with redis.utils.pipeline(self.redis) as pi:
            coll_key = self.info_keys['coll'].format(user=user, coll=coll)
            user_key = self.info_keys['user'].format(user=user)
            pi.hincrby(coll_key, 'size', -length)
            pi.hincrby(user_key, 'size', -length)

# ============================================================================
class WebRecRedisIndexer(WritableRedisIndexer):
    def __init__(self, *args, **kwargs):
        super(WebRecRedisIndexer, self).__init__(*args, **kwargs)

        self.size_keys = kwargs.get('size_keys', [])
        self.rec_info_key_templ = kwargs.get('rec_info_key_templ')

    def add_urls_to_index(self, stream, params, filename, length):
        cdx_list = (super(WebRecRedisIndexer, self).
                      add_urls_to_index(stream, params, filename, length))

        with redis.utils.pipeline(self.redis) as pi:
            for key_templ in self.size_keys:
                key = res_template(key_templ, params)
                pi.hincrby(key, 'size', length)

                if key_templ == self.rec_info_key_templ and cdx_list:
                    pi.hset(key, 'updated_at', str(int(time.time())))

        return cdx_list

# ============================================================================
class SkipCheckingMultiFileWARCWriter(MultiFileWARCWriter):
    def __init__(self, *args, **kwargs):
        super(SkipCheckingMultiFileWARCWriter, self).__init__(*args, **kwargs)
        self.redis = kwargs.get('redis')
        self.skip_key_template = kwargs.get('skip_key_templ')

    def _is_write_req(self, req, params):
        if not req or not req.rec_headers or not self.skip_key_template:
            return False

        skip_key = res_template(self.skip_key_template, params)

        if self.redis.get(skip_key) == b'1':
            print('SKIPPING REQ', target_uri)
            return False

        return True

<commit_msg>recorder: ensure that deleting a collection also decreases the user size counter, #97<commit_after>from recorder.recorderapp import RecorderApp
from recorder.redisindexer import WritableRedisIndexer

from recorder.warcwriter import MultiFileWARCWriter, SimpleTempWARCWriter
from recorder.filters import SkipDupePolicy
from recorder.filters import ExcludeSpecificHeaders

import redis
import time
import json
import glob

from webagg.utils import res_template, ParamFormatter, StreamIter, chunk_encode_iter

from bottle import Bottle, request, debug, response
import os
import shutil
from six import iteritems

import gevent

# ============================================================================
class WebRecRecorder(object):
    def __init__(self, config=None):
        self.upstream_url = os.environ['WEBAGG_HOST']

        self.record_root_dir = os.environ['RECORD_ROOT']

        self.warc_path_templ = config['file_path_templ']
        self.warc_path_templ = self.record_root_dir + self.warc_path_templ

        self.cdxj_key_templ = config['cdxj_key_templ']

        self.rec_page_key_templ = config['r_page_key_templ']

        self.info_keys = config['info_key_templ']

        self.warc_key_templ = config['warc_key_templ']

        self.warc_rec_prefix = config['warc_name_prefix']
        self.warc_name_templ = config['warc_name_templ']

        self.full_warc_prefix = config['full_warc_prefix']

        self.name = config['recorder_name']

        self.del_templ = config['del_templ']

        self.skip_key_templ = config['skip_key_templ']

        self.redis_base_url = os.environ['REDIS_BASE_URL']
        self.redis = redis.StrictRedis.from_url(self.redis_base_url)

        self.app = Bottle()
        self.recorder = self.init_recorder()

        self.app.mount('/record', self.recorder)
        self.app.get('/download', callback=self.download)
        debug(True)

        gevent.spawn(self.delete_listen_loop)

    def init_recorder(self):
        self.dedup_index = WebRecRedisIndexer(
            name=self.name,
            redis=self.redis,

            cdx_key_template=self.cdxj_key_templ,
            file_key_template=self.warc_key_templ,
            rel_path_template=self.warc_path_templ,

            full_warc_prefix=self.full_warc_prefix,

            dupe_policy=SkipDupePolicy(),

            size_keys=self.info_keys.values(),
            rec_info_key_templ=self.info_keys['rec'],
        )

        header_filter = ExcludeSpecificHeaders(['Set-Cookie', 'Cookie'])

        writer = SkipCheckingMultiFileWARCWriter(dir_template=self.warc_path_templ,
                                     filename_template=self.warc_name_templ,
                                     dedup_index=self.dedup_index,
                                     redis=self.redis,
                                     skip_key_templ=self.skip_key_templ,
                                     header_filter=header_filter)

        self.writer = writer
        recorder_app = RecorderApp(self.upstream_url,
                                   writer,
                                   accept_colls='live')

        return recorder_app

    def get_pagelist(self, user, coll, rec):
        page_key_pattern = self.rec_page_key_templ.format(user=user, coll=coll, rec=rec)

        pages = []
        for page_key in self.redis.scan_iter(match=page_key_pattern):
            for page in self.redis.hvals(page_key):
                pages.append(json.loads(page.decode('utf-8')))

        return pages

    def download(self):
        user = request.query.get('user', '')
        coll = request.query.get('coll', '*')
        rec = request.query.get('rec', '*')
        type = request.query.get('type')

        filename = request.query.get('filename', 'rec.warc.gz')

        #if not user:
        #    response.status = 400
        #    return {'error_message': 'No User Provided'}

        templ = self.warc_path_templ + '*.warc.gz'
        warcs = list(glob.glob(templ.format(user=user, coll=coll, rec=rec)))

        metadata = {'pages': self.get_pagelist(user, coll, rec)}

        part_of = coll
        if rec != '*':
            part_of += '/' + rec

        # warcinfo Record
        info = {'software': 'Webrecorder Platform v2.0',
                'format': 'WARC File Format 1.0',
                'json-metadata': json.dumps(metadata),
                'isPartOf': part_of,
                'creator': user,
               }

        title = request.query.get('rec_title')
        if title:
            info['title'] = title

        coll_title = request.query.get('coll_title')
        if coll_title:
            info['isPartOf'] = coll_title

        wi_writer = SimpleTempWARCWriter()
        wi_writer.write_record(wi_writer.create_warcinfo_record(filename, **info))
        warcinfo = wi_writer.get_buffer()

        key_templ = self.info_keys.get(type, '')
        key_pattern = key_templ.format(user=user, coll=coll, rec=rec)

        length = len(warcinfo)
        try:
            length += int(self.redis.hget(key_pattern, 'size'))
        except Exception as e:
            print(e)

        def read_all(warcinfo):
            yield warcinfo

            for warc in warcs:
                with open(warc, 'rb') as fh:
                    for chunk in StreamIter(fh):
                        yield chunk

        response.headers['Content-Type'] = 'application/octet-stream'
        response.headers['Content-Length'] = int(length)
        resp = read_all(warcinfo)
        #response.headers['Transfer-Encoding'] = 'chunked'
        #resp = chunk_encode_iter(resp)
        return resp

    def delete_listen_loop(self):
        self.pubsub = self.redis.pubsub()
        self.pubsub.subscribe('delete')

        print('Waiting for delete messages')

        for item in self.pubsub.listen():
            try:
                if item['type'] == 'message' and item['channel'] == b'delete':
                    self.handle_delete(item['data'].decode('utf-8'))
            except:
                import traceback
                traceback.print_exc()

    def handle_delete(self, data):
        data = json.loads(data)

        user = data['user']
        coll = data['coll']
        rec = data['rec']
        type = data['type']

        try:
            self.delete_files(type, user, coll, rec)
        except:
            import traceback
            traceback.print_exc()

        try:
            self.delete_redis_keys(type, user, coll, rec)
        except:
            import traceback
            traceback.print_exc()

    def delete_files(self, type, user, coll, rec):
        if type not in (('user', 'coll', 'rec')):
            print('Unknown delete type ' + str(type))
            return

        glob_path = self.warc_path_templ.format(user=user, coll=coll, rec=rec)

        for dirname in glob.glob(glob_path):
            self.recorder.writer.close_dir(dirname)

        if glob_path.endswith('/'):
            glob_path = os.path.dirname(glob_path)

        if type == 'rec':
            dir_to_delete = glob_path
        elif type == 'coll':
            dir_to_delete = os.path.dirname(glob_path)
        elif type == 'user':
            dir_to_delete = os.path.dirname(os.path.dirname(glob_path))

        try:
            print('Deleting Files in ' + dir_to_delete)
            shutil.rmtree(dir_to_delete)
        except Exception as e:
            print(e)

    def delete_redis_keys(self, type, user, coll, rec):
        key_templ = self.del_templ.get(type)
        if not key_templ:
            print('Unknown delete type ' + str(type))
            return

        key_pattern = key_templ.format(user=user, coll=coll, rec=rec)
        keys_to_del = list(self.redis.scan_iter(match=key_pattern))

        if type == 'rec':
            self._delete_rec_warc_key(user, coll, rec)
            self._delete_decrease_size(user, coll, rec, type)
        elif type == 'coll':
            self._delete_decrease_size(user, coll, rec, type)

        with redis.utils.pipeline(self.redis) as pi:
            for key in keys_to_del:
                pi.delete(key)

    def _delete_rec_warc_key(self, user, coll, rec):
        warc_key = self.warc_key_templ.format(user=user, coll=coll, rec=rec)
        allwarcs = self.redis.hgetall(warc_key)

        warc_rec_prefix = self.warc_rec_prefix.format(user=user, coll=coll, rec=rec)

        with redis.utils.pipeline(self.redis) as pi:
            for n, v in iteritems(allwarcs):
                n = n.decode('utf-8')
                if n.startswith(warc_rec_prefix):
                    pi.hdel(warc_key, n)

    def _delete_decrease_size(self, user, coll, rec, type):
        del_info = self.info_keys[type].format(user=user, coll=coll, rec=rec)
        try:
            length = int(self.redis.hget(del_info, 'size'))
        except:
            print('Error decreasing size')
            return

        with redis.utils.pipeline(self.redis) as pi:
            user_key = self.info_keys['user'].format(user=user)
            pi.hincrby(user_key, 'size', -length)

            if type == 'rec':
                coll_key = self.info_keys['coll'].format(user=user, coll=coll)
                pi.hincrby(coll_key, 'size', -length)

# ============================================================================
class WebRecRedisIndexer(WritableRedisIndexer):
    def __init__(self, *args, **kwargs):
        super(WebRecRedisIndexer, self).__init__(*args, **kwargs)

        self.size_keys = kwargs.get('size_keys', [])
        self.rec_info_key_templ = kwargs.get('rec_info_key_templ')

    def add_urls_to_index(self, stream, params, filename, length):
        cdx_list = (super(WebRecRedisIndexer, self).
                      add_urls_to_index(stream, params, filename, length))

        with redis.utils.pipeline(self.redis) as pi:
            for key_templ in self.size_keys:
                key = res_template(key_templ, params)
                pi.hincrby(key, 'size', length)

                if key_templ == self.rec_info_key_templ and cdx_list:
                    pi.hset(key, 'updated_at', str(int(time.time())))

        return cdx_list

# ============================================================================
class SkipCheckingMultiFileWARCWriter(MultiFileWARCWriter):
    def __init__(self, *args, **kwargs):
        super(SkipCheckingMultiFileWARCWriter, self).__init__(*args, **kwargs)
        self.redis = kwargs.get('redis')
        self.skip_key_template = kwargs.get('skip_key_templ')

    def _is_write_req(self, req, params):
        if not req or not req.rec_headers or not self.skip_key_template:
            return False

        skip_key = res_template(self.skip_key_template, params)

        if self.redis.get(skip_key) == b'1':
            print('SKIPPING REQ', target_uri)
            return False

        return True

<|endoftext|>


<commit_before># Test vertical velocity computation
# ==================================
#
# Solves 3D continuity equation for simple horzontal velocity fields.
#
# Tuomas Karna 2015-07-10
from cofs import *

def test1():
    # ---- test 1: constant bathymetry
    n_layers = 6
    outputDir = createDirectory('outputs')
    mesh2d = UnitSquareMesh(10, 10)

    # bathymetry
    P1_2d = FunctionSpace(mesh2d, 'CG', 1)
    bathymetry_2d = Function(P1_2d, name='Bathymetry')
    bathymetry_2d.assign(1.0)

    # create solver
    solverObj = solver.flowSolver(mesh2d, bathymetry_2d, n_layers)
    solverObj.options.uAdvection = Constant(1e-3)
    solverObj.options.TExport = 100.0
    solverObj.options.T = 100.0
    solverObj.options.outputDir = 'tmp'

    solverObj.createEquations()
    # w needs to be projected to cartesian vector field for sanity check
    w_3d_proj = Function(solverObj.P1DGv, name='projected w')
    # use symmetry condition at all boundaries
    bnd_markers = solverObj.eq_sw.boundary_markers
    bnd_funcs = {}
    for k in bnd_markers:
        bnd_funcs[k] = {'symm': None}

    solverObj.fields.uv_3d.project(Expression(('1e-3', '0.0', '0.0')))
    computeVertVelocity(solverObj.fields.w_3d, solverObj.fields.uv_3d, solverObj.fields.bathymetry_3d,
                        boundary_markers=bnd_markers, boundary_funcs=bnd_funcs)
    w_3d_proj.project(solverObj.fields.w_3d)
    print 'w', w_3d_proj.dat.data.min(), w_3d_proj.dat.data.max()
    assert(np.allclose(w_3d_proj.dat.data, 0.0))
    print 'PASSED'

    solverObj.fields.uv_3d.project(Expression(('1e-3*x[0]', '0.0', '0.0')))
    computeVertVelocity(solverObj.fields.w_3d, solverObj.fields.uv_3d, solverObj.fields.bathymetry_3d)
    w_3d_proj.project(solverObj.fields.w_3d)
    print 'w', w_3d_proj.dat.data.min(), w_3d_proj.dat.data.max()
    assert(np.allclose(w_3d_proj.dat.data.min(), -1e-3))
    print 'PASSED'
    linProblemCache.clear()

def test2():
    # ---- test 2: sloping bathymetry
    n_layers = 6
    outputDir = createDirectory('outputs')
    mesh2d = UnitSquareMesh(10,10)

    # bathymetry
    P1_2d = FunctionSpace(mesh2d, 'CG', 1)
    bathymetry_2d = Function(P1_2d, name='Bathymetry')
    bathymetry_2d.interpolate(Expression('1.0 + x[0]'))

    solverObj = solver.flowSolver(mesh2d, bathymetry_2d, n_layers)
    solverObj.options.uAdvection = Constant(1e-3)
    solverObj.options.TExport = 100.0
    solverObj.options.T = 100.0
    solverObj.options.outputDir = 'tmp'

    solverObj.createEquations()
    # w needs to be projected to cartesian vector field for sanity check
    w_3d_proj = Function(solverObj.P1DGv, name='projected w')
    # use symmetry condition at all boundaries
    bnd_markers = solverObj.eq_sw.boundary_markers
    bnd_funcs = {}
    for k in bnd_markers:
        bnd_funcs[k] = {'symm': None}

    solverObj.fields.uv_3d.project(Expression(('1e-3', '0.0', '0.0')))
    computeVertVelocity(solverObj.fields.w_3d, solverObj.fields.uv_3d, solverObj.fields.bathymetry_3d,
                        boundary_markers=bnd_markers, boundary_funcs=bnd_funcs)
    w_3d_proj.project(solverObj.fields.w_3d)
    print 'w', w_3d_proj.dat.data.min(), w_3d_proj.dat.data.max()
    assert(np.allclose(w_3d_proj.dat.data[:, 2], -1e-3))
    print 'PASSED'
    solverObj.export()

    solverObj.uv_3d.project(Expression(('1e-3*x[0]', '0.0', '0.0')))
    computeVertVelocity(solverObj.fields.w_3d, solverObj.fields.uv_3d, solverObj.fields.bathymetry_3d,
                        boundary_markers=bnd_markers, boundary_funcs=bnd_funcs)
    w_3d_proj.project(solverObj.fields.w_3d)
    print 'w', w_3d_proj.dat.data.min(), w_3d_proj.dat.data.max()
    assert(np.allclose(w_3d_proj.dat.data.min(), -3e-3, rtol=1e-2))
    print 'PASSED'
    solverObj.export()
    linProblemCache.clear()

test1()
test2()
<commit_msg>fixed continuity test; passes for dg velocity<commit_after># Test vertical velocity computation
# ==================================
#
# Solves 3D continuity equation for simple horzontal velocity fields.
#
# Tuomas Karna 2015-07-10
from cofs import *

def test1():
    # ---- test 1: constant bathymetry
    n_layers = 6
    outputDir = createDirectory('outputs')
    mesh2d = UnitSquareMesh(10, 10)

    # bathymetry
    P1_2d = FunctionSpace(mesh2d, 'CG', 1)
    bathymetry_2d = Function(P1_2d, name='Bathymetry')
    bathymetry_2d.assign(1.0)

    # create solver
    solverObj = solver.flowSolver(mesh2d, bathymetry_2d, n_layers)
    solverObj.options.mimetic = False
    solverObj.options.uAdvection = Constant(1e-3)
    solverObj.options.TExport = 100.0
    solverObj.options.T = 100.0
    solverObj.options.outputDir = outputDir

    solverObj.createEquations()
    # w needs to be projected to cartesian vector field for sanity check
    w_3d_proj = Function(solverObj.P1DGv, name='projected w')
    # use symmetry condition at all boundaries
    bnd_markers = solverObj.eq_sw.boundary_markers
    bnd_funcs = {}
    for k in bnd_markers:
        bnd_funcs[k] = {'symm': None}

    solverObj.fields.uv_3d.project(Expression(('1e-3', '0.0', '0.0')))
    computeVertVelocity(solverObj.fields.w_3d, solverObj.fields.uv_3d, solverObj.fields.bathymetry_3d,
                        boundary_markers=bnd_markers, boundary_funcs=bnd_funcs)
    w_3d_proj.project(solverObj.fields.w_3d)
    print 'w', w_3d_proj.dat.data.min(), w_3d_proj.dat.data.max()
    assert(np.allclose(w_3d_proj.dat.data, 0.0))
    print 'PASSED'

    solverObj.fields.uv_3d.project(Expression(('1e-3*x[0]', '0.0', '0.0')))
    computeVertVelocity(solverObj.fields.w_3d, solverObj.fields.uv_3d, solverObj.fields.bathymetry_3d)
    w_3d_proj.project(solverObj.fields.w_3d)
    print 'w', w_3d_proj.dat.data.min(), w_3d_proj.dat.data.max()
    assert(np.allclose(w_3d_proj.dat.data.min(), -1e-3))
    print 'PASSED'
    linProblemCache.clear()

def test2():
    # ---- test 2: sloping bathymetry
    n_layers = 6
    outputDir = createDirectory('outputs')
    mesh2d = UnitSquareMesh(10,10)

    # bathymetry
    P1_2d = FunctionSpace(mesh2d, 'CG', 1)
    bathymetry_2d = Function(P1_2d, name='Bathymetry')
    bathymetry_2d.interpolate(Expression('1.0 + x[0]'))

    solverObj = solver.flowSolver(mesh2d, bathymetry_2d, n_layers)
    solverObj.options.mimetic = False
    solverObj.options.uAdvection = Constant(1e-3)
    solverObj.options.TExport = 100.0
    solverObj.options.T = 100.0
    solverObj.options.outputDir = outputDir

    solverObj.createEquations()
    # w needs to be projected to cartesian vector field for sanity check
    w_3d_proj = Function(solverObj.P1DGv, name='projected w')
    # use symmetry condition at all boundaries
    bnd_markers = solverObj.eq_sw.boundary_markers
    bnd_funcs = {}
    for k in bnd_markers:
        bnd_funcs[k] = {'symm': None}

    solverObj.fields.uv_3d.project(Expression(('1e-3', '0.0', '0.0')))
    computeVertVelocity(solverObj.fields.w_3d, solverObj.fields.uv_3d, solverObj.fields.bathymetry_3d,
                        boundary_markers=bnd_markers, boundary_funcs=bnd_funcs)
    w_3d_proj.project(solverObj.fields.w_3d)
    print 'w', w_3d_proj.dat.data.min(), w_3d_proj.dat.data.max()
    assert(np.allclose(w_3d_proj.dat.data[:, 2], -1e-3))
    print 'PASSED'
    solverObj.export()

    solverObj.fields.uv_3d.project(Expression(('1e-3*x[0]', '0.0', '0.0')))
    computeVertVelocity(solverObj.fields.w_3d, solverObj.fields.uv_3d, solverObj.fields.bathymetry_3d,
                        boundary_markers=bnd_markers, boundary_funcs=bnd_funcs)
    w_3d_proj.project(solverObj.fields.w_3d)
    print 'w', w_3d_proj.dat.data.min(), w_3d_proj.dat.data.max()
    assert(np.allclose(w_3d_proj.dat.data.min(), -3e-3, rtol=1e-2))
    print 'PASSED'
    solverObj.export()
    linProblemCache.clear()

test1()
test2()
<|endoftext|>


<commit_before>from discord.ext import commands
from datetime import datetime
import discord
from .utils import checks
import aiohttp
from urllib.parse import parse_qs
from lxml import etree

def date(argument):
    formats = (
        '%Y/%m/%d',
        '%Y-%m-%d',
    )

    for fmt in formats:
        try:
            return datetime.strptime(argument, fmt)
        except ValueError:
            continue

    raise commands.BadArgument('Cannot convert to date. Expected YYYY/MM/DD or YYYY-MM-DD.')

class Buttons:
    """Buttons that make you feel."""

    def __init__(self, bot):
        self.bot = bot

    @commands.command(hidden=True)
    async def feelgood(self):
        """press"""
        await self.bot.say('*pressed*')

    @commands.command(hidden=True)
    async def feelbad(self):
        """depress"""
        await self.bot.say('*depressed*')

    @commands.command()
    async def love(self):
        """What is love?"""
        await self.bot.say('http://i.imgur.com/JthwtGA.png')

    @commands.command(hidden=True)
    async def bored(self):
        """boredom looms"""
        await self.bot.say('http://i.imgur.com/BuTKSzf.png')

    @commands.command(pass_context=True)
    @checks.mod_or_permissions(manage_messages=True)
    async def nostalgia(self, ctx, date: date, *, channel: discord.Channel = None):
        """Pins an old message from a specific date.

        If a channel is not given, then pins from the channel the
        command was ran on.

        The format of the date must be either YYYY-MM-DD or YYYY/MM/DD.
        """

        if channel is None:
            channel = ctx.message.channel

        async for m in self.bot.logs_from(channel, after=date, limit=1):
            try:
                await self.bot.pin_message(m)
            except:
                await self.bot.say('\N{THUMBS DOWN SIGN} Could not pin message.')
            else:
                await self.bot.say('\N{THUMBS UP SIGN} Successfully pinned message.')

    @nostalgia.error
    async def nostalgia_error(self, error, ctx):
        if type(error) is commands.BadArgument:
            await self.bot.say(error)

    def parse_google_card(self, node):
        if node is None:
            return None

        e = discord.Embed(colour=0x738bd7)

        # check if it's a calculator card:
        calculator = node.find(".//table/tr/td/span[@class='nobr']/h2[@class='r']")
        if calculator is not None:
            e.title = 'Calculator'
            e.description = ''.join(calculator.itertext())
            return e

        parent = node.getparent()

        # check for unit conversion card
        unit = parent.find(".//ol//div[@class='_Tsb']")
        if unit is not None:
            e.title = 'Unit Conversion'
            e.description = ''.join(''.join(n.itertext()) for n in unit)
            return e

        # check for currency conversion card
        currency = parent.find(".//ol/table[@class='std _tLi']/tr/td/h2")
        if currency is not None:
            e.title = 'Currency Conversion'
            e.description = ''.join(currency.itertext())
            return e

        # check for release date card
        release = parent.find(".//div[@id='_vBb']")
        if release is not None:
            try:
                date = ''.join(release[0].itertext()).strip()
                info = ''.join(release[1].itertext()).strip()
            except:
                return None
            else:
                e.title = 'Date Info'
                e.description = '%s\n%s' % (date, info)
                return e

        # check for definition card
        words = parent.find(".//ol/div[@class='g']/div/h3[@class='r']/div")
        if words is not None:
            try:
                definition_info = words.getparent().getparent()[1] # yikes
            except:
                pass
            else:
                try:
                    # inside is a
 with two
                    # the first is the actual word, the second is the pronunciation
                    e.title = words[0].text
                    e.description = words[1].text
                except:
                    return None

                # inside the table there's the actual definitions
                # they're separated as noun/verb/adjective with a list
                # of definitions
                for row in definition_info:
                    if len(row.attrib) != 0:
                        # definitions are empty

                        # if there is something in the
 then we're done
                        # with the definitions
                        break

                    try:
                        data = row[0]
                        lexical_category = data[0].text
                        body = []
                        for index, definition in enumerate(data[1], 1):
                            body.append('%s. %s' % (index, definition.text))

                        e.add_field(name=lexical_category, value='\n'.join(body), inline=False)
                    except:
                        continue

                return e

        # check for "time in" card
        time_in = parent.find(".//ol//div[@class='_Tsb _HOb _Qeb']")
        if time_in is not None:
            try:
                time_place = ''.join(time_in.find("span[@class='_HOb _Qeb']").itertext()).strip()
                the_time = ''.join(time_in.find("div[@class='_rkc _Peb']").itertext()).strip()
                the_date = ''.join(time_in.find("div[@class='_HOb _Qeb']").itertext()).strip()
            except:
                return None
            else:
                e.title = time_place
                e.description = '%s\n%s' % (the_time, the_date)
                return e

        # check for weather card
        # this one is the most complicated of the group lol
        # everything is under a
 which has a
        #
{{ weather for place }}

        # string, the rest is fucking table fuckery.
        weather = parent.find(".//ol//div[@class='e']")
        if weather is None:
            return None

        location = weather.find('h3')
        if location is None:
            return None

        e.title = ''.join(location.itertext())

        table = weather.find('table')
        if table is None:
            return None

        # This is gonna be a bit fucky.
        # So the part we care about is on the second data
        # column of the first tr
        try:
            tr = table[0]
            img = tr[0].find('img')
            category = img.get('alt')
            image = 'https:' + img.get('src')
            temperature = tr[1].xpath("./span[@class='wob_t']//text()")[0]
        except:
            return None # RIP
        else:
            e.set_thumbnail(url=image)
            e.description = '*%s*' % category
            e.add_field(name='Temperature', value=temperature)

        # On the 4th column it tells us our wind speeds
        try:
            wind = ''.join(table[3].itertext()).replace('Wind: ', '')
        except:
            return None
        else:
            e.add_field(name='Wind', value=wind)

        # On the 5th column it tells us our humidity
        try:
            humidity = ''.join(table[4][0].itertext()).replace('Humidity: ', '')
        except:
            return None
        else:
            e.add_field(name='Humidity', value=humidity)

        return e

    async def get_google_entries(self, query):
        params = {
            'q': query,
            'safe': 'on'
        }
        headers = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 6.3; Win64; x64)'
        }

        # list of URLs
        entries = []

        # the result of a google card, an embed
        card = None

        async with aiohttp.get('https://www.google.com/search', params=params, headers=headers) as resp:
            if resp.status != 200:
                raise RuntimeError('Google somehow failed to respond.')

            root = etree.fromstring(await resp.text(), etree.HTMLParser())

            # with open('google.html', 'w', encoding='utf-8') as f:
            #     f.write(etree.tostring(root, pretty_print=True).decode('utf-8'))

            """
            Tree looks like this.. sort of..

                ...

                    <a href="/url?q=<url>" ...>title

                ...

                    date here
                    summary here, can contain tag

            """

            card_node = root.find(".//div[@id='topstuff']")
            card = self.parse_google_card(card_node)

            search_nodes = root.findall(".//div[@class='g']")
            for node in search_nodes:
                url_node = node.find('.//h3/a')
                if url_node is None:
                    continue

                url = url_node.attrib['href']
                if not url.startswith('/url?'):
                    continue

                url = parse_qs(url[5:])['q'][0] # get the URL from ?q query string

                # if I ever cared about the description, this is how
                entries.append(url)

                # short = node.find(".//span[@class='st']")
                # if short is None:
                #     entries.append((url, ''))
                # else:
                #     text = ''.join(short.itertext())
                #     entries.append((url, text.replace('...', '')))

        return card, entries

    @commands.command(aliases=['google'])
    async def g(self, *, query):
        """Searches google and gives you top result."""
        await self.bot.type()
        try:
            card, entries = await self.get_google_entries(query)
        except RuntimeError as e:
            await self.bot.say(str(e))
        else:
            if card:
                msg = '\n'.join(map(lambda x: '<%s>' % x, entries[:3]))
                card.add_field(name='Search Results', value='\n'.join(entries[:3]), inline=False)
                return await self.bot.say(embed=card)

            next_two = entries[1:3]
            if next_two:
                formatted = '\n'.join(map(lambda x: '<%s>' % x, next_two))
                msg = '{}\n\n**See also:**\n{}'.format(entries[0], formatted)
            else:
                msg = entries[0]

            await self.bot.say(msg)

    @commands.command(pass_context=True)
    @commands.cooldown(rate=1, per=60.0, type=commands.BucketType.user)
    async def feedback(self, ctx, *, content: str):
        """Gives feedback about the bot.

        This is a quick way to request features or bug fixes
        without being in the bot's server.

        The bot will communicate with you via PM about the status
        of your request if possible.

        You can only request feedback once a minute.
        """

        e = discord.Embed(title='Feedback', colour=0x738bd7)
        msg = ctx.message

        channel = self.bot.get_channel('263814407191134218')
        if channel is None:
            return

        e.set_author(name=str(msg.author), icon_url=msg.author.avatar_url or msg.author.default_avatar_url)
        e.description = content
        e.timestamp = msg.timestamp

        if msg.server is not None:
            e.add_field(name='Server', value='{0.name} (ID: {0.id})'.format(msg.server), inline=False)

        e.add_field(name='Channel', value='{0} (ID: {0.id})'.format(msg.channel), inline=False)
        e.set_footer(text='Author ID: ' + msg.author.id)

        await self.bot.send_message(channel, embed=e)
        await self.bot.send_message(msg.channel, 'Successfully sent feedback \u2705')

    @commands.command()
    @checks.is_owner()
    async def pm(self, user_id: str, *, content: str):
        user = await self.bot.get_user_info(user_id)

        try:
            await self.bot.send_message(user, content)
        except:
            await self.bot.say('Could not PM user by ID ' + user_id)
        else:
            await self.bot.say('PM successfully sent.')

def setup(bot):
    bot.add_cog(Buttons(bot))
<commit_msg>Actually use the title for date info for `?g`.<commit_after>from discord.ext import commands
from datetime import datetime
import discord
from .utils import checks
import aiohttp
from urllib.parse import parse_qs
from lxml import etree

def date(argument):
    formats = (
        '%Y/%m/%d',
        '%Y-%m-%d',
    )

    for fmt in formats:
        try:
            return datetime.strptime(argument, fmt)
        except ValueError:
            continue

    raise commands.BadArgument('Cannot convert to date. Expected YYYY/MM/DD or YYYY-MM-DD.')

class Buttons:
    """Buttons that make you feel."""

    def __init__(self, bot):
        self.bot = bot

    @commands.command(hidden=True)
    async def feelgood(self):
        """press"""
        await self.bot.say('*pressed*')

    @commands.command(hidden=True)
    async def feelbad(self):
        """depress"""
        await self.bot.say('*depressed*')

    @commands.command()
    async def love(self):
        """What is love?"""
        await self.bot.say('http://i.imgur.com/JthwtGA.png')

    @commands.command(hidden=True)
    async def bored(self):
        """boredom looms"""
        await self.bot.say('http://i.imgur.com/BuTKSzf.png')

    @commands.command(pass_context=True)
    @checks.mod_or_permissions(manage_messages=True)
    async def nostalgia(self, ctx, date: date, *, channel: discord.Channel = None):
        """Pins an old message from a specific date.

        If a channel is not given, then pins from the channel the
        command was ran on.

        The format of the date must be either YYYY-MM-DD or YYYY/MM/DD.
        """

        if channel is None:
            channel = ctx.message.channel

        async for m in self.bot.logs_from(channel, after=date, limit=1):
            try:
                await self.bot.pin_message(m)
            except:
                await self.bot.say('\N{THUMBS DOWN SIGN} Could not pin message.')
            else:
                await self.bot.say('\N{THUMBS UP SIGN} Successfully pinned message.')

    @nostalgia.error
    async def nostalgia_error(self, error, ctx):
        if type(error) is commands.BadArgument:
            await self.bot.say(error)

    def parse_google_card(self, node):
        if node is None:
            return None

        e = discord.Embed(colour=0x738bd7)

        # check if it's a calculator card:
        calculator = node.find(".//table/tr/td/span[@class='nobr']/h2[@class='r']")
        if calculator is not None:
            e.title = 'Calculator'
            e.description = ''.join(calculator.itertext())
            return e

        parent = node.getparent()

        # check for unit conversion card
        unit = parent.find(".//ol//div[@class='_Tsb']")
        if unit is not None:
            e.title = 'Unit Conversion'
            e.description = ''.join(''.join(n.itertext()) for n in unit)
            return e

        # check for currency conversion card
        currency = parent.find(".//ol/table[@class='std _tLi']/tr/td/h2")
        if currency is not None:
            e.title = 'Currency Conversion'
            e.description = ''.join(currency.itertext())
            return e

        # check for release date card
        release = parent.find(".//div[@id='_vBb']")
        if release is not None:
            try:
                e.description = ''.join(release[0].itertext()).strip()
                e.title = ''.join(release[1].itertext()).strip()
                return e
            except:
                return None

        # check for definition card
        words = parent.find(".//ol/div[@class='g']/div/h3[@class='r']/div")
        if words is not None:
            try:
                definition_info = words.getparent().getparent()[1] # yikes
            except:
                pass
            else:
                try:
                    # inside is a
 with two
                    # the first is the actual word, the second is the pronunciation
                    e.title = words[0].text
                    e.description = words[1].text
                except:
                    return None

                # inside the table there's the actual definitions
                # they're separated as noun/verb/adjective with a list
                # of definitions
                for row in definition_info:
                    if len(row.attrib) != 0:
                        # definitions are empty

                        # if there is something in the
 then we're done
                        # with the definitions
                        break

                    try:
                        data = row[0]
                        lexical_category = data[0].text
                        body = []
                        for index, definition in enumerate(data[1], 1):
                            body.append('%s. %s' % (index, definition.text))

                        e.add_field(name=lexical_category, value='\n'.join(body), inline=False)
                    except:
                        continue

                return e

        # check for "time in" card
        time_in = parent.find(".//ol//div[@class='_Tsb _HOb _Qeb']")
        if time_in is not None:
            try:
                time_place = ''.join(time_in.find("span[@class='_HOb _Qeb']").itertext()).strip()
                the_time = ''.join(time_in.find("div[@class='_rkc _Peb']").itertext()).strip()
                the_date = ''.join(time_in.find("div[@class='_HOb _Qeb']").itertext()).strip()
            except:
                return None
            else:
                e.title = time_place
                e.description = '%s\n%s' % (the_time, the_date)
                return e

        # check for weather card
        # this one is the most complicated of the group lol
        # everything is under a
 which has a
        #
{{ weather for place }}

        # string, the rest is fucking table fuckery.
        weather = parent.find(".//ol//div[@class='e']")
        if weather is None:
            return None

        location = weather.find('h3')
        if location is None:
            return None

        e.title = ''.join(location.itertext())

        table = weather.find('table')
        if table is None:
            return None

        # This is gonna be a bit fucky.
        # So the part we care about is on the second data
        # column of the first tr
        try:
            tr = table[0]
            img = tr[0].find('img')
            category = img.get('alt')
            image = 'https:' + img.get('src')
            temperature = tr[1].xpath("./span[@class='wob_t']//text()")[0]
        except:
            return None # RIP
        else:
            e.set_thumbnail(url=image)
            e.description = '*%s*' % category
            e.add_field(name='Temperature', value=temperature)

        # On the 4th column it tells us our wind speeds
        try:
            wind = ''.join(table[3].itertext()).replace('Wind: ', '')
        except:
            return None
        else:
            e.add_field(name='Wind', value=wind)

        # On the 5th column it tells us our humidity
        try:
            humidity = ''.join(table[4][0].itertext()).replace('Humidity: ', '')
        except:
            return None
        else:
            e.add_field(name='Humidity', value=humidity)

        return e

    async def get_google_entries(self, query):
        params = {
            'q': query,
            'safe': 'on'
        }
        headers = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 6.3; Win64; x64)'
        }

        # list of URLs
        entries = []

        # the result of a google card, an embed
        card = None

        async with aiohttp.get('https://www.google.com/search', params=params, headers=headers) as resp:
            if resp.status != 200:
                raise RuntimeError('Google somehow failed to respond.')

            root = etree.fromstring(await resp.text(), etree.HTMLParser())

            # with open('google.html', 'w', encoding='utf-8') as f:
            #     f.write(etree.tostring(root, pretty_print=True).decode('utf-8'))

            """
            Tree looks like this.. sort of..

                ...

                    <a href="/url?q=<url>" ...>title

                ...

                    date here
                    summary here, can contain tag

            """

            card_node = root.find(".//div[@id='topstuff']")
            card = self.parse_google_card(card_node)

            search_nodes = root.findall(".//div[@class='g']")
            for node in search_nodes:
                url_node = node.find('.//h3/a')
                if url_node is None:
                    continue

                url = url_node.attrib['href']
                if not url.startswith('/url?'):
                    continue

                url = parse_qs(url[5:])['q'][0] # get the URL from ?q query string

                # if I ever cared about the description, this is how
                entries.append(url)

                # short = node.find(".//span[@class='st']")
                # if short is None:
                #     entries.append((url, ''))
                # else:
                #     text = ''.join(short.itertext())
                #     entries.append((url, text.replace('...', '')))

        return card, entries

    @commands.command(aliases=['google'])
    async def g(self, *, query):
        """Searches google and gives you top result."""
        await self.bot.type()
        try:
            card, entries = await self.get_google_entries(query)
        except RuntimeError as e:
            await self.bot.say(str(e))
        else:
            if card:
                msg = '\n'.join(map(lambda x: '<%s>' % x, entries[:3]))
                card.add_field(name='Search Results', value='\n'.join(entries[:3]), inline=False)
                return await self.bot.say(embed=card)

            next_two = entries[1:3]
            if next_two:
                formatted = '\n'.join(map(lambda x: '<%s>' % x, next_two))
                msg = '{}\n\n**See also:**\n{}'.format(entries[0], formatted)
            else:
                msg = entries[0]

            await self.bot.say(msg)

    @commands.command(pass_context=True)
    @commands.cooldown(rate=1, per=60.0, type=commands.BucketType.user)
    async def feedback(self, ctx, *, content: str):
        """Gives feedback about the bot.

        This is a quick way to request features or bug fixes
        without being in the bot's server.

        The bot will communicate with you via PM about the status
        of your request if possible.

        You can only request feedback once a minute.
        """

        e = discord.Embed(title='Feedback', colour=0x738bd7)
        msg = ctx.message

        channel = self.bot.get_channel('263814407191134218')
        if channel is None:
            return

        e.set_author(name=str(msg.author), icon_url=msg.author.avatar_url or msg.author.default_avatar_url)
        e.description = content
        e.timestamp = msg.timestamp

        if msg.server is not None:
            e.add_field(name='Server', value='{0.name} (ID: {0.id})'.format(msg.server), inline=False)

        e.add_field(name='Channel', value='{0} (ID: {0.id})'.format(msg.channel), inline=False)
        e.set_footer(text='Author ID: ' + msg.author.id)

        await self.bot.send_message(channel, embed=e)
        await self.bot.send_message(msg.channel, 'Successfully sent feedback \u2705')

    @commands.command()
    @checks.is_owner()
    async def pm(self, user_id: str, *, content: str):
        user = await self.bot.get_user_info(user_id)

        try:
            await self.bot.send_message(user, content)
        except:
            await self.bot.say('Could not PM user by ID ' + user_id)
        else:
            await self.bot.say('PM successfully sent.')

def setup(bot):
    bot.add_cog(Buttons(bot))
<|endoftext|>


<commit_before>#!/usr/bin/env python
import time
import threading
import Queue
import os
import pyuarm
import rospy

from std_msgs.msg import String

def ros_try_catch(fn):
        def try_catch(*args, **kwargs):
            try:
                return fn(*args, **kwargs)
            except Exception as e:
                err_msg = "Error in function '" + fn.func_name + "': " + str(e.message)
                rospy.logerr(err_msg)
                rospy.signal_shutdown(err_msg)
        return try_catch

class UARM_interface():

    def __init__(self):
        self.uarm = None
        self.connected = False
        self.alive = True

        self.ros_rate = None
        self.ros_hz = 0

        self.settings = []

        self.uarm_read_thread = None
        self.uarm_read_queue = None
        self.read_queue_get_lock = threading.Lock()
        self.read_queue_put_lock = threading.Lock()
        self.uarm_read_pub = None

        self.uarm_interface_thread = None
        self.uarm_interface_queue = None
        self.interface_queue_get_lock = threading.Lock()
        self.interface_queue_put_lock = threading.Lock()

        self.playback_thread = None
        self.playback_active = False
        self.playback_data = []
        self.loading = False

        self.ja = []

    def get_setting(self, name, string_val=False, list=False):
        for line in self.settings:
            if line[0] == name:
                if string_val:
                    return line[1]
                else:
                    if list:
                        return float(line[1:])
                    else:
                        return float(line[1])

    def connect(self):
        try:
            self.uarm = pyuarm.get_uarm()
            self.connected = True
            self.load_parameters()
            self.start_threads()
            rospy.loginfo("Connected")
        except Exception as e:
            self.connected = False
            err = str(e.message)
            rospy.logerr("Connection error: " + err)
            rospy.signal_shutdown("Connection error")

    def shutdown(self):
        rospy.loginfo("Shutdown function call")
        rospy.signal_shutdown("Shutdown function call")
        start_shutdown = time.time()
        while self.uarm_interface_thread.is_alive() or self.uarm_read_thread.is_alive():
            # self.send_to_interface_queue("SHUTDOWN", priority=True)
            # self.send_to_read_queue("SHUTDOWN", priority=True)
            self.send_to_interface_queue("SHUTDOWN", priority=1)
            self.send_to_read_queue("SHUTDOWN", priority=1)
            time.sleep(0.5)
            if time.time()-start_shutdown > 5:
                break
        self.alive = False
        self.uarm.disconnect()

    def load_parameters(self):
        rospy.loginfo("Loading parameters")

        dir_path = os.path.dirname(os.path.realpath(__file__))
        f = open(dir_path + "/settings.txt")
        self.settings = []
        for line in f:
            self.settings.append(line.split(','))
        f.close()

        self.ros_hz = self.get_setting("ros_hz")
        self.read_pos = self.get_setting("read_pos")
        print self.read_pos
        self.read_ja = self.get_setting("read_ja")
        print self.read_ja
        self.read_AI = self.get_setting("read_AI",list=True)
        print self.read_AI

        self.uarm_read_pub = rospy.Publisher('uarm_read', String, queue_size=10)
        rospy.Subscriber("uarm_write", String, self.uarm_write_callback)
        rospy.init_node('uarm_node', anonymous=True)
        self.ros_rate = rospy.Rate(self.ros_hz)

        #self.uarm_read_queue = Queue.Queue()
        #self.uarm_interface_queue = Queue.Queue()

        self.uarm_read_queue = Queue.PriorityQueue()
        self.uarm_interface_queue = Queue.PriorityQueue()

        rospy.loginfo("Done loading parameters.")

    def start_threads(self):
        rospy.loginfo("Starting threads")
        if self.connected is True:
            self.uarm_read_thread = threading.Thread(target=self.uarm_read)
            self.uarm_interface_thread = threading.Thread(target=self.uarm_interface)

            self.uarm_read_thread.daemon = True
            self.uarm_read_thread.start()

            self.uarm_interface_thread.daemon = True
            self.uarm_interface_thread.start()

            self.request_detach()

        else:
            rospy.logerr("Startup error")
            rospy.signal_shutdown("Startup error")

    def get_read_data(self):
        msg = []
        print "here"
        if self.read_pos == 1:
            msg.append(self.read_position())
        elif self.read_ja == 1:
            msg.append(self.read_joint_angles())
        elif self.read_AI[0] == 1:
            for i in self.read_AI[1:]:
                msg.append(self.read_analog(i))

        print msg
        return msg

    def uarm_interface(self):
        rospy.loginfo("uarm_interface running")
        while True and (rospy.is_shutdown() is False):
            request = self.get_from_interface_queue()
            if request == "READ":
                curr_vals = self.get_read_data()
                try:
                    self.send_to_read_queue(curr_vals)
                except Exception as e:
                    print "Error: ", e
                    rospy.logerr("Error writing to queue. Queue probably shutdown.")
                    break
                #time.sleep(1.0/self.ros_hz)
                try:
                    self.ja = curr_vals[1]
                except Exception as e:
                    err = str(e.message)
                    rospy.logerr("uArm not ready! " + err)
                    rospy.signal_shutdown("Error reading from uArm")

                if self.playback_active is False and self.loading is False:
                    self.send_to_interface_queue("READ")

            elif request == "SHUTDOWN":
                break
            else:
                self.process_command(request)
                if self.playback_active is False and self.loading is False:
                    self.send_to_interface_queue("READ")

        rospy.loginfo("uarm_interface shutdown")
        self.shutdown()

    def request_detach(self):
        rospy.loginfo("uArm detach")
        self.send_to_interface_queue("DET")

    def request_attach(self):
        rospy.loginfo("uArm attach")
        self.send_to_interface_queue("ATT")

    def pump_on(self):
        rospy.loginfo("uArm Pump On")
        self.send_to_interface_queue("PUMP_ON")

    def pump_off(self):
        rospy.loginfo("uArm Pump Off")
        self.send_to_interface_queue("PUMP_OFF")

    @ros_try_catch
    def read_analog(self, pin_num):
        return round(self.uarm.get_analog(pin_num), 3)

    @ros_try_catch
    def get_joint_angles(self):
        return self.uarm.get_servo_angle()

    @ros_try_catch
    def read_position(self):
        return self.uarm.get_position()

    @ros_try_catch
    def read_joint_angles(self):
        # return [self.get_joint_angles(), time.time()]
        return self.get_joint_angles()

    def uarm_read(self):
        rospy.loginfo("uarm_read running")
        while True and (rospy.is_shutdown() is False):
            robot_values = self.get_from_read_queue(blocking=False)
            if robot_values == "SHUTDOWN":
                rospy.logwarn("sending shutdown signal")
                rospy.signal_shutdown("Normal Shutdown Procedure")
                break
            elif not robot_values:
                pass
            elif robot_values == "DONE":
                self.uarm_read_pub.publish("DONE")
            else:
                msg = str(robot_values)
                msg = msg.translate(None, '[]')
                self.uarm_read_pub.publish(msg)
                #self.ros_rate.sleep()

        rospy.loginfo("uarm_read shutdown")

    def send_to_interface_queue(self, msg, msg_list=False, priority=10):
        with self.interface_queue_put_lock:
            if msg_list:
                for m in msg_list:
                    self.uarm_interface_queue.put((priority,m))
            else:
                self.uarm_interface_queue.put((priority, msg))

    # def send_to_interface_queue(self, msg, msg_list=False, priority=False):
    #     with self.interface_queue_put_lock:
    #         if msg_list:
    #             if priority:
    #                 msg_list = msg + self.get_from_interface_queue(all_msgs=True)
    #             for m in msg_list:
    #                 self.uarm_interface_queue.put(m)
    #         else:
    #             if priority:
    #                 msg_list = [msg] + self.get_from_interface_queue(all_msgs=True)
    #                 for m in msg_list:
    #                     self.uarm_interface_queue.put(m)
    #             else:
    #                 self.uarm_interface_queue.put(msg)

    def filter_interface_queue(self, msg_filter, invert=False):
        msgs = self.get_from_interface_queue(all_msgs=True, blocking=True)
        if msg_filter is not "":
            # print "FILTER: ", filter
            n = 0
            for i, msg in enumerate(msgs):
                if filter in msg and not invert:
                    msgs.pop(i)
                    n += 1
                elif filter not in msg and invert:
                    msgs.pop(i)
                    n += 1
            if msgs is not []:
                # print n, " messages filtered matching search terms", filter, invert
                # print msgs
                #self.send_to_interface_queue(msgs, msg_list=True, priority=True)
                self.send_to_interface_queue(msgs, msg_list=True, priority=1)

    def get_from_interface_queue(self, all_msgs=False, blocking=False):
        with self.interface_queue_get_lock:
            if all_msgs:
                msgs = []
                while self.uarm_interface_queue.qsize() > 0:
                    try:
                        msg = self.uarm_interface_queue.get(blocking)
                        try:
                            msg = msg[1]
                        except:
                            pass
                        print msg
                        msgs.append(msg)

                    except Queue.Empty:
                        msgs = []

                return msgs
            else:
                try:
                    msg = self.uarm_interface_queue.get(blocking)
                except Queue.Empty:
                    msg = ""
                try:
                    msg = msg[1]
                except:
                    pass
                return msg

    def send_to_read_queue(self, msg, msg_list=False, priority=10):
        with self.read_queue_put_lock:
            if msg_list:
                for m in msg:
                    self.uarm_read_queue.put((priority,m))
            else:
                self.uarm_read_queue.put((priority,msg))

    # def send_to_read_queue(self, msg, msg_list=False, priority=False):
    #     with self.read_queue_put_lock:
    #         if msg_list:
    #             if priority:
    #                 msg_list = msg + self.get_from_read_queue(all_msgs=True)
    #             for m in msg_list:
    #                 self.uarm_read_queue.put(m)
    #         else:
    #             if priority:
    #                 # print "Sending priority message, read_queue:", msg
    #                 msg_list = [msg] + self.get_from_read_queue(all_msgs=True)
    #                 for m in msg_list:
    #                     self.uarm_read_queue.put(m)
    #             else:
    #                 self.uarm_read_queue.put(msg)

    def get_from_read_queue(self, all_msgs=False, blocking=False):
        with self.read_queue_get_lock:
            if all_msgs:
                msgs = []
                while self.uarm_read_queue.qsize() > 0:
                    try:
                        msg = self.uarm_read_queue.get(blocking)
                        try:
                            msg = msg[1:]
                        except:
                            pass
                        msgs.append()
                    except Queue.Empty:
                        msgs = []
                return msgs
            else:
                try:
                    msg = self.uarm_read_queue.get(blocking)
                    try:
                        msg = msg[1:]
                    except:
                        pass

                except Queue.Empty:
                    msg = ""
                return msg

    def uarm_write_callback(self, data):
        # print "DATA: ", data.data
        if data.data == "CLEAR":
                self.get_from_interface_queue(all_msgs=True)
                self.get_from_read_queue(all_msgs=True)

        elif data.data[0] == "!":
                msg = data.data[1:]
                #print msg
                #self.send_to_interface_queue(msg, priority=True)
                self.send_to_interface_queue(msg, priority=1)
        else:
                self.send_to_interface_queue(data.data)

    def playback(self):
        if self.playback_data:
            self.loading = False
            self.get_from_interface_queue(all_msgs=True)  # flush queue
            try:
                joint_angles = self.ja
                self.send_to_interface_queue("JA"+str(joint_angles[0]) + "," +
                                             str(joint_angles[1]) + "," +
                                             str(joint_angles[2]) +
                                             str(joint_angles[3]))
            except Exception as e:
                # print "joint angles not ready yet: ", e
                err = str(e.message)
                rospy.logerr("joint angles not ready yet: " + err)
                rospy.signal_shutdown("joint angles not ready yet")

            self.send_to_interface_queue("ATT")

            self.filter_interface_queue("READ")

            for line in self.playback_data:
                # print self.playback_active, line
                if self.playback_active is False:
                    self.get_from_interface_queue(all_msgs=True)
                    break
                msg = str(line)

                self.send_to_interface_queue("READ")
                self.send_to_interface_queue(msg)

        self.send_to_interface_queue("BEEP")
        self.send_to_interface_queue("DET")
        self.playback_data = []

    def load_playback_data(self, data_line):
        self.loading = True
        rospy.loginfo("Loading playback data...")
        self.playback_data.append(data_line)

    @ros_try_catch
    def process_command(self, command):
        if command == "PUMP_ON":
            self.uarm.set_pump(1)

        if command == "PUMP_OFF":
            self.uarm.set_pump(0)

        if command == "ATT":
            self.uarm.set_servo_attach()

        if command == "DET":
            self.uarm.set_servo_detach()

        if command[0:3] == "POS" and self.playback_active:
            position = map(float, command[3:].split(','))
            self.uarm.set_position(position[0], position[1], position[2])

        if command[0:3] == "REL":
            adjust = float(command[3:])
            # print adjust
            self.uarm.set_position(x=0, y=0, z=adjust, speed=0, relative=True)

        if command[0:2] == "JA" and self.playback_active:
            angle = map(float, command[2:].split(','))
            for i in range(0, len(angle)-1):
                self.uarm.set_servo_angle(i, angle[i])

        if command[0:4] == "LOAD":
            self.load_playback_data(command[4:])

        if command == "PLAY":
            if self.playback_data:
                self.playback_active = True
                self.playback_thread = threading.Thread(target=self.playback)
                self.playback_thread.daemon = True

                self.playback_thread.start()
        if command == "BEEP":
            self.uarm.set_buzzer(10000, 0.1)
            #self.send_to_read_queue("DONE", priority=True)
            self.send_to_read_queue("DONE", priority=1)
            self.playback_active = False

        if command == "STOP":
            self.playback_active = False
            self.filter_interface_queue(msg_filter="READ")
            time.sleep(0.5)
            self.filter_interface_queue(msg_filter="JA")
            self.playback_data = []
<commit_msg>speed debug<commit_after>#!/usr/bin/env python
import time
import threading
import Queue
import os
import pyuarm
import rospy

from std_msgs.msg import String

def ros_try_catch(fn):
        def try_catch(*args, **kwargs):
            try:
                return fn(*args, **kwargs)
            except Exception as e:
                err_msg = "Error in function '" + fn.func_name + "': " + str(e.message)
                rospy.logerr(err_msg)
                rospy.signal_shutdown(err_msg)
        return try_catch

class UARM_interface():

    def __init__(self):
        self.uarm = None
        self.connected = False
        self.alive = True

        self.ros_rate = None
        self.ros_hz = 0

        self.settings = []

        self.uarm_read_thread = None
        self.uarm_read_queue = None
        self.read_queue_get_lock = threading.Lock()
        self.read_queue_put_lock = threading.Lock()
        self.uarm_read_pub = None

        self.uarm_interface_thread = None
        self.uarm_interface_queue = None
        self.interface_queue_get_lock = threading.Lock()
        self.interface_queue_put_lock = threading.Lock()

        self.playback_thread = None
        self.playback_active = False
        self.playback_data = []
        self.loading = False

        self.ja = []

    def get_setting(self, name, string_val=False, list=False):
        for line in self.settings:
            if line[0] == name:
                if string_val:
                    return line[1]
                else:
                    if list:
                        print line
                        return float(line[1:])
                    else:
                        return float(line[1])

    def connect(self):
        try:
            self.uarm = pyuarm.get_uarm()
            self.connected = True
            self.load_parameters()
            self.start_threads()
            rospy.loginfo("Connected")
        except Exception as e:
            self.connected = False
            err = str(e.message)
            rospy.logerr("Connection error: " + err)
            rospy.signal_shutdown("Connection error")

    def shutdown(self):
        rospy.loginfo("Shutdown function call")
        rospy.signal_shutdown("Shutdown function call")
        start_shutdown = time.time()
        while self.uarm_interface_thread.is_alive() or self.uarm_read_thread.is_alive():
            # self.send_to_interface_queue("SHUTDOWN", priority=True)
            # self.send_to_read_queue("SHUTDOWN", priority=True)
            self.send_to_interface_queue("SHUTDOWN", priority=1)
            self.send_to_read_queue("SHUTDOWN", priority=1)
            time.sleep(0.5)
            if time.time()-start_shutdown > 5:
                break
        self.alive = False
        self.uarm.disconnect()

    def load_parameters(self):
        rospy.loginfo("Loading parameters")

        dir_path = os.path.dirname(os.path.realpath(__file__))
        f = open(dir_path + "/settings.txt")
        self.settings = []
        for line in f:
            self.settings.append(line.split(','))
        f.close()

        self.ros_hz = self.get_setting("ros_hz")
        self.read_pos = self.get_setting("read_pos")
        self.read_ja = self.get_setting("read_ja")
        self.read_AI = self.get_setting("read_AI",list=True)

        self.uarm_read_pub = rospy.Publisher('uarm_read', String, queue_size=10)
        rospy.Subscriber("uarm_write", String, self.uarm_write_callback)
        rospy.init_node('uarm_node', anonymous=True)
        self.ros_rate = rospy.Rate(self.ros_hz)

        #self.uarm_read_queue = Queue.Queue()
        #self.uarm_interface_queue = Queue.Queue()

        self.uarm_read_queue = Queue.PriorityQueue()
        self.uarm_interface_queue = Queue.PriorityQueue()

        rospy.loginfo("Done loading parameters.")

    def start_threads(self):
        rospy.loginfo("Starting threads")
        if self.connected is True:
            self.uarm_read_thread = threading.Thread(target=self.uarm_read)
            self.uarm_interface_thread = threading.Thread(target=self.uarm_interface)

            self.uarm_read_thread.daemon = True
            self.uarm_read_thread.start()

            self.uarm_interface_thread.daemon = True
            self.uarm_interface_thread.start()

            self.request_detach()

        else:
            rospy.logerr("Startup error")
            rospy.signal_shutdown("Startup error")

    def get_read_data(self):
        msg = []
        print "here"
        if self.read_pos == 1:
            msg.append(self.read_position())
        elif self.read_ja == 1:
            msg.append(self.read_joint_angles())
        elif self.read_AI[0] == 1:
            for i in self.read_AI[1:]:
                msg.append(self.read_analog(i))

        print msg
        return msg

    def uarm_interface(self):
        rospy.loginfo("uarm_interface running")
        while True and (rospy.is_shutdown() is False):
            request = self.get_from_interface_queue()
            if request == "READ":
                curr_vals = self.get_read_data()
                try:
                    self.send_to_read_queue(curr_vals)
                except Exception as e:
                    print "Error: ", e
                    rospy.logerr("Error writing to queue. Queue probably shutdown.")
                    break
                #time.sleep(1.0/self.ros_hz)
                try:
                    self.ja = curr_vals[1]
                except Exception as e:
                    err = str(e.message)
                    rospy.logerr("uArm not ready! " + err)
                    rospy.signal_shutdown("Error reading from uArm")

                if self.playback_active is False and self.loading is False:
                    self.send_to_interface_queue("READ")

            elif request == "SHUTDOWN":
                break
            else:
                self.process_command(request)
                if self.playback_active is False and self.loading is False:
                    self.send_to_interface_queue("READ")

        rospy.loginfo("uarm_interface shutdown")
        self.shutdown()

    def request_detach(self):
        rospy.loginfo("uArm detach")
        self.send_to_interface_queue("DET")

    def request_attach(self):
        rospy.loginfo("uArm attach")
        self.send_to_interface_queue("ATT")

    def pump_on(self):
        rospy.loginfo("uArm Pump On")
        self.send_to_interface_queue("PUMP_ON")

    def pump_off(self):
        rospy.loginfo("uArm Pump Off")
        self.send_to_interface_queue("PUMP_OFF")

    @ros_try_catch
    def read_analog(self, pin_num):
        return round(self.uarm.get_analog(pin_num), 3)

    @ros_try_catch
    def get_joint_angles(self):
        return self.uarm.get_servo_angle()

    @ros_try_catch
    def read_position(self):
        return self.uarm.get_position()

    @ros_try_catch
    def read_joint_angles(self):
        # return [self.get_joint_angles(), time.time()]
        return self.get_joint_angles()

    def uarm_read(self):
        rospy.loginfo("uarm_read running")
        while True and (rospy.is_shutdown() is False):
            robot_values = self.get_from_read_queue(blocking=False)
            if robot_values == "SHUTDOWN":
                rospy.logwarn("sending shutdown signal")
                rospy.signal_shutdown("Normal Shutdown Procedure")
                break
            elif not robot_values:
                pass
            elif robot_values == "DONE":
                self.uarm_read_pub.publish("DONE")
            else:
                msg = str(robot_values)
                msg = msg.translate(None, '[]')
                self.uarm_read_pub.publish(msg)
                #self.ros_rate.sleep()

        rospy.loginfo("uarm_read shutdown")

    def send_to_interface_queue(self, msg, msg_list=False, priority=10):
        with self.interface_queue_put_lock:
            if msg_list:
                for m in msg_list:
                    self.uarm_interface_queue.put((priority,m))
            else:
                self.uarm_interface_queue.put((priority, msg))

    # def send_to_interface_queue(self, msg, msg_list=False, priority=False):
    #     with self.interface_queue_put_lock:
    #         if msg_list:
    #             if priority:
    #                 msg_list = msg + self.get_from_interface_queue(all_msgs=True)
    #             for m in msg_list:
    #                 self.uarm_interface_queue.put(m)
    #         else:
    #             if priority:
    #                 msg_list = [msg] + self.get_from_interface_queue(all_msgs=True)
    #                 for m in msg_list:
    #                     self.uarm_interface_queue.put(m)
    #             else:
    #                 self.uarm_interface_queue.put(msg)

    def filter_interface_queue(self, msg_filter, invert=False):
        msgs = self.get_from_interface_queue(all_msgs=True, blocking=True)
        if msg_filter is not "":
            # print "FILTER: ", filter
            n = 0
            for i, msg in enumerate(msgs):
                if filter in msg and not invert:
                    msgs.pop(i)
                    n += 1
                elif filter not in msg and invert:
                    msgs.pop(i)
                    n += 1
            if msgs is not []:
                # print n, " messages filtered matching search terms", filter, invert
                # print msgs
                #self.send_to_interface_queue(msgs, msg_list=True, priority=True)
                self.send_to_interface_queue(msgs, msg_list=True, priority=1)

    def get_from_interface_queue(self, all_msgs=False, blocking=False):
        with self.interface_queue_get_lock:
            if all_msgs:
                msgs = []
                while self.uarm_interface_queue.qsize() > 0:
                    try:
                        msg = self.uarm_interface_queue.get(blocking)
                        try:
                            msg = msg[1]
                        except:
                            pass
                        print msg
                        msgs.append(msg)

                    except Queue.Empty:
                        msgs = []

                return msgs
            else:
                try:
                    msg = self.uarm_interface_queue.get(blocking)
                except Queue.Empty:
                    msg = ""
                try:
                    msg = msg[1]
                except:
                    pass
                return msg

    def send_to_read_queue(self, msg, msg_list=False, priority=10):
        with self.read_queue_put_lock:
            if msg_list:
                for m in msg:
                    self.uarm_read_queue.put((priority,m))
            else:
                self.uarm_read_queue.put((priority,msg))

    # def send_to_read_queue(self, msg, msg_list=False, priority=False):
    #     with self.read_queue_put_lock:
    #         if msg_list:
    #             if priority:
    #                 msg_list = msg + self.get_from_read_queue(all_msgs=True)
    #             for m in msg_list:
    #                 self.uarm_read_queue.put(m)
    #         else:
    #             if priority:
    #                 # print "Sending priority message, read_queue:", msg
    #                 msg_list = [msg] + self.get_from_read_queue(all_msgs=True)
    #                 for m in msg_list:
    #                     self.uarm_read_queue.put(m)
    #             else:
    #                 self.uarm_read_queue.put(msg)

    def get_from_read_queue(self, all_msgs=False, blocking=False):
        with self.read_queue_get_lock:
            if all_msgs:
                msgs = []
                while self.uarm_read_queue.qsize() > 0:
                    try:
                        msg = self.uarm_read_queue.get(blocking)
                        try:
                            msg = msg[1:]
                        except:
                            pass
                        msgs.append()
                    except Queue.Empty:
                        msgs = []
                return msgs
            else:
                try:
                    msg = self.uarm_read_queue.get(blocking)
                    try:
                        msg = msg[1:]
                    except:
                        pass

                except Queue.Empty:
                    msg = ""
                return msg

    def uarm_write_callback(self, data):
        # print "DATA: ", data.data
        if data.data == "CLEAR":
                self.get_from_interface_queue(all_msgs=True)
                self.get_from_read_queue(all_msgs=True)

        elif data.data[0] == "!":
                msg = data.data[1:]
                #print msg
                #self.send_to_interface_queue(msg, priority=True)
                self.send_to_interface_queue(msg, priority=1)
        else:
                self.send_to_interface_queue(data.data)

    def playback(self):
        if self.playback_data:
            self.loading = False
            self.get_from_interface_queue(all_msgs=True)  # flush queue
            try:
                joint_angles = self.ja
                self.send_to_interface_queue("JA"+str(joint_angles[0]) + "," +
                                             str(joint_angles[1]) + "," +
                                             str(joint_angles[2]) +
                                             str(joint_angles[3]))
            except Exception as e:
                # print "joint angles not ready yet: ", e
                err = str(e.message)
                rospy.logerr("joint angles not ready yet: " + err)
                rospy.signal_shutdown("joint angles not ready yet")

            self.send_to_interface_queue("ATT")

            self.filter_interface_queue("READ")

            for line in self.playback_data:
                # print self.playback_active, line
                if self.playback_active is False:
                    self.get_from_interface_queue(all_msgs=True)
                    break
                msg = str(line)

                self.send_to_interface_queue("READ")
                self.send_to_interface_queue(msg)

        self.send_to_interface_queue("BEEP")
        self.send_to_interface_queue("DET")
        self.playback_data = []

    def load_playback_data(self, data_line):
        self.loading = True
        rospy.loginfo("Loading playback data...")
        self.playback_data.append(data_line)

    @ros_try_catch
    def process_command(self, command):
        if command == "PUMP_ON":
            self.uarm.set_pump(1)

        if command == "PUMP_OFF":
            self.uarm.set_pump(0)

        if command == "ATT":
            self.uarm.set_servo_attach()

        if command == "DET":
            self.uarm.set_servo_detach()

        if command[0:3] == "POS" and self.playback_active:
            position = map(float, command[3:].split(','))
            self.uarm.set_position(position[0], position[1], position[2])

        if command[0:3] == "REL":
            adjust = float(command[3:])
            # print adjust
            self.uarm.set_position(x=0, y=0, z=adjust, speed=0, relative=True)

        if command[0:2] == "JA" and self.playback_active:
            angle = map(float, command[2:].split(','))
            for i in range(0, len(angle)-1):
                self.uarm.set_servo_angle(i, angle[i])

        if command[0:4] == "LOAD":
            self.load_playback_data(command[4:])

        if command == "PLAY":
            if self.playback_data:
                self.playback_active = True
                self.playback_thread = threading.Thread(target=self.playback)
                self.playback_thread.daemon = True

                self.playback_thread.start()
        if command == "BEEP":
            self.uarm.set_buzzer(10000, 0.1)
            #self.send_to_read_queue("DONE", priority=True)
            self.send_to_read_queue("DONE", priority=1)
            self.playback_active = False

        if command == "STOP":
            self.playback_active = False
            self.filter_interface_queue(msg_filter="READ")
            time.sleep(0.5)
            self.filter_interface_queue(msg_filter="JA")
            self.playback_data = []
<|endoftext|>