265 lines
9.7 KiB
C#
265 lines
9.7 KiB
C#
using Aurora.Api.Devices;
|
|
using Hermes;
|
|
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
|
|
namespace AuroraLight.Fainstec
|
|
{
|
|
internal class ENLight : SerialConn, IENLight
|
|
{
|
|
private string _deviceId;
|
|
private int _lightChannelCount;
|
|
|
|
public bool _commError { get; set; } = false;
|
|
private SerialConnConfig _connConfig;
|
|
readonly int BYTE_MAX = 1024;
|
|
public int[] LightValue { get; set; }
|
|
|
|
const int LIGHT_MAX_VALUE = 255;
|
|
protected int m_timeOut = 1;
|
|
|
|
public ENLight(string deviceId, bool isSimul, int lightChannelCount) : base(deviceId, isSimul)
|
|
{
|
|
_deviceId = deviceId;
|
|
_lightChannelCount = lightChannelCount;
|
|
LightValue = new int[lightChannelCount];
|
|
}
|
|
|
|
public enum _CommandType
|
|
{
|
|
SendStartOfHeader = 0x01,
|
|
SendEndOfTransmission = 0x04,
|
|
ReceiveAcknowledge = 0x06,
|
|
ReceiveNegativeAcknowledge = 0x15,
|
|
}
|
|
public enum _OperationCoed
|
|
{
|
|
Write = 0x00,
|
|
Read = 0x01,
|
|
}
|
|
|
|
public enum _RegisterAddress
|
|
{
|
|
ReadTestRegister = 0x00,
|
|
ReadWriteTestRegister = 0x04,
|
|
ChannelSelectRegister = 0x20,
|
|
StepValueRegister = 0x28,
|
|
ChannelOnOffRegister = 0x34,
|
|
AllChannelBrightnessReadRegister1 = 0x38,
|
|
AllChannelBrightnessReadRegister2 = 0x3C,
|
|
EthernetEnvironmentAddressRegister = 0x40,
|
|
EthernetEnvironmentDataRegister = 0x44,
|
|
|
|
}
|
|
public enum _ChannelControl
|
|
{
|
|
Channel1 = 0x01,
|
|
Channel2 = 0x02,
|
|
Channel3 = 0x04,
|
|
Channel4 = 0x08,
|
|
Channel5 = 0x10,
|
|
Channel6 = 0x20,
|
|
Channel7 = 0x40,
|
|
Channel8 = 0x80,
|
|
ChannelAll = 0xFF,
|
|
}
|
|
protected BitArray m_channelOnOffStatus = new BitArray(8);
|
|
public BitArray ChannelOnOffStatus {
|
|
get { lock (this) { return m_channelOnOffStatus; } }
|
|
set { lock (this) { m_channelOnOffStatus = value; } }
|
|
}
|
|
#region 비트 연산
|
|
protected static byte[] BitArrayToByteArray(BitArray bits)
|
|
{
|
|
byte[] ret = new byte[(bits.Length - 1) / 8 + 1];
|
|
bits.CopyTo(ret, 0);
|
|
return ret;
|
|
}
|
|
#endregion
|
|
public bool InitInternal(SerialConnConfig conn)
|
|
{
|
|
_connConfig = conn;
|
|
LightValue = Enumerable.Repeat(0, (int)_lightChannelCount).ToArray<int>();
|
|
|
|
bool bRet = false;
|
|
try {
|
|
// Legacy 에는 Buffer clear 를 위한 Reset 함수가 있으나, Aurora SerialConn 에서는 Write 할때 Buffer clear 를 자동으로 해준다.
|
|
// Open 할때 자동으로 켜줄것인가? 켜는함수는 따로 호출할것인가. Legacy 에서는 자동으로 켜줬는데 다른 Device 는 자동으로 켜주지 않는다.
|
|
bRet = Open(_connConfig) == E1.OK;
|
|
if (bRet) {
|
|
bRet = OffLightInternal() == E1.OK;
|
|
if (bRet)
|
|
Log.D(string.Format("[ {0} CONNECTED ]", _deviceId));
|
|
_commError = !bRet;
|
|
} else {
|
|
_commError = true;
|
|
}
|
|
return bRet;
|
|
} catch (Exception e) {
|
|
Log.W($"InitInternal Failed. ( {e.Message} )");
|
|
return bRet;
|
|
}
|
|
|
|
}
|
|
public bool IsPortErrorInternal()
|
|
{
|
|
return _commError;
|
|
}
|
|
|
|
public int OffLightInternal()
|
|
{
|
|
try {
|
|
if (!IsConnected()) return E2.NOT_CONNECTED;
|
|
SetAllLightPowerStatus(false);
|
|
return E1.OK;
|
|
} catch (Exception e) {
|
|
Log.W($"OffLightInternal Failed. ( {e.Message} )");
|
|
return E2.CANCELLED;
|
|
}
|
|
}
|
|
public int OffLightInternal(int iChannel)
|
|
{
|
|
try {
|
|
if (!IsConnected()) return E2.NOT_CONNECTED;
|
|
SetLightPowerStatus(iChannel, false);
|
|
return E1.OK;
|
|
} catch (Exception e) {
|
|
Log.W($"{iChannel}ch OffLightInternal Failed. ( {e.Message} )");
|
|
return E2.CANCELLED;
|
|
}
|
|
}
|
|
public int SetLightValueInternal(List<int> values)
|
|
{
|
|
try {
|
|
bool bRet = true;
|
|
for (int i = 0; i < values.Count; i++) {
|
|
if (SetLightBrightness(i, values[i]) != E1.OK)
|
|
bRet = false;
|
|
}
|
|
return bRet ? E1.OK : E2.CANCELLED;
|
|
} catch (Exception e) {
|
|
Log.W($"SetLightValueInternal Failed. ( {e.Message} )");
|
|
return E2.CANCELLED;
|
|
}
|
|
}
|
|
|
|
public int SetLightValueInternal(int iChannel, int iValue)
|
|
{
|
|
try {
|
|
return SetLightBrightness(iChannel, iValue);
|
|
} catch (Exception e) {
|
|
Log.W($"{iChannel}ch SetLightValueInternal Failed. ( {e.Message} )");
|
|
return E2.CANCELLED;
|
|
}
|
|
}
|
|
public void SetAllLightPowerStatus(bool on)
|
|
{
|
|
for (int i = 0; i < _lightChannelCount; i++) {
|
|
SetLightPowerStatus(i, on);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 조명의 채널을 키고 끄는 함수(밝기 값은 유지됨)
|
|
/// </summary>
|
|
/// <param name="channel">설정할 조명 채널(0부터 시작)</param>
|
|
/// <param name="on">ON/OFF</param>
|
|
public void SetLightPowerStatus(int channel, bool bOn)
|
|
{
|
|
try {
|
|
if (!IsConnected())
|
|
return;
|
|
else if (channel < 0 || _lightChannelCount - 1 < channel)
|
|
return;
|
|
|
|
lock (this) {
|
|
byte[] command = new byte[6];
|
|
command[0] = Convert.ToByte(_CommandType.SendStartOfHeader); // SOH(Start Of Header)
|
|
command[1] = Convert.ToByte(_OperationCoed.Write); // OperationCdoe(Write:0x00, Read:0x01)
|
|
command[2] = 0x01; // DataLength
|
|
command[3] = Convert.ToByte(_RegisterAddress.ChannelOnOffRegister); // Address
|
|
|
|
ChannelOnOffStatus.Set(channel, bOn);
|
|
command[4] = BitArrayToByteArray(ChannelOnOffStatus)[0];
|
|
|
|
command[5] = Convert.ToByte(_CommandType.SendEndOfTransmission); // EOT(End Of Transmission)
|
|
|
|
// write 로 쓰고 read 로 받았는지 확인하는듯하다.
|
|
// Aurora 에서는 ReadExisting 으로 하면 command 를 write 한 다음 대답을 받아오는것 같다.
|
|
// on, off 는 어디서 처리?
|
|
string strRecieve;
|
|
ReadExisting(command, out strRecieve);
|
|
|
|
//strRecieve 를 가지고 제대로 받았는지 return 할 수도 있을것 같다.
|
|
}
|
|
} catch (Exception e) {
|
|
Log.W($"{channel}ch SetLightPowerStatus Failed. ( {e.Message} )");
|
|
}
|
|
}
|
|
public int SetLightBrightness(int channel, int brightnessValue)
|
|
{
|
|
try {
|
|
if (!IsConnected())
|
|
return E2.NOT_CONNECTED;
|
|
|
|
if (!ChannelValidCheck(channel))
|
|
return E2.INVALID_ARGUMENT;
|
|
|
|
if (!ValueValidCheck(brightnessValue))
|
|
return E2.INVALID_ARGUMENT;
|
|
|
|
lock (this) {
|
|
uint targetLightValue = (uint)Math.Ceiling(LIGHT_MAX_VALUE * (brightnessValue * 0.01));
|
|
|
|
byte[] command = new byte[6];
|
|
command[0] = Convert.ToByte(_CommandType.SendStartOfHeader); // SOH(Start Of Header)
|
|
command[1] = Convert.ToByte(_OperationCoed.Write); // OperationCdoe(Write:0x00, Read:0x01)
|
|
command[2] = 0x01; // DataLength
|
|
command[3] = Convert.ToByte(_RegisterAddress.StepValueRegister); // Address
|
|
command[4] = Convert.ToByte(targetLightValue); // Data
|
|
command[5] = Convert.ToByte(_CommandType.SendEndOfTransmission); // EOT(End Of Transmission)
|
|
|
|
string strRecieve;
|
|
ReadExisting(command, out strRecieve);
|
|
|
|
byte receiveData = Convert.ToByte(strRecieve[0]);
|
|
bool bAckExist = receiveData == (int)_CommandType.ReceiveAcknowledge ? true : false;
|
|
bool bNakExist = receiveData == (int)_CommandType.ReceiveNegativeAcknowledge ? true : false;
|
|
|
|
|
|
if (bAckExist == true && bNakExist == false) {
|
|
LightValue[channel] = brightnessValue;
|
|
return E1.OK;
|
|
} else
|
|
return E2.UNAVAILABLE;
|
|
}
|
|
} catch (Exception e) {
|
|
Log.W($"{channel}ch SetLightBrightness Failed. ( {e.Message} )");
|
|
return E2.CANCELLED;
|
|
}
|
|
|
|
}
|
|
private bool ChannelValidCheck(int iChannel)
|
|
{
|
|
if (iChannel < _lightChannelCount && iChannel >= 0) {
|
|
return true;
|
|
} else {
|
|
Log.W($"Channel is not exist. Range : 0~{(int)_lightChannelCount - 1} Input : {iChannel}");
|
|
return false;
|
|
}
|
|
}
|
|
|
|
private bool ValueValidCheck(int iValue)
|
|
{
|
|
if (iValue <= 255 && iValue >= 0) {
|
|
return true;
|
|
} else {
|
|
Log.W($"LightValue Range Error. Range : 0~255, Input : {iValue}");
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
}
|