{"id":286,"date":"2015-11-01T16:34:37","date_gmt":"2015-11-02T00:34:37","guid":{"rendered":"http:\/\/www.skifactz.com\/wifi\/?p=286"},"modified":"2015-11-01T16:38:02","modified_gmt":"2015-11-02T00:38:02","slug":"scanmeternm-new-wifi-antenna-pointing-tool","status":"publish","type":"post","link":"https:\/\/www.skifactz.com\/wifi\/?p=286","title":{"rendered":"Scanmeternm: New WiFi Antenna Pointing Tool"},"content":{"rendered":"<p>The old <a href=\"http:\/\/www.skifactz.com\/wifi\/?p=112\">Scanmeter<\/a> high gain WiFi antenna pointer written in Bash still works very well.<\/p>\n<p>However, it depends on the output of iwlist command to read wireless APs. For some reason iwlist is not reliable\u00a0on my new \u00a0Ubuntu machine.<\/p>\n<p>I wrote a new antenna pointing tool in Python called Scanmeternm. Instead of iwlist, I am reading the wireless router power using ncmli dev wifi command.\u00a0It&#8217;s certainly easier to customize for casual coders than the old Bash Scanmeter. For example, you could probably use the script to control an Arduino stepper motor and automatically rotate antenna on top of a vehicle.<\/p>\n<p><strong>Usage<\/strong><\/p>\n<p>The usage is very straightforward, and it is more user friendly than the old Scanmeter.<\/p>\n<p>If you download to your Downloads directory, you&#8217;d add executable privilege:<\/p>\n<pre>chmod +x ~\/Downloads\/scanmeternm.py<\/pre>\n<p>Run as:<\/p>\n<pre>.\/~\/Downloads\/scanmeternm.py<\/pre>\n<p><strong>Caveats<\/strong><\/p>\n<ul>\n<li>Requires Network-manager package<\/li>\n<li>Does not work in Windows, maybe not even in OS X. I don&#8217;t know if Network-manager is available for Mac.<\/li>\n<li>I don&#8217;t know what units are used for nmcli dev wifi output. They may be linear or logarithmic. The meter readout green\/red threshold is entirely arbitrary.<\/li>\n<\/ul>\n<pre class=\"easycode; title: Scanmeternm.py Wifi Antenna Pointer;lang:;\"> #!\u00a0\/usr\/bin\/env\u00a0python\r\n\r\n#\u00a0Measure\u00a0wifi\u00a0signal\u00a0based\u00a0on\u00a0nmcli.\u00a0Works\u00a0only\u00a0if\u00a0Network-manager\u00a0is\u00a0installed.\r\n#\u00a0Scanmeternm\u00a0V1.0,\u00a0skifactz.com\/wifi\r\n\r\nfrom\u00a0subprocess\u00a0import\u00a0Popen,\u00a0PIPE,\u00a0STDOUT\r\nimport\u00a0sys\r\nimport\u00a0os\r\nimport\u00a0time\r\n\r\n#\u00a0User\u00a0customizable\u00a0variables\r\n#\u00a0Customize\u00a0meter\u00a0readout\u00a0here\r\nthreshold\u00a0=\u00a052\u00a0\u00a0\u00a0#\u00a0Red\/green\u00a0threshold\r\nchar\u00a0=\u00a0u'\\u2588'\u00a0#\u00a0Graphics\u00a0character,\u00a0default\u00a0is\u00a0a\u00a0box\r\n\r\n#\u00a0Menu\u00a0scanned\u00a0list\u00a0variables\r\nssidMaxLength\u00a0=\u00a017\u00a0#\u00a0Truncate\u00a0length\u00a0to\u00a0satisfy\u00a0tab\u00a0based\u00a0layout\u00a0fit\u00a0within\u00a080\u00a0columns.\r\ntab\u00a0=\u00a0'\\t'\u00a0#\u00a0Tab\u00a0character.\u00a0Can\u00a0use\u00a0'\u00a0'\u00a0or\u00a0'\\t'\u00a0*\u00a02\u00a0to\u00a0modify\u00a0layout\r\n\r\n\r\n#\u00a0Lookup\u00a0tables\u00a0for\u00a02.4\u00a0GHz\u00a0and\u00a05\u00a0GHz\u00a0frequency\u00a0to\u00a0channel\u00a0conversion.\r\n\r\nlut24\u00a0=\u00a0{\r\n2412:'01\u00a0(2.4\u00a0GHz)',\r\n2417:'02\u00a0(2.4\u00a0GHz)',\r\n2422:'03\u00a0(2.4\u00a0GHz)',\r\n2427:'04\u00a0(2.4\u00a0GHz)',\r\n2432:'05\u00a0(2.4\u00a0GHz)',\r\n2437:'06\u00a0(2.4\u00a0GHz)',\r\n2442:'07\u00a0(2.4\u00a0GHz)',\r\n2447:'08\u00a0(2.4\u00a0GHz)',\r\n2452:'09\u00a0(2.4\u00a0GHz)',\r\n2457:'10\u00a0(2.4\u00a0GHz)',\r\n2462:'11\u00a0(2.4\u00a0GHz)',\r\n2467:'12\u00a0(2.4\u00a0GHz)',\r\n2472:'13\u00a0(2.4\u00a0GHz)',\r\n2484:'14\u00a0(2.4\u00a0GHz)'\r\n};\r\n\r\nlut5\u00a0=\u00a0{\r\n5035:'07\u00a0\u00a0(5\u00a0GHz)',\r\n5040:'08\u00a0\u00a0(5\u00a0GHz)',\r\n5045:'09\u00a0\u00a0(5\u00a0GHz)',\r\n5055:'11\u00a0\u00a0(5\u00a0GHz)',\r\n5060:'12\u00a0\u00a0(5\u00a0GHz)',\r\n5080:'16\u00a0\u00a0(5\u00a0GHz)',\r\n5170:'34\u00a0\u00a0(5\u00a0GHz)',\r\n5180:'36\u00a0\u00a0(5\u00a0GHz)',\r\n5190:'38\u00a0\u00a0(5\u00a0GHz)',\r\n5200:'40\u00a0\u00a0(5\u00a0GHz)',\r\n5210:'42\u00a0\u00a0(5\u00a0GHz)',\r\n5220:'44\u00a0\u00a0(5\u00a0GHz)',\r\n5230:'46\u00a0\u00a0(5\u00a0GHz)',\r\n5240:'48\u00a0\u00a0(5\u00a0GHz)',\r\n5260:'52\u00a0\u00a0(5\u00a0GHz)',\r\n5280:'56\u00a0\u00a0(5\u00a0GHz)',\r\n5300:'60\u00a0\u00a0(5\u00a0GHz)',\r\n5320:'64\u00a0\u00a0(5\u00a0GHz)',\r\n5500:'100\u00a0(5\u00a0GHz)',\r\n5520:'104\u00a0(5\u00a0GHz)',\r\n5540:'108\u00a0(5\u00a0GHz)',\r\n5560:'112\u00a0(5\u00a0GHz)',\r\n5580:'116\u00a0(5\u00a0GHz)',\r\n5600:'120\u00a0(5\u00a0GHz)',\r\n5620:'124\u00a0(5\u00a0GHz)',\r\n5640:'128\u00a0(5\u00a0GHz)',\r\n5660:'132\u00a0(5\u00a0GHz)',\r\n5680:'136\u00a0(5\u00a0GHz)',\r\n5700:'140\u00a0(5\u00a0GHz)',\r\n5720:'144\u00a0(5\u00a0GHz)',\r\n5745:'149\u00a0(5\u00a0GHz)',\r\n5765:'153\u00a0(5\u00a0GHz)',\r\n5785:'157\u00a0(5\u00a0GHz)',\r\n5805:'161\u00a0(5\u00a0GHz)',\r\n5825:'165\u00a0(5\u00a0GHz)'\r\n};\r\n\r\n#\u00a0Convert\u00a02.4\u00a0GHz\u00a0and\u00a05\u00a0GHz\u00a0to\u00a0channel\u00a0numbers.\r\ndef\u00a0getchannel(freq):\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0if\u00a0freq[0]\u00a0==\u00a0'2':\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return\u00a0lut24[int(freq)]\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0if\u00a0freq[0]\u00a0==\u00a0'5':\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return\u00a0lut5[int(freq)]\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return\u00a0'N\/A'\r\n\r\n#\u00a0Prints\u00a0list\u00a0of\u00a0scanned\u00a0APs\u00a0for\u00a0main\u00a0menu\u00a0and\u00a0returns\u00a0the\u00a0list\r\ndef\u00a0aplist():\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0#\u00a0Clear\u00a0Linux\u00a0console\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Popen(['clear'])\r\n\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0#\u00a0Scan\u00a0available\u00a0APs\u00a0and\u00a0save\u00a0in\u00a0scannedMenu\u00a0list.\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0scan\u00a0=\u00a0Popen(['nmcli',\u00a0'dev',\u00a0'wifi'],\u00a0stdout=PIPE,\u00a0stderr=STDOUT)\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0scannedMenu=[]\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0for\u00a0line\u00a0in\u00a0scan.stdout:\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0scannedMenu.append(line)\r\n\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0#\u00a0Print\u00a0menu\u00a0header.\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0print\u00a0'No.\u00a0SSID',\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0print\u00a0'\u00a0'\u00a0*\u00a0(ssidMaxLength\u00a0-\u00a04),\u00a0#\u00a0White\u00a0spaces\u00a0minus\u00a0SSID\u00a0length\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0print\u00a0'BSSID\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0CHANNEL\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0POWER\u00a0\u00a0\u00a0ENCRYPT.'\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0print\u00a0u'\\u00af'\u00a0*\u00a080\r\n\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0#\u00a0SSID\u00a0and\u00a0SECURITY\u00a0fields\u00a0may\u00a0contain\u00a0spaces.\u00a0We\u00a0use\u00a0the\u00a0':'\u00a0marks\u00a0as\u00a0the\u00a0parsing\u00a0ref.\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0for\u00a0line\u00a0in\u00a0scannedMenu[1:]:\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0ssid\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0=\u00a0line.split(\"'\")[1]\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0cells\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0=\u00a0line.split(':')\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0bssid\u00a0=\u00a0':'.join([cells[0][-2:],\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0cells[1],\u00a0cells[2],\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0cells[3],\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0cells[4],\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0cells[5][:2]])\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0cells\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0=\u00a0cells[5].split()\u00a0#\u00a0Split\u00a0cells\u00a0using\u00a0space\u00a0for\u00a0the\u00a0rest\u00a0of\u00a0the\u00a0fields.\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0chan\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0=\u00a0getchannel(cells[2])\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0power\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0=\u00a0cells[6]\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0encrypt\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0=\u00a0cells[7]\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0lineNo\u00a0=\u00a0str(scannedMenu.index(line))\u00a0#\u00a0Number\u00a0APs\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0print\u00a0lineNo.zfill(2)\u00a0+\u00a0'\u00a0',\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0print\u00a0ssid[:ssidMaxLength],\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0print\u00a0'\u00a0'\u00a0*\u00a0(ssidMaxLength\u00a0-\u00a0len(ssid)),\u00a0#\u00a0Padding\u00a0based\u00a0on\u00a0maximum\u00a0SSID\u00a0length\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0print\u00a0tab.join([bssid,\u00a0chan,\u00a0power,\u00a0encrypt])\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0print\r\n\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return\u00a0scannedMenu\r\n\r\n#\u00a0Menu\u00a0user\u00a0input\u00a0returns\u00a0selected\u00a0bssid\u00a0and\u00a0facilitates\u00a0user\u00a0commands\u00a0like\u00a0'S'\u00a0and\u00a0'Q'.\r\ndef\u00a0menuinput(scannedMenu):\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0ap\u00a0=\u00a0False\r\n\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0def\u00a0enterap():\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0ap\u00a0=\u00a0raw_input('Enter\u00a0access\u00a0point\u00a0number.\u00a0Enter\u00a0S\u00a0for\u00a0new\u00a0scan\u00a0or\u00a0Q\u00a0to\u00a0quit.\u00a0\\n')\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0if\u00a0ap\u00a0==\u00a0's'\u00a0or\u00a0ap\u00a0==\u00a0'S':\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0aplist()\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0if\u00a0ap\u00a0==\u00a0'q'\u00a0or\u00a0ap\u00a0==\u00a0'Q':\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0sys.exit()\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0if\u00a0ap.isdigit()\u00a0==\u00a0False:\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0ap\u00a0=\u00a0False\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0if\u00a0int(ap)\u00a0&gt;\u00a0len(scannedMenu)\u00a0-\u00a01:\u00a0#\u00a0-1\u00a0because\u00a0of\u00a0the\u00a0nmcli\u00a0header\u00a0line\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0ap\u00a0=\u00a0False\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0if\u00a0int(ap)\u00a0==\u00a00:\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0print\u00a0'No\u00a0such\u00a0AP.'\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0ap\u00a0=\u00a0False\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return\u00a0ap\r\n\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0#\u00a0User\u00a0input,\u00a0loop\u00a0until\u00a0ap\u00a0no\u00a0longer\u00a0False\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0while\u00a0ap\u00a0==\u00a0False:\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0ap\u00a0=\u00a0enterap()\r\n\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0#\u00a0User\u00a0input\u00a0selection\u00a0assignent\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0for\u00a0line\u00a0in\u00a0scannedMenu[1:]:\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0lineNo\u00a0=\u00a0scannedMenu.index(line)\u00a0#\u00a0index\u00a0number\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0if\u00a0int(ap)\u00a0==\u00a0lineNo:\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0ssidSel\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0=\u00a0line.split(\"'\")[1]\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0cells\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0=\u00a0line.split(':')\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0bssidSel\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0=\u00a0':'.join([cells[0][-2:],\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0cells[1],\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0cells[2],\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0cells[3],\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0cells[4],\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0cells[5][:2]])\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return\u00a0ssidSel,\u00a0bssidSel\r\n\r\n\r\n#\u00a0Main\u00a0menu\u00a0control\u00a0calls\u00a0AP\u00a0scanning,\u00a0prints\u00a0the\u00a0list\u00a0and\u00a0calls\u00a0user\u00a0AP\u00a0selection.\r\ndef\u00a0mainControl():\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0#\u00a0print\u00a0ap\u00a0list,\u00a0get\u00a0the\u00a0list\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0scannedMenu\u00a0=\u00a0aplist()\r\n\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0#\u00a0user\u00a0menu\u00a0input.\u00a0get\u00a0selected\u00a0ssid\u00a0and\u00a0bssid\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0global\u00a0scanselection\u00a0#\u00a0Declaring\u00a0global\u00a0list\u00a0so\u00a0it\u00a0is\u00a0available\u00a0to\u00a0AP\u00a0scan\u00a0below\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0scanselection\u00a0=\u00a0menuinput(scannedMenu)\r\n\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0print\u00a0'You\u00a0selected:',\u00a0scanselection[0],\u00a0scanselection[1]\u00a0+\u00a0'\\n'\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0print\u00a0'CTRL\u00a0+\u00a0C\u00a0exits\u00a0scan\u00a0mode.'\u00a0+\u00a0'\\n'\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0time.sleep(.33)\r\n\r\nmainControl()\r\n\r\n\r\ndef\u00a0red(text):\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return\u00a0('\\033[91m'\u00a0+\u00a0text\u00a0+\u00a0'\\033[0m')\r\n\r\ndef\u00a0green(text):\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return\u00a0('\\033[92m'\u00a0+\u00a0text\u00a0+\u00a0'\\033[0m')\r\n\r\n#\u00a0Here\u00a0we\u00a0print\u00a0power\u00a0reading\u00a0to\u00a0the\u00a0scaled\u00a0console\u00a0in\u00a0form\u00a0of\u00a0an\u00a0dynamic\u00a0histogram.\r\ndef\u00a0readout(power):\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0if\u00a0powerScaled\u00a0==\u00a00:\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0print\u00a0'%s\u00a0is\u00a0out\u00a0of\u00a0range\u00a0or\u00a0not\u00a0transmitting.'\u00a0%scanselection[0]\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0if\u00a0powerScaled\u00a0&lt;\u00a0thresholdScaled:\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0lPower\u00a0=\u00a0powerScaled\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0else:\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0lPower\u00a0=\u00a0thresholdScaled\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0hPower\u00a0=\u00a0powerScaled\u00a0-\u00a0thresholdScaled\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0sys.stdout.write(red(char)\u00a0*\u00a0lPower)\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0sys.stdout.write(green(char)\u00a0*\u00a0hPower)\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0print\u00a0power\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0#print\u00a0'\\r'\r\n\r\nwhile\u00a0True:\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0try:\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0#\u00a0We\u00a0declare\u00a0these\u00a0two\u00a0variables\u00a0for\u00a0the\u00a0scenario\u00a0when\u00a0the\u00a0radio\u00a0signal\u00a0drops\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0powerScaled\u00a0=\u00a00\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0thresholdScaled\u00a0=\u00a00\r\n\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0scan\u00a0=\u00a0Popen(['nmcli',\u00a0'dev',\u00a0'wifi'],\u00a0stdout=PIPE,\u00a0stderr=STDOUT)\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0#\u00a0Is\u00a0the\u00a0selected\u00a0bssid\u00a0continuosly\u00a0present\u00a0in\u00a0the\u00a0scan?\u00a0If\u00a0so,\u00a0proceed.\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0for\u00a0line\u00a0in\u00a0scan.stdout:\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0if\u00a0scanselection[1]\u00a0in\u00a0line:\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0cells\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0=\u00a0line.split(':')\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0cells\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0=\u00a0cells[5].split()\u00a0#\u00a0Split\u00a0cells\u00a0using\u00a0white\u00a0space\u00a0for\u00a0the\u00a0rest.\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0power\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0=\u00a0int(cells[6])\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0#\u00a0Dynamically\u00a0scale\u00a0max\u00a0nmcli\u00a0signal\u00a0to\u00a0maximum\u00a0console\u00a0width,\u00a0non-dB\u00a0units\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0rows,\u00a0columns\u00a0=\u00a0os.popen('stty\u00a0size',\u00a0'r').read().split()\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0scaleFactor\u00a0=\u00a0float(columns)\u00a0\/\u00a0100\u00a0#\u00a0Max\u00a0terminal\u00a0width\u00a0\/\u00a0max\u00a0nmcli\u00a0signal\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0powerScaled\u00a0=\u00a0int(round(power\u00a0*\u00a0scaleFactor))\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0thresholdScaled\u00a0=\u00a0int(round(threshold\u00a0*\u00a0scaleFactor))\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0#\u00a0Print\u00a0readout\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0readout(powerScaled)\r\n\r\n#\u00a0On\u00a0CTRL\u00a0+\u00a0C\u00a0go\u00a0to\u00a0main\u00a0menu\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0except\u00a0KeyboardInterrupt:\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0mainControl()<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>The old Scanmeter high gain WiFi antenna pointer written in Bash still works very well. However, it depends on the output of iwlist command to read wireless APs. For some reason iwlist is not reliable\u00a0on my new \u00a0Ubuntu machine. I wrote a new antenna pointing tool in Python called Scanmeternm. Instead of iwlist, I am &hellip; <a href=\"https:\/\/www.skifactz.com\/wifi\/?p=286\" class=\"more-link\">Continue reading <span class=\"screen-reader-text\">Scanmeternm: New WiFi Antenna Pointing Tool<\/span> <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[5,2],"tags":[],"class_list":["post-286","post","type-post","status-publish","format-standard","hentry","category-software","category-wifi"],"_links":{"self":[{"href":"https:\/\/www.skifactz.com\/wifi\/index.php?rest_route=\/wp\/v2\/posts\/286","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.skifactz.com\/wifi\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.skifactz.com\/wifi\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.skifactz.com\/wifi\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.skifactz.com\/wifi\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=286"}],"version-history":[{"count":2,"href":"https:\/\/www.skifactz.com\/wifi\/index.php?rest_route=\/wp\/v2\/posts\/286\/revisions"}],"predecessor-version":[{"id":288,"href":"https:\/\/www.skifactz.com\/wifi\/index.php?rest_route=\/wp\/v2\/posts\/286\/revisions\/288"}],"wp:attachment":[{"href":"https:\/\/www.skifactz.com\/wifi\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=286"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.skifactz.com\/wifi\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=286"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.skifactz.com\/wifi\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=286"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}