#!/usr/bin/env ruby
begin
require 'wx'
rescue LoadError => no_wx_err
begin
require 'rubygems'
require 'wx'
rescue LoadError
raise no_wx_err
end
end
require 'net/http'
require 'open-uri'
require 'uri'
require 'fileutils.rb'
require 'yaml'
class RouterConfig
def user
@user
end
def user=(usr)
@user=usr
end
def url
@url
end
def url=(ur)
@url=ur
end
def pass
@pass
end
def pass=(pw)
@pass=pw
end
end
# custom dialogs
class ConnectedStationsMessageBox < Wx::Dialog
def initialize (what)
super(nil, -1, "Connected Stations")
if (what == nil) then what ="" end
sizer = Wx::BoxSizer.new(Wx::VERTICAL)
label = Wx::StaticText.new(self, -1, what)
sizer.add(label, 0, Wx::ALIGN_CENTER | Wx::ALL, 5)
button_sizer = Wx::StdDialogButtonSizer.new()
btn = Wx::Button.new(self, Wx::ID_OK, 'OK')
btn.set_default()
button_sizer.add_button(btn)
button_sizer.realize
sizer.add(button_sizer, 0, Wx::ALIGN_CENTER_VERTICAL|Wx::ALL, 5)
set_sizer(sizer)
sizer.fit(self)
end
end
class ConfigureRouterMessageBox < Wx::Dialog
def initialize(routerConfig)
if (routerConfig != nil) then
if (routerConfig.user != nil) then user = routerConfig.user else user = "" end
if (routerConfig.pass != nil) then pass = routerConfig.pass else pass = "" end
if (routerConfig.url != nil) then url = routerConfig.url else url = "" end
end
super(nil, -1, 'Router Config')
sizer = Wx::BoxSizer.new(Wx::VERTICAL)
label = Wx::StaticText.new(self, -1, "Router Configuration")
sizer.add(label, 0, Wx::ALIGN_CENTER | Wx::ALL, 5)
box = Wx::BoxSizer.new(Wx::HORIZONTAL)
label = Wx::StaticText.new(self, -1, "URL")
box.add(label, 0, Wx::ALIGN_CENTER | Wx::ALL, 5)
text = Wx::TextCtrl.new(self, -1, url, Wx::DEFAULT_POSITION, Wx::Size.new(80,-1))
box.add(text, 1, Wx::ALIGN_CENTER | Wx::ALL, 5)
sizer.add(box, 0, Wx::GROW | Wx::ALIGN_CENTER_VERTICAL | Wx::ALL, 5)
box = Wx::BoxSizer.new(Wx::HORIZONTAL)
label = Wx::StaticText.new(self, -1, "Username")
box.add(label, 0, Wx::ALIGN_CENTER | Wx::ALL, 5)
text = Wx::TextCtrl.new(self, -1, user, Wx::DEFAULT_POSITION, Wx::Size.new(80,-1))
box.add(text, 1, Wx::ALIGN_CENTER | Wx::ALL, 5)
sizer.add(box, 0, Wx::GROW | Wx::ALIGN_CENTER_VERTICAL | Wx::ALL, 5)
box = Wx::BoxSizer.new(Wx::HORIZONTAL)
label = Wx::StaticText.new(self, -1, "Password")
box.add(label, 0, Wx::ALIGN_CENTER | Wx::ALL, 5)
text = Wx::TextCtrl.new(self, -1, pass, Wx::DEFAULT_POSITION, Wx::Size.new(80,-1), Wx::TE_PASSWORD)
box.add(text, 1, Wx::ALIGN_CENTER | Wx::ALL, 5)
sizer.add(box, 0, Wx::GROW | Wx::ALIGN_CENTER_VERTICAL | Wx::ALL, 5)
line = Wx::StaticLine.new(self, -1, Wx::DEFAULT_POSITION,
Wx::Size.new(20,-1), Wx::LI_HORIZONTAL)
sizer.add(line, 0, Wx::ALIGN_BOTTOM | Wx::GROW , 5)
button_sizer = Wx::StdDialogButtonSizer.new()
btn = Wx::Button.new(self, Wx::ID_OK, 'OK')
btn.set_default()
button_sizer.add_button(btn)
btn = Wx::Button.new(self, Wx::ID_CANCEL, 'Cancel')
button_sizer.add_button(btn)
button_sizer.realize
sizer.add(button_sizer, 0, Wx::ALIGN_CENTER_VERTICAL|Wx::ALL, 5)
set_sizer(sizer)
sizer.fit(self)
end
end
class WifiTaskBarIcon < Wx::TaskBarIcon
MENU_ITEM_SHOWALL = 6000
MENU_ITEM_CONFIGURE = 6001
MENU_ITEM_QUIT = 6002
EVT_TIMER_ID = 6003
def routerConfig
@routerConfig
end
def routerConfig=(rcf)
@routerConfig=rcf
end
def load_config
begin
@routerConfig=YAML::load(File.open(@configFolder+@configFile)) if File.exist?(@configFolder+@configFile)
if (!@routerConfig) then
puts "Error loading config file: "+$!
@routerConfig = RouterConfig.new
return false
else
print "Found #{@configFolder}#{@configFile}.\n"
@tURL = URI.parse(routerConfig.url)
return true
end
rescue
puts "Exception raised while loading config file: "+$!
@routerConfig = RouterConfig.new
return false
end
end
def initialize()
super()
@configFolder = ENV['HOME']+"/.wifistat/"
@configFile = "config.yaml"
@staticConn=0
@conf=load_config
load_images
set_icon(@inactive, 'WiFi Monitor - Inactive')
@image_index = 1
# setup events for left click and menu items
evt_taskbar_left_dclick {show_stations }
evt_menu(MENU_ITEM_SHOWALL) {show_stations }
evt_menu(MENU_ITEM_CONFIGURE) { configure_router }
evt_menu(MENU_ITEM_QUIT) { exit }
timer = Wx::Timer.new(self, EVT_TIMER_ID)
evt_timer(EVT_TIMER_ID) { update }
timer.start(1000)
end
def create_popup_menu
menu = Wx::Menu.new
menu.append(MENU_ITEM_SHOWALL, "Show all")
menu.append(MENU_ITEM_CONFIGURE, "Configure")
menu.append_separator
menu.append(MENU_ITEM_QUIT, "Quit")
return menu
end
def make_icon(imgname)
# Resize the image if required by the plataform
img = Wx::Image.new(imgname)
if Wx::PLATFORM == "WXMSW"
img = img.scale(16, 16)
elsif Wx::PLATFORM == "WXGTK"
img = img.scale(22, 22)
end
icon = Wx::Icon.new
icon.copy_from_bitmap(Wx::Bitmap.new(img))
return icon
end
def load_images
#wxruby has no support for svg files, so we stick with png images
@active = make_icon("/usr/share/icons/Tango/32x32/status/gnome-dev-wavelan-encrypted.png")
@inactive = make_icon("/usr/share/icons/Tango/32x32/status/network-offline.png")
@config = make_icon("/usr/share/icons/Tango/32x32/apps/config-users.png")
end
def configure_router
dlg = ConfigureRouterMessageBox.new(@routerConfig)
dlg.center_on_screen(Wx::BOTH)
val = dlg.show_modal()
if val == Wx::ID_OK
FileUtils.mkdir_p(@configFolder) unless File.directory?(@configFolder)
File.open(@configFolder+@configFile, 'w') { |f| f.puts @routerConfig.to_yaml }
dlg = ConnectedStationsMessageBox.new("New config for #{@routerConfig.url}")
else
puts "cancelled"
end
dlg.destroy
@conf=true
@tURL = URI.parse(@routerConfig.url)
end
def check
# http request/html parsing to check for new connections
# TODO: make regex a configurable parameter for multiple routers
allItem = Array.new
regex=/writeRow\(\[sid\,\"(.+)\"\,(.+)\,(.+)/
open(@tURL, :http_basic_authentication=> [@routerConfig.user, @routerConfig.pass]) {|f|
oi=f.read
oi.scan(regex)
tmpHash= {'mac'=>$1,'chan'=>$2}
allItem << tmpHash
}
return allItem
rescue
#puts "Error http request: "+$!
dlg = Wx::MessageDialog.new(nil, "Error http request: "+$!, "Error", Wx::OK | Wx::ICON_INFORMATION)
dlg.show_modal()
dlg.destroy()
end
def show_stations
if (@allStation != nil) then
stList="MAC\t\t\t\tchan\n"
@allStation.each { |st| stList+=st['mac']+"\t\t"+st['chan']+"\n" }
else
stList="No data\n"
end
dlg = ConnectedStationsMessageBox.new(stList)
dlg.center_on_screen(Wx::BOTH)
dlg.show_modal()
end
def update
return if (@conf==false)
@allStation = check()
return if (@allStation == nil)
@staticConn=@allStation.size if (@staticConn == 0)
if (@staticConn != @allStation.size) then
dlg = ConnectedStationsMessageBox.new("A new station has connected on \n#{routerConfig.url}")
dlg.center_on_screen(Wx::BOTH)
dlg.show_modal()
end
if (@allStation == nil) then
nStat=0
else
nStat=@allStation.size
end
tip = if nStat > 0 then "#{nStat} connections" else 'no connection' end
if nStat > 0 then
set_icon(@active, 'WiFi Monitor: '+tip)
else
set_icon(@inactive, 'WiFi Monitor: '+tip)
end
end
end
class WiFiMonitorApp < Wx::App
def on_init
@tbicon = WifiTaskBarIcon.new()
end
end
wifimon = WiFiMonitorApp.new
wifimon.main_loop
Like this:
Like Loading...