Post to MQTT

Co-authored-by: Copilot <copilot@github.com>
This commit is contained in:
=
2026-04-26 13:04:29 +02:00
parent d5a4a8c791
commit a5aa6de67b
6 changed files with 119 additions and 52 deletions

View File

@@ -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"]

View File

@@ -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'

View File

@@ -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

View File

@@ -94,15 +94,11 @@ 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))
} # Result
rescue
p "Socket problem."
end
# Result
return reading return reading
end end

77
app/helpers/MqttClient.rb Normal file
View 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

View File

@@ -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