Skip to content

Commit

Permalink
POCS status store (#1264)
Browse files Browse the repository at this point in the history
* POCS status

* Store the status in the db, which sends to firestore.

* Don't store the state info permanently.

* Default all db insert_current to not storing permanently. This could be done better.

* Format.

* Fixing a number of units in the observatory status.

* Fixing a number of units in the observatory status.

* More formatting.

* Change the statue and include the next state.

* Add default directory

Tested on `PAN007`.
  • Loading branch information
wtgee authored May 12, 2024
1 parent decee14 commit 373e85f
Show file tree
Hide file tree
Showing 9 changed files with 62 additions and 47 deletions.
2 changes: 1 addition & 1 deletion src/panoptes/pocs/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ def __init__(self, config_host=None, config_port=None, *args, **kwargs):
self._config_host = config_host or os.getenv('PANOPTES_CONFIG_HOST', 'localhost')
self._config_port = config_port or os.getenv('PANOPTES_CONFIG_PORT', 6563)

log_dir = self.get_config('directories.base') + '/../logs'
log_dir = self.get_config('directories.base', default='.') + '/../logs'
cloud_logging_level = kwargs.get(
'cloud_logging_level',
self.get_config('panoptes_network.cloud_logging_level', default=None)
Expand Down
37 changes: 22 additions & 15 deletions src/panoptes/pocs/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
from panoptes.pocs.scheduler.observation.base import Observation
from panoptes.pocs.state.machine import PanStateMachine
from panoptes.pocs.utils import error
from panoptes.pocs.utils.logger import get_logger


class POCS(PanStateMachine, PanBase):
Expand Down Expand Up @@ -47,7 +46,8 @@ def __init__(
observatory,
state_machine_file=None,
simulators=None,
*args, **kwargs):
*args, **kwargs
):

# Explicitly call the base class.
PanBase.__init__(self, *args, **kwargs)
Expand Down Expand Up @@ -158,19 +158,21 @@ def should_retry(self):
return self._obs_run_retries >= 0

@property
def status(self):
status = dict()

def status(self) -> dict:
try:
status['state'] = self.state
status['system'] = {
'free_space': str(self._free_space),
status = {
'from_state': self.state,
'to_state': self.next_state,
'system': {
'free_space': str(self._free_space),
},
'observatory': self.observatory.status
}
status['observatory'] = self.observatory.status
self.db.insert_current('status', status, store_permanently=False)
return status
except Exception as e: # pragma: no cover
self.logger.warning(f"Can't get status: {e!r}")

return status
return {}

################################################################################################
# Methods
Expand Down Expand Up @@ -266,7 +268,8 @@ def reset_observing_run(self):

def observe_target(self,
observation: Optional[Observation] = None,
park_if_unsafe: bool = True):
park_if_unsafe: bool = True
):
"""Observe something! 🔭🌠
Note: This is a long-running blocking method.
Expand Down Expand Up @@ -375,7 +378,7 @@ def is_safe(self, no_warning=False, horizon='observe', ignore=None, park_if_not_
safe = all([v for k, v in is_safe_values.items() if k not in ignore])

# Insert safety reading
self.db.insert_current('safety', is_safe_values)
self.db.insert_current('safety', is_safe_values, store_permanently=False)

if not safe:
if no_warning is False:
Expand Down Expand Up @@ -465,8 +468,12 @@ def is_weather_safe(self, stale=180):

return is_safe

def has_free_space(self, directory=None, required_space=0.25 * u.gigabyte,
low_space_percent=1.5):
def has_free_space(
self,
directory=None,
required_space=0.25 * u.gigabyte,
low_space_percent=1.5
):
"""Does hard drive have disk space (>= 0.5 GB).
Args:
Expand Down
12 changes: 6 additions & 6 deletions src/panoptes/pocs/mount/ioptron/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -303,22 +303,22 @@ def _update_status(self):
status_dict = status_match.groupdict()

self._state = MountState(int(status_dict['state']))
status['state'] = self.state
status['state'] = self.state.name
status['parked_software'] = self.is_parked

coords_unit = getattr(u, self._location_units)
status['longitude'] = Longitude((float(status_dict['longitude']) * coords_unit).to(u.degree))
# Longitude adds +90° to avoid negative numbers, so subtract for original.
status['latitude'] = Latitude((float(status_dict['latitude']) * coords_unit).to(u.degree) - (90 * u.degree))

status['gps'] = MountGPS(int(status_dict['gps']))
status['tracking'] = MountTrackingState(int(status_dict['tracking']))
status['gps'] = MountGPS(int(status_dict['gps'])).name
status['tracking'] = MountTrackingState(int(status_dict['tracking'])).name

self._movement_speed = MountMovementSpeed(int(status_dict['movement_speed']))
status['movement_speed'] = self._movement_speed
status['movement_speed'] = self._movement_speed.name

status['time_source'] = MountTimeSource(int(status_dict['time_source']))
status['hemisphere'] = MountHemisphere(int(status_dict['hemisphere']))
status['time_source'] = MountTimeSource(int(status_dict['time_source'])).name
status['hemisphere'] = MountHemisphere(int(status_dict['hemisphere'])).name

self._at_mount_park = self.state == MountState.PARKED
self._is_home = self.state == MountState.AT_HOME
Expand Down
10 changes: 6 additions & 4 deletions src/panoptes/pocs/mount/mount.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
from astropy import units as u
from astropy.coordinates import EarthLocation
from astropy.coordinates import SkyCoord
from panoptes.utils.utils import get_quantity_value

from panoptes.pocs.base import PanBase
from panoptes.utils.serializers import from_yaml
from panoptes.utils.time import current_time
Expand Down Expand Up @@ -125,13 +127,13 @@ def status(self):

current_coord = self.get_current_coordinates()
if current_coord is not None:
status['current_ra'] = current_coord.ra
status['current_dec'] = current_coord.dec
status['current_ra'] = get_quantity_value(current_coord.ra, unit='degree')
status['current_dec'] = get_quantity_value(current_coord.dec, unit='degree')

if self.has_target:
target_coord = self.get_target_coordinates()
status['mount_target_ra'] = target_coord.ra
status['mount_target_dec'] = target_coord.dec
status['mount_target_ra'] = get_quantity_value(target_coord.ra, unit='degree')
status['mount_target_dec'] = get_quantity_value(target_coord.dec, unit='degree')
except Exception as e:
self.logger.debug(f'Problem getting mount status: {e!r}')

Expand Down
22 changes: 12 additions & 10 deletions src/panoptes/pocs/observatory.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
import os
from collections import OrderedDict
from contextlib import suppress
from datetime import datetime
from multiprocessing import Process
from pathlib import Path
from typing import Dict, Optional

import numpy as np
from astropy import units as u
from astropy.coordinates import get_body
from astropy.io.fits import setval
from panoptes.utils import error
from panoptes.utils import images as img_utils
from panoptes.utils.images import fits as fits_utils
from panoptes.utils.time import current_time, CountdownTimer, flatten_time
from panoptes.utils.utils import get_quantity_value

import panoptes.pocs.camera.fli
from panoptes.pocs.base import PanBase
Expand Down Expand Up @@ -290,11 +291,13 @@ def status(self):
if self.mount and self.mount.is_initialized:
status['mount'] = self.mount.status
current_coords = self.mount.get_current_coordinates()
status['mount']['current_ha'] = self.observer.target_hour_angle(now, current_coords)
status['mount']['current_ha'] = get_quantity_value(
self.observer.target_hour_angle(now, current_coords), unit='degree'
)
if self.mount.has_target:
target_coords = self.mount.get_target_coordinates()
target_ha = self.observer.target_hour_angle(now, target_coords)
status['mount']['mount_target_ha'] = target_ha
status['mount']['mount_target_ha'] = get_quantity_value(target_ha, unit='degree')
except Exception as e: # pragma: no cover
self.logger.warning(f"Can't get mount status: {e!r}")

Expand All @@ -314,17 +317,16 @@ def status(self):

try:
status['observer'] = {
'siderealtime': str(self.sidereal_time),
'siderealtime': get_quantity_value(self.sidereal_time, unit='degree'),
'utctime': now,
'localtime': datetime.now(),
'local_evening_astro_time': self._evening_astro_time,
'local_morning_astro_time': self._morning_astro_time,
'local_sun_set_time': self._local_sunset,
'local_sun_rise_time': self._local_sunrise,
'local_sun_position': self._local_sun_pos,
'local_moon_alt': self.observer.moon_altaz(now).alt,
'local_sun_position': get_quantity_value(self._local_sun_pos, unit='degree'),
'local_moon_alt': get_quantity_value(self.observer.moon_altaz(now).alt, unit='degree'),
'local_moon_illumination': self.observer.moon_illumination(now),
'local_moon_phase': self.observer.moon_phase(now),
'local_moon_phase': get_quantity_value(self.observer.moon_phase(now)) / np.pi,
}

except Exception as e: # pragma: no cover
Expand Down Expand Up @@ -501,7 +503,7 @@ def process_observation(
):
self.logger.debug(f"Adding current observation to db: {image_id}")
metadata['status'] = 'complete'
self.db.insert_current('images', metadata)
self.db.insert_current('images', metadata, store_permanently=False)

if make_pretty_images or self.get_config(
'observations.make_pretty_images',
Expand Down Expand Up @@ -575,7 +577,7 @@ def analyze_recent(self):
'd_dec': self.current_offset_info.delta_dec.value,
'magnitude': self.current_offset_info.magnitude.value,
'unit': 'arcsec',
}
}, store_permanently=False
)

