async def _main(args):
    # parse the spi flash
    if args.spi_flash:
        with open(args.spi_flash, 'rb') as spi_flash_file:
            spi_flash = FlashMemory(spi_flash_file.read())
    else:
        # Create memory containing default controller stick calibration
        spi_flash = FlashMemory()

    # Get controller name to emulate from arguments
    controller = Controller.from_arg(args.controller)

    with utils.get_output(path=args.log, default=None) as capture_file:
        # prepare the the emulated controller
        factory = controller_protocol_factory(controller, spi_flash=spi_flash)
        ctl_psm, itr_psm = 17, 19
        transport, protocol = await create_hid_server(factory, reconnect_bt_addr=args.reconnect_bt_addr,
                                                      ctl_psm=ctl_psm,
                                                      itr_psm=itr_psm, capture_file=capture_file,
                                                      device_id=args.device_id)

        controller_state = protocol.get_controller_state()

        # Create keyboard and mouse interface
        kmi = KMI(controller_state)
        # run the kmi
        try:
            await kmi.run()
        finally:
            logger.info('Stopping communication...')
            await transport.close()
Exemple #2
0
async def main(args):
    # parse the spi flash
    if args.spi_flash:
        with open(args.spi_flash, 'rb') as spi_flash_file:
            spi_flash = FlashMemory(spi_flash_file.read())
    else:
        # Create memory containing default controller stick calibration
        spi_flash = FlashMemory()

    # Get controller name to emulate from arguments
    controller = Controller.from_arg(args.controller)

    with utils.get_output(path=args.log, default=None) as capture_file:
        # prepare the the emulated controller
        factory = controller_protocol_factory(controller, spi_flash=spi_flash)
        ctl_psm, itr_psm = 17, 19
        transport, protocol = await create_hid_server(factory, reconnect_bt_addr=args.reconnect_bt_addr,
                                                      ctl_psm=ctl_psm,
                                                      itr_psm=itr_psm, capture_file=capture_file,
                                                      device_id=args.device_id)

        controller_state = protocol.get_controller_state()

        await controller_state.connect()

        ## RUN CONTROLLER CODE HERE
        await xbox(controller_state)

        await transport.close()
Exemple #3
0
async def _main(args):
    # parse the spi flash
    if args.spi_flash:
        with open(args.spi_flash, 'rb') as spi_flash_file:
            spi_flash = FlashMemory(spi_flash_file.read())
    else:
        # Create memory containing default controller stick calibration
        spi_flash = FlashMemory()

    # Get controller name to emulate from arguments
    controller = Controller.from_arg(args.controller)

    with utils.get_output(path=args.log, default=None) as capture_file:
        # prepare the the emulated controller
        factory = controller_protocol_factory(controller, spi_flash=spi_flash)
        ctl_psm, itr_psm = 17, 19
        transport, protocol = await create_hid_server(
            factory,
            reconnect_bt_addr=args.reconnect_bt_addr,
            ctl_psm=ctl_psm,
            itr_psm=itr_psm,
            capture_file=capture_file,
            device_id=args.device_id)

        controller_state = protocol.get_controller_state()

        joycon_server = JoyConRestfull()

        th = threading.Thread(target=joycon_server.run)
        th.start()

        # Create command line interface and add some extra commands
        cli = ControllerCLI(controller_state, queue)
        _register_commands_with_controller_state(controller_state, cli)
        cli.add_command(
            'amiibo',
            ControllerCLI.deprecated(
                'Command was removed - use "nfc" instead!'))

        # set default nfc content supplied by argument
        if args.nfc is not None:
            await cli.commands['nfc'](args.nfc)

        #asyncio.ensure_future(cli.run())
        #asyncio.ensure_future(app.run(port='5002'))
        # run the cli
        try:
            await cli.run()
        finally:
            logger.info('Stopping communication...')
            await transport.close()
