@@ -16,6 +16,5 @@ RUN \
|
|||||||
apt-get install -y $BUILD_PACKAGES && \
|
apt-get install -y $BUILD_PACKAGES && \
|
||||||
bundle install
|
bundle install
|
||||||
|
|
||||||
COPY . .
|
|
||||||
|
|
||||||
CMD ["/bin/bash -c ruby ./smartmeter.rb"]
|
CMD ["/bin/bash -c ruby ./smartmeter.rb"]
|
||||||
|
|||||||
1
Gemfile
1
Gemfile
@@ -12,3 +12,4 @@ gem 'numo-narray'
|
|||||||
gem 'i18n'
|
gem 'i18n'
|
||||||
gem 'gruff'
|
gem 'gruff'
|
||||||
gem 'net-http' # to avoid error: uninitialized constant ...
|
gem 'net-http' # to avoid error: uninitialized constant ...
|
||||||
|
gem 'mqtt'
|
||||||
|
|||||||
67
Gemfile.lock
67
Gemfile.lock
@@ -1,13 +1,13 @@
|
|||||||
GEM
|
GEM
|
||||||
remote: https://rubygems.org/
|
remote: https://rubygems.org/
|
||||||
specs:
|
specs:
|
||||||
activemodel (7.1.5.1)
|
activemodel (7.1.6)
|
||||||
activesupport (= 7.1.5.1)
|
activesupport (= 7.1.6)
|
||||||
activerecord (7.1.5.1)
|
activerecord (7.1.6)
|
||||||
activemodel (= 7.1.5.1)
|
activemodel (= 7.1.6)
|
||||||
activesupport (= 7.1.5.1)
|
activesupport (= 7.1.6)
|
||||||
timeout (>= 0.4.0)
|
timeout (>= 0.4.0)
|
||||||
activesupport (7.1.5.1)
|
activesupport (7.1.6)
|
||||||
base64
|
base64
|
||||||
benchmark (>= 0.3)
|
benchmark (>= 0.3)
|
||||||
bigdecimal
|
bigdecimal
|
||||||
@@ -20,53 +20,55 @@ GEM
|
|||||||
mutex_m
|
mutex_m
|
||||||
securerandom (>= 0.3)
|
securerandom (>= 0.3)
|
||||||
tzinfo (~> 2.0)
|
tzinfo (~> 2.0)
|
||||||
base64 (0.2.0)
|
base64 (0.3.0)
|
||||||
benchmark (0.4.0)
|
benchmark (0.5.0)
|
||||||
bigdecimal (3.1.9)
|
bigdecimal (4.1.2)
|
||||||
concurrent-ruby (1.3.4)
|
concurrent-ruby (1.3.6)
|
||||||
connection_pool (2.4.1)
|
connection_pool (2.5.5)
|
||||||
daemons (1.4.1)
|
daemons (1.4.1)
|
||||||
date (3.4.1)
|
date (3.5.1)
|
||||||
drb (2.2.1)
|
drb (2.2.3)
|
||||||
et-orbi (1.2.11)
|
et-orbi (1.4.0)
|
||||||
tzinfo
|
tzinfo
|
||||||
fugit (1.11.1)
|
fugit (1.12.1)
|
||||||
et-orbi (~> 1, >= 1.2.11)
|
et-orbi (~> 1.4)
|
||||||
raabro (~> 1.4)
|
raabro (~> 1.4)
|
||||||
gruff (0.24.0)
|
gruff (0.24.0)
|
||||||
histogram
|
histogram
|
||||||
rmagick (>= 5.3)
|
rmagick (>= 5.3)
|
||||||
histogram (0.2.4.1)
|
histogram (0.2.4.1)
|
||||||
i18n (1.14.6)
|
i18n (1.14.8)
|
||||||
concurrent-ruby (~> 1.0)
|
concurrent-ruby (~> 1.0)
|
||||||
logger (1.6.4)
|
logger (1.7.0)
|
||||||
mail (2.8.1)
|
mail (2.9.0)
|
||||||
|
logger
|
||||||
mini_mime (>= 0.1.1)
|
mini_mime (>= 0.1.1)
|
||||||
net-imap
|
net-imap
|
||||||
net-pop
|
net-pop
|
||||||
net-smtp
|
net-smtp
|
||||||
mini_mime (1.1.5)
|
mini_mime (1.1.5)
|
||||||
mini_portile2 (2.8.8)
|
minitest (5.26.1)
|
||||||
minitest (5.25.4)
|
mqtt (0.7.0)
|
||||||
|
logger
|
||||||
mutex_m (0.3.0)
|
mutex_m (0.3.0)
|
||||||
mysql2 (0.5.6)
|
mysql2 (0.5.7)
|
||||||
net-http (0.6.0)
|
bigdecimal
|
||||||
uri
|
net-http (0.9.1)
|
||||||
net-imap (0.4.18)
|
uri (>= 0.11.1)
|
||||||
|
net-imap (0.4.24)
|
||||||
date
|
date
|
||||||
net-protocol
|
net-protocol
|
||||||
net-pop (0.1.2)
|
net-pop (0.1.2)
|
||||||
net-protocol
|
net-protocol
|
||||||
net-protocol (0.2.2)
|
net-protocol (0.2.2)
|
||||||
timeout
|
timeout
|
||||||
net-smtp (0.5.0)
|
net-smtp (0.5.1)
|
||||||
net-protocol
|
net-protocol
|
||||||
nokogiri (1.15.7)
|
nokogiri (1.15.7-aarch64-linux)
|
||||||
mini_portile2 (~> 2.8.2)
|
|
||||||
racc (~> 1.4)
|
racc (~> 1.4)
|
||||||
numo-narray (0.9.2.1)
|
numo-narray (0.9.2.1)
|
||||||
observer (0.1.2)
|
observer (0.1.2)
|
||||||
pkg-config (1.5.8)
|
pkg-config (1.6.5)
|
||||||
raabro (1.4.0)
|
raabro (1.4.0)
|
||||||
racc (1.8.1)
|
racc (1.8.1)
|
||||||
rmagick (5.5.0)
|
rmagick (5.5.0)
|
||||||
@@ -75,12 +77,12 @@ GEM
|
|||||||
rufus-scheduler (3.9.2)
|
rufus-scheduler (3.9.2)
|
||||||
fugit (~> 1.1, >= 1.11.1)
|
fugit (~> 1.1, >= 1.11.1)
|
||||||
securerandom (0.3.2)
|
securerandom (0.3.2)
|
||||||
serialport (1.3.2)
|
serialport (1.4.0)
|
||||||
state_pattern (2.0.2)
|
state_pattern (2.0.2)
|
||||||
timeout (0.4.3)
|
timeout (0.6.1)
|
||||||
tzinfo (2.0.6)
|
tzinfo (2.0.6)
|
||||||
concurrent-ruby (~> 1.0)
|
concurrent-ruby (~> 1.0)
|
||||||
uri (1.0.2)
|
uri (1.1.1)
|
||||||
|
|
||||||
PLATFORMS
|
PLATFORMS
|
||||||
ruby
|
ruby
|
||||||
@@ -91,6 +93,7 @@ DEPENDENCIES
|
|||||||
gruff
|
gruff
|
||||||
i18n
|
i18n
|
||||||
mail
|
mail
|
||||||
|
mqtt
|
||||||
mysql2
|
mysql2
|
||||||
net-http
|
net-http
|
||||||
nokogiri
|
nokogiri
|
||||||
|
|||||||
@@ -94,14 +94,10 @@ class InSyncState < StatePattern::State
|
|||||||
reading.save
|
reading.save
|
||||||
end
|
end
|
||||||
|
|
||||||
# Write to EmonHub
|
# Post current_kw_consumed and current_kw_produced to MQTT
|
||||||
begin
|
MqttClient.publish("home/energy/current_kw_consumed", reading.current_kw_consumed.to_s)
|
||||||
TCPSocket.open("printserver",5050){|s|
|
MqttClient.publish("home/energy/current_kw_produced", reading.current_kw_produced.to_s)
|
||||||
s.write(sprintf("8 %d %d\r\n", reading.current_kw_consumed*1000, reading.current_kw_produced*1000))
|
|
||||||
}
|
|
||||||
rescue
|
|
||||||
p "Socket problem."
|
|
||||||
end
|
|
||||||
# Result
|
# Result
|
||||||
return reading
|
return reading
|
||||||
|
|
||||||
|
|||||||
77
app/helpers/MqttClient.rb
Normal file
77
app/helpers/MqttClient.rb
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
begin
|
||||||
|
require "mqtt"
|
||||||
|
rescue LoadError
|
||||||
|
# Fallback to mosquitto_pub when the mqtt gem is not available.
|
||||||
|
end
|
||||||
|
|
||||||
|
module MqttClient
|
||||||
|
class << self
|
||||||
|
def publish(topic, payload, retain: false, qos: 0)
|
||||||
|
return false if topic.nil? || topic.empty?
|
||||||
|
|
||||||
|
if defined?(MQTT)
|
||||||
|
publish_with_ruby_mqtt(topic, payload, retain, qos)
|
||||||
|
else
|
||||||
|
publish_with_mosquitto_pub(topic, payload, retain, qos)
|
||||||
|
end
|
||||||
|
rescue StandardError => e
|
||||||
|
warn("[MqttClient] publish failed: #{e.class}: #{e.message}")
|
||||||
|
false
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def publish_with_ruby_mqtt(topic, payload, retain, qos)
|
||||||
|
options = {
|
||||||
|
host: mqtt_host,
|
||||||
|
port: mqtt_port,
|
||||||
|
keep_alive: 30
|
||||||
|
}
|
||||||
|
|
||||||
|
options[:username] = mqtt_username if mqtt_username
|
||||||
|
options[:password] = mqtt_password if mqtt_password
|
||||||
|
|
||||||
|
MQTT::Client.connect(options) do |client|
|
||||||
|
client.publish(topic, payload.to_s, retain, qos)
|
||||||
|
end
|
||||||
|
|
||||||
|
true
|
||||||
|
end
|
||||||
|
|
||||||
|
def publish_with_mosquitto_pub(topic, payload, retain, qos)
|
||||||
|
command = [
|
||||||
|
"mosquitto_pub",
|
||||||
|
"-h", mqtt_host,
|
||||||
|
"-p", mqtt_port.to_s,
|
||||||
|
"-q", qos.to_s,
|
||||||
|
"-t", topic,
|
||||||
|
"-m", payload.to_s
|
||||||
|
]
|
||||||
|
|
||||||
|
command << "-r" if retain
|
||||||
|
|
||||||
|
ok = system(*command)
|
||||||
|
warn("[MqttClient] mosquitto_pub failed") unless ok
|
||||||
|
ok
|
||||||
|
end
|
||||||
|
|
||||||
|
def mqtt_host
|
||||||
|
ENV.fetch("MQTT_HOST", "localhost")
|
||||||
|
end
|
||||||
|
|
||||||
|
def mqtt_port
|
||||||
|
Integer(ENV.fetch("MQTT_PORT", "1883"))
|
||||||
|
rescue ArgumentError
|
||||||
|
1883
|
||||||
|
end
|
||||||
|
|
||||||
|
def mqtt_username
|
||||||
|
v = ENV["MQTT_USERNAME"]
|
||||||
|
v.nil? || v.strip.empty? ? nil : v
|
||||||
|
end
|
||||||
|
|
||||||
|
def mqtt_password
|
||||||
|
ENV["MQTT_PASSWORD"]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -21,15 +21,6 @@ services:
|
|||||||
- .:/usr/src/app
|
- .:/usr/src/app
|
||||||
depends_on:
|
depends_on:
|
||||||
- db
|
- db
|
||||||
rstudio:
|
|
||||||
container_name: rstudio
|
|
||||||
restart: unless-stopped
|
|
||||||
build: ./rstudio
|
|
||||||
environment:
|
|
||||||
PASSWORD: secret
|
|
||||||
volumes:
|
|
||||||
- ./rstudio:/home/rstudio/smartmeter
|
|
||||||
ports:
|
|
||||||
- 8787:8787
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user