Esempio n. 1
0
def activate_plugin(plugin, config=None, db=None):
	if not config:
		config = ConfigService()
	if not db:
		db = Database(config)
		
	plugins_path = config.get('general', 'plugins_path')
	fabui_path = config.get('general', 'fabui_path')

	plugin_dir = os.path.join(plugins_path, plugin)
	
	if not os.path.exists(plugin_dir):
		return False

	# Link controller
	create_link( os.path.join(plugin_dir, 'controller.php'), os.path.join(fabui_path, 'application/controllers/Plugin_{0}.php'.format(plugin) ) ) 
	# Link views
	create_dir(os.path.join( fabui_path, 'application/views/plugin' ) )
	create_link( os.path.join(plugin_dir, 'views'), os.path.join(fabui_path, 'application/views/plugin/{0}'.format(plugin)) ) 
	# Link assets
	create_dir( os.path.join( fabui_path, 'assets/plugin' ) )
	create_link( os.path.join(plugin_dir, 'assets'), os.path.join(fabui_path, 'assets/plugin/{0}'.format(plugin)) ) 

	meta_file = os.path.join( plugin_dir, "meta.json" )

	with open(meta_file) as f:
		meta_content = f.read()

	p = Plugin(db)
	p['name'] = plugin
	p['attributes'] = meta_content
	p.write()

	return True
Esempio n. 2
0
class Translation():
    def __init__(self, config=None):
        if not config:
            self.config = ConfigService()

        self.tr = gettext.translation('fabui',
                                      '/usr/share/fabui/locale',
                                      fallback=True)
        self.tp = gettext.translation('fabui',
                                      '/usr/share/fabui/locale',
                                      fallback=True)

    def setLanguage(self, lang, domain='fabui'):

        locale_path = self.config.get('general', 'locale_path')
        self.tr = gettext.translation('fabui',
                                      locale_path,
                                      fallback=True,
                                      languages=[lang])

    def setPluginLanguage(self, plugin_name, lang):
        plugins_path = self.config.get('general', 'plugins_path')
        locale_path = '{0}{1}/locale'.format(plugins_path, plugin_name)
        self.tp = gettext.translation(plugin_name,
                                      locale_path,
                                      fallback=True,
                                      languages=[lang])

    def get(self, text):

        t = self.tp.gettext(text)
        if t == text:
            t = self.tr.gettext(text)
        return t
Esempio n. 3
0
def main():
    from ws4py.client.threadedclient import WebSocketClient
    from fabtotum.fabui.notify       import NotifyService
    from fabtotum.utils.pyro.gcodeclient import GCodeServiceClient
    from fabtotum.fabui.config import ConfigService
    from fabtotum.os.paths     import RUN_PATH
    import logging
    import argparse
    import os
    
    
    # Setup arguments
    parser = argparse.ArgumentParser()
    parser.add_argument("-L", "--log", help="Use logfile to store log messages.",   default='/var/log/fabui/gpiomonitor.log')
    parser.add_argument("-p", "--pidfile", help="File to store process pid.",       default=os.path.join(RUN_PATH, 'gpiomonitor.pid') )

    # Get arguments
    args = parser.parse_args()
    pidfile = args.pidfile
    
    with open(pidfile, 'w') as f:
        f.write( str(os.getpid()) )
    
    config = ConfigService()

    # Load configuration
    NOTIFY_FILE         = config.get('general', 'notify_file')
    ##################################################################
    SOCKET_HOST         = config.get('socket', 'host')
    SOCKET_PORT         = config.get('socket', 'port')
    ##################################################################
    EVENT_PIN           = config.get('totumduino', 'event_pin')
    
    # Pyro GCodeService wrapper
    gcs = GCodeServiceClient()
    
    ws = WebSocketClient('ws://'+SOCKET_HOST +':'+SOCKET_PORT+'/')
    ws.connect();

    # Notification service
    ns = NotifyService(ws, NOTIFY_FILE, config)
    
    # Setup logger
    logger2 = logging.getLogger('GPIOMonitor')
    logger2.setLevel(logging.DEBUG)
    fh = logging.FileHandler(args.log, mode='w')

    #~ formatter = logging.Formatter("%(name)s - %(levelname)s : %(message)s")
    formatter = logging.Formatter("[%(asctime)s] %(levelname)s : %(message)s")
    fh.setFormatter(formatter)
    fh.setLevel(logging.DEBUG)
    logger2.addHandler(fh)
    
    gpioMonitor = GPIOMonitor(ns, gcs, logger2, EVENT_PIN)
    gpioMonitor.start()
    gpioMonitor.loop()
Esempio n. 4
0
def main():
    config = ConfigService()

    # SETTING EXPECTED ARGUMENTS
    parser = argparse.ArgumentParser(
        formatter_class=argparse.ArgumentDefaultsHelpFormatter)
    parser.add_argument("-T", "--task-id", help="Task ID.", default=0)
    parser.add_argument("-F", "--file-name", help="File name.", required=True)
    parser.add_argument(
        "--autolevel",
        action='store_true',
        help="Auto bed leveling. Valid only when --standalone is used.",
        default=False)
    parser.add_argument("--lang",
                        help="Output language",
                        default='en_US.UTF-8')
    parser.add_argument("--email",
                        help="Send an email on task finish",
                        action='store_true',
                        default=False)
    parser.add_argument("--shutdown",
                        help="Shutdown on task finish",
                        action='store_true',
                        default=False)

    # GET ARGUMENTS
    args = parser.parse_args()

    # INIT VARs
    gcode_file = args.file_name  # GCODE FILE
    task_id = args.task_id
    autolevel = args.autolevel
    lang = args.lang
    send_email = bool(args.email)

    if task_id == 0:
        standalone = True
    else:
        standalone = False

    monitor_file = config.get(
        'general', 'task_monitor'
    )  # TASK MONITOR FILE (write stats & task info, es: temperatures, speed, etc
    log_trace = config.get('general', 'trace')  # TASK TRACE FILE

    app = PrintApplication(log_trace,
                           monitor_file,
                           standalone,
                           autolevel,
                           lang=lang,
                           send_email=send_email)

    app.run(task_id, gcode_file)
    app.loop()
Esempio n. 5
0
def main():
    config = ConfigService()

    # SETTING EXPECTED ARGUMENTS
    destination = config.get('general', 'bigtemp_path')
    
    # SETTING EXPECTED ARGUMENTS
    parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter)
    parser.add_argument("task_id",          help="Task ID." )
    parser.add_argument("-d", "--dest",     help="Destination folder."),      default=destination )
    parser.add_argument("-i", "--intrinsic",help="Intrinsic camera parameters.", default='intrinsic.json' )
    parser.add_argument("-o", "--output",   help="Extrinsic camera parameters.", default='extrinsic.json' )
    parser.add_argument("-W", "--width",    help="Image width in pixels.",   default=1296)
    parser.add_argument("-H", "--height",   help="Image height in pixels.",  default=972)
    parser.add_argument("-r", "--rotation", help="Image rotation.",          default=0)
    parser.add_argument("-x", "--x-offset", help="X offset.",                default=104)
    parser.add_argument("-y", "--y-offset", help="Y offset.",                default=117)
    parser.add_argument("-z", "--z-offset", help="Z offset.",                default=220)
    parser.add_argument("-b", "--base-height", help="Chessboard height of it's base.", default=0)
    parser.add_argument("--lang",           help="Output language", 		 default='en_US.UTF-8' )
    
    # GET ARGUMENTS    
    args = parser.parse_args()
    
    # INIT VARs
    task_id         = int(args.task_id)
    destination     = args.dest
    intrinsic_file  = args.intrinsic
    monitor_file    = config.get('general', 'task_monitor') # TASK MONITOR FILE (write stats & task info, ex: temperatures, speed, etc
    log_trace       = config.get('general', 'trace')        # TASK TRACE FILE 
    width           = int(args.width)
    height          = int(args.height)
    rotation        = int(args.rotation)
    x_offset        = float(args.x_offset)
    y_offset        = float(args.y_offset)
    z_offset        = float(args.z_offset)
    base_height     = float(args.base_height)
    output_file     = args.output
    lang			= args.lang
    output_dir      = destination

    if not os.path.exists(output_dir):
        makedirs(output_dir)
    
    app = Extrinsic(log_trace,
                  monitor_file, 
                  output_dir,
                  output_file,
                  width=width,
                  height=height,
                  rotation=rotation,
                  lang=lang)
Esempio n. 6
0
def install_plugin(plugin_filename, config=None, db=None):
	if not config:
		config = ConfigService()
		
	plugins_path = config.get('general', 'plugins_path')
	top, meta = extract_plugin(plugin_filename, config)

	if meta:
		slug = meta['plugin_slug']
		plugin_dir  = os.path.join(plugins_path, slug)
		
		installed_plugins = get_installed_plugins(config)
		active_plugins = get_active_plugins(config, db)
		
		was_active = False
		if slug in active_plugins:
			deactivate_plugin(slug, config, db)
			was_active = True
		
		if slug in installed_plugins:
			remove_plugin(slug, config)

		create_dir(plugin_dir)
		copy_files( os.path.join(top, '*'), plugin_dir)
		
		remove_dir(top)
		
		if was_active:
			activate_plugin(slug, config, db)
		
		return True
		
	return False
Esempio n. 7
0
def extract_plugin(plugin_filename, config=None):
	"""
	Extract plugin file and verify that it IS a plugin archive
	"""
	if not config:
		config = ConfigService()
		
	top = ""
	meta = {}
	
	temp_dir = build_path( config.get('general', 'temp_path'), 'new_plugin' )
	create_dir(temp_dir)
	
	cmd = 'unzip "{0}" -d "{1}" -o'.format(plugin_filename, temp_dir)
	try:
		subprocess.check_output( shlex.split(cmd) )
	except subprocess.CalledProcessError as e:
		pass
	
	fn = find_file("meta.json", temp_dir)

	try:
		fn = fn[0]
		f = open(fn)
		meta =  json.loads( f.read() )
		top = os.path.dirname(fn)
	except Exception as e:
		remove_dir(temp_dir)
	
	return top, meta
    def __init__(self, x1, x2, y1, y2, skip_homing=False, lang='en_US.UTF-8'):
        config = ConfigService()
        monitor_file = config.get('general', 'task_monitor')
        log_trace = config.get('general', 'trace')
        super(ProbeArea, self).__init__(log_trace,
                                        monitor_file,
                                        config=config,
                                        use_stdout=False,
                                        lang=lang)

        self.probe_length = 50

        self.x1 = x1
        self.x2 = x2
        self.y1 = y1
        self.y2 = y2
        self.skip_homing = skip_homing
Esempio n. 9
0
def main():
    config = ConfigService()

    # SETTING EXPECTED ARGUMENTS
    parser = argparse.ArgumentParser(
        formatter_class=argparse.ArgumentDefaultsHelpFormatter)
    parser.add_argument("-T", "--task-id", help="Task ID.", default=0)
    parser.add_argument("-e",
                        "--extruder",
                        help="Extruder to select.",
                        default=0)
    parser.add_argument("-t",
                        "--temp",
                        help="Temperature used for PID tunind.",
                        default=200)
    parser.add_argument("-c",
                        "--cycles",
                        help="Number of tuning cycles",
                        default=8)
    parser.add_argument("--lang",
                        help="Output language",
                        default='en_US.UTF-8')

    # GET ARGUMENTS
    args = parser.parse_args()

    # INIT VARs
    task_id = int(args.task_id)  # TASK ID
    monitor_file = config.get(
        'general', 'task_monitor'
    )  # TASK MONITOR FILE (write stats & task info, ex: temperatures, speed, etc
    log_trace = config.get('general', 'trace')  # TASK TRACE FILE
    temperature = int(args.temp)
    extruder = int(args.extruder)
    cycles = int(args.cycles)
    lang = args.lang

    app = PIDAutotune(log_trace, monitor_file, lang=lang)

    app_thread = Thread(target=app.run,
                        args=([task_id, extruder, temperature, cycles]))
    app_thread.start()

    # app.loop() must be started to allow callbacks
    app.loop()
    app_thread.join()
