sappho-heatmiser-proxy 0.1.1 → 0.1.2
Sign up to get free protection for your applications and to get access to all the features.
- data/bin/sappho-heatmiser-proxy +12 -12
- data/lib/sappho-heatmiser-proxy.rb +44 -35
- data/lib/sappho-heatmiser-proxy/command_queue.rb +60 -60
- data/lib/sappho-heatmiser-proxy/heatmiser.rb +96 -86
- 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 +131 -136
- data/lib/sappho-heatmiser-proxy/model/heatmiser_log.rb +29 -0
- data/lib/sappho-heatmiser-proxy/system_configuration.rb +48 -33
- data/lib/sappho-heatmiser-proxy/version.rb +18 -18
- metadata +59 -10
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
|
+
$: << File.expand_path('../lib', __FILE__)
|
9
|
+
|
10
|
+
require 'sappho-heatmiser-proxy'
|
11
|
+
|
12
|
+
Sappho::Heatmiser::Proxy::CommandLine.process
|
@@ -1,35 +1,44 @@
|
|
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
|
-
|
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 'mongo_mapper'
|
16
|
+
require 'mongo/connection'
|
17
|
+
require 'thread'
|
18
|
+
|
19
|
+
class CommandLine
|
20
|
+
|
21
|
+
def CommandLine.process
|
22
|
+
log = Sappho::ApplicationAutoFlushLog.instance
|
23
|
+
log.info "#{NAME} version #{VERSION} - #{HOMEPAGE}"
|
24
|
+
config = SystemConfiguration.instance
|
25
|
+
if config.mongoLogging
|
26
|
+
log.info "connecting to mongodb database #{config.mongodbDatabase} on #{config.mongodbHostname}:#{config.mongodbPort}"
|
27
|
+
MongoMapper.connection = Mongo::Connection.new config.mongodbHostname, config.mongodbPort
|
28
|
+
MongoMapper.database = config.mongodbDatabase
|
29
|
+
else
|
30
|
+
log.info 'logging to mongodb is disabled'
|
31
|
+
end
|
32
|
+
Sappho::Socket::SafeServer.new('heatmiser proxy', config.heatmiserPort, config.maxClients, config.detailedLogging).serve do
|
33
|
+
| socket, ip | HeatmiserClient.new(socket, ip).communicate
|
34
|
+
end
|
35
|
+
Thread.new do
|
36
|
+
Heatmiser.new.monitor
|
37
|
+
end.join
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -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,86 +1,96 @@
|
|
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
|
-
|
40
|
-
|
41
|
-
|
42
|
-
timeNow.
|
43
|
-
|
44
|
-
timeNow.
|
45
|
-
|
46
|
-
timeNow.
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
socket.
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
reply
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
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-heatmiser-proxy/model/heatmiser_log'
|
16
|
+
require 'sappho-socket/safe_socket'
|
17
|
+
|
18
|
+
class Heatmiser
|
19
|
+
|
20
|
+
include Sappho::LogUtilities
|
21
|
+
|
22
|
+
def monitor
|
23
|
+
status = HeatmiserStatus.instance
|
24
|
+
queue = CommandQueue.instance
|
25
|
+
log = Sappho::ApplicationAutoFlushLog.instance
|
26
|
+
config = SystemConfiguration.instance
|
27
|
+
desc = "heatmiser #{config.heatmiserId} at #{config.heatmiserHostname}:#{config.heatmiserPort}"
|
28
|
+
log.info "connecting to #{desc}"
|
29
|
+
queryCommand = HeatmiserCRC.new([0x93, 0x0B, 0x00, config.pinLo, config.pinHi, 0x00, 0x00, 0xFF, 0xFF]).appendCRC
|
30
|
+
socket = Sappho::Socket::SafeSocket.new 5
|
31
|
+
loop do
|
32
|
+
begin
|
33
|
+
command = queryCommand
|
34
|
+
if queuedCommand = queue.get
|
35
|
+
command = queuedCommand
|
36
|
+
else
|
37
|
+
if status.get{status.valid ? status.deviceTimeOffset : 0.0}.abs > 5 and config.heatmiserHardware
|
38
|
+
timeNow = Time.now
|
39
|
+
dayOfWeek = timeNow.wday
|
40
|
+
dayOfWeek = 7 if dayOfWeek == 0
|
41
|
+
command = HeatmiserCRC.new([0xA3, 0x12, 0x00, config.pinLo, config.pinHi, 0x01, 0x2B, 0x00, 0x07,
|
42
|
+
timeNow.year - 2000,
|
43
|
+
timeNow.month,
|
44
|
+
timeNow.day,
|
45
|
+
dayOfWeek,
|
46
|
+
timeNow.hour,
|
47
|
+
timeNow.min,
|
48
|
+
timeNow.sec]).appendCRC
|
49
|
+
log.info "clock correction: #{hexString command}"
|
50
|
+
end
|
51
|
+
end
|
52
|
+
log.debug "sending command: #{hexString command}" if log.debug?
|
53
|
+
socket.open config.heatmiserHostname, config.heatmiserPort
|
54
|
+
socket.settle 0.1
|
55
|
+
startTime = Time.now
|
56
|
+
socket.write command.pack('c*')
|
57
|
+
reply = socket.read(81).unpack('c*')
|
58
|
+
timestamp = Time.now
|
59
|
+
log.debug "reply: #{hexString reply}" if log.debug?
|
60
|
+
crcHi = reply.pop & 0xFF
|
61
|
+
crcLo = reply.pop & 0xFF
|
62
|
+
crc = HeatmiserCRC.new reply
|
63
|
+
if (reply[0] & 0xFF) == 0x94 and reply[1] == 0x51 and reply[2] == 0 and
|
64
|
+
crc.crcHi == crcHi and crc.crcLo == crcLo
|
65
|
+
reply << crcLo << crcHi
|
66
|
+
status.set reply, timestamp, (timestamp - startTime)
|
67
|
+
queue.completed if queuedCommand
|
68
|
+
Sappho::Heatmiser::Model::HeatmiserLog.new(status.get{{
|
69
|
+
:deviceId => config.heatmiserId,
|
70
|
+
:timestamp => timestamp,
|
71
|
+
:sensedTemperature => status.sensedTemperature,
|
72
|
+
:requestedTemperature => status.requestedTemperature,
|
73
|
+
:heatOn => status.heatOn,
|
74
|
+
:frostProtectOn => status.frostProtectOn,
|
75
|
+
:deviceTimeOffset => status.deviceTimeOffset}}).save if config.mongoLogging
|
76
|
+
else
|
77
|
+
log.info "#{desc} responded with invalid bytes - ignoring it this time"
|
78
|
+
end
|
79
|
+
rescue Timeout::Error
|
80
|
+
status.invalidate
|
81
|
+
log.info "#{desc} is not responding - the connection might be down"
|
82
|
+
rescue => error
|
83
|
+
status.invalidate
|
84
|
+
log.error error
|
85
|
+
end
|
86
|
+
socket.settle 0.1
|
87
|
+
socket.close
|
88
|
+
socket.settle 2
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
end
|
93
|
+
|
94
|
+
end
|
95
|
+
end
|
96
|
+
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,136 +1,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 =
|
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
|
-
|
132
|
-
end
|
133
|
-
|
134
|
-
end
|
135
|
-
end
|
136
|
-
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 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 = false
|
92
|
+
@raw = raw.dup
|
93
|
+
@sensedTemperature = ((raw[44] & 0xFF) | ((raw[45] << 8) & 0xFF00)) / 10.0
|
94
|
+
@holdMinutes = (raw[38] & 0xFF) | ((raw[39] << 8) & 0xFF00)
|
95
|
+
@heatOn = raw[47] == 1
|
96
|
+
@keyLockOn = raw[29] == 1
|
97
|
+
@frostProtectOn = raw[30] == 1
|
98
|
+
@holidayOn = raw[37] == 1
|
99
|
+
@holidayReturnTime = Time.local(2000 + (raw[32] & 0xFF), raw[33], raw[34], raw[35], raw[36], 0)
|
100
|
+
@requestedTemperature = @frostProtectOn ? raw[24] & 0xFF : raw[25] & 0xFF
|
101
|
+
@deviceTimeOffset = Time.local(2000 + (raw[48] & 0xFF), raw[49], raw[50],
|
102
|
+
raw[52], raw[53], raw[54]) - timestamp
|
103
|
+
dayOfWeek = raw[51]
|
104
|
+
@dayOfWeek = dayOfWeek == 7 ? 0 : dayOfWeek
|
105
|
+
@schedule = {
|
106
|
+
:weekday => Schedule.new(@raw, 55),
|
107
|
+
:weekend => Schedule.new(@raw, 67)
|
108
|
+
}
|
109
|
+
@timeSinceLastValid = timestamp - @timestamp
|
110
|
+
@timestamp = timestamp
|
111
|
+
@sampleTime = sampleTime
|
112
|
+
@valid = true
|
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
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
def invalidate
|
124
|
+
@mutex.synchronize { @valid = false }
|
125
|
+
end
|
126
|
+
|
127
|
+
end
|
128
|
+
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
@@ -0,0 +1,29 @@
|
|
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
|
@@ -1,33 +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
|
-
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
|
-
|
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
|
+
require 'sappho-basics/auto_flush_log'
|
13
|
+
|
14
|
+
class SystemConfiguration
|
15
|
+
|
16
|
+
include Singleton
|
17
|
+
|
18
|
+
attr_reader :heatmiserId, :heatmiserHostname, :heatmiserPort, :heatmiserHardware,
|
19
|
+
:pinLo, :pinHi, :maxClients,
|
20
|
+
:mongoLogging, :mongodbHostname, :mongodbPort, :mongodbDatabase,
|
21
|
+
:detailedLogging
|
22
|
+
|
23
|
+
def initialize
|
24
|
+
log = Sappho::ApplicationAutoFlushLog.instance
|
25
|
+
filename = File.expand_path(ARGV[0] || 'heatmiser-proxy.yml')
|
26
|
+
log.info "loading application configuration from #{filename}"
|
27
|
+
data = YAML.load_file(filename)
|
28
|
+
@heatmiserId = data['heatmiser.id']
|
29
|
+
@heatmiserHostname = data['heatmiser.address']
|
30
|
+
@heatmiserPort = data.has_key?('heatmiser.port') ? Integer(data['heatmiser.port']) : 8068
|
31
|
+
@heatmiserHardware = data.has_key? 'heatmiser.hardware'
|
32
|
+
pin = Integer data['heatmiser.pin']
|
33
|
+
@pinLo = pin & 0xFF
|
34
|
+
@pinHi = (pin >> 8) & 0xFF
|
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,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.2'
|
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
|
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: 31
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 1
|
9
|
-
-
|
10
|
-
version: 0.1.
|
9
|
+
- 2
|
10
|
+
version: 0.1.2
|
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-19 00:00:00 Z
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
21
21
|
name: rake
|
@@ -50,6 +50,54 @@ 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
|
53
101
|
description: See the project home page for more information
|
54
102
|
email:
|
55
103
|
- andrew@heald.co.uk
|
@@ -61,14 +109,15 @@ extra_rdoc_files: []
|
|
61
109
|
|
62
110
|
files:
|
63
111
|
- bin/sappho-heatmiser-proxy
|
64
|
-
- lib/sappho-heatmiser-proxy.rb
|
65
|
-
- lib/sappho-heatmiser-proxy/version.rb
|
112
|
+
- lib/sappho-heatmiser-proxy/command_queue.rb
|
66
113
|
- lib/sappho-heatmiser-proxy/heatmiser.rb
|
114
|
+
- lib/sappho-heatmiser-proxy/heatmiser_client.rb
|
67
115
|
- lib/sappho-heatmiser-proxy/heatmiser_crc.rb
|
68
|
-
- lib/sappho-heatmiser-proxy/system_configuration.rb
|
69
116
|
- lib/sappho-heatmiser-proxy/heatmiser_status.rb
|
70
|
-
- lib/sappho-heatmiser-proxy/
|
71
|
-
- lib/sappho-heatmiser-proxy/
|
117
|
+
- lib/sappho-heatmiser-proxy/model/heatmiser_log.rb
|
118
|
+
- lib/sappho-heatmiser-proxy/system_configuration.rb
|
119
|
+
- lib/sappho-heatmiser-proxy/version.rb
|
120
|
+
- lib/sappho-heatmiser-proxy.rb
|
72
121
|
homepage: https://github.com/sappho/sappho-heatmiser-proxy/wiki
|
73
122
|
licenses: []
|
74
123
|
|
@@ -98,7 +147,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
98
147
|
requirements: []
|
99
148
|
|
100
149
|
rubyforge_project: sappho-heatmiser-proxy
|
101
|
-
rubygems_version: 1.8.
|
150
|
+
rubygems_version: 1.8.11
|
102
151
|
signing_key:
|
103
152
|
specification_version: 3
|
104
153
|
summary: Acts as a proxy for Heatmiser hardware to allow continuous monitoring and control by many controllers
|