import netw
from netw import get_init_status, INIT_OK, INIT_CONF0, INIT_RESET, INIT_BEGIN, INIT_FAILURE
from ucollections import namedtuple
from vts import unit_info, delay_ms as sleep
from micropython import const

class NetError(Exception):
    pass

# All received data will be put here (key: channel, value: list of packets)
_data = {}

# This function can be set to execute when a message arrives, preempting the
# default callback
_preempt_msg = None

#user_set_callback
net0_cb = None

def _get_next_atconf():
    # Make a copy of the list
    msgs = netw.get_messages()[:]
    if len(msgs):
        print(msgs)
    for (i, msg) in enumerate(msgs):
        if netw.UBX_EDM_TYPE_CONFIRMATION == msg.type and netw.UBX_EDM_ID_AT == msg.id:
            netw.get_messages().pop(i)
            return msg

def _wait_for_ok():
    while 1:
        atconf = _get_next_atconf()
        if atconf is None or atconf.msg is None:
            continue
        msg_l = atconf.msg.decode('utf-8').strip().split('\r')
        for l in msg_l:
            l = l.strip()
            if l == 'ERROR':
                raise NetError('ODIN error')
            elif l == 'OK':
                return

def cmd(s):
    # netw.tx_msg_edm(s, netw.UBX_EDM_ID_AT, netw.UBX_EDM_TYPE_REQUEST)
    netw.tx_msg_edm(s, netw.UBX_EDM_CMD_AT_REQ)
    print("Sent ", s)

def cmdok(s):
    # Clear old messages, if any, before sending command
    netw.get_messages().clear()
    netw.tx_msg_edm(s, netw.UBX_EDM_CMD_AT_REQ)
    _wait_for_ok()

def cmd_resp(command='AT+UBTLN?'):
    netw.get_messages().clear()
    cmd(command)
    val = []
    while 1:
        atconf = _get_next_atconf()
        # If no AT confirmation yet, go back to the start of the loop
        if atconf is None:
            continue
        # Received an AT confirmation packet, get message inside and split by
        # lines
        resp = atconf.msg.decode('utf-8').strip().split('\r')
        # print(resp)
        for l in resp:
            l = l.strip()
            if l == 'ERROR':
                raise NetError('Error Returned from that command')
            elif l == 'OK':
                if val:
                    return val[0] if (len(val) == 1) else val
                else:
                    return resp
            else:
                if l == '"':
                    val[-1] += l
                else:
                    val.append(l)

def data_send(channel, data):
    # netw.tx_msg_edm(chr(channel) + data, netw.UBX_EDM_ID_DATA, netw.UBX_EDM_TYPE_COMMAND)
    netw.tx_msg_edm(chr(channel) + data,  netw.UBX_EDM_TYPE_COMMAND)

def callback_wrapper(type):
    """ Wrapper for callback.

        The original ODIN net0 callback wasn't triggered if the received message was an AT
        response/confirmation. The netw callback is triggered for all messages so we use this
        wrapper to filter out the AT responses.
    """
    global net0_cb
    if not type == 0x0045 and not net0_cb is None:
        net0_cb()

def callback(cb):
    global net0_cb
    def is_callback(val):
        return type(val).__name__ in ['bound_method', 'function', 'closure']

    if cb is None:
        netw.set_callback(None)
        net0_cb = None
    elif not is_callback(cb):
        raise TypeError('invalid callback argument')
    else:
        net0_cb = cb
        netw.set_callback(callback_wrapper)

def wifi_scan():
    Wlan_base = namedtuple('wlan',
        ('ssid',
        'bssid',
        'channel',
        'rssi',
        'op_mode',
        'auth_suites',
        'unicast_ciphers',
        'group_ciphers'))

    class Wlan(Wlan_base):
        def __hash__(self):
            return int(self.bssid[:7], 16) ^ int(self.bssid[7:12], 16)
        def __eq__(self, other):
            return self.bssid == other.bssid
        def __lt__(self, other):
            return self.bssid < other.bssid
        def __gt__(self, other):
            return self.bssid > other.bssid

    resp = ''
    val = []
    # Clear old messages, if any, before sending command
    netw.get_messages().clear()
    cmd('AT+UWSCAN')
    while 1:
        atconf = _get_next_atconf()
        # If no AT confirmation yet, go back to the start of the loop
        if atconf is None:
            continue
        # Received an AT confirmation packet, get message inside and split by
        # lines
        resp = atconf.msg.decode('utf-8').strip().split('\r')
        for l in resp:
            l = l.strip()
            if l[:8] == '+UWSCAN:':
                # Strip identifier
                l = l[8:]
                # Split by commas, but avoid splitting the ssid (use the fact
                # it's surrounded by quotes)
                fields = l.split('"')
                fields = (
                    fields[0][:-1].split(',')
                    + [fields[1]]
                    + fields[2][1:].split(','))
                v = Wlan(
                    fields[2],
                    fields[0],
                    int(fields[3]),
                    int(fields[4]),
                    int(fields[1]),
                    int(fields[5]),
                    int(fields[6]),
                    int(fields[7]))
                val.append(v)
            elif l == 'ERROR':
                raise NetError('Error while scanning wi-fi networks')
            elif l == 'OK':
                return sorted(list(set(val)))