Esempio n. 10
0
def setLanguage(lang, domain='fab_diagnostic', config=None):
    if not config:
        config = ConfigService()

    locale_path = config.get('general', 'locale_path')
    
    tr = gettext.translation('fab_diagnostic', locale_path, fallback=True, languages=[lang])
    _ = tr.ugettext
    
    return _
Esempio n. 11
0
def main():
    config = ConfigService()

    # SETTING EXPECTED ARGUMENTS
    parser = argparse.ArgumentParser(
        formatter_class=argparse.ArgumentDefaultsHelpFormatter)
    parser.add_argument("-T", "--task-id", help="Task ID.", default=0)
    parser.add_argument("-n",
                        "--num_probes",
                        help="Number of probings per screw.",
                        default=1,
                        type=int)
    parser.add_argument("-s",
                        "--skip_homing",
                        action='store_true',
                        help="Skip homing.")
    parser.add_argument("--lang",
                        help="Output language",
                        default='en_US.UTF-8')

    # GET ARGUMENTS
    args = parser.parse_args()

    # INIT VARs
    task_id = int(args.task_id)
    monitor_file = config.get('general', 'task_monitor')
    log_trace = config.get('general', 'trace')
    num_probes = args.num_probes
    skip_homing = args.skip_homing
    lang = args.lang

    print "num_probes: ", num_probes

    app = ManualBedLeveling(log_trace, monitor_file, config=config, lang=lang)

    app_thread = Thread(target=app.run,
                        args=([task_id, num_probes, skip_homing]))
    app_thread.start()

    app.loop()  # app.loop() must be started to allow callbacks
    app_thread.join()
Esempio n. 12
0
def remove_plugin(plugin, config=None):
	if not config:
		config = ConfigService()
	
	plugins_path = config.get('general', 'plugins_path')
	plugin_dir = os.path.join( plugins_path, plugin )
	
	if os.path.exists(plugin_dir):
		remove_dir(plugin_dir)
		return True
		
	return False
Esempio n. 13
0
def startup(gcs):
    config = ConfigService()
    
    try:
        color = config.get('units', 'color')
    except KeyError:
        color = {
            'r' : 255,
            'g' : 255,
            'b' : 255,
        }
    
    try:
        safety_door = config.get('units', 'safety')['door']
    except KeyError:
        safety_door = 0
    
    try:
        switch = config.get('units', 'switch')
    except KeyError:
        switch = 0
    
    try:
        collision_warning = config.get('units', 'safety')['collision-warning']
    except KeyError:
        collision_warning = 0
    
    gcs.send("M728")
    gcs.send("M402")
    gcs.send("M701 S"+str(color['r']))
    gcs.send("M702 S"+str(color['g']))
    gcs.send("M703 S"+str(color['b']))
        
    gcs.send("M732 S"+str(safety_door))
    gcs.send("M714 S"+str(switch))
        
    gcs.send("M734 S"+str(collision_warning))
Esempio n. 14
0
class Database(object):
    """
    """
    
    def __init__(self, config = None):
        if not config:
            self.config = ConfigService()
        else:
            self.config = config
        
        self.lock = RLock()
        self.database_file = self.config.get('general', 'database')
        
    def get_connection(self):
        return sqlite3.connect(self.database_file)
Esempio n. 15
0
def get_installed_plugins(config=None):
	if not config:
		config = ConfigService()
		
	plugins_path = config.get('general', 'plugins_path')
	
	result = {}
	
	for dirname in os.listdir(plugins_path):
		plugin_dir = os.path.join( plugins_path, dirname)
		plugin_meta = os.path.join(plugin_dir, "meta.json")
		if os.path.exists(plugin_meta):
			with open(plugin_meta) as f:
				meta = json.loads( f.read() )
				result[dirname] = meta
				
	return result
Esempio n. 16
0
def deactivate_plugin(plugin, config=None, db=None):
	if not config:
		config = ConfigService()
	if not db:
		db = Database(config)
		
	fabui_path = config.get('general', 'fabui_path')
	
	remove_file( os.path.join(fabui_path, 'application/controllers/Plugin_{0}.php'.format(plugin) ) )
	remove_file( os.path.join(fabui_path, 'application/views/plugin/{0}'.format(plugin)) )
	remove_file( os.path.join(fabui_path, 'assets/plugin/{0}'.format(plugin)) )
	
	p = Plugin(db)
	p.query_by('name', plugin)
	p.delete()
	
	return True
Esempio n. 17
0
def reset():

    print "TOTUMDUINO: reset"

    config = ConfigService()

    reset_pin_s = config.get('totumduino', 'reset_pin', '17')
    reset_pins = reset_pin_s.split(',')

    try:
        #GPIO.setmode(GPIO.BOARD)
        GPIO.setmode(GPIO.BCM)
        GPIO.setwarnings(False)

        for pin in reset_pins:
            reset_pin = int(pin)

            GPIO.setup(reset_pin, GPIO.OUT)
            GPIO.output(reset_pin, GPIO.HIGH)
            time.sleep(0.5)
            GPIO.output(reset_pin, GPIO.LOW)

        time.sleep(0.5)

        for pin in reset_pins:
            reset_pin = int(pin)

            GPIO.output(reset_pin, GPIO.HIGH)

        GPIO.cleanup()

    except Exception as e:
        print e
        print "No GPIO support in QEMU simulation"

    time.sleep(1)
Esempio n. 18
0
''' Set the highest baudrate available '''
def testBaud(port, baud_rate):
    ser = serial.Serial(port, baud_rate, timeout=0.5)
    ser.flushInput()
    ser.write("G0\r\n")
    serial_reply=ser.readline().rstrip()
    ser.close()
    return serial_reply != ''

#serial_port = config.get('serial', 'port')

baud_list=[250000, 115200]
accepted_baud=0

for baud in baud_list:
    if(testBaud(configService.get('serial', 'PORT'), baud)):
        accepted_baud = baud
        break

if accepted_baud > 0:
    print "Baud Rate available is: " + str(accepted_baud)
    
else:
    accepted_baud=115200

if os.path.exists(SERIAL_INI) == False:
    file = open(SERIAL_INI, 'w+')
    file.write("[serial]\n")
    file.close()

config = ConfigParser.ConfigParser()
Esempio n. 19
0
def main():
    from fabtotum.fabui.config import ConfigService
    dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)

    config = ConfigService()

    # Get PRISM BT address and use it as default value if it exists
    bt_addr = config.get('bluetooth', 'prism_bt_address', '')
    bt_addr_required = True
    if bt_addr:
        bt_addr_required = False

    # Setup arguments
    parser = argparse.ArgumentParser()
    parser.add_argument("command", help="Prism management command.")
    parser.add_argument("-v",
                        dest='verbose',
                        action='store_true',
                        help="Verbose.",
                        default=False)
    parser.add_argument("--arg-list",
                        help="Comma separated argument list.",
                        default=[])
    parser.add_argument(
        "-a",
        "--address",
        help="Bluetooth address.",
        # In case there is no prism_bt_address preconfigured, fallback to asking for the address
        required=bt_addr_required,
        default=bt_addr)
    parser.add_argument("-P", "--port", help="L2C port", default=0x1001)

    args = parser.parse_args()
    cmd = args.command
    arg_list = args.arg_list
    bt_port = args.port
    bt_addr = args.address
    verbose = args.verbose

    if arg_list:
        arg_list = arg_list.split(',')

    # Ensure bluetooth is enabled
    p = subprocess.Popen(['connmanctl', 'enable', 'bluetooth'],
                         stdout=subprocess.PIPE,
                         stderr=subprocess.PIPE)
    out, err = p.communicate()

    if 'Enabled bluetooth' == out.strip():
        # Give bluetoothd some time to bring up the hci device
        time.sleep(3)
        if verbose:
            print "Bluetooth enabled"

    if cmd in ['connect', 'disconnect', 'trust', 'untrust']:
        adapter = Adapter()
        arg_list.append(adapter.Address)

    if verbose:
        print "Send: ", cmd

    print send_command(cmd, arg_list, bt_addr, bt_port, verbose)
