示例#1
0
文件: config.py 项目: yesrod/hoplite
 def __init__(self, config_file="config.json", debug=False):
     self.debug = debug
     utils.debug_msg(self, "load config start")
     self.config_file = config_file
     try:
         save = open(self.config_file, "r")
         config = json.load(save)
         save.close()
     except IOError:
         print("No config found at %s, using defaults" % self.config_file)
         config = self.build_config()
     except ValueError:
         print("Config at %s has syntax issues, cannot load" %
               self.config_file)
         config = None
     utils.debug_msg(self, config)
     self.config = config
     utils.debug_msg(self, "checking for required values")
     required = {'display': 'st7735', 'weight_mode': 'as_kg_gross'}
     for r in required.keys():
         if not r in self.config.keys():
             utils.debug_msg(self,
                             "adding default: %s %s" % (r, required[r]))
             self.config[r] = required[r]
     utils.debug_msg(self, "load config end")
示例#2
0
文件: display.py 项目: yesrod/hoplite
    def __init__(self, hoplite, display):
        self.display = display
        self.h = hoplite
        self.debug = self.h.debug

        resource_package = __name__
        resource_path = ''
        static_path = pkg_resources.resource_filename(resource_package, resource_path)

        self.font = ImageFont.truetype('%s/font/OpenSans-Regular.ttf' % static_path, 16)

        if self.display == None:
            utils.debug_msg(self, "Display not found, using default of st7735")
            self.display = 'st7735'

        try:
            parser = cmdline.create_parser(description='HOPLITE display args')
            conf = cmdline.load_config('%s/conf/%s.conf' % (static_path, display))
            args = parser.parse_args(conf)
        except FileNotFoundError:
            conf = ['--display=%s' % display]
            args = parser.parse_args(conf)

        try:
            self.device = cmdline.create_device(args)
        except error.Error as e:
            parser.error(e)
            self.device = None
示例#3
0
文件: restapi.py 项目: yesrod/hoplite
def add_channel(index, channel, data):
    if channel != 'A' and channel != 'B':
        return error(400, 'No such channel %s at index %s' % (channel, index))

    required_keys = ('name', 'size', 'tare', 'volume')
    optional_keys = {'co2': False, 'refunit': 0, 'offset': 0}
    submission = dict()
    for key in required_keys:
        if not key in data.keys():
            return error(400, 'Key %s is required' % key)
        submission[key] = data[key]
    for key in optional_keys.keys():
        if not key in data.keys():
            submission[key] = optional_keys[key]
        else:
            submission[key] = data[key]
    try:
        instance.ShData['config']['hx'][int(
            index)]['channels'][channel] = submission
        instance.shmem_write()
        return response(False, 200, {channel: submission},
                        '%s successfully created or updated' % channel)
    except IndexError:
        utils.debug_msg(instance, traceback.format_exc())
        return error(400, 'No existing index %s' % index)
示例#4
0
文件: web.py 项目: yesrod/hoplite
    def apply_settings(self, widget):
        utils.debug_msg(self, "start")
        self.settings_up = False

        weight_mode = self.settings_dialog.get_field(
            'weight_options').get_value()
        self.api_write('PUT', 'weight_mode', {'weight_mode': weight_mode})
        utils.debug_msg(self, "end")
示例#5
0
文件: web.py 项目: yesrod/hoplite
    def edit_keg_channel_handler(self, widget, channel):
        utils.debug_msg(self, "start")
        port = self.edit_keg_dialog.get_field(
            'port_box').children['1'].get_value()
        hx_list = self.api_data['hx_list']
        index = utils.get_index_from_port(port, hx_list)

        self.fill_edit_keg(index, channel)
        utils.debug_msg(self, "end")
示例#6
0
文件: restapi.py 项目: yesrod/hoplite
def delete_index(index):
    try:
        deleted_data = instance.ShData['config']['hx'][int(index)]
        del instance.ShData['config']['hx'][int(index)]
        instance.shmem_write()
        return response(False, 200, {index: deleted_data},
                        '%s successfully deleted' % index)
    except IndexError:
        utils.debug_msg(instance, traceback.format_exc())
        return error(400, 'No existing index %s' % index)
