예제 #1
0
    def _schedule_orm_to_dto(
        schedule_orm
    ):  # type: (DaySchedule) -> Optional[ThermostatScheduleDTO]
        schedule = schedule_orm.schedule_data
        amount_of_entries = len(schedule)
        if amount_of_entries == 0:
            logger.warning('Mapping an empty temperature day schedule.')
            return None
        if amount_of_entries < 5:
            logger.warning(
                'Not enough data to map day schedule. Returning best effort data.'
            )
            return ThermostatScheduleDTO(temp_night=16.0,
                                         start_day_1='07:00',
                                         end_day_1='09:00',
                                         temp_day_1=20,
                                         start_day_2='16:00',
                                         end_day_2='22:00',
                                         temp_day_2=20)

        # Parsing day/night, assuming following (classic) schedule:
        #      ______     ______
        #      |    |     |    |
        # _____|    |_____|    |_____
        # ^    ^    ^     ^    ^
        # So to parse a classic format out of it, at least 5 of the markers are required
        index = 0
        kwargs = {}  # type: Dict[str, Any]
        for timestamp in sorted(schedule.keys(), key=lambda t: int(t)):
            temperature = schedule[timestamp]
            timestamp_int = int(timestamp)
            if index == 0:
                kwargs['temp_night'] = temperature
            elif index == 1:
                kwargs['temp_day_1'] = temperature
                kwargs['start_day_1'] = '{0:02d}:{1:02d}'.format(
                    timestamp_int // 3600, (timestamp_int % 3600) // 60)
            elif index == 2:
                kwargs['end_day_1'] = '{0:02d}:{1:02d}'.format(
                    timestamp_int // 3600, (timestamp_int % 3600) // 60)
            elif index == 3:
                kwargs['temp_day_2'] = temperature
                kwargs['start_day_2'] = '{0:02d}:{1:02d}'.format(
                    timestamp_int // 3600, (timestamp_int % 3600) // 60)
            elif index == 4:
                kwargs['end_day_2'] = '{0:02d}:{1:02d}'.format(
                    timestamp_int // 3600, (timestamp_int % 3600) // 60)
            index += 1
        return ThermostatScheduleDTO(**kwargs)
예제 #2
0
 def orm_to_dto(orm_object):  # type: (EepromModel) -> ThermostatDTO
     data = orm_object.serialize()
     kwargs = {
         'name': data['name'],
         'permanent_manual': data['permanent_manual']
     }
     for i in range(6):
         field = 'setp{0}'.format(i)
         kwargs[field] = data[field]
     for field in [
             'sensor', 'output0', 'output1', 'pid_p', 'pid_i', 'pid_d',
             'pid_int', 'room'
     ]:
         kwargs[field] = Toolbox.nonify(data[field],
                                        ThermostatMapper.BYTE_MAX)
     for day in ['mon', 'tue', 'wed', 'thu', 'fri', 'sat', 'sun']:
         field = 'auto_{0}'.format(day)
         kwargs[field] = ThermostatScheduleDTO(temp_night=data[field][0],
                                               start_day_1=data[field][1],
                                               end_day_1=data[field][2],
                                               temp_day_1=data[field][3],
                                               start_day_2=data[field][4],
                                               end_day_2=data[field][5],
                                               temp_day_2=data[field][6])
     return ThermostatDTO(id=data['id'], **kwargs)
예제 #3
0
    def test_orm_to_dto_mapping(self):
        controller = GatewayThermostatMappingTests._create_controller()

        group, _ = ThermostatGroup.get_or_create(
            number=0,
            name='Default',
            on=True,
            mode=ThermostatGroup.Modes.HEATING)
        thermostat = Thermostat(
            number=10,
            start=0,  # 0 is on a thursday
            name='thermostat',
            thermostat_group=group)
        thermostat.save()

        for i in range(7):
            day_schedule = DaySchedule(index=i, content='{}', mode='heating')
            day_schedule.thermostat = thermostat
            day_schedule.save()

        heating_thermostats = controller.load_heating_thermostats()
        self.assertEqual(1, len(heating_thermostats))
        dto = heating_thermostats[0]  # type: ThermostatDTO

        self.assertEqual(
            ThermostatDTO(id=10,
                          name='thermostat',
                          setp3=14.0,
                          setp4=14.0,
                          setp5=14.0,
                          sensor=None,
                          pid_p=120.0,
                          pid_i=0.0,
                          pid_d=0.0,
                          room=None,
                          permanent_manual=True), dto)

        day_schedule = thermostat.heating_schedules()[0]  # type: DaySchedule
        day_schedule.schedule_data = {
            0: 5.0,
            120: 5.5,  # 120 and 1200 are selected because 120 < 1200,
            1200: 6.0,  # but str(120) > str(1200)
            3600: 6.5,
            7500: 7.0
        }
        day_schedule.save()
        heating_thermostats = controller.load_heating_thermostats()
        self.assertEqual(1, len(heating_thermostats))
        dto = heating_thermostats[0]  # type: ThermostatDTO

        self.assertEqual(
            ThermostatScheduleDTO(temp_night=5.0,
                                  temp_day_1=5.5,
                                  temp_day_2=6.5,
                                  start_day_1='00:02',
                                  end_day_1='00:20',
                                  start_day_2='01:00',
                                  end_day_2='02:05'), dto.auto_thu)
예제 #4
0
    def _schedule_orm_to_dto(
        schedule_orm,
        mode,
        log_warnings=True
    ):  # type: (DaySchedule, Literal['cooling', 'heating'], bool) -> Optional[ThermostatScheduleDTO]
        schedule = schedule_orm.schedule_data
        amount_of_entries = len(schedule)
        if amount_of_entries == 0:
            if log_warnings:
                logger.warning('Mapping an empty temperature day schedule.')
            schedule = DaySchedule.DEFAULT_SCHEDULE[mode]
        elif amount_of_entries < 5:
            if log_warnings:
                logger.warning(
                    'Not enough data to map day schedule. Returning best effort data.'
                )
            schedule = DaySchedule.DEFAULT_SCHEDULE[mode]

        # Parsing day/night, assuming following (classic) schedule:
        #      ______     ______
        #      |    |     |    |
        # _____|    |_____|    |_____
        # ^    ^    ^     ^    ^
        # So to parse a classic format out of it, at least 5 of the markers are required
        index = 0
        kwargs = {}  # type: Dict[str, Any]
        for timestamp in sorted(schedule.keys(), key=lambda t: int(t)):
            temperature = schedule[timestamp]
            timestamp_int = int(timestamp)
            if index == 0:
                kwargs['temp_night'] = temperature
            elif index == 1:
                kwargs['temp_day_1'] = temperature
                kwargs['start_day_1'] = '{0:02d}:{1:02d}'.format(
                    timestamp_int // 3600, (timestamp_int % 3600) // 60)
            elif index == 2:
                kwargs['end_day_1'] = '{0:02d}:{1:02d}'.format(
                    timestamp_int // 3600, (timestamp_int % 3600) // 60)
            elif index == 3:
                kwargs['temp_day_2'] = temperature
                kwargs['start_day_2'] = '{0:02d}:{1:02d}'.format(
                    timestamp_int // 3600, (timestamp_int % 3600) // 60)
            elif index == 4:
                kwargs['end_day_2'] = '{0:02d}:{1:02d}'.format(
                    timestamp_int // 3600, (timestamp_int % 3600) // 60)
            index += 1
        return ThermostatScheduleDTO(**kwargs)
예제 #5
0
 def deserialize(
         api_data):  # type: (Dict) -> Tuple[ThermostatDTO, List[str]]
     loaded_fields = ['id']
     thermostat_dto = ThermostatDTO(api_data['id'])
     loaded_fields += SerializerToolbox.deserialize(
         dto=thermostat_dto,  # Referenced
         api_data=api_data,
         mapping={
             'name': ('name', None),
             'permanent_manual': ('permanent_manual', None),
             'setp0': ('setp0', None),
             'setp1': ('setp1', None),
             'setp2': ('setp2', None),
             'setp3': ('setp3', None),
             'setp4': ('setp4', None),
             'setp5': ('setp5', None),
             'room': ('room', ThermostatSerializer.BYTE_MAX),
             'sensor': ('sensor', ThermostatSerializer.BYTE_MAX),
             'output0': ('output0', ThermostatSerializer.BYTE_MAX),
             'output1': ('output1', ThermostatSerializer.BYTE_MAX),
             'pid_p': ('pid_p', ThermostatSerializer.BYTE_MAX),
             'pid_i': ('pid_i', ThermostatSerializer.BYTE_MAX),
             'pid_d': ('pid_d', ThermostatSerializer.BYTE_MAX),
             'pid_int': ('pid_int', ThermostatSerializer.BYTE_MAX)
         })
     for day in ['mon', 'tue', 'wed', 'thu', 'fri', 'sat', 'sun']:
         field = 'auto_{0}'.format(day)
         if field not in api_data:
             continue
         loaded_fields.append(field)
         field_dto = ThermostatScheduleDTO(temp_night=api_data[field][0],
                                           start_day_1=api_data[field][1],
                                           end_day_1=api_data[field][2],
                                           temp_day_1=api_data[field][3],
                                           start_day_2=api_data[field][4],
                                           end_day_2=api_data[field][5],
                                           temp_day_2=api_data[field][6])
         setattr(thermostat_dto, field, field_dto)
     return thermostat_dto, loaded_fields
예제 #6
0
    def test_save(self):
        temperatures = {}

        def _get_temperature(sensor_id):
            return temperatures[sensor_id]

        controller = GatewayThermostatMappingTests._create_controller(
            get_sensor_temperature_status=_get_temperature)

        room = Room(number=5)
        room.save()

        thermostat_group = ThermostatGroup(number=0, name='global')
        thermostat_group.save()
        thermostat = Thermostat(
            number=10,
            start=0,  # 0 is on a thursday
            name='thermostat',
            thermostat_group=thermostat_group)
        thermostat.save()

        heating_thermostats = controller.load_heating_thermostats()
        self.assertEqual(1, len(heating_thermostats))
        dto = heating_thermostats[0]  # type: ThermostatDTO

        default_schedule_dto = ThermostatScheduleDTO(temp_day_1=20.0,
                                                     start_day_1='07:00',
                                                     end_day_1='09:00',
                                                     temp_day_2=21.0,
                                                     start_day_2='17:00',
                                                     end_day_2='22:00',
                                                     temp_night=16.0)

        Sensor.create(number=15)

        dto.room = 5
        dto.sensor = 15
        dto.output0 = 5
        dto.name = 'changed'
        dto.auto_thu = ThermostatScheduleDTO(temp_night=10,
                                             temp_day_1=15,
                                             temp_day_2=30,
                                             start_day_1='08:00',
                                             end_day_1='10:30',
                                             start_day_2='16:00',
                                             end_day_2='18:45')

        temperatures[15] = 5.0
        controller.save_heating_thermostats([dto])

        heating_thermostats = controller.load_heating_thermostats()
        self.assertEqual(1, len(heating_thermostats))
        dto = heating_thermostats[0]  # type: ThermostatDTO

        self.assertEqual(
            ThermostatDTO(id=10,
                          name='changed',
                          setp3=16.0,
                          setp4=15.0,
                          setp5=22.0,
                          sensor=15,
                          pid_p=120.0,
                          pid_i=0.0,
                          pid_d=0.0,
                          room=5,
                          output0=5,
                          permanent_manual=True,
                          auto_mon=default_schedule_dto,
                          auto_tue=default_schedule_dto,
                          auto_wed=default_schedule_dto,
                          auto_thu=ThermostatScheduleDTO(temp_night=10.0,
                                                         temp_day_1=15.0,
                                                         temp_day_2=30.0,
                                                         start_day_1='08:00',
                                                         end_day_1='10:30',
                                                         start_day_2='16:00',
                                                         end_day_2='18:45'),
                          auto_fri=default_schedule_dto,
                          auto_sat=default_schedule_dto,
                          auto_sun=default_schedule_dto), dto)
예제 #7
0
 def serialize(
         thermostat_dto,
         fields):  # type: (ThermostatDTO, Optional[List[str]]) -> Dict
     data = {
         'id':
         thermostat_dto.id,
         'name':
         thermostat_dto.name,
         'room':
         Toolbox.denonify(thermostat_dto.room,
                          ThermostatSerializer.BYTE_MAX),
         'setp0':
         thermostat_dto.setp0,
         'setp1':
         thermostat_dto.setp1,
         'setp2':
         thermostat_dto.setp2,
         'setp3':
         thermostat_dto.setp3,
         'setp4':
         thermostat_dto.setp4,
         'setp5':
         thermostat_dto.setp5,
         'sensor':
         Toolbox.denonify(thermostat_dto.sensor,
                          ThermostatSerializer.BYTE_MAX),
         'output0':
         Toolbox.denonify(thermostat_dto.output0,
                          ThermostatSerializer.BYTE_MAX),
         'output1':
         Toolbox.denonify(thermostat_dto.output1,
                          ThermostatSerializer.BYTE_MAX),
         'pid_p':
         Toolbox.denonify(thermostat_dto.pid_p,
                          ThermostatSerializer.BYTE_MAX),
         'pid_i':
         Toolbox.denonify(thermostat_dto.pid_i,
                          ThermostatSerializer.BYTE_MAX),
         'pid_d':
         Toolbox.denonify(thermostat_dto.pid_d,
                          ThermostatSerializer.BYTE_MAX),
         'pid_int':
         Toolbox.denonify(thermostat_dto.pid_int,
                          ThermostatSerializer.BYTE_MAX),
         'permanent_manual':
         thermostat_dto.permanent_manual
     }
     for day in ['mon', 'tue', 'wed', 'thu', 'fri', 'sat', 'sun']:
         field = 'auto_{0}'.format(day)
         dto_data = getattr(thermostat_dto,
                            field)  # type: ThermostatScheduleDTO
         if dto_data is None:
             # TODO: Remove once UI can handle "no schedule"
             dto_data = ThermostatScheduleDTO(temp_night=16,
                                              temp_day_1=20,
                                              temp_day_2=20,
                                              start_day_1="07:00",
                                              end_day_1="09:00",
                                              start_day_2="16:00",
                                              end_day_2="22:00")
         data[field] = [
             dto_data.temp_night, dto_data.start_day_1, dto_data.end_day_1,
             dto_data.temp_day_1, dto_data.start_day_2, dto_data.end_day_2,
             dto_data.temp_day_2
         ]
     return SerializerToolbox.filter_fields(data, fields)
예제 #8
0
    def test_save(self):
        temperatures = {}

        def _get_temperature(sensor_id):
            return temperatures[sensor_id]

        controller = GatewayThermostatMappingTests._create_controller(
            get_sensor_temperature_status=_get_temperature)

        thermostat_group = ThermostatGroup(number=0, name='global')
        thermostat_group.save()
        thermostat = Thermostat(
            number=10,
            start=0,  # 0 is on a thursday
            name='thermostat',
            thermostat_group=thermostat_group)
        thermostat.save()

        for i in range(7):
            day_schedule = DaySchedule(index=i, content='{}', mode='heating')
            day_schedule.thermostat = thermostat
            day_schedule.save()

        heating_thermostats = controller.load_heating_thermostats()
        self.assertEqual(1, len(heating_thermostats))
        dto = heating_thermostats[0]  # type: ThermostatDTO

        Sensor.create(number=15)

        dto.room = 5  # This field won't be saved
        dto.sensor = 15
        dto.output0 = 5
        dto.name = 'changed'
        dto.auto_thu = ThermostatScheduleDTO(temp_night=10,
                                             temp_day_1=15,
                                             temp_day_2=30,
                                             start_day_1='08:00',
                                             end_day_1='10:30',
                                             start_day_2='16:00',
                                             end_day_2='18:45')

        temperatures[15] = 5.0
        controller.save_heating_thermostats([
            (dto, ['sensor', 'output0', 'name', 'auto_thu'])
        ])

        heating_thermostats = controller.load_heating_thermostats()
        self.assertEqual(1, len(heating_thermostats))
        dto = heating_thermostats[0]  # type: ThermostatDTO

        self.assertEqual(
            ThermostatDTO(
                id=10,
                name='changed',
                setp3=14.0,
                setp4=14.0,
                setp5=14.0,
                sensor=15,
                pid_p=120.0,
                pid_i=0.0,
                pid_d=0.0,
                room=None,  # Unchanged
                output0=5,
                permanent_manual=True,
                auto_thu=ThermostatScheduleDTO(temp_night=10.0,
                                               temp_day_1=15.0,
                                               temp_day_2=30.0,
                                               start_day_1='08:00',
                                               end_day_1='10:30',
                                               start_day_2='16:00',
                                               end_day_2='18:45')),
            dto)