Пример #1
0
    def test_switch_heating_and_cooling_without_threshold(
            self, pid_mock_class, control, h_current, h_switch, c_current,
            c_switch):
        pid_mock = pid_mock_class.return_value

        self.heater.get.return_value = h_current
        self.cooler.get.return_value = c_current

        pid_mock.return_value = control

        tunings_mock = PropertyMock()
        type(pid_mock).tunings = tunings_mock
        tunings_mock.return_value = (1, 2, 3)

        components_mock = PropertyMock()
        type(pid_mock).components = components_mock
        components_mock.return_value = (4, 3, 2)

        controller = Controller(self.config, 5, 0, self.heater, self.cooler,
                                self.limiter, self.current_temp,
                                self.fridge_temp, [])

        controller.control()

        if h_switch is None:
            self.heater.set.assert_not_called()
        else:
            self.heater.set.assert_called_with(h_switch)

        if c_switch is None:
            self.cooler.set.assert_not_called()
        else:
            self.cooler.set.assert_called_with(c_switch)
Пример #2
0
    def test_updates_pid_values_on_control(self, pid_mock_class):
        pid_mock = pid_mock_class.return_value

        tunings_mock = PropertyMock()
        type(pid_mock).tunings = tunings_mock
        tunings_mock.return_value = (1, 2, 3)

        components_mock = PropertyMock()
        type(pid_mock).components = components_mock
        components_mock.return_value = (4, 3, 2)

        controller = Controller(self.config, 5, 0.5, self.heater, self.cooler,
                                self.limiter, self.current_temp,
                                self.fridge_temp, [])

        self.config.get.side_effect = lambda key: {
            "p": 4,
            "i": 5,
            "d": 6,
            "target": 23,
            "heating_limit": 40,
            "limit_window": 5
        }.get(key)

        pid_mock.return_value = 5

        controller.control()

        tunings_mock.assert_called_with((4, 5, 6))
Пример #3
0
    def test_initiates_with_pid_values_and_target_from_config(
            self, pid_mock_class):
        Controller(self.config, 5, 0.5, self.heater, self.cooler, self.limiter,
                   self.current_temp, self.fridge_temp, [])

        pid_mock_class.assert_called_with(Kp=1,
                                          Ki=2,
                                          Kd=3,
                                          setpoint=23,
                                          sample_time=5)
def main():
    config = Config("./config.json")
    secrets = Config("./secret.json")

    display = Display(["environment", "vessel", "fridge", "target"], ["heater", "cooler", "limiter"])
    display.handle_temperature("target", config.get("target"), config.get("target"))

    data_collector = DataCollector(["environment", "vessel", "fridge", "target"],
                                   ["heater", "cooler", "limiter"])
    csv_writer = CsvWriter(data_collector)
    influxdb_writer = InfluxDBWriter(secrets, data_collector)

    data_collector.handle_temperature("target", config.get("target"), config.get("target"))

    env_sensor = Sensor("environment", "28-0301a2798a9f", "/sys/bus/w1/devices", config.get("average_window"),
                        [display, data_collector])
    vessel_sensor = Sensor("vessel", "28-0301a2799ddf", "/sys/bus/w1/devices", config.get("average_window"),
                           [display, data_collector])
    fridge_sensor = Sensor("fridge", "28-0301a27988e2", "/sys/bus/w1/devices", config.get("average_window"),
                           [display, data_collector])

    heater_ssr = Ssr("heater", 16, [display, data_collector])
    cooler_ssr = Ssr("cooler", 20, [display, data_collector])

    limiter = Limiter("limiter", heater_ssr, [display, data_collector])

    controller = Controller(config, config.get("control_interval"), config.get("control_deadband"),
                            heater_ssr, cooler_ssr, limiter,
                            vessel_sensor, fridge_sensor, [data_collector])

    runnables = [(env_sensor, config.get("sensor_interval"), 0),
                 (vessel_sensor, config.get("sensor_interval"), 0),
                 (fridge_sensor, config.get("sensor_interval"), 0),
                 (controller, config.get("control_interval"), 2),
                 (config, config.get("config_interval"), 0),
                 (csv_writer, config.get("csv_interval"), 0),
                 (influxdb_writer, config.get("influxdb_interval"), 0)]

    threads = []
    for runnable, interval, init_delay in runnables:
        t = Thread(target=runnable.start, args=(interval, init_delay))
        threads.append(t)
        t.start()

    shutdown.wait()

    logger.info("Received interrupt, shutting down")

    for index, (runnable, interval, init_delay) in enumerate(runnables):
        runnable.stop()
        threads[index].join()

    display.shutdown()
    heater_ssr.shutdown()
