Exemple #1
0
def connect_wifi(known_nets):
    wl = WLAN()
    wl.mode(WLAN.STA)
    original_ssid = wl.ssid()
    original_auth = wl.auth()
    print(" [*] Scanning for known wifi nets")
    available_nets = wl.scan()
    print(' [+] Found {} WiFi APs.'.format(len(available_nets)))
    for available_net in available_nets:
        print('     - {} ({})'.format(available_net.ssid, available_net.rssi))
    nets = frozenset([e.ssid for e in available_nets])

    known_nets_names = frozenset([key for key in known_nets])
    net_to_use = list(nets & known_nets_names)
    try:
        net_to_use = net_to_use[0]
        net_properties = known_nets[net_to_use]
        pwd = net_properties['pwd']
        sec = [e.sec for e in available_nets if e.ssid == net_to_use][0]
        if 'wlan_config' in net_properties:
            wl.ifconfig(config=net_properties['wlan_config'])
        wl.connect(net_to_use, (sec, pwd), timeout=10000)
        while not wl.isconnected():
            machine.idle()  # save power while waiting
        print(" [+] Connected to " + net_to_use + " with IP address: " +
              wl.ifconfig()[0])

    except Exception as e:
        print(
            " [-] Failed to connect to any known network, going into AP mode")
        wl.init(mode=WLAN.AP,
                ssid=original_ssid,
                auth=original_auth,
                channel=6,
                antenna=WLAN.INT_ANT)
import machine
from keychain import WLAN_SSID, WLAN_PASSKEY
from helpers import setup_rtc

known_nets = [(WLAN_SSID, WLAN_PASSKEY)]

