thomas-ghysbrecht-thermostat-exercise 0.1.2.pre.a

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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: bd2a9d561838ec347e9472ce9d99afe78a35eb1e
4
+ data.tar.gz: e0700576bdd5ac5d5517bf80da662684f01b669a
5
+ SHA512:
6
+ metadata.gz: 57a6b7915f5f8622ae6fa79b82f78675daff5c0fac8b3a80344cd1e382b90d4087437affc966cbd6f42cf10c621a7709e62cd49427bc095d268954715a50c8e9
7
+ data.tar.gz: daacfb7593ebb0a02906a0d1a4c8ef86108be863fee0beb57756272b89d27d726b2591f7920f6110d8e19f4a6998c987bc0679d517b46d08d868d3c4de130f26
data/bin/thermostat ADDED
@@ -0,0 +1,64 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require_relative "../lib/thermos.rb"
4
+ require_relative "../lib/httpsvalue.rb"
5
+ require_relative "../lib/logger.rb"
6
+ require_relative "../lib/status.rb"
7
+ require_relative "../lib/mqtttemp.rb"
8
+ require_relative "../lib/parser.rb"
9
+ require "OpenSSL"
10
+ require 'json'
11
+ require 'rubygems'
12
+
13
+ parser_var = Parser.new
14
+ options = parser_var.parse(ARGV)
15
+
16
+ logger = ThermoLogger.new()
17
+ status = Status.new()
18
+
19
+ if(options.mqtt)
20
+ mqtttemp = Mqtttemp.new(options.mqtt)
21
+ end
22
+
23
+ nest = Thermos.new(options.target, options.range)
24
+
25
+ #Get a termperature from the console arguments
26
+ if(options.kelvin || options.celcius || options.fahrenheit)
27
+ nest.set_kelvin(options.kelvin) if options.kelvin
28
+ nest.set_celcius(options.celcius) if options.celcius
29
+ nest.set_fahrenheit(options.fahrenheit) if options.fahrenheit
30
+ status.get_status(nest)
31
+ logger.log_event(nest)
32
+ end
33
+
34
+
35
+ #Get a temperature from the internet
36
+ if(options.httplink)
37
+ OpenSSL::SSL::VERIFY_PEER = OpenSSL::SSL::VERIFY_NONE #Bypass the SSL certificate problem, but gives a warning :(
38
+ httpsvalue = Httpsvalue.new
39
+ nest.set_celcius(httpsvalue.get_value(options.httplink).to_f)
40
+ status.get_status(nest)
41
+ logger.log_event(nest)
42
+ end
43
+
44
+ #Get a temperature from a Json file
45
+ if(options.json)
46
+ nest.set_celcius(JSON.parse(File.read(options.json))["temperature"].to_f)
47
+ status.get_status(nest)
48
+ logger.log_event(nest)
49
+ end
50
+
51
+ #Get the temperature from MQTT
52
+ if(options.subscribe)
53
+ mqtttemp.on_change do |temp|
54
+ nest.set_celcius(temp);
55
+ status.get_status(nest);
56
+ logger.log_event(nest);
57
+ mqtttemp.send_led_hex(nest.get_hex_leds, options.publish) if options.publish
58
+ end
59
+
60
+ mqtttemp.enable_thread(options.subscribe);
61
+
62
+ while(true)
63
+ end
64
+ end
data/lib/httpsvalue.rb ADDED
@@ -0,0 +1,10 @@
1
+ # The Httpsvalue returns a value on a webpage.
2
+ #
3
+ # @author Thomas Ghysbrecht <ghysbrecht@hotmail.com>
4
+ class Httpsvalue
5
+ require "open-uri"
6
+ # Get a value fromt this url
7
+ def get_value(url)
8
+ data = URI.parse(url).read
9
+ end
10
+ end
data/lib/logger.rb ADDED
@@ -0,0 +1,25 @@
1
+ require 'date'
2
+
3
+ # The ThermoLoger class logs the thermos object's status in a file.
4
+ #
5
+ # @author Thomas Ghysbrecht <ghysbrecht@hotmail.com>
6
+ class ThermoLogger
7
+
8
+ # Logs a message to a file
9
+ def log_message(message)
10
+ open('log.txt', 'a') do |f|
11
+ f.puts message
12
+ end
13
+ end
14
+
15
+ # Logs the thermos class to a file
16
+ def log_event(thermos)
17
+ current_time = DateTime.now
18
+ log_message("-------------------------------------------------------")
19
+ log_message(current_time.strftime "%d/%m/%Y %H:%M:%S")
20
+ log_message("Received temperature value: " + thermos.temperature.to_s)
21
+ log_message("Led value: " + thermos.get_hex_leds)
22
+ log_message("Heater is " + (thermos.relaisHeater ? "ON" : "OFF"))
23
+ log_message("Cooler is " + (thermos.relaisCooler ? "ON" : "OFF"))
24
+ end
25
+ end
data/lib/mqtttemp.rb ADDED
@@ -0,0 +1,53 @@
1
+ require 'mqtt'
2
+
3
+ # Mqtt class that makes it possible to receive and send values via mqtt.
4
+ #
5
+ # You can attach a block of code to run when a value is received. Also you can
6
+ # send the led hex value via mqtt to a specified topic.
7
+ # @author Thomas Ghysbrecht <ghysbrecht@hotmail.com>
8
+ class Mqtttemp
9
+
10
+ # Set up the class with the brokere server address
11
+ def initialize(server)
12
+ @server = server;
13
+ end
14
+
15
+ # Attachach a codeblock that will be executed when a value is received
16
+ def on_change &block
17
+ @on_change_block = block
18
+ end
19
+
20
+ # Enable a thread that executes the on_change block when something is
21
+ # received on the topic given via the argument.
22
+ def enable_thread(mqtt_topic)
23
+ Thread.new do
24
+ MQTT::Client.connect(@server) do |c|
25
+ c.get(mqtt_topic) do |topic,message|
26
+ if(isValidJson(message))
27
+ @on_change_block.call(JSON.parse(message)["temperature"]) unless @on_change_block.nil?
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
33
+
34
+
35
+ def isValidJson(json)
36
+ JSON.parse(json)
37
+ return true
38
+ rescue JSON::ParserError => e
39
+ return false
40
+ end
41
+
42
+ # Send a hex value via MQTT to a topic.
43
+ # Argumens:
44
+ # hex (string) : The hex value that needs to be sent in format "FFAA33".
45
+ # topic (string) : The topic where to send the hex value to.
46
+ def send_led_hex(hex, topic)
47
+ MQTT::Client.connect(@server) do |c|
48
+ data = '{"color":"'+ hex +'"}'
49
+ c.publish(topic, data)
50
+ end
51
+ end
52
+
53
+ end
data/lib/parser.rb ADDED
@@ -0,0 +1,68 @@
1
+ require 'optparse'
2
+
3
+ Options = Struct.new(:kelvin, :celcius, :target, :fahrenheit, :range, :httplink, :mqtt, :json, :subscribe, :publish )
4
+
5
+ # Parser class using optparse, this makes it possible to easly use this
6
+ # app as an CLI app.
7
+ # @author Thomas Ghysbrecht <ghysbrecht@hotmail.com>
8
+ class Parser
9
+ def parse(options)
10
+ args = Options.new()
11
+
12
+ opt_parser = OptionParser.new do |opts|
13
+ opts.banner = "Usage: app.rb [options]"
14
+
15
+ opts.on("-K", "--Kelvin=TEMP",Float, "Temperature in Kelvin") do |arg|
16
+ args.kelvin = arg
17
+ end
18
+
19
+ opts.on("-C", "--Celcius=TEMP",Float, "Temperature in Celcius") do |arg|
20
+ args.celcius = arg
21
+ end
22
+
23
+ opts.on("-F", "--Fahrenheit=TEMP",Float, "Temperature in Fahrenheit") do |arg|
24
+ args.fahrenheit = arg
25
+ end
26
+
27
+ opts.on("-t", "--target=TEMP",Float, "Target temperature") do |arg|
28
+ args.target = arg
29
+ end
30
+
31
+ opts.on("-r", "--range=TEMP",Float, "Range for temperature") do |arg|
32
+ args.range = arg
33
+ end
34
+
35
+ opts.on("-H", "--httpget=LINK", "Get the temperature from the link") do |arg|
36
+ args.httplink = arg
37
+ end
38
+
39
+ opts.on("-m", "--mqtt=LINK", "Set the mqtt broker link") do |arg|
40
+ args.mqtt = arg
41
+ end
42
+
43
+ opts.on("-s", "--subscribe=NAME", "Subscribe to MQTT channel (broker link mandatory)") do |arg|
44
+ args.subscribe = arg
45
+ end
46
+
47
+ opts.on("-p", "--publish=NAME", "Publish to MQTT channel (broker link mandatory)") do |arg|
48
+ args.publish = arg
49
+ end
50
+
51
+ opts.on("-j", "--json=FILENAME", "Use a JSON file for the temperature") do |arg|
52
+ args.json = arg
53
+ end
54
+
55
+ opts.on("-h", "--help", "Prints this help") do
56
+ puts opts
57
+ exit
58
+ end
59
+ end
60
+
61
+ opt_parser.parse!(options)
62
+
63
+ raise OptionParser::MissingArgument if args.range.nil?
64
+ raise OptionParser::MissingArgument if args.target.nil?
65
+
66
+ return args
67
+ end
68
+ end
data/lib/status.rb ADDED
@@ -0,0 +1,25 @@
1
+ # Status class that prints out the themos object's status
2
+ #
3
+ # @author Thomas Ghysbrecht <ghysbrecht@hotmail.com>
4
+ class Status
5
+ # Prints out the current status in the console
6
+ def get_status(nest)
7
+ puts "----------------------------------------------------------------------------------------"
8
+ puts "+-------------------------+"
9
+ puts "| Led Status |"
10
+ puts "+-------------------------+"
11
+ puts "Red led: #{nest.red.round(0)}"
12
+ puts "Green led: #{nest.green.round(0)}"
13
+ puts "Blue led: #{nest.blue.round(0)}"
14
+ puts "Hex value: " + nest.get_hex_leds
15
+ puts "+-------------------------+"
16
+ puts "| Relais Status |"
17
+ puts "+-------------------------+"
18
+ puts "Cooler: " + (nest.relaisCooler ? "ON" : "OFF")
19
+ puts "Heater: " + (nest.relaisHeater ? "ON" : "OFF")
20
+ puts "+-------------------------+"
21
+ puts "| Temperature Status |"
22
+ puts "+-------------------------+"
23
+ puts "Temperature: #{nest.temperature.round(1)}"
24
+ end
25
+ end
data/lib/thermos.rb ADDED
@@ -0,0 +1,90 @@
1
+ # Temperature class with multiple temperature compatibility
2
+ #
3
+ # The Temperature class stores a temperature. And decides the led color and relais.
4
+ # @author Thomas Ghysbrecht <ghysbrecht@hotmail.com>
5
+ class Thermos
6
+
7
+ attr_accessor :target
8
+ attr_accessor :range
9
+
10
+ attr_reader :red
11
+ attr_reader :green
12
+ attr_reader :blue
13
+ attr_reader :relaisCooler
14
+ attr_reader :relaisHeater
15
+ attr_reader :temperature
16
+
17
+ # Initializes the class with a target and range
18
+ # Arguments:
19
+ # - target (float) : The target temperature
20
+ # - range (float) : What temperatures are acceptable around the target
21
+ def initialize(target, range)
22
+ @target = target
23
+ @range = range
24
+ reset_leds
25
+ @relaisCooler = false;
26
+ @relaisHeater = false;
27
+ end
28
+
29
+ # Sets the temperature with a Celcius value.
30
+ # This method also reset and sets the leds.
31
+ def set_celcius (temperature)
32
+ @temperature = temperature
33
+ reset_leds
34
+ set_leds
35
+ end
36
+
37
+ # Sets the temperature with a Kelvin value
38
+ # This method also reset and sets the leds.
39
+ def set_kelvin (temperature)
40
+ @temperature = temperature - 273.15
41
+ reset_leds
42
+ set_leds
43
+ end
44
+
45
+ # Sets the temperature with a Fahrenheit value
46
+ # This method also reset and sets the leds.
47
+ def set_fahrenheit (temperature)
48
+ @temperature = (temperature - 32)/1.8
49
+ reset_leds
50
+ set_leds
51
+ end
52
+
53
+ def reset_leds
54
+ @red = 0.0
55
+ @green = 0.0
56
+ @blue = 0.0
57
+ end
58
+
59
+
60
+ def set_leds
61
+ if(@temperature < (@target - @range))
62
+ multiplier = ( (@target - @temperature) / (5 * @range)) #5 times the range from the target is very blue
63
+ multiplier > 1 ? multiplier = 1 : multiplier = multiplier
64
+ @blue = 255*multiplier
65
+
66
+ @relaisHeater = true;
67
+ @relaisCooler = false;
68
+
69
+ elsif(@temperature > (@target + @range))
70
+ multiplier = ( (@temperature - @target) / (5 * @range)) #5 times the range from the target is very red
71
+ multiplier > 1 ? multiplier = 1 : multiplier = multiplier
72
+ @red = 255*multiplier
73
+
74
+ @relaisHeater = false;
75
+ @relaisCooler = true;
76
+ else
77
+ multiplier = ((@temperature - @target).abs / @range ) #0 time the range from the target is very green
78
+ @green = 255*(1-multiplier)
79
+
80
+ @relaisHeater = false;
81
+ @relaisCooler = false;
82
+ end
83
+ end
84
+
85
+ # Return the led status in hex format -> FF88AA
86
+ def get_hex_leds
87
+ "%02x%02x%02x" % [@red,@green,@blue]
88
+ end
89
+
90
+ end
metadata ADDED
@@ -0,0 +1,51 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: thomas-ghysbrecht-thermostat-exercise
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.2.pre.a
5
+ platform: ruby
6
+ authors:
7
+ - Thomas Ghysbrecht
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-05-09 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: A thermostat simulator in ruby
14
+ email: ghysbrecht@hotmail.com
15
+ executables:
16
+ - thermostat
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - bin/thermostat
21
+ - lib/httpsvalue.rb
22
+ - lib/logger.rb
23
+ - lib/mqtttemp.rb
24
+ - lib/parser.rb
25
+ - lib/status.rb
26
+ - lib/thermos.rb
27
+ homepage: https://github.com/thomieboy/ruby-thermos
28
+ licenses:
29
+ - MIT
30
+ metadata: {}
31
+ post_install_message:
32
+ rdoc_options: []
33
+ require_paths:
34
+ - lib
35
+ required_ruby_version: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ">="
38
+ - !ruby/object:Gem::Version
39
+ version: '0'
40
+ required_rubygems_version: !ruby/object:Gem::Requirement
41
+ requirements:
42
+ - - ">"
43
+ - !ruby/object:Gem::Version
44
+ version: 1.3.1
45
+ requirements: []
46
+ rubyforge_project:
47
+ rubygems_version: 2.5.2
48
+ signing_key:
49
+ specification_version: 4
50
+ summary: Ruby thermostat
51
+ test_files: []