/* * Copyright (c) 2025 LG Electronics Inc. * SPDX-License-Identifier: LicenseRef-LGE-Proprietary */ using Aurora.Api; using Aurora.Api.Devices; using VisionCommon; using Hermes; using System.Collections.Generic; using System.Linq; namespace VisionLight { /// /// 조명 제어 결과 /// public enum eLightResult { /// 성공 OK, /// 실패 NG, /// 이전 값과 동일할 경우 생략 SKIP } /// /// 조명 베이스 클래스 /// public abstract class LightBase : Device { /// lock 설정을 위한 객체 protected readonly object LockThis = new object(); /// 로그 protected Logger LOG { get; set; } /// /// 채널 별 마지막 조명 값 /// 마지막 조명 값과 동일한 경우 Write하지 않기 위함. /// protected Dictionary LastChLevels { get; set; } = new Dictionary(); /// /// 채널 별 마지막 On/Off 상태 값 /// 마지막 조명 상태와 동일한 경우 Write하지 않기 위함. /// protected Dictionary LastChOnOffs { get; set; } = new Dictionary(); /// 디바이스 컨피그 protected LightConfig LightConfig { get; set; } /// 연결 타입 (시리얼 or 소켓) public eLightConnType LightConnType { get; set; } = eLightConnType.None; /// /// 생성자 /// EquipmentInfo.SimulationMode로 시뮬레이션 상태를 설정한다. /// /// 디바이스 ID protected LightBase(string deviceId) : this(deviceId, EquipmentInfoManager.EquipmentInfo.SimulationMode) { } /// /// 생성자 /// /// 디바이스 ID /// 시뮬레이션 상태 protected LightBase(string deviceId, bool isSimul) { IsSimul = isSimul; Type = DeviceType.Light; DeviceId = deviceId; LOG = new Logger(string.Format("{0}[{1}]", GetType().Name, DeviceId)); // Light_XXX[LIGHT#N] } /// /// 다비이스 컨피그 설정 /// /// protected void SetLightConfig(LightConfig lightConfig) { LightConfig = lightConfig; } /// /// 채널 별 마지막 조명 값, On/Off 상태 설정 /// protected void InitLastChParams() { for (int ch = LightConfig.Channels.Min; ch <= LightConfig.Channels.Max; ch++) { if (!LastChOnOffs.ContainsKey(ch)) { LastChOnOffs.Add(ch, false); } } for (int ch = LightConfig.Channels.Min; ch <= LightConfig.Channels.Max; ch++) { if (!LastChLevels.ContainsKey(ch)) { var initLevel = LightConfig.ChannelConfigs.Where(x => x.Ch == ch)?.FirstOrDefault()?.Level ?? 0; LastChLevels.Add(ch, initLevel); } } } /// /// 채널 별 마지막 조명 값, On/Off 상태 초기화 /// protected void ClearLastChParams() { LastChOnOffs?.Clear(); LastChLevels?.Clear(); } /// /// On 상태 여부 체크 /// /// 채널 번호 /// true: On, false: Off protected bool IsLastChOn(int channel) { if (LastChOnOffs.ContainsKey(channel)) { if (LastChOnOffs[channel].Equals(true)) { return true; } } return false; } /// /// 조명 켜기 수행 메소드 /// /// 채널 번호 /// 실행 결과 protected abstract eLightResult SetOnImpl(int channel); /// /// 조명 끄기 수행 메소드 /// /// 채널 번호 /// 실행 결과 protected abstract eLightResult SetOffImpl(int channel); /// /// 조명 값 제어 수행 메소드 /// /// 설정 값 /// 채널 번호 /// 실행 결과 protected abstract eLightResult SetLevelImpl(int level, int channel); /// /// 조명 켜기 /// /// 채널 번호 /// Device Actaivated를 무시하고 조명킬지 확인 여부 /// 조명 제어 결과 public eLightResult SetOn(int channel, bool isDefault = false) { // 마지막 조명 상태가 On일 경우 그냥 빠져 나감. if (!CheckActivated(isDefault) || !CheckChannel(channel)) { return eLightResult.NG; } if (IsLastChOn(channel)) { return eLightResult.SKIP; } var res = eLightResult.OK; if (!IsSimul) { res = SetOnImpl(channel); } if (res == eLightResult.OK) { LastChOnOffs[channel] = true; // 마지막 조명 상태 저장 } return res; } /// /// 모든 채널의 조명 켜기 /// public void SetOnAll() { for (int ch = LightConfig.Channels.Min; ch <= LightConfig.Channels.Max; ch++) { SetOn(ch); } } /// /// 모든 채널의 조명 켜기 - Device Activated 여부 무시하고 진행 ( 내부적으로만 사용 ) /// internal void SetOnAllInternal() { for (int ch = LightConfig.Channels.Min; ch <= LightConfig.Channels.Max; ch++) { SetOn(ch, isDefault : true); } } /// /// 조명 끄기 /// /// 채널 번호 /// 조명 제어 결과 public eLightResult SetOff(int channel) { if (!CheckActivated() || !CheckChannel(channel)) { return eLightResult.NG; } // 마지막 조명 상태가 Off일 경우 그냥 빠져 나감. if (!IsLastChOn(channel)) { return eLightResult.SKIP; } var res = eLightResult.OK; if (!IsSimul) { res = SetOffImpl(channel); } if (res == eLightResult.OK) { LastChOnOffs[channel] = false; // 마지막 조명 상태 저장 } return res; } /// /// 모든 채널의 조명 끄기 /// public void SetOffAll() { for (int ch = LightConfig.Channels.Min; ch <= LightConfig.Channels.Max; ch++) { SetOff(ch); } } /// /// 조명 상태 가져오기 /// /// 채널 번호 /// 조명 상태 (on : true, off : false) public bool GetOnOff(int channel) { if (!CheckActivated() || !CheckChannel(channel)) { return false; } if (LastChOnOffs.ContainsKey(channel)) { return LastChOnOffs[channel]; } return false; } /// /// 조명 값 가져오기 /// /// 채널 번호 /// 조명 값 public int GetLevel(int channel) { if (!CheckActivated() || !CheckChannel(channel)) { return -1; } if (LastChLevels.ContainsKey(channel)) { return LastChLevels[channel]; } LOG.FuncE($"Invalid channel : {channel}"); return 0; } /// /// 조명 값 제어 (개별) /// /// 레벨 /// 채널 번호 /// 조명 제어 결과 public eLightResult SetLevel(int level, int channel) { if (!CheckActivated() || !CheckChannel(channel) || !CheckLevel(level)) { return eLightResult.NG; } // 마지막 조명값과 동일한 경우 그냥 빠져 나감. if (LastChLevels.ContainsKey(channel)) { if (LastChLevels[channel].Equals(level)) { return eLightResult.SKIP; } } var res = eLightResult.OK; if (!IsSimul) { res = SetLevelImpl(level, channel); } if (res == eLightResult.OK) { LastChLevels[channel] = level; // 마지막 조명 값 저장 } return res; } #region Check Method /// /// Channel 접근이 정상적인지 확인하는 Method (셋팅값과 동일한지) /// /// 채널 /// 채널 정상 여부 internal bool CheckChannel(int channel) { if ((LightConfig.Channels.InRange(channel)) || channel == -1) { return true; } else { LOG.E($"NotSupported Channel {channel}"); return false; } } /// /// level 접근이 정상적인지 확인하는 Method (Dim Range 셋팅값과 동일한지) /// /// 조명 값 (Dim Range) /// 레벨 정상 여부 internal bool CheckLevel(int level) { if (LightConfig.DimRange.InRange(level)) { return true; } else { LOG.E($"NotSupported level({LightConfig.DimRange.Min} ~ {LightConfig.DimRange.Max}) : {level}"); return false; } } internal bool CheckActivated(bool isDiscard = false) { if(isDiscard) { return true; } if (!IsActivated) { LOG.E($"{DeviceId} : Light Device is not activated"); } return IsActivated; } #endregion } }