1pub use super::camera_telescope_shared::GuideDirection;
2
3use super::Device;
4use super::time_repr::{Iso8601, TimeRepr};
5#[cfg(feature = "client")]
6use crate::api::macros::ConvertConvenienceProp;
7use crate::{ASCOMError, ASCOMResult};
8use macro_rules_attribute::apply;
9use num_enum::{IntoPrimitive, TryFromPrimitive};
10use serde::{Deserialize, Serialize};
11use serde_repr::{Deserialize_repr, Serialize_repr};
12use std::ops::RangeInclusive;
13use std::time::SystemTime;
14
15#[apply(rpc_trait)]
17pub trait Telescope: Device + Send + Sync {
18 #[http("alignmentmode", method = Get)]
20 async fn alignment_mode(&self) -> ASCOMResult<AlignmentMode> {
21 Err(ASCOMError::NOT_IMPLEMENTED)
22 }
23
24 #[http("altitude", method = Get, device_state = Altitude)]
26 async fn altitude(&self) -> ASCOMResult<f64> {
27 Err(ASCOMError::NOT_IMPLEMENTED)
28 }
29
30 #[http("aperturearea", method = Get)]
32 async fn aperture_area(&self) -> ASCOMResult<f64> {
33 Err(ASCOMError::NOT_IMPLEMENTED)
34 }
35
36 #[http("aperturediameter", method = Get)]
38 async fn aperture_diameter(&self) -> ASCOMResult<f64> {
39 Err(ASCOMError::NOT_IMPLEMENTED)
40 }
41
42 #[http("athome", method = Get, device_state = AtHome)]
46 async fn at_home(&self) -> ASCOMResult<bool>;
47
48 #[http("atpark", method = Get, device_state = AtPark)]
52 async fn at_park(&self) -> ASCOMResult<bool>;
53
54 #[http("azimuth", method = Get, device_state = Azimuth)]
56 async fn azimuth(&self) -> ASCOMResult<f64> {
57 Err(ASCOMError::NOT_IMPLEMENTED)
58 }
59
60 #[http("canfindhome", method = Get)]
62 async fn can_find_home(&self) -> ASCOMResult<bool> {
63 Ok(false)
64 }
65
66 #[http("canpark", method = Get)]
68 async fn can_park(&self) -> ASCOMResult<bool> {
69 Ok(false)
70 }
71
72 #[http("canpulseguide", method = Get)]
74 async fn can_pulse_guide(&self) -> ASCOMResult<bool> {
75 Ok(false)
76 }
77
78 #[http("cansetdeclinationrate", method = Get)]
80 async fn can_set_declination_rate(&self) -> ASCOMResult<bool> {
81 Ok(false)
82 }
83
84 #[http("cansetguiderates", method = Get)]
86 async fn can_set_guide_rates(&self) -> ASCOMResult<bool> {
87 Ok(false)
88 }
89
90 #[http("cansetpark", method = Get)]
92 async fn can_set_park(&self) -> ASCOMResult<bool> {
93 Ok(false)
94 }
95
96 #[http("cansetpierside", method = Get)]
98 async fn can_set_pier_side(&self) -> ASCOMResult<bool> {
99 Ok(false)
100 }
101
102 #[http("cansetrightascensionrate", method = Get)]
104 async fn can_set_right_ascension_rate(&self) -> ASCOMResult<bool> {
105 Ok(false)
106 }
107
108 #[http("cansettracking", method = Get)]
110 async fn can_set_tracking(&self) -> ASCOMResult<bool> {
111 Ok(false)
112 }
113
114 #[http("canslew", method = Get)]
116 async fn can_slew(&self) -> ASCOMResult<bool> {
117 Ok(false)
118 }
119
120 #[http("canslewaltaz", method = Get)]
122 async fn can_slew_alt_az(&self) -> ASCOMResult<bool> {
123 Ok(false)
124 }
125
126 #[http("canslewaltazasync", method = Get)]
128 async fn can_slew_alt_az_async(&self) -> ASCOMResult<bool> {
129 Ok(false)
130 }
131
132 #[http("canslewasync", method = Get)]
134 async fn can_slew_async(&self) -> ASCOMResult<bool> {
135 Ok(false)
136 }
137
138 #[http("cansync", method = Get)]
140 async fn can_sync(&self) -> ASCOMResult<bool> {
141 Ok(false)
142 }
143
144 #[http("cansyncaltaz", method = Get)]
146 async fn can_sync_alt_az(&self) -> ASCOMResult<bool> {
147 Ok(false)
148 }
149
150 #[http("canunpark", method = Get)]
152 async fn can_unpark(&self) -> ASCOMResult<bool> {
153 Ok(false)
154 }
155
156 #[http("declination", method = Get, device_state = Declination)]
160 async fn declination(&self) -> ASCOMResult<f64> {
161 Err(ASCOMError::NOT_IMPLEMENTED)
162 }
163
164 #[http("declinationrate", method = Get)]
168 async fn declination_rate(&self) -> ASCOMResult<f64>;
169
170 #[http("declinationrate", method = Put)]
174 async fn set_declination_rate(
175 &self,
176
177 #[http("DeclinationRate")] declination_rate: f64,
178 ) -> ASCOMResult<()> {
179 Err(ASCOMError::NOT_IMPLEMENTED)
180 }
181
182 #[http("doesrefraction", method = Get)]
184 async fn does_refraction(&self) -> ASCOMResult<bool> {
185 Err(ASCOMError::NOT_IMPLEMENTED)
186 }
187
188 #[http("doesrefraction", method = Put)]
190 async fn set_does_refraction(
191 &self,
192
193 #[http("DoesRefraction")] does_refraction: bool,
194 ) -> ASCOMResult<()> {
195 Err(ASCOMError::NOT_IMPLEMENTED)
196 }
197
198 #[http("equatorialsystem", method = Get)]
200 async fn equatorial_system(&self) -> ASCOMResult<EquatorialCoordinateType>;
201
202 #[http("focallength", method = Get)]
204 async fn focal_length(&self) -> ASCOMResult<f64> {
205 Err(ASCOMError::NOT_IMPLEMENTED)
206 }
207
208 #[http("guideratedeclination", method = Get)]
210 async fn guide_rate_declination(&self) -> ASCOMResult<f64> {
211 Err(ASCOMError::NOT_IMPLEMENTED)
212 }
213
214 #[http("guideratedeclination", method = Put)]
216 async fn set_guide_rate_declination(
217 &self,
218
219 #[http("GuideRateDeclination")] guide_rate_declination: f64,
220 ) -> ASCOMResult<()> {
221 Err(ASCOMError::NOT_IMPLEMENTED)
222 }
223
224 #[http("guideraterightascension", method = Get)]
226 async fn guide_rate_right_ascension(&self) -> ASCOMResult<f64> {
227 Err(ASCOMError::NOT_IMPLEMENTED)
228 }
229
230 #[http("guideraterightascension", method = Put)]
232 async fn set_guide_rate_right_ascension(
233 &self,
234
235 #[http("GuideRateRightAscension")] guide_rate_right_ascension: f64,
236 ) -> ASCOMResult<()> {
237 Err(ASCOMError::NOT_IMPLEMENTED)
238 }
239
240 #[http("ispulseguiding", method = Get, device_state = IsPulseGuiding)]
242 async fn is_pulse_guiding(&self) -> ASCOMResult<bool> {
243 Err(ASCOMError::NOT_IMPLEMENTED)
244 }
245
246 #[http("rightascension", method = Get, device_state = RightAscension)]
248 async fn right_ascension(&self) -> ASCOMResult<f64>;
249
250 #[http("rightascensionrate", method = Get)]
254 async fn right_ascension_rate(&self) -> ASCOMResult<f64>;
255
256 #[http("rightascensionrate", method = Put)]
260 async fn set_right_ascension_rate(
261 &self,
262
263 #[http("RightAscensionRate")] right_ascension_rate: f64,
264 ) -> ASCOMResult<()> {
265 Err(ASCOMError::NOT_IMPLEMENTED)
266 }
267
268 #[http("sideofpier", method = Get, device_state = SideOfPier)]
270 async fn side_of_pier(&self) -> ASCOMResult<PierSide> {
271 Err(ASCOMError::NOT_IMPLEMENTED)
272 }
273
274 #[http("sideofpier", method = Put)]
276 async fn set_side_of_pier(
277 &self,
278 #[http("SideOfPier")] side_of_pier: PierSide,
279 ) -> ASCOMResult<()> {
280 Err(ASCOMError::NOT_IMPLEMENTED)
281 }
282
283 #[http("siderealtime", method = Get)]
285 async fn sidereal_time(&self) -> ASCOMResult<f64>;
286
287 #[http("siteelevation", method = Get)]
289 async fn site_elevation(&self) -> ASCOMResult<f64> {
290 Err(ASCOMError::NOT_IMPLEMENTED)
291 }
292
293 #[http("siteelevation", method = Put)]
295 async fn set_site_elevation(
296 &self,
297
298 #[http("SiteElevation")] site_elevation: f64,
299 ) -> ASCOMResult<()> {
300 Err(ASCOMError::NOT_IMPLEMENTED)
301 }
302
303 #[http("sitelatitude", method = Get)]
305 async fn site_latitude(&self) -> ASCOMResult<f64> {
306 Err(ASCOMError::NOT_IMPLEMENTED)
307 }
308
309 #[http("sitelatitude", method = Put)]
311 async fn set_site_latitude(
312 &self,
313 #[http("SiteLatitude")] site_latitude: f64,
314 ) -> ASCOMResult<()> {
315 Err(ASCOMError::NOT_IMPLEMENTED)
316 }
317
318 #[http("sitelongitude", method = Get)]
320 async fn site_longitude(&self) -> ASCOMResult<f64> {
321 Err(ASCOMError::NOT_IMPLEMENTED)
322 }
323
324 #[http("sitelongitude", method = Put)]
326 async fn set_site_longitude(
327 &self,
328
329 #[http("SiteLongitude")] site_longitude: f64,
330 ) -> ASCOMResult<()> {
331 Err(ASCOMError::NOT_IMPLEMENTED)
332 }
333
334 #[http("slewing", method = Get, device_state = Slewing)]
336 async fn slewing(&self) -> ASCOMResult<bool> {
337 Err(ASCOMError::NOT_IMPLEMENTED)
338 }
339
340 #[http("slewsettletime", method = Get)]
342 async fn slew_settle_time(&self) -> ASCOMResult<i32> {
343 Err(ASCOMError::NOT_IMPLEMENTED)
344 }
345
346 #[http("slewsettletime", method = Put)]
348 async fn set_slew_settle_time(
349 &self,
350
351 #[http("SlewSettleTime")] slew_settle_time: i32,
352 ) -> ASCOMResult<()> {
353 Err(ASCOMError::NOT_IMPLEMENTED)
354 }
355
356 #[http("targetdeclination", method = Get)]
358 async fn target_declination(&self) -> ASCOMResult<f64> {
359 Err(ASCOMError::NOT_IMPLEMENTED)
360 }
361
362 #[http("targetdeclination", method = Put)]
364 async fn set_target_declination(
365 &self,
366
367 #[http("TargetDeclination")] target_declination: f64,
368 ) -> ASCOMResult<()> {
369 Err(ASCOMError::NOT_IMPLEMENTED)
370 }
371
372 #[http("targetrightascension", method = Get)]
374 async fn target_right_ascension(&self) -> ASCOMResult<f64> {
375 Err(ASCOMError::NOT_IMPLEMENTED)
376 }
377
378 #[http("targetrightascension", method = Put)]
380 async fn set_target_right_ascension(
381 &self,
382
383 #[http("TargetRightAscension")] target_right_ascension: f64,
384 ) -> ASCOMResult<()> {
385 Err(ASCOMError::NOT_IMPLEMENTED)
386 }
387
388 #[http("tracking", method = Get, device_state = Tracking)]
390 async fn tracking(&self) -> ASCOMResult<bool>;
391
392 #[http("tracking", method = Put)]
394 async fn set_tracking(&self, #[http("Tracking")] tracking: bool) -> ASCOMResult<()> {
395 Err(ASCOMError::NOT_IMPLEMENTED)
396 }
397
398 #[http("trackingrate", method = Get)]
400 async fn tracking_rate(&self) -> ASCOMResult<DriveRate>;
401
402 #[http("trackingrate", method = Put)]
404 async fn set_tracking_rate(
405 &self,
406
407 #[http("TrackingRate")] tracking_rate: DriveRate,
408 ) -> ASCOMResult<()> {
409 Err(ASCOMError::NOT_IMPLEMENTED)
410 }
411
412 #[http("trackingrates", method = Get)]
414 async fn tracking_rates(&self) -> ASCOMResult<Vec<DriveRate>> {
415 Err(ASCOMError::NOT_IMPLEMENTED)
416 }
417
418 #[http("utcdate", method = Get, via = TimeRepr<Iso8601>)]
420 async fn utc_date(&self) -> ASCOMResult<SystemTime>;
421
422 #[http("utcdate", method = Put)]
424 async fn set_utc_date(
425 &self,
426
427 #[http("UTCDate", via = TimeRepr<Iso8601>)] utc_date: SystemTime,
428 ) -> ASCOMResult<()> {
429 Err(ASCOMError::NOT_IMPLEMENTED)
430 }
431
432 #[http("abortslew", method = Put)]
434 async fn abort_slew(&self) -> ASCOMResult<()> {
435 Err(ASCOMError::NOT_IMPLEMENTED)
436 }
437
438 #[http("axisrates", method = Get, via = AxisRates)]
440 async fn axis_rates(
441 &self,
442 #[http("Axis")] axis: TelescopeAxis,
443 ) -> ASCOMResult<Vec<RangeInclusive<f64>>>;
444
445 #[http("canmoveaxis", method = Get)]
447 async fn can_move_axis(&self, #[http("Axis")] axis: TelescopeAxis) -> ASCOMResult<bool> {
448 Ok(false)
449 }
450
451 #[http("destinationsideofpier", method = Get)]
453 async fn destination_side_of_pier(
454 &self,
455
456 #[http("RightAscension")] right_ascension: f64,
457
458 #[http("Declination")] declination: f64,
459 ) -> ASCOMResult<PierSide> {
460 Err(ASCOMError::NOT_IMPLEMENTED)
461 }
462
463 #[http("findhome", method = Put)]
465 async fn find_home(&self) -> ASCOMResult<()> {
466 Err(ASCOMError::NOT_IMPLEMENTED)
467 }
468
469 #[http("moveaxis", method = Put)]
471 async fn move_axis(
472 &self,
473
474 #[http("Axis")] axis: TelescopeAxis,
475
476 #[http("Rate")] rate: f64,
477 ) -> ASCOMResult<()> {
478 Err(ASCOMError::NOT_IMPLEMENTED)
479 }
480
481 #[http("park", method = Put)]
483 async fn park(&self) -> ASCOMResult<()> {
484 Err(ASCOMError::NOT_IMPLEMENTED)
485 }
486
487 #[http("pulseguide", method = Put)]
489 async fn pulse_guide(
490 &self,
491
492 #[http("Direction")] direction: GuideDirection,
493
494 #[http("Duration")] duration: i32,
495 ) -> ASCOMResult<()> {
496 Err(ASCOMError::NOT_IMPLEMENTED)
497 }
498
499 #[http("setpark", method = Put)]
501 async fn set_park(&self) -> ASCOMResult<()> {
502 Err(ASCOMError::NOT_IMPLEMENTED)
503 }
504
505 #[http("slewtoaltaz", method = Put)]
507 async fn slew_to_alt_az(
508 &self,
509
510 #[http("Azimuth")] azimuth: f64,
511
512 #[http("Altitude")] altitude: f64,
513 ) -> ASCOMResult<()> {
514 Err(ASCOMError::NOT_IMPLEMENTED)
515 }
516
517 #[http("slewtoaltazasync", method = Put)]
521 async fn slew_to_alt_az_async(
522 &self,
523
524 #[http("Azimuth")] azimuth: f64,
525
526 #[http("Altitude")] altitude: f64,
527 ) -> ASCOMResult<()> {
528 Err(ASCOMError::NOT_IMPLEMENTED)
529 }
530
531 #[http("slewtocoordinates", method = Put)]
533 async fn slew_to_coordinates(
534 &self,
535
536 #[http("RightAscension")] right_ascension: f64,
537
538 #[http("Declination")] declination: f64,
539 ) -> ASCOMResult<()> {
540 Err(ASCOMError::NOT_IMPLEMENTED)
541 }
542
543 #[http("slewtocoordinatesasync", method = Put)]
547 async fn slew_to_coordinates_async(
548 &self,
549
550 #[http("RightAscension")] right_ascension: f64,
551
552 #[http("Declination")] declination: f64,
553 ) -> ASCOMResult<()> {
554 Err(ASCOMError::NOT_IMPLEMENTED)
555 }
556
557 #[http("slewtotarget", method = Put)]
561 async fn slew_to_target(&self) -> ASCOMResult<()> {
562 Err(ASCOMError::NOT_IMPLEMENTED)
563 }
564
565 #[http("slewtotargetasync", method = Put)]
569 async fn slew_to_target_async(&self) -> ASCOMResult<()> {
570 Err(ASCOMError::NOT_IMPLEMENTED)
571 }
572
573 #[http("synctoaltaz", method = Put)]
575 async fn sync_to_alt_az(
576 &self,
577
578 #[http("Azimuth")] azimuth: f64,
579
580 #[http("Altitude")] altitude: f64,
581 ) -> ASCOMResult<()> {
582 Err(ASCOMError::NOT_IMPLEMENTED)
583 }
584
585 #[http("synctocoordinates", method = Put)]
587 async fn sync_to_coordinates(
588 &self,
589
590 #[http("RightAscension")] right_ascension: f64,
591
592 #[http("Declination")] declination: f64,
593 ) -> ASCOMResult<()> {
594 Err(ASCOMError::NOT_IMPLEMENTED)
595 }
596
597 #[http("synctotarget", method = Put)]
599 async fn sync_to_target(&self) -> ASCOMResult<()> {
600 Err(ASCOMError::NOT_IMPLEMENTED)
601 }
602
603 #[http("unpark", method = Put)]
605 async fn unpark(&self) -> ASCOMResult<()> {
606 Err(ASCOMError::NOT_IMPLEMENTED)
607 }
608
609 #[http("interfaceversion", method = Get)]
613 async fn interface_version(&self) -> ASCOMResult<i32> {
614 Ok(4_i32)
615 }
616}
617
618#[cfg(feature = "client")]
620#[derive(Debug, Clone, Copy, PartialEq)]
621pub struct SiteCoords {
622 pub latitude: f64,
624 pub longitude: f64,
626 pub elevation: f64,
628}
629
630#[cfg(feature = "client")]
631impl ConvertConvenienceProp for SiteCoords {
632 type Inner = f64;
633 type Arr = [f64; 3];
634
635 fn from_arr([latitude, longitude, elevation]: Self::Arr) -> Self {
636 Self {
637 latitude,
638 longitude,
639 elevation,
640 }
641 }
642
643 fn into_arr(self) -> Self::Arr {
644 [self.latitude, self.longitude, self.elevation]
645 }
646}
647
648#[cfg(feature = "client")]
650#[derive(Debug, Clone, Copy, PartialEq)]
651pub struct RaDec {
652 pub right_ascension: f64,
654 pub declination: f64,
656}
657
658#[cfg(feature = "client")]
659impl ConvertConvenienceProp for RaDec {
660 type Inner = f64;
661 type Arr = [f64; 2];
662
663 fn from_arr([right_ascension, declination]: Self::Arr) -> Self {
664 Self {
665 right_ascension,
666 declination,
667 }
668 }
669
670 fn into_arr(self) -> Self::Arr {
671 [self.right_ascension, self.declination]
672 }
673}
674
675convenience_props!(Telescope {
676 #[
678 set
680 ]
681 guide_rates_ra_dec(guide_rate_right_ascension, guide_rate_declination): RaDec,
682
683 ra_dec(right_ascension, declination): RaDec,
685
686 #[
688 set
690 ]
691 ra_dec_rates(right_ascension_rate, declination_rate): RaDec,
692
693 alt_az(altitude, azimuth): RaDec,
695
696 #[
698 set
700 ]
701 site_coords(site_latitude, site_longitude, site_elevation): SiteCoords,
702
703 #[
705 set
707 ]
708 target_ra_dec(target_right_ascension, target_declination): RaDec,
709});
710
711#[derive(
713 Debug,
714 PartialEq,
715 Eq,
716 Clone,
717 Copy,
718 Serialize_repr,
719 Deserialize_repr,
720 TryFromPrimitive,
721 IntoPrimitive,
722)]
723#[repr(i32)]
724pub enum AlignmentMode {
725 AltAz = 0,
727
728 Polar = 1,
730
731 GermanPolar = 2,
733}
734
735#[derive(
737 Debug,
738 PartialEq,
739 Eq,
740 Clone,
741 Copy,
742 Serialize_repr,
743 Deserialize_repr,
744 TryFromPrimitive,
745 IntoPrimitive,
746)]
747#[repr(i32)]
748pub enum EquatorialCoordinateType {
749 Other = 0,
751
752 Topocentric = 1,
754
755 J2000 = 2,
757
758 J2050 = 3,
760
761 B1950 = 4,
763}
764
765#[derive(
767 Debug,
768 PartialEq,
769 Eq,
770 Clone,
771 Copy,
772 Serialize_repr,
773 Deserialize_repr,
774 TryFromPrimitive,
775 IntoPrimitive,
776)]
777#[repr(i32)]
778pub enum PierSide {
779 East = 0,
781
782 West = 1,
784
785 Unknown = -1,
787}
788
789#[derive(
791 Debug,
792 PartialEq,
793 Eq,
794 Clone,
795 Copy,
796 Serialize_repr,
797 Deserialize_repr,
798 TryFromPrimitive,
799 IntoPrimitive,
800)]
801#[repr(i32)]
802pub enum DriveRate {
803 Sidereal = 0,
805
806 Lunar = 1,
808
809 Solar = 2,
811
812 King = 3,
814}
815
816#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
818#[serde(rename_all = "PascalCase")]
819struct AxisRate {
820 pub minimum: f64,
824
825 pub maximum: f64,
829}
830
831#[derive(Serialize, Deserialize)]
832#[serde(transparent)]
833pub(super) struct AxisRates(Vec<AxisRate>);
834
835impl From<AxisRates> for Vec<RangeInclusive<f64>> {
836 fn from(axis_rates: AxisRates) -> Self {
837 axis_rates
838 .0
839 .into_iter()
840 .map(|axis_rate| axis_rate.minimum..=axis_rate.maximum)
841 .collect()
842 }
843}
844
845impl From<Vec<RangeInclusive<f64>>> for AxisRates {
846 fn from(ranges: Vec<RangeInclusive<f64>>) -> Self {
847 Self(
848 ranges
849 .into_iter()
850 .map(|range| {
851 let (minimum, maximum) = range.into_inner();
852 AxisRate { minimum, maximum }
853 })
854 .collect(),
855 )
856 }
857}
858
859#[derive(
861 Debug,
862 PartialEq,
863 Eq,
864 Clone,
865 Copy,
866 Serialize_repr,
867 Deserialize_repr,
868 TryFromPrimitive,
869 IntoPrimitive,
870)]
871#[repr(i32)]
872pub enum TelescopeAxis {
873 Primary = 0,
875
876 Secondary = 1,
878
879 Tertiary = 2,
881}