AUTH_OPEN     = 1
AUTH_WPA_WPA2 = 2
AUTH_LEAP     = 3
AUTH_PEAP     = 4
IP_STATIC = 1
IP_DHCP   = 2

def wifi_setup(
    wlan,
    password='',
    auth=AUTH_WPA_WPA2,
    ipmode=IP_DHCP,
    use_bssid=False,
    always_active=False):

    n = wlan
    if type(n) is str:
        ssid = n
    else:
        ssid = n.ssid
    cmdok('AT+UWSCA=0,4')
    cmdok('AT+UWSC=0,0,{:d}'.format(always_active))
    cmdok('AT+UWSC=0,2,"{0}"'.format(ssid))
    if use_bssid:
        cmdok('AT+UWSC=0,3,"{0}"'.format(n.bssid))
    cmdok('AT+UWSC=0,5,{0}'.format(auth))
    if auth != AUTH_OPEN:
        cmdok('AT+UWSC=0,{0},"{1}"'.format(
            8 if AUTH_WPA_WPA2 == auth else 9,
            password))
    cmdok('AT+UWSC=0,100,{0}'.format(ipmode))
    # Store profile
    cmdok('AT+UWSCA=0,1')

def wifi_connect():
    # Activate profile
    cmdok('AT+UWSCA=0,3')

def wifi_disconnect():
    # Deactivate profile
    cmdok('AT+UWSCA=0,4')

def wifi_erase():
    # Deactivate profile
    cmdok('AT+UWSCA=0,4')
    # Reset profile
    cmdok('AT+UWSCA=0,0')
    # Store profile
    cmdok('AT+UWSCA=0,1')

def wifi_is_configured():
    res = None
    # Clear old messages, if any, before sending command
    netw.get_messages().clear()
    cmd('AT+UWSC=0,2')
    while 1:
        atconf = _get_next_atconf()
        # If no AT confirmation yet, go back to the start of the loop
        if atconf is None:
            continue
        # Received an AT confirmation packet, get message inside and split by
        # lines
        resp = atconf.msg.decode('utf-8').strip().split('\r')
        for l in resp:
            l = l.strip()
            if l[:6] == '+UWSC:':
                res = (l != '+UWSC:0,2,""')
            elif l == 'ERROR':
                raise NetError('Error while checking config')
            elif l == 'OK':
                if res is None:
                    raise NetError('Empty response while checking config')
                return res

def wifi_status():
    from ucollections import namedtuple
    Wlan_short = namedtuple('wlan',
        ('ssid',
        'bssid',
        'channel',
        'status',
        'rssi'))

    ssid = bssid = channel = status = rssi = None
    # Clear old messages, if any, before sending command
    netw.get_messages().clear()
    cmd('AT+UWSSTAT')
    while 1:
        atconf = _get_next_atconf()
        # If no AT confirmation yet, go back to the start of the loop
        if atconf is None:
            continue
        # Received an AT confirmation packet, get message inside and split by
        # lines
        resp = atconf.msg.decode('utf-8').strip().split('\r')
        for l in resp:
            l = l.strip()
            if l[:9] == '+UWSSTAT:':
                # Strip identifier
                l = l[9:]
                # Split by first comma
                id = int(l[0])
                val = l[2:]
                if id == 0:
                    # Strip quotes
                    ssid = val[1:-1]
                elif id == 1:
                    bssid = val
                elif id == 2:
                    channel = int(val)
                elif id == 3:
                    status = ['Disabled', 'Disconnected', 'Connected'][int(val)]
                elif id == 6:
                    rssi = int(val)
            elif l == 'ERROR':
                raise NetError('Error while getting wi-fi status')
            elif l == 'OK':
                return Wlan_short(ssid, bssid, channel, status, rssi)

