sappho-heatmiser-proxy 0.1.2 → 0.1.3
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.
- data/bin/sappho-heatmiser-proxy +12 -12
- data/lib/sappho-heatmiser-proxy/command_queue.rb +60 -60
- data/lib/sappho-heatmiser-proxy/heatmiser.rb +92 -96
- data/lib/sappho-heatmiser-proxy/heatmiser_client.rb +78 -78
- data/lib/sappho-heatmiser-proxy/heatmiser_crc.rb +48 -48
- data/lib/sappho-heatmiser-proxy/heatmiser_status.rb +136 -131
- data/lib/sappho-heatmiser-proxy/system_configuration.rb +34 -48
- data/lib/sappho-heatmiser-proxy/version.rb +18 -18
- data/lib/sappho-heatmiser-proxy.rb +35 -44
- metadata +10 -59
- data/lib/sappho-heatmiser-proxy/model/heatmiser_log.rb +0 -29
data/bin/sappho-heatmiser-proxy
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
#!/usr/bin/env ruby
|
|
2
|
-
|
|
3
|
-
# See https://github.com/sappho/sappho-heatmiser-proxy/wiki for project documentation.
|
|
4
|
-
# This software is licensed under the GNU Affero General Public License, version 3.
|
|
5
|
-
# See http://www.gnu.org/licenses/agpl.html for full details of the license terms.
|
|
6
|
-
# Copyright 2012 Andrew Heald.
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
require 'sappho-heatmiser-proxy'
|
|
11
|
-
|
|
12
|
-
Sappho::Heatmiser::Proxy::CommandLine.process
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
|
|
3
|
+
# See https://github.com/sappho/sappho-heatmiser-proxy/wiki for project documentation.
|
|
4
|
+
# This software is licensed under the GNU Affero General Public License, version 3.
|
|
5
|
+
# See http://www.gnu.org/licenses/agpl.html for full details of the license terms.
|
|
6
|
+
# Copyright 2012 Andrew Heald.
|
|
7
|
+
|
|
8
|
+
$:.unshift File.join(File.dirname(__FILE__), *%w[.. lib])
|
|
9
|
+
|
|
10
|
+
require 'sappho-heatmiser-proxy'
|
|
11
|
+
|
|
12
|
+
Sappho::Heatmiser::Proxy::CommandLine.process
|
|
@@ -1,60 +1,60 @@
|
|
|
1
|
-
# See https://github.com/sappho/sappho-heatmiser-proxy/wiki for project documentation.
|
|
2
|
-
# This software is licensed under the GNU Affero General Public License, version 3.
|
|
3
|
-
# See http://www.gnu.org/licenses/agpl.html for full details of the license terms.
|
|
4
|
-
# Copyright 2012 Andrew Heald.
|
|
5
|
-
|
|
6
|
-
module Sappho
|
|
7
|
-
module Heatmiser
|
|
8
|
-
module Proxy
|
|
9
|
-
|
|
10
|
-
require 'singleton'
|
|
11
|
-
require 'thread'
|
|
12
|
-
require 'sappho-basics/auto_flush_log'
|
|
13
|
-
|
|
14
|
-
class CommandQueue
|
|
15
|
-
|
|
16
|
-
include Singleton, Sappho::LogUtilities
|
|
17
|
-
|
|
18
|
-
def initialize
|
|
19
|
-
@queue = []
|
|
20
|
-
@mutex = Mutex.new
|
|
21
|
-
@log = Sappho::ApplicationAutoFlushLog.instance
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
def push clientIP, command
|
|
25
|
-
@log.info "client #{clientIP} requests command: #{hexString command}"
|
|
26
|
-
@mutex.synchronize do
|
|
27
|
-
@queue << {
|
|
28
|
-
:clientIP => clientIP,
|
|
29
|
-
:command => command.dup
|
|
30
|
-
}
|
|
31
|
-
end
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
def get
|
|
35
|
-
command = nil
|
|
36
|
-
@mutex.synchronize do
|
|
37
|
-
if @queue.size > 0
|
|
38
|
-
queue = @queue[0]
|
|
39
|
-
command = queue[:command].dup
|
|
40
|
-
@log.info "client #{queue[:clientIP]} command executing: #{hexString command}"
|
|
41
|
-
end
|
|
42
|
-
end
|
|
43
|
-
command
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
def completed
|
|
47
|
-
@mutex.synchronize do
|
|
48
|
-
if @queue.size > 0
|
|
49
|
-
queue = @queue[0]
|
|
50
|
-
@log.info "client #{queue[:clientIP]} command completed: #{hexString queue[:command]}"
|
|
51
|
-
@queue.shift
|
|
52
|
-
end
|
|
53
|
-
end
|
|
54
|
-
end
|
|
55
|
-
|
|
56
|
-
end
|
|
57
|
-
|
|
58
|
-
end
|
|
59
|
-
end
|
|
60
|
-
end
|
|
1
|
+
# See https://github.com/sappho/sappho-heatmiser-proxy/wiki for project documentation.
|
|
2
|
+
# This software is licensed under the GNU Affero General Public License, version 3.
|
|
3
|
+
# See http://www.gnu.org/licenses/agpl.html for full details of the license terms.
|
|
4
|
+
# Copyright 2012 Andrew Heald.
|
|
5
|
+
|
|
6
|
+
module Sappho
|
|
7
|
+
module Heatmiser
|
|
8
|
+
module Proxy
|
|
9
|
+
|
|
10
|
+
require 'singleton'
|
|
11
|
+
require 'thread'
|
|
12
|
+
require 'sappho-basics/auto_flush_log'
|
|
13
|
+
|
|
14
|
+
class CommandQueue
|
|
15
|
+
|
|
16
|
+
include Singleton, Sappho::LogUtilities
|
|
17
|
+
|
|
18
|
+
def initialize
|
|
19
|
+
@queue = []
|
|
20
|
+
@mutex = Mutex.new
|
|
21
|
+
@log = Sappho::ApplicationAutoFlushLog.instance
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def push clientIP, command
|
|
25
|
+
@log.info "client #{clientIP} requests command: #{hexString command}"
|
|
26
|
+
@mutex.synchronize do
|
|
27
|
+
@queue << {
|
|
28
|
+
:clientIP => clientIP,
|
|
29
|
+
:command => command.dup
|
|
30
|
+
}
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def get
|
|
35
|
+
command = nil
|
|
36
|
+
@mutex.synchronize do
|
|
37
|
+
if @queue.size > 0
|
|
38
|
+
queue = @queue[0]
|
|
39
|
+
command = queue[:command].dup
|
|
40
|
+
@log.info "client #{queue[:clientIP]} command executing: #{hexString command}"
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
command
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def completed
|
|
47
|
+
@mutex.synchronize do
|
|
48
|
+
if @queue.size > 0
|
|
49
|
+
queue = @queue[0]
|
|
50
|
+
@log.info "client #{queue[:clientIP]} command completed: #{hexString queue[:command]}"
|
|
51
|
+
@queue.shift
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
@@ -1,96 +1,92 @@
|
|
|
1
|
-
# See https://github.com/sappho/sappho-heatmiser-proxy/wiki for project documentation.
|
|
2
|
-
# This software is licensed under the GNU Affero General Public License, version 3.
|
|
3
|
-
# See http://www.gnu.org/licenses/agpl.html for full details of the license terms.
|
|
4
|
-
# Copyright 2012 Andrew Heald.
|
|
5
|
-
|
|
6
|
-
module Sappho
|
|
7
|
-
module Heatmiser
|
|
8
|
-
module Proxy
|
|
9
|
-
|
|
10
|
-
require 'sappho-heatmiser-proxy/heatmiser_crc'
|
|
11
|
-
require 'sappho-heatmiser-proxy/heatmiser_status'
|
|
12
|
-
require 'sappho-basics/auto_flush_log'
|
|
13
|
-
require 'sappho-heatmiser-proxy/command_queue'
|
|
14
|
-
require 'sappho-heatmiser-proxy/system_configuration'
|
|
15
|
-
require 'sappho-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
dayOfWeek =
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
timeNow.
|
|
43
|
-
timeNow.
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
timeNow.
|
|
47
|
-
timeNow.
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
reply
|
|
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
|
-
end
|
|
95
|
-
end
|
|
96
|
-
end
|
|
1
|
+
# See https://github.com/sappho/sappho-heatmiser-proxy/wiki for project documentation.
|
|
2
|
+
# This software is licensed under the GNU Affero General Public License, version 3.
|
|
3
|
+
# See http://www.gnu.org/licenses/agpl.html for full details of the license terms.
|
|
4
|
+
# Copyright 2012 Andrew Heald.
|
|
5
|
+
|
|
6
|
+
module Sappho
|
|
7
|
+
module Heatmiser
|
|
8
|
+
module Proxy
|
|
9
|
+
|
|
10
|
+
require 'sappho-heatmiser-proxy/heatmiser_crc'
|
|
11
|
+
require 'sappho-heatmiser-proxy/heatmiser_status'
|
|
12
|
+
require 'sappho-basics/auto_flush_log'
|
|
13
|
+
require 'sappho-heatmiser-proxy/command_queue'
|
|
14
|
+
require 'sappho-heatmiser-proxy/system_configuration'
|
|
15
|
+
require 'sappho-socket/safe_socket'
|
|
16
|
+
|
|
17
|
+
class Heatmiser
|
|
18
|
+
|
|
19
|
+
include Sappho::LogUtilities
|
|
20
|
+
|
|
21
|
+
def monitor
|
|
22
|
+
status = HeatmiserStatus.instance
|
|
23
|
+
queue = CommandQueue.instance
|
|
24
|
+
log = Sappho::ApplicationAutoFlushLog.instance
|
|
25
|
+
config = SystemConfiguration.instance
|
|
26
|
+
desc = "heatmiser at #{config.heatmiserHostname}:#{config.heatmiserPort}"
|
|
27
|
+
queryCommand = HeatmiserCRC.new([0x93, 0x0B, 0x00, config.pinLo, config.pinHi, 0x00, 0x00, 0xFF, 0xFF]).appendCRC
|
|
28
|
+
socket = Sappho::Socket::SafeSocket.new 5
|
|
29
|
+
timestamp = Time.now - config.sampleDelay
|
|
30
|
+
loop do
|
|
31
|
+
begin
|
|
32
|
+
command = nil
|
|
33
|
+
if queuedCommand = queue.get
|
|
34
|
+
command = queuedCommand
|
|
35
|
+
else
|
|
36
|
+
if status.get{status.valid ? status.deviceTimeOffset : 0.0}.abs > 150
|
|
37
|
+
timeNow = Time.now
|
|
38
|
+
dayOfWeek = timeNow.wday
|
|
39
|
+
dayOfWeek = 7 if dayOfWeek == 0
|
|
40
|
+
command = HeatmiserCRC.new([0xA3, 0x12, 0x00, config.pinLo, config.pinHi, 0x01, 0x2B, 0x00, 0x07,
|
|
41
|
+
timeNow.year - 2000,
|
|
42
|
+
timeNow.month,
|
|
43
|
+
timeNow.day,
|
|
44
|
+
dayOfWeek,
|
|
45
|
+
timeNow.hour,
|
|
46
|
+
timeNow.min,
|
|
47
|
+
timeNow.sec]).appendCRC
|
|
48
|
+
log.info "clock correction: #{hexString command}"
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
unless command
|
|
52
|
+
command = queryCommand if (Time.now - timestamp) >= config.sampleDelay
|
|
53
|
+
end
|
|
54
|
+
if command
|
|
55
|
+
log.debug "sending command: #{hexString command}" if log.debug?
|
|
56
|
+
socket.close # just in case it wasn't last time around
|
|
57
|
+
socket.open config.heatmiserHostname, config.heatmiserPort
|
|
58
|
+
socket.settle 0.1
|
|
59
|
+
startTime = Time.now
|
|
60
|
+
socket.write command.pack('c*')
|
|
61
|
+
reply = socket.read(81).unpack('c*')
|
|
62
|
+
timestamp = Time.now
|
|
63
|
+
socket.settle 0.1
|
|
64
|
+
socket.close
|
|
65
|
+
log.debug "reply: #{hexString reply}" if log.debug?
|
|
66
|
+
crcHi = reply.pop & 0xFF
|
|
67
|
+
crcLo = reply.pop & 0xFF
|
|
68
|
+
crc = HeatmiserCRC.new reply
|
|
69
|
+
if (reply[0] & 0xFF) == 0x94 and reply[1] == 0x51 and reply[2] == 0 and
|
|
70
|
+
crc.crcHi == crcHi and crc.crcLo == crcLo
|
|
71
|
+
reply << crcLo << crcHi
|
|
72
|
+
status.set reply, timestamp, (timestamp - startTime) do
|
|
73
|
+
queue.completed if queuedCommand
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
rescue Timeout::Error
|
|
78
|
+
status.invalidate
|
|
79
|
+
log.info "#{desc} is not responding - assuming connection down"
|
|
80
|
+
rescue => error
|
|
81
|
+
status.invalidate
|
|
82
|
+
log.error error
|
|
83
|
+
end
|
|
84
|
+
socket.settle 2
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
end
|
|
@@ -1,78 +1,78 @@
|
|
|
1
|
-
# See https://github.com/sappho/sappho-heatmiser-proxy/wiki for project documentation.
|
|
2
|
-
# This software is licensed under the GNU Affero General Public License, version 3.
|
|
3
|
-
# See http://www.gnu.org/licenses/agpl.html for full details of the license terms.
|
|
4
|
-
# Copyright 2012 Andrew Heald.
|
|
5
|
-
|
|
6
|
-
module Sappho
|
|
7
|
-
module Heatmiser
|
|
8
|
-
module Proxy
|
|
9
|
-
|
|
10
|
-
require 'sappho-basics/auto_flush_log'
|
|
11
|
-
require 'sappho-heatmiser-proxy/heatmiser_status'
|
|
12
|
-
require 'sappho-heatmiser-proxy/command_queue'
|
|
13
|
-
require 'sappho-heatmiser-proxy/system_configuration'
|
|
14
|
-
|
|
15
|
-
class HeatmiserClient
|
|
16
|
-
|
|
17
|
-
include Sappho::LogUtilities
|
|
18
|
-
|
|
19
|
-
def initialize client, ip
|
|
20
|
-
@ip = ip
|
|
21
|
-
@client = client
|
|
22
|
-
@status = HeatmiserStatus.instance
|
|
23
|
-
@log = Sappho::ApplicationAutoFlushLog.instance
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
def communicate
|
|
27
|
-
config = SystemConfiguration.instance
|
|
28
|
-
active = true
|
|
29
|
-
while active do
|
|
30
|
-
begin
|
|
31
|
-
command = read 5
|
|
32
|
-
if command == 'check'
|
|
33
|
-
reply = @status.get {
|
|
34
|
-
@status.timeSinceLastValid > 60 ?
|
|
35
|
-
'error: no response from heatmiser unit in last minute' :
|
|
36
|
-
@status.valid ? 'ok' : 'error: last response from heatmiser unit was invalid'
|
|
37
|
-
}
|
|
38
|
-
@log.info "client #{@ip} checking status - reply: #{reply}"
|
|
39
|
-
@client.write "#{reply}\r\n"
|
|
40
|
-
active = false
|
|
41
|
-
else
|
|
42
|
-
command = command.unpack('c*')
|
|
43
|
-
@log.debug "header: #{hexString command}" if @log.debug?
|
|
44
|
-
raise ClientDataError, "invalid pin" unless (command[3] & 0xFF) == config.pinLo and (command[4] & 0xFF) == config.pinHi
|
|
45
|
-
packetSize = (command[1] & 0xFF) | ((command[2] << 8) & 0xFF00)
|
|
46
|
-
raise ClientDataError, "invalid packet size" if packetSize < 7 or packetSize > 128
|
|
47
|
-
command += read(packetSize - 5).unpack('c*')
|
|
48
|
-
CommandQueue.instance.push @ip, command unless (command[0] & 0xFF) == 0x93
|
|
49
|
-
@status.get { @client.write @status.raw.pack('c*') if @status.valid }
|
|
50
|
-
@log.info "command received from client #{@ip} so it is alive"
|
|
51
|
-
end
|
|
52
|
-
rescue Timeout::Error
|
|
53
|
-
@log.info "timeout on client #{@ip} so presuming it dormant"
|
|
54
|
-
active = false
|
|
55
|
-
rescue ClientDataError => error
|
|
56
|
-
@log.info "data error from client #{@ip}: #{error.message}"
|
|
57
|
-
active = false
|
|
58
|
-
rescue => error
|
|
59
|
-
@log.error error
|
|
60
|
-
active = false
|
|
61
|
-
end
|
|
62
|
-
end
|
|
63
|
-
end
|
|
64
|
-
|
|
65
|
-
def read size
|
|
66
|
-
data = @client.read size
|
|
67
|
-
raise ClientDataError, "nothing received so presuming it has disconnected" unless data and data.size == size
|
|
68
|
-
data
|
|
69
|
-
end
|
|
70
|
-
|
|
71
|
-
class ClientDataError < Interrupt
|
|
72
|
-
end
|
|
73
|
-
|
|
74
|
-
end
|
|
75
|
-
|
|
76
|
-
end
|
|
77
|
-
end
|
|
78
|
-
end
|
|
1
|
+
# See https://github.com/sappho/sappho-heatmiser-proxy/wiki for project documentation.
|
|
2
|
+
# This software is licensed under the GNU Affero General Public License, version 3.
|
|
3
|
+
# See http://www.gnu.org/licenses/agpl.html for full details of the license terms.
|
|
4
|
+
# Copyright 2012 Andrew Heald.
|
|
5
|
+
|
|
6
|
+
module Sappho
|
|
7
|
+
module Heatmiser
|
|
8
|
+
module Proxy
|
|
9
|
+
|
|
10
|
+
require 'sappho-basics/auto_flush_log'
|
|
11
|
+
require 'sappho-heatmiser-proxy/heatmiser_status'
|
|
12
|
+
require 'sappho-heatmiser-proxy/command_queue'
|
|
13
|
+
require 'sappho-heatmiser-proxy/system_configuration'
|
|
14
|
+
|
|
15
|
+
class HeatmiserClient
|
|
16
|
+
|
|
17
|
+
include Sappho::LogUtilities
|
|
18
|
+
|
|
19
|
+
def initialize client, ip
|
|
20
|
+
@ip = ip
|
|
21
|
+
@client = client
|
|
22
|
+
@status = HeatmiserStatus.instance
|
|
23
|
+
@log = Sappho::ApplicationAutoFlushLog.instance
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def communicate
|
|
27
|
+
config = SystemConfiguration.instance
|
|
28
|
+
active = true
|
|
29
|
+
while active do
|
|
30
|
+
begin
|
|
31
|
+
command = read 5
|
|
32
|
+
if command == 'check'
|
|
33
|
+
reply = @status.get {
|
|
34
|
+
@status.timeSinceLastValid > 60 ?
|
|
35
|
+
'error: no response from heatmiser unit in last minute' :
|
|
36
|
+
@status.valid ? 'ok' : 'error: last response from heatmiser unit was invalid'
|
|
37
|
+
}
|
|
38
|
+
@log.info "client #{@ip} checking status - reply: #{reply}"
|
|
39
|
+
@client.write "#{reply}\r\n"
|
|
40
|
+
active = false
|
|
41
|
+
else
|
|
42
|
+
command = command.unpack('c*')
|
|
43
|
+
@log.debug "header: #{hexString command}" if @log.debug?
|
|
44
|
+
raise ClientDataError, "invalid pin" unless (command[3] & 0xFF) == config.pinLo and (command[4] & 0xFF) == config.pinHi
|
|
45
|
+
packetSize = (command[1] & 0xFF) | ((command[2] << 8) & 0xFF00)
|
|
46
|
+
raise ClientDataError, "invalid packet size" if packetSize < 7 or packetSize > 128
|
|
47
|
+
command += read(packetSize - 5).unpack('c*')
|
|
48
|
+
CommandQueue.instance.push @ip, command unless (command[0] & 0xFF) == 0x93
|
|
49
|
+
@status.get { @client.write @status.raw.pack('c*') if @status.valid }
|
|
50
|
+
@log.info "command received from client #{@ip} so it is alive"
|
|
51
|
+
end
|
|
52
|
+
rescue Timeout::Error
|
|
53
|
+
@log.info "timeout on client #{@ip} so presuming it dormant"
|
|
54
|
+
active = false
|
|
55
|
+
rescue ClientDataError => error
|
|
56
|
+
@log.info "data error from client #{@ip}: #{error.message}"
|
|
57
|
+
active = false
|
|
58
|
+
rescue => error
|
|
59
|
+
@log.error error
|
|
60
|
+
active = false
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def read size
|
|
66
|
+
data = @client.read size
|
|
67
|
+
raise ClientDataError, "nothing received so presuming it has disconnected" unless data and data.size == size
|
|
68
|
+
data
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
class ClientDataError < Interrupt
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|
|
@@ -1,48 +1,48 @@
|
|
|
1
|
-
# See https://github.com/sappho/sappho-heatmiser-proxy/wiki for project documentation.
|
|
2
|
-
# This software is licensed under the GNU Affero General Public License, version 3.
|
|
3
|
-
# See http://www.gnu.org/licenses/agpl.html for full details of the license terms.
|
|
4
|
-
# Copyright 2012 Andrew Heald.
|
|
5
|
-
|
|
6
|
-
module Sappho
|
|
7
|
-
module Heatmiser
|
|
8
|
-
module Proxy
|
|
9
|
-
|
|
10
|
-
class HeatmiserCRC
|
|
11
|
-
|
|
12
|
-
LookupHi = [
|
|
13
|
-
0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70,
|
|
14
|
-
0x81, 0x91, 0xA1, 0xB1, 0xC1, 0xD1, 0xE1, 0xF1
|
|
15
|
-
]
|
|
16
|
-
LookupLo = [
|
|
17
|
-
0x00, 0x21, 0x42, 0x63, 0x84, 0xA5, 0xC6, 0xE7,
|
|
18
|
-
0x08, 0x29, 0x4A, 0x6B, 0x8C, 0xAD, 0xCE, 0xEF
|
|
19
|
-
]
|
|
20
|
-
attr_reader :crcHi, :crcLo
|
|
21
|
-
|
|
22
|
-
def initialize bytes
|
|
23
|
-
@bytes = bytes
|
|
24
|
-
@crcHi = 0xFF
|
|
25
|
-
@crcLo = 0xFF
|
|
26
|
-
bytes.each do |byte|
|
|
27
|
-
addNibble byte >> 4
|
|
28
|
-
addNibble byte & 0x0F
|
|
29
|
-
end
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
def appendCRC
|
|
33
|
-
@bytes << @crcLo << @crcHi
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
private
|
|
37
|
-
|
|
38
|
-
def addNibble nibble
|
|
39
|
-
t = ((@crcHi >> 4) ^ nibble) & 0x0F
|
|
40
|
-
@crcHi = (((@crcHi << 4) & 0xFF) | (@crcLo >> 4)) ^ LookupHi[t]
|
|
41
|
-
@crcLo = ((@crcLo << 4) & 0xFF) ^ LookupLo[t]
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
end
|
|
47
|
-
end
|
|
48
|
-
end
|
|
1
|
+
# See https://github.com/sappho/sappho-heatmiser-proxy/wiki for project documentation.
|
|
2
|
+
# This software is licensed under the GNU Affero General Public License, version 3.
|
|
3
|
+
# See http://www.gnu.org/licenses/agpl.html for full details of the license terms.
|
|
4
|
+
# Copyright 2012 Andrew Heald.
|
|
5
|
+
|
|
6
|
+
module Sappho
|
|
7
|
+
module Heatmiser
|
|
8
|
+
module Proxy
|
|
9
|
+
|
|
10
|
+
class HeatmiserCRC
|
|
11
|
+
|
|
12
|
+
LookupHi = [
|
|
13
|
+
0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70,
|
|
14
|
+
0x81, 0x91, 0xA1, 0xB1, 0xC1, 0xD1, 0xE1, 0xF1
|
|
15
|
+
]
|
|
16
|
+
LookupLo = [
|
|
17
|
+
0x00, 0x21, 0x42, 0x63, 0x84, 0xA5, 0xC6, 0xE7,
|
|
18
|
+
0x08, 0x29, 0x4A, 0x6B, 0x8C, 0xAD, 0xCE, 0xEF
|
|
19
|
+
]
|
|
20
|
+
attr_reader :crcHi, :crcLo
|
|
21
|
+
|
|
22
|
+
def initialize bytes
|
|
23
|
+
@bytes = bytes
|
|
24
|
+
@crcHi = 0xFF
|
|
25
|
+
@crcLo = 0xFF
|
|
26
|
+
bytes.each do |byte|
|
|
27
|
+
addNibble byte >> 4
|
|
28
|
+
addNibble byte & 0x0F
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def appendCRC
|
|
33
|
+
@bytes << @crcLo << @crcHi
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
private
|
|
37
|
+
|
|
38
|
+
def addNibble nibble
|
|
39
|
+
t = ((@crcHi >> 4) ^ nibble) & 0x0F
|
|
40
|
+
@crcHi = (((@crcHi << 4) & 0xFF) | (@crcLo >> 4)) ^ LookupHi[t]
|
|
41
|
+
@crcLo = ((@crcLo << 4) & 0xFF) ^ LookupLo[t]
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
@@ -1,131 +1,136 @@
|
|
|
1
|
-
# See https://github.com/sappho/sappho-heatmiser-proxy/wiki for project documentation.
|
|
2
|
-
# This software is licensed under the GNU Affero General Public License, version 3.
|
|
3
|
-
# See http://www.gnu.org/licenses/agpl.html for full details of the license terms.
|
|
4
|
-
# Copyright 2012 Andrew Heald.
|
|
5
|
-
|
|
6
|
-
module Sappho
|
|
7
|
-
module Heatmiser
|
|
8
|
-
module Proxy
|
|
9
|
-
|
|
10
|
-
require 'singleton'
|
|
11
|
-
require 'thread'
|
|
12
|
-
require 'sappho-basics/auto_flush_log'
|
|
13
|
-
|
|
14
|
-
class HeatmiserStatus
|
|
15
|
-
|
|
16
|
-
include Singleton, Sappho::LogUtilities
|
|
17
|
-
|
|
18
|
-
attr_reader :valid, :timestamp, :sampleTime, :timeSinceLastValid, :sensedTemperature,
|
|
19
|
-
:requestedTemperature, :heatOn, :keyLockOn, :frostProtectOn, :deviceTimeOffset,
|
|
20
|
-
:dayOfWeek, :schedule
|
|
21
|
-
|
|
22
|
-
class TimedTemperature
|
|
23
|
-
|
|
24
|
-
attr_reader :hour, :minute, :temperature
|
|
25
|
-
|
|
26
|
-
def initialize raw, bytePosition
|
|
27
|
-
@hour = raw[bytePosition] & 0xFF
|
|
28
|
-
@minute = raw[bytePosition + 1] & 0xFF
|
|
29
|
-
@temperature = raw[bytePosition + 2] & 0xFF
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
def valid?
|
|
33
|
-
@hour < 24 and @minute < 60
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
def description
|
|
37
|
-
"#{@hour}:#{@minute}-#{@temperature}"
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
class Schedule
|
|
43
|
-
|
|
44
|
-
attr_reader :schedule
|
|
45
|
-
|
|
46
|
-
def initialize raw, bytePosition
|
|
47
|
-
@schedule = []
|
|
48
|
-
(0 ... 4).map do |position|
|
|
49
|
-
timedTemperature = TimedTemperature.new(raw, bytePosition + 3 * position)
|
|
50
|
-
@schedule << timedTemperature if timedTemperature.valid?
|
|
51
|
-
end
|
|
52
|
-
end
|
|
53
|
-
|
|
54
|
-
def description
|
|
55
|
-
(@schedule.collect {|timedTemperature| timedTemperature.description}).join(' ')
|
|
56
|
-
end
|
|
57
|
-
|
|
58
|
-
end
|
|
59
|
-
|
|
60
|
-
def initialize
|
|
61
|
-
@mutex = Mutex.new
|
|
62
|
-
@log = Sappho::ApplicationAutoFlushLog.instance
|
|
63
|
-
@valid = false
|
|
64
|
-
@raw = []
|
|
65
|
-
@timestamp = Time.now
|
|
66
|
-
@sampleTime = 0.0
|
|
67
|
-
@timeSinceLastValid = 0.0
|
|
68
|
-
@sensedTemperature = 0.0
|
|
69
|
-
@requestedTemperature = 0
|
|
70
|
-
@holidayReturnTime = Time.now
|
|
71
|
-
@holdMinutes = 0
|
|
72
|
-
@heatOn = false
|
|
73
|
-
@keyLockOn = false
|
|
74
|
-
@frostProtectOn = false
|
|
75
|
-
@holidayOn = false
|
|
76
|
-
@deviceTimeOffset = 0.0
|
|
77
|
-
@dayOfWeek = 0
|
|
78
|
-
@schedule = {}
|
|
79
|
-
end
|
|
80
|
-
|
|
81
|
-
def raw
|
|
82
|
-
@raw.dup
|
|
83
|
-
end
|
|
84
|
-
|
|
85
|
-
def get
|
|
86
|
-
@mutex.synchronize { yield }
|
|
87
|
-
end
|
|
88
|
-
|
|
89
|
-
def set raw, timestamp, sampleTime
|
|
90
|
-
@mutex.synchronize do
|
|
91
|
-
@valid =
|
|
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
|
-
|
|
130
|
-
|
|
131
|
-
|
|
1
|
+
# See https://github.com/sappho/sappho-heatmiser-proxy/wiki for project documentation.
|
|
2
|
+
# This software is licensed under the GNU Affero General Public License, version 3.
|
|
3
|
+
# See http://www.gnu.org/licenses/agpl.html for full details of the license terms.
|
|
4
|
+
# Copyright 2012 Andrew Heald.
|
|
5
|
+
|
|
6
|
+
module Sappho
|
|
7
|
+
module Heatmiser
|
|
8
|
+
module Proxy
|
|
9
|
+
|
|
10
|
+
require 'singleton'
|
|
11
|
+
require 'thread'
|
|
12
|
+
require 'sappho-basics/auto_flush_log'
|
|
13
|
+
|
|
14
|
+
class HeatmiserStatus
|
|
15
|
+
|
|
16
|
+
include Singleton, Sappho::LogUtilities
|
|
17
|
+
|
|
18
|
+
attr_reader :valid, :timestamp, :sampleTime, :timeSinceLastValid, :sensedTemperature,
|
|
19
|
+
:requestedTemperature, :heatOn, :keyLockOn, :frostProtectOn, :deviceTimeOffset,
|
|
20
|
+
:dayOfWeek, :schedule
|
|
21
|
+
|
|
22
|
+
class TimedTemperature
|
|
23
|
+
|
|
24
|
+
attr_reader :hour, :minute, :temperature
|
|
25
|
+
|
|
26
|
+
def initialize raw, bytePosition
|
|
27
|
+
@hour = raw[bytePosition] & 0xFF
|
|
28
|
+
@minute = raw[bytePosition + 1] & 0xFF
|
|
29
|
+
@temperature = raw[bytePosition + 2] & 0xFF
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def valid?
|
|
33
|
+
@hour < 24 and @minute < 60
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def description
|
|
37
|
+
"#{@hour}:#{@minute}-#{@temperature}"
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
class Schedule
|
|
43
|
+
|
|
44
|
+
attr_reader :schedule
|
|
45
|
+
|
|
46
|
+
def initialize raw, bytePosition
|
|
47
|
+
@schedule = []
|
|
48
|
+
(0 ... 4).map do |position|
|
|
49
|
+
timedTemperature = TimedTemperature.new(raw, bytePosition + 3 * position)
|
|
50
|
+
@schedule << timedTemperature if timedTemperature.valid?
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def description
|
|
55
|
+
(@schedule.collect {|timedTemperature| timedTemperature.description}).join(' ')
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def initialize
|
|
61
|
+
@mutex = Mutex.new
|
|
62
|
+
@log = Sappho::ApplicationAutoFlushLog.instance
|
|
63
|
+
@valid = false
|
|
64
|
+
@raw = []
|
|
65
|
+
@timestamp = Time.now
|
|
66
|
+
@sampleTime = 0.0
|
|
67
|
+
@timeSinceLastValid = 0.0
|
|
68
|
+
@sensedTemperature = 0.0
|
|
69
|
+
@requestedTemperature = 0
|
|
70
|
+
@holidayReturnTime = Time.now
|
|
71
|
+
@holdMinutes = 0
|
|
72
|
+
@heatOn = false
|
|
73
|
+
@keyLockOn = false
|
|
74
|
+
@frostProtectOn = false
|
|
75
|
+
@holidayOn = false
|
|
76
|
+
@deviceTimeOffset = 0.0
|
|
77
|
+
@dayOfWeek = 0
|
|
78
|
+
@schedule = {}
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def raw
|
|
82
|
+
@raw.dup
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def get
|
|
86
|
+
@mutex.synchronize { yield }
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def set raw, timestamp, sampleTime
|
|
90
|
+
@mutex.synchronize do
|
|
91
|
+
@valid = true
|
|
92
|
+
begin
|
|
93
|
+
@raw = raw.dup
|
|
94
|
+
@sensedTemperature = ((raw[44] & 0xFF) | ((raw[45] << 8) & 0xFF00)) / 10.0
|
|
95
|
+
@holdMinutes = (raw[38] & 0xFF) | ((raw[39] << 8) & 0xFF00)
|
|
96
|
+
@heatOn = raw[47] == 1
|
|
97
|
+
@keyLockOn = raw[29] == 1
|
|
98
|
+
@frostProtectOn = raw[30] == 1
|
|
99
|
+
@holidayOn = raw[37] == 1
|
|
100
|
+
@holidayReturnTime = Time.local(2000 + (raw[32] & 0xFF), raw[33], raw[34], raw[35], raw[36], 0)
|
|
101
|
+
@requestedTemperature = @frostProtectOn ? raw[24] & 0xFF : raw[25] & 0xFF
|
|
102
|
+
@deviceTimeOffset = Time.local(2000 + (raw[48] & 0xFF), raw[49], raw[50],
|
|
103
|
+
raw[52], raw[53], raw[54]) - timestamp
|
|
104
|
+
dayOfWeek = raw[51]
|
|
105
|
+
@dayOfWeek = dayOfWeek == 7 ? 0 : dayOfWeek
|
|
106
|
+
@schedule = {
|
|
107
|
+
:weekday => Schedule.new(@raw, 55),
|
|
108
|
+
:weekend => Schedule.new(@raw, 67)
|
|
109
|
+
}
|
|
110
|
+
@timeSinceLastValid = timestamp - @timestamp
|
|
111
|
+
@timestamp = timestamp
|
|
112
|
+
@sampleTime = sampleTime
|
|
113
|
+
if @log.debug?
|
|
114
|
+
@log.debug "#{hexString raw}"
|
|
115
|
+
@log.debug "#{@requestedTemperature} #{@holdMinutes / 60}:#{@holdMinutes % 60} #{@sensedTemperature} #{@heatOn} #{@keyLockOn} #{@frostProtectOn} #{@timeSinceLastValid} #{@dayOfWeek} #{@deviceTimeOffset} #{sampleTime} #{@holidayOn} #{@holidayReturnTime}"
|
|
116
|
+
@log.debug "weekday: #{@schedule[:weekday].description} weekend: #{@schedule[:weekend].description}"
|
|
117
|
+
else
|
|
118
|
+
@log.info "received status: heating is #{@heatOn ? "on" : "off"} because required temperature is #{@requestedTemperature} and actual is #{@sensedTemperature}"
|
|
119
|
+
end
|
|
120
|
+
yield
|
|
121
|
+
rescue => error
|
|
122
|
+
@log.error error
|
|
123
|
+
@valid = false
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
def invalidate
|
|
129
|
+
@mutex.synchronize { @valid = false }
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
end
|
|
@@ -1,48 +1,34 @@
|
|
|
1
|
-
# See https://github.com/sappho/sappho-heatmiser-proxy/wiki for project documentation.
|
|
2
|
-
# This software is licensed under the GNU Affero General Public License, version 3.
|
|
3
|
-
# See http://www.gnu.org/licenses/agpl.html for full details of the license terms.
|
|
4
|
-
# Copyright 2012 Andrew Heald.
|
|
5
|
-
|
|
6
|
-
module Sappho
|
|
7
|
-
module Heatmiser
|
|
8
|
-
module Proxy
|
|
9
|
-
|
|
10
|
-
require 'singleton'
|
|
11
|
-
require 'yaml'
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
@maxClients = data.has_key?('clients.max') ? Integer(data['clients.max']) : 10
|
|
36
|
-
@mongoLogging = data.has_key?('mongodb.address') and data.has_key?('mongodb.database')
|
|
37
|
-
@mongodbHostname = data['mongodb.address']
|
|
38
|
-
@mongodbPort = data.has_key?('mongodb.port') ? Integer(data['mongodb.port']) : 27017
|
|
39
|
-
@mongodbDatabase = data['mongodb.database']
|
|
40
|
-
@detailedLogging = data.has_key? 'logging.detailed'
|
|
41
|
-
raise "missing settings in #{filename}" unless @heatmiserId and @heatmiserHostname
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
end
|
|
47
|
-
end
|
|
48
|
-
end
|
|
1
|
+
# See https://github.com/sappho/sappho-heatmiser-proxy/wiki for project documentation.
|
|
2
|
+
# This software is licensed under the GNU Affero General Public License, version 3.
|
|
3
|
+
# See http://www.gnu.org/licenses/agpl.html for full details of the license terms.
|
|
4
|
+
# Copyright 2012 Andrew Heald.
|
|
5
|
+
|
|
6
|
+
module Sappho
|
|
7
|
+
module Heatmiser
|
|
8
|
+
module Proxy
|
|
9
|
+
|
|
10
|
+
require 'singleton'
|
|
11
|
+
require 'yaml'
|
|
12
|
+
|
|
13
|
+
class SystemConfiguration
|
|
14
|
+
|
|
15
|
+
include Singleton
|
|
16
|
+
|
|
17
|
+
attr_reader :heatmiserHostname, :heatmiserPort, :pinLo, :pinHi, :sampleDelay, :maxClients
|
|
18
|
+
|
|
19
|
+
def initialize
|
|
20
|
+
data = YAML.load_file(File.expand_path(ARGV[0] || 'heatmiser-proxy.yml'))
|
|
21
|
+
@heatmiserHostname = data['heatmiser.address']
|
|
22
|
+
@heatmiserPort = Integer data['heatmiser.port']
|
|
23
|
+
pin = Integer data['heatmiser.pin']
|
|
24
|
+
@pinLo = pin & 0xFF
|
|
25
|
+
@pinHi = (pin >> 8) & 0xFF
|
|
26
|
+
@sampleDelay = Integer data['heatmiser.sample.delay']
|
|
27
|
+
@maxClients = Integer data['clients.max']
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
# See https://github.com/sappho/sappho-heatmiser-proxy/wiki for project documentation.
|
|
2
|
-
# This software is licensed under the GNU Affero General Public License, version 3.
|
|
3
|
-
# See http://www.gnu.org/licenses/agpl.html for full details of the license terms.
|
|
4
|
-
# Copyright 2012 Andrew Heald.
|
|
5
|
-
|
|
6
|
-
module Sappho
|
|
7
|
-
module Heatmiser
|
|
8
|
-
module Proxy
|
|
9
|
-
NAME = 'sappho-heatmiser-proxy'
|
|
10
|
-
VERSION = '0.1.
|
|
11
|
-
AUTHORS = ['Andrew Heald']
|
|
12
|
-
EMAILS = ['andrew@heald.co.uk']
|
|
13
|
-
HOMEPAGE = 'https://github.com/sappho/sappho-heatmiser-proxy/wiki'
|
|
14
|
-
SUMMARY = 'Acts as a proxy for Heatmiser hardware to allow continuous monitoring and control by many controllers'
|
|
15
|
-
DESCRIPTION = 'See the project home page for more information'
|
|
16
|
-
end
|
|
17
|
-
end
|
|
18
|
-
end
|
|
1
|
+
# See https://github.com/sappho/sappho-heatmiser-proxy/wiki for project documentation.
|
|
2
|
+
# This software is licensed under the GNU Affero General Public License, version 3.
|
|
3
|
+
# See http://www.gnu.org/licenses/agpl.html for full details of the license terms.
|
|
4
|
+
# Copyright 2012 Andrew Heald.
|
|
5
|
+
|
|
6
|
+
module Sappho
|
|
7
|
+
module Heatmiser
|
|
8
|
+
module Proxy
|
|
9
|
+
NAME = 'sappho-heatmiser-proxy'
|
|
10
|
+
VERSION = '0.1.3'
|
|
11
|
+
AUTHORS = ['Andrew Heald']
|
|
12
|
+
EMAILS = ['andrew@heald.co.uk']
|
|
13
|
+
HOMEPAGE = 'https://github.com/sappho/sappho-heatmiser-proxy/wiki'
|
|
14
|
+
SUMMARY = 'Acts as a proxy for Heatmiser hardware to allow continuous monitoring and control by many controllers'
|
|
15
|
+
DESCRIPTION = 'See the project home page for more information'
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -1,44 +1,35 @@
|
|
|
1
|
-
# See https://github.com/sappho/sappho-heatmiser-proxy/wiki for project documentation.
|
|
2
|
-
# This software is licensed under the GNU Affero General Public License, version 3.
|
|
3
|
-
# See http://www.gnu.org/licenses/agpl.html for full details of the license terms.
|
|
4
|
-
# Copyright 2012 Andrew Heald.
|
|
5
|
-
|
|
6
|
-
module Sappho
|
|
7
|
-
module Heatmiser
|
|
8
|
-
module Proxy
|
|
9
|
-
|
|
10
|
-
require 'sappho-heatmiser-proxy/heatmiser'
|
|
11
|
-
require 'sappho-heatmiser-proxy/heatmiser_client'
|
|
12
|
-
require 'sappho-basics/auto_flush_log'
|
|
13
|
-
require 'sappho-socket/safe_server'
|
|
14
|
-
require 'sappho-heatmiser-proxy/version'
|
|
15
|
-
require '
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
Heatmiser.new.monitor
|
|
37
|
-
end.join
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
end
|
|
43
|
-
end
|
|
44
|
-
end
|
|
1
|
+
# See https://github.com/sappho/sappho-heatmiser-proxy/wiki for project documentation.
|
|
2
|
+
# This software is licensed under the GNU Affero General Public License, version 3.
|
|
3
|
+
# See http://www.gnu.org/licenses/agpl.html for full details of the license terms.
|
|
4
|
+
# Copyright 2012 Andrew Heald.
|
|
5
|
+
|
|
6
|
+
module Sappho
|
|
7
|
+
module Heatmiser
|
|
8
|
+
module Proxy
|
|
9
|
+
|
|
10
|
+
require 'sappho-heatmiser-proxy/heatmiser'
|
|
11
|
+
require 'sappho-heatmiser-proxy/heatmiser_client'
|
|
12
|
+
require 'sappho-basics/auto_flush_log'
|
|
13
|
+
require 'sappho-socket/safe_server'
|
|
14
|
+
require 'sappho-heatmiser-proxy/version'
|
|
15
|
+
require 'thread'
|
|
16
|
+
|
|
17
|
+
class CommandLine
|
|
18
|
+
|
|
19
|
+
def CommandLine.process
|
|
20
|
+
Sappho::ApplicationAutoFlushLog.instance.info "#{NAME} version #{VERSION} - #{HOMEPAGE}"
|
|
21
|
+
port = SystemConfiguration.instance.heatmiserPort
|
|
22
|
+
maxClients = SystemConfiguration.instance.maxClients
|
|
23
|
+
Sappho::Socket::SafeServer.new('heatmiser proxy', port, maxClients).serve do
|
|
24
|
+
| socket, ip | HeatmiserClient.new(socket, ip).communicate
|
|
25
|
+
end
|
|
26
|
+
Thread.new do
|
|
27
|
+
Heatmiser.new.monitor
|
|
28
|
+
end.join
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
metadata
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: sappho-heatmiser-proxy
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
hash:
|
|
4
|
+
hash: 29
|
|
5
5
|
prerelease:
|
|
6
6
|
segments:
|
|
7
7
|
- 0
|
|
8
8
|
- 1
|
|
9
|
-
-
|
|
10
|
-
version: 0.1.
|
|
9
|
+
- 3
|
|
10
|
+
version: 0.1.3
|
|
11
11
|
platform: ruby
|
|
12
12
|
authors:
|
|
13
13
|
- Andrew Heald
|
|
@@ -15,7 +15,7 @@ autorequire:
|
|
|
15
15
|
bindir: bin
|
|
16
16
|
cert_chain: []
|
|
17
17
|
|
|
18
|
-
date: 2012-03-
|
|
18
|
+
date: 2012-03-29 00:00:00 Z
|
|
19
19
|
dependencies:
|
|
20
20
|
- !ruby/object:Gem::Dependency
|
|
21
21
|
name: rake
|
|
@@ -50,54 +50,6 @@ dependencies:
|
|
|
50
50
|
version: 0.1.1
|
|
51
51
|
type: :runtime
|
|
52
52
|
version_requirements: *id002
|
|
53
|
-
- !ruby/object:Gem::Dependency
|
|
54
|
-
name: mongo_mapper
|
|
55
|
-
prerelease: false
|
|
56
|
-
requirement: &id003 !ruby/object:Gem::Requirement
|
|
57
|
-
none: false
|
|
58
|
-
requirements:
|
|
59
|
-
- - ">="
|
|
60
|
-
- !ruby/object:Gem::Version
|
|
61
|
-
hash: 51
|
|
62
|
-
segments:
|
|
63
|
-
- 0
|
|
64
|
-
- 11
|
|
65
|
-
- 0
|
|
66
|
-
version: 0.11.0
|
|
67
|
-
type: :runtime
|
|
68
|
-
version_requirements: *id003
|
|
69
|
-
- !ruby/object:Gem::Dependency
|
|
70
|
-
name: mongo
|
|
71
|
-
prerelease: false
|
|
72
|
-
requirement: &id004 !ruby/object:Gem::Requirement
|
|
73
|
-
none: false
|
|
74
|
-
requirements:
|
|
75
|
-
- - ">="
|
|
76
|
-
- !ruby/object:Gem::Version
|
|
77
|
-
hash: 13
|
|
78
|
-
segments:
|
|
79
|
-
- 1
|
|
80
|
-
- 6
|
|
81
|
-
- 1
|
|
82
|
-
version: 1.6.1
|
|
83
|
-
type: :runtime
|
|
84
|
-
version_requirements: *id004
|
|
85
|
-
- !ruby/object:Gem::Dependency
|
|
86
|
-
name: bson_ext
|
|
87
|
-
prerelease: false
|
|
88
|
-
requirement: &id005 !ruby/object:Gem::Requirement
|
|
89
|
-
none: false
|
|
90
|
-
requirements:
|
|
91
|
-
- - ">="
|
|
92
|
-
- !ruby/object:Gem::Version
|
|
93
|
-
hash: 13
|
|
94
|
-
segments:
|
|
95
|
-
- 1
|
|
96
|
-
- 6
|
|
97
|
-
- 1
|
|
98
|
-
version: 1.6.1
|
|
99
|
-
type: :runtime
|
|
100
|
-
version_requirements: *id005
|
|
101
53
|
description: See the project home page for more information
|
|
102
54
|
email:
|
|
103
55
|
- andrew@heald.co.uk
|
|
@@ -109,15 +61,14 @@ extra_rdoc_files: []
|
|
|
109
61
|
|
|
110
62
|
files:
|
|
111
63
|
- bin/sappho-heatmiser-proxy
|
|
112
|
-
- lib/sappho-heatmiser-proxy
|
|
64
|
+
- lib/sappho-heatmiser-proxy.rb
|
|
65
|
+
- lib/sappho-heatmiser-proxy/version.rb
|
|
113
66
|
- lib/sappho-heatmiser-proxy/heatmiser.rb
|
|
114
|
-
- lib/sappho-heatmiser-proxy/heatmiser_client.rb
|
|
115
67
|
- lib/sappho-heatmiser-proxy/heatmiser_crc.rb
|
|
116
|
-
- lib/sappho-heatmiser-proxy/heatmiser_status.rb
|
|
117
|
-
- lib/sappho-heatmiser-proxy/model/heatmiser_log.rb
|
|
118
68
|
- lib/sappho-heatmiser-proxy/system_configuration.rb
|
|
119
|
-
- lib/sappho-heatmiser-proxy/
|
|
120
|
-
- lib/sappho-heatmiser-proxy.rb
|
|
69
|
+
- lib/sappho-heatmiser-proxy/heatmiser_status.rb
|
|
70
|
+
- lib/sappho-heatmiser-proxy/command_queue.rb
|
|
71
|
+
- lib/sappho-heatmiser-proxy/heatmiser_client.rb
|
|
121
72
|
homepage: https://github.com/sappho/sappho-heatmiser-proxy/wiki
|
|
122
73
|
licenses: []
|
|
123
74
|
|
|
@@ -147,7 +98,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
147
98
|
requirements: []
|
|
148
99
|
|
|
149
100
|
rubyforge_project: sappho-heatmiser-proxy
|
|
150
|
-
rubygems_version: 1.8.
|
|
101
|
+
rubygems_version: 1.8.17
|
|
151
102
|
signing_key:
|
|
152
103
|
specification_version: 3
|
|
153
104
|
summary: Acts as a proxy for Heatmiser hardware to allow continuous monitoring and control by many controllers
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
# See https://github.com/sappho/sappho-heatmiser-proxy/wiki for project documentation.
|
|
2
|
-
# This software is licensed under the GNU Affero General Public License, version 3.
|
|
3
|
-
# See http://www.gnu.org/licenses/agpl.html for full details of the license terms.
|
|
4
|
-
# Copyright 2012 Andrew Heald.
|
|
5
|
-
|
|
6
|
-
module Sappho
|
|
7
|
-
module Heatmiser
|
|
8
|
-
module Model
|
|
9
|
-
|
|
10
|
-
require 'mongo_mapper'
|
|
11
|
-
require 'mongo_mapper/document'
|
|
12
|
-
|
|
13
|
-
class HeatmiserLog
|
|
14
|
-
|
|
15
|
-
include MongoMapper::Document
|
|
16
|
-
|
|
17
|
-
key :deviceId, String
|
|
18
|
-
key :timestamp, Time
|
|
19
|
-
key :sensedTemperature, Float
|
|
20
|
-
key :requestedTemperature, Integer
|
|
21
|
-
key :heatOn, Boolean
|
|
22
|
-
key :frostProtectOn, Boolean
|
|
23
|
-
key :deviceTimeOffset, Float
|
|
24
|
-
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
end
|
|
28
|
-
end
|
|
29
|
-
end
|