<commit_before>require 'pathname'
require 'mysql2'
require 'dotenv'
require 'json'

$LOAD_PATH << File.expand_path("../lib", __FILE__)

require "p1_meter_reader"
require "database_connection_factory"
require "database_reader"
require "output/database_writer"
require "database_config"

require "current_water_usage_store"
require "recent_measurement_store"

ROOT_PATH = Pathname.new File.dirname(__FILE__)

Dotenv.load

def get_last_water_measurement(environment)
  database_reader = DatabaseReader.new(DatabaseConnectionFactory.new(environment))

  database_reader.last_measurement.water
end

def main
  environment = ENV.fetch('ENVIRONMENT')

  measurement_counter = 0

  database_writer = DatabaseWriter.new(DatabaseConnectionFactory.new(environment))
  database_writer.save_interval = 15

  recent_measurement_store = RecentMeasurementStore.new(
    number_of_entries: 8 * 60, # 8 hours at 1 measurement per minute
    redis_list_name: ENV.fetch("REDIS_LIST_NAME")
  )

  current_water_usage_store = CurrentWaterUsageStore.new

  last_water_measurement = 0

  if environment == "production"
    last_water_measurement = get_last_water_measurement(environment)

    stream_splitter = P1MeterReader::DataParsing::StreamSplitter.new("/XMX5XMXABCE100129872")
    water_data_source = P1MeterReader::DataParsing::WaterMeasurementListener.new
  else
    puts "Fake stream splitter"
    stream_splitter = P1MeterReader::DataParsing::FakeStreamSplitter.new
    water_data_source = P1MeterReader::DataParsing::FakeWaterMeasurementListener.new
  end

  water_measurement_parser = P1MeterReader::Models::WaterMeasurementParser.new(last_water_measurement)

  recorder = P1MeterReader::Recorder.new(
    p1_data_source: stream_splitter,
    water_data_source: water_data_source,
    water_measurement_parser: water_measurement_parser
  )

  recorder.collect_data do |measurement|
    json = measurement_to_json(measurement, measurement_counter)

    database_writer.save_unless_exists(measurement)
    recent_measurement_store.add(json)
    current_water_usage_store.add(measurement)

    measurement_counter += 1
  end
end

def measurement_to_json(measurement, measurement_counter)
  {
    id:               measurement_counter,
    time_stamp:       measurement.time_stamp.to_s,
    time_stamp_utc:   measurement.time_stamp_utc.to_s,
    stroom_dal:       measurement.stroom_dal.to_f,
    stroom_piek:      measurement.stroom_piek.to_f,
    stroom_current:   measurement.stroom_current.to_f,
    gas:              measurement.gas.to_f,
    water:            measurement.water.to_f
  }.to_json
end

puts "Starting..."
main<commit_msg>Initialize P1 device through dotenv.<commit_after>require 'pathname'
require 'mysql2'
require 'dotenv'
require 'json'
require 'serialport'

$LOAD_PATH << File.expand_path("../lib", __FILE__)

require "p1_meter_reader"
require "database_connection_factory"
require "database_reader"
require "output/database_writer"
require "database_config"

require "current_water_usage_store"
require "recent_measurement_store"

ROOT_PATH = Pathname.new File.dirname(__FILE__)

Dotenv.load

def get_last_water_measurement(environment)
  database_reader = DatabaseReader.new(DatabaseConnectionFactory.new(environment))

  database_reader.last_measurement.water
end

def main
  environment = ENV.fetch('ENVIRONMENT')

  measurement_counter = 0

  database_writer = DatabaseWriter.new(DatabaseConnectionFactory.new(environment))
  database_writer.save_interval = 15

  recent_measurement_store = RecentMeasurementStore.new(
    number_of_entries: 8 * 60, # 8 hours at 1 measurement per minute
    redis_list_name: ENV.fetch("REDIS_LIST_NAME")
  )

  current_water_usage_store = CurrentWaterUsageStore.new

  last_water_measurement = 0

  if environment == "production"
    last_water_measurement = get_last_water_measurement(environment)

    stream_splitter = P1MeterReader::DataParsing::StreamSplitter.new(ENV.fetch("P1_CONVERTER_MESSAGE_START"), input: serial_port)
    water_data_source = P1MeterReader::DataParsing::WaterMeasurementListener.new
  else
    puts "Fake stream splitter"
    stream_splitter = P1MeterReader::DataParsing::FakeStreamSplitter.new
    water_data_source = P1MeterReader::DataParsing::FakeWaterMeasurementListener.new
  end

  water_measurement_parser = P1MeterReader::Models::WaterMeasurementParser.new(last_water_measurement)

  recorder = P1MeterReader::Recorder.new(
    p1_data_source: stream_splitter,
    water_data_source: water_data_source,
    water_measurement_parser: water_measurement_parser
  )

  recorder.collect_data do |measurement|
    json = measurement_to_json(measurement, measurement_counter)

    database_writer.save_unless_exists(measurement)
    recent_measurement_store.add(json)
    current_water_usage_store.add(measurement)

    measurement_counter += 1
  end
end

def measurement_to_json(measurement, measurement_counter)
  {
    id:               measurement_counter,
    time_stamp:       measurement.time_stamp.to_s,
    time_stamp_utc:   measurement.time_stamp_utc.to_s,
    stroom_dal:       measurement.stroom_dal.to_f,
    stroom_piek:      measurement.stroom_piek.to_f,
    stroom_current:   measurement.stroom_current.to_f,
    gas:              measurement.gas.to_f,
    water:            measurement.water.to_f
  }.to_json
end


def serial_port
  device = ENV.fetch("P1_CONVERTER_DEVICE")
  baud_rate = Integer(ENV.fetch("P1_CONVERTER_BAUD_RATE"))

  serial_port = SerialPort.new(device, baud_rate)
  serial_port.data_bits = 7
  serial_port.stop_bits = 1
  serial_port.parity = SerialPort::EVEN

  serial_port
end

puts "Starting..."
main
{'fraction_non_alphanumeric': 0.07833363005162898, 'fraction_numerical': 0.009613672779063557, 'mean_word_length': 5.291153415453527, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2292925', 'n_tokens_mistral': 1848, 'n_tokens_neox': 1803, 'n_words': 282}