except error.SolveError:
Expand Down
2 changes: 1 addition & 1 deletion src/panoptes/pocs/sensor/power.py
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,7 @@ def record(self, collection_name: str = None):
recent_values = self.readings

collection_name = collection_name or self.arduino_board_name
self.db.insert_current(collection_name, recent_values)
self.db.insert_current(collection_name, recent_values, store_permanently=False)

return recent_values

Expand Down
4 changes: 2 additions & 2 deletions src/panoptes/pocs/sensor/remote.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,11 +55,11 @@ def capture(self, store_result: bool = True) -> dict:
sensor_data['date'] = current_time(flatten=True)

if store_result and len(sensor_data) > 0:
self.db.insert_current(self.sensor_name, sensor_data)
self.db.insert_current(self.sensor_name, sensor_data, store_permanently=False)

# Make a separate power entry
if 'power' in sensor_data:
self.db.insert_current('power', sensor_data['power'])
self.db.insert_current('power', sensor_data['power'], store_permanently=False)

self.logger.debug(f'Remote data: {sensor_data}')

Expand Down
2 changes: 1 addition & 1 deletion src/panoptes/pocs/sensor/weather.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ def record(self):
"""Record the rolling mean of the power readings in the database."""
recent_values = self.weather_station.get_reading()

self.db.insert_current(self.collection_name, recent_values)
self.db.insert_current(self.collection_name, recent_values, store_permanently=False)

