2026-01-26 14:51:28 +09:00

323 lines
11 KiB
C#

/*
* 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 {
/// <summary>
/// 조명 제어 결과
/// </summary>
public enum eLightResult {
/// <summary> 성공 </summary>
OK,
/// <summary> 실패 </summary>
NG,
/// <summary> 이전 값과 동일할 경우 생략 </summary>
SKIP
}
/// <summary>
/// 조명 베이스 클래스
/// </summary>
public abstract class LightBase : Device {
/// <summary> lock 설정을 위한 객체 </summary>
protected readonly object LockThis = new object();
/// <summary> 로그 </summary>
protected Logger LOG { get; set; }
/// <summary>
/// 채널 별 마지막 조명 값
/// 마지막 조명 값과 동일한 경우 Write하지 않기 위함.
/// </summary>
protected Dictionary<int, int> LastChLevels { get; set; } = new Dictionary<int, int>();
/// <summary>
/// 채널 별 마지막 On/Off 상태 값
/// 마지막 조명 상태와 동일한 경우 Write하지 않기 위함.
/// </summary>
protected Dictionary<int, bool> LastChOnOffs { get; set; } = new Dictionary<int, bool>();
/// <summary> 디바이스 컨피그 </summary>
protected LightConfig LightConfig { get; set; }
/// <summary> 연결 타입 (시리얼 or 소켓) </summary>
public eLightConnType LightConnType { get; set; } = eLightConnType.None;
/// <summary>
/// 생성자
/// EquipmentInfo.SimulationMode로 시뮬레이션 상태를 설정한다.
/// </summary>
/// <param name="deviceId">디바이스 ID</param>
protected LightBase(string deviceId)
: this(deviceId, EquipmentInfoManager.EquipmentInfo.SimulationMode) {
}
/// <summary>
/// 생성자
/// </summary>
/// <param name="deviceId">디바이스 ID</param>
/// <param name="isSimul">시뮬레이션 상태</param>
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]
}
/// <summary>
/// 다비이스 컨피그 설정
/// </summary>
/// <param name="lightConfig"></param>
protected void SetLightConfig(LightConfig lightConfig) {
LightConfig = lightConfig;
}
/// <summary>
/// 채널 별 마지막 조명 값, On/Off 상태 설정
/// </summary>
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);
}
}
}
/// <summary>
/// 채널 별 마지막 조명 값, On/Off 상태 초기화
/// </summary>
protected void ClearLastChParams() {
LastChOnOffs?.Clear();
LastChLevels?.Clear();
}
/// <summary>
/// On 상태 여부 체크
/// </summary>
/// <param name="channel">채널 번호</param>
/// <returns>true: On, false: Off</returns>
protected bool IsLastChOn(int channel) {
if (LastChOnOffs.ContainsKey(channel)) {
if (LastChOnOffs[channel].Equals(true)) {
return true;
}
}
return false;
}
/// <summary>
/// 조명 켜기 수행 메소드
/// </summary>
/// <param name="channel">채널 번호</param>
/// <returns>실행 결과</returns>
protected abstract eLightResult SetOnImpl(int channel);
/// <summary>
/// 조명 끄기 수행 메소드
/// </summary>
/// <param name="channel">채널 번호</param>
/// <returns>실행 결과</returns>
protected abstract eLightResult SetOffImpl(int channel);
/// <summary>
/// 조명 값 제어 수행 메소드
/// </summary>
/// <param name="level">설정 값</param>
/// <param name="channel">채널 번호</param>
/// <returns>실행 결과</returns>
protected abstract eLightResult SetLevelImpl(int level, int channel);
/// <summary>
/// 조명 켜기
/// </summary>
/// <param name="channel">채널 번호</param>
/// <param name="isDefault">Device Actaivated를 무시하고 조명킬지 확인 여부</param>
/// <returns>조명 제어 결과</returns>
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;
}
/// <summary>
/// 모든 채널의 조명 켜기
/// </summary>
public void SetOnAll() {
for (int ch = LightConfig.Channels.Min; ch <= LightConfig.Channels.Max; ch++) {
SetOn(ch);
}
}
/// <summary>
/// 모든 채널의 조명 켜기 - Device Activated 여부 무시하고 진행 ( 내부적으로만 사용 )
/// </summary>
internal void SetOnAllInternal() {
for (int ch = LightConfig.Channels.Min; ch <= LightConfig.Channels.Max; ch++) {
SetOn(ch, isDefault : true);
}
}
/// <summary>
/// 조명 끄기
/// </summary>
/// <param name="channel">채널 번호</param>
/// <returns>조명 제어 결과</returns>
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;
}
/// <summary>
/// 모든 채널의 조명 끄기
/// </summary>
public void SetOffAll() {
for (int ch = LightConfig.Channels.Min; ch <= LightConfig.Channels.Max; ch++) {
SetOff(ch);
}
}
/// <summary>
/// 조명 상태 가져오기
/// </summary>
/// <param name="channel">채널 번호</param>
/// <returns>조명 상태 (on : true, off : false)</returns>
public bool GetOnOff(int channel) {
if (!CheckActivated() || !CheckChannel(channel)) {
return false;
}
if (LastChOnOffs.ContainsKey(channel)) {
return LastChOnOffs[channel];
}
return false;
}
/// <summary>
/// 조명 값 가져오기
/// </summary>
/// <param name="channel">채널 번호</param>
/// <returns>조명 값</returns>
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;
}
/// <summary>
/// 조명 값 제어 (개별)
/// </summary>
/// <param name="level">레벨</param>
/// <param name="channel">채널 번호</param>
/// <returns>조명 제어 결과</returns>
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
/// <summary>
/// Channel 접근이 정상적인지 확인하는 Method (셋팅값과 동일한지)
/// </summary>
/// <param name="channel">채널</param>
/// <returns>채널 정상 여부</returns>
internal bool CheckChannel(int channel) {
if ((LightConfig.Channels.InRange(channel)) || channel == -1) {
return true;
}
else {
LOG.E($"NotSupported Channel {channel}");
return false;
}
}
/// <summary>
/// level 접근이 정상적인지 확인하는 Method (Dim Range 셋팅값과 동일한지)
/// </summary>
/// <param name="level">조명 값 (Dim Range) </param>
/// <returns>레벨 정상 여부</returns>
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
}
}