Home4/src/main/java/de/ph87/home/device/DeviceService.java
2024-11-27 14:32:25 +01:00

101 lines
3.3 KiB
Java

package de.ph87.home.device;
import de.ph87.home.area.Area;
import de.ph87.home.area.AreaService;
import de.ph87.home.common.crud.CrudAction;
import de.ph87.home.common.crud.EntityNotFound;
import de.ph87.home.property.*;
import jakarta.annotation.Nullable;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.List;
@Slf4j
@Service
@Transactional
@RequiredArgsConstructor
public class DeviceService {
private final PropertyService propertyService;
private final DeviceRepository deviceRepository;
private final ApplicationEventPublisher applicationEventPublisher;
private final AreaService areaService;
@NonNull
public DeviceDto create(@NonNull final String areaUuid, @NonNull final String name, @NonNull final String slug, @NonNull final String stateProperty) {
final Area area = areaService.getByUuid(areaUuid);
return publish(deviceRepository.save(new Device(area, name, slug, stateProperty)), CrudAction.UPDATED);
}
public void setState(@NonNull final String uuidOrSlug, final boolean state) throws PropertyNotFound, PropertyNotWritable, PropertyTypeMismatch {
log.debug("setState: uuidOrSlug={}, state={}", uuidOrSlug, state);
final Device device = getByUuidOrSlug(uuidOrSlug);
propertyService.write(device.getStatePropertyId(), state, Boolean.class);
}
@NonNull
public DeviceDto getByUuidOrSlugDto(final @NonNull String uuidOrSlug) {
return toDto(getByUuidOrSlug(uuidOrSlug));
}
@NonNull
private Device getByUuidOrSlug(@NonNull final String uuidOrSlug) {
return deviceRepository.findByUuidOrSlug(uuidOrSlug, uuidOrSlug).orElseThrow(() -> new EntityNotFound("uuidOrSlug", uuidOrSlug));
}
@NonNull
public DeviceDto toDto(@NonNull final Device device) {
final PropertyDto<Boolean> state = propertyService.dtoByIdAndTypeOrNull(device.getStatePropertyId(), Boolean.class);
return new DeviceDto(device, state);
}
@NonNull
private Device getByUuid(@NonNull final String uuid) {
return deviceRepository.findById(uuid).orElseThrow(() -> new EntityNotFound("uuid", uuid));
}
@NonNull
public List<DeviceDto> list(@Nullable final DeviceFilter filter) throws PropertyTypeMismatch {
final List<DeviceDto> all = deviceRepository.findAll().stream().map(this::toDto).toList();
if (filter == null) {
return all;
}
final List<DeviceDto> results = new ArrayList<>();
for (final DeviceDto dto : all) {
if (filter.filter(dto)) {
results.add(dto);
}
}
return results;
}
@EventListener(PropertyDto.class)
public void onPropertyChange(@NonNull final PropertyDto<?> dto) {
deviceRepository.findAllByStatePropertyId(dto.getId()).forEach(device -> publish(device, CrudAction.CREATED));
}
@NonNull
private DeviceDto publish(@NonNull final Device device, @NonNull final CrudAction action) {
final DeviceDto dto = toDto(device);
log.info("Device {}: {}", action, dto);
applicationEventPublisher.publishEvent(dto);
return dto;
}
@NonNull
public DeviceDto getByUuidDto(@NonNull final String uuid) {
return toDto(getByUuid(uuid));
}
}