return recent_values

Expand Down
18 changes: 11 additions & 7 deletions src/panoptes/pocs/state/machine.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
import os
from contextlib import suppress
from pathlib import Path

from transitions.extensions.states import Tags as MachineState
from transitions import Machine
from panoptes.utils import error
from panoptes.utils.utils import listify
from panoptes.utils.config.client import get_config
from panoptes.utils.library import load_module
from panoptes.utils.serializers import from_yaml
from panoptes.utils.config.client import get_config
from panoptes.utils.utils import listify
from transitions import Machine
from transitions.extensions.states import Tags as MachineState


class PanStateMachine(Machine):
Expand Down Expand Up @@ -85,7 +84,8 @@ def next_state(self, value):
################################################################################################

def run(self, exit_when_done=False, run_once=False, park_when_done=True,
initial_next_state='ready'):
initial_next_state='ready'
):
"""Runs the state machine loop.
This runs the state machine in a loop. Setting the machine property
Expand Down Expand Up @@ -218,7 +218,11 @@ def goto_next_state(self):
state_changed = transition_method()
if state_changed:
self.logger.success(f'Finished with {self.state} state')
self.db.insert_current('state', {"source": self.state, "dest": self.next_state})
self.db.insert_current(
'state',
{"source": self.state, "dest": self.next_state},
store_permanently=False
)

return state_changed

Expand Down

0 comments on commit 373e85f

Please sign in to comment.