class BTFactory():
    def __init__(self, verbose=False):

        ## init attr
        self.verbose = verbose
        self._adapter = None
        self.controller_address = None
        self.config = ConfigService()
        self.status = None

        ## init adapater
        self._init_adapter()

    #######################
    ## INIT BLUETOOTH ADAPTER
    #######################
    def _init_adapter(self):
        dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)

        ## get bluetooth status
        self.status = bluetooth_status()

        ## enable bluetooth if is necessary
        if (self.status['powered'] == False):
            self.enable_bluetooth()

        self._adapter = Adapter(verbose=self.verbose)

        ## power adapter if necessary
        if not self._adapter.Powered:
            self._adapter.Powered = True

        self.controller_address = self._adapter.Address

    #######################
    ## ENABLE BLUETOOTH
    #######################
    def enable_bluetooth(self):
        if (self.verbose):
            print "Enabling bluetooth"
        enable_bluetooth()
        ## give time to bluetooth
        time.sleep(2)
        self.status = bluetooth_status()

    #######################
    ## PAIR
    #######################
    def pair(self, mac_address=None, look_for_name="PRISM"):

        if (self.status['paired'] != False):
            if (self.status['paired']['mac_address'] == mac_address
                    or self.status['paired']['name'] == look_for_name):
                if (self.verbose):
                    print "Already paired, skip pairing"
                return {
                    'paired': True,
                    'mac_address': self.status['paired']['mac_address'],
                    'name': self.status['paired']['name']
                }

        if (self.verbose):
            print "trying to pair with: {0} [{1}]".format(
                look_for_name, mac_address)

        if (self.status['powered'] == False):
            self.enable_bluetooth()

        paired = False

        ## start pairing
        devices = self._adapter.discoverDevices(look_for_address=mac_address,
                                                timeout=60,
                                                verbose=self.verbose)

        for addrees in devices:
            device = devices[addrees]
            paired = True
            # mac_address = addrees
            if (self.verbose):
                print addrees, device.Name, device.Paired, device.Trusted, device.Adapter
            # mac_address = addrees
            if not device.Paired:
                if (self.verbose):
                    print "Pairing.."
                device.Pair()
                device.Trusted = True

        if paired:
            if (self.verbose):
                print "Paired with {0} [{1}]".format(look_for_name,
                                                     mac_address)

            ## save to config file
            self.config.set('bluetooth', 'prism_bt_address', str(mac_address))
            self.config.set('bluetooth', 'prism_bt_name', str(look_for_name))
            self.config.save('bluetooth')

            ### trust us
            ## give time to bluetooth
            time.sleep(2)
            send_command('trust', [self.controller_address],
                         mac_address,
                         verbose=self.verbose)

        return {
            'paired': paired,
            'mac_address': mac_address,
            'name': look_for_name
        }

    #######################
    ## UNPAIR
    #######################
    def unpair(self, mac_address):
        try:
            self._adapter.RemoveDevice(mac_address)
            ### tell also device to unpair
            send_command('disconnect', [self.controller_address],
                         mac_address,
                         verbose=self.verbose)
            # send_command('unpair', [self.controller_address], mac_address, verbose=self.verbose)

            ## save to config file
            self.config.set('bluetooth', 'prism_bt_address', '')
            self.config.set('bluetooth', 'prism_bt_name', '')
            self.config.set('bluetooth', 'prism_bt_network_address', '')
            self.config.save('bluetooth')

        except Exception as e:
            pass
        return True

    #######################
    ## SCAN
    #######################
    def scan(self):
        if (self.verbose):
            print "Scan for devices..."

        return scan('list')

    ###################################
    ## AUTO PAIR AND CONNECT TO PRISM
    ###################################
    def auto_connection(self, name="PRISM", mac_address=None):

        if (self.status['paired'] == False):
            if (mac_address == None or mac_address == ""):
                devices = self.scan()
                for device in devices:
                    if (device['name'] == name):
                        mac_address = device['mac']
        else:
            if (mac_address == None or mac_address == ""):
                mac_address = self.status['paired']['mac_address']

        if (self.verbose):
            print "Autoconnection to {0} [{1}]".format(name, mac_address)

        pairing_result = self.pair(mac_address=mac_address, look_for_name=name)
        mac_address = pairing_result['mac_address']
        paired = pairing_result['paired']
        connection = None

        if (paired):
            connection = self.send_command('connect', [], mac_address)

        return {'connection': connection, 'paired': paired}

    ###################################
    ## SEN COMMAND TO PRISM
    ###################################
    def send_command(self, command, args=[], mac_address=None, port=0x1001):

        if (mac_address == None or mac_address == ""):

            if self.status['paired'] != False:
                if "mac_address" in self.status['paired']:
                    mac_address = self.status['paired']['mac_address']
                else:
                    return {'error': _("No connected device")}

        socket = bluetooth.BluetoothSocket(bluetooth.L2CAP)
        socket.settimeout(3)

        if (self.verbose):
            print "Trying to connect to {0} on port {1}".format(
                mac_address, port)

        try:
            socket.connect((mac_address, port))
            #bluetooth.set_packet_timeout(mac_address, 0)

            if command in ['connect', 'disconnect', 'trust', 'untrust']:
                args.append(self._adapter.Address)

            if command in ['connect', 'rpc']:
                tether_address = get_ip_address('tether')
                if (tether_address != 'n.a'):
                    args.append(tether_address)
                    args.append(self.config.get('xmlrpc', 'xmlrpc_port'))

            data = json.dumps({'cmd': command, 'args': args})

            if self.verbose:
                print "Data sent {0}".format(data)

            ## send data
            socket.send(data)

            # get data
            reply = socket.recv(1024)

            # close socket
            socket.close()

            if self.verbose:
                print "Data received:".format(reply)

            response = json.loads(reply)

            ## save network address
            if (command in ['connect', 'network-address']):
                self.config.set('bluetooth', 'prism_bt_network_address',
                                response['reply'])
                self.config.save('bluetooth')

            if (command == 'disconnect'):
                self.config.set('bluetooth', 'prism_bt_network_address', '')
                self.config.save('bluetooth')

            return {'command': command, 'response': response['reply']}

        except Exception as e:
            if self.verbose:
                print "Error: {0}".format(e)

            return {'error': str(e)}
Esempio n. 21
0
from watchdog.events import PatternMatchingEventHandler

# Import internal modules
from fabtotum.fabui.config  import ConfigService
from fabtotum.fabui.gpusher import GCodePusher
import fabtotum.fabui.macros.general as general_macros
import fabtotum.fabui.macros.printing as print_macros

config = ConfigService()

# SETTING EXPECTED ARGUMENTS
parser = argparse.ArgumentParser()
parser.add_argument("file",         help="gcode file to execute")
parser.add_argument("command_file", help="command file")
parser.add_argument("task_id",      help="id_task")
parser.add_argument("monitor",      help="monitor file",  default=config.get('general', 'task_monitor'), nargs='?')
parser.add_argument("trace",        help="trace file",  default=config.get('general', 'trace'), nargs='?')
parser.add_argument("--ext_temp",   help="extruder temperature (for UI feedback only)",  default=180, nargs='?')
parser.add_argument("--bed_temp",   help="bed temperature (for UI feedback only)",  default=50,  nargs='?')
parser.add_argument("--standalone", help="call macros internally",  default=False, nargs='?')

# GET ARGUMENTS
args = parser.parse_args()