def network_status():
    from ucollections import namedtuple
    Network = namedtuple('network',
        ('hmac',
        'status',
        'iftype',
        'ipv4_addr',
        'subnet_mask',
        'gateway',
        'DNS_prim',
        'DNS_sec',
        'ipv6_lladdr'))

    mac = stat = ift = ipv4 = snet = gway = dns1 = dns2 = ipv6 = None
    # Clear old messages, if any, before sending command
    netw.get_messages().clear()
    cmd('AT+UNSTAT')
    while 1:
        atconf = _get_next_atconf()
        # If no AT confirmation yet, go back to the start of the loop
        if atconf is None:
            continue
        # Received an AT confirmation packet, get message inside and split by
        # lines
        resp = atconf.msg.decode('utf-8').strip().split('\r')
        for l in resp:
            l = l.strip()
            if l[:8] == '+UNSTAT:':
                # Strip identifier and interface id
                l = l[10:]
                # Split by commas and get status id
                fields = l.split(',')
                sid = int(fields[0])
                if sid == 0:
                    mac = fields[1]
                elif sid == 1:
                    stat = ['down', 'up'][int(fields[1])]
                elif sid == 2:
                    ift = (
                        ['unknown',
                        'wi-fi station',
                        'wi-fi AP',
                        'ethernet',
                        'PPP'])[int(fields[1])]
                if sid == 101:
                    ipv4 = fields[1]
                if sid == 102:
                    snet = fields[1]
                if sid == 103:
                    gway = fields[1]
                if sid == 104:
                    dns1 = fields[1]
                if sid == 105:
                    dns2 = fields[1]
                if sid == 201:
                    ipv6 = fields[1]
            elif l == 'ERROR':
                raise NetError('Error while getting network status')
            elif l == 'OK':
                return Network(mac, stat, ift, ipv4, snet, gway, dns1, dns2, ipv6)

_last_conn_channel = None

def peer_connect(url, cb=None):
    global _last_conn_channel
    _last_conn_channel = None
    val = None

    # Create a preempt callback which will signal when the message we want arrives
    def ppt_msg_cb():
        global _last_conn_channel
        msg = netw.get_messages()[-1]
        if netw.UBX_EDM_TYPE_EVENT == msg.type and netw.UBX_EDM_ID_CONNECT == msg.id:
            _last_conn_channel = msg.msg[0]
        elif netw.UBX_EDM_ID_DISCONNECT == msg.id:
            _last_conn_channel = -1
        # Return false unconditionally because we want to see the event printed
        # on the console
        return False

    # Set the callback
    global _preempt_msg
    _preempt_msg = cb if cb else ppt_msg_cb
    # Clear old messages, if any, before sending command
    netw.get_messages().clear()
    # Issue command
    cmd('AT+UDCP="' + url + '"')
    while 1:
        atconf = _get_next_atconf()
        # If no AT confirmation yet, go back to the start of the loop
        if atconf is None:
            continue
        # Received an AT confirmation packet, get message inside and split by
        # lines
        resp = atconf.msg.decode('utf-8').strip().split('\r')
        for l in resp:
            l = l.strip()
            if l[:6] == '+UDCP:':
                # Strip identifier
                l = l[6:]
                # Wait for connect event
                while _last_conn_channel is None:
                    pass
                # Unset callback
                _preempt_msg = None
                channel = _last_conn_channel
                # Check for error
                if channel == -1:
                    raise NetError('Channel Error while connecting to peer')
                # Create entry in data table
                _data[channel] = []
                # Return handle and channel
                val = (int(l), channel)
            elif l == 'ERROR':
                raise NetError('Unknown Error while connecting to peer')
            elif l == 'OK':
                return val

def peer_disconnect(handle):
    cmdok('AT+UDCPC=' + str(handle))

def set_data_handle_cb(channel, func):
    data_handlers[channel] = func

def set_at_event_handler(msg, func):
    if callable(func):
        at_handlers[msg] = func
    else:
        raise TypeError("argument is not a callable function")

def get_stored_data(channel):
    try:
        msgs = _data[channel].copy()
        _data[channel].clear()
    except KeyError:
        #Channel not created yet
        return []
    return msgs

############BT###################

BT_MODE_DISC_OFF                = const(1)
BT_MODE_DISC_LIMITED            = const(2)
BT_MODE_DISC_ON                 = const(3)