示例#7
0
文件: web.py 项目: yesrod/hoplite
 def delete_keg(self, widget, index, channel):
     utils.debug_msg(self, "start")
     self.delete_keg_up = False
     self.delete_keg_dialog.hide()
     if len(self.api_data['hx_list'][index]['channels'].keys()) <= 1:
         endpoint = 'hx/%s/' % str(index)
         self.api_delete(endpoint)
     else:
         endpoint = 'hx/%s/%s/' % (str(index), channel)
         self.api_delete(endpoint)
     utils.debug_msg(self, "end")
示例#8
0
文件: web.py 项目: yesrod/hoplite
 def get_port_data(self, dialog):
     utils.debug_msg(self, "start")
     new_conf = dict()
     new_conf['port'] = dialog.get_field(
         'port_box').children['1'].get_value()
     new_conf['pd_sck'] = dialog.get_field(
         'hx_pins').children['1'].get_value()
     new_conf['dout'] = dialog.get_field(
         'hx_pins').children['3'].get_value()
     new_conf['channel'] = dialog.get_field(
         'channel_box').children['1'].get_value()
     utils.debug_msg(self, "end")
     return new_conf
示例#9
0
文件: restapi.py 项目: yesrod/hoplite
def delete_channel(index, channel):
    try:
        deleted_data = instance.ShData['config']['hx'][int(
            index)]['channels'][channel]
        del instance.ShData['config']['hx'][int(index)]['channels'][channel]
        instance.shmem_write()
        return response(False, 200, {channel: deleted_data},
                        '%s successfully deleted' % channel)
    except KeyError:
        utils.debug_msg(instance, traceback.format_exc())
        return error(400, 'No existing channel %s' % channel)
    except IndexError:
        utils.debug_msg(instance, traceback.format_exc())
        return error(400, 'No existing index %s' % index)
示例#10
0
文件: web.py 项目: yesrod/hoplite
    def set_keg_gui_data(self, dialog, keg_box_id, new_conf):
        utils.debug_msg(self, "start")
        utils.debug_msg(self, "new_conf: %s" % new_conf)
        utils.debug_msg(self, "keg_box_id: %s" % keg_box_id)
        keg_box = dialog.get_field(keg_box_id)

        keg_box.children['name'].children['val'].set_value(
            new_conf.get('name', ''))
        keg_box.children['size'].children['val'].set_value(
            new_conf.get('size', ''))
        keg_box.children['co2_box'].children['1'].set_value(
            new_conf.get('co2', False))

        if new_conf['size'] == 'custom':
            keg_box.children['custom'].children['1'].set_value(
                str(new_conf.get('volume', '')))
            keg_box.children['custom'].children['3'].set_value(
                str(new_conf.get('tare', '')))
        else:
            try:
                pd_sck = utils.keg_data[new_conf['size']][0]
                dout = utils.keg_data[new_conf['size']][1]
            except KeyError:
                pd_sck = ''
                dout = ''
            keg_box.children['custom'].children['1'].set_value(str(pd_sck))
            keg_box.children['custom'].children['3'].set_value(str(dout))
        utils.debug_msg(self, "end")
示例#11
0
文件: restapi.py 项目: yesrod/hoplite
 def set_display():
     data = validate_request()
     if data == None:
         return error(400, 'Bad Request - invalid JSON')
     else:
         try:
             display = data['display']
         except KeyError:
             utils.debug_msg(instance, traceback.format_exc())
             return error(400, 'Bad Request - no display in request')
         instance.ShData['config']['display'] = display
         instance.shmem_write()
         return response(False, 200, {'display': display},
                         'display successfully updated')
示例#12
0
文件: web.py 项目: yesrod/hoplite
    def idle(self):
        utils.debug_msg(self, "start")

        self.api_read()
        self.co2_list = []
        self.container.children['keg_table'] = self.build_keg_table()
        t = utils.as_degF(self.api_data.get('temp', 0))
        try:
            co2 = self.co2_list[0]  #TODO: Handle multiple CO2 sources
        except IndexError:
            co2 = "???"
        self.temp.set_text("%s\nCO2:%s%%" % (t, co2))

        utils.debug_msg(self, "end")