# INIT VARs
gcode_file      = args.file         # GCODE FILE
command_file    = args.command_file # OVERRIDE DATA FILE 
task_id         = args.task_id      # TASK ID  
monitor_file    = args.monitor      # TASK MONITOR FILE (write stats & task info, es: temperatures, speed, etc
log_trace       = args.trace        # TASK TRACE FILE 
ext_temp_target = args.ext_temp     # EXTRUDER TARGET TEMPERATURE (previously read from file) 
Esempio n. 22
0
class GCodePusher(object):
    """
    GCode pusher.
    """

    TASK_PREPARING = 'preparing'
    TASK_RUNNING = 'running'
    TASK_PAUSED = 'paused'
    TASK_COMPLETED = 'completed'
    TASK_COMPLETING = 'completing'
    TASK_ABORTING = 'aborting'
    TASK_ABORTED = 'aborted'
    TASK_TERMINATED = 'terminated'

    TYPE_PRINT = 'print'
    TYPE_MILL = 'mill'
    TYPE_SCAN = 'scan'
    TYPE_LASER = 'laser'

    UPDATE_PERIOD = 2  # seconds

    def __init__(self,
                 log_trace=None,
                 monitor_file=None,
                 gcs=None,
                 config=None,
                 use_callback=True,
                 use_stdout=False,
                 update_period=2,
                 lang='en_US.UTF-8',
                 send_email=False,
                 auto_shutdown=False):

        self.monitor_lock = RLock()

        self.UPDATE_PERIOD = update_period
        self.gcode_info = None
        self.lang = lang
        _ = setLanguage(self.lang)
        self.use_stdout = use_stdout
        # Task specific attributes
        self.task_stats = {
            'type': 'unknown',
            'controller': 'unknown',
            'id': 0,
            'pid': os.getpid(),
            'status': GCodePusher.TASK_PREPARING,
            'started_time': time.time(),
            'estimated_time': 0,
            'completed_time': 0,
            'duration': 0,
            'percent': 0.0,
            'auto_shutdown': auto_shutdown,
            'send_email': send_email,
            'message': ''
        }

        # Pusher/File specific attributes
        self.pusher_stats = {
            'file': {
                'full_path': '',
                'name': '',
            },
            'line_total': 0,
            'line_current': 0,
            'type': GCodeInfo.RAW,
            'first_move': False
        }

        # Pusher/File specific attributes
        self.override_stats = {
            'z_override': 0.0,
            'fan': 0,
            'rpm': 0,
            'laser': 0,
            'flow_rate': 0,
            'speed': 0
        }

        self.standardized_stats = {
            'task': self.task_stats,
            'gpusher': self.pusher_stats,
            'override': self.override_stats
        }

        if not config:
            self.config = ConfigService()
        else:
            self.config = config

        if not gcs:
            self.gcs = GCodeServiceClient()
        else:
            self.gcs = gcs

        if not monitor_file:
            monitor_file = self.config.get('general', 'task_monitor')

        if not log_trace:
            log_trace = self.config.get('general', 'trace')

        self.monitor_file = monitor_file
        self.trace_file = log_trace

        self.trace_logger = logging.getLogger('Trace')
        self.trace_logger.setLevel(logging.INFO)

        ch = logging.FileHandler(log_trace)
        formatter = logging.Formatter("%(message)s")
        ch.setFormatter(formatter)
        ch.setLevel(logging.INFO)
        self.trace_logger.addHandler(ch)

        self.temperatres_file = self.config.get('general', 'temperature')

        if use_callback:
            self.gcs.register_callback(self.callback_handler)

        self.gmacro = GMacroHandler(self.gcs,
                                    self.config,
                                    self.trace,
                                    self.resetTrace,
                                    lang=self.lang)

        self.progress_monitor = None
        self.db = Database(self.config)

    def __send_task_email(self):

        if not self.task_stats["send_email"]:
            return

        import shlex, subprocess
        cmd = 'sudo -u www-data php /usr/share/fabui/index.php Std sendTaskEmail/{0}'.format(
            self.task_stats['id'])
        try:
            output = subprocess.check_output(shlex.split(cmd))
            self.trace(_("Email sent"))
        except subprocess.CalledProcessError as e:
            self.trace(_("Email sending failed"))

    def __self_destruct(self):
        import signal
        print 'Initiating SIGKILL'
        pid = os.getpid()
        os.kill(pid, signal.SIGKILL)
        print 'SIGKILL Failed'

    def add_monitor_group(self, group, content={}):
        """
        Add a custom group to monitor file with a specific content.
        If not content is provided, the groups is initialized with an empty dict.
        
        :param group: Group name.
        :param content: Dictinary containg group attributes.
        :type group: string
        :type content: dict
        """
        if group not in self.standardized_stats:
            self.standardized_stats[group] = content

        return self.standardized_stats[group]

    def remove_monitor_group(self, group):
        """
        Remove a custom group from the monitor file.
        
        :param group: Group name.
        :type group: string
        """
        if group not in ['task', 'override', 'gpusher']:
            del self.standardized_stats[group]

    def update_monitor_file(self):
        """
        Write stats to monitor file
        """
        # Update duration
        self.task_stats['duration'] = str(
            time.time() - float(self.task_stats['started_time']))

        if self.monitor_file:
            with open(self.monitor_file, 'w+') as file:
                file.write(json.dumps(self.standardized_stats))

    def trace(self, log_msg):
        """ 
        Write to log message to trace file
        
        :param log_msg: Log message
        :type log_msg: string
        """
        if self.use_stdout:
            print log_msg
        else:
            self.trace_logger.info(log_msg)

    def resetTrace(self):
        """ Reset trace file """
        #with open(self.trace_file, 'w'):
        #   pass
        open(self.trace_file, 'w').close()

    def __shutdown_procedure(self):
        self.trace(_("Schutting down..."))

        # Wait for all commands to be finished
        reply = self.gcs.send('M400')

        # Tell totumduino Raspberry is going to sleep :'(
        reply = self.gcs.send('M729')

        # Stop the GCodeService connection
        self.gcs.stop()

        os.system('poweroff')

    def first_move_callback(self):
        self.trace(_("Task Started"))

    def __first_move_callback(self):
        """
        Triggered when first move command in file executed
        """
        self.pusher_stats['first_move'] = True
        self.first_move_callback()

    def gcode_comment_callback(self, data):
        """
        Triggered when a comment in gcode file is detected
        """
        pass

    def __gcode_comment_callback(self, data):

        if 'layer' in data:
            with self.monitor_lock:
                if 'print' in self.standardized_stats:
                    self.standardized_stats['print']['layer_current'] = data[
                        'layer']
                    self.update_monitor_file()

        self.gcode_comment_callback(data)

    def temp_change_callback(self, action, data):
        """
        Triggered when temperature change is detected
        """
        pass

    def __temp_change_callback(self, action, data):
        self.temp_change_callback(action, data)

    def gcode_action_callback(self, action, data):
        """
        Triggered when action hook for a gcode command is activated 
        """
        pass

    def __gcode_action_callback(self, action, data):

        monitor_write = False

        with self.monitor_lock:
            if action == 'heating':

                if data[0] == 'M109':
                    self.trace(
                        _("Wait for nozzle temperature to reach {0}°C").
                        format(data[1]))
                elif data[0] == 'M190':
                    self.trace(
                        _("Wait for bed temperature to reach {0}°C").
                        format(data[1]))
                elif data[0] == 'M104':
                    self.trace(
                        _("Nozzle temperature set to {0}°C").format(
                            data[1]))
                elif data[0] == 'M140':
                    self.trace(
                        _("Bed temperature set to {0}°C").format(data[1]))

            elif action == 'cooling':

                if data[0] == 'M106':

                    if (len(data) > 1):
                        s_value = data[1]
                    else:
                        s_value = FAN_MAX_VALUE

                    value = int((float(s_value) / FAN_MAX_VALUE) * 100)
                    self.trace(_("Fan value set to {0}%").format(value))
                    self.override_stats['fan'] = float(s_value)
                    monitor_write = True
                elif data[0] == 'M107':
                    self.trace(_("Fan off"))
                    self.override_stats['fan'] = 0.0
                    monitor_write = True

            elif action == 'z_override':
                self.override_stats['z_override'] = float(data[0])

            elif action == 'printing':

                if data[0] == 'M220':  # Speed factor
                    value = float(data[1])
                    self.trace(_("Speed factor set to {0}%").format(value))
                    self.override_stats['speed'] = float(data[1])
                    monitor_write = True
                elif data[0] == 'M221':  # Extruder flow
                    value = float(data[1])
                    self.trace(_("Extruder flow set to {0}%").format(value))
                    self.override_stats['flow_rate'] = float(data[1])
                    monitor_write = True

            elif action == 'milling':
                if data[0] == 'M0':
                    """ .. todo: do something with it """
                    pass
                elif data[0] == 'M1':
                    """ .. todo: do something with it """
                    pass
                elif data[0] == 'M3':
                    value = int(data[1])
                    self.trace(_("Milling motor RPM set to {0}").format(value))
                    self.override_stats['rpm'] = float(data[1])
                    monitor_write = True
                elif data[0] == 'M4':
                    value = int(data[1])
                    self.trace(_("Milling motor RPM set to {0}").format(value))
                    self.override_stats['rpm'] = float(data[1])
                    monitor_write = True
                elif data[0] == 'M6':
                    value = float(data[1])
                    """ .. todo: Check whether laser power should be scaled from 0-255 to 0.0-100.0 """
                    self.trace(_("Laser power set to {0}%").format(value))
                    self.override_stats['laser'] = float(data[1])
                    monitor_write = True

            elif action == 'pause':
                self.pause()

            elif action == 'message':
                self.task_stats['message'] = data
                self.trace(data)

            if monitor_write:
                self.update_monitor_file()

        self.gcode_action_callback(action, data)

    def file_done_callback(self):
        """ Triggered when gcode file execution is completed """
        if self.task_stats["auto_shutdown"]:
            self.__shutdown_procedure()
        else:
            self._stop()

    def __file_done_callback(self, data):
        """
        Internal file done callback preventing user from overloading it.
        """
        with self.monitor_lock:
            self.task_stats['percent'] = 100.0
            self.update_monitor_file()

        self.file_done_callback()

        if self.task_stats['status'] == self.TASK_COMPLETED:
            self.__send_task_email()

    def finish_task(self):
        self.gcs.finish()

    def set_task_status(self, status):
        """
        Set task status.
        
        :param status: Can be one of `GCodePusher.TASK_*` values
        """
        with self.monitor_lock:
            self.task_stats['status'] = status
            self.update_monitor_file()

        if (status == GCodePusher.TASK_COMPLETED
                or status == GCodePusher.TASK_ABORTED):
            self.task_stats['completed_time'] = time.time()
            self.__update_task_db()

        if (status == GCodePusher.TASK_COMPLETED
                or status == GCodePusher.TASK_COMPLETING
                or status == GCodePusher.TASK_ABORTING
                or status == GCodePusher.TASK_ABORTED
                or status == GCodePusher.TASK_RUNNING):
            self.__update_task_db()

    def is_aborted(self):
        return (self.task_stats['status'] == GCodePusher.TASK_ABORTED
                or self.task_stats['status'] == GCodePusher.TASK_ABORTING)

    def is_paused(self):
        return self.task_stats['status'] == GCodePusher.TASK_PAUSED

    def is_started(self):
        return self.task_stats['status'] == GCodePusher.TASK_RUNNING

    def is_completed(self):
        return (self.task_stats['status'] == GCodePusher.TASK_COMPLETED
                or self.task_stats['status'] == GCodePusher.TASK_COMPLETING)

    def state_change_callback(self, data):
        """
        Triggered when state is changed. (paused/resumed)
        """
        pass

    def __state_change_callback(self, data):
        """
        """

        with self.monitor_lock:
            if data == 'paused':
                #~ self.trace( _("Task has been paused") )
                self.task_stats['status'] = GCodePusher.TASK_PAUSED
                #self.monitor_info["paused"] = True
            elif data == 'resumed':
                self.task_stats['status'] = GCodePusher.TASK_RUNNING

            elif data == 'aborted':
                #~ self.trace( _("Task has been aborted") )
                self.task_stats['status'] = GCodePusher.TASK_ABORTING
                self.__update_task_db()

            elif data == 'terminated':
                self.trace(_("Task has been terminated"))
                self.task_stats['status'] = GCodePusher.TASK_TERMINATED
                self.update_monitor_file()
                self.__self_destruct()

            self.update_monitor_file()

        self.state_change_callback(data)

        with self.monitor_lock:
            if data == 'resuming':
                self.gcs.resumed()

    def progress_callback(self, percentage):
        """ 
        Triggered when progress percentage changes 
        
        :param percentage: Progress percentage 0.0 to 100.0
        :type percentage: float
        """
        pass

    def error_callback(self, error_no):
        """ 
        Triggered when an error occures.
        
        :param error_no: Error number
        :param error_msg: Error message
        :type error_no: int
        :type error_msg: string
        """
        pass

    def __error_callback(self, error_no):
        # TODO: process errors
        # TODO: complete ERROR_MESSAGE
        self.error_callback(error_no)

    def __config_change_callback(self, id, data):
        if id == 'shutdown':
            with self.monitor_lock:
                self.task_stats["auto_shutdown"] = (data == 'on')
                self.update_monitor_file()
        elif id == 'email':
            with self.monitor_lock:
                self.task_stats["send_email"] = (data == 'on')
                self.update_monitor_file()
        elif id == 'reload':
            self.config.reload()

    def callback_handler(self, action, data):

        if action == 'file_done':
            self.__file_done_callback(data)
        elif action == 'gcode_comment':
            self.__gcode_comment_callback(data)
        elif action.startswith('gcode_action'):
            self.__gcode_action_callback(action.split(':')[1], data)
        elif action == 'first_move':
            self.__first_move_callback()
        elif action.startswith('temp_change'):
            self.__temp_change_callback(action.split(':')[1], data)
        elif action == 'state_change':
            self.__state_change_callback(data)
        elif action.startswith('config:'):
            self.__config_change_callback(action.split(':')[1], data)
        elif action == 'error':
            self.__error_callback(data[0])
        elif action == 'self_descruct':
            print 'Self Descruct sequence activated...'
            self.__self_destruct()
        else:
            self.custom_action_callback(action, data)

    def custom_action_callback(self, action, data):
        """
        Handle user defined action
        """
        pass

    def get_progress(self):
        """ 
        Get progress of file push or override this function for custom progress calculation.
        """
        return self.gcs.get_progress()

    def __progress_monitor_thread(self):
        old_progress = -1
        monitor_write = False

        while self.gcs.still_running():

            progress = self.get_progress()

            if old_progress != progress:
                old_progress = progress
                dur = float(self.task_stats['duration'])

                first_move = self.pusher_stats['first_move']

                if progress == 0.0 or first_move == False:
                    self.task_stats['estimated_time'] = 0
                else:
                    self.task_stats['estimated_time'] = (
                        (dur / float(progress)) * 100.0)

                print self.task_stats['estimated_time'], progress

                self.progress_callback(progress)

            # Write progress even if it did not change because duration is update
            # during update_monitor_file()
            with self.monitor_lock:
                self.task_stats['percent'] = progress
                self.update_monitor_file()

            time.sleep(GCodePusher.UPDATE_PERIOD)

    def prepare_task(self,
                     task_id,
                     task_type='unknown',
                     task_controller='make',
                     gcode_file=None):

        self.task_stats['type'] = task_type
        self.task_stats['controller'] = task_controller
        self.task_stats['id'] = task_id
        self.task_stats['status'] = GCodePusher.TASK_PREPARING
        self.task_stats['started_time'] = time.time()
        self.task_stats['completed_time'] = 0
        self.task_stats['estimated_time'] = 0
        self.task_stats['duration'] = 0
        self.task_stats['percent'] = 0.0
        #~ self.task_stats['auto_shutdown']    = auto_shutdown # configured in __init __
        #~ self.task_stats['send_email']       = send_email    # configured in __init __
        self.task_stats['message'] = ''

        self.override_stats['z_override'] = 0.0
        self.override_stats['fan'] = 0
        self.override_stats['rpm'] = 0
        self.override_stats['laser'] = 0
        self.override_stats['flow_rate'] = 100.0
        self.override_stats['speed'] = 100.0

        self.resetTrace()

        if gcode_file:
            self.trace(_("Processing file"))
            self.trace(_("This may take a while, please wait"))
            gfile = GCodeFile(gcode_file)
            self.trace(_("File processed"))
            task_db = self.get_task(task_id)
            file = self.get_file(task_db['id_file'])
            self.pusher_stats['file']['full_path'] = gcode_file
            self.pusher_stats['file']['name'] = file['client_name']
            self.pusher_stats['line_total'] = gfile.info['line_count']
            self.pusher_stats['line_current'] = 0
            self.pusher_stats['type'] = gfile.info['type']
            self.pusher_stats['first_move'] = False

            if gfile.info['type'] == GCodeInfo.PRINT:
                engine = 'unknown'
                if 'slicer' in gfile.info:
                    engine = gfile.info['slicer']

                layer_total = 0
                if 'layer_count' in gfile.info:
                    layer_total = int(gfile.info['layer_count'])

                if 'print' not in self.standardized_stats:
                    self.print_stats = {
                        'layer_total': layer_total,
                        'layer_current': 0,
                        'engine': engine
                    }
                    self.add_monitor_group('print', self.print_stats)
                else:
                    self.standardized_stats['print']['engine'] = engine
                    self.standardized_stats['print']['layer_current'] = 0
                    self.standardized_stats['print'][
                        'layer_total'] = layer_total

            elif gfile.info['type'] == GCodeInfo.MILL or gfile.info[
                    'type'] == GCodeInfo.DRILL:
                self.mill_stats = {
                    # Place holder
                }
                self.add_monitor_group('mill', self.mill_stats)

            #~ elif gfile.info['type'] == GCodeInfo.LASER:
            #~ self.laser_stats = {
            #~ # Place holder
            #~ }
            #~ self.add_monitor_group('laser', self.laser_stats)

        if self.monitor_file:
            self.progress_monitor = Thread(
                target=self.__progress_monitor_thread)
            self.progress_monitor.start()

        with self.monitor_lock:
            self.update_monitor_file()

    def __update_task_db(self):
        """
        Converts task_stats to compatible format for sys_tasks table and writes
        the values to the database.
        """
        task_id = self.task_stats['id']

        if task_id == 0:
            return

        task_db = Task(self.db, task_id)

        if (self.task_stats['status'] == GCodePusher.TASK_PREPARING
                or self.task_stats['status'] == GCodePusher.TASK_RUNNING
                or self.task_stats['status'] == GCodePusher.TASK_PAUSED):

            task_db['status'] = GCodePusher.TASK_RUNNING

        elif (self.task_stats['status'] == GCodePusher.TASK_COMPLETED
              or self.task_stats['status'] == GCodePusher.TASK_ABORTING
              or self.task_stats['status'] == GCodePusher.TASK_ABORTED):
            task_db['status'] = self.task_stats['status']

            task_db['finish_date'] = timestamp2datetime(
                self.task_stats['completed_time'])

        task_db['type'] = self.task_stats['type']
        task_db['controller'] = self.task_stats['controller']

        tid = task_db.write()

        if task_id == TableItem.DEFAULT:
            self.task_stats['id'] = tid
            with self.monitor_lock:
                self.update_monitor_file()

    def loop(self):
        """
        Wait for all GCodePusher threads to finish.
        """
        self.gcs.loop()
        if self.progress_monitor:
            self.progress_monitor.join()
        time.sleep(0.5)

    def __stop_thread(self):
        self.gcs.stop()

    def stop(self):
        """
        Signal all GCodePusher threads to stop.
        """
        stop_thread = Thread(target=self.__stop_thread)
        stop_thread.start()

    def exec_macro(self, preset, args=None, atomic=True):
        """
        Execute macro command.
        """
        return self.gmacro.run(preset, args, atomic, reset_trace=False)

    def send(self,
             code,
             block=True,
             timeout=None,
             trace=None,
             group='gcode',
             expected_reply='ok'):
        """
        Send a single gcode command and display trace message.
        """
        if trace:
            self.trace(trace)

        #TODO: ConnectionClosedError
        return self.gcs.send(code,
                             block=block,
                             timeout=timeout,
                             group=group,
                             expected_reply=expected_reply)

    def send_file(self, filename):
        """
        Send a file to totumduino. File will be send line by line and it's progress 
        can be monitored using `get_progress` function.
        When the file has been completely sent `file_done_callback` will be called.
        """
        return self.gcs.send_file(filename)

    def get_temperature_history(self):
        """
        Return temperature history data.
        """
        try:
            json_f = open(self.temperatres_file, 'r')
            return json.load(json_f)
        except:
            return {}

    #### Object related API ####

    def get_task(self, task_id):
        t = Task(self.db, task_id)
        if t.exists():
            return t
        return None

    def get_file(self, file_id):
        f = File(self.db, file_id)
        if f.exists():
            return f
        return None

    def get_object(self, object_id):
        obj = Object(self.db, object_id)
        if obj.exists():
            return obj
        return None

    def add_object(self, name, desc, user_id, public=Object.PUBLIC):
        """
        Add object to database.
        """
        obj = Object(self.db,
                     user_id=user_id,
                     name=name,
                     desc=desc,
                     public=public)
        obj.write()

        return obj

    def delete_object(self, object_id):
        """
        Remove object from database and all the files associated to it.
        """
        to_delete = []

        obj = self.get_object(object_id)
        if obj:
            ofmap = ObjFile(self.db)

            files = ofmap.object_files(object_id)
            for fid in files:
                f = File(self.db, file_id=fid)
                aids = ofmap.file_associations(fid)
                # Check if file is only associated to one object
                # if so we can remove it from db and filesystem
                if len(aids) == 1:
                    to_delete.append(f['full_path'])
                    f.delete()

            # Remove all associations with object_id
            aids = ofmap.object_associations(object_id)
            ofmap.delete(aids)

            obj.delete()

            for f in to_delete:
                try:
                    os.remove(f)
                except Exception as e:
                    pass

    def pause(self):
        self.gcs.pause()

    def resume(self):
        self.gcs.resume()
