blink_tm 0.4.0 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: aee9807ee73b58a75f7c4c0d09fcda705f6d8087d51e3c5178ab0472ebd2faae
4
- data.tar.gz: d9156630e58cc9d4a41b26b7f0666f2abe565de91e8d1636bb8733920a9dfac0
3
+ metadata.gz: 290de1234088715cb8d957462afdd3a8f54c1c876f2b49ae35de7546cb352da8
4
+ data.tar.gz: e4a103649d1c326c86eb74931ca4a4796e150c186e9f6ef05926410d33ab31b2
5
5
  SHA512:
6
- metadata.gz: 204d49f580218bce9aed96a58a27a1f6fae07996e8d9a911749fec17a621b8c4cfcf2f081e71447e0d61788b22032713239c287d0b1194d6c4e6b048fdcd24a1
7
- data.tar.gz: 4c269cca6fb02329354483e4495a88da1270c6426a2756315eb8bc88ef0577466165d0f2239181a140bcf04042c04c4ae4b53c0ec53044034bd930954f98f606
6
+ metadata.gz: 7641d9d08838db8707dd75a327a417090ef0c0ecdddf0f458f34c5caeffb1406dde99272db73ad30d5e3ef288b348534b5834e09365ead845b4db34efa598c5d
7
+ data.tar.gz: 119773e1b395a46910267f6bee5f6c284a7bb3208953c40649c1d3981f31f6508f39b202d983a658ffedb7988b3dc4082be86c162df01b0063a0bf373352d4c9
data/exe/blink-tm CHANGED
@@ -1,19 +1,86 @@
1
1
  #!/usr/bin/env ruby
2
2
  require 'blink_tm'
3
3
 
4
- # Find Device running Blink Taskmanager
5
- dev = nil
4
+
5
+ if ARGV.any?(/^\-(\-version|v)$/)
6
+ puts "BlinkTM Version #{BlinkTM::BOLD}#{BlinkTM::VERSION}#{BlinkTM::RESET}"
7
+ exit
8
+ end
9
+
10
+ written_pid = false
11
+
12
+ BlinkTM::log "BlinkTM Version #{BlinkTM::VERSION}"
13
+ if File.exist?(BlinkTM::LOCKFILE)
14
+ BlinkTM.log 'error', "Lock file #{BlinkTM::LOCKFILE} already exists! If it's not running you might manually delete this to make blinktm work."
15
+
16
+ pid = IO.read(BlinkTM::LOCKFILE) if File.readable?(BlinkTM::LOCKFILE)
17
+ process_name = File.readable?("/proc/#{pid}/cmdline") ? IO.read("/proc/#{pid}/cmdline") : 'unknown'
18
+ stat = File.readable?("/proc/#{pid}/stat") ? IO.read("/proc/#{pid}/stat") : nil
19
+ state = stat ? stat.gsub(/\(.+\)/, '').split[1] : 'unknown'
20
+ friendly_state = case state
21
+ when ?S then 'Sleeping'
22
+ when ?I then 'Idle'
23
+ when ?Z then 'Zombie'
24
+ when ?R then 'Running'
25
+ when ?T then 'Stopped'
26
+ else 'Unknown'
27
+ end
28
+
29
+ BlinkTM.log 'info', <<~EOF
30
+ Process Details:
31
+ \t- ID: #{pid}
32
+ \t- Command: #{File.basename(process_name.gsub(?\u0000, ?\s))}
33
+ \t- Status: #{friendly_state}
34
+ EOF
35
+
36
+ exit!
37
+ else
38
+ begin
39
+ IO.write(BlinkTM::LOCKFILE, $$)
40
+ written_pid = true
41
+ rescue Exception
42
+ puts "Can't write to #{BlinkTM::LOCKFILE}"
43
+ exit!
44
+ end
45
+ end
46
+
6
47
  retry_count = 0
7
48
 
8
- while(!dev)
9
- dev = BlinkTM.find_device
49
+ # Find Device running Blink Taskmanager
50
+ dev = BlinkTM::find_device!
51
+ file = nil
52
+
53
+ begin
54
+ BlinkTM.start(dev) { |x| file = x }
55
+ rescue BlinkTM::SyncError
56
+ sleep 1
57
+ retry
58
+ rescue Errno::ENOENT, Errno::EIO, BlinkTM::NoDeviceError
59
+ file &.close
60
+ sleep 0.125
61
+ dev = BlinkTM::find_device!
62
+ retry
63
+ rescue Interrupt, SystemExit, SignalException
64
+ file &.close
65
+ File.delete(BlinkTM::LOCKFILE)
66
+ rescue Exception
67
+
68
+ mesg = <<~EOF
69
+ :: Time: #{Time.now.strftime("%A %d %B %Y, %H:%M:%S:%5N %p")}:
70
+ #{$!.full_message}
10
71
 
11
- if dev
12
- puts "#{BlinkTM::BOLD}#{BlinkTM::GREEN}:: #{Time.now.strftime('%H:%M:%S.%2N')}: Device discovered successfully. Path: #{dev}#{BlinkTM::RESET}"
72
+ Please notify these bugs to the issue tracker.
73
+ #{'-' * 70}
74
+ EOF
75
+
76
+ if File.writable?(BlinkTM::LOGFILE)
77
+ log = File.open(BlinkTM::LOGFILE, 'a')
78
+ log.write(mesg)
79
+ log.close
13
80
  else
14
- puts "#{BlinkTM::BOLD}#{BlinkTM::RED}:: #{Time.now.strftime('%H:%M:%S.%2N')}: No device found. Retrying #{retry_count += 1}#{BlinkTM::RESET}"
15
- sleep 0.5
81
+ puts "Logs aren't writable\n\nHere's a detailed message of what has happened:"
82
+ puts mesg
16
83
  end
84
+ ensure
85
+ File.delete(BlinkTM::LOCKFILE)
17
86
  end
18
-
19
- BlinkTM.start(dev)
@@ -7,7 +7,7 @@ VALUE setBaudRate(volatile VALUE obj, volatile VALUE dev, volatile VALUE speed)
7
7
  char *device = StringValuePtr(dev) ;
8
8
  unsigned int spd = NUM2UINT(speed) ;
9
9
 
10
- int serial_port = open(device, O_RDWR) ;
10
+ int serial_port = open(device, O_RDWR | O_NOCTTY) ;
11
11
  struct termios tty ;
12
12
 
13
13
  char status = tcgetattr(serial_port, &tty) ;
@@ -22,7 +22,10 @@ VALUE setBaudRate(volatile VALUE obj, volatile VALUE dev, volatile VALUE speed)
22
22
  -isig -icanon -iexten -echo -echoe -echok -echoctl -echoke
23
23
  */
24
24
 
25
- if(status != 0) return Qnil ;
25
+ if(status != 0) {
26
+ close(serial_port) ;
27
+ return Qnil ;
28
+ }
26
29
 
27
30
  tty.c_cflag &= ~CSIZE ;
28
31
  tty.c_cflag |= CS8 ;
@@ -46,18 +49,20 @@ VALUE setBaudRate(volatile VALUE obj, volatile VALUE dev, volatile VALUE speed)
46
49
  cfsetospeed(&tty, spd) ;
47
50
  status = tcsetattr(serial_port, TCSANOW, &tty) ;
48
51
 
49
- if (status == 0) return Qtrue ;
52
+ close(serial_port) ;
50
53
 
54
+ if (status == 0) return Qtrue ;
51
55
  return Qfalse ;
52
56
  }
53
57
 
54
58
  VALUE getBaudRate(volatile VALUE obj, volatile VALUE dev) {
55
59
  char *device = StringValuePtr(dev) ;
56
60
 
57
- int serial_port = open(device, O_RDWR) ;
61
+ int serial_port = open(device, O_RDWR | O_NOCTTY | O_NONBLOCK) ;
58
62
  struct termios tty ;
59
63
 
60
64
  char status = tcgetattr(serial_port, &tty) ;
65
+ close(serial_port) ;
61
66
 
62
67
  if(status == 0) {
63
68
  unsigned int in = cfgetispeed(&tty) ;
data/ext/crc32/crc32.c ADDED
@@ -0,0 +1,33 @@
1
+ /*
2
+ Source:
3
+ https://commandlinefanatic.com/cgi-bin/showarticle.cgi?article=art008
4
+
5
+ Note that this obeys the standard and matches with Ruby's Zlib.crc32(...)
6
+ */
7
+
8
+ #define CRC32_DIVISOR 0xEDB88320
9
+ #include "ruby.h"
10
+
11
+ static VALUE getCRC(volatile VALUE obj, volatile VALUE str) {
12
+ char *input = StringValuePtr(str) ;
13
+ unsigned char len = strlen(input) ;
14
+ unsigned long crc = 0xFFFFFFFF ;
15
+
16
+ for (unsigned char i = 0 ; i < len ; ++i) {
17
+ crc ^= input[i] ;
18
+
19
+ for (unsigned char k = 8 ; k ; --k) {
20
+ crc = crc & 1 ? (crc >> 1) ^ CRC32_DIVISOR : crc >> 1 ;
21
+ }
22
+ }
23
+
24
+ char buffer[11] ;
25
+ sprintf(buffer, "%lu", crc ^ 0xFFFFFFFF) ;
26
+
27
+ return rb_str_new_cstr(buffer) ;
28
+ }
29
+
30
+ void Init_crc32() {
31
+ VALUE blinktm = rb_define_module("BlinkTM") ;
32
+ rb_define_module_function(blinktm, "crc32", getCRC, 1) ;
33
+ }
@@ -0,0 +1,2 @@
1
+ require 'mkmf'
2
+ create_makefile 'blink_tm/crc32'
@@ -4,8 +4,6 @@
4
4
  module BlinkTM
5
5
  # Detect device
6
6
  def find_device
7
- dev = nil
8
-
9
7
  Dir.glob('/sys/bus/usb/devices/*').each { |x|
10
8
  v = File.join(x, 'idVendor')
11
9
  vendor = IO.read(v).strip if File.readable?(v)
@@ -14,39 +12,45 @@ module BlinkTM
14
12
  product = IO.read(p).strip if File.readable?(p)
15
13
 
16
14
  if vendor == '1a86' && product == '7523'
17
- puts "#{BOLD}#{GREEN}:: #{Time.now.strftime('%H:%M:%S.%2N')}: A potential device discovered: #{vendor}:#{product}#{RESET}"
15
+ log 'warn', "A potential device discovered: #{vendor}:#{product}"
18
16
 
19
17
  Dir.glob('/dev/ttyUSB[0-9]*').each { |x|
20
18
  if File.writable?(x)
21
- puts "#{BlinkTM::BOLD}#{BlinkTM::BLUE}:: #{Time.now.strftime('%H:%M:%S.%2N')}: Changing baudrate to 57600...#{BlinkTM::RESET}"
19
+ log 'success', "Changing baudrate to 57600..."
22
20
 
23
21
  if BlinkTM.set_baudrate(x, BlinkTM::BAUDRATE)
24
- puts "#{BlinkTM::BOLD}#{BlinkTM::GREEN}:: #{Time.now.strftime('%H:%M:%S.%2N')}: Successfully Changed baudrate to 57600...#{BlinkTM::RESET}"
22
+ log 'success', 'Successfully Changed baudrate to 57600...'
25
23
  else
26
- puts "#{BlinkTM::BOLD}#{BlinkTM::RED}:: #{Time.now.strftime('%H:%M:%S.%2N')}: Cannot change the baudrate#{BlinkTM::RESET}"
24
+ log 'error', 'Cannot change the baudrate'
27
25
  end
28
26
  else
29
- "#{BOLD}#{RED}:: #{Time.now.strftime('%H:%M:%S.%2N')}: No permission granted to change Baudrate#{RESET}"
27
+ log 'error', 'No permission granted to change Baudrate'
30
28
  end
31
29
 
32
30
  if File.readable?(x)
33
31
  begin
34
- if File.open(x).readpartial(30).to_s.scrub.include?("BTM")
35
- puts "#{BOLD}#{ORANGE}:: #{Time.now.strftime('%H:%M:%S.%2N')}: Multiple Blink Task "\
36
- "Manager Hardware Found! "\
37
- "Selecting: #{vendor}:#{product}#{RESET}" if dev
38
-
39
- dev = x
40
- end
32
+ return x if File.open(x).read_nonblock(30).to_s.scrub.include?("BTM")
41
33
  rescue EOFError
42
- sleep 0.125
34
+ sleep 0.05
43
35
  retry
36
+ rescue Errno::ENOENT, Errno::EIO
44
37
  end
45
38
  end
46
39
  }
47
40
  end
48
41
  }
49
42
 
43
+ nil
44
+ end
45
+
46
+ @@retry_count = 0
47
+ def find_device!
48
+ while(!(dev = BlinkTM.find_device))
49
+ log 'error', "No device found. Retrying #{@@retry_count += 1}"
50
+ sleep 0.5
51
+ end
52
+
53
+ log 'success', "Device discovered successfully. Path: #{dev}#{BlinkTM::RESET}"
50
54
  dev
51
55
  end
52
56
 
@@ -79,7 +83,7 @@ module BlinkTM
79
83
  Thread.new {
80
84
  while true
81
85
  _cpu_u = LS::CPU.total_usage(POLLING).to_f
82
- cpu_u = _cpu_u.nan? ? 0 : _cpu_u.to_i
86
+ cpu_u = _cpu_u.nan? ? 255 : _cpu_u.to_i
83
87
  end
84
88
  }
85
89
 
@@ -102,91 +106,107 @@ module BlinkTM
102
106
  end
103
107
  }
104
108
 
105
- begin
106
- raise NoDeviceError unless device
107
-
108
- in_sync = false
109
- fd = IO.sysopen(device, Fcntl::O_RDWR)
110
- file = IO.open(fd)
109
+ prev_crc32 = ''
110
+ raise NoDeviceError unless device
111
111
 
112
- until in_sync
113
- # Clear out any extra zombie bits
114
- file.syswrite(?~)
115
- # Start the device
116
- file.syswrite(?#)
117
- file.flush
112
+ in_sync = false
118
113
 
119
- sleep 0.125
114
+ fd = IO.sysopen(
115
+ device,
116
+ Fcntl::O_RDWR | Fcntl::O_NOCTTY | Fcntl::O_NONBLOCK | Fcntl::O_TRUNC
117
+ )
120
118
 
121
- begin
122
- if file.readpartial(8000).include?(?~)
123
- in_sync = true
124
- break
125
- end
126
- rescue EOFError
127
- sleep 0.05
128
- retry
129
- end
130
- end
131
-
132
- puts "#{BlinkTM::BOLD}#{BlinkTM::GREEN}:: #{Time.now.strftime('%H:%M:%S.%2N')}: Device ready!#{BlinkTM::RESET}"
133
-
134
- while true
135
- # cpu(01234) memUsed(999993) swapUsed(999992) io_active(0)
136
- # netUpload(999991) netDownload(999990)
137
- # disktotal(999990) diskused(999990)
119
+ file = IO.open(fd)
120
+ yield file
138
121
 
139
- memstat = LS::Memory.stat
140
- mem_u = memstat[:used].to_i.*(1024).*(100).fdiv(memstat[:total].to_i * 1024).round
122
+ until in_sync
123
+ # Clear out any extra zombie bits
124
+ file.syswrite(?~.freeze)
125
+ # Start the device
126
+ file.syswrite(?#.freeze)
127
+ file.flush
141
128
 
142
- swapstat = LS::Swap.stat
143
- swap_u = swapstat[:used].to_i.*(1024).*(100).fdiv(swapstat[:total].to_i * 1024).round
129
+ sleep 0.125
144
130
 
145
- # Output has to be exactly this long. If not, blink-taskmanager shows invalid result.
146
- # No string is split inside blink-task manager, it just depends on the string length.
147
- #
148
- # cpu(100) memUsed(100) swapUsed(100)
149
- # netDownload(9991) netUpload(9991)
150
- # ioWrite(9991) ioRead(9991)
131
+ begin
132
+ if file.read_nonblock(8000).include?(?~)
133
+ in_sync = true
134
+ break
135
+ end
136
+ rescue EOFError
137
+ sleep 0.05
138
+ retry
139
+ end
140
+ end
151
141
 
152
- # Debugging string
153
- # str = "#{"%03d" % cpu_u} #{"%03d" % mem_u} #{"%03d" % swap_u} "\
154
- # "#{convert_bytes(net_u)} #{convert_bytes(net_d)} "\
155
- # "#{convert_bytes(io_r)} #{convert_bytes(io_w)}"
142
+ sync_error_count = 0
143
+
144
+ log 'success', 'Device ready!'
145
+ file.read
146
+
147
+ while true
148
+ # cpu(01234) memUsed(999993) swapUsed(999992) io_active(0)
149
+ # netUpload(999991) netDownload(999990)
150
+ # disktotal(999990) diskused(999990)
151
+
152
+ memstat = LS::Memory.stat
153
+ _mem_u = memstat[:used].to_i.*(1024).*(100).fdiv(memstat[:total].to_i * 1024)
154
+ mem_u = _mem_u.nan? ? 255 : _mem_u.round
155
+
156
+ swapstat = LS::Swap.stat
157
+ _swap_u = swapstat[:used].to_i.*(1024).*(100).fdiv(swapstat[:total].to_i * 1024)
158
+ swap_u = _swap_u.nan? ? 255 : _swap_u.round
159
+
160
+ # Output has to be exactly this long. If not, blink-taskmanager shows invalid result.
161
+ # No string is split inside blink-task manager, it just depends on the string length.
162
+ #
163
+ # cpu(100) memUsed(100) swapUsed(100)
164
+ # netDownload(9991) netUpload(9991)
165
+ # ioWrite(9991) ioRead(9991)
166
+
167
+ # Debugging string
168
+ # str = "#{"%03d" % cpu_u} #{"%03d" % mem_u} #{"%03d" % swap_u} "\
169
+ # "#{convert_bytes(net_u)} #{convert_bytes(net_d)} "\
170
+ # "#{convert_bytes(io_r)} #{convert_bytes(io_w)}"
171
+
172
+ str = "!##{"%03d" % cpu_u}#{"%03d" % mem_u}#{"%03d" % swap_u}"\
173
+ "#{convert_bytes(net_u)}#{convert_bytes(net_d)}"\
174
+ "#{convert_bytes(io_r)}#{convert_bytes(io_w)}1~"
175
+
176
+ # Rescuing from suspend
177
+ file.syswrite(str)
178
+ file.flush
179
+ crc32 = file.read.scrub![/\d+/]
180
+
181
+ unless crc32 == prev_crc32 || prev_crc32.empty?
182
+ raise SyncError if sync_error_count > 1
183
+ sync_error_count += 1
184
+ else
185
+ sync_error_count = 0 unless sync_error_count == 0
186
+ end
156
187
 
157
- str = "!##{"%03d" % cpu_u}#{"%03d" % mem_u}#{"%03d" % swap_u}"\
158
- "#{convert_bytes(net_u)}#{convert_bytes(net_d)}"\
159
- "#{convert_bytes(io_r)}#{convert_bytes(io_w)}1~"
188
+ prev_crc32 = BlinkTM.crc32(str[2..-2])
189
+ sleep REFRESH
190
+ end
160
191
 
161
- # Rescuing from suspend
162
- file.syswrite(str)
163
- file.flush
192
+ unless device
193
+ puts "#{BlinkTM::BOLD}#{BlinkTM::RED}:: #{Time.now.strftime('%H:%M:%S.%2N')}: Error establishing connection. Don't worry if this is a valid device. Retrying...#{BlinkTM::RESET}"
194
+ sleep 0.1
195
+ end
196
+ end
164
197
 
165
- sleep REFRESH
166
- end
167
- rescue Interrupt, SystemExit, SignalException
168
- file &.close
169
- exit 0
170
- rescue Errno::ENOENT, BlinkTM::NoDeviceError
171
- file &.close
172
- device = find_device
173
-
174
- unless device
175
- puts "#{BlinkTM::BOLD}#{BlinkTM::RED}:: #{Time.now.strftime('%H:%M:%S.%2N')}: Error establishing connection. Don't worry if this is a valid device. Retrying...#{BlinkTM::RESET}"
176
- sleep 0.1
177
- end
198
+ def log(type, message = nil)
199
+ message, type = type, nil if type && !message
178
200
 
179
- retry
180
- rescue BlinkTM::DeviceNotReady
181
- file &.close
182
- sleep 0.1
183
- retry
184
- rescue Exception
185
- puts $!.full_message
186
- file &.close
187
- sleep 0.1
188
- retry
201
+ colour = case type
202
+ when 0, 'fatal', 'error' then BlinkTM::RED
203
+ when 1, 'warn' then BlinkTM::ORANGE
204
+ when 2, 'info' then BlinkTM::BLUE
205
+ when 3, 'success', 'ok' then BlinkTM::GREEN
206
+ else ''
189
207
  end
208
+
209
+ puts "#{BlinkTM::BOLD}#{colour}:: #{Time.now.strftime('%H:%M:%S.%2N')}: #{message}#{BlinkTM::RESET}"
190
210
  end
191
211
 
192
212
  extend(self)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module BlinkTM
4
- VERSION = "0.4.0"
4
+ VERSION = "2.1.0"
5
5
  end
data/lib/blink_tm.rb CHANGED
@@ -6,18 +6,19 @@ $-v = true
6
6
 
7
7
  module BlinkTM
8
8
  # Important Constants
9
- BAUDRATE = BlinkTM::B57600
9
+ BAUDRATE = BlinkTM::B38400
10
10
  SCANID = 'BTM'
11
11
 
12
12
  # POLLING time, how often should CPU, Net, IO usages should be updated.
13
13
  # Should always be a float.
14
- POLLING = 0.375
14
+ POLLING = 0.250
15
15
 
16
16
  # Refresh time, how often the main loop should run
17
17
  REFRESH = 0.5
18
18
 
19
19
  # Errors
20
20
  NoDeviceError = Class.new(StandardError)
21
+ SyncError = Class.new(StandardError)
21
22
  DeviceNotReady = Class.new(StandardError)
22
23
 
23
24
  # Units
@@ -33,6 +34,8 @@ module BlinkTM
33
34
  ORANGE = "\e[38;2;245;155;20m"
34
35
  BOLD = "\e[1m"
35
36
  RESET = "\e[0m"
37
+ LOCKFILE = '/tmp/blinktaskmanager.pid'
38
+ LOGFILE = '/tmp/blinktaskmanager.err.log'
36
39
 
37
40
  # Other constants
38
41
  ROOT_DEV = ::LinuxStat::Mounts.root
@@ -47,3 +50,4 @@ end
47
50
  require 'blink_tm/version'
48
51
  require 'fcntl'
49
52
  require 'blink_tm/blink_tm'
53
+ require 'blink_tm/crc32'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: blink_tm
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 2.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sourav Goswami
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-06-07 00:00:00.000000000 Z
11
+ date: 2022-03-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: linux_stat
@@ -31,11 +31,14 @@ executables:
31
31
  - blink-tm
32
32
  extensions:
33
33
  - ext/baudrate/extconf.rb
34
+ - ext/crc32/extconf.rb
34
35
  extra_rdoc_files: []
35
36
  files:
36
37
  - exe/blink-tm
37
38
  - ext/baudrate/baudrate.c
38
39
  - ext/baudrate/extconf.rb
40
+ - ext/crc32/crc32.c
41
+ - ext/crc32/extconf.rb
39
42
  - lib/blink_tm.rb
40
43
  - lib/blink_tm/blink_tm.rb
41
44
  - lib/blink_tm/version.rb
@@ -58,7 +61,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
58
61
  - !ruby/object:Gem::Version
59
62
  version: '0'
60
63
  requirements: []
61
- rubygems_version: 3.2.18
64
+ rubygems_version: 3.3.8
62
65
  signing_key:
63
66
  specification_version: 4
64
67
  summary: A controller for Arduino OLED System Monitor, Blink Task Manager