biscuit-monitor 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore CHANGED
@@ -1,5 +1,6 @@
1
1
  *.gem
2
2
  *.log
3
+ *.log.*
3
4
  *.rbc
4
5
  .bundle
5
6
  .config
@@ -18,3 +19,4 @@ test/version_tmp
18
19
  tmp
19
20
  /.bin
20
21
  /vendor/bundle
22
+ /.idea
data/Gemfile CHANGED
@@ -6,5 +6,13 @@ source 'https://rubygems.org'
6
6
  gemspec
7
7
 
8
8
  group :development, :test do
9
- gem 'rspec'
9
+ end
10
+
11
+ group :development do
12
+ gem 'ap'
13
+ gem 'debugger'
14
+ gem 'hirb'
15
+ gem 'interactive_editor'
16
+ gem 'tmuxinator'
17
+ gem 'wirble'
10
18
  end
data/bin/biscuit-monitor CHANGED
@@ -1,8 +1,17 @@
1
1
  #!/usr/bin/env ruby -w
2
2
  # encoding: utf-8
3
3
 
4
- $:.unshift(File.dirname(__FILE__) + '/../lib') unless $:.include?(File.dirname(__FILE__) + '/../lib')
4
+ trap('SIGINT') { throw :ctrl_c }
5
5
 
6
- require 'biscuit-monitor'
6
+ catch :ctrl_c do
7
+ begin
8
+ $:.unshift(File.dirname(__FILE__) + '/../lib') unless $:.include?(File.dirname(__FILE__) + '/../lib')
7
9
 
8
- Biscuit::Monitor::CLI.start
10
+ require 'biscuit-monitor'
11
+
12
+ Biscuit::Monitor::CLI.start
13
+ rescue SystemExit, Interrupt
14
+ raise
15
+ rescue Exception => ex
16
+ end
17
+ end
data/bin/console ADDED
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env ruby -w
2
+ # encoding: utf-8
3
+
4
+ $LOAD_PATH.unshift File.dirname(__FILE__) + "/../lib"
5
+
6
+ require 'biscuit-monitor'
7
+ require 'irb'
8
+ require 'irb/completion'
9
+
10
+ include Biscuit::Monitor
11
+
12
+ IRB.start
@@ -15,8 +15,11 @@ Gem::Specification.new do |gem|
15
15
  gem.require_paths = ["lib"]
16
16
  gem.version = Biscuit::Monitor::VERSION
17
17
 
18
- gem.add_runtime_dependency 'thor'
18
+ gem.add_runtime_dependency 'colorize'
19
19
  gem.add_runtime_dependency 'multi_json'
20
20
  gem.add_runtime_dependency 'oj'
21
- gem.add_runtime_dependency 'colorize'
21
+ gem.add_runtime_dependency 'sequel'
22
+ gem.add_runtime_dependency 'sqlite3'
23
+ gem.add_runtime_dependency 'thor'
24
+ gem.add_runtime_dependency 'nokogiri-plist'
22
25
  end
