Files
smartmeter/app/helpers/InSyncState.rb
= a5aa6de67b Post to MQTT
Co-authored-by: Copilot <copilot@github.com>
2026-04-26 13:04:29 +02:00

106 lines
4.0 KiB
Ruby

require "socket"
class InSyncState < StatePattern::State
END_OF_FRAME = "!****\n"
# def initialize(stateful, previous_state)
# # open socket to EmonHub
# @hub = TCPSocket.new 'raspberrypi.lan', 5050
# @hub.setsockopt(Socket::SOL_SOCKET, Socket::SO_KEEPALIVE, true)
# super(stateful, previous_state)
# end
def handle_byte_stream(bytes)
idx = 0
#sync_pattern_length = Synchronizer::SYNC_PATTERN.length
sync_pattern_length = END_OF_FRAME.length
#p "Sync length: #{sync_length}"
frame = ""
while (idx+sync_pattern_length < bytes.length && !new_frame_starts(bytes,idx,sync_pattern_length)) do
frame = frame + bytes[idx]
idx = idx +1
end
# did we reach the end of the frame?
if new_frame_starts(bytes,idx,sync_pattern_length)
frame_lines = frame.split("\n")
puts "--- FRAME ---"
# p frame_lines
# p "##################"
reading = handle_frame(frame_lines)
p reading
return bytes[idx+sync_pattern_length..-1] || ""
else
return bytes
end
end
private
def new_frame_starts(bytes,idx,sync_pattern_length)
#return bytes[idx..idx+sync_pattern_length-1].eql?(Synchronizer::SYNC_PATTERN)
#return bytes[idx..idx+sync_pattern_length-1].eql?(END_OF_FRAME)
return bytes[idx].eql?(END_OF_FRAME[0])
end
def handle_frame(frame_lines)
# prepare DB record
last_reading = Reading.last
reading = Reading.new
frame_lines.each {| line|
if line.match(/1-0:1.8.1/) # Verbruik hoog tarief
reading.total_kwh_consumed_high = line.split(/1-0:1.8.1\(|\*kWh\)/).join.to_f
# p "Total kwh consumed (high): #{total_kwh_consumed_high}."
end
if line.match(/1-0:1.8.2/) # Verbruik laag tarief
reading.total_kwh_consumed_low = line.split(/1-0:1.8.2\(|\*kWh\)/).join.to_f
# p "Total kwh consumed (low): #{total_kwh_consumed_low}."
end
if line.match(/1-0:2.8.1/) # Teruglevering hoog tarief
reading.total_kwh_produced_high = line.split(/1-0:2.8.1\(|\*kWh\)/).join.to_f
# p "Total kwh produced (high): #{total_kwh_produced_high}."
end
if line.match(/1-0:2.8.2/) # Teruglevering laag tarief
reading.total_kwh_produced_low = line.split(/1-0:2.8.2\(|\*kWh\)/).join.to_f
# p "Total kwh produced (low): #{total_kwh_produced_low}."
end
if line.match(/1-0:1.7.0/) # Actueel verbruik
reading.current_kw_consumed = line.split(/1-0:1.7.0\(|\*kW\)/).join.to_f
#p "Current kW consumed: #{current_kw_consumed}."
end
if line.match(/1-0:2.7.0/) # Actueel terug
reading.current_kw_produced = line.split(/1-0:2.7.0\(|\*kW\)/).join.to_f
end
if line.match(/0-0:96.14.0/) # Hoog/laag tarief
reading.high_tarif = line.split(/0-0:96.14.0\(|\)/).join.eql?("0002")
end
# example line: "0-1:24.2.1(250717121000S)(00000.474*m3)"
if match = line.match(/^(0-1:24.2.1)\(([^)]+)\)\(([\d.]+)\*m3\)$/) # Gas verbruik (1x per uur een nieuwe stand)
#p "Gas reading: #{match[1]} (#{match[2]})"
#datetime = DateTime.strptime(match[2][0..11], "%y%m%d%H%M%S")
#p "Gas reading at #{datetime}."
reading.total_m3_gas_consumed = match[3].to_f
end
}
if last_reading && last_reading.eql_reading?(reading)
p "Nothing changed. Do not add to the database"
else
reading.save
end
# Post current_kw_consumed and current_kw_produced to MQTT
MqttClient.publish("home/energy/current_kw_consumed", reading.current_kw_consumed.to_s)
MqttClient.publish("home/energy/current_kw_produced", reading.current_kw_produced.to_s)
# Result
return reading
end
end