BT_MODE_CONN_OFF                = const(1)
BT_MODE_CONN_ON                 = const(2)

BT_MODE_PAIR_OFF                = const(1)
BT_MODE_PAIR_ON                 = const(2)

BT_MODE_SEC_DISABLED            = const(1)
BT_MODE_SEC_DEFAULT             = const(2)
BT_MODE_SEC_DISPLAY_PASSKEY     = const(3)
BT_MODE_SEC_CONFIRM             = const(4)
BT_MODE_SEC_ENTER_PASSKEY       = const(5)

def _bt_save():
    cmdok('AT&W')

def discoverable():
    netw.get_messages().clear()
    cmd('AT+UBTDM?')
    while 1:
        atconf = _get_next_atconf()
        # If no AT confirmation yet, go back to the start of the loop
        if atconf is None:
            continue
        # Received an AT confirmation packet, get message inside and split by
        # lines
        val = None
        resp = atconf.msg.decode('utf-8').strip().split('\r')
        print("Discoverable:" , resp)
        for l in resp:
            l = l.strip()
            if l[:7] == '+UBTDM:':
                # Strip identifier
                val = True if (int(l[-1]) > 1) else False
            elif l == 'ERROR':
                raise NetError('Unable to check discovrability')
            elif l == 'OK':
                if val is None:
                    raise NetError('Empty response while checking config')
                return val

def set_bt_name(name):
    cmdok('AT+UBTLN='+name)
    _bt_save()

def bt_search(timeout=15000):
    """Search for nearby bluetooth devices. Generator Function used
    as some devices can take up to 30 seconds to appear. You must catch
    the StopIteration yourself.

    Args:
        timeout (int, optional): Search Time. Defaults to 15000.

    Raises:
        NetError: Error retrieving Bluetooth device info

    Returns:
        None

    Yields:
        Bluetooth Device: Tuple-inherited class with Address, RSSI,
        COD and Local name fields
    """
    device_attr = namedtuple('bt_device',
    ('address',
    'rssi',
    'cod',
    'name'))

    class BT_Device(device_attr):
        def __hash__(self):
            return int(self.address[:7], 16) ^ int(self.address[7:12], 16)
        def __eq__(self, other):
            return self.address == other.address
        def __lt__(self, other):
            return self.address < other.address
        def __gt__(self, other):
            return self.address > other.address

    netw.get_messages().clear()
    devices = []
    # responses = cmd_resp('AT+UBTI=1,'+str(timeout))
    cmd('AT+UBTI=1,'+str(timeout))
    while 1:
        atconf = _get_next_atconf()
        # If no AT confirmation yet, go back to the start of the loop
        if atconf is None:
            yield None #return control to main controller while waiting
            continue
        # Received an AT confirmation packet, get message inside and split by
        # lines
        msg = atconf.msg.decode('utf-8').strip().split('\r')
        # print(msg)
        for resp in msg:
            resp = resp.strip()
            if resp == 'ERROR':
                raise NetError('Error Returned from that command')
            elif resp == 'OK':
                return devices
            else:
                if resp[:6] == '+UBTI:':
                    # Strip identifier
                    resp = resp[6:]
                    # Split by commas, but avoid splitting the ssid (use the fact
                    # it's surrounded by quotes)
                    fields = resp.split('"')
                    fields = fields[0][:-1].split(',') + [fields[1]]
                    fields[0] = fields[0][:12]
                    new_dev = BT_Device(*fields)
                    devices.append(new_dev)
                    yield new_dev

def bt_search_blocking(timeout=5000):
    """Identical to the above function, except no generator expressions
    so this function blocks until BT search is complete

    Args:
        timeout (int, optional): Search Time. Defaults to 5000.

    Returns:
        List: list of bt_device objects, see above function for info
    """
    device_attr = namedtuple('bt_device',
    ('address',
    'rssi',
    'cod',
    'name'))

    class BT_Device(device_attr):
        def __hash__(self):
            return int(self.address[:7], 16) ^ int(self.address[7:12], 16)
        def __eq__(self, other):
            return self.address == other.address
        def __lt__(self, other):
            return self.address < other.address
        def __gt__(self, other):
            return self.address > other.address

    devices = []
    responses = cmd_resp('AT+UBTI=1,'+str(timeout))
    for resp in responses:
        if resp[:6] == '+UBTI:':
            # Strip identifier
            resp = resp[6:]
            # Split by commas, but avoid splitting the ssid (use the fact
            # it's surrounded by quotes)
            fields = resp.split('"')
            fields = fields[0][:-1].split(',') + [fields[1]]
            fields[0] = fields[0][:12]
            devices.append(BT_Device(*fields))
    return devices