Пример #5
0
    def test_only_updates_pid_values_if_changed(self, pid_mock_class):
        pid_mock = pid_mock_class.return_value

        tunings_mock = PropertyMock()
        type(pid_mock).tunings = tunings_mock
        tunings_mock.return_value = (1, 2, 3)

        components_mock = PropertyMock()
        type(pid_mock).components = components_mock
        components_mock.return_value = (4, 3, 2)

        controller = Controller(self.config, 5, 0.5, self.heater, self.cooler,
                                self.limiter, self.current_temp,
                                self.fridge_temp, [])

        pid_mock.return_value = 5

        controller.control()

        tunings_mock.assert_called_once_with()  # the getter, not the setter
Пример #6
0
    def test_publishes_to_listeners(self, pid_mock_class):
        pid_mock = pid_mock_class.return_value

        tunings_mock = PropertyMock()
        type(pid_mock).tunings = tunings_mock
        tunings_mock.return_value = (1, 2, 3)

        components_mock = PropertyMock()
        type(pid_mock).components = components_mock
        components_mock.return_value = (4, 3, 2)

        controller = Controller(self.config, 5, 0.5, self.heater, self.cooler,
                                self.limiter, self.current_temp,
                                self.fridge_temp, [self.listener])

        pid_mock.return_value = .4

        controller.control()

        self.listener.handle_controller.assert_called_with(4, 3, 2, .4)
Пример #7
0
    def test_dont_switch_heating_on_if_under_heating_threshold(
            self, pid_mock_class):
        pid_mock = pid_mock_class.return_value

        self.heater.get.return_value = False

        pid_mock.return_value = 0.4

        tunings_mock = PropertyMock()
        type(pid_mock).tunings = tunings_mock
        tunings_mock.return_value = (1, 2, 3)

        components_mock = PropertyMock()
        type(pid_mock).components = components_mock
        components_mock.return_value = (4, 3, 2)

        controller = Controller(self.config, 5, 0.5, self.heater, self.cooler,
                                self.limiter, self.current_temp,
                                self.fridge_temp, [])

        controller.control()

        self.heater.set.assert_not_called()
Пример #8
0
    def test_feeds_current_temperature_to_pid(self, pid_mock_class):
        pid_mock = pid_mock_class.return_value

        current_temp = Mock()
        self.current_temp.get_average.return_value = current_temp

        tunings_mock = PropertyMock()
        type(pid_mock).tunings = tunings_mock
        tunings_mock.return_value = (1, 2, 3)

        components_mock = PropertyMock()
        type(pid_mock).components = components_mock
        components_mock.return_value = (4, 3, 2)

        controller = Controller(self.config, 5, 0.5, self.heater, self.cooler,
                                self.limiter, self.current_temp,
                                self.fridge_temp, [])

        pid_mock.return_value = 5

        controller.control()

        pid_mock.assert_called_with(current_temp)
Пример #9
0
    def test_switch_off_heating_if_over_heating_limit(self, pid_mock_class,
                                                      fridge_temperature,
                                                      cb_current, cb_switch,
                                                      h_current, h_switch):
        pid_mock = pid_mock_class.return_value

        self.fridge_temp.get.return_value = fridge_temperature

        self.heater.get.return_value = h_current
        self.cooler.get.return_value = False
        self.limiter.get.return_value = cb_current

        pid_mock.return_value = 3  # would trigger the heater

        tunings_mock = PropertyMock()
        type(pid_mock).tunings = tunings_mock
        tunings_mock.return_value = (1, 2, 3)

        components_mock = PropertyMock()
        type(pid_mock).components = components_mock
        components_mock.return_value = (4, 3, 2)

        controller = Controller(self.config, 5, 0, self.heater, self.cooler,
                                self.limiter, self.current_temp,
                                self.fridge_temp, [])

        controller.control()

        if cb_switch is None:
            self.limiter.set.assert_not_called()
        else:
            self.limiter.set.assert_called_with(cb_switch)

        if h_switch is None:
            self.heater.set.assert_not_called()
        else:
            self.heater.set.assert_called_with(h_switch)