@@ -0,0 +1,31 @@
1
+ # encoding: utf-8
2
+
3
+ module Biscuit
4
+ module Monitor
5
+
6
+ require 'nokogiri-plist'
7
+
8
+ class AccessPointScanner
9
+
10
+ SCAN_ACCESS_POINTS = %x[/System/Library/PrivateFrameworks/Apple80211.framework/Versions/Current/Resources/airport --scan --xml]
11
+
12
+ attr_reader :found_access_points, :scanned_on
13
+
14
+ def exec
15
+ @scanned_on = Time.now.utc
16
+
17
+ @found_access_points = raw_found_access_points.map do |access_point|
18
+ { ssid: access_point["SSID"].strip, ssid_name: access_point["SSID_STR"], bssid: access_point["BSSID"], rssi: access_point["RSSI"], scanned_on: @scanned_on }
19
+ end
20
+ end
21
+
22
+ def raw_found_access_points
23
+ @raw_found_access_points ||= Nokogiri::PList(SCAN_ACCESS_POINTS)
24
+ end
25
+
26
+ def scan
27
+ SCAN_ACCESS_POINTS
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,36 @@
1
+ # encoding: utf-8
2
+
3
+ require 'colorize'
4
+
5
+ module Biscuit
6
+ module Monitor
7
+ class Cinr
8
+ attr_accessor :level
9
+
10
+ def initialize(level)
11
+ @level = Integer(level)
12
+ end
13
+
14
+ def message
15
+ "CINR: #{@level}dBs".colorize(foreground_color)
16
+ end
17
+
18
+ def foreground_color
19
+ case
20
+ when @level > 24 then
21
+ :green
22
+ when (13..24).include?(@level) then
23
+ :light_green
24
+ when (8..12).include?(@level) then
25
+ :yellow
26
+ when (3..7).include?(@level) then
27
+ :light_red
28
+ when @level < 3 then
29
+ :red
30
+ else
31
+ :white
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,20 @@
1
+ # encoding: utf-8
2
+
3
+ module Biscuit
4
+ module Monitor
5
+
6
+ require 'thor'
7
+
8
+ class CLI < Thor
9
+ default_task :monitor
10
+
11
+ desc 'monitor', 'Start monitoring your biscuit.'
12
+ method_option :device_ip, default: '192.168.1.1', aliases: '-d'
13
+ method_option :polling_frequency_in_seconds, default: 3, aliases: '-f'
14
+
15
+ def monitor
16
+ Biscuit::Monitor::Poller.new(options[:device_ip], Integer(options[:polling_frequency_in_seconds])).poll
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,71 @@
1
+ # encoding: utf-8
2
+
3
+ module Biscuit
4
+ module Monitor
5
+ class Poller
6
+ def initialize(device_ip, polling_frequency_in_seconds)
7
+ @device_ip = device_ip
8
+ @polling_frequency_in_seconds = polling_frequency_in_seconds
9
+ end
10
+
11
+ def poll
12
+ until false
13
+ begin
14
+
15
+ ss = SignalStrength.new(@device_ip)
16
+ ss.exec
17
+
18
+ message = ''
19
+ message << ss.cinr
20
+ message << ' '
21
+ message << ss.rssi
22
+
23
+ write message
24
+
25
+ Thread.new do
26
+ ap = AccessPointScanner.new
27
+ ap.exec
28
+ ap.found_access_points.each do |access_point|
29
+ DB_CONN[:wi_fi_access_points].insert(access_point)
30
+ LOGGER.debug(access_point)
31
+ end
32
+ end
33
+
34
+ Thread.new(ss.response) do |sig_str|
35
+ DB_CONN[:wi_max_statuses].insert(sig_str)
36
+ LOGGER.debug(sig_str)
37
+ end
38
+
39
+ rescue Errno::EHOSTUNREACH => err
40
+
41
+ write "Cannot find the biscuit. Check your connection. Tail #{LOG_FILE} for details."
42
+ LOGGER.error(err.inspect)
43
+
44
+ rescue StandardError => err
45
+
46
+ write "There was an error talking to your biscuit. Tail #{LOG_FILE} for details."
47
+ LOGGER.error(err.inspect)
48
+
49
+ ensure
50
+
51
+ sleep @polling_frequency_in_seconds # TODO when error increase length of time until next check to avoid spamming error log
52
+
53
+ end
54
+ end
55
+ end
56
+
57
+ private
58
+
59
+ def clear_last_message
60
+ (@last_message || '').length.times { print "\b" }
61
+ end
62
+
63
+ def write(message)
64
+ clear_last_message
65
+ print message
66
+ @last_message = message
67
+ end
68
+ end
69
+ end
70
+ end
71
+
@@ -0,0 +1,30 @@
1
+ # encoding: utf-8
2
+
3
+ require 'colorize'
4
+
5
+ module Biscuit
6
+ module Monitor
7
+ class Rssi
8
+ attr_accessor :level
9
+
10
+ def initialize(level)
11
+ @level = Integer(level)
12
+ end
13
+
14
+ def message
15
+ "RSSI: #{@level}dBs".colorize(foreground_color)
16
+ end
17
+
18
+ def foreground_color
19
+ case
20
+ when @level > -50 then
21
+ :green
22
+ when @level < -100 then
23
+ :red
24
+ else
25
+ :yellow
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,72 @@
1
+ # encoding: utf-8
2
+
3
+ module Biscuit
4
+ module Monitor
5
+
6
+ %w< multi_json net/http uri >.each { |dep| require dep }
7
+
8
+ class SignalStrength
9
+ attr_reader :response
10
+
11
+ def initialize(device_ip)
12
+ @device_ip = device_ip
13
+ end
14
+
15
+ def exec
16
+ @response = parse(parse_javascript_to_json(Net::HTTP.get(device_uri)))[:data]
17
+ @response.merge!(captured_on: Time.now.utc)
18
+ end
19
+
20
+ def cinr
21
+ Cinr.new(@response[:cinr]).message
22
+ end
23
+
24
+ def rssi
25
+ Rssi.new(@response[:rssi]).message
26
+ end
27
+
28
+ private
29
+
30
+ def device_uri
31
+ URI.parse("http://#@device_ip/cgi-bin/webmain.cgi?act=act_wimax_status&param=WIMAX_LINK_STATUS,WIMAX_DEVICE_STATUS")
32
+ # TODO get the battery status
33
+ # URI.parse("http://#{@device_ip}/cgi-bin/webmain.cgi?act_battery_status&TYPE=BISCUIT&param=BATTERY_STATUS")
34
+ end
35
+
36
+ def parse(document)
37
+ data = {}
38
+ hash = MultiJson.decode(document, symbolize_keys: true)
39
+ hash.delete(:list)
40
+ hash.each do |k, v|
41
+ data[k] = if v.class == String && /^-?\d+$/ =~ v
42
+ Integer(v)
43
+ elsif v.class == Hash
44
+ idata = {}
45
+ v.each do |ik, iv|
46
+ idata[ik] = if iv.class == String && /^-?\d+$/ =~ iv
47
+ Integer(iv)
48
+ else
49
+ iv
50
+ end
51
+ end
52
+ idata
53
+ else
54
+ v
55
+ end
56
+ end
57
+ data
58
+ end
59
+
60
+ def parse_javascript_to_json(document)
61
+ document = document.downcase.split.join
62
+ document.gsub!(/'/, '"')
63
+ document.gsub!(/:(\d*),/, ':"\1",')
64
+ document.gsub!(/(\w*):"/, '"\1":"')
65
+ document.gsub!(/(\w*):{/, '"\1": {')
66
+ document.gsub!(/(\w*):\[/, '"\1": [')
67
+ document.gsub!(/":"/, '": "')
68
+ document.gsub!(/,/, ', ')
69
+ end
70
+ end
71
+ end
72
+ end
@@ -1,5 +1,7 @@
1
+ # encoding: utf-8
2
+
1
3
  module Biscuit
2
4
  module Monitor
3
- VERSION = "0.0.2"
5
+ VERSION = "0.0.3"
4
6
  end
5
7
  end
@@ -1,147 +1,25 @@
1
1
  # encoding: utf-8
2
2
 
3
- require 'biscuit-monitor/version'
4
- require 'colorize'
5
- require 'logger'
6
- require 'multi_json'
7
- require 'net/http'
8
- require 'thor'
9
- require 'uri'
10
-
11
3
  module Biscuit
12
4
  module Monitor
13
- trap("SIGINT") { throw :ctrl_c }
14
-
15
- class Monitor
16
- def initialize(device_ip)
17
- @logger = Logger.new('biscuit-monitor.log', 10, 1024000)
18
- @device_ip = device_ip
19
- @seconds = 3
20
- end
21
-
22
- def device_uri
23
- URI.parse("http://#{@device_ip}/cgi-bin/webmain.cgi?act=act_wimax_status&param=WIMAX_LINK_STATUS,WIMAX_DEVICE_STATUS")
24
- # TODO get the battery status
25
- # URI.parse("http://#{@device_ip}/cgi-bin/webmain.cgi?act_battery_status&TYPE=BISCUIT&param=BATTERY_STATUS")
26
- end
27
-
28
- def clear_last_message
29
- (@last_message || "").length.times { print "\b" }
30
- end
31
-
32
- def cinr_foreground_color(cinr)
33
- case
34
- when cinr > 24
35
- :green
36
- when (13..24).include?(cinr)
37
- :light_green
38
- when (8..12).include?(cinr)
39
- :yellow
40
- when (3..7).include?(cinr)
41
- :light_red
42
- when cinr < 3
43
- :red
44
- end
45
- end
46
-
47
- def rssi_foreground_color (rssi)
48
- case
49
- when rssi > -50
50
- :green
51
- when rssi < -100
52
- :red
53
- else
54
- :yellow
55
- end
56
- end
57
-
58
- def poll
59
- catch :ctrl_c do
60
- begin
61
- response = parse(scrub_response(Net::HTTP.get(device_uri)))
62
-
63
- cinr = Integer(response[:data][:cinr])
64
- rssi = Integer(response[:data][:rssi])
65
-
66
- message = "CINR: #{cinr}dBs".colorize(cinr_foreground_color(cinr))
67
- message << " ".uncolorize
68
- message << "RSSI: #{rssi}dBs".colorize(rssi_foreground_color(rssi))
69
-
70
- write message
71
- @logger.debug(response)
72
-
73
- rescue Errno::EHOSTUNREACH => err
74
-
75
- write "Cannot find the biscuit. Check your connection."
76
- @logger.error(err.inspect)
77
-
78
- rescue StandardError => err
79
-
80
- write "There was an error checking your biscuit. See the logfile for details."
81
- @logger.error(err.inspect)
82
-
83
- ensure
84
-
85
- sleep @seconds # TODO when error increase length of time until next check to avoid spamming error log
86
- end until false
87
-
88
- end
89
- end
90
-
91
- def write(message)
92
- clear_last_message
93
- print message
94
- @last_message = message
95
- end
96
-
97
5
 
6
+ %w< etc logger sequel sqlite3 >.each { |dep| require dep }
98
7
 
99
- def parse(document)
100
- data = {}
101
- hash = MultiJson.decode(document, symbolize_keys: true)
102
- hash.delete(:list)
103
- hash.each do |k,v|
104
- data[k] = if v.class == String && /^-?\d+$/ =~ v
105
- Integer(v)
106
- elsif v.class == Hash
107
- idata = {}
108
- v.each do |ik, iv|
109
- idata[ik] = if iv.class == String && /^-?\d+$/ =~ iv
110
- Integer(iv)
111
- else
112
- iv
113
- end
114
- end
115
- idata
116
- else
117
- v
118
- end
119
- end
120
- data
121
- end
8
+ HOME_DIR = Etc.getpwuid.dir
9
+ biscuit_monitor_root_dir = "#{HOME_DIR}/.biscuit-monitor"
10
+ Dir.mkdir(biscuit_monitor_root_dir) unless File.directory?(biscuit_monitor_root_dir)
11
+ biscuit_monitor_log_dir = "#{biscuit_monitor_root_dir}/log"
12
+ Dir.mkdir(biscuit_monitor_log_dir) unless File.directory?(biscuit_monitor_log_dir)
122
13
 
14
+ LOG_FILE = "#{biscuit_monitor_log_dir}/biscuit-monitor.log"
15
+ LOGGER = Logger.new(LOG_FILE, 10, 1024000)
123
16
 
124
- def scrub_response(document)
125
- document = document.split.join
126
- document.gsub!(/'/, '"')
127
- document.gsub!(/:(\d*),/, ':"\1",')
128
- document.gsub!(/(\w*):"/, '"\1":"')
129
- document.gsub!(/(\w*):{/, '"\1": {')
130
- document.gsub!(/(\w*):\[/, '"\1": [')
131
- document.gsub!(/":"/, '": "')
132
- document.gsub!(/,/, ', ')
133
- end
17
+ DB_CONN = Sequel.sqlite("#{biscuit_monitor_root_dir}/biscuit_monitor.db", loggers: [LOGGER])
134
18
 
135
- end
19
+ Sequel.extension :migration
20
+ Sequel::Migrator.apply(DB_CONN, File.expand_path(File.dirname(__FILE__)) + '/migrations')
136
21
 
137
- class CLI < Thor
138
- default_task :start
139
22
 
140
- desc "start", "Start monitoring your biscuit."
141
- method_option :device_ip, :default => "192.168.1.1", :aliases => "-d"
142
- def start
143
- Biscuit::Monitor::Monitor.new(options[:device_ip]).poll
144
- end
145
- end
23
+ %w< version cinr rssi access_point_scanner poller cli signal_strength >.each { |dep| require "biscuit-monitor/#{dep}" }
146
24
  end
147
25
  end
@@ -0,0 +1,19 @@
1
+ # encoding: utf-8
2
+
3
+ Sequel.migration do
4
+ change do
5
+ create_table :wi_max_statuses do
6
+ primary_key :id
7
+ Integer :cf # 2657000
8
+ Integer :cinr # 35
9
+ Integer :rssi # -56
10
+ Integer :tx_power # -11
11
+ String :bsid # "00:00:02:26:27:93"
12
+ String :dev_s # "dataconnected"
13
+ String :dummy09 # "xx"
14
+ String :wimax_device_status # "success"
15
+ String :wimax_link_status # "success"
16
+ String :captured_on
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,14 @@
1
+ # encoding: utf-8
2
+
3
+ Sequel.migration do
4
+ change do
5
+ create_table :wi_fi_access_points do
6
+ primary_key :id
7
+ String :ssid
8
+ String :ssid_name
9
+ Integer :rssi # -56
10
+ String :bssid # "00:00:02:26:27:93"
11
+ String :scanned_on
12
+ end
13
+ end
14
+ end
data/log/.gitkeep ADDED
File without changes