Esempio n. 23
0
class NotifyService(object):
    """
    Notification service. Handles all notification by sending the messages to
    an opened websocket and writing the same messages to a NOTIFY_FILE file as a 
    fallback in case websocket is not supported.
    """
    def __init__(self, WebSocket=None, notify_file=None, config=None):

        self.notify_lock = RLock()

        if not config:
            self.config = ConfigService()
        else:
            self.config = config

        if not notify_file:
            notify_file = self.config.get('general', 'notify_file')

        if not WebSocket:
            SOCKET_HOST = self.config.get('socket', 'host')
            SOCKET_PORT = self.config.get('socket', 'port')
            self.ws = WebSocketClient('ws://' + SOCKET_HOST + ':' +
                                      SOCKET_PORT + '/')
            self.ws.connect()
        else:
            self.ws = WebSocket

        self.notify_file = notify_file

        self.backtrack = int(self.config.get('notify', 'backtrack', 30))
        self.event_id = 0
        self.events = []

    def notify(self, event_type, event_data):

        with self.notify_lock:
            self.__add_event(event_type, event_data)
            self.__send_message(event_type, event_data)

    def get_last(self):
        if self.events:
            return self.events[-1]
        return None

    def __add_event(self, event_type, event_data):
        """
        Add a new event to the event list and write the list to NOTIFY_FILE.
        """
        self.event_id += 1  # Increment the event ID number

        event = {'id': self.event_id, 'type': event_type, 'data': event_data}

        if len(self.events) >= self.backtrack:
            self.events = self.events[1:] + [event]
        else:
            self.events.append(event)

        wrapper = {'events': self.events, 'last_event': event}

        with open(self.notify_file, 'w') as f:
            f.write(json.dumps(wrapper))

    def __send_message(self, type, data):
        """
        Send message to WebSocket server.
        
        :param type: Message type
        :param data: Message data
        :type type: string
        :type data: string
        """
        message = {'type': type, 'data': data}
        self.ws.send(json.dumps(message))
Esempio n. 24
0
class Jog:
 
    def __init__(self, jog_response_file, gcs = None, config = None, logger = None):
        if not config:
            self.config = ConfigService()
        else:
            self.config = config
        
        if not gcs:
            self.gcs = GCodeServiceClient()
        else:
            self.gcs = gcs
        
        if logger:
            self.log = logger
        else:
            self.log = logging.getLogger('Jog')
            ch = logging.StreamHandler()
            ch.setLevel(logging.DEBUG)
            formatter = logging.Formatter("%(levelname)s : %(message)s")
            ch.setFormatter(formatter)
            self.log.addHandler(ch)
        
        self.jog_response_file = jog_response_file
        # Erase content of jog_response_file
        open(jog_response_file, 'w').close()
        
        self.backtrack = int(self.config.get('jog', 'backtrack', 20))
        self.response = {}
        self.tokens = []
        self.cq = queue.Queue()
        self.running = False
        
        self.send_thread = None
    
    def __add_token(self, token):
        to_remove = []
        
        if len(self.tokens) < self.backtrack:
            if token not in self.tokens:
                self.tokens.append(token)
        else:
            if token not in self.tokens:
                to_remove.append( self.tokens[0] )
                self.tokens = self.tokens[1:] + [token]
        
        return to_remove
    
    def __send_thread(self):
        self.log.debug("Jog thread: started")
        
        with open(self.jog_response_file, 'w') as f:
            f.write(json.dumps(self.response) )
        
        while self.running:
            
            cmd = self.cq.get()
            
            if cmd.id == Command.KILL:
                break
                
            elif cmd.id == Command.CLEAR:
                self.response = {}
                
            elif cmd.id == Command.GCODE:
                token = cmd.data[0]
                gcode = cmd.data[1]
                
                #~ reply = self.gcs.send(gcode, group = 'jog:{0}'.format(token) )
                #~ self.log.debug("jog.send [%s]", gcode)
                reply = self.gcs.send(gcode, group = 'jog' )
                #~ for ln in reply:
                    #~ self.log.debug("jog.reply [%s] : %s", gcode, ln)
                #print "jog:", reply
                
                # self.tokens
                
                to_remove = self.__add_token(token)
                for tok in to_remove:
                    if tok in self.response:
                        del self.response[tok]
                
                self.response[token] = {'code': gcode, 'reply': reply}
                
            print self.response
            with open(self.jog_response_file, 'w') as f:
                f.write(json.dumps(self.response) )
                
        self.log.debug("Jog thread: stopped")
        
    ### API ###
    
    def is_running(self):
        """ Returns `True` if the service is running """
        return self.running
    
    def start(self):
        """ Start the service. """
        self.running = True
        self.send_thread = Thread( name = "Jog-send", target = self.__send_thread )
        self.send_thread.start()
        
    def clear(self):
        """ Clear response file """
        self.cq.put( Command.clear() )
        
    def stop(self):
        """ Stop the service. """
        self.running = False
        # Used to wake up send_thread so it can detect the condition
        self.cq.put( Command.kill() )
        
    def loop(self):
        """ Loop until the service is stopped. """
        if self.send_thread:
            self.send_thread.join()
    
    def send(self, token, gcode):
        """
        Send a gcode command and write the reply to jog_response_file.
        
        :param token: ID used to pair gcode command and reply
        :param gcode: Gcode to send
        :type token: string
        :type gcode: string
        """
        self.cq.put( Command.gcode(token, gcode) )