async def _main(args):
    # parse the spi flash
    if args.spi_flash:
        with open(args.spi_flash, 'rb') as spi_flash_file:
            spi_flash = FlashMemory(spi_flash_file.read())
    else:
        # Create memory containing default controller stick calibration
        spi_flash = FlashMemory()

    # Get controller name to emulate from arguments
    controller = Controller.from_arg(args.controller)

    with utils.get_output(path=args.log, default=None) as capture_file:
        factory = controller_protocol_factory(controller, spi_flash=spi_flash)
        ctl_psm, itr_psm = 17, 19
        transport, protocol = await create_hid_server(
            factory,
            reconnect_bt_addr=args.reconnect_bt_addr,
            ctl_psm=ctl_psm,
            itr_psm=itr_psm,
            capture_file=capture_file,
            device_id=args.device_id)

        controller_state = protocol.get_controller_state()

        # Create command line interface and add some extra commands
        cli = ControllerCLI(controller_state)

        # Wrap the script so we can pass the controller state. The doc string will be printed when calling 'help'
        async def _run_Controller():
            '''
            - Controller
            '''
            await xbox(controller_state)

        # add the script from above
        #cli.add_command('mash', call_mash_button)
        cli.add_command('Controller', _run_Controller)
        cli.add_command('controller', _run_Controller)

        try:
            await cli.run()
        finally:
            logger.info('Stopping communication...')
            await transport.close()
Exemple #5
0
async def _main(args, loop):
    logger.info('Waiting for HID devices... Please connect one JoyCon (left OR right), or a Pro Controller over Bluetooth. '
                'Note: The bluez "input" plugin needs to be enabled (default)')

    controller = None
    while controller is None:
        for device in hid.enumerate(0, 0):
            # looking for devices matching Nintendo's vendor id and JoyCon product id
            if device['vendor_id'] == VENDOR_ID and device['product_id'] in (PRODUCT_ID_JL, PRODUCT_ID_JR, PRODUCT_ID_PC):
                controller = device
                break
        else:
            await asyncio.sleep(2)

    logger.info(f'Found controller "{controller}".')

    with utils.get_output(path=args.output, open_flags='wb', default=None) as output:
        with AsyncHID(path=controller['path'], loop=loop) as hid_controller:
            await dump_spi_flash(hid_controller, output_file=output)
Exemple #6
0
async def _main(args):
    # parse the spi flash
    if args.spi_flash:
        with open(args.spi_flash, 'rb') as spi_flash_file:
            spi_flash = FlashMemory(spi_flash_file.read())
    else:
        # Create memory containing default controller stick calibration
        spi_flash = FlashMemory()

    # Get controller name to emulate from arguments
    controller = Controller.from_arg(args.controller)

    with utils.get_output(path=args.log, default=None) as capture_file:
        # prepare the the emulated controller
        factory = controller_protocol_factory(controller, spi_flash=spi_flash)
        ctl_psm, itr_psm = 17, 19

        if args.bt_addr_file is not None:
            bt_addr = open(args.bt_addr_file, "r").read()
            if bt_addr == "ANY":
                bt_addr = None
        else:
            bt_addr = args.reconnect_bt_addr

        transport, protocol = await create_hid_server(
            factory,
            reconnect_bt_addr=bt_addr,
            ctl_psm=ctl_psm,
            itr_psm=itr_psm,
            capture_file=capture_file,
            device_id=args.device_id)

        controller_state = protocol.get_controller_state()

        # Create socket interface and add some extra commands
        socket_interface = ControllerSocketInterface(args.socket,
                                                     controller_state)
        _register_commands_with_controller_state(controller_state,
                                                 socket_interface)

        # run the socket_interface
        await socket_interface.start_server()
        return socket_interface, transport
Exemple #7
0
async def main(args, q):
    # parse the spi flash
    logger.name = "CLI进程"
    if args.spi_flash:
        with open(args.spi_flash, 'rb') as spi_flash_file:
            spi_flash = FlashMemory(spi_flash_file.read())
    else:
        # Create memory containing default controller stick calibration
        spi_flash = FlashMemory()

    # Get controller name to emulate from arguments
    controller = Controller.from_arg(args.controller)

    with utils.get_output(path=args.log, default=None) as capture_file:
        # prepare the the emulated controller
        factory = controller_protocol_factory(controller, spi_flash=spi_flash)
        ctl_psm, itr_psm = 17, 19
        transport, protocol = await create_hid_server(
            factory,
            reconnect_bt_addr=args.reconnect_bt_addr,
            ctl_psm=ctl_psm,
            itr_psm=itr_psm,
            capture_file=capture_file,
            device_id=args.device_id)

        controller_state = protocol.get_controller_state()
        joycontrol_http.controller_state = controller_state
        method = controller_state.button_state.set_button
        q.put(method)
        logger.debug("controller开始监听")
        while True:
            await asyncio.sleep(0.1)
            if q.empty():
                continue
            msg = q.get()
            if isinstance(msg, Command):
                if msg.target == "controller":
                    if msg.cmd == "btn_push":
                        from joycontrol.controller_state import button_push
                        await button_push(controller_state, msg.obj)