示例#13
0
文件: display.py 项目: yesrod/hoplite
    def fill_bar(self, x, y, min_w, max_w, w, outline="white", fill=None):
        net_w = max(w - min_w, 0)
        max_net_w = max_w - min_w
        fill_percent = float(net_w) / float(max_net_w)
        max_y = self.device.height - 21
        min_y = y+1
        max_bar = max_y - min_y
        fill_height = max(min_y, min_y + (max_bar - (max_bar * fill_percent)))

        if fill == None:
            fill = utils.fill_bar_color(fill_percent)

        self.draw.rectangle([x,y, x+20,self.device.height-20], outline=outline, fill="black")
        self.draw.rectangle([x+1,fill_height, x+19,max_y], outline=fill, fill=fill)
        utils.debug_msg(self, "%s: %s" % (fill_percent, fill)) 
示例#14
0
文件: hoplite.py 项目: yesrod/hoplite
    def __init__(self, debug=False):
        # debug flag - this should be first
        self.debug = debug
        utils.debug_msg(self, "init start")

        # while true, run update loop
        self.updating = False

        # config file location
        self.config_file = None

        # temperature sensor output
        # TODO: evaluate if this can be replaced by read_temp()
        self.temp = None

        utils.debug_msg(self, "init end")
示例#15
0
文件: web.py 项目: yesrod/hoplite
 def api_delete(self, endpoint):
     utils.debug_msg(self, "start")
     headers = {'Content-Type': 'application/json'}
     dest_url = self.api_url + endpoint
     response = requests.delete(dest_url, headers=headers)
     if response.status_code != "200":
         utils.debug_msg(self, "response: %s" % response.json())
         utils.debug_msg(self, dest_url)
     utils.debug_msg(self, "end")
示例#16
0
文件: restapi.py 项目: yesrod/hoplite
def add_index(data):
    new_index = dict()
    for key in ('pd_sck', 'dout'):
        if not key in data.keys():
            return error(400, 'Key %s is required' % key)
        new_index[key] = data[key]

    new_index['channels'] = dict()
    if not 'channels' in data.keys():
        return error(
            400,
            'channels must be a JSON object containing one or more channels')
    try:
        for channel in data['channels'].keys():
            if channel not in ('A', 'B'):
                return error(400,
                             'Invalid channel %s - must be A or B' % channel)

            required_keys = ('name', 'size', 'tare', 'volume')
            optional_keys = {'co2': False, 'refunit': 0, 'offset': 0}
            submission = dict()
            for key in required_keys:
                if not key in data['channels'][channel].keys():
                    return error(
                        400, 'Channel %s key %s is required' % (channel, key))
                submission[key] = data['channels'][channel][key]
            for key in optional_keys.keys():
                if not key in data['channels'][channel].keys():
                    submission[key] = optional_keys[key]
                else:
                    submission[key] = data['channels'][channel][key]
            new_index['channels'][channel] = submission

    except AttributeError:
        utils.debug_msg(instance, traceback.format_exc())
        return error(
            400,
            'channels must be a JSON object containing one or more channels also represented as JSON objects'
        )

    instance.ShData['config']['hx'].append(new_index)
    instance.shmem_write()
    last_index = len(instance.ShData['config']['hx']) - 1
    return response(False, 200, {last_index: new_index},
                    'Index %s successfully created or updated' % last_index)
示例#17
0
文件: web.py 项目: yesrod/hoplite
    def fill_port_info(self, index, port):
        utils.debug_msg(self, "start")
        try:
            hx_conf = self.api_data['hx_list'][index]
            self.edit_keg_dialog.get_field('hx_pins').children['1'].set_value(
                str(hx_conf.get('pd_sck', '')))
            self.edit_keg_dialog.get_field('hx_pins').children['3'].set_value(
                str(hx_conf.get('dout', '')))

        except (KeyError, IndexError, TypeError):
            if port != "custom":
                self.edit_keg_dialog.get_field(
                    'hx_pins').children['1'].set_value(
                        str(utils.breakout_ports[port][0]))
                self.edit_keg_dialog.get_field(
                    'hx_pins').children['3'].set_value(
                        str(utils.breakout_ports[port][1]))
        utils.debug_msg(self, "end")