Esempio n. 25
0
class MyFabtotumCom:

    RESPONSE_CODES_DESCRIPTION = {
        SERVICE_SUCCESS: 'SERVICE_SUCCESS',
        SERVICE_UNAUTHORIZED: 'SERVICE_UNAUTHORIZED',
        SERVICE_FORBIDDEN: 'SERVICE_FORBIDDEN',
        SERVICE_SERVER_ERROR: 'SERVICE_SERVER_ERROR',
        SERVICE_INVALID_PARAMETER: 'SERVICE_INVALID_PARAMETER',
        SERVICE_ALREADY_REGISTERED: 'SERVICE_ALREADY_REGISTERED',
        SERVICE_PRINTER_UNKNOWN: 'SERVICE_PRINTER_UNKNOWN'
    }

    STATUS = {
        0: 'AVAILABLE',
        1: 'BUSY',
        2: 'BUSY',
        3: 'PAUSED',
        4: 'PAUSED',
    }

    def __init__(self, gcs, logger, config=None):

        if config:
            self.config = config
        else:
            self.config = ConfigService()

        self.gcs = gcs
        self.db = Database(self.config)
        self.log = logger

        self.url = self.config.get('my.fabtotum.com', 'myfabtotum_url')
        self.api_version = self.config.get('my.fabtotum.com',
                                           'myfabtotum_api_version')
        self.thread_polling = None
        self.thread_update = None
        self.thread_reload = None
        self.running = False
        self.jsonrpc_version = "2.0"
        self.request_timeout = 5
        self.polling_interval = 5
        self.info_interval = (60 * 30)  # 30 minutes
        self.internal_update_interval = (60 * 5)  #  5 minutes
        self.id_counter = 0
        self.leds_colors = {}
        #self.mac_address      = None
        #self.serial_number    = None
        #self.fab_id           = None
        #self.unit_name        = None
        #self.batch_number     = None
        #self.fw_version       = None

        self.__init_vars()

    def __init_vars(self):
        """ init vars """
        self.mac_address = self.getMACAddres()
        self.ip_lan = self.getIPLan()
        self.serial_number = self.getSerialNumber()
        self.fab_id = self.getFabID()
        self.unit_name = self.getUnitName()
        #self.batch_number  = self.getBatchNumer()
        #self.fw_version    = self.getFwVersion()
        self.unit_color = self.getUnitColor()
        self.leds_colors = self.getLedsColors()
        self.fabui_version = self.getFabUiVersion()

    def call(self, method, params):
        """ make jsonrpc call to my.fabtotum.com remote server """
        try:
            self.id_counter += 1

            headers = {
                'content-type': 'application/json',
                'user-agent': 'fabtotum'
            }

            payload = {
                "method": method,
                "params": params,
                "jsonrpc": self.jsonrpc_version,
                "id": self.id_counter,
            }
            response = requests.post(self.url,
                                     data=json.dumps(payload),
                                     headers=headers,
                                     timeout=self.request_timeout,
                                     verify=False).json()

            if "result" in response:
                return response['result']
            elif "error" in response:
                self.log.debug("MyFabtotumCom - {0} : {1} : {2}".format(
                    response['error']['message'], response['error']['code'],
                    response['error']['data']))
                return False

        except requests.exceptions.RequestException as e:
            self.log.debug("MyFabtotumCom - {0}".format(e))
            self.log.debug("MyFabtotumCom - {0}".format(payload))
            return False

    def __getSystemConfig(self, value):
        """ get value from system config table """
        sysconfig = SysConfig(self.db)
        sysconfig.query_by('key', value)
        return sysconfig['text']

    def getFabID(self):
        """ """
        user = User(self.db)
        user.query_by('role', 'administrator')
        settings = json.loads(user['settings'])
        if "fabid" in settings:
            return settings['fabid']['email']
        else:
            return False

    def getMACAddres(self, iface='eth0'):
        """ get printer mac address """
        return get_mac_address('eth0')

    def getSerialNumber(self):
        """ get printer serial number """
        return self.__getSystemConfig('serial_number')

    def getUnitName(self):
        """ get unit name """
        return self.__getSystemConfig('unit_name')

    def getUnitColor(self):
        """ get unit color """
        return self.__getSystemConfig('unit_color')

    def getLedsColors(self):
        """ get ambient leds lights """
        try:
            return self.config.get('settings', 'color')
        except:
            return {'r': 255, 'g': 255, 'b': 255}

    def getBatchNumer(self):
        """ get batch number """
        try:
            reply = self.gcs.send("M763", group='gcode')
            return reply[0].strip()
        except:
            return 0

    def getModel(self):
        """ get fabtotum model """
        batch_number = self.getBatchNumer()
        model = fabtotum_model(batch_number)
        return "{0} ({1})".format(model, batch_number)

    def getFwVersion(self):
        """ get firmware version """
        try:
            reply = self.gcs.send("M765", group='gcode')
            return reply[0].strip()
        except:
            return "N.D."

    def getFabUiVersion(self):
        """ get fabui version """
        bundle = get_local_bundle('fabui')
        if bundle:
            return bundle['version']
        else:
            return None

    def getIPLan(self):
        """ return IP address """
        return get_ip_address('wlan0')

    def getState(self):
        """ printer's state """
        return self.STATUS[self.gcs.getState()]

    def identify(self):
        """ remote command identify printer"""
        self.log.info("MyFabtotumCom - Identify printer")

        # reload infos and send all to remote server
        self.reload(update=True)

        self.gcs.send("M300", group='gcode')
        self.gcs.send("M150 R0 U255 B255 S50", group='gcode')
        time.sleep(3)
        self.gcs.send("M701 S{0}".format(self.leds_colors['r']), group='gcode')
        self.gcs.send("M702 S{0}".format(self.leds_colors['g']), group='gcode')
        self.gcs.send("M703 S{0}".format(self.leds_colors['b']), group='gcode')
        self.gcs.send("M300", group='gcode')

    def reboot(self):
        """ remote command reboot unit """
        os.system('reboot')

    def lock(self):
        """ remote command lock printer """
        self.log.info("MyFabtotumCom - Lock printer")

    def unlock(self):
        """ remote command unlock printer """
        self.log.info("MyFabtotumCom - Unlock printer")

    def switch_off(self):
        """ remote commnad switch off """
        os.system("poweroff")

    def end_job(self):
        """ remote command  end active task """
        self.log.info("MyFabtotumCom - Abort task")
        self.gcs.abort()

    def fab_polling(self):
        """ ping my.fabtotum.com remote server for new commands """
        params = {
            "serialno": self.serial_number,
            "mac": self.mac_address,
            "state": self.getState(),
            "apiversion": self.api_version,
            "iplan": self.ip_lan,
            "fabuiversion": self.fabui_version
        }
        result = self.call('fab_polling', params)
        if result:
            if result["status_code"] == SERVICE_SUCCESS:
                if "command" in result:
                    try:
                        getattr(self, result["command"].lower())()
                    except AttributeError:
                        self.log.debug(
                            "MyFabtotumCom - {0} : command not valid".format(
                                result["command"]))
                    except:
                        self.log.debug(
                            "MyFabtotumCom - Unexpected error: {0}".format(
                                sys.exc_info()[0]))

                if "pollinterval" in result:
                    self.polling_interval = result['pollinterval']
            else:
                self.log.debug("MyFabtotumCom - {0}".format(
                    self.RESPONSE_CODES_DESCRIPTION[result["status_code"]]))

    def fab_info_update(self):
        """ update data on my.fabtotum.com remote server """

        head = self.config.get_current_head_info()
        params = {
            "serialno": self.serial_number,
            "mac": self.mac_address,
            "data": {
                "name": self.unit_name,
                "model": self.getModel(),
                "head": head["name"],
                "fwversion": self.getFwVersion(),
                "iplan": self.ip_lan,
                'color': self.unit_color,
                'fabuiversion': self.fabui_version
            },
            "apiversion": self.api_version,
        }

        result = self.call('fab_info_update', params)

        if result:
            self.log.debug("MyFabtotumCom - fab_info_update: {0} - {1}".format(
                self.RESPONSE_CODES_DESCRIPTION[result["status_code"]],
                params))

    def start(self):
        """ start server """
        self.running = True

        self.thread_polling = Thread(name="MyFabtotumCom_Polling",
                                     target=self.__thread_polling)
        self.thread_polling.start()

        self.thread_update = Thread(name="MyFabtotumCom_InfoUpdate",
                                    target=self.__thread_update)
        self.thread_update.start()

        self.thread_reload = Thread(name="MyFabtotumCom_Reload",
                                    target=self.__thread_reload)
        self.thread_reload.start()

    def stop(self):
        self.running = False

    def reload(self, update=True):
        """ reload settings """
        self.mac_address = self.getMACAddres()
        self.ip_lan = self.getIPLan()
        self.serial_number = self.getSerialNumber()
        self.fab_id = self.getFabID()
        self.unit_name = self.getUnitName()
        #self.batch_number  = self.getBatchNumer()
        #self.fw_version    = self.getFwVersion()
        self.unit_color = self.getUnitColor()
        self.leds_colors = self.getLedsColors()
        self.fabui_version = self.getFabUiVersion()
        #### update info
        if (update == True):
            self.fab_info_update()
        self.log.debug("MyFabtotumCom - Settings reloaded")

    def __thread_polling(self):
        """ polling thread """
        self.log.debug("MyFabtotumCom Polling_thread: started")
        while self.running:
            if self.fab_id:
                self.fab_polling()
            time.sleep(self.polling_interval)

    def __thread_update(self):
        """ info update thread """
        self.log.debug("MyFabtotumCom InfoUpdate_thread: started")
        while self.running:
            if self.fab_id:
                self.fab_info_update()
            time.sleep(self.info_interval)

    def __thread_reload(self):
        """ internal update """
        self.log.debug("MyFabtotumCom Reload_thread: started")
        while self.running:
            if self.fab_id:
                self.reload(update=False)
            time.sleep(self.internal_update_interval)

    def loop(self):
        if self.thread_polling:
            self.thread_polling.join()

        if self.thread_update:
            self.thread_update.join()

        if self.thread_reload:
            self.thread_reload.join()
from fabtotum.os.monitor.gpiomonitor    import GPIOMonitor

def signal_handler(signal, frame):
    print "You pressed Ctrl+C!"
    print "Shutting down services. Please wait..."
    ws.close()
    gcserver.stop()
    gcservice.stop()
    observer.stop()
    usbMonitor.stop()
    gpioMonitor.stop()

config = ConfigService()

# Load configuration
LOCK_FILE           = config.get('general', 'lock')
TRACE               = config.get('general', 'trace')
COMMAND             = config.get('general', 'command')
MACRO_RESPONSE      = config.get('general', 'macro_response')
TASK_MONITOR        = config.get('general', 'task_monitor')
EMERGENCY_FILE      = config.get('general', 'emergency_file')
##################################################################
SOCKET_HOST         = config.get('socket', 'host')
SOCKET_PORT         = config.get('socket', 'port')
##################################################################
HW_DEFAULT_SETTINGS = config.get('hardware', 'default_settings')
HW_CUSTOM_SETTINGS  = config.get('hardware', 'custom_settings')
##################################################################
USB_DISK_FOLDER     = config.get('usb', 'usb_disk_folder')
USB_FILE            = config.get('usb', 'usb_file')
##################################################################
Esempio n. 27
0
def test_case():
    from fabtotum.utils.pyro.gcodeclient import GCodeServiceClient
    from fabtotum.fabui.config import ConfigService
    from selftests_common import getEndstopValues, getFrontPanelStatus

    # Pyro GCodeService wrapper
    gcs = GCodeServiceClient()
    config = ConfigService()

    try:
        safety_door = config.get('settings', 'safety.door')
    except KeyError:
        safety_door = 0

    try:
        switch = config.get('settings', 'switch')
    except KeyError:
        switch = 0

    try:
        bed_enabled = config.get('settings', 'hardware')['bed']['enable']
    except KeyError:
        bed_enabled = True

    ####################################################################

    RETR = 0

    # Read 24VDC
    reply = gcs.send("M751")
    if reply:
        #V_24V:24.562 V
        try:
            V = float(reply[0].split(':')[1].split()[0])
            if V > 19.200 and V < 28.800:
                print _(
                    "[V] PSU Voltage nominal 24V DC (+/-20% tolerance): {0}V"
                ).format(V)
            else:
                print _(
                    "CRITICAL: PSU Voltage anomaly. Expected 24V DC +/-20%, got : {0}V"
                ).format(V)
                RETR = 1
        except:
            print _("No response for M751")
            RETR = 1
    else:
        print _("No response for M751")
        RETR = 1

    # Read 5VDC
    reply = gcs.send("M752")
    if reply:
        #V_5V:4.979 V
        try:
            V = float(reply[0].split(':')[1].split()[0])
            if V > 4.0 and V < 6.0:
                print _(
                    "[V] 5V DC Power Supply is Nominal (+/-20% tolerance): {0}V"
                ).format(V)
            else:
                print _(
                    "CRITICAL: 5V DC Power Supply anomaly. Expected 5V DC +/-20%, got : {0}V"
                ).format(V)
                RETR = 1
        except:
            print _("No response for M752")
            RETR = 1
    else:
        print _("No response for M752")
        RETR = 1

    # Read Current
    reply = gcs.send("M753")
    if reply:
        #Isinked:0.000 A
        try:
            A = float(reply[0].split(':')[1].split()[0])
            if A < 0.5:
                print _("[A] Power consumption is Nominal : {0}A < 500mA"
                        ).format(A)
            else:
                print _(
                    "CRITICAL: Power consumption Anomaly : {0}A, expected < 500mA"
                ).format(A)
                RETR = 1
        except:
            print _("No response for M753")
            RETR = 1
    else:
        print _("No response for M753")
        RETR = 1

    # Result
    exit(RETR)