Exemple #8
0
    async def start(self, args):
        # Create memory containing default controller stick calibration
        spi_flash = FlashMemory()

        # Get controller name to emulate from arguments
        controller = Controller.from_arg('PRO_CONTROLLER')

        with utils.get_output(path=None, default=None) as capture_file:
            factory = controller_protocol_factory(controller,
                                                  spi_flash=spi_flash)
            ctl_psm, itr_psm = 17, 19
            transport, protocol = await create_hid_server(
                factory,
                reconnect_bt_addr=args.reconnect_bt_addr,
                ctl_psm=ctl_psm,
                itr_psm=itr_psm,
                capture_file=capture_file,
                device_id=args.device_id)

            controller_state = protocol.get_controller_state()
            self.transport = transport

            try:
                # waits until controller is fully connected
                await controller_state.connect()
                joycontrol_plugin = self.__load_plugin(args.plugin,
                                                       controller_state,
                                                       args.plugin_options)
                await joycontrol_plugin.run()
            except Exception as e:
                logger.error(e)
            finally:
                logger.info('Stopping communication...')
                await transport.close()
                self.transport = None
                self.joycontrol_cmd = None
Exemple #9
0
async def _main(args):

    # Create memory containing default controller stick calibration
    spi_flash = FlashMemory()

    # Get controller name to emulate from arguments
    controller = Controller.PRO_CONTROLLER

    with utils.get_output(path=args.log, default=None) as capture_file:
        factory = controller_protocol_factory(controller, spi_flash=spi_flash)
        transport, protocol = await create_hid_server(
            factory, ctl_psm=17, itr_psm=19, capture_file=capture_file)

        controller_state = protocol.get_controller_state()

        # Create command line interface and add some extra commands
        cli = command.CCLI(controller_state)

        try:
            await controller_state.connect()
            await cli.run()
        finally:
            logger.info('Stopping communication...')
            await transport.close()
Exemple #10
0
async def _main(args):
    # parse the spi flash
    if args.spi_flash:
        with open(args.spi_flash, 'rb') as spi_flash_file:
            spi_flash = FlashMemory(spi_flash_file.read())
    else:
        # Create memory containing default controller stick calibration
        spi_flash = FlashMemory()

    # Get controller name to emulate from arguments
    controller = Controller.from_arg(args.controller)

    with utils.get_output(path=args.log, default=None) as capture_file:
        factory = controller_protocol_factory(controller, spi_flash=spi_flash)
        ctl_psm, itr_psm = 17, 19
        transport, protocol = await create_hid_server(
            factory,
            reconnect_bt_addr=args.reconnect_bt_addr,
            ctl_psm=ctl_psm,
            itr_psm=itr_psm,
            capture_file=capture_file,
            device_id=args.device_id)

        controller_state = protocol.get_controller_state()

        # Create command line interface and add some extra commands
        cli = ControllerCLI(controller_state)

        # Wrap the script so we can pass the controller state. The doc string will be printed when calling 'help'
        async def _run_test_controller_buttons():
            """
            test_buttons - Navigates to the "Test Controller Buttons" menu and presses all buttons.
            """
            await test_controller_buttons(controller_state)

        # add the script from above
        cli.add_command('test_buttons', _run_test_controller_buttons)

        # Create amiibo command
        async def amiibo(*args):
            """
            amiibo - Sets amiibo content

            Usage:
                amiibo <file_name>          Set controller state NFC content to file
                amiibo remove               Remove NFC content from controller state
            """
            if controller_state.get_controller() == Controller.JOYCON_L:
                raise ValueError('NFC content cannot be set for JOYCON_L')
            elif not args:
                raise ValueError(
                    '"amiibo" command requires amiibo dump file path as argument!'
                )
            elif args[0] == 'remove':
                controller_state.set_nfc(None)
                print('Removed nfc content.')
            else:
                await set_amiibo(controller_state, args[0])

        # add the script from above
        cli.add_command('amiibo', amiibo)

        try:
            await cli.run()
        finally:
            logger.info('Stopping communication...')
            await transport.close()