示例#18
0
文件: hoplite.py 项目: yesrod/hoplite
    def init_hx711(self, hx_conf):
        utils.debug_msg(self, "init hx711 start")
        dout = int(hx_conf['dout'])
        pd_sck = int(hx_conf['pd_sck'])

        try:
            offset_A = hx_conf['channels']['A']['offset']
            refunit_A = hx_conf['channels']['A']['refunit']
        except (ValueError, KeyError):
            offset_A = None
            refunit_A = None
        try:
            offset_B = hx_conf['channels']['B']['offset']
            refunit_B = hx_conf['channels']['B']['refunit']
        except (ValueError, KeyError):
            offset_B = None
            refunit_B = None

        hx = HX711(dout, pd_sck)
        hx.set_reading_format("MSB", "MSB")
        hx.reset()

        if refunit_A is not None and offset_A is not None:
            try:
                hx.set_reference_unit_A(refunit_A)
            except ValueError:
                print("Bad channel A reference unit %s, using 1" % refunit_A)
                hx.set_reference_unit_A(1)
            hx.set_offset_A(offset_A)
        else:
            hx.set_reference_unit_A(1)

        if refunit_B is not None and offset_B is not None:
            try:
                hx.set_reference_unit_B(refunit_B)
            except ValueError:
                print("Bad channel B reference unit %s, using 1" % refunit_B)
                hx.set_reference_unit_B(1)
            hx.set_offset_B(offset_B)
        else:
            hx.set_reference_unit_B(1)

        utils.debug_msg(self, "init hx711 end")
        return hx
示例#19
0
文件: web.py 项目: yesrod/hoplite
 def api_read(self, force=False):
     utils.debug_msg(self, "start")
     since_last_update = int(time.time()) - self.api_last_updated
     if since_last_update > self.api_update_interval or force:
         response = requests.get(self.api_url)
         self.api_data = response.json()['data']['v1']
         self.api_last_updated = int(time.time())
         utils.debug_msg(self, "api_data: %s" % self.api_data)
     else:
         utils.debug_msg(
             self, "not updating, last update %is ago" % since_last_update)
     utils.debug_msg(self, "end")
示例#20
0
文件: restapi.py 项目: yesrod/hoplite
 def set_weight_mode():
     data = validate_request()
     if data == None:
         return error(400, 'Bad Request - invalid JSON')
     else:
         try:
             weight_mode = data['weight_mode']
         except KeyError:
             utils.debug_msg(instance, traceback.format_exc())
             return error(400, 'Bad Request - no weight_mode in request')
         valid_modes = ('as_kg_gross', 'as_kg_net', 'as_pint', 'as_pct')
         if not weight_mode in valid_modes:
             return error(
                 400, 'Bad Request - invalid weight_mode %s' % weight_mode)
         else:
             instance.ShData['config']['weight_mode'] = weight_mode
             instance.shmem_write()
             return response(False, 200, {'weight_mode': weight_mode},
                             'weight_mode successfully updated')
示例#21
0
文件: web.py 项目: yesrod/hoplite
    def apply_edit_keg(self, widget):
        utils.debug_msg(self, "start")
        self.edit_keg_up = False

        self.api_read(force=True)
        hx_list = self.api_data['hx_list']

        port_conf = self.get_port_data(self.edit_keg_dialog)
        port = port_conf['port']
        index = utils.get_index_from_port(port, hx_list)
        channel = port_conf['channel']

        if index != None:
            for attribute in ('pd_sck', 'dout'):
                endpoint = 'hx/%s/%s' % (str(index), attribute)
                self.api_write('PUT', endpoint,
                               {attribute: port_conf[attribute]})

            try:
                chan = hx_list[index]['channels'][channel]
            except KeyError:
                chan = {}
            new_conf = self.get_keg_gui_data(self.edit_keg_dialog, 'keg_box')
            chan['name'] = new_conf['name']
            chan['size'] = new_conf['size']
            chan['volume'] = new_conf['volume']
            chan['tare'] = new_conf['tare']
            chan['co2'] = new_conf['co2']
            endpoint = 'hx/%s/%s/' % (str(index), channel)
            self.api_write('POST', endpoint, chan)

        else:
            hx = dict()
            hx['pd_sck'] = port_conf['pd_sck']
            hx['dout'] = port_conf['dout']
            hx['channels'] = dict()
            hx['channels'][channel] = self.get_keg_gui_data(
                self.edit_keg_dialog, 'keg_box')
            endpoint = 'hx/'
            self.api_write('POST', endpoint, hx)

        self.api_read(force=True)
        utils.debug_msg(self, "end")
