wifi-Configurator for Nodejs
A wifi configuration module for linux with GUI that uses default/open networks so that it does not have to create an access point. Other configuration options are provided such as using SD card, USB devices, (web bluetooth - not yet implemented).
The most common way for configuring WiFi on a linux systems without any way of directly inputing the WiFi credentials into the device, such on a raspberry pi without I/O peripherals, is to have the device create an Access Point to which the user can connect and access a web page on which the credentials for a WiFi network can be entered and saved, such as happens with Farmbot. The farmbot wifi-configurator is now integrated into FarmbotOs, but it used to be a separate piece of software. But we are persuaded that there are more efficient ways of doing this, since:
- It is time consuming as the device has to restart after the configuration to disable the Access Point and try connecting to the WiFi network. If the credentials are wrong, the device will restart again to create the Access Point, and restart again, ad infinitum.
- In the said system, it is not possible for the device to work without connecting to a network. This need not always be the case as some operations can be done offline.
- The user may not have a WiFi enabled device with which to connect to the linux system's device's Access Point to configure the network. Other options will then come in handy.
- There are easier options which may be more preferable to a user.
- Even without an open network or the default network, the configuration server is still accessible through ethernet.
wifi-Configurator is a NodeJS module to configure WiFi on a linux system including Raspberry Pi providing several options, namely:
- Connecting to a default network. The user can create a network on his device called
wifi-configurator
with the password wifi-config
. The device will try connecting to this network so that the user may be able to access the network configuration page. - If the device is unable to connect to the the default network, it will try connecting to any open networks. It will loop through all open networks as long as there is no activity in them. This gives the user an option of either creating the default network on their device, or creating an open access point on their device.
- SD Card and USB devices. WiFi credentials can be saved on SD card/USB drives in a file called
wifiConfig.yaml
or wifiConfig.yml
in the root directory of any of the drive partitions and inserted into the linux device. The credentials will be read as soon as the drive is connected and mounted. - Bluetooth Low Energy and Web Bluetooth - (not yet implemented).
wifi-Configurator has been designed as part of the csynage media kit
The reasons for this can be found here
Usage
You need do nothing more than:
npm install wifi-configurator
const wifi = require('wifi-configurator')();
WiFi configurator will run as soon as you run your application. See example in examples. You can configure you wifi networks using any of these options, as already mentioned:
- create a file called
wifiConfig.yaml
or wifiConfig.yml
in a USB drive/SD card with the configuration for your WiFi network and insert it into your device. Optionally on a raspberry pi you can save this configuration file on the boot partition of your SD card. The configuration you have created will be read and saved in your device, and it will be used to connect to your network. This is the easiest way as it will require no further programming. Here is an example of the yml
file:
SSID1: "CARTO"
SSID2: "CARTO"
SSID3:
- CARTO1
- CARTO2
1:
SSID4: CARTO1
2:
SSID4: CARTO2
The network credentials should be saved as SSID, PARAPHRASE
pairs (see sample configuration for SSID1
and SSID2
). But if there are two networks with the same SSID (and different passwords), then their passwords can be saved as an array which is the value for the SSID (see SSID3
in sample configuration which has two networks with same SSID). The old configuration method is given for SSID4
. But no comment shall be given about it as it has been deprecated due to its poor readability. It's however the configuration that is still used for saving the credentials internally.
- create a wireless network on any device with the default wireless credentials for wifi-configurator
SSID: wifi-configurator
and password:wifi-config
. The device will connect to this network. Optionally you can create an open network and the device will connect to it. Or you can connect the device to a network using an ethernet cable. Then you will be able to connect to the configuration page of the device. The address at which this page is served can be found by performing some device discovery. An example of how this can be done is given below (see examples):
const mdns = require('multicast-dns')()
const etc = require('node-etc');
const appName = etc.packageJson().name;
mdns.on('response', function(response) {
console.log('got a response packet:', response.answers)
console.log(`server is running on ${response.answers[0].target}`)
})
mdns.query({
questions:[{
name: `${appName}-wifi-config.local`,
type: 'A'
}]
})
The result obtained from the mdns query will be something like:
{
name: 'wifi-configurator-nameless',
type: 'SRV',
ttl: 0,
class: 'IN',
flush: false,
data: {
priority: 10,
weight: 0,
port: 3074,
target: 'http://192.168.100.32:3074'
}
}
data.url
will give the url where you can access the configuration server. If the device is connected to several networks, then it will be a comma separated list of urls. You should be able to identify which url is accessible from your network. The name
will be wifi-configurator-${deviceName}
. deviceName
, as long as it has not be configured, will return nameless
. The configuration page has a default username and password which should be changed on first log in.
The default username is NOBODY
and password is PASSWORD
. No mechanism is provided for retrieving lost passwords, except for addition of new users using the configuration file as described below.
Changing Username/Password and DeviceName
1. Using deviceConfig.yaml
In the same manner that wifiConfig.yaml
is created, you can also optionally create another configuration file called deviceConfig.yaml
. From this the wifi-configurator will be able to read the device name (after it has been correctly set) so as to be able to distinguish between several devices on a network. This makes it easier to know which exact device you are working on than when devices are merely identified using their hostnames so that where there are several devices on a single network they are simply known by their hostname and the number which is usually added after the hostname, such as raspberrypi-1.local
, raspberrypi-2.local
. After the first login you can be able to change the name of your device to have your devices identified with names that you assign to them, such as sitting room TV
, kitchen oven
, etc.
A sample configuration for this yaml file is:
DEVICENAME: nameless
USERS
provides credentials for those who will be able to log in to your device and change the settings. It can also be used by other modules of your application that need authentication. Such basic authentication is provided so as to enable offline operation where a more sophisticated authentication server such as keycloak cannot be accessed.
NOTE:
- The password is provided in plain text, but stored encrypted.
- After supplying the device name in the configuration file, it is best to delete it as it will overwrite any changes made from the server configuration page.
2. Using the configuration page as described above.
Examples of available functions
You can listen to events emitted:
wifi.on("unmounted", (mp) => console.log(`unmounted ${mp}`))
wifi.on("mounted", (mp) => { console.log(`mounted ${mp}`) });
wifi.on("wifi", (msg) => {
switch (msg) {
case "connected":
console.log('connected to wifi');
break;
case "disconnected":
console.log('disconnected from wifi');
break;
}
})
wifi.on("internet", (msg) => {
switch (msg) {
case "connected":
console.log('connected to internet');
break;
case "disconnected":
console.log('disconnected from internet');
break;
}
})
Examples of other functions
console.log(test.listSavedNetworks())
console.log(test.removeSavedNetwork({ SSID: 'GS', 'password': 'GS' }))
console.log(test.listSavedNetworks())
console.log(test.saveNetworkifNotExists({ SSID: 'GS', 'password': 'GS' }))
console.log(test.listSavedNetworks())
console.log(test.editNetwork({ SSID: 'GS', 'password': 'GS' }, { SSID: 'GS', 'password': 'GS1' }))
console.log(test.listSavedNetworks())
test.connectToSpecificNetwork({ SSID: 'GS', password: 'GS1' })
test.pauseInternetChecks()
You can also find user management function examples in test.js
For all available functions, please refer to the API
How it works
If you add and run wifi-configurator
as a module to your application, it will be able to read wifi configuration data from connected SD cards, USB drives and all mounted drives. The wifi configuration is a yaml/yml
file called wifiConfig.yaml
or wifiConfig.yml
which is saved in the root directory of any of the drives. In raspberry pi, you can save this file in the boot
partion.
A sample configuration for the yaml
file is:
SSID: PARAPHRASE
SSID: PARAPHRASE1
In JSON this would be:
{
"1": {
"SSID1": "PARAPHRASE1"
},
"2": {
"SSID2": "PARAPHRASE2"
}
}
The number is given so that credentials can be saved for different networks having the same SSID.
The credentials from all drives are saved using node-etc into /etc/${appName}/wifiConfig.yaml
or ~/etc/${appName}/wifiConfig.yaml
depending on how the system is configigured. appName
is the name of your application as given in your package.json
file. It can easily be obtained using node-etc
.
const etc = require('node-etc');
let appName = etc.packageJson().name;
The module will scan available networks and connect to the first valid network whose credentials are stored or to the first open network. The module will its connection to the internet and disconnect from the network if it has no connection to the internet, and try connecting to the next network. Thus the network with the best connectivity to the internet is always the one that is connected to.
API
wifiConfigurator
Kind: global class
new wifiConfigurator()
constructor
Read configuration from mounted devices and save to config file
Check if connected to wifi. If not, scan available networks and try to connect using available credentials
wifiConfigurator.listSavedNetworks() ⇒ Array.<String>
list saved networks
Kind: instance method of wifiConfigurator
Returns: Array.<String>
- - SSID and password
wifiConfigurator.removeSavedNetwork(options)
removeSavedNetwork
Kind: instance method of wifiConfigurator
Param | Type | Description |
---|
options | Object | |
options.SSID | string | SSID |
options.password | string | Password |
wifiConfigurator.editNetwork(optionsOld, optionsNew)
edit network credentials
Kind: instance method of wifiConfigurator
Param | Type | Description |
---|
optionsOld | * | |
optionsOld.SSID | string | SSID |
optionsOld.password | string | Password |
optionsNew | * | |
optionsNew.SSID | string | SSID |
optionsNew.password | string | Password |
wifiConfigurator.saveDefaults()
save default network credentials
Kind: instance method of wifiConfigurator
wifiConfigurator.networkSaved(options)
Check if credentials are already saved
Kind: instance method of wifiConfigurator
Param | Type | Description |
---|
options | Object | |
options.SSID | string | SSID |
options.password | string | Password |
wifiConfigurator.saveNetworkifNotExists(options)
Save network credentials if they do not exist already.
Kind: instance method of wifiConfigurator
Param | Type | Description |
---|
options | Object | |
options.SSID | string | SSID |
options.password | string | Password |
wifiConfigurator.changeDeviceName(deviceName)
Change device name
Kind: instance method of wifiConfigurator
Param | Type |
---|
deviceName | string |
wifiConfigurator.getConnectedNetwork()
Get connected network
Kind: instance method of wifiConfigurator
wifiConfigurator.removeSavedNetworkv1(ssid, password)
remove saved network
Kind: instance method of wifiConfigurator
Param | Type |
---|
ssid | string |
password | string |
wifiConfigurator.httpserver(options)
Servers a settings page that is accessible from another device to read/edit the settings on this device
Kind: instance method of wifiConfigurator
wifiConfigurator.getLocalExternalIP(iface)
get local server external IP address on given interface
Kind: instance method of wifiConfigurator
wifiConfigurator.getAllLocalExternalIP(iface)
get local server external IP address on all interfaces
Kind: instance method of wifiConfigurator
wifiConfigurator.readDeviceConfig() ⇒ object
Read saved device configuration data, or return the default values
Kind: instance method of wifiConfigurator
Returns: object
- - {DEVICENAME, USERS:{USERNAME: PASSWORD}}
wifiConfigurator.editDeviceName(deviceName)
Change device name
Kind: instance method of wifiConfigurator
Param | Type | Default |
---|
deviceName | string | "nameless" |
wifiConfigurator.encrypt(password)
encrypt password
Kind: instance method of wifiConfigurator
wifiConfigurator.addUser(username, password)
create a new user
Kind: instance method of wifiConfigurator
Param | Type |
---|
username | string |
password | string |
wifiConfigurator.listUsers() ⇒ object
List Users
Kind: instance method of wifiConfigurator
wifiConfigurator.removeUser(username, [force])
Remove a user
Kind: instance method of wifiConfigurator
Param | Type | Default | Description |
---|
username | string | | |
[force] | boolean | false | remove even if only single user is left |
wifiConfigurator.authenticateUser(username, password)
Authenticate configuration user
Kind: instance method of wifiConfigurator
Param | Type |
---|
username | string |
password | string |
wifiConfigurator.createAdvertisement()
mdns service discovery
Kind: instance method of wifiConfigurator
wifiConfigurator.wifiStatusProcess()
try connecting to wifi if is disconnected
Kind: instance method of wifiConfigurator
wifiConfigurator.internetStatus()
disconnect from network and try another one if there is no internet
Kind: instance method of wifiConfigurator
wifiConfigurator.checkInternetConnected()
Check if device has internet access
emits internet event with status:disconnected/connected and another internet event with checked to show that its done
Kind: instance method of wifiConfigurator
wifiConfigurator.pauseInternetChecks()
Pause internet checks so that if does not disconnect from current network if there is no internet
Kind: instance method of wifiConfigurator
wifiConfigurator.resumeInternetChecks()
Resume internet checks so that if may disconnect from current network if there is no internet
Kind: instance method of wifiConfigurator
wifiConfigurator.getUsb() ⇒ Array.<string>
List mount points of all mounted drives
Kind: instance method of wifiConfigurator
Returns: Array.<string>
- - array of locations where all mounted disks are mounted
wifiConfigurator.watchDrives() ⇒ null
Watch for mounting and unmounting of drives
Kind: instance method of wifiConfigurator
Returns: null
- - emits mounted/unmounted event with mounted/unmounted mount point
wifiConfigurator.readConfigurations()
Read configurations from drives and save then to ${savedConfigFileName}
Kind: instance method of wifiConfigurator
wifiConfigurator.connectToNetworks()
Manage list of networks and try connecting one if not connected
Kind: instance method of wifiConfigurator
wifiConfigurator.listAvailbleNetworks()
List avaialable networks
Kind: instance method of wifiConfigurator
wifiConfigurator.scan() ⇒ Promise
scan available networks
Kind: instance method of wifiConfigurator
Returns: Promise
- which resolves with list of available networks
wifiConfigurator.connectToSpecificNetwork(options)
Connect to specific network
Kind: instance method of wifiConfigurator
Param | Type | Description |
---|
options | Object | |
options.SSID | string | SSID |
options.password | string | Password |
wifiConfigurator.disconnect()
disconnect
Kind: instance method of wifiConfigurator
wifiConfigurator.connect([Object])
choose network to connect to
Kind: instance method of wifiConfigurator
Param | Description |
---|
[Object] | scannedNetworks |
wifiConfigurator.listConnections() ⇒ Promise
Check if connected to WiFi network
Kind: instance method of wifiConfigurator
Returns: Promise
- which resolves with number of connections. 0 if no connection
Developed by CSECO
CSECO is a mechatronics firm specializing in engineering technology to be cheap enough to be affordable to low income earners.
http://www.cseco.co.ke
Todo