def get_name_from_address(addr):
    netw.get_messages().clear()
    cmd('AT+UBTND='+str(addr))
    while 1:
        atconf = _get_next_atconf()
        # If no AT confirmation yet, go back to the start of the loop
        if atconf is None:
            continue
        # Received an AT confirmation packet, get message inside and split by
        # lines
        val = None
        resp = atconf.msg.decode('utf-8').strip().split('\r')
        for l in resp:
            l = l.strip()
            if l[:7] == '+UBTND:':
                # Strip identifier
                val = l[7:]
            elif l == 'ERROR':
                raise NetError('Error while fetching remote device name')
            elif l == 'OK':
                if val is None:
                    raise NetError('Empty response while checking BT Name')
                return val

def _default_bt_pairing_cb(msg):
    print("Pairing...", end=' ')
    # print(msg)
    msg = msg.split(',')
    try:
        name = get_name_from_address(msg[0])
    except NetError:
        name = msg[0]
    if msg[1] is '0':
        print("Success. Paired with {}".format(name))
        _bt_save()
    elif msg[1] is '1':
        print("Failed - Timeout")
    elif msg[1] is '2':
        print("Failed - Authentication error")
    elif msg[1] is '3':
        print("Failed - Security Risk (or weak link)")
    else:
        print("Error - Unknown Response")

def _default_bt_connection_event(msg):
    global _last_conn_channel
    msg = msg.split(',')
    _last_conn_channel = int(msg[0])
    if msg[1] is '1': #bluetooth connection
        try:
            name = get_name_from_address(msg[3][:12])
        except NetError:
            name = msg[0]
        print(name, "connected to this device (BT)")

def set_bt_authentication_cb(cb):
    sec_level = int(cmd_resp('AT+UBTSM?').split(':')[1].split(',')[0])
    if sec_level == BT_MODE_SEC_DISPLAY_PASSKEY:
        set_at_event_handler('+UUBTUPE', cb)
    elif sec_level == BT_MODE_SEC_ENTER_PASSKEY:
        set_at_event_handler('+UUBTUPE', cb)
    elif sec_level == BT_MODE_SEC_CONFIRM:
        set_at_event_handler('+UUBTUPC', cb)
    else:
        raise NetError("Security Mode {} does not require authentication".format(sec_level))

def enable_pairing(security=BT_MODE_SEC_DEFAULT, pairing=BT_MODE_PAIR_ON,
                    discoverability=BT_MODE_DISC_ON, connectability=BT_MODE_CONN_ON):
    #may require re-calling after a BT disconnect as accepted...
    #... connections set pairing mode to disabled
    cmdok('AT+UBTSM={}'.format(security)) #set Security Mode
    cmdok('AT+UBTDM={}'.format(pairing)) #set Discoverability on
    cmdok('AT+UBTCM={}'.format(connectability)) #set Connectability Mode
    cmdok('AT+UBTPM={}'.format(pairing)) #set Pairing Mode
    at_handlers['+UUBTB'] = _default_bt_pairing_cb
    at_handlers['+UUDPC'] = _default_bt_connection_event

def get_paired_devices():
    resp = ''
    val = []
    # Clear old messages, if any, before sending command
    netw.get_messages().clear()
    cmd('AT+UBTBD')
    while 1:
        atconf = _get_next_atconf()
        # If no AT confirmation yet, go back to the start of the loop
        if atconf is None:
            continue
        # Received an AT confirmation packet, get message inside and split by
        # lines
        resp = atconf.msg.decode('utf-8').strip().split('\r')
        for l in resp:
            l = l.strip()
            if l[:7] == '+UBTBD:':
                # Strip identifier
                l = l[7:]
                device = l.split(',')
                val.append(device)
            elif l == 'ERROR':
                raise NetError('Error checking paired device list')
            elif l == 'OK':
                for i, device in enumerate(val):
                    try: device.append(get_name_from_address(device[0]))
                    except NetError: device.append('')
                    val[i] = tuple(val[i])
                return sorted(list(set(val)))

def bt_pair(device):
    """device: bt_addr"""
    cmdok('AT+UBTB='+str(device))

