def v0_set_thermostat_mode(self,
                               thermostat_on,
                               cooling_mode=False,
                               cooling_on=False,
                               automatic=None,
                               setpoint=None):
        mode = 'cooling' if cooling_mode else 'heating'
        global_thermosat = ThermostatGroup.v0_get_global()
        global_thermosat.on = thermostat_on
        global_thermosat.mode = mode
        global_thermosat.save()

        for thermostat_number, thermostat_pid in self.thermostat_pids.iteritems(
        ):
            thermostat = Thermostat.get(number=thermostat_number)
            if thermostat is not None:
                if automatic is False and setpoint is not None and 3 <= setpoint <= 5:
                    thermostat.active_preset = Preset.get_by_thermostat_and_v0_setpoint(
                        thermostat=thermostat, v0_setpoint=setpoint)
                else:
                    thermostat.active_preset = thermostat.get_preset(
                        'SCHEDULE')
                thermostat_pid.update_thermostat(thermostat)
                thermostat_pid.tick()
        return {'status': 'OK'}
 def v0_get_thermostat_configurations(self, fields=None):
     # TODO: implement the new v1 config format
     thermostats = Thermostat.select()
     return [
         thermostat.to_v0_format(mode='heating', fields=fields)
         for thermostat in thermostats
     ]
    def set_current_preset(self, thermostat_number, preset_name):
        thermostat = Thermostat.get(number=thermostat_number)
        preset = thermostat.get_preset(preset_name)
        thermostat.active_preset = preset
        thermostat.save()

        thermostat_pid = self.thermostat_pids.get(thermostat_number)
        thermostat_pid.update_thermostat(thermostat)
        thermostat_pid.tick()
 def refresh_thermostats_from_db(self):
     for thermostat in Thermostat.select():
         thermostat_pid = self.thermostat_pids.get(thermostat.number)
         if thermostat_pid is None:
             thermostat_pid = ThermostatPid(thermostat,
                                            self._pump_valve_controller)
             thermostat_pid.subscribe_state_changes(
                 self.v0_event_thermostat_changed)
             self.thermostat_pids[thermostat.number] = thermostat_pid
         thermostat_pid.update_thermostat(thermostat)
         thermostat_pid.tick()
    def set_setpoint_from_scheduler(cls,
                                    thermostat_number,
                                    heating_temperature=None,
                                    cooling_temperature=None,
                                    thermostat_controller=INJECTED):
        logger.info(
            'Setting setpoint from scheduler for thermostat {}: H{} C{}'.
            format(thermostat_number, heating_temperature,
                   cooling_temperature))
        thermostat = Thermostat.get(number=thermostat_number)
        active_preset = thermostat.active_preset

        # only update when not in preset mode like away, party, ...
        if active_preset.name == 'SCHEDULE':
            thermostat_controller.set_current_setpoint(thermostat_number,
                                                       heating_temperature,
                                                       cooling_temperature)
        else:
            logger.info(
                'Thermostat is currently in preset mode, skipping update setpoint from scheduler.'
            )
    def set_current_setpoint(self,
                             thermostat_number,
                             heating_temperature=None,
                             cooling_temperature=None):
        if heating_temperature is None and cooling_temperature is None:
            return

        thermostat = Thermostat.get(number=thermostat_number)
        # when setting a setpoint manually, switch to manual preset except for when we are in scheduled mode
        # scheduled mode will override the setpoint when the next edge in the schedule is triggered
        active_preset = thermostat.active_preset
        if active_preset.name not in ['SCHEDULE', 'MANUAL']:
            active_preset = thermostat.get_preset('MANUAL')
            thermostat.active_preset = active_preset

        if heating_temperature is not None:
            active_preset.heating_setpoint = float(heating_temperature)
        if cooling_temperature is not None:
            active_preset.cooling_setpoint = float(cooling_temperature)
        active_preset.save()
        thermostat_pid = self.thermostat_pids.get(thermostat_number)
        thermostat_pid.update_thermostat(thermostat)
        thermostat_pid.tick()
    def create_or_update_thermostat_from_v0_api(thermostat_number,
                                                config,
                                                mode='heating'):
        """
        :param thermostat_number: the thermostat number for which the config needs to be stored
        :type thermostat_number: int
        :param config: the v0 config dict e.g. {'auto_wed': [17, '06:30', '08:30', 20, '17:00', '23:30', 21], 'auto_mon': [17, '06:30', '08:30', 20, '17:00', '23:30', 21], 'output0': 0, 'output1': 3, 'room': 255, 'id': 2, 'auto_sat': [17, '06:30', '08:30', 20, '17:00', '23:30', 21], 'sensor': 0, 'auto_sun': [17, '06:30', '08:30', 20, '17:00', '23:30', 21], 'auto_th': [17, '06:30', '08:30', 20, '17:00', '23:30', 21], 'pid_int': 0, 'auto_tue': [17, '06:30', '08:30', 20, '17:00', '23:30', 21], 'setp0': 20, 'setp5': 18, 'setp4': 18, 'pid_p': 120, 'setp1': 17, 'name': 'H - Thermostat 2', 'setp3': 18, 'setp2': 21, 'auto_fri': [17, '06:30', '08:30', 20, '17:00', '23:30', 21], 'pid_d': 0, 'pid_i': 0}
        :type config: dict
        :param mode: heating or cooling
        :type mode: str
        :returns the thermostat
        """
        logger.info('config {}'.format(config))
        # we don't get a start date, calculate last monday night to map the schedules
        now = int(time.time())
        day_of_week = (now / 86400 - 4) % 7  # 0: Monday, 1: Tuesday, ...
        last_monday_night = now - now % 86400 - day_of_week * 86400

        # update/save thermostat configuration
        try:
            thermostat = Thermostat.get(number=thermostat_number)
        except DoesNotExist:
            thermostat = Thermostat(number=thermostat_number)
        if config.get('name') is not None:
            thermostat.name = config['name']
        if config.get('sensor') is not None:
            thermostat.sensor = int(config['sensor'])
        if config.get('room') is not None:
            thermostat.room = int(config['room'])
        if config.get('pid_p') is not None:
            if mode == 'heating':
                thermostat.pid_heating_p = float(config['pid_p'])
            else:
                thermostat.pid_cooling_p = float(config['pid_p'])
        if config.get('pid_i') is not None:
            if mode == 'heating':
                thermostat.pid_heating_i = float(config['pid_i'])
            else:
                thermostat.pid_cooling_i = float(config['pid_i'])
        if config.get('pid_d') is not None:
            if mode == 'heating':
                thermostat.pid_heating_d = float(config['pid_d'])
            else:
                thermostat.pid_cooling_d = float(config['pid_d'])
        thermostat.start = last_monday_night
        thermostat.save()

        # update/save output configuration
        output_config_present = config.get(
            'output0') is not None or config.get('output1') is not None
        if output_config_present:
            # unlink all previously linked valve_numbers, we are resetting this with the new outputs we got from the API
            deleted = ValveToThermostat.delete().where(ValveToThermostat.thermostat == thermostat)\
                                                .where(ValveToThermostat.mode == mode)\
                                                .execute()
            logger.info('unlinked {} valve_numbers from thermostat {}'.format(
                deleted, thermostat.name))

            for field in ['output0', 'output1']:
                if config.get(field) is not None:
                    # 1. get or create output, creation also saves to db
                    output_number = int(config[field])
                    if output_number == 255:
                        continue
                    output, output_created = Output.get_or_create(
                        number=output_number)

                    # 2. get or create the valve and link to this output
                    try:
                        valve = Valve.get(output=output, number=output_number)

                    except DoesNotExist:
                        valve = Valve(output=output, number=output_number)
                    valve.name = 'Valve (output {})'.format(output_number)
                    valve.save()

                    # 3. link the valve to the thermostat, set properties
                    try:
                        valve_to_thermostat = ValveToThermostat.get(
                            valve=valve, thermostat=thermostat, mode=mode)
                    except DoesNotExist:
                        valve_to_thermostat = ValveToThermostat(
                            valve=valve, thermostat=thermostat, mode=mode)
                    # TODO: decide if this is a cooling thermostat or heating thermostat
                    valve_to_thermostat.priority = 0 if field == 'output0' else 1
                    valve_to_thermostat.save()

        # update/save scheduling configuration
        for (day_index, key) in [(0, 'auto_mon'), (1, 'auto_tue'),
                                 (2, 'auto_wed'), (3, 'auto_thu'),
                                 (4, 'auto_fri'), (5, 'auto_sat'),
                                 (6, 'auto_sun')]:
            if config.get(key) is not None:
                v0_schedule = config[key]
                try:
                    day_schedule = DaySchedule.get(thermostat=thermostat,
                                                   index=day_index,
                                                   mode=mode)
                    day_schedule.update_schedule_from_v0(v0_schedule)
                except DoesNotExist:
                    day_schedule = DaySchedule.from_v0_dict(
                        thermostat=thermostat,
                        index=day_index,
                        mode=mode,
                        v0_schedule=v0_schedule)
                day_schedule.save()

        for (field, preset_name) in [('setp3', 'AWAY'), ('setp4', 'VACATION'),
                                     ('setp5', 'PARTY')]:
            if config.get(field) is not None:
                try:
                    preset = Preset.get(name=preset_name,
                                        thermostat=thermostat)
                except DoesNotExist:
                    preset = Preset(name=preset_name, thermostat=thermostat)
                if mode == 'cooling':
                    preset.cooling_setpoint = float(config[field])
                else:
                    preset.heating_setpoint = float(config[field])
                preset.active = False
                preset.save()

        return thermostat
 def v0_get_cooling_configuration(self, cooling_id, fields=None):
     # TODO: implement the new v1 config format
     thermostat = Thermostat.get(number=cooling_id)
     return thermostat.to_v0_format(mode='cooling', fields=fields)
 def v0_get_cooling_configurations(self, fields=None):
     thermostats = Thermostat.select()
     return [
         thermostat.to_v0_format(mode='cooling', fields=fields)
         for thermostat in thermostats
     ]
 def v0_get_thermostat_configuration(self, thermostat_number, fields=None):
     # TODO: implement the new v1 config format
     thermostat = Thermostat.get(number=thermostat_number)
     return thermostat.to_v0_format(mode='heating', fields=fields)
 def get_current_preset(self, thermostat_number):
     thermostat = Thermostat.get(number=thermostat_number)
     return thermostat.active_preset