sappho-heatmiser-proxy 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +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
+ $:.unshift File.join(File.dirname(__FILE__), *%w[.. lib])
9
+
10
+ require 'sappho-heatmiser-proxy'
11
+
12
+ Sappho::Heatmiser::Proxy::CommandLine.process
@@ -0,0 +1,28 @@
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_proxy'
12
+ require 'thread'
13
+
14
+ class CommandLine
15
+
16
+ def CommandLine.process
17
+ Thread.abort_on_exception = true
18
+ hm = Heatmiser.new
19
+ hm.monitor
20
+ HeatmiserProxy.new.serve
21
+ hm.wait
22
+ end
23
+
24
+ end
25
+
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,62 @@
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-heatmiser-proxy/trace_log'
13
+ require 'sappho-heatmiser-proxy/system_configuration'
14
+
15
+ class ClientRegister
16
+
17
+ include Singleton
18
+
19
+ def initialize
20
+ @mutex = Mutex.new
21
+ @clients = {}
22
+ @max = Integer SystemConfiguration.instance.config['heatmiser.clients.max']
23
+ @log = TraceLog.instance
24
+ end
25
+
26
+ def register client
27
+ @mutex.synchronize do
28
+ ip = client.getpeername
29
+ @clients[client] = ip = (4 ... 8).map{|pos|ip[pos]}.join('.')
30
+ @log.info "client #{ip} connected"
31
+ log
32
+ end
33
+ end
34
+
35
+ def unregister client
36
+ @mutex.synchronize do
37
+ ip = @clients[client]
38
+ @clients.delete client
39
+ @log.info "client #{ip} disconnected"
40
+ log
41
+ end
42
+ end
43
+
44
+ def ip client
45
+ @mutex.synchronize { @clients[client] }
46
+ end
47
+
48
+ def maxAlreadyConnected?
49
+ @mutex.synchronize { @clients.size >= @max }
50
+ end
51
+
52
+ private
53
+
54
+ def log
55
+ @log.info "clients: #{@clients.size > 0 ? (@clients.collect{|client, ip| ip}).join(', ') : 'none'}"
56
+ end
57
+
58
+ end
59
+
60
+ end
61
+ end
62
+ end
@@ -0,0 +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-heatmiser-proxy/trace_log'
13
+
14
+ class CommandQueue
15
+
16
+ include Singleton
17
+
18
+ def initialize
19
+ @queue = []
20
+ @mutex = Mutex.new
21
+ @log = TraceLog.instance
22
+ end
23
+
24
+ def push clientIP, command
25
+ @log.info "client #{clientIP} requests command: #{TraceLog.hex 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: #{TraceLog.hex 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: #{TraceLog.hex queue[:command]}"
51
+ @queue.shift
52
+ end
53
+ end
54
+ end
55
+
56
+ end
57
+
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,107 @@
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-heatmiser-proxy/trace_log'
13
+ require 'sappho-heatmiser-proxy/command_queue'
14
+ require 'thread'
15
+ require 'timeout'
16
+ require 'socket'
17
+ require 'sappho-heatmiser-proxy/system_configuration'
18
+
19
+ class Heatmiser
20
+
21
+ def monitor
22
+ @thread = Thread.new do
23
+ status = HeatmiserStatus.instance
24
+ queue = CommandQueue.instance
25
+ log = TraceLog.instance
26
+ config = SystemConfiguration.instance.config
27
+ hostname = config['heatmiser.address']
28
+ port = Integer config['heatmiser.port']
29
+ pin = Integer config['heatmiser.pin']
30
+ pinLo = pin & 0xFF
31
+ pinHi = (pin >> 8) & 0xFF
32
+ queryCommand = HeatmiserCRC.new([0x93, 0x0B, 0x00, pinLo, pinHi, 0x00, 0x00, 0xFF, 0xFF]).appendCRC
33
+ loop do
34
+ status.invalidate
35
+ begin
36
+ log.info "opening connection to heatmiser at #{hostname}:#{port}"
37
+ TCPSocket.open hostname, port do | socket |
38
+ log.info "connected to heatmiser at #{hostname}:#{port}"
39
+ loop do
40
+ begin
41
+ sleep 5
42
+ command = queryCommand
43
+ if queuedCommand = queue.get
44
+ command = queuedCommand
45
+ else
46
+ if status.get{status.valid ? status.deviceTimeOffset : 0.0}.abs > 5.0
47
+ timeNow = Time.now
48
+ dayOfWeek = timeNow.wday
49
+ dayOfWeek = 7 if dayOfWeek == 0
50
+ command = HeatmiserCRC.new([0xA3, 0x12, 0x00, pinLo, pinHi, 0x01, 0x2B, 0x00, 0x07,
51
+ timeNow.year - 2000,
52
+ timeNow.month,
53
+ timeNow.day,
54
+ dayOfWeek,
55
+ timeNow.hour,
56
+ timeNow.min,
57
+ timeNow.sec]).appendCRC
58
+ log.info "clock correction: #{TraceLog.hex command}"
59
+ end
60
+ end
61
+ log.debug "sending command: #{TraceLog.hex command}" if log.debug?
62
+ reply = []
63
+ startTime = Time.now
64
+ timeout 20 do
65
+ socket.write command.pack('c*')
66
+ reply = socket.read(81).unpack('c*')
67
+ end
68
+ timestamp = Time.now
69
+ log.debug "reply: #{TraceLog.hex reply}" if log.debug?
70
+ crcHi = reply.pop & 0xFF
71
+ crcLo = reply.pop & 0xFF
72
+ crc = HeatmiserCRC.new reply
73
+ if (reply[0] & 0xFF) == 0x94 and reply[1] == 0x51 and reply[2] == 0 and
74
+ crc.crcHi == crcHi and crc.crcLo == crcLo
75
+ reply << crcLo << crcHi
76
+ status.set reply, timestamp, (timestamp - startTime) do
77
+ queue.completed if queuedCommand
78
+ end
79
+ end
80
+ rescue Timeout::Error
81
+ log.info "heatmiser at #{hostname}:#{port} is not responding - assuming connection down"
82
+ break
83
+ rescue => error
84
+ log.error error
85
+ break
86
+ end
87
+ end
88
+ log.info "closing connection to heatmiser at #{hostname}:#{port}"
89
+ socket.close
90
+ end
91
+ rescue => error
92
+ log.error error
93
+ end
94
+ sleep 10
95
+ end
96
+ end
97
+ end
98
+
99
+ def wait
100
+ @thread.join
101
+ end
102
+
103
+ end
104
+
105
+ end
106
+ end
107
+ end
@@ -0,0 +1,70 @@
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 'thread'
11
+ require 'socket'
12
+ require 'sappho-heatmiser-proxy/trace_log'
13
+ require 'sappho-heatmiser-proxy/heatmiser_status'
14
+ require 'sappho-heatmiser-proxy/command_queue'
15
+ require 'sappho-heatmiser-proxy/client_register'
16
+
17
+ class HeatmiserClient
18
+
19
+ def session client
20
+ @clients = ClientRegister.instance
21
+ @clients.register client
22
+ @ip = @clients.ip client
23
+ @client = client
24
+ @status = HeatmiserStatus.instance
25
+ @log = TraceLog.instance
26
+ Thread.new do
27
+ loop do
28
+ begin
29
+ timeout 20 do
30
+ command = read 5
31
+ @log.debug "header: #{TraceLog.hex command}" if @log.debug?
32
+ packetSize = (command[1] & 0xFF) | ((command[2] << 8) & 0x0F00)
33
+ command += read(packetSize - 5)
34
+ CommandQueue.instance.push @ip, command unless (command[0] & 0xFF) == 0x93
35
+ @status.get { @client.write @status.raw.pack('c*') if @status.valid }
36
+ @log.info "command received from client #{@ip} so it is alive"
37
+ end
38
+ rescue Timeout::Error
39
+ @log.info "no command received from client #{@ip} so presuming it dormant"
40
+ break
41
+ rescue HeatmiserClient::ReadError
42
+ @log.info "unable to receive data from client #{@ip} so presuming it has disconnected"
43
+ break
44
+ rescue => error
45
+ @log.error error
46
+ break
47
+ end
48
+ end
49
+ begin
50
+ @client.close
51
+ rescue
52
+ end
53
+ @clients.unregister @client
54
+ end
55
+ end
56
+
57
+ def read size
58
+ data = @client.read size
59
+ raise HeatmiserClient::ReadError unless data and data.size == size
60
+ data.unpack('c*')
61
+ end
62
+
63
+ class ReadError < Interrupt
64
+ end
65
+
66
+ end
67
+
68
+ end
69
+ end
70
+ end
@@ -0,0 +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
@@ -0,0 +1,42 @@
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_client'
11
+ require 'sappho-heatmiser-proxy/client_register'
12
+ require 'thread'
13
+ require 'socket'
14
+ require 'sappho-heatmiser-proxy/trace_log'
15
+
16
+ class HeatmiserProxy
17
+
18
+ def serve
19
+ Thread.new do
20
+ clients = ClientRegister.instance
21
+ port = Integer SystemConfiguration.instance.config['heatmiser.port']
22
+ log = TraceLog.instance
23
+ log.info "opening proxy server port #{port}"
24
+ TCPServer.open port do | server |
25
+ log.info "proxy server port #{port} is now open"
26
+ loop do
27
+ if clients.maxAlreadyConnected?
28
+ sleep 1
29
+ else
30
+ log.info "listening for new clients on proxy server port #{port}"
31
+ HeatmiserClient.new.session server.accept
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
37
+
38
+ end
39
+
40
+ end
41
+ end
42
+ end
@@ -0,0 +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-heatmiser-proxy/trace_log'
13
+
14
+ class HeatmiserStatus
15
+
16
+ include Singleton
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 = TraceLog.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 "#{TraceLog.hex 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
@@ -0,0 +1,27 @@
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 :config
18
+
19
+ def initialize
20
+ @config = YAML.load_file(File.expand_path(ARGV[0] || 'heatmiser-proxy.yml'))
21
+ end
22
+
23
+ end
24
+
25
+ end
26
+ end
27
+ end
@@ -0,0 +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 'logger'
13
+ require 'sappho-heatmiser-proxy/system_configuration'
14
+ require 'sappho-heatmiser-proxy/version'
15
+
16
+ class TraceLog
17
+
18
+ include Singleton
19
+
20
+ def initialize
21
+ @mutex = Mutex.new
22
+ config = SystemConfiguration.instance.config
23
+ @log = Logger.new(config['log.stdout'] ? STDOUT : config['log.filename'])
24
+ @log.level = config['log.debug'] ? Logger::DEBUG : Logger::INFO
25
+ @log.formatter = proc { |severity, datetime, progname, message| "#{message}\n" }
26
+ @log.info "#{NAME} version #{VERSION} - #{HOMEPAGE}"
27
+ end
28
+
29
+ def info message
30
+ @mutex.synchronize do
31
+ @log.info message
32
+ end if @log.info?
33
+ end
34
+
35
+ def debug message
36
+ @mutex.synchronize do
37
+ @log.debug message
38
+ end if @log.debug?
39
+ end
40
+
41
+ def error error
42
+ @mutex.synchronize do
43
+ @log.error "error! #{error.message}"
44
+ error.backtrace.each { |error| @log.error error }
45
+ end if @log.error?
46
+ end
47
+
48
+ def debug?
49
+ @log.debug?
50
+ end
51
+
52
+ def TraceLog.hex bytes
53
+ (bytes.collect {|byte| "%02x " % (byte & 0xFF)}).join
54
+ end
55
+
56
+ end
57
+
58
+ end
59
+ end
60
+ end
@@ -0,0 +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.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
metadata ADDED
@@ -0,0 +1,93 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: sappho-heatmiser-proxy
3
+ version: !ruby/object:Gem::Version
4
+ hash: 29
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 1
10
+ version: 0.0.1
11
+ platform: ruby
12
+ authors:
13
+ - Andrew Heald
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2012-02-26 00:00:00 Z
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: rake
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ none: false
25
+ requirements:
26
+ - - ">="
27
+ - !ruby/object:Gem::Version
28
+ hash: 11
29
+ segments:
30
+ - 0
31
+ - 9
32
+ - 2
33
+ - 2
34
+ version: 0.9.2.2
35
+ type: :development
36
+ version_requirements: *id001
37
+ description: See the project home page for more information
38
+ email:
39
+ - andrew@heald.co.uk
40
+ executables:
41
+ - sappho-heatmiser-proxy
42
+ extensions: []
43
+
44
+ extra_rdoc_files: []
45
+
46
+ files:
47
+ - bin/sappho-heatmiser-proxy
48
+ - lib/sappho-heatmiser-proxy.rb
49
+ - lib/sappho-heatmiser-proxy/client_register.rb
50
+ - lib/sappho-heatmiser-proxy/command_queue.rb
51
+ - lib/sappho-heatmiser-proxy/heatmiser.rb
52
+ - lib/sappho-heatmiser-proxy/heatmiser_client.rb
53
+ - lib/sappho-heatmiser-proxy/heatmiser_crc.rb
54
+ - lib/sappho-heatmiser-proxy/heatmiser_proxy.rb
55
+ - lib/sappho-heatmiser-proxy/heatmiser_status.rb
56
+ - lib/sappho-heatmiser-proxy/system_configuration.rb
57
+ - lib/sappho-heatmiser-proxy/trace_log.rb
58
+ - lib/sappho-heatmiser-proxy/version.rb
59
+ homepage: https://github.com/sappho/sappho-heatmiser-proxy/wiki
60
+ licenses: []
61
+
62
+ post_install_message:
63
+ rdoc_options: []
64
+
65
+ require_paths:
66
+ - lib
67
+ required_ruby_version: !ruby/object:Gem::Requirement
68
+ none: false
69
+ requirements:
70
+ - - ">="
71
+ - !ruby/object:Gem::Version
72
+ hash: 3
73
+ segments:
74
+ - 0
75
+ version: "0"
76
+ required_rubygems_version: !ruby/object:Gem::Requirement
77
+ none: false
78
+ requirements:
79
+ - - ">="
80
+ - !ruby/object:Gem::Version
81
+ hash: 3
82
+ segments:
83
+ - 0
84
+ version: "0"
85
+ requirements: []
86
+
87
+ rubyforge_project: sappho-heatmiser-proxy
88
+ rubygems_version: 1.8.17
89
+ signing_key:
90
+ specification_version: 3
91
+ summary: Acts as a proxy for Heatmiser hardware to allow continuous monitoring and control by many controllers
92
+ test_files: []
93
+