Exemple #11
0
        'Selection of adapters may not work if the bluez "input" plugin is enabled.'
    )
    parser.add_argument(
        '--spi-flash',
        dest="spi_flash",
        metavar="FILE",
        help="Memory dump of a real Switch "
        "controller. Required for joystick emulation. Allows "
        "displaying of JoyCon colors. Memory dumbs can be created "
        "using the dump_spi_flash.py script.")
    args = parser.parse_args()

    controller = Controller.PRO_CONTROLLER
    spi_flash = None
    if args.spi_flash:
        with open(args.spi_flash, 'rb') as spi_flash_file:
            spi_flash = FlashMemory(spi_flash_file.read())

    with open(args.script, 'r') as f:
        script = yaml.load(f)

    with utils.get_output(path=args.log, default=None) as capture_file:
        loop = asyncio.get_event_loop()
        loop.run_until_complete(
            _main(script,
                  controller,
                  reconnect_bt_addr=args.addr,
                  capture_file=capture_file,
                  spi_flash=spi_flash,
                  device_id=args.device_id))
async def _main(args):
    # parse the spi flash
    if args.spi_flash:
        with open(args.spi_flash, 'rb') as spi_flash_file:
            spi_flash = FlashMemory(spi_flash_file.read())
    else:
        # Create memory containing default controller stick calibration
        spi_flash = FlashMemory()

    # Get controller name to emulate from arguments
    controller = Controller.from_arg(args.controller)

    with utils.get_output(path=args.log, default=None) as capture_file:
        factory = controller_protocol_factory(controller, spi_flash=spi_flash)
        ctl_psm, itr_psm = 17, 19
        transport, protocol = await create_hid_server(
            factory,
            reconnect_bt_addr=args.reconnect_bt_addr,
            ctl_psm=ctl_psm,
            itr_psm=itr_psm,
            capture_file=capture_file,
            device_id=args.device_id)

        controller_state = protocol.get_controller_state()

        # Create command line interface and add some extra commands
        cli = ControllerCLI(controller_state)

        # Wrap the script so we can pass the controller state. The doc string will be printed when calling 'help'
        async def _run_test_controller_buttons():
            """
            test_buttons - Navigates to the "Test Controller Buttons" menu and presses all buttons.
            """
            await test_controller_buttons(controller_state)

        # add the script from above
        cli.add_command('test_buttons', _run_test_controller_buttons)

        # Mash a button command
        async def call_mash_button(*args):
            """
            mash - Mash a specified button at a set interval

            Usage:
                mash <button> <interval>
            """
            if not len(args) == 2:
                raise ValueError(
                    '"mash_button" command requires a button and interval as arguments!'
                )

            button, interval = args
            await mash_button(controller_state, button, interval)

        # add the script from above
        cli.add_command('mash', call_mash_button)

        # Create nfc command
        async def nfc(*args):
            """
            nfc - Sets nfc content

            Usage:
                nfc <file_name>          Set controller state NFC content to file
                nfc remove               Remove NFC content from controller state
            """
            if controller_state.get_controller() == Controller.JOYCON_L:
                raise ValueError('NFC content cannot be set for JOYCON_L')
            elif not args:
                raise ValueError(
                    '"nfc" command requires file path to an nfc dump as argument!'
                )
            elif args[0] == 'remove':
                controller_state.set_nfc(None)
                print('Removed nfc content.')
            else:
                await set_nfc(controller_state, args[0])

        # add the script from above
        cli.add_command('nfc', nfc)
        cli.add_command(
            'amiibo',
            ControllerCLI.deprecated(
                'Command is deprecated - use "nfc" instead!'))

        if args.nfc is not None:
            await nfc(args.nfc)
        eventToButton = {
            304: 'b',
            305: 'a',
            307: 'y',
            308: 'x',
            704: 'left',
            705: 'right',
            706: 'up',
            707: 'down',
            311: 'r',
            310: 'l',
            312: 'zl',
            313: 'zr',
            314: 'minus',
            315: 'plus',
            317: 'l_stick',
            318: 'r_stick',
        }

        device = evdev.InputDevice(
            "/dev/input/by-id/usb-045e_0291-event-joystick")
        caps = device.capabilities()
        try:
            t1 = time.perf_counter()
            cnt = 0
            async for event in device.async_read_loop():
                if event.type == ecodes.EV_SYN:
                    lasttask = asyncio.ensure_future(
                        sync_controller(controller_state))
                if event.type == ecodes.EV_ABS:
                    if event.code == 0:
                        controller_state.l_stick_state.set_h(event.value //
                                                             22 + 2048)
                    elif event.code == 1:
                        controller_state.l_stick_state.set_v(
                            -(event.value - 15) // 22 + 2047)
                    elif event.code == 3:
                        controller_state.r_stick_state.set_h(event.value //
                                                             22 + 2048)
                    elif event.code == 4:
                        controller_state.r_stick_state.set_v(
                            -(event.value - 15) // 22 + 2047)
                elif event.type == ecodes.EV_KEY:
                    if event.code in eventToButton:
                        buttonCode = eventToButton[event.code]
                        button_set_state(controller_state, buttonCode, event)
                        if event.code == 305:
                            if event.value == 1:
                                if controller_state.button_state.get_button(
                                        'zr'):
                                    button_set_state(controller_state, 'home',
                                                     event)
                            else:
                                button_set_state(controller_state, 'home',
                                                 event)
                        lasttask = asyncio.ensure_future(
                            sync_controller(controller_state))
                cnt = cnt + 1
                if cnt > 50:
                    cnt = 0
                    t2 = time.perf_counter()
                    deltaT = t2 - t1
                    freq = 50.00 / deltaT
                    str = " 50 event takes  " + format(
                        deltaT, '.2f') + " secs freq = " + format(freq, '.2f')
                    logger.info(str)
                    t1 = t2
        except:
            logger.info('unexpected')
            logger.info(sys.exc_info()[0])
        finally:
            logger.info('Stopping communication...')
            await transport.close()
Exemple #13
0
import argparse
import asyncio
import logging
import os
import socket
import struct
import time
import hid
from joycontrol import logging_default as log, utils
from joycontrol.device import HidDevice
from joycontrol.server import PROFILE_PATH
from joycontrol.utils import AsyncHID
logger = logging.getLogger(__name__)
VENDOR_ID = 1406
PRODUCT_ID_JL = 8198
PRODUCT_ID_JR = 8199
PRODUCT_ID_PC = 8201

class Relay:
    def __init__(self, capture_file=None):
        self._capture_file = capture_file
    async def relay_input(self, hid_device, client_itr):
        loop = asyncio.get_event_loop()
        while True:
            data = await hid_device.read(100)
            # add adding byte for input report
            data = b'\xa1' + data
            if self._capture_file is not None:
                # write data to log file
                current_time = struct.pack('d', time.time())
Exemple #14
0
async def _main(args):
    # parse the spi flash
    if args.spi_flash:
        with open(args.spi_flash, 'rb') as spi_flash_file:
            spi_flash = FlashMemory(spi_flash_file.read())
    else:
        # Create memory containing default controller stick calibration
        spi_flash = FlashMemory()

    # Get controller name to emulate from arguments
    controller = Controller.from_arg(args.controller)
    async def nfc(*args):
        if controller_state.get_controller() == Controller.JOYCON_L:
            raise ValueError('NFC content cannot be set for JOYCON_L')
        elif not args:
            raise ValueError('"nfc" command requires file path to an nfc dump as argument!')
        elif args[0] == 'remove':
            controller_state.set_nfc(None)
            print('Removed nfc content.')
        else:
            _loop = asyncio.get_event_loop()
            with open(args[0], 'rb') as nfc_file:
                content = await _loop.run_in_executor(None, nfc_file.read)
                controller_state.set_nfc(content)

    with utils.get_output(path=args.log, default=None) as capture_file:
        # prepare the the emulated controller
        factory = controller_protocol_factory(controller, spi_flash=spi_flash)
        ctl_psm, itr_psm = 17, 19
        draw.text((x, top + 16), str("Waiting for Switch to"), font=font, fill=255)
        draw.text((x + 40, top + 24), str("Connect,"), font=font, fill=255)
        draw.text((x + 18, top + 40), str("Please open the"), font=font, fill=255)
        draw.text((x + 6, top + 48), str("'Change Grip/Order'"), font=font, fill=255)
        draw.text((x + 46, top + 56), str("menu."), font=font, fill=255)

        disp.image(image)
        disp.display()
        transport, protocol = await create_hid_server(factory, reconnect_bt_addr=args.reconnect_bt_addr,
                                                      ctl_psm=ctl_psm,
                                                      itr_psm=itr_psm, capture_file=capture_file,
                                                      device_id=args.device_id)

        controller_state = protocol.get_controller_state()

        # Create command line interface and add some extra commands
        cli = ControllerCLI(controller_state)

        # set default nfc content supplied by argument
        if args.nfc is not None:
            await cli.commands['nfc'](args.nfc)

        # run the cli
        try:
            await nfc(args.nfc)
            await run_at_start(controller_state)
            #await cli.run()


        finally:
            logger.info('Stopping communication...')
            await transport.close()
Exemple #15
0
async def _main(args):
    # parse the spi flash
    if args.spi_flash:
        with open(args.spi_flash, 'rb') as spi_flash_file:
            spi_flash = FlashMemory(spi_flash_file.read())
    else:
        # Create memory containing default controller stick calibration
        spi_flash = FlashMemory()

    # Get controller name to emulate from arguments
    controller = Controller.from_arg(args.controller)

    with utils.get_output(path=args.log, default=None) as capture_file:
        factory = controller_protocol_factory(controller, spi_flash=spi_flash)
        ctl_psm, itr_psm = 17, 19
        transport, protocol = await create_hid_server(
            factory,
            reconnect_bt_addr=args.reconnect_bt_addr,
            ctl_psm=ctl_psm,
            itr_psm=itr_psm,
            capture_file=capture_file,
            device_id=args.device_id)

        controller_state = protocol.get_controller_state()

        # Create command line interface and add some extra commands
        cli = ControllerCLI(controller_state)

        # Wrap the script so we can pass the controller state. The doc string will be printed when calling 'help'
        async def _run_test_control():
            """
            test_control - test method that will be removed later
            """
            await test_control(controller_state)

        async def _run_keyboard_control():
            """
            keyboard - binds controls to keyboard. Keybinding:
            q=LEFT w=LstickUP e=UP r=ZL t=L y=R u=ZR i=RstickUP
            a=LstickLEFT s=LstickDOWN d=LstickRIGHT f=RIGHT g=capture h=home j=RstickLEFT k=RStickDOWN l=RstickRIGHT
            c=DOWN up=X down=B left=Y right=A
            plus= + minus= -
            """
            await keyboard_control(controller_state)

        async def _run_recording_control():
            """
            recording - binds controls to keyboard, and records input until recording stopped.
            saved recordings can be replayed using cmd >> recording_playback
            Keybinding:
            q=LEFT w=LstickUP e=UP r=ZL t=L y=R u=ZR i=RstickUP
            a=LstickLEFT s=LstickDOWN d=LstickRIGHT f=RIGHT g=capture h=home j=RstickLEFT k=RStickDOWN l=RstickRIGHT
            c=DOWN up=X down=B left=Y right=A
            plus= + minus= -
            """
            await record_keyboard(controller_state)

        async def _run_recording_playback():
            """
            playback - select a saved recording and replay it
            """
            await recording_playback(controller_state)

        async def _run_delete_recording():
            """
            delete_rec - select a saved recording and delete it
            """
            await delete_recording(controller_state)

        async def _run_test_controller_buttons():
            """
            test_buttons - Navigates to the "Test Controller Buttons" menu and presses all buttons.
            """
            await test_controller_buttons(controller_state)

        # Mash a button command
        async def call_mash_button(*args):
            """
            mash - Mash a specified button at a set interval
            Usage:
                mash <button> <interval>
            """
            if not len(args) == 2:
                raise ValueError(
                    '"mash_button" command requires a button and interval as arguments!'
                )

            button, interval = args
            await mash_button(controller_state, button, interval)

        # Create nfc command
        async def nfc(*args):
            """
            nfc - Sets nfc content

            Usage:
                nfc <file_name>          Set controller state NFC content to file
                nfc remove               Remove NFC content from controller state
            """
            if controller_state.get_controller() == Controller.JOYCON_L:
                raise ValueError('NFC content cannot be set for JOYCON_L')
            elif not args:
                raise ValueError(
                    '"nfc" command requires file path to an nfc dump as argument!'
                )
            elif args[0] == 'remove':
                controller_state.set_nfc(None)
                print('Removed nfc content.')
            else:
                await set_nfc(controller_state, args[0])

        cli.add_command('test_buttons', _run_test_controller_buttons)
        cli.add_command('keyboard', _run_keyboard_control)
        cli.add_command('recording', _run_recording_control)
        cli.add_command('playback', _run_recording_playback)
        cli.add_command('delete_rec', _run_delete_recording)
        cli.add_command('mash', call_mash_button)
        # add the script from above
        cli.add_command('nfc', nfc)

        if args.nfc is not None:
            await nfc(args.nfc)

        try:
            await cli.run()
        finally:
            logger.info('Stopping communication...')
            await transport.close()