3

At my home I have two separate routers due to poor signals when being in one location opposed to another.

When I work on my Macbook from different locations I find it annoying when I have to switch between routers. The eventual goal is to run a more complex script under launchd to identify if a better networks is present and automate the change over.

I've tried experimenting with networksetup -listnetworkserviceorder and networksetup -listallhardwareports but have had no luck.

In AppleScript or any other scripting language a way to measure two router's strength similar to what's visible on the menu bar's wifi signal?

3

If your main priority is to have your Mac automatically switch to next strongest access point.....

Your Mac can do that for you already.

Of course you have to have set up both routers as Automatically Join and at the top of your list.

Then tell it to roam and it will automatically connect to next stronger signal network.

Even better is if your SSID and WPA are the same for both.

To turn the roaming on in case it was off do this in Terminal:

sudo defaults write /Library/Preferences/com.apple.airport.opproam enabled -bool true

Then set it up to automatically join next strongest access point

sudo /System/Library/PrivateFrameworks/Apple80211.framework/Versions/A/Resources/airport prefs joinMode=Strongest

You are done, now you can move around and your Mac will keep you connected to the strongest signal.

More reading material here

And Apple explains it how it works

If you still prefer scripting this process here is the list of Airport commands /System/Library/PrivateFrameworks/Apple80211.framework/Versions/A/Resources/airport

  • The article you linked ("More reading material here") says the contents of com.apple.airport.opproam has been ignored by the OS since Yosemite. So I don't think your command will work unless you're running an old OS. – Wowfunhappy Nov 8 '18 at 15:43
  • @Wowfunhappy, just checked it is still there and active on High Sierra.` /Library/Preferences/com.apple.airport.opproam.plist` – Ruskes Nov 8 '18 at 15:51
  • 1
    It's there, but not used. "Handoff" (what forces clients from one AP to the next) is handled by the controller of the WiFi network. For this to work, there has to be a minimum of a -12dBM delta between the two signals – Allan Nov 8 '18 at 16:31
  • @Wowfunhappy Trigger threshold The trigger threshold is the minimum signal level a client requires to maintain the current connection. macOS clients monitor and maintain the current BSSID’s connection until the RSSI crosses the -75 dBm threshold. After RSSI crosses that threshold, macOS scans for roam candidate BSSIDs for the current ESSID. – Ruskes Nov 8 '18 at 16:38
3

Here's a JavaScript for Automation (JXA) script that will scan for WiFi networks and retrieve the SSIDs and RSSI values:

ObjC.import('CoreWLAN');
nil = $();

(() => {

    const defaultInterface = $.CWWiFiClient.sharedWiFiClient.interface;

    if (!defaultInterface.powerOn) return false;

    const networks = defaultInterface
                    .scanForNetworksWithNameError(nil,nil)
                    .allObjects;

    const SSIDs = ObjC.deepUnwrap(networks.valueForKey('ssid'));
    const RSSIValues = ObjC.deepUnwrap(networks.valueForKey('rssiValue'));

    const WiFi = SSIDs.reduce((ξ, item, i)=>{ 
                    ξ[item] = RSSIValues[i];
                    return ξ;
               }, {})

    var WiFiByStrength = {};
    Object.keys(WiFi).sort((i,j)=>{ return WiFi[j] - WiFi[i]; })
                     .map(key=>WiFiByStrength[key] = WiFi[key]);

    return WiFiByStrength;

})();

It presents the output of key-value pairs sorted by signal strength (RSSI) in order, starting with the strongest WiFi network signal first:

{"CK.net":-38, "NCC-1701-D":-59, "Peter's Wi-Fi Network":-67, 
"BTWifi-X":-68, "BTWifi-with-FON":-68, "BTHub4-WMJM":-68}

Here, the RSSI values are negative numbers, with a number closer to 0 (more positive) indicative of a stronger WiFi signal.

2

Yes - both the current network and potential networks can be scripted from unix command line / shell so that extends to most automation languages - including AppleScript. I'd make your final program in python or swift, but here's how to start your process with signal strength.

Getting the current connected network is easy and quick. The relevant entries for signal and noise are the raw radio values on the channel negotiated but it would be better to key off Transmit Rate since as long as you have faster than X network, it doesn't really matter what noise / signal since the transmit rate drops down when the signal drops or the noise raises.

system_profiler SPAirPortDataType:

       AC88U_5G:
          PHY Mode: 802.11ac
          BSSID: 54:36:9b:2d:78:e2
          Channel: 149
          Country Code: CN
          Network Type: Infrastructure
          Security: WPA2 Personal
          Signal / Noise: -26 dBm / -81 dBm
          Transmit Rate: 867
          MCS Index: 9
      Other Local Wi-Fi Networks:
        AC88U:
          PHY Mode: 802.11n
          BSSID: 54:36:9b:2d:78:e1
          Channel: 7
          Country Code: CN
          Network Type: Infrastructure
          Security: WPA2 Personal
          Signal / Noise: -18 dBm / 0 dBm

Scanning all possible radios and channels is quite slower (5 to 10 seconds instead of a fraction of a second to run) than the simple dump above, so you'd need a program to handle that or a script that's a lot more savvy. I'd start with airport --scan and filter for your preferred SSID or known MAC address on your base stations:

/System/Library/PrivateFrameworks/Apple80211.framework/Versions/A/Resources/airport --scan

Once you've scanned, the system_profiler should report more results as the scan results seem to be cached locally for a while.

WiFi engineers perform this optimization all the time by controlling the MCS / Transmit rate. Simply choose all transmit rates you wish to evict all clients for your main radio and once they lose connection at the preferred high speeds, all OS will drop and then pick up the next radio that's available. Much easier than rolling out custom scripts to all the devices that connect to your two radios.

Also, it goes without saying - if you could make both radios broadcast on the same SSID - then your Apple products would just roam but maybe you have a good reason to not have the same network name and simplify your work.

And to answer @nohillside question "how to decide which Wi-Fi is stronger" here are some guidelines.

enter image description here

  • Can you add some detail on how to read the output, especially on how to decide which Wi-Fi is stronger? – nohillside Nov 4 '18 at 15:00
  • @nohillside Ok,I am not good at script, but I will try a simple one. – maP1E bluE Nov 4 '18 at 15:05
  • 1
    I got you @maP1EbluE - This is a very well known design problem for WiFi engineers. The RSSI and Signal are bad things to automate, but if the OP wants signal - it's there. The real two items to key on are MCS Index and Transmit rate and your answer is perfect to get a measure for when the OP wants to start the drop process. Trying to write the whole program / script is far too broad for one question so your answer should be perfect for how to get started. +1 – bmike Nov 4 '18 at 15:50
  • I didn‘t ask for a script actually, but just an explanation on which of the values are important. – nohillside Nov 4 '18 at 16:01
  • 1
    @nohillside You didn't ask for a script, but the OP had it after the main question. I've edited the question to make this not too broad. There's some good info - hopefully I didn't add too many words here - please anyone pare down my text if the short answer of airport --getinfo and airport --scan is all that's needed here and the explanation to look at transmit rate when you wish to bail on a network instead of RSSI / SNR / Signal / Noise decibel values. – bmike Nov 4 '18 at 16:02

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .