-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathbluethermd
executable file
·129 lines (110 loc) · 2.74 KB
/
bluethermd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
#!/usr/bin/env ruby
repo_lib = File.dirname($0) + '/../lib/ruby'
if File.directory?(repo_lib)
$: << repo_lib
end
require 'bluetherm'
require 'optparse'
require 'pathname'
$0 = 'bluethermd'
@sqlite3_loaded = false
begin
require 'sqlite3'
@sqlite3_loaded = true
rescue LoadError
end
STDOUT.sync = true
STDERR.sync = true
@device_path = '/dev/rfcomm0'
@is_print = true
@sqlite_path = nil
@poll_interval = 10
OptionParser.new do |opts|
opts.on('--device=PATH', 'Bluetooth serial device to connect to') \
{ |v| @device_path = v }
opts.on('--update-interval=SECONDS',
"Log rate, default is #{@poll_interval}") \
{ |v| @poll_interval = v.to_i }
opts.on('--quiet', "Suppress terminal output") \
{ |v| @is_print = false }
if @sqlite3_loaded
opts.on('--sqlite-path=PATH', 'Temperatures are in milli-Celsius') \
{ |v| @sqlite_path = Pathname.new(v) }
else
opts.separator('(SQLite3 support disabled; sqlite3.rb not found!)')
end
end.parse!
unless @is_print or @sqlite_path
opts.abort("choose at least one of print-to-stdout or log-to-sqlite")
end
def log(message)
if @is_print
puts "bluethermd: #{message}"
end
end
#
# Helper for writing sensor values to an SQLite3 database.
#
class BlueTherm::Database # :nodoc:
def initialize(path, logger=nil)
@conn = SQLite3::Database.new(path.to_s)
@logger = logger
@last = {}
@handles = {}
end
def record!(sensor_n, temperature)
return if temperature == @last[sensor_n]
@handles[sensor_n] ||= begin
table = "sensor_#{sensor_n}"
@conn.execute "
CREATE TABLE IF NOT EXISTS #{table} (
epoch INTEGER,
mC INTEGER
)
"
@conn.prepare("INSERT INTO #{table} (epoch, mC) VALUES (?, ?)")
end
pass = 1
begin
@handles[sensor_n].execute(Time.now.to_i, (temperature * 1000).to_i)
@last[sensor_n] = temperature
rescue SQLite3::BusyException => ex
if pass > 3
log "database is too busy; skipping update: #{ex.message}"
else
log "database is busy; retrying..."
pass += 1
sleep 0.1
retry
end
end
end
def log(message)
@logger.call(message) if @logger
end
end
if @sqlite_path
unless @sqlite_path.exist?
@sqlite_path.dirname.mkpath
end
@db = BlueTherm::Database.new(@sqlite_path, method(:log))
end
begin
BlueTherm.poll(@device_path, @poll_interval, method(:log)) do |t1, t2|
if @is_print
ansi, reset = nil, nil
if STDOUT.tty?
ansi = "\033[01m"
reset = "\033[0m"
end
puts "#{ansi}t1=#{t1.round(2)} t2=#{t2.round(2)}#{reset}"
end
if @db
@db.record!(1, t1)
@db.record!(2, t2)
end
end
rescue SignalException => ex
STDERR.puts "received #{ex}"
exit
end