Esempio n. 28
0
xmlrpc_pidfile = args.xmlrpc_pidfile
btagent_pidfile = args.btagent_pidfile
no_xmlrpc = args.no_xmlrpc
gpio_pidfile = args.gpio_pidfile
no_gpiomonitor = args.no_gpiomonitor
no_btagent = args.no_btagent
no_monitor = args.no_monitor
#myfabtotumcom_pidfile = args.myfabtotumcom_pidfile

with open(pidfile, 'w') as f:
    f.write(str(os.getpid()))

config = ConfigService()

# Load configuration
TRACE = config.get('general', 'trace')
TASK_MONITOR = config.get('general', 'task_monitor')
TEMP_MONITOR_FILE = config.get('general', 'temperature')
NOTIFY_FILE = config.get('general', 'notify_file')
LOG_LEVEL = config.get('general', 'log_level', 'INFO')
##################################################################
SOCKET_HOST = config.get('socket', 'host')
SOCKET_PORT = config.get('socket', 'port')
##################################################################
HW_DEFAULT_SETTINGS = config.get('hardware', 'settings')
##################################################################
USB_DISK_FOLDER = config.get('usb', 'usb_disk_folder')
USB_FILE = config.get('usb', 'usb_file')
##################################################################
SERIAL_PORT = config.get('serial', 'PORT')
SERIAL_BAUD = config.get('serial', 'BAUD')
Esempio n. 29
0
class UpdateFactory:
    def __init__(self,
                 arch='armhf',
                 mcu='atmega1280',
                 notify_update=None,
                 config=None,
                 gcs=None):
        self.config = config
        if not config:
            self.config = ConfigService()

        if not gcs:
            self.gcs = GCodeServiceClient()
        else:
            self.gcs = gcs

        self.arch = arch
        self.mcu = mcu
        self.remote = RemoteVersion(arch, mcu, config=config)

        self.tasks = []
        self.notify_update = notify_update

        self.reboot_required = False
        self.status = ''
        self.task = ''

    def getTasks(self):
        return self.tasks

    def getBundles(self):
        return self.remote.getBundles()

    def getFirmware(self):
        return self.remote.getFirmware()

    def getBoot(self):
        return self.remote.getBoot()

    def getPlugins(self):
        return self.remote.getPlugins()

    def getEndpoint(self, name):
        if name == "bundle":
            return self.remote.getColibriEndpoint()
        elif name == "firmware":
            return self.remote.getFirmwareEndpoint()
        elif name == "boot":
            return self.remote.getColibriEndpoint()
        elif name == "plugins":
            return self.remote.getPluginsEndpoint()

    def getTempFolder(self):
        return self.config.get('general', 'bigtemp_path')

    def addTask(self, task):
        task.setFactory(self)
        self.tasks.append(task)

    def update(self):
        if self.notify_update:
            self.notify_update(self)

    def getCurrentStatus(self):
        task = self.getTaskByName(self.task)
        if task:
            return task.getStatus()
        return ""

    def getTaskByName(self, name):
        if not name:
            return None

        for task in self.tasks:
            if task.getName() == name:
                return task

        return None

    def setStatus(self, status):
        self.status = status
        self.update()

    def getStatus(self):
        return self.status

    def setCurrentTask(self, task):
        self.task = task

    def getCurrentTask(self):
        return self.task

    def getCurrentName(self):
        task = self.getTaskByName(self.task)
        if task:
            return task.getName()
        return ""

    def getCurrentType(self):
        task = self.getTaskByName(self.task)
        if task:
            return task.getType()
        return ""

    def setRebootRequired(self, reboot):
        self.reboot_required = reboot

    def getRebootRequired(self):
        return self.reboot_required

    def serialize(self):
        data = {
            "current": {
                "name": self.getCurrentName(),
                "type": self.getCurrentType(),
                "status": self.getStatus(),
                "task": self.getCurrentTask(),
                "reboot": self.getRebootRequired()
            },
            "tasks": []
        }

        #~ for task in self.tasks:
        #~ data["tasks"][task.getName()] = task.serialize()
        for task in self.tasks:
            data["tasks"].append(task.serialize())

        return data
Esempio n. 30
0
class StatsMonitor:

    MAX_DELTA_TIME = 60  # Maximum allowed delta time

    def __init__(self, stats_file, gcs=None, config=None, logger=None):

        if not gcs:
            self.gcs = GCodeServiceClient()
        else:
            self.gcs = gcs

        if not config:
            self.config = ConfigService()
        else:
            self.config = config

        if logger:
            self.log = logger
        else:
            self.log = logging.getLogger('StatsMonitor')
            ch = logging.StreamHandler()
            ch.setLevel(logging.DEBUG)
            formatter = logging.Formatter("%(levelname)s : %(message)s")
            ch.setFormatter(formatter)
            self.log.addHandler(ch)

        self.stats_file = stats_file
        self.running = False

        self.monitor_thread = None
        self.monitor_write_thread = None
        self.ev_update = Event()
        self.backtrack = int(self.config.get('monitor', 'backtrack', 20))
        self.update_period = float(self.config.get('monitor', 'period'))

        ## Monitor variables, fill arrays with zeros
        self.ext_temp = [0.0] * self.backtrack
        self.ext_temp_target = [0.0] * self.backtrack
        self.bed_temp = [0.0] * self.backtrack
        self.bed_temp_target = [0.0] * self.backtrack
        self.delta = [0] * self.backtrack
        self.last_update_time = time.time()

        # re
        #~ self.re_temp = re.compile('ok\sT:(?P<T>[0-9]+\.[0-9]+)\s\/(?P<TT>[0-9]+\.[0-9]+)\sB:(?P<B>[0-9]+\.[0-9]+)\s\/(?P<BT>[0-9]+\.[0-9]+)\s')

        self.config.register_callback(self.__reload_config)

    def __reload_config(self):

        old_backtrack = self.backtrack

        self.backtrack = int(self.config.get('monitor', 'backtrack'))
        self.update_period = float(self.config.get('monitor', 'period'))

        if old_backtrack != self.backtrack:
            self.ext_temp = [0.0] * self.backtrack
            self.ext_temp_target = [0.0] * self.backtrack
            self.bed_temp = [0.0] * self.backtrack
            self.bed_temp_target = [0.0] * self.backtrack
            self.delta = [0] * self.backtrack
            self.last_update_time = time.time()

    #~ def __parse_temperature(self, line):
    #~ match = self.re_temp.search(line)
    #~ if match:
    #~ return ( match.group('T'), match.group('TT'), match.group('B'), match.group('BT') )

    @staticmethod
    def __rotate_values(value_list, new_value=None):
        if new_value == None:
            new_value = value_list[-1]

        return value_list[1:] + [new_value]

    def __update_values(self,
                        ext_temp=None,
                        ext_temp_target=None,
                        bed_temp=None,
                        bed_temp_target=None):
        """
        Update all values and delta.
        """

        delta = time.time() - self.last_update_time
        if delta > StatsMonitor.MAX_DELTA_TIME:
            delta = StatsMonitor.MAX_DELTA_TIME

        self.ext_temp = self.__rotate_values(self.ext_temp, ext_temp)
        self.ext_temp_target = self.__rotate_values(self.ext_temp_target,
                                                    ext_temp_target)
        self.bed_temp = self.__rotate_values(self.bed_temp, bed_temp)
        self.bed_temp_target = self.__rotate_values(self.bed_temp_target,
                                                    bed_temp_target)
        self.delta = self.__rotate_values(self.delta, delta)

        self.last_update_time = time.time()

        # Trigger write operation
        self.ev_update.set()

    def __write_thread(self):
        """
        Thread to handle write_stats from a single location.
        """
        self.log.debug("StatsMonitor write thread: started [{0}]".format(
            self.update_period))
        while self.running:
            # Used both as a delay and event trigger
            if self.ev_update.wait(self.update_period):
                # There was an update event, so write the new data
                self.__write_stats()
                self.ev_update.clear()

                #self.__write_stats()

        self.log.debug("StatsMonitor write thread: stopped")

    def __monitor_thread(self):
        """
        Thread for periodic temperature reading.
        """
        self.log.debug("StatsMonitor thread: started")
        while self.running:

            # Get temperature
            # Timeout is to prevent waiting for too long when there is a long running
            # command like M109,M190,G29 or G28
            #~ reply = self.gcs.send('M105', group = 'monitor', timeout = 2)
            reply = self.gcs.send('M105', group='monitor', block=True)
            if reply != None:  # No timeout occured
                try:
                    #a, b, c, d = self.__parse_temperature(reply[0])
                    temps = parseM105(reply)
                    if temps:
                        a = temps['T']
                        b = temps['target']['T']
                        c = temps['B']
                        d = temps['target']['B']
                        self.__update_values(a, b, c, d)

                    # with this one there is too much callback threads on the queue
                    # self.gcs.push("temp_change:all", [a, b, c, d])
                except Exception as e:
                    self.log.debug("MONITOR: M105 error, %s", str(e))
            else:
                self.log.debug("MONITOR: M105 aborted")

            # Wait for the specified period of time before reading temp again
            time.sleep(self.update_period)

        self.log.debug("StatsMonitor thread: stopped")

    def __temp_change_callback(self, action, data):
        """
        Capture asynchronous temperature updates during M109 and M190.
        """
        if action == 'ext_bed':
            self.log.debug("Ext: %f, Bed: %f", float(data[0]), float(data[1]))
            self.__update_values(ext_temp=float(data[0]),
                                 bed_temp=float(data[1]))
        elif action == 'all':
            self.log.debug("Ext: %f/%f, Bed: %f/%f", float(data[0]),
                           float(data[1]), float(data[2]), float(data[3]))
            self.__update_values(float(data[0]), float(data[1]),
                                 float(data[2]), float(data[3]))
        elif action == 'bed':
            self.log.debug("Bed: %f", float(data[0]))
            self.__update_values(bed_temp=float(data[0]))
        elif action == 'ext':
            self.log.debug("Ext: %f", float(data[0]))
            self.__update_values(ext_temp=float(data[0]))

    def __gcode_action_callback(self, action, data):
        """
        Capture asynchronous events that modify temperature.
        """
        if action == 'heating':

            if data[0] == 'M109':
                self.__update_values(ext_temp_target=float(data[1]))
            elif data[0] == 'M190':
                self.__update_values(bed_temp_target=float(data[1]))
            elif data[0] == 'M104':
                self.__update_values(ext_temp_target=float(data[1]))
            elif data[0] == 'M140':
                self.__update_values(bed_temp_target=float(data[1]))

    def __callback_handler(self, action, data):
        """
        General callback handler.
        """

        if action.startswith('temp_change'):
            self.__temp_change_callback(action.split(':')[1], data)
        elif action.startswith('gcode_action'):
            self.__gcode_action_callback(action.split(':')[1], data)

    def __write_stats(self):
        """
        Write stats to the stats_file.
        """
        stats = {
            'ext_temp': self.ext_temp,
            'ext_temp_target': self.ext_temp_target,
            'bed_temp': self.bed_temp,
            'bed_temp_target': self.bed_temp_target,
            'delta': self.delta
        }

        with open(self.stats_file, 'w') as f:
            f.write(json.dumps(stats))

    ### API ###

    def set_backtrack_size(self, size):
        # TODO:
        if self.backtrack != size:
            # resize
            pass
        self.backtrack = size

    def start(self):
        self.running = True

        self.gcs.register_callback(self.__callback_handler)

        self.monitor_thread = Thread(name="Monitor",
                                     target=self.__monitor_thread)
        self.monitor_thread.start()

        self.monitor_write_thread = Thread(name="Monitor_write",
                                           target=self.__write_thread)
        self.monitor_write_thread.start()

    def loop(self):
        if self.monitor_thread:
            self.monitor_thread.join()

    def stop(self):
        self.running = False
        self.ev_update.set()