示例#22
0
文件: restapi.py 项目: yesrod/hoplite
def get_all_hx_with_weight():
    hxs = list()
    try:
        utils.debug_msg(instance, "get keg config")
        hxs_config = instance.ShData['config']['hx']
        utils.debug_msg(instance, "enumerate hx")
        for index, hx in enumerate(hxs_config):
            utils.debug_msg(instance, "hx %s" % index)
            hxs.insert(index, add_weight_to_hx(index, hx))
    except (IndexError, KeyError, ValueError):
        utils.debug_msg(instance, traceback.format_exc())
    return hxs
示例#23
0
文件: web.py 项目: yesrod/hoplite
    def show_delete_keg_confirm(self, widget, index, channel):
        utils.debug_msg(self, "start")
        if self.delete_keg_up == True:
            return
        else:
            self.delete_keg_up = True

        self.delete_keg_dialog = gui.GenericDialog(title='DELETE Keg?',
                                                   width=240)
        warning_label = gui.Label(
            "Are you sure you want to delete keg at index %s channel %s?" %
            (index, channel))
        self.delete_keg_dialog.append(warning_label)
        self.delete_keg_dialog.set_on_cancel_dialog_listener(
            self.cancel_delete_keg)
        self.delete_keg_dialog.children['buttons_container'].children[
            'confirm_button'].onclick.do(self.delete_keg, index, channel)
        self.delete_keg_dialog.show(self)
        utils.debug_msg(self, "end")
示例#24
0
文件: hoplite.py 项目: yesrod/hoplite
 def read_co2(self):
     co2 = list()
     for index, hx_conf in enumerate(self.config.get('hx')):
         for channel in ['A', 'B']:
             try:
                 if hx_conf['channels'][channel]['co2'] == True:
                     local_w = self.hx711_read_ch(self.hx_handles[index],
                                                  channel)
                     local_max = hx_conf['channels'][channel][
                         'volume'] * 1000
                     local_tare = hx_conf['channels'][channel]['tare'] * 1000
                     utils.debug_msg(
                         self, "channel %s: %s, %s, %s" %
                         (channel, local_w, local_max, local_tare))
                     local_net_w = max((local_w - local_tare), 0)
                     local_pct = local_net_w / float(local_max)
                     co2.append(int(local_pct * 100))
             except KeyError:
                 pass
     return co2
示例#25
0
文件: web.py 项目: yesrod/hoplite
 def fill_edit_keg(self, index, channel, empty=False):
     utils.debug_msg(self, "start")
     new_conf = {}
     try:
         hx_conf = self.api_data['hx_list'][index]['channels'][channel]
         new_conf['volume'] = hx_conf['volume']
         new_conf['tare'] = hx_conf['tare']
         new_conf['name'] = hx_conf['name']
         new_conf['size'] = hx_conf['size']
         new_conf['co2'] = hx_conf['co2']
     except (KeyError, IndexError, TypeError):
         new_conf['volume'] = ''
         new_conf['tare'] = ''
         new_conf['name'] = ''
         new_conf['size'] = ''
         new_conf['co2'] = False
     self.set_keg_gui_data(self.edit_keg_dialog, 'keg_box', new_conf)
     self.edit_keg_dialog.set_on_confirm_dialog_listener(
         self.apply_edit_keg)
     utils.debug_msg(self, "end")
示例#26
0
文件: web.py 项目: yesrod/hoplite
    def edit_keg_port_handler(self, widget, port):
        utils.debug_msg(self, "start")
        hx_list = self.api_data['hx_list']
        pd_sck = self.edit_keg_dialog.get_field('hx_pins').children['1']
        dout = self.edit_keg_dialog.get_field('hx_pins').children['3']
        if port == 'custom':
            pd_sck.set_enabled(True)
            dout.set_enabled(True)
            custom_values = (pd_sck.get_value(), dout.get_value())
            index = utils.get_index_from_port(port, custom_values)
        else:
            pd_sck.set_enabled(False)
            dout.set_enabled(False)
            index = utils.get_index_from_port(port, hx_list)

        channel = self.edit_keg_dialog.get_field(
            'channel_box').children['1'].get_value()

        self.fill_edit_keg(index, channel)
        self.fill_port_info(index, port)
        utils.debug_msg(self, "end")
