WastedFreeTime
WastedFreeTime

Reputation: 325

Using Perl to format nmcli output and get WiFi names

I want to get a list of available Wifi's via nmcli and return the output formatted in JSON.
Currently i have written this:

use JSON;

sub get_available_wifi_list {

    ### rescan for wifi 
    system('nmcli device wifi rescan');

    # get the list of wifi's
    my $nmcli_output= `nmcli device wifi`;

    # every line into array
    my @wifi_list = split /\n/, $nmcli_output;

    ### remove first line
    shift(@wifi_list);

    # pack into json 
    my $data_ref = \@wifi_list;
    my $json = to_json($data_ref);  

    return $json;
}

The nmcli device wifi raw output is:

IN-USE  SSID                MODE   CHAN  RATE        SIGNAL  BARS  SECURITY 
*       WLAN-123            Infra  11    130 Mbit/s  60      ▂▄▆_  WPA2     
        FRITZ!Box 7430 JW   Infra  1     195 Mbit/s  57      ▂▄▆_  WPA2     
        Telekom_FON         Infra  11    130 Mbit/s  47      ▂▄__  --       
        WLAN-123ABC         Infra  6     270 Mbit/s  32      ▂▄__  WPA2     
        WiFi-Repeater       Infra  1     135 Mbit/s  24      ▂___  WPA2  

The SSID may contain whitespaces could be a problem too. I need an array with a hash for every WiFi with all stats as key value pairs. Something like:

@wifi_list = (
    { 
         SSID = 'WLAN-123',
         MODE = 'Infra',
         SIGNAL = 60,
         SECURITY = 'WPA2'
     },
     {
         SSID = 'FRITZ!BOX 7430 JW',
         MODE = 'Infra',
         SIGNAL = 60,
         SECURITY = 'WPA2'
      }, ...
);

Maybe other solutions for getting the WiFi names and stats would work better but i want to connect to one of the given Wifi's later so i use nmcli.
Thank you for help!

Upvotes: 2

Views: 838

Answers (2)

Polar Bear
Polar Bear

Reputation: 6798

Please see if the following code piece does what you are looking for

Note: although no JSON involved at all -- data stored in a hash

use strict;
use warnings;
use feature 'say';

use utf8;
use Data::Dumper;

binmode STDOUT, ':utf8';

my @wifi;
my @fields = split ' ', <DATA>;

while( <DATA> ) {
    my %hash;
    my @array = unpack('A8A20A7A6A12A8A6A8',$_);
    push @wifi, \%hash;
}

say Dumper(\@wifi);

__DATA__
IN-USE  SSID                MODE   CHAN  RATE        SIGNAL  BARS  SECURITY 
*       WLAN-123            Infra  11    130 Mbit/s  60      ▂▄▆_  WPA2     
        FRITZ!Box 7430 JW   Infra  1     195 Mbit/s  57      ▂▄▆_  WPA2     
        Telekom_FON         Infra  11    130 Mbit/s  47      ▂▄__  --       
        WLAN-123ABC         Infra  6     270 Mbit/s  32      ▂▄__  WPA2     
        WiFi-Repeater       Infra  1     135 Mbit/s  24      ▂___  WPA2  

Output

$VAR1 = [
          {
            'RATE' => '130 Mbit/s',
            'SSID' => 'WLAN-123',
            'BARS' => "\x{2582}\x{2584}\x{2586}_",
            'CHAN' => '11',
            'MODE' => 'Infra',
            'SIGNAL' => '60',
            'SECURITY' => 'WPA2',
            'IN-USE' => '*'
          },
          {
            'CHAN' => '1',
            'MODE' => 'Infra',
            'BARS' => "\x{2582}\x{2584}\x{2586}_",
            'RATE' => '195 Mbit/s',
            'SSID' => 'FRITZ!Box 7430 JW',
            'IN-USE' => '',
            'SECURITY' => 'WPA2',
            'SIGNAL' => '57'
          },
          {
            'RATE' => '130 Mbit/s',
            'SSID' => 'Telekom_FON',
            'BARS' => "\x{2582}\x{2584}__",
            'MODE' => 'Infra',
            'CHAN' => '11',
            'IN-USE' => '',
            'SIGNAL' => '47',
            'SECURITY' => '--'
          },
          {
            'CHAN' => '6',
            'MODE' => 'Infra',
            'RATE' => '270 Mbit/s',
            'SSID' => 'WLAN-123ABC',
            'BARS' => "\x{2582}\x{2584}__",
            'IN-USE' => '',
            'SECURITY' => 'WPA2',
            'SIGNAL' => '32'
          },
          {
            'SIGNAL' => '24',
            'SECURITY' => 'WPA2',
            'IN-USE' => '',
            'BARS' => "\x{2582}___",
            'RATE' => '135 Mbit/s',
            'SSID' => 'WiFi-Repeater',
            'MODE' => 'Infra',
            'CHAN' => '1'
          }
        ];

Upvotes: 0

brian d foy
brian d foy

Reputation: 132778

nmcli already has features to help you do this. You can get the output in other formats:

$ nmcli -m multiline device wifi
IN-USE:                                 *
SSID:                                   Home Wifi
MODE:                                   Infra
CHAN:                                   48
RATE:                                   270 Mbit/s
SIGNAL:                                 75
BARS:                                   ▂▄▆_
SECURITY:                               WPA2

Even better is terse output, which is now just a colon-separated string:

$ nmcli --terse  device wifi
*:Home Wifi:Infra:48:270 Mbit/s:76:▂▄▆_:WPA2

You can even tell nmcli which fields you want:

$ nmcli --get-values ssid,mode  device wifi
Home Wifi:Infra

Upvotes: 4

Related Questions