Device State Implementation and Requirements |
This topic contains the following sections:
Many ASCOM properties provide information about current device state and fall into two categories:
Configuration information – These are set prior to an operation commencing and stay fixed for the lifetime of an operation such as Camera.BinX and Telescope.SiteLatitude.
Operational information – These change while an operation is in progress such as Telescope.RightAscension, Focuser.Position and ObservingConditions.WindGust.
The DeviceState property will return all the device’s operational property values in a single call to reduce latency and network bandwidth. Configuration information is not included because this is either set and known by the application or can be read once at the beginning of an operation.
The DeviceState property is intended to improve ASCOM Interface support for two primary use cases:
Status reporting in client user interfaces.
Progress monitoring for processes initiated by the client.
From both the client’s and the device’s perspective, DeviceState is a “best endeavours” call. This is to ensure that the maximum amount of available data is returned by the device to the client.
A device must return all operational values that it definitively knows but can omit entries where value are unknown.
Devices must not throw exceptions / return errors when values are not known. An empty list, with no TimeStamp, must be returned if no values are known.
If you wish to report additional values to clients, beyond those defined as operational, implement an Action e.g. via Telescope.Action(string, string) and Telescope.SupportedActions, and return your items in this way rather than adding them to the DeviceState response. This is to ensure that the ``DeviceState`` call is as performant as possible for both client and device and is not burdened with information that unduly increases its size and transmission time. Conform will report non-standard StateValue items found in the DeviceState response as Issues.
Applications must expect that, from time to time, some operational state values may not be present in the device response and must implement a strategy to deal with such “missing” values.
An optional string TimeStamp property in ISO-8601 format can be included to record the time at which the state was measured, if known. The general format (in Microsoft custom date format style) is "yyyy-MM-ddTHH:mm:ss.fffffff". If required, an optional Z can be appended to designate the value as a UTC time or an optional time zone offset can be provided. E.g.
An unqualified local time e.g. 2016-03-04T17:45:31.1234567, which corresponds to 17:45:31.1234567 local time on 4th March 2016.
A local time including the UTC time and a time zone offset e.g. 2016-03-04T17:45:31.123456+05.30 for the India Standard Time zone (+5.5 hours), which corresponds to 23:15:31.1234567 local time on 4th March 2016.
A UTC time using the Z time-zone designator e.g. 2016-03-04T17:45:31.1234567Z, which corresponds to 17:45:31.1234567 UTC on 4th March 2016.
The COM and Alpaca interfaces are functionally equivalent and return an enumerable collection of IStateValue objects.
The ASCOM COM driver interface definition is:
public IstateValueCollection DeviceState { get; }
The StateValueCollection type is provided to make creating device state responses straightforward. It provides an enumerable list of IStateValue objects that can be consumed by COM, .NET Framework and .NET 5 onward clients.
Each element of the enumeration must be a COM registered class that implements the IStateValue interface and exposes the two properties below. The StateValue class is provided specifically for this purpose.
public interface IStateValue { string Name { get; } object Value { get; } }
IStateValue.Name is the name of an operational property. The name is case sensitive and must match the property name’s spelling and casing in the ASCOM interface specification.
The IStateValue.Value property has the object type so that it can accept any type including the types commonly used in ASCOM interfaces such as int16, int32, double, string and enum. This approach avoids localisation complexities when transferring numeric and bool types.
Here is an example of creating a focuser DeviceState response:
public IStateValueCollection DeviceState { get { List<IStateValue> deviceState = new List<IStateValue>(); try { deviceState.Add(new StateValue(nameof(IFocuserV4.IsMoving), IsMoving)); } catch { } try { deviceState.Add(new StateValue(nameof(IFocuserV4.Position), Position)); } catch { } try { deviceState.Add(new StateValue(nameof(IFocuserV4.Temperature), Temperature)); } catch { } try { deviceState.Add(new StateValue(DateTime.Now)); } catch { } return new StateValueCollection(deviceState); } }
The Alpaca device response uses the standard Alpaca message structure consisting of Value, ClientTransactionID, ServerTransactionID, ErrorNumber and ErrorMessage keys. The content of the Value key is a JSON array of IStateValue objects with Name and Value keys defined identically to those in the COM interface.
Here is a formatted example of a Camera DeviceState Alpaca JSON response:
{ "Value":[ {"Name":"CameraState","Value":0}, {"Name":"CCDTemperature","Value":10}, {"Name":"CoolerPower","Value":0}, {"Name":"HeatSinkTemperature","Value":10}, {"Name":"ImageReady","Value":false}, {"Name":"IsPulseGuiding","Value":false}, {"Name":"PercentCompleted","Value":0}, {"Name":"TimeStamp","Value":"2023-06-14T11:17:50.0Z"} ], "ClientTransactionID":123, "ServerTransactionID":456, "ErrorNumber":0, "ErrorMessage":"" }
Device type | Operational Properties |
---|---|
Camera | CameraState, CCDTemperature, CoolerPower, HeatSinkTemperature, ImageReady, IsPulseGuiding, PercentCompleted, TimeStamp |
CoverCalibrator | Brightness, CalibratorState, CoverState, CalibratorReady, CoverMoving, TimeStamp |
Dome | Altitude, AtHome, AtPark, Azimuth, ShutterStatus, Slewing, TimeStamp |
FilterWheel | Position, TimeStamp |
Focuser | IsMoving, Position, Temperature, TimeStamp |
ObservingConditions | CloudCover, DewPoint Humidity, Pressure, RainRate, SkyBrightness, SkyQuality, SkyTemperature, StarFWHM, Temperature, WindDirection, WindGust, WindSpeed, TimeStamp |
Rotator | IsMoving, MechanicalPosition, Position, TimeStamp |
SafetyMonitor | IsSafe, TimeStamp |
Switch | Since a single Switch device can be configured to provide many controllable switches, a standard is required to enable the controllable switch states to be returned by the Switch device. The standard is that: The controllable switch number is appended to the name of the property when constructing the DeviceState property name. For the GetSwitch property, DeviceState property names would start at GetSwitch0 and progress through GetSwitch1, GetSwitch2 etc. until reaching the last controllable switch number: MaxSwitch - 1. A similar model applies to the GetSwitchValue and StateChangeComplete properties. E.g. For a Switch device with four controllable switches, the DeviceState property names would be:
|
Telescope | Altitude, AtHome, AtPark, Azimuth, Declination, IsPulseGuiding, RightAscension. SideOfPier, SiderealTime, Slewing, Tracking, UTCDate, TimeStamp |
Video | CameraState, TimeStamp |
As a convenience for application developers, all ASCOM client toolkit devices will provide an additional property that presents the device’s DeviceState response as a class. The name of the additional property for most devices will follow the format: {DeviceType}State where {DeviceType} is Dome, Telescope etc. The Camera property will be named CameraDeviceState to avoid a conflict with the ICamera.CameraState property.
Note: Due to the variable nature of the Switch’s device state response there is no helper class for the Switch device.
The signature of these additional properties will be:
public CameraDeviceState CameraDeviceState { get; } // Camera device public {DeviceType}State {DeviceType}State { get; } // All other devices
Within the ASCOM device interfaces all operational information values are defined as value types that do not allow an “unknown” state to be represented. To address this, toolkit response classes will expose nullable value types so that clients can detect the “unknown” state in addition to the property’s actual value.
Using the telescope device AtPark property as an example, if the device returns a value for the AtPark property:
TelescopeState.AtPark.HasValue will return true.
TelescopeState.AtPark will return the value.
TelescopeState.AtPark.Value will return the value.
If the device does not return a value for the AtPark property:
TelescopeState.AtPark.HasValue will return false.
TelescopeState.AtPark will return null.
TelescopeState.AtPark.Value will throw a System.InvalidOperationException.
When a client GETs a device state property the toolkit will:
Create a response class with all property values set to null.
Call the device’s DeviceState property.
Populate the response class’s properties with the information returned by the device.
Please note that response class data is immutable. To obtain updated device state information GET a new response class instance from the toolkit’s device state property.
This is the definition of the class returned by DriverAccess’s TelescopeDeviceState property:
public class TelescopeDeviceState : ITelescopeDeviceState { public TelescopeDeviceState() { } // Other initiators omitted for clarity public double? Altitude { get; private set; } = null; public bool? AtHome { get; private set; } = null; public bool? AtPark { get; private set; } = null; public double? Azimuth { get; private set; } = null; public double? Declination { get; private set; } = null; public bool? IsPulseGuiding { get; private set; } = null; public double? RightAscension { get; private set; } = null; public PierSide? SideOfPier { get; private set; } = null; public double? SiderealTime { get; private set; } = null; public bool? Slewing { get; private set; } = null; public bool? Tracking { get; private set; } = null; public DateTime? UTCDate { get; private set; } = null; public DateTime? TimeStamp { get; private set; } = null; }