sappho-heatmiser-proxy 0.1.1 → 0.1.2
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.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
|