示例#27
0
文件: hoplite.py 项目: yesrod/hoplite
    def runtime_init(self):
        # All the stuff needed for runtime lives here so the Hoplite class
        # can pe imported into other things for stuff like loading configs
        # without breaking GPIO access, etc.
        utils.debug_msg(self, "runtime init start")

        # dictionary containing current shared memory data
        self.ShData = dict()

        # dict containing current config
        self.config = Config(self.config_file, debug=self.debug)

        # list of handles for all keg HX711's found in config
        self.hx_handles = list()

        # co2 weights are a list now, could be multiple co2 cylinders
        self.co2_w = list()

        # REST API class
        self.api = RestApi(self)

        # output display
        try:
            self.display = Display(self, self.config.get('display'))
        except KeyError:
            utils.debug_msg(
                self, "Display not found in config, using default st7735")
            self.display = Display(self, 'st7735')

        utils.debug_msg(self, "runtime init end")
示例#28
0
文件: hoplite.py 项目: yesrod/hoplite
    def main(self, config_file='config.json', api_listen=None):
        self.config_file = config_file
        self.runtime_init()
        if self.config.config == None:
            print("No valid config, bailing out")
            sys.exit()

        utils.debug_msg(self, "debug enabled")

        self.ShData['data'] = dict()
        self.ShData['data']['weight'] = list()
        self.ShData['config'] = self.config.config

        self.setup_all_kegs()

        utils.debug_msg(self, 'api listener: %s' % api_listen)
        if api_listen != None:
            api_listen_split = api_listen.split(':')
            if len(api_listen_split) == 2:
                api_host = api_listen_split[0]
                api_port = api_listen_split[1]
            elif len(api_listen_split) == 1:
                api_host = api_listen_split[0]
                api_port = '5000'
            else:
                print(
                    'Incorrect formatting for API listen address, using defaults'
                )
                api_host = '0.0.0.0'
                api_port = '5000'
        else:
            api_host = '0.0.0.0'
            api_port = '5000'

        print('Starting API at %s:%s' % (api_host, api_port))
        self.api_process = threading.Thread(None,
                                            self.api.worker,
                                            'hoplite REST api',
                                            kwargs={
                                                'host': api_host,
                                                'port': api_port
                                            })
        self.api_process.daemon = True
        self.api_process.start()

        try:
            self.updating = True
            self.update_process = threading.Thread(None, self.update,
                                                   'hoplite data collection')
            self.update_process.daemon = True
            self.update_process.start()
            while self.updating:
                time.sleep(1)
        except (KeyboardInterrupt, SystemExit, RuntimeError):
            utils.debug_msg(self, "stop updating")
            self.updating = False
            self.update_process.join(30)
            self.cleanup()
            sys.exit()
示例#29
0
文件: web.py 项目: yesrod/hoplite
    def get_keg_gui_data(self, dialog, keg_box_id):
        utils.debug_msg(self, "start")
        keg_box = dialog.get_field(keg_box_id)
        utils.debug_msg(self, "keg_box: %s" % keg_box)

        new_size = keg_box.children['size'].children['val'].get_value(
        )  # this takes forever sometimes to actually select, need to investigate
        utils.debug_msg(self, "new_size: %s" % new_size)
        if new_size == 'custom':
            vol = float(keg_box.children['custom'].children['1'].get_value())
            tare = float(keg_box.children['custom'].children['3'].get_value())
        else:
            vol = utils.keg_data[new_size][0]
            tare = utils.keg_data[new_size][1]

        new_conf = dict()
        new_conf['name'] = keg_box.children['name'].children['val'].get_value()
        new_conf['size'] = new_size
        new_conf['co2'] = keg_box.children['co2_box'].children['1'].get_value()
        new_conf['volume'] = vol
        new_conf['tare'] = tare
        utils.debug_msg(self, "new_conf: %s" % new_conf)
        utils.debug_msg(self, "end")
        return new_conf
示例#30
0
文件: restapi.py 项目: yesrod/hoplite
def validate_request():
    try:
        data = request.json
        utils.debug_msg(instance, data)
    except BadRequest:
        utils.debug_msg(instance, traceback.format_exc())
        utils.debug_msg(instance,
                        "request is not valid JSON: %s" % request.get_data())
        data = None
    return data