// // Created by rhetenor on 04.10.18. // #include #include "OutputDriverFactory.h" #include "utility/LoggerFactory.h" #include "output/detail/DisplayController.h" #include "output/detail/SoundBoardPinController.h" #include "output/detail/DisplayBoardPinController.h" #include "output/detail/DriverBoardPinController.h" #include "output/items/detail/EightDigitDisplay.h" #include "output/items/detail/SevenDigitDisplay.h" #include "output/items/Flipper.h" namespace flippR_driver { namespace output { namespace OutputDriverFactory { using namespace nlohmann; namespace config { namespace { json solenoids; json lamps; json sounds; json displays; } } std::shared_ptr get_OutputDriver(std::istream& solenoid_config, std::istream& lamp_config, std::istream& sound_config, std::istream& display_config) { utility::LoggerFactory::CreateOutputLogger(); solenoid_config >> config::solenoids; lamp_config >> config::lamps; sound_config >> config::sounds; display_config >> config::displays; auto output_pin_mutex = std::make_shared(); std::shared_ptr driver_board_pin_controller(new detail::DriverBoardPinController(output_pin_mutex)); /* auto solenoids = create_solenoids(driver_board_pin_controller); auto flippers = create_flippers(driver_board_pin_controller);*/ LampFactory lamp_factory(config::lamps, driver_board_pin_controller); try { auto lamps = lamp_factory.getItemMap(); } catch(json::exception &e) { CLOG(INFO, OUTPUT_LOGGER) << "File " << "sound_config.json" << " seems to be corrupted: " << ": " << e.what(); exit(EXIT_FAILURE); } /*auto sound_board_pin_controller = create_SoundBoardPinController(); auto sounds = create_sounds(sound_board_pin_controller); std::unique_ptr display_board_pin_controller(new detail::DisplayBoardPinController(parse_pins_display_board(display_config))); auto displays = create_displays(); std::unique_ptr display_controller(new detail::DisplayController(displays, std::move(display_board_pin_controller))); auto display_map = map_displays(displays); return std::make_shared(std::move(display_controller), solenoids, lamps, sounds, flippers, display_map);*/ } std::map> create_solenoids(std::shared_ptr &pin_controller) { json port_extenders = get_element("port_extenders", config::solenoids, ""); initialize_port_extenders(port_extenders, pin_controller.get(), "solenoid_config.json"); json solenoids_json = get_element("solenoids", config::solenoids, "solenoid_config.json"); std::chrono::milliseconds deactivation_time{ get_value("deactivation_time_milliseconds", config::solenoids, "solenoid_config.json") }; std::map> solenoids; for(auto &solenoid_json : solenoids_json) { auto solenoid = create_solenoid(solenoid_json, port_extenders, pin_controller, deactivation_time); solenoids.emplace(solenoid->get_name(), solenoid); } return solenoids; } std::shared_ptr create_solenoid(nlohmann::json &solenoid_json, nlohmann::json &port_extenders, std::shared_ptr &pin_controller, std::chrono::milliseconds deactivation_time) { std::string config_file_name = "config::solenoid.json"; uint8_t pin_base = get_pin_base(solenoid_json, port_extenders, config_file_name); auto name = get_value("name", solenoid_json, config_file_name); auto address = get_value("address", solenoid_json, config_file_name); if(solenoid_json.find("deactivation_time_milliseconds") != solenoid_json.end()) { deactivation_time = std::chrono::milliseconds(get_value("deactivation_time_milliseconds", solenoid_json, config_file_name)); } return std::make_shared(pin_controller, address, pin_base, name, deactivation_time); } std::map> create_flippers(std::shared_ptr &pin_controller) { json port_extenders = get_element("port_extenders", config::solenoids, "solenoid_config.json"); json flippers_json = get_element("flippers", config::solenoids, "solenoid_config.json"); std::chrono::milliseconds deactivation_time{ get_value("deactivation_time_milliseconds", config::solenoids, "solenoid_config.json") }; std::map> flippers; for(auto &flipper_json : flippers_json) { auto flipper = create_flipper(flipper_json, port_extenders, pin_controller); flippers.emplace(flipper->get_name(), flipper); } return flippers; } std::shared_ptr create_flipper(nlohmann::json &flipper_json, json &port_extenders, std::shared_ptr &pin_controller) { std::string config_file_name = "solenoid_config.json"; uint8_t pin_base = get_pin_base(flipper_json, port_extenders, config_file_name); auto address = get_value("address", flipper_json, config_file_name); auto name = get_value("name", flipper_json, config_file_name); return std::make_shared(pin_controller, address, pin_base, name); } std::map> create_sounds(std::istream &sound_config, std::shared_ptr &pin_controller) { json port_extenders = get_element("port_extenders", config::sounds, "sound_config.json"); initialize_port_extenders(port_extenders, pin_controller.get(), "sound_config.json"); std::chrono::milliseconds deactivation_time{ get_value("deactivation_time_milliseconds", config::sounds, "solenoid_config.json") }; json sounds_json = get_element("sounds", config::sounds, "sound_config.json"); std::map> sounds; for(auto &sound_json : sounds_json) { auto sound = create_sound(sound_json, port_extenders, pin_controller, deactivation_time); sounds.emplace(sound->get_name(), sound); } return sounds; } std::shared_ptr create_sound(json &sound_json, json &port_extenders, std::shared_ptr &pin_controller, std::chrono::milliseconds &deactivation_time) { std::string config_file_name = "sound_config.json"; uint8_t pin_base = get_pin_base(sound_json, port_extenders, config_file_name); auto address = get_value("address", sound_json, config_file_name); auto name = get_value("name", sound_json, config_file_name); auto id = get_value("id", sound_json, config_file_name); return std::make_shared(pin_controller, address, pin_base, name, deactivation_time, id); } uint8_t get_sound_fire_address() { json port_extenders = get_element("port_extenders", config::sounds, "sound_config.json"); json fire_pin = get_element("fire_pin", config::sounds, "sound_config.json"); auto pin_base = get_pin_base(fire_pin, port_extenders, "sound_config.json"); auto address = get_value("address", fire_pin, "sound_config.json"); return address; } std::map parse_pins_display_board(std::istream &display_config) { std::string config_file = "display_config.json"; json display_board_config = get_element("display_board", config::displays, config_file); std::map pins_display; pins_display["run"] = get_value("run", display_board_config, config_file); json display_select = display_board_config.at("display_select"); for(int i = 1; i < 6; i++) { pins_display["display_select" + std::to_string(i)] = get_value(std::to_string(i), display_select, config_file); } json segment_select = display_board_config.at("segment_select"); pins_display["segment_select_A"] = get_value("A", segment_select, config_file); pins_display["segment_select_B"] = get_value("B", segment_select, config_file); pins_display["segment_select_C"] = get_value("C", segment_select, config_file); json digit_select = display_board_config.at("digit_select"); pins_display["digit_select_A"] = get_value("A", digit_select, config_file); pins_display["digit_select_B"] = get_value("B", digit_select, config_file); pins_display["digit_select_C"] = get_value("C", digit_select, config_file); pins_display["digit_select_D"] = get_value("D", digit_select, config_file);; return pins_display; } std::vector> create_displays(std::istream &display_config) { json displays_json = get_element("displays", config::displays, "display_config.json"); std::vector> displays; for(json &display_json : displays_json) { auto display = create_display(display_json); displays.push_back(display); } return displays; } std::shared_ptr create_display(json & display_json) { /* std::string config_file = "display_config.json"; auto id = get_value("id", display_json, config_file); auto address = get_value("address", display_json, config_file); auto digits = get_value("digits", display_json, config_file); if(digits == 8) return std::make_shared(address, id); else if(digits == 7) return std::make_shared(address, id); else throw new std::logic_error("Display digits can either be 7 or 8");*/ } std::map> map_displays(const std::vector> &displays) { std::map> display_map; for(auto &display : displays) { display_map.emplace(display->get_address(), display); } return display_map; } void initialize_port_extenders(json &port_extenders, PinController * pin_controller, const std::string & file_name) { for (auto & extender_json : port_extenders) { auto i2c_address = get_value("i2c_address", extender_json, file_name); auto pin_base = get_value("pin_base", extender_json, file_name); pin_controller->initialize_port_expander(i2c_address, pin_base); } } uint8_t get_pin_base(json & object, json & port_extenders, const std::string & config_file_name) { if(object.find("extender") != object.end()) { auto extender_name = get_value("extender", object, config_file_name); for (auto & extender : port_extenders) { auto actual_extender = get_value("name", extender, config_file_name); if (actual_extender == extender_name) { try { return extender.at("pin_base").get(); } catch(json::exception &e) { CLOG(INFO, OUTPUT_LOGGER) << "pin_base not set for " << extender_name << " in " << config_file_name; return 0; } } } } CLOG(INFO, OUTPUT_LOGGER) << "Extender not set for " << object << " in " << config_file_name; return 0; } json get_element(const std::string & name, json & object, const std::string & file_name) { json sub_object; try { sub_object = object.at(name); } catch(json::exception &e) { CLOG(ERROR, OUTPUT_LOGGER) << "File " << file_name << " seems to be corrupted at " << name << ": " << e.what(); exit(EXIT_FAILURE); } return sub_object; } template type get_value(const std::string & name, json & object, const std::string & file_name) { type element; try { element = object.at(name).get(); } catch(json::exception &e) { /*CLOG(ERROR, OUTPUT_LOGGER)*/ std::cerr << "File " << file_name << " seems to be corrupted at " << name << ": " << e.what(); exit(EXIT_FAILURE); } return element; } std::shared_ptr create_SoundBoardPinController() { return std::shared_ptr(); } } } }