if machine.reset_cause(
) != machine.SOFT_RESET:  # needed to avoid losing connection after a soft reboot
    from network import WLAN
    wl = WLAN()

    # save the default ssid and auth
    original_ssid = wl.ssid()
    original_auth = wl.auth()

    wl.mode(WLAN.STA)

    available_nets = wl.scan()
    nets = frozenset([e.ssid for e in available_nets])

    known_nets_names = frozenset([e[0] for e in known_nets])
    net_to_use = list(nets & known_nets_names)

    try:
        net_to_use = net_to_use[0]
        pwd = dict(known_nets)[net_to_use]
        sec = [e.sec for e in available_nets if e.ssid == net_to_use][0]
        wl.connect(net_to_use, (sec, pwd), timeout=10000)
        setup_rtc()
    except:
        wl.init(mode=WLAN.AP,
Exemple #3
0
        time.sleep(1)
        timeout -= 1
    if wifi.isconnected():
        print('Connected')
    else:
        print('Connection failed!')


wifi = WLAN()
print(wifi.mode() == WLAN.STA)
print(wifi.antenna() == WLAN.INT_ANT)

wifi = WLAN(mode=WLAN.AP)
print(wifi.mode() == WLAN.AP)
print(wifi.channel() == 1)
print(wifi.auth() == None)
print(wifi.antenna() == WLAN.INT_ANT)
wifi = WLAN(0, mode=WLAN.AP, ssid='test-wlan', auth=(WLAN.WPA, '123456abc'), channel=7)
print(wifi.mode() == WLAN.AP)
print(wifi.channel() == 7)
print(wifi.ssid() == 'test-wlan')
print(wifi.auth() == (WLAN.WPA, '123456abc'))
print(wifi.antenna() == WLAN.INT_ANT)

wifi = WLAN(mode=WLAN.STA)
print(wifi.mode() == WLAN.STA)
scan_r = wifi.scan()
print(len(scan_r) > 3)
for net in scan_r:
    if net.ssid == testconfig.wlan_ssid:
        # test that the scan results contains the desired params
Exemple #4
0
        time.sleep(1)
        timeout -= 1
    if wifi.isconnected():
        print('Connected')
    else:
        print('Connection failed!')


wifi = WLAN(0, WLAN.STA)
print(wifi.mode() == WLAN.STA)
print(wifi.antenna() == WLAN.INT_ANT)

wifi = WLAN(mode=WLAN.AP)
print(wifi.mode() == WLAN.AP)
print(wifi.channel() == 1)
print(wifi.auth() == None)
print(wifi.antenna() == WLAN.INT_ANT)
wifi = WLAN(0,
            mode=WLAN.AP,
            ssid='test-wlan',
            auth=(WLAN.WPA, '123456abc'),
            channel=7)
print(wifi.mode() == WLAN.AP)
print(wifi.channel() == 7)
print(wifi.ssid() == 'test-wlan')
print(wifi.auth() == (WLAN.WPA, '123456abc'))
print(wifi.antenna() == WLAN.INT_ANT)

wifi = WLAN(mode=WLAN.STA)
print(wifi.mode() == WLAN.STA)
time.sleep(5)  # this ensures a full network scan
Exemple #5
0
class WifiManager:
    def __init__(self, known_nets):
        self._known_nets = known_nets
        # create network in STAtion mode
        # pycom: device always starts up in AP-mode
        #self._wl = WLAN()
        #self._wl.mode(WLAN.STA)

    '''def print_debug(self, message):
        """print_debug() - for debugging """
        if USE_DEBUG:
            print(msg)
    '''

    # 2019-1203 new, due to Exception error in legacy WifiManager
    # pre-condition: self._known_nets is not None
    # post-condition: self._wl is created
    # returns: IP
    # URL: https://docs.pycom.io/tutorials/all/wlan/
    def connect(self):
        """connect() - connects device according to network parameters in JSON-file."""
        if machine.reset_cause() != machine.SOFT_RESET:
            # from network import WLAN
            self._wl = WLAN()
            self._wl.mode(WLAN.STA)
            original_ssid = self._wl.ssid()
            original_auth = self._wl.auth()

            print_debug("Wifimanager - scanning for known wifi nets...")
            available_nets = self._wl.scan()
            nets = frozenset([e.ssid for e in available_nets])

            known_nets_names = frozenset([key for key in self._known_nets])
            net_to_use = list(nets & known_nets_names)
            print_debug("Wifimanager - SSID to use...{}".format(net_to_use))
            try:
                net_to_use = net_to_use[0]
                print_debug("Wifimanager - net to use...{}".format(net_to_use))
                net_properties = self._known_nets[net_to_use]
                pwd = net_properties['pwd']
                sec = [e.sec for e in available_nets
                       if e.ssid == net_to_use][0]
                print_debug(
                    "Wifimanager - net_properties...{}".format(net_properties))
                if 'wlan_config' in net_properties:
                    print_debug("Wifimanager - wlan_config...{}".format(
                        net_properties['wlan_config']))
                    self._wl.ifconfig(config=net_properties['wlan_config'])
                self._wl.connect(net_to_use, (sec, pwd), timeout=10000)
                ip = self.wait_for_networking(1)
                self._ssid = net_to_use
                print_debug("Connected to " + net_to_use +
                            " with IP address:" + ip)

            except Exception as e:
                print(
                    "Failed to connect to any known network, going into AP mode"
                )
                self._wl.init(mode=WLAN.AP,
                              ssid=original_ssid,
                              auth=original_auth,
                              channel=6,
                              antenna=WLAN.INT_ANT)
                self._ssid = None

        else:
            print_debug("Already connected to " + net_to_use +
                        " with IP address:" + self._wl.ifconfig()[0])

        return self._wl.ifconfig()[0]

    def wait_for_networking(self, dt=1):
        """ wait unitil network is connected and returns IP"""
        station = self._wl  # network.WLAN(mode=network.WLAN.STA)
        while not station.isconnected():
            time.sleep(dt)
            machine.idle()
        ip = station.ifconfig()[0]
        return ip

    # wrapper for disconnecting network
    def disconnect(self):
        """disconnect() - de-activate network interface, but leaves Wifi radio on"""
        self._wl.disconnect(
        )  # pycom - disconnect from Wifi, but leave Wif radio on.
        print_debug('WifiManager::Wifi disconnected')

    # wrapper for disabling Wifi radio
    def deinit(self):
        """deinit() - disable Wifi radio"""
        self._wl.deint()  # pycom
        print_debug('WifiManager::Wifi radio off')

    # wrapper for network scan
    def scan(self):
        """scan() - Performs a network scan and returns a list
        of named tuples with (ssid, bssid, sec, channel, rssi)
        """
        return self._wl.scan()

    def change_access(self, user=None, passwrd=None):
        """change_access - change password for telnet and ftp access"""
        if (user is None) or (passwrd is None):
            print('WifiManager:: username and password must be specified')
            return

        server = Server()  # from network
        # disable the server
        server.deinit()
        # enable the server again with new credentials
        # for ftp and telnet, not USB
        server.init(login=(user, passwrd), timeout=600)
        print_debug('WifiManager::password {} is changed...'.format(user))

    # wrappers for wlan settings.
    @property
    def ssid(self):
        """ ssid() - returns SSID of connected Wifi network"""
        return self._ssid

    @property
    def isconnected(self):
        """isconnected() - returns if connected to Wifi (True)
        or not (False)"""
        return self._wl.isconnected()

    @property
    def ip(self):
        """ip() - returns IP of device on connected Wifi network"""
        return self._wl.ifconfig()[0]

    @property
    def mac(self):
        """returns MAC-address of device"""
        mac = hexlify(self._wl.mac(), ':').decode()  # pycom
        # return (mac) # lower case
        return mac.upper()

    # ================================================
    # legacy methods
    # ================================================
    import json

    def __readjson(self, jsonfile):
        """readjson(file) - returns the contents of file in JSON-format"""
        with open(jsonfile, 'r') as infile:
            config = json.load(infile)
        if USE_DEBUG:
            print('WifiManager::JSON settings: {}'.format(config))
        return config
Exemple #6
0
class WiFiManager:
    def __init__(self, manager, settings):
        self.manager = manager
        self.settings = settings

        # WIFI settings.
        self.stations = self.settings.get('networking.wifi.stations')
        self.station = None

    def start(self):
        """
        https://docs.pycom.io/tutorials/all/wlan.html
        https://github.com/pycom/pydocs/blob/master/firmwareapi/pycom/network/wlan.md
        """

        # Todo: Propagate more parameters here, e.g. for using an external antenna.
        self.station = WLAN()

        #if machine.reset_cause() == machine.SOFT_RESET:
        #   print("WiFi STA: Network connection after SOFT_RESET.")
        #    self.print_short_status()
        #    # Inform about networking status.
        #    self.print_address_status()
        #    return True

        # Save the default ssid and auth for restoring AP mode later
        original_ssid = self.station.ssid()
        original_auth = self.station.auth()

        # Inform about networking status.
        self.print_address_status()

        # Setup network interface.
        self.station.init()

        # Check WiFi connectivity.
        if self.station.isconnected():

            log.info(
                "WiFi STA: Network connection already established, will skip scanning and resume connectivity."
            )
            self.print_short_status()

            # Give system some breath.
            time.sleep(0.25)

            # Inform about networking status.
            self.print_address_status()

            return True

        # Prepare information about known WiFi networks.
        networks_known = frozenset(
            [station['ssid'] for station in self.stations])

        log.info("WiFi STA: Starting interface")
        self.station.mode(WLAN.STA)

        # Attempt to connect to known/configured networks.
        log.info("WiFi STA: Directly connecting to configured networks: %s",
                 list(networks_known))
        try:
            self.connect_stations(networks_known)

        except:
            log.warning('WiFi: Switching to AP mode not implemented yet')

        # Todo: Reenable WiFi AP mode in the context of an "initial configuration" mode.
        """
        log.info('WiFi: Switching to AP mode')
        # WLAN.AP, original_ssid, original_auth, WLAN.INT_ANT
        # TOOD: Make default channel configurable
        self.station.init(mode=WLAN.AP, ssid=original_ssid, auth=original_auth, channel=6, antenna=WLAN.INT_ANT)
        """

    def power_off(self):
        """
        Power off all radio peripherals.

        - https://forum.pycom.io/topic/563/disabling-wifi-on-lopy
        - https://github.com/Hiverize/FiPy/commit/b6b15677
        """

        # WiFi
        if self.station:
            try:
                log.info('Turning off WiFi')
                self.station.deinit()
            except:
                log.exception('Turning off WiFi failed')

    def connect_stations(self, network_names):

        # Prepare information about known WiFi networks.
        network_map = {station['ssid']: station for station in self.stations}

        for network_name in network_names:
            try:
                # All the configuration details for this network.
                # {
                #    'ssid': 'FooBar',
                #    'password': '******',
                #    'ifconfig': ('192.168.42.42', '255.255.255.0', '192.168.42.1', '192.168.42.1'),
                # }
                network_selected = network_map[network_name]
                if self.connect_station(network_selected):
                    break

            except Exception:
                log.exception(
                    'WiFi STA: Connecting to "{}" failed'.format(network_name))

        if not self.station.isconnected():

            self.forget_network(network_name)

            message = 'WiFi STA: Connecting to any network candidate failed'
            description = 'Please check your WiFi configuration for one of the ' \
                          'station candidates {}.'.format(len(network_names))
            log.error('{}. {}'.format(message, description))
            log.warning(
                'Todo: We might want to switch to AP mode here or alternatively '
                'buffer telemetry data to flash to be scheduled for transmission later.'
            )
            raise WiFiException(message)

    def connect_station(self, network):

        network_name = network['ssid']

        log.info('WiFi STA: Prepare connecting to network "{}"'.format(
            network_name))

        auth_mode = self.get_auth_mode(network_name)

        log.info(
            'WiFi STA: Attempt connecting to network "{}" with auth mode "{}"'.
            format(network_name, auth_mode))

        password = network['password']

        # TODO: Optionally, configure hostname.
        # https://docs.micropython.org/en/latest/library/network.WLAN.html
        # https://github.com/pycom/pycom-micropython-sigfox/pull/165
        # https://forum.pycom.io/topic/3326/new-firmware-release-v1-18-0
        if 'dhcp_hostname' in network:
            if hasattr(self.station, 'config'):
                log.ingo('WiFi STA: Using dhcp_hostname "{}"'.format(
                    network['dhcp_hostname']))
                self.station.config(dhcp_hostname=network['dhcp_hostname'])
            else:
                log.error('Could not set hostname on older MicroPython')

        # Optionally, configure static IP address.
        if 'ifconfig' in network:
            log.info(
                'WiFi STA: Using static network configuration "{}"'.format(
                    network_name))
            self.station.ifconfig(config=network['ifconfig'])

        # Obtain timeout value.
        network_timeout = network.get('timeout', 15.0)

        # Set interval how often to poll for WiFi connectivity.
        network_poll_interval = 800

        # Connect to WiFi station.
        log.info(
            'WiFi STA: Starting connection to "{}" with timeout of {} seconds'.
            format(network_name, network_timeout))
        self.station.connect(network_name, (auth_mode, password),
                             timeout=int(network_timeout * 1000))

        # Wait for station network to arrive.
        # ``isconnected()`` returns True when connected to a WiFi access point *and* having a valid IP address.
        retries = int(network_timeout * network_poll_interval)
        while not self.station.isconnected() and retries > 0:

            log.info(
                'WiFi STA: Waiting for network "{}".'.format(network_name))
            retries -= 1

            # Save power while waiting.
            machine.idle()

            # Feed watchdog.
            self.manager.device.feed_watchdog()

            # Don't busy-wait.
            time.sleep_ms(network_poll_interval)

        if not self.station.isconnected():
            raise WiFiException(
                'WiFi STA: Unable to connect to "{}"'.format(network_name))

        # Inform about networking status.
        self.print_short_status()
        self.print_address_status()

        return True

    def scan_stations(self):

        self.manager.device.feed_watchdog()

        # Inquire visible networks.
        log.info("WiFi STA: Scanning for networks")
        stations_available = self.station.scan()
        networks_found = frozenset([e.ssid for e in stations_available])

        # Print names/SSIDs of networks found.
        log.info("WiFi STA: Networks available: %s", list(networks_found))

        return stations_available

        # Compute set of effective networks by intersecting known with found ones.
        #network_candidates = list(networks_found & networks_known)
        #log.info("WiFi STA: Network candidates: %s", network_candidates)

    def get_ssid(self):
        return self.station.ssid()

    def get_ip_address(self):
        try:
            return self.station.ifconfig()[0]
        except:
            pass

    def get_auth_mode(self, network_name):

        # NVRAM key for storing auth mode per network. Maximum of 15 characters.
        auth_mode_nvs_key = self.auth_mode_nvs_key(network_name)

        # Get WiFi STA auth mode from NVRAM.
        try:
            import pycom
            auth_mode = pycom.nvs_get(auth_mode_nvs_key)
            log.info('WiFi STA: Auth mode from NVRAM with key=%s, value=%s',
                     auth_mode_nvs_key, auth_mode)
        except:
            auth_mode = None

        # Fall back to find out WiFi STA auth mode by network scan.
        if auth_mode is None:
            log.info(
                'WiFi STA: Unknown auth mode for network "%s", invoking WiFi scan',
                network_name)
            wifi_neighbourhood = self.scan_stations()

            #log.info('WiFi STA: Neighbourhood is %s', wifi_neighbourhood)
            for e in wifi_neighbourhood:
                if e.ssid == network_name:
                    auth_mode = e.sec
                    break

            if not auth_mode:
                message = 'WiFi STA: Unable to inquire auth mode for network "{}"'.format(
                    network_name)
                log.warning(message)
                raise WiFiException(message)

            log.info(
                'WiFi STA: Storing auth mode into NVRAM with key=%s, value=%s',
                auth_mode_nvs_key, auth_mode)
            try:
                import pycom
                pycom.nvs_set(auth_mode_nvs_key, auth_mode)
            except:
                log.exception('WiFi STA: Storing auth mode into NVRAM failed')

        return auth_mode

    def auth_mode_nvs_key(self, ssid):
        """
        Hack to get a short representation of a WiFi SSID in order to
        squeeze it into a NVRAM key with a maximum length of 15 characters.

        Fixme: Review this.
        """
        import hashlib
        import ubinascii
        digest = ubinascii.hexlify(hashlib.sha512(ssid).digest()).decode()
        identifier = 'wa.{}'.format(digest[15:27])
        return identifier

    def forget_network(self, network_name):
        log.info('WiFi STA: Forgetting NVRAM data for network "{}"'.format(
            network_name))
        auth_mode_nvs_key = self.auth_mode_nvs_key(network_name)
        try:
            import pycom
            pycom.nvs_erase(auth_mode_nvs_key)
        except:
            pass

    def print_short_status(self):
        log.info('WiFi STA: Connected to "{}" with IP address "{}"'.format(
            self.get_ssid(), self.get_ip_address()))

    def print_address_status(self):
        mac_address = self.humanize_mac_addresses(self.station.mac())
        ifconfig = self.station.ifconfig()
        log.info('WiFi STA: Networking address (MAC): %s', mac_address)
        log.info('WiFi STA: Networking address (IP):  %s', ifconfig)

    def humanize_mac_addresses(self, mac):
        info = {}
        if hasattr(mac, 'sta_mac'):
            info['sta_mac'] = format_mac_address(
                binascii.hexlify(mac.sta_mac).decode())
        if hasattr(mac, 'ap_mac'):
            info['ap_mac'] = format_mac_address(
                binascii.hexlify(mac.ap_mac).decode())
        return info

    def print_metrics(self):
        metrics = SystemWiFiMetrics(self.station).read()
        log.info('WiFi STA: Metrics: %s', metrics)
Exemple #7
0
        signal.signal(signal.SIGINT, sigint_handler)
        signal.signal(signal.SIGTERM, sigint_handler)

    # Initialize led matrix framebuffer on top of HAL
    display = LedMatrix(driver, config['LedMatrix'])
    driver.clear_display()

    if pycom_board:
        # We're running under MCU here
        from bootscene import BootScene
        scene = BootScene(display, config['Boot'])
        wlan = WLAN(mode=WLAN.STA)
        if not wlan.isconnected():
            print('WLAN: Scanning for networks')
            scene.render(0, 0, 0)
            default_ssid, default_auth = wlan.ssid(), wlan.auth()
            candidates = wlan.scan()
            for conf in config['networks']:
                nets = [
                    candidate for candidate in candidates
                    if candidate.ssid == conf['ssid']
                ]
                if not nets:
                    continue
                print('WLAN: Connecting to known network: {}'.format(
                    nets[0].ssid))
                wlan.connect(nets[0].ssid,
                             auth=(nets[0].sec, conf['password']))
                for i in range(1, 40):
                    scene.render(i, 0, 0)
                    time.sleep(0.2)
Exemple #8
0
known_nets = {
    'wifilocal': {
        'pwd': 'PWD',
        'wlan_config': ('192.168.x.x', '255.255.x.x', '192.168.x.x', '1.1.1.1')
    },
    'hotspot': {
        'pwd': 'PWD'
    }
}

if machine.reset_cause() != machine.SOFT_RESET:
    from network import WLAN
    wlan = WLAN()
    wlan.mode(WLAN.STA)
    original_ssid = wlan.ssid()
    original_auth = wlan.auth()

    print("Scanning for known wifi nets")
    available_nets = wlan.scan()
    nets = frozenset([e.ssid for e in available_nets])

    known_nets_names = frozenset([key for key in known_nets])
    net_to_use = list(nets & known_nets_names)
    try:
        net_to_use = net_to_use[0]
        net_properties = known_nets[net_to_use]
        pwd = net_properties['pwd']
        sec = [e.sec for e in available_nets if e.ssid == net_to_use][0]
        if 'wlan_config' in net_properties:
            wlan.ifconfig(config=net_properties['wlan_config'])
        wlan.connect(net_to_use, (sec, pwd), timeout=10000)