garden_messenger 0.1.0 → 0.2.0
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 +4 -4
- data/.rubocop.yml +1 -1
- data/Gemfile.lock +16 -4
- data/README.md +4 -4
- data/exe/garden_messenger +1 -50
- data/garden_messenger.gemspec +1 -1
- data/lib/garden_messenger/atlas_scientific/ec.rb +21 -0
- data/lib/garden_messenger/atlas_scientific/i2c_device.rb +100 -0
- data/lib/garden_messenger/atlas_scientific/ph.rb +17 -0
- data/lib/garden_messenger/atlas_scientific/temperature.rb +13 -0
- data/lib/garden_messenger/cli.rb +57 -0
- data/lib/garden_messenger/reporter.rb +1 -1
- data/lib/garden_messenger/version.rb +1 -1
- data/lib/garden_messenger.rb +5 -0
- metadata +16 -11
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: a7b25c790bf561282f4fb0e150d2a6d5e75cbae1f7e2a7176af43a25caef39d9
|
|
4
|
+
data.tar.gz: 9e7109e232c79bea95bba4a1a7b885809bcddbd909af94f9ed5bb7ba26f72700
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 2d90a0176635a0c122c70f169c9233bcfe7cad1851b8abf2ba3f855ea8e5f27093a10ea1a28614b00608cc7a8b3832f725a1e5740b41fac4ab671f9de293122c
|
|
7
|
+
data.tar.gz: 99a55d17590b04f90e76a2c4ec6680f46e7c40179629681bac3b7c5da15a1fdbd2b3e0b66ad771982479bda83f81db9fb728b7bcf9389b0c6b847d97d2a85754
|
data/.rubocop.yml
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
inherit_from:
|
|
2
|
-
- https://raw.githubusercontent.com/siegy22/dotfiles/
|
|
2
|
+
- https://raw.githubusercontent.com/siegy22/dotfiles/c4b42f0bba4e4eb0a573d538ecc99266be90a8f8/rubocop.yml
|
data/Gemfile.lock
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
garden_messenger (0.
|
|
4
|
+
garden_messenger (0.2.0)
|
|
5
5
|
action_cable_client (~> 3.0)
|
|
6
6
|
http (~> 4.1)
|
|
7
|
-
i2c-devices (~> 0.0.6)
|
|
8
7
|
thor (~> 0.20)
|
|
9
8
|
|
|
10
9
|
GEM
|
|
@@ -12,9 +11,16 @@ GEM
|
|
|
12
11
|
specs:
|
|
13
12
|
action_cable_client (3.0.1)
|
|
14
13
|
websocket-eventmachine-client (>= 1.2.0)
|
|
14
|
+
activesupport (6.0.0.rc1)
|
|
15
|
+
concurrent-ruby (~> 1.0, >= 1.0.2)
|
|
16
|
+
i18n (>= 0.7, < 2)
|
|
17
|
+
minitest (~> 5.1)
|
|
18
|
+
tzinfo (~> 1.1)
|
|
19
|
+
zeitwerk (~> 2.1, >= 2.1.4)
|
|
15
20
|
addressable (2.6.0)
|
|
16
21
|
public_suffix (>= 2.0.2, < 4.0)
|
|
17
22
|
ast (2.4.0)
|
|
23
|
+
concurrent-ruby (1.1.5)
|
|
18
24
|
domain_name (0.5.20180417)
|
|
19
25
|
unf (>= 0.0.5, < 1.0.0)
|
|
20
26
|
eventmachine (1.2.7)
|
|
@@ -27,7 +33,8 @@ GEM
|
|
|
27
33
|
domain_name (~> 0.5)
|
|
28
34
|
http-form_data (2.1.1)
|
|
29
35
|
http_parser.rb (0.6.0)
|
|
30
|
-
|
|
36
|
+
i18n (1.6.0)
|
|
37
|
+
concurrent-ruby (~> 1.0)
|
|
31
38
|
jaro_winkler (1.5.2)
|
|
32
39
|
minitest (5.11.3)
|
|
33
40
|
parallel (1.17.0)
|
|
@@ -47,9 +54,12 @@ GEM
|
|
|
47
54
|
unicode-display_width (>= 1.4.0, < 1.6)
|
|
48
55
|
ruby-progressbar (1.10.0)
|
|
49
56
|
thor (0.20.3)
|
|
57
|
+
thread_safe (0.3.6)
|
|
58
|
+
tzinfo (1.2.5)
|
|
59
|
+
thread_safe (~> 0.1)
|
|
50
60
|
unf (0.1.4)
|
|
51
61
|
unf_ext
|
|
52
|
-
unf_ext (0.0.7.
|
|
62
|
+
unf_ext (0.0.7.6)
|
|
53
63
|
unicode-display_width (1.5.0)
|
|
54
64
|
websocket (1.2.8)
|
|
55
65
|
websocket-eventmachine-base (1.2.0)
|
|
@@ -59,11 +69,13 @@ GEM
|
|
|
59
69
|
websocket-eventmachine-client (1.2.0)
|
|
60
70
|
websocket-eventmachine-base (~> 1.0)
|
|
61
71
|
websocket-native (1.0.0)
|
|
72
|
+
zeitwerk (2.1.5)
|
|
62
73
|
|
|
63
74
|
PLATFORMS
|
|
64
75
|
ruby
|
|
65
76
|
|
|
66
77
|
DEPENDENCIES
|
|
78
|
+
activesupport (= 6.0.0.rc1)
|
|
67
79
|
bundler (~> 2.0)
|
|
68
80
|
garden_messenger!
|
|
69
81
|
minitest (~> 5.0)
|
data/README.md
CHANGED
|
@@ -6,10 +6,10 @@ Collects data of [AtlasScientific](https://www.atlas-scientific.com/) and [myStr
|
|
|
6
6
|
|
|
7
7
|
Currently supported:
|
|
8
8
|
|
|
9
|
-
[
|
|
10
|
-
[
|
|
11
|
-
[
|
|
12
|
-
[x] [myStrom Switch (CH)](https://mystrom.ch/wifi-switch-ch/)
|
|
9
|
+
- [x] [pH Kit](https://www.atlas-scientific.com/product_pages/kits/ph-kit.html)
|
|
10
|
+
- [x] [Conductivity Kit](https://www.atlas-scientific.com/product_pages/kits/ec_k1_0_kit.html)
|
|
11
|
+
- [x] [Temperature Kit](https://www.atlas-scientific.com/product_pages/kits/temp_kit.html)
|
|
12
|
+
- [x] [myStrom Switch (CH)](https://mystrom.ch/wifi-switch-ch/)
|
|
13
13
|
|
|
14
14
|
|
|
15
15
|
## Installation
|
data/exe/garden_messenger
CHANGED
|
@@ -1,54 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env ruby
|
|
2
2
|
|
|
3
3
|
require 'garden_messenger'
|
|
4
|
-
require 'thor'
|
|
5
4
|
|
|
6
|
-
|
|
7
|
-
desc 'report MONITOR_URL TOKEN [options]', 'Report to a monitor which is located on MONITOR_URL'
|
|
8
|
-
option 'wattage-switch-host'
|
|
9
|
-
option 'update-rate'
|
|
10
|
-
option 'verbose', type: :boolean
|
|
11
|
-
def report(monitor_url, token)
|
|
12
|
-
reporter = GardenMessenger::Reporter.new(
|
|
13
|
-
monitor_url,
|
|
14
|
-
token,
|
|
15
|
-
options.fetch('update-rate') { 30 },
|
|
16
|
-
options.fetch('verbose') { false }
|
|
17
|
-
)
|
|
18
|
-
|
|
19
|
-
reporter.report! do
|
|
20
|
-
data = {}
|
|
21
|
-
|
|
22
|
-
if options.key?('wattage-switch-host')
|
|
23
|
-
wattage = GardenMessenger::Wattage.new(options['wattage-switch-host'])
|
|
24
|
-
data[:wattage] = wattage.get
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
data[:temp] = rand(18.0...26.0)
|
|
28
|
-
data[:ph] = rand(4.0...8.0)
|
|
29
|
-
data[:ec] = rand(0.8...1.6)
|
|
30
|
-
|
|
31
|
-
data
|
|
32
|
-
end
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
desc 'dev', 'Report random values to local monitor'
|
|
36
|
-
def dev
|
|
37
|
-
reporter = GardenMessenger::Reporter.new(
|
|
38
|
-
'ws://localhost:3000/cable',
|
|
39
|
-
'dev-token',
|
|
40
|
-
1,
|
|
41
|
-
true
|
|
42
|
-
)
|
|
43
|
-
|
|
44
|
-
reporter.report! do
|
|
45
|
-
temp = rand(18.0...26.0)
|
|
46
|
-
ph = rand(4.0...8.0)
|
|
47
|
-
ec = rand(0.8...1.6)
|
|
48
|
-
wattage = rand(700.0...800.0)
|
|
49
|
-
{ temp: temp, ph: ph, ec: ec, wattage: wattage }
|
|
50
|
-
end
|
|
51
|
-
end
|
|
52
|
-
end
|
|
53
|
-
|
|
54
|
-
MessengerCLI.start(ARGV)
|
|
5
|
+
GardenMessenger::CLI.start(ARGV)
|
data/garden_messenger.gemspec
CHANGED
|
@@ -24,9 +24,9 @@ Gem::Specification.new do |spec|
|
|
|
24
24
|
|
|
25
25
|
spec.add_dependency 'action_cable_client', '~> 3.0'
|
|
26
26
|
spec.add_dependency 'http', '~> 4.1'
|
|
27
|
-
spec.add_dependency 'i2c-devices', '~> 0.0.6'
|
|
28
27
|
spec.add_dependency 'thor', '~> 0.20'
|
|
29
28
|
|
|
29
|
+
spec.add_development_dependency 'activesupport', '6.0.0.rc1'
|
|
30
30
|
spec.add_development_dependency 'bundler', '~> 2.0'
|
|
31
31
|
spec.add_development_dependency 'minitest', '~> 5.0'
|
|
32
32
|
spec.add_development_dependency 'rake', '~> 10.0'
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
require 'garden_messenger/atlas_scientific/i2c_device'
|
|
2
|
+
|
|
3
|
+
module GardenMessenger
|
|
4
|
+
module AtlasScientific
|
|
5
|
+
# Abstraction layer to EZO Conductivity Circuit
|
|
6
|
+
# https://www.atlas-scientific.com/product_pages/circuits/ezo_ec.html
|
|
7
|
+
class EC < I2CDevice
|
|
8
|
+
def initialize(address = 0x64)
|
|
9
|
+
super(address)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def probe_type=(type)
|
|
13
|
+
k(type)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def k(*args)
|
|
17
|
+
execute('k', *args)
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
module GardenMessenger
|
|
2
|
+
module AtlasScientific
|
|
3
|
+
class I2CDevice
|
|
4
|
+
class NoDataToSendError < StandardError; end
|
|
5
|
+
class StillProcessingError < StandardError; end
|
|
6
|
+
class CommandSyntaxError < StandardError; end
|
|
7
|
+
class UnknownStatusCodeError < StandardError; end
|
|
8
|
+
|
|
9
|
+
STILL_PROCESSING = 254
|
|
10
|
+
I2C_SLAVE = 0x0703
|
|
11
|
+
|
|
12
|
+
def initialize(address, path = Dir.glob('/dev/i2c-*').first)
|
|
13
|
+
@address = address
|
|
14
|
+
@path = path
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# Takes a reading using the r ezo command
|
|
18
|
+
# and casts it to a float
|
|
19
|
+
def reading
|
|
20
|
+
r.to_f
|
|
21
|
+
end
|
|
22
|
+
alias take_reading reading
|
|
23
|
+
alias read reading
|
|
24
|
+
|
|
25
|
+
def take_reading_with_temperature_compensation(temperature)
|
|
26
|
+
rt(temperature.to_s).to_f
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def calibrated?
|
|
30
|
+
!execute('cal', '?').casecmp?('?cal,0')
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
[
|
|
34
|
+
'baud',
|
|
35
|
+
'cal',
|
|
36
|
+
'factory',
|
|
37
|
+
'find',
|
|
38
|
+
'i',
|
|
39
|
+
'i2c',
|
|
40
|
+
'l',
|
|
41
|
+
'o',
|
|
42
|
+
'plock',
|
|
43
|
+
'r',
|
|
44
|
+
'rt',
|
|
45
|
+
'sleep',
|
|
46
|
+
'status',
|
|
47
|
+
't'
|
|
48
|
+
].each do |cmd|
|
|
49
|
+
define_method(cmd) do |*args|
|
|
50
|
+
execute(cmd, *args)
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
alias information i
|
|
55
|
+
|
|
56
|
+
alias temperature_compensation t
|
|
57
|
+
|
|
58
|
+
alias protocol_lock plock
|
|
59
|
+
|
|
60
|
+
def execute(command, *args)
|
|
61
|
+
io = File.open(@path, 'r+')
|
|
62
|
+
# Set i2c address and mode
|
|
63
|
+
io.ioctl(I2C_SLAVE, @address)
|
|
64
|
+
|
|
65
|
+
# Prepare EZO command like
|
|
66
|
+
ezo_command = [command, *args].join(',')
|
|
67
|
+
|
|
68
|
+
io.syswrite(ezo_command)
|
|
69
|
+
return if command == 'sleep'
|
|
70
|
+
|
|
71
|
+
# Wait for the command to finish
|
|
72
|
+
result, status = loop do
|
|
73
|
+
result = io.read(31)
|
|
74
|
+
status = result[0].unpack1('C')
|
|
75
|
+
break [result, status] unless status == STILL_PROCESSING
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
check_for_status_code(status, ezo_command)
|
|
79
|
+
result[1..-1].strip
|
|
80
|
+
ensure
|
|
81
|
+
io&.close
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def check_for_status_code(code, ezo_command)
|
|
85
|
+
return if code == 1
|
|
86
|
+
|
|
87
|
+
case code
|
|
88
|
+
when 255
|
|
89
|
+
raise NoDataToSendError
|
|
90
|
+
when 2
|
|
91
|
+
raise CommandSyntaxError, "There was an error executing the following command: #{ezo_command}\n" \
|
|
92
|
+
'Please check the documentation of your circuit.'
|
|
93
|
+
else
|
|
94
|
+
raise UnknownStatusCodeError, "Unkown Response code: #{code} received from device.\n" \
|
|
95
|
+
'Check the latest datasheet of atlas scientific.'
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
require 'garden_messenger/atlas_scientific/i2c_device'
|
|
2
|
+
|
|
3
|
+
module GardenMessenger
|
|
4
|
+
module AtlasScientific
|
|
5
|
+
# Abstraction layer to EZO pH Circuit
|
|
6
|
+
# https://www.atlas-scientific.com/product_pages/circuits/ezo_ph.html
|
|
7
|
+
class PH < I2CDevice
|
|
8
|
+
def initialize(address = 0x63)
|
|
9
|
+
super(address)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def slope
|
|
13
|
+
execute('slope', '?')
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
require 'garden_messenger/atlas_scientific/i2c_device'
|
|
2
|
+
|
|
3
|
+
module GardenMessenger
|
|
4
|
+
module AtlasScientific
|
|
5
|
+
# Abstraction layer to EZO RTD Temperature Circuit
|
|
6
|
+
# https://www.atlas-scientific.com/product_pages/circuits/ezo_rtd.html
|
|
7
|
+
class Temperature < I2CDevice
|
|
8
|
+
def initialize(address = 0x66)
|
|
9
|
+
super(address)
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
require 'thor'
|
|
2
|
+
|
|
3
|
+
module GardenMessenger
|
|
4
|
+
class CLI < Thor
|
|
5
|
+
desc 'report MONITOR_URL TOKEN [options]', 'Report to a monitor which is located on MONITOR_URL'
|
|
6
|
+
option 'wattage-switch-host'
|
|
7
|
+
option 'update-rate'
|
|
8
|
+
option 'verbose', type: :boolean
|
|
9
|
+
def report(monitor_url, token)
|
|
10
|
+
reporter = GardenMessenger::Reporter.new(
|
|
11
|
+
monitor_url,
|
|
12
|
+
token,
|
|
13
|
+
options.fetch('update-rate') { 30 },
|
|
14
|
+
options.fetch('verbose') { false }
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
water_temperature = GardenMessenger::AtlasScientific::Temperature.new
|
|
18
|
+
ph = GardenMessenger::AtlasScientific::PH.new
|
|
19
|
+
ec = GardenMessenger::AtlasScientific::EC.new
|
|
20
|
+
wattage = GardenMessenger::Wattage.new(options['wattage-switch-host'])
|
|
21
|
+
|
|
22
|
+
reporter.report! do
|
|
23
|
+
data = { air_temp: 0.0, humidity: 0.0 }
|
|
24
|
+
|
|
25
|
+
data[:wattage] = wattage.get if options.key?('wattage-switch-host')
|
|
26
|
+
data[:water_temp] = water_temperature.take_reading
|
|
27
|
+
ph_thread = Thread.new { ph.take_reading_with_temperature_compensation(data[:water_temp]) }
|
|
28
|
+
ec_thread = Thread.new { ec.take_reading_with_temperature_compensation(data[:water_temp]) }
|
|
29
|
+
data[:ph] = ph_thread.value
|
|
30
|
+
data[:ec] = ec_thread.value
|
|
31
|
+
|
|
32
|
+
data
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
desc 'dev', 'Report random values to local monitor'
|
|
37
|
+
def dev
|
|
38
|
+
reporter = GardenMessenger::Reporter.new(
|
|
39
|
+
'ws://localhost:3000/cable',
|
|
40
|
+
'dev-token',
|
|
41
|
+
1,
|
|
42
|
+
true
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
reporter.report! do
|
|
46
|
+
{
|
|
47
|
+
air_temp: rand(18.0...30.0),
|
|
48
|
+
humidity: rand(50.0...60.0),
|
|
49
|
+
water_temp: rand(18.0...26.0),
|
|
50
|
+
ph: rand(4.0...8.0),
|
|
51
|
+
ec: rand(0.8...1.6),
|
|
52
|
+
wattage: rand(700.0...800.0)
|
|
53
|
+
}
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
data/lib/garden_messenger.rb
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
|
+
require 'garden_messenger/cli'
|
|
1
2
|
require 'garden_messenger/reporter'
|
|
2
3
|
require 'garden_messenger/version'
|
|
3
4
|
require 'garden_messenger/wattage'
|
|
5
|
+
require 'garden_messenger/atlas_scientific/i2c_device'
|
|
6
|
+
require 'garden_messenger/atlas_scientific/ph'
|
|
7
|
+
require 'garden_messenger/atlas_scientific/ec'
|
|
8
|
+
require 'garden_messenger/atlas_scientific/temperature'
|
|
4
9
|
|
|
5
10
|
module GardenMessenger
|
|
6
11
|
class Error < StandardError; end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: garden_messenger
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.2.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Yves Siegrist
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2019-
|
|
11
|
+
date: 2019-05-05 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: action_cable_client
|
|
@@ -39,33 +39,33 @@ dependencies:
|
|
|
39
39
|
- !ruby/object:Gem::Version
|
|
40
40
|
version: '4.1'
|
|
41
41
|
- !ruby/object:Gem::Dependency
|
|
42
|
-
name:
|
|
42
|
+
name: thor
|
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
|
44
44
|
requirements:
|
|
45
45
|
- - "~>"
|
|
46
46
|
- !ruby/object:Gem::Version
|
|
47
|
-
version: 0.
|
|
47
|
+
version: '0.20'
|
|
48
48
|
type: :runtime
|
|
49
49
|
prerelease: false
|
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
|
51
51
|
requirements:
|
|
52
52
|
- - "~>"
|
|
53
53
|
- !ruby/object:Gem::Version
|
|
54
|
-
version: 0.
|
|
54
|
+
version: '0.20'
|
|
55
55
|
- !ruby/object:Gem::Dependency
|
|
56
|
-
name:
|
|
56
|
+
name: activesupport
|
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
|
58
58
|
requirements:
|
|
59
|
-
- -
|
|
59
|
+
- - '='
|
|
60
60
|
- !ruby/object:Gem::Version
|
|
61
|
-
version:
|
|
62
|
-
type: :
|
|
61
|
+
version: 6.0.0.rc1
|
|
62
|
+
type: :development
|
|
63
63
|
prerelease: false
|
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
|
65
65
|
requirements:
|
|
66
|
-
- -
|
|
66
|
+
- - '='
|
|
67
67
|
- !ruby/object:Gem::Version
|
|
68
|
-
version:
|
|
68
|
+
version: 6.0.0.rc1
|
|
69
69
|
- !ruby/object:Gem::Dependency
|
|
70
70
|
name: bundler
|
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -148,6 +148,11 @@ files:
|
|
|
148
148
|
- garden_messenger.gemspec
|
|
149
149
|
- garden_messenger.service
|
|
150
150
|
- lib/garden_messenger.rb
|
|
151
|
+
- lib/garden_messenger/atlas_scientific/ec.rb
|
|
152
|
+
- lib/garden_messenger/atlas_scientific/i2c_device.rb
|
|
153
|
+
- lib/garden_messenger/atlas_scientific/ph.rb
|
|
154
|
+
- lib/garden_messenger/atlas_scientific/temperature.rb
|
|
155
|
+
- lib/garden_messenger/cli.rb
|
|
151
156
|
- lib/garden_messenger/reporter.rb
|
|
152
157
|
- lib/garden_messenger/version.rb
|
|
153
158
|
- lib/garden_messenger/wattage.rb
|