shell over NUS (NUS shell transport) not working as expected

I have adapted the shell over NUS example into some code we have ourself. The code we have have so far used physical UART as a shell interface. I can see that the Bluetooth connection is also reported as a backend, but I don't get any response on shell commands over bluetooth. I am guessing I am missing some kind of CONFIGs to get this working. Have anybody experienced similar behaviour?

Parents
  • Hello

    Does the NUS shell example by itself work as intended?

    If so, have you looked at the configs used in that sample?

    Best regards,

    Einar

  • Sometimes the simplest thing is creating problem. Problem lies (partially) between keyboard and chair: 
    I used the nRF Toolbox on the phone to try out the code. 
    Every time I tried to transmit something I saw that it got transmitted, and I got the characters echoed back. But nothing happened.
    The problem is that when you send something from the nRF Toolbox (at least on iOS), the carrier-return/line-feed is not sent! This I discovered when debugging and seeing that only 4 characters got sent when it wrote "help" and hit return.
    Making a macro did change all this. 
    An idea for the application team at Nordic: Make the serial terminal support Bluetooth LE serial port. There are cross-platform libraries for bluetooth (I don't know if it exists for electra, but python and others have now cross-platform libraries).

  • I had the same problem. For Linux, there are tools from Nordic to solve it, see the documentation: developer.nordicsemi.com/.../shell_bt_nus.html

    But I wrote a simple one file Python script to have just a terminal to the NUS shell. It is a bit slow, because of the polling, but otherwise works well, including ANSI color, tab-completion etc.:

    #!/usr/bin/env python3
    
    # installation requirement:
    # pip3 install bluepy
    #
    # first connect a USB bluetooth adapter. "hcitool dev" should show it:
    #
    # $ hcitool dev
    # Devices:
    #         hci0    18:4F:32:F2:16:22
    #
    # If not, then check, if the USB device is recognized at all:
    #
    # $ lsusb
    # Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
    # Bus 001 Device 019: ID 0a5c:21e8 Broadcom Corp. BCM20702A0 Bluetooth 4.0
    # ...
    #
    # If it doesn't get detected, try another USB adapter.
    #
    # If detected, then maybe first start it:
    #
    # sudo hciconfig hci0 up
    #
    # Sometimes the Bluetooth stack gets stuck, and even a `hcitool lescan`
    # doesn't work anymore, or you get an error like this:
    # bluepy.btle.BTLEManagementError: Failed to execute management command 'scanend' (code: 11, error: Rejected)
    # In this case, restart the interface like this:
    #
    # sudo hciconfig hci0 down
    # sudo hciconfig hci0 up
    #
    # If you have more than one USB bluetooth adapter, try hci1 etc.
    #
    # Then start the peripheral, and search for the key fob:
    #
    # $ sudo hcitool lescan
    # LE Scan ...
    # E9:56:3D:BF:59:3E FOOBAR
    # ...
    #
    # Important: if you have more than one bluetooth adapter, then old Bluetooth 4 adapter
    # might see it, too, but it won't work with it. Then as described above, use the right
    # adapter with hciconfig.
    # 
    # Finally start the NUS script:
    #
    # $ ./nus.py E9:56:3D:BF:59:3E
    #
    # the output should look like this:
    # connected
    #
    # Then you can use it like a terminal, tab-completion works, too.
    
    import struct
    from bluepy.btle import *
    import sys
    import time
    import atexit
    
    import sys, termios
    from select import select
    
    if len(sys.argv) != 2:
    	print("usage: python nus.py bluetooth-address")
    	exit()
    
    # save the terminal settings
    fd = sys.stdin.fileno()
    new_term = termios.tcgetattr(fd)
    old_term = termios.tcgetattr(fd)
    
    # new terminal setting unbuffered
    new_term[3] = (new_term[3] & ~termios.ICANON & ~termios.ECHO)
    termios.tcsetattr(fd, termios.TCSAFLUSH, new_term)
    
    def getch():
        return sys.stdin.read(1)
    
    def kbhit():
        dr,dw,de = select([sys.stdin], [], [], 0)
        return len(dr)>0
    
    # at script exit, restore termios settings
    def restore():
        termios.tcsetattr(fd, termios.TCSAFLUSH, old_term)
        print()
    atexit.register(restore)
    
    # callback class for handling Mobee messages
    class MyDelegate(DefaultDelegate):
        def __init__(self):
            DefaultDelegate.__init__(self)
    
        def handleNotification(self, cHandle, data):
            sys.stdout.buffer.write(data)
            sys.stdout.flush()
    
    # connect to device
    per = Peripheral(sys.argv[1], "random")
    print("connected")
    
    while True:
        try:
            # set callback for notifications
            per.setDelegate(MyDelegate())
    
            # enable notification
            setup_data = b"\x01\x00"
            notify = per.getCharacteristics(uuid='6e400003-b5a3-f393-e0a9-e50e24dcca9e')[0]
            notify_handle = notify.getHandle() + 1
            per.writeCharacteristic(notify_handle, setup_data, withResponse=True)
            
            # get send characteristics
            c = per.getCharacteristics(uuid='6e400002-b5a3-f393-e0a9-e50e24dcca9e')[0]
            
            # wait for answer
            while True:
                if per.waitForNotifications(0.0001) or True:
                    if kbhit():
                        ch = getch()
                        c.write(ch.encode('latin-1'))
                    continue
        except KeyboardInterrupt:
            sys.exit(0)
        finally:
            per.disconnect()
    

Reply
  • I had the same problem. For Linux, there are tools from Nordic to solve it, see the documentation: developer.nordicsemi.com/.../shell_bt_nus.html

    But I wrote a simple one file Python script to have just a terminal to the NUS shell. It is a bit slow, because of the polling, but otherwise works well, including ANSI color, tab-completion etc.:

    #!/usr/bin/env python3
    
    # installation requirement:
    # pip3 install bluepy
    #
    # first connect a USB bluetooth adapter. "hcitool dev" should show it:
    #
    # $ hcitool dev
    # Devices:
    #         hci0    18:4F:32:F2:16:22
    #
    # If not, then check, if the USB device is recognized at all:
    #
    # $ lsusb
    # Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
    # Bus 001 Device 019: ID 0a5c:21e8 Broadcom Corp. BCM20702A0 Bluetooth 4.0
    # ...
    #
    # If it doesn't get detected, try another USB adapter.
    #
    # If detected, then maybe first start it:
    #
    # sudo hciconfig hci0 up
    #
    # Sometimes the Bluetooth stack gets stuck, and even a `hcitool lescan`
    # doesn't work anymore, or you get an error like this:
    # bluepy.btle.BTLEManagementError: Failed to execute management command 'scanend' (code: 11, error: Rejected)
    # In this case, restart the interface like this:
    #
    # sudo hciconfig hci0 down
    # sudo hciconfig hci0 up
    #
    # If you have more than one USB bluetooth adapter, try hci1 etc.
    #
    # Then start the peripheral, and search for the key fob:
    #
    # $ sudo hcitool lescan
    # LE Scan ...
    # E9:56:3D:BF:59:3E FOOBAR
    # ...
    #
    # Important: if you have more than one bluetooth adapter, then old Bluetooth 4 adapter
    # might see it, too, but it won't work with it. Then as described above, use the right
    # adapter with hciconfig.
    # 
    # Finally start the NUS script:
    #
    # $ ./nus.py E9:56:3D:BF:59:3E
    #
    # the output should look like this:
    # connected
    #
    # Then you can use it like a terminal, tab-completion works, too.
    
    import struct
    from bluepy.btle import *
    import sys
    import time
    import atexit
    
    import sys, termios
    from select import select
    
    if len(sys.argv) != 2:
    	print("usage: python nus.py bluetooth-address")
    	exit()
    
    # save the terminal settings
    fd = sys.stdin.fileno()
    new_term = termios.tcgetattr(fd)
    old_term = termios.tcgetattr(fd)
    
    # new terminal setting unbuffered
    new_term[3] = (new_term[3] & ~termios.ICANON & ~termios.ECHO)
    termios.tcsetattr(fd, termios.TCSAFLUSH, new_term)
    
    def getch():
        return sys.stdin.read(1)
    
    def kbhit():
        dr,dw,de = select([sys.stdin], [], [], 0)
        return len(dr)>0
    
    # at script exit, restore termios settings
    def restore():
        termios.tcsetattr(fd, termios.TCSAFLUSH, old_term)
        print()
    atexit.register(restore)
    
    # callback class for handling Mobee messages
    class MyDelegate(DefaultDelegate):
        def __init__(self):
            DefaultDelegate.__init__(self)
    
        def handleNotification(self, cHandle, data):
            sys.stdout.buffer.write(data)
            sys.stdout.flush()
    
    # connect to device
    per = Peripheral(sys.argv[1], "random")
    print("connected")
    
    while True:
        try:
            # set callback for notifications
            per.setDelegate(MyDelegate())
    
            # enable notification
            setup_data = b"\x01\x00"
            notify = per.getCharacteristics(uuid='6e400003-b5a3-f393-e0a9-e50e24dcca9e')[0]
            notify_handle = notify.getHandle() + 1
            per.writeCharacteristic(notify_handle, setup_data, withResponse=True)
            
            # get send characteristics
            c = per.getCharacteristics(uuid='6e400002-b5a3-f393-e0a9-e50e24dcca9e')[0]
            
            # wait for answer
            while True:
                if per.waitForNotifications(0.0001) or True:
                    if kbhit():
                        ch = getch()
                        c.write(ch.encode('latin-1'))
                    continue
        except KeyboardInterrupt:
            sys.exit(0)
        finally:
            per.disconnect()
    

Children
No Data
Related