def bt_unpair(device=None, all_devices=False):
    if (not device) and (not all_devices):
        raise NetError("Please specify a device to unpair, or use the 'all_devices' keyword arg")
    if all_devices:
        device = '0xFFFFFFFFFFFF'
    """device: bt_addr"""
    cmdok('AT+UBTUB='+str(device))

def bt_connect(device):
    url = 'spp://{}/'.format(device)
    return peer_connect(url)

def get_bt_strength(device):
    rssi = cmd_resp('AT+UBTRSS='+device).split(':')[1]
    lq   = cmd_resp('AT+UBTLQ='+device).split(':')[1]
    return rssi, lq


##################################
at_handlers = {}
data_handlers = {}

def _no_action(msg=None):
    print("No Handler for this Message")
    pass

def _store_data(data, length, channel):
    try:
        _data[channel].append(data)
    except KeyError:
        pass

# Set callback for unsolicited messages
def unsolic_cb():
    global _last_conn_channel
    # print("UnSolic CB")
    if _preempt_msg is not None and _preempt_msg():
        return
    msg = netw.get_messages().pop()
    id_type = msg.type | (msg.id << 4)
    if netw.UBX_EDM_TYPE_EVENT == msg.type:
        if netw.UBX_EDM_ID_CONNECT == msg.id:
            print('Connection event (channel {0})'.format(msg.msg[0]))
            print('  Type:     ', end='')
            msg_type = msg.msg[1]
            if 1 == msg_type:
                print('Bluetooth')
                print(msg)
                _data[msg.msg[0]] = []
                _last_conn_channel = msg.msg[0]
                print("Scheme: ", {1: 'SPP', 2: 'DUN', 3: 'UUID', 4: 'SPS', 5: 'Reserved'}[msg.msg[1]])
                print("Frame Size: ", (msg.msg[-2] <<8) + msg.msg[-1])
            elif 2 == msg_type:
                print('IPv4')
                print('  Protocol:', {0: 'TCP', 1: 'UDP'}[msg.msg[2]])
                addr = '{0}.{1}.{2}.{3}'.format(
                    msg.msg[3],
                    msg.msg[4],
                    msg.msg[5],
                    msg.msg[6])
                port = (msg.msg[7] << 8) + msg.msg[8]
                port = '' if 0 == port else ':' + str(port)
                print('  Remote:  ', addr + port)
                addr = '{0}.{1}.{2}.{3}'.format(
                    msg.msg[9],
                    msg.msg[10],
                    msg.msg[11],
                    msg.msg[12])
                port = (msg.msg[13] << 8) + msg.msg[14]
                port = '' if port == 0 else ':' + str(port)
                print('  Local:   ', addr + port)
            elif 3 == msg_type:
                print('IPv6')
        elif netw.UBX_EDM_ID_AT == msg.id:
            at_msg = msg.msg.decode('utf-8').strip().split(':')
            print(at_msg[0], "-", len(at_msg[1]))
            at_handlers.get(at_msg[0], _no_action)(at_msg[1])
        elif netw.UBX_EDM_ID_DATA == msg.id:
            mchannel = msg.msg[0]
            mdata = msg.msg[1:]
            # print('Data event (channel {0}, {1} bytes): {2}'.format(
            #     mchannel,
            #     msg.len - 1,
            #     mdata))
            data_handlers.get(mchannel, _store_data)(mdata, msg.len - 1, mchannel)

        elif netw.UBX_EDM_ID_DISCONNECT == msg.id:
            print('Disconnection event (channel {0})'.format(msg.msg[0]))
        else:
            print('Unidentified event:', msg)
    else:
        print('Unsolicited message:', msg)


if __name__ == "__main__":
    # print(wifi_scan())
    print("Loaded Network Module")
    # def respond_to_sec(msg):
    #     msg = msg.split(',')
    #     try:
    #         cmdok('AT+UBTUC={},1'.format(msg[0]))
    #         print("Success!")
    #     except NetError:
    #         print("Try 1 Failed")
    #         try:
    #             cmdok('AT+UBTUC={},1'.format(msg[0].strip('p')))
    #         except NetError:
    #             print("TOTAL FAILURE...")

    # _net0.callback(unsolic_cb)
    # set_bt_name('VBOX TOUCH '+ str(unit_info()['Serial Number']))
    # enable_pairing(BT_MODE_SEC_CONFIRM)
    # set_bt_authentication_cb(respond_to_sec)