/*
* 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
}
}