public void PLCSafetyInterlockStatusEnumTest() { //GetFromByte Tests Assert.AreEqual(PLCSafetyInterlockStatusEnum.UNDEFINED, PLCSafetyInterlockStatusConversionHelper.GetFromByte(0x0)); Assert.AreEqual(PLCSafetyInterlockStatusEnum.LOCKED, PLCSafetyInterlockStatusConversionHelper.GetFromByte(0x1)); Assert.AreEqual(PLCSafetyInterlockStatusEnum.UNLOCKED, PLCSafetyInterlockStatusConversionHelper.GetFromByte(0x2)); //ConvertToByte Tests Assert.AreEqual(0x0, PLCSafetyInterlockStatusConversionHelper.ConvertToByte(PLCSafetyInterlockStatusEnum.UNDEFINED)); Assert.AreEqual(0x1, PLCSafetyInterlockStatusConversionHelper.ConvertToByte(PLCSafetyInterlockStatusEnum.LOCKED)); Assert.AreEqual(0x2, PLCSafetyInterlockStatusConversionHelper.ConvertToByte(PLCSafetyInterlockStatusEnum.UNLOCKED)); }
public bool ProcessRequest(NetworkStream ActiveClientStream, byte[] query) { int ExpectedSize = query[0] + (256 * query[1]); if (query.Length != ExpectedSize) { throw new ArgumentException( "ScaleModelPLCDriverController read a package specifying a size [" + ExpectedSize.ToString() + "], but the actual size was different [" + query.Length + "]." ); } byte CommandQueryTypeAndExpectedResponseStatus = query[2]; byte CommandQueryTypeByte = (byte)(CommandQueryTypeAndExpectedResponseStatus & 0x3F); byte ExpectedResponseStatusByte = (byte)(CommandQueryTypeAndExpectedResponseStatus >> 6); PLCCommandAndQueryTypeEnum CommandQueryTypeEnum = PLCCommandAndQueryTypeConversionHelper.GetFromByte(CommandQueryTypeByte); PLCCommandResponseExpectationEnum ExpectedResponseStatusEnum = PLCCommandResponseExpectationConversionHelper.GetFromByte(ExpectedResponseStatusByte); byte[] FinalResponseContainer; if (ExpectedResponseStatusEnum == PLCCommandResponseExpectationEnum.FULL_RESPONSE) { FinalResponseContainer = new byte[] { 0x13, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }; switch (CommandQueryTypeEnum) { case PLCCommandAndQueryTypeEnum.TEST_CONNECTION: { FinalResponseContainer[3] = 0x1; FinalResponseContainer[2] = 0x1; break; } case PLCCommandAndQueryTypeEnum.GET_CURRENT_AZEL_POSITIONS: { double TestAzimuth = 180.0; double TestElevation = 42.0; Array.Copy(BitConverter.GetBytes(TestAzimuth), 0, FinalResponseContainer, 3, 8); Array.Copy(BitConverter.GetBytes(TestElevation), 0, FinalResponseContainer, 11, 8); FinalResponseContainer[2] = 0x1; break; } case PLCCommandAndQueryTypeEnum.GET_CURRENT_LIMIT_SWITCH_STATUSES: { PLCLimitSwitchStatusEnum StatusAzimuthUnderRotation = PLCLimitSwitchStatusEnum.WITHIN_SAFE_LIMITS; PLCLimitSwitchStatusEnum StatusAzimuthOverRotation = PLCLimitSwitchStatusEnum.WITHIN_SAFE_LIMITS; PLCLimitSwitchStatusEnum StatusElevationUnderRotation = PLCLimitSwitchStatusEnum.WITHIN_SAFE_LIMITS; PLCLimitSwitchStatusEnum StatusElevationOverRotation = PLCLimitSwitchStatusEnum.WITHIN_SAFE_LIMITS; int PacketSum = PLCLimitSwitchStatusConversionHelper.ConvertToByte(StatusElevationOverRotation) + (PLCLimitSwitchStatusConversionHelper.ConvertToByte(StatusElevationUnderRotation) * 0x4) + (PLCLimitSwitchStatusConversionHelper.ConvertToByte(StatusAzimuthOverRotation) * 0x10) + (PLCLimitSwitchStatusConversionHelper.ConvertToByte(StatusAzimuthUnderRotation) * 0x40) ; FinalResponseContainer[3] = (byte)PacketSum; FinalResponseContainer[2] = 0x1; break; } case PLCCommandAndQueryTypeEnum.GET_CURRENT_SAFETY_INTERLOCK_STATUS: { FinalResponseContainer[3] = PLCSafetyInterlockStatusConversionHelper.ConvertToByte(PLCSafetyInterlockStatusEnum.LOCKED); FinalResponseContainer[2] = 0x1; break; } default: { throw new ArgumentException("Invalid PLCCommandAndQueryTypeEnum value seen while expecting a response: " + CommandQueryTypeEnum.ToString()); } } } else if (ExpectedResponseStatusEnum == PLCCommandResponseExpectationEnum.MINOR_RESPONSE) { FinalResponseContainer = new byte[] { 0x3, 0x0, 0x0 }; switch (CommandQueryTypeEnum) { case PLCCommandAndQueryTypeEnum.CANCEL_ACTIVE_OBJECTIVE_AZEL_POSITION: case PLCCommandAndQueryTypeEnum.SHUTDOWN: case PLCCommandAndQueryTypeEnum.CALIBRATE: { FinalResponseContainer[2] = 0x1; break; } case PLCCommandAndQueryTypeEnum.SET_OBJECTIVE_AZEL_POSITION: { double NextAZ, NextEL; try { NextAZ = BitConverter.ToDouble(query, 3); NextEL = BitConverter.ToDouble(query, 11); } catch (Exception e) { if ((e is ArgumentException) || (e is ArgumentNullException) || (e is ArgumentOutOfRangeException)) { // This error code means that the data could not be converted into a double-precision floating point FinalResponseContainer[2] = 0x2; break; } else { // Unexpected exception throw e; } } if ((NextAZ < 0) || (NextAZ > 360)) { // This error code means that the objective azimuth position is invalid FinalResponseContainer[2] = 0x3; break; } if ((NextEL < 0) || (NextEL > 90)) { // This error code means that the objective elevation position is invalid FinalResponseContainer[2] = 0x4; break; } // Otherwise, this is valid // TODO: Perform task(s) to set objective orientation! FinalResponseContainer[2] = 0x1; break; } default: { throw new ArgumentException("Invalid PLCCommandAndQueryTypeEnum value seen while NOT expecting a response: " + CommandQueryTypeEnum.ToString()); } } } else { throw new ArgumentException("Invalid PLCCommandResponseExpectationEnum value seen while processing client request in ScaleModelPLCDriver: " + ExpectedResponseStatusEnum.ToString()); } return(AttemptToWriteDataToServer(ActiveClientStream, FinalResponseContainer)); }
public bool ProcessRequest(NetworkStream ActiveClientStream, byte[] query) { int ExpectedSize = query[0] + (256 * query[1]); if (query.Length != ExpectedSize) { throw new ArgumentException( "TestPLCDriverController read a package specifying a size [" + ExpectedSize.ToString() + "], but the actual size was different [" + query.Length + "]." ); } byte CommandQueryTypeAndExpectedResponseStatus = query[2]; byte CommandQueryTypeByte = (byte)(CommandQueryTypeAndExpectedResponseStatus & 0x3F); byte ExpectedResponseStatusByte = (byte)(CommandQueryTypeAndExpectedResponseStatus >> 6); PLCCommandAndQueryTypeEnum CommandQueryTypeEnum = PLCCommandAndQueryTypeConversionHelper.GetFromByte(CommandQueryTypeByte); PLCCommandResponseExpectationEnum ExpectedResponseStatusEnum = PLCCommandResponseExpectationConversionHelper.GetFromByte(ExpectedResponseStatusByte); byte[] FinalResponseContainer; if (ExpectedResponseStatusEnum == PLCCommandResponseExpectationEnum.FULL_RESPONSE) { FinalResponseContainer = new byte[] { 0x13, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }; switch (CommandQueryTypeEnum) { case PLCCommandAndQueryTypeEnum.TEST_CONNECTION: { FinalResponseContainer[3] = 0x1; FinalResponseContainer[2] = 0x1; break; } case PLCCommandAndQueryTypeEnum.GET_CURRENT_AZEL_POSITIONS: { Array.Copy(BitConverter.GetBytes(CurrentOrientation.Azimuth), 0, FinalResponseContainer, 3, 8); Array.Copy(BitConverter.GetBytes(CurrentOrientation.Elevation), 0, FinalResponseContainer, 11, 8); FinalResponseContainer[2] = 0x1; break; } case PLCCommandAndQueryTypeEnum.GET_CURRENT_LIMIT_SWITCH_STATUSES: { double CurrentAZ = CurrentOrientation.Azimuth; double CurrentEL = CurrentOrientation.Elevation; double ThresholdAZ = MiscellaneousHardwareConstants.LIMIT_SWITCH_AZ_THRESHOLD_DEGREES; double ThresholdEL = MiscellaneousHardwareConstants.LIMIT_SWITCH_EL_THRESHOLD_DEGREES; // Subtracting out those 2 degrees is because of our actual rotational limits of (-2 : 362) and (-2 : 92) degrees in azimuth and elevation respectively PLCLimitSwitchStatusEnum StatusAzimuthUnderRotation = (CurrentAZ < (ThresholdAZ - 2.0)) ? PLCLimitSwitchStatusEnum.WITHIN_WARNING_LIMITS : PLCLimitSwitchStatusEnum.WITHIN_SAFE_LIMITS; PLCLimitSwitchStatusEnum StatusAzimuthOverRotation = (CurrentAZ > (360 + ThresholdAZ - 2.0)) ? PLCLimitSwitchStatusEnum.WITHIN_WARNING_LIMITS : PLCLimitSwitchStatusEnum.WITHIN_SAFE_LIMITS; PLCLimitSwitchStatusEnum StatusElevationUnderRotation = (CurrentEL < (ThresholdEL - 2.0)) ? PLCLimitSwitchStatusEnum.WITHIN_WARNING_LIMITS : PLCLimitSwitchStatusEnum.WITHIN_SAFE_LIMITS; PLCLimitSwitchStatusEnum StatusElevationOverRotation = (CurrentEL > (90 + ThresholdEL - 2.0)) ? PLCLimitSwitchStatusEnum.WITHIN_WARNING_LIMITS : PLCLimitSwitchStatusEnum.WITHIN_SAFE_LIMITS; int PacketSum = PLCLimitSwitchStatusConversionHelper.ConvertToByte(StatusElevationOverRotation) + (PLCLimitSwitchStatusConversionHelper.ConvertToByte(StatusElevationUnderRotation) * 0x4) + (PLCLimitSwitchStatusConversionHelper.ConvertToByte(StatusAzimuthOverRotation) * 0x10) + (PLCLimitSwitchStatusConversionHelper.ConvertToByte(StatusAzimuthUnderRotation) * 0x40) ; FinalResponseContainer[3] = (byte)PacketSum; FinalResponseContainer[2] = 0x1; break; } case PLCCommandAndQueryTypeEnum.GET_CURRENT_SAFETY_INTERLOCK_STATUS: { FinalResponseContainer[3] = PLCSafetyInterlockStatusConversionHelper.ConvertToByte(PLCSafetyInterlockStatusEnum.LOCKED); FinalResponseContainer[2] = 0x1; break; } default: { throw new ArgumentException("Invalid PLCCommandAndQueryTypeEnum value seen while expecting a response: " + CommandQueryTypeEnum.ToString()); } } } else if (ExpectedResponseStatusEnum == PLCCommandResponseExpectationEnum.MINOR_RESPONSE) { FinalResponseContainer = new byte[] { 0x3, 0x0, 0x0 }; switch (CommandQueryTypeEnum) { case PLCCommandAndQueryTypeEnum.CANCEL_ACTIVE_OBJECTIVE_AZEL_POSITION: case PLCCommandAndQueryTypeEnum.SHUTDOWN: case PLCCommandAndQueryTypeEnum.CALIBRATE: { FinalResponseContainer[2] = 0x1; break; } case PLCCommandAndQueryTypeEnum.SET_OBJECTIVE_AZEL_POSITION: { double NextAZ, NextEL; try { NextAZ = BitConverter.ToDouble(query, 3); NextEL = BitConverter.ToDouble(query, 11); } catch (Exception e) { if ((e is ArgumentException) || (e is ArgumentNullException) || (e is ArgumentOutOfRangeException)) { // This error code means that the data could not be converted into a double-precision floating point FinalResponseContainer[2] = 0x2; break; } else { // Unexpected exception throw e; } } if ((NextAZ < 0) || (NextAZ > 360)) { // This error code means that the objective azimuth position is invalid FinalResponseContainer[2] = 0x3; break; } if ((NextEL < 0) || (NextEL > 90)) { // This error code means that the objective elevation position is invalid FinalResponseContainer[2] = 0x4; break; } // Otherwise, this is valid CurrentOrientation = new Orientation(NextAZ, NextEL); logger.Info("[TestPLCDriver] Setting current orientation to {" + CurrentOrientation.Azimuth.ToString() + ", " + CurrentOrientation.Elevation.ToString() + "}"); FinalResponseContainer[2] = 0x1; break; } default: { throw new ArgumentException("Invalid PLCCommandAndQueryTypeEnum value seen while NOT expecting a response: " + CommandQueryTypeEnum.ToString()); } } } else { throw new ArgumentException("Invalid PLCCommandResponseExpectationEnum value seen while processing client request in ScaleModelPLCDriver: " + ExpectedResponseStatusEnum.ToString()); } return(AttemptToWriteDataToServer(ActiveClientStream, FinalResponseContainer)); }