Esempio n. 31
0
class RemoteVersion:
    def __init__(self, arch='armhf', mcu='atmega1280', config=None):
        self.config = config
        if not config:
            self.config = ConfigService()

        self.colibri_endpoint = self.config.get('updates', 'colibri_endpoint')
        self.firmware_endpoint = self.config.get('updates',
                                                 'firmware_endpoint')
        self.plugin_endpoint = self.config.get('updates', 'plugins_endpoint')
        self.arch = arch
        self.mcu = mcu
        self.colibri = None
        self.firmware = None
        self.plugins = None
        self.setColibri()
        self.setFirmware()
        self.setPlugins()

    def getRemoteData(self, endpoint):
        curl = pycurl.Curl()
        buffer = BytesIO()
        curl.setopt(pycurl.URL, endpoint)
        curl.setopt(pycurl.TIMEOUT, 30)
        curl.setopt(pycurl.FOLLOWLOCATION, 1)
        curl.setopt(pycurl.SSL_VERIFYPEER, 0)
        curl.setopt(pycurl.SSL_VERIFYHOST, 0)
        curl.setopt(pycurl.MAXREDIRS, 5)
        curl.setopt(curl.WRITEDATA, buffer)
        curl.perform()
        return buffer.getvalue()

    def setColibri(self):
        self.colibri = json.loads(
            self.getRemoteData(
                os.path.join(self.colibri_endpoint, self.arch,
                             "version.json")))

    def setFirmware(self):
        self.firmware = json.loads(
            self.getRemoteData(
                os.path.join(self.firmware_endpoint, "fablin", self.mcu,
                             "version.json")))

    def setPlugins(self):
        self.plugins = json.loads(
            self.getRemoteData(
                os.path.join(self.plugin_endpoint, "cached.json")))

    def getColibri(self):
        return self.colibri

    def getBundles(self):
        return self.colibri['bundles']

    def getBoot(self):
        return self.colibri['boot']

    def getImages(self):
        return self.colibri['images']

    def getFirmware(self):
        if 'firmware' in self.firmware:
            return self.firmware['firmware']
        return {}

    def getPlugins(self):
        return self.plugins

    def getColibriEndpoint(self):
        return os.path.join(self.colibri_endpoint, self.arch)

    def getFirmwareEndpoint(self):
        return os.path.join(self.firmware_endpoint, 'fablin', self.mcu)

    def getPluginsEndpoint(self):
        return self.firmware_endpoint
Esempio n. 32
0
def main():
    config = ConfigService()

    # SETTING EXPECTED ARGUMENTS
    destination = config.get('general', 'bigtemp_path')

    parser = argparse.ArgumentParser(
        formatter_class=argparse.ArgumentDefaultsHelpFormatter)
    #~ subparsers = parser.add_subparsers(help='sub-command help', dest='type')

    parser.add_argument("-T", "--task-id", help="Task ID.", default=0)
    parser.add_argument("-U",
                        "--user-id",
                        help="User ID. (future use)",
                        default=0)
    parser.add_argument("-O", "--object-id", help="Object ID.", default=0)
    parser.add_argument("-N", "--object-name", help="Object name.", default='')
    parser.add_argument("-F", "--file-name", help="File name.", default='')

    parser.add_argument("-d",
                        "--dest",
                        help="Destination folder.",
                        default=destination)
    parser.add_argument("-s",
                        "--slices",
                        help="Number of slices.",
                        default=100)
    parser.add_argument("-i", "--iso", help="ISO.", default=400)
    parser.add_argument("-p",
                        "--power",
                        help="Scan laser power 0-255.",
                        default=230)
    parser.add_argument("-W",
                        "--width",
                        help="Image width in pixels.",
                        default=1296)
    parser.add_argument("-H",
                        "--height",
                        help="Image height in pixels",
                        default=972)
    parser.add_argument("-C", "--camera", help="Camera version", default='v1')
    parser.add_argument("-b",
                        "--begin",
                        help="Begin scanning from X.",
                        default=0)
    parser.add_argument("-e", "--end", help="End scanning at X.", default=100)
    parser.add_argument("-y", "--y-offset", help="Y offset.", default=117)
    parser.add_argument("-z", "--z-offset", help="Z offset.", default=145)
    parser.add_argument("-a",
                        "--a-offset",
                        help="A offset/rotation.",
                        default=0)
    parser.add_argument("-o",
                        "--output",
                        help="Output point cloud file.",
                        default=os.path.join(destination, 'cloud.asc'))
    parser.add_argument("--lang",
                        help="Output language",
                        default='en_US.UTF-8')
    parser.add_argument("--email",
                        help="Send an email on task finish",
                        action='store_true',
                        default=False)
    parser.add_argument("--shutdown",
                        help="Shutdown on task finish",
                        action='store_true',
                        default=False)

    # GET ARGUMENTS
    args = parser.parse_args()

    slices = int(args.slices)
    destination = args.dest
    iso = int(args.iso)
    power = int(args.power)
    start_x = float(args.begin)
    end_x = float(args.end)
    width = int(args.width)
    height = int(args.height)
    z_offset = float(args.z_offset)
    y_offset = float(args.y_offset)
    a_offset = float(args.a_offset)

    task_id = int(args.task_id)
    user_id = int(args.user_id)
    object_id = int(args.object_id)
    object_name = args.object_name
    file_name = args.file_name
    camera_version = args.camera

    if task_id == 0:
        standalone = True
    else:
        standalone = False

    cloud_file = args.output
    lang = args.lang
    send_email = bool(args.email)
    monitor_file = config.get(
        'general', 'task_monitor'
    )  # TASK MONITOR FILE (write stats & task info, es: temperatures, speed, etc
    log_trace = config.get('general', 'trace')  # TASK TRACE FILE

    scan_dir = os.path.join(destination, "images")

    if not os.path.exists(scan_dir):
        makedirs(scan_dir)

    ##### delete files
    cleandirs(scan_dir)

    camera_path = os.path.join(config.get('hardware', 'cameras'))

    ################################################################################

    print 'SWEEP SCAN MODULE STARTING'
    print 'scanning from' + str(start_x) + "to" + str(end_x)
    print 'Num of scans : [{0}]'.format(slices)
    print 'ISO  setting : ', iso
    print 'Resolution   : ', width, '*', height, ' px'
    print 'Y-offset (y) : ', y_offset
    print 'Z-offset (z) : ', z_offset
    print 'A-Offset.    : ', a_offset

    #ESTIMATED SCAN TIME ESTIMATION
    estimated = (slices * 2) / 60.0
    if estimated < 1:
        estimated *= 60.0
        unit = "Seconds"
    else:
        unit = "Minutes"

    print 'Estimated Scan time =', str(estimated) + " " + str(
        unit) + "  [Pessimistic]"

    app = SweepScan(log_trace,
                    monitor_file,
                    scan_dir,
                    standalone=standalone,
                    width=width,
                    height=height,
                    iso=iso,
                    power=power,
                    lang=lang,
                    send_email=send_email)

    app_thread = Thread(target=app.run,
                        args=([
                            task_id, object_id, object_name, file_name,
                            camera_path, camera_version, start_x, end_x,
                            a_offset, y_offset, z_offset, slices, cloud_file
                        ]))
    app_thread.start()

    # app.loop() must be started to allow callbacks
    app.loop()
    app_thread.join()
Esempio n. 33
0
def main():
    config = ConfigService()

    # SETTING EXPECTED ARGUMENTS
    parser = argparse.ArgumentParser(
        add_help=False, formatter_class=argparse.ArgumentDefaultsHelpFormatter)

    parser.add_argument("-T", "--task-id", help="Task ID.", default=0)
    parser.add_argument("-U",
                        "--user-id",
                        help="User ID. (future use)",
                        default=0)

    parser.add_argument("--address", help="Remove server address.")
    parser.add_argument("--port", help="Remove server port.", default=9898)
    parser.add_argument("-d",
                        "--dest",
                        help="Destination folder.",
                        default=config.get('general', 'bigtemp_path'))
    parser.add_argument("-s",
                        "--slices",
                        help="Number of slices.",
                        default=100)
    parser.add_argument("-i", "--iso", help="ISO.", default=400)
    parser.add_argument("-W",
                        "--width",
                        help="Image width in pixels.",
                        default=1920)
    parser.add_argument("-H",
                        "--height",
                        help="Image height in pixels",
                        default=1080)
    parser.add_argument("-b",
                        "--begin",
                        help="Begin scanning from X.",
                        default=0)
    parser.add_argument("-e", "--end", help="End scanning at X.", default=360)
    parser.add_argument("-z", "--z-offset", help="Z offset.", default=0)
    parser.add_argument("-y", "--y-offset", help="Y offset.", default=0)
    parser.add_argument("-a",
                        "--a-offset",
                        help="A offset/rotation.",
                        default=0)
    parser.add_argument("--lang",
                        help="Output language",
                        default='en_US.UTF-8')
    parser.add_argument(
        "--standalone",
        action='store_true',
        help="Standalone operation. Does all preparations and cleanup.")
    parser.add_argument('--help',
                        action='help',
                        help="Show this help message and exit")
    parser.add_argument("--email",
                        help="Send an email on task finish",
                        action='store_true',
                        default=False)
    parser.add_argument("--shutdown",
                        help="Shutdown on task finish",
                        action='store_true',
                        default=False)

    # GET ARGUMENTS
    args = parser.parse_args()

    slices = int(args.slices)
    destination = args.dest
    host_address = args.address
    host_port = int(args.port)
    iso = int(args.iso)
    start_a = float(args.begin)
    end_a = float(args.end)
    width = int(args.width)
    height = int(args.height)
    z_offset = float(args.z_offset)
    y_offset = float(args.y_offset)
    a_offset = float(args.a_offset)
    standalone = args.standalone
    task_id = int(args.task_id)
    lang = args.lang
    send_email = bool(args.email)

    monitor_file = config.get(
        'general', 'task_monitor'
    )  # TASK MONITOR FILE (write stats & task info, es: temperatures, speed, etc
    log_trace = config.get('general', 'trace')  # TASK TRACE FILE

    scan_dir = os.path.join(destination, "images")

    if not os.path.exists(scan_dir):
        makedirs('scan_dir')

    ##### delete files
    cleandirs(scan_dir)

    ################################################################################

    app = PhotogrammetryScan(log_trace,
                             monitor_file,
                             scan_dir,
                             standalone=standalone,
                             width=width,
                             height=height,
                             iso=iso,
                             host_address=host_address,
                             host_port=host_port,
                             lang=lang,
                             send_email=send_email)

    app_thread = Thread(target=app.run,
                        args=([task_id, start_a, end_a, y_offset, slices]))
    app_thread.start()

    app.loop()  # app.loop() must be started to allow callbacks
    app_thread.join()
Esempio n. 34
0
#!/bin/env python
# -*- coding: utf-8; -*-

# Import internal modules
from fabtotum.fabui.config import ConfigService

cfg = ConfigService()

print cfg.get('serial', 'baud')
print cfg.get('serial', 'port')
print cfg.get('task', 'lock_file')