Loading Common/Interfaces/AntennaInterface/idl/Supervisor.idl +14 −8 Original line number Diff line number Diff line Loading @@ -15,7 +15,6 @@ module Antenna { struct SupervisorDataBlock { ACS::Time timeMark; boolean tracking; double sunAvoidanceOffset; }; const string SUPERVISOR_DATA_CHANNEL = "SupervisorData"; Loading Loading @@ -80,6 +79,20 @@ module Antenna { double getWindSafeLimit() raises (ComponentErrors::ComponentErrorsEx); /** Get the average wind value. * * @throw ComponentErrors::ComponentErrorsEx */ double getAverageWind() raises (ComponentErrors::ComponentErrorsEx); /** Distance from the Sun: sqrt(delta_az**2 + delta_el**2) * * @throw ComponentErrors::ComponentErrorsEx */ double getSunDistance() raises (ComponentErrors::ComponentErrorsEx); /** Set Sun avoidance to "ON" or "OFF" * * In case the Sun avoidance is "ON", the Supervisor component sets Loading Loading @@ -118,13 +131,6 @@ module Antenna { double getSunSafeLimit() raises (ComponentErrors::ComponentErrorsEx); /** Get the current offset applied to the antenna coordinates * * @throw ComponentErrors::ComponentErrorsEx */ double getSunOffset() raises (ComponentErrors::ComponentErrorsEx); /** Return true when the Supervisor is not setting any offset related * to the Sun avoidance * Loading Common/Servers/PySupervisor/src/Supervisor/SupervisorImpl.py +145 −44 Original line number Diff line number Diff line Loading @@ -42,7 +42,8 @@ class SupervisorImpl(POA, cc, services, lcycle): 'supervisorGetSunAvoidance': ('getSunAvoidance', ()), 'supervisorSetSunSafeLimit': ('setSunSafeLimit', (float,)), 'supervisorGetSunSafeLimit': ('getSunSafeLimit', ()), 'supervisorGetSunOffset': ('getSunOffset', ()), 'supervisorGetSunDistance': ('getSunDistance', ()), 'supervisorGetWind': ('getAverageWind', ()), 'supervisorIsTracking': ('isTracking', ()), } Loading @@ -63,14 +64,14 @@ class SupervisorImpl(POA, cc, services, lcycle): def cleanUp(self): self.stop_threads = True # self.supplier.disconnect() def setup(self, code): self.log(f"Supervisor.setup({code})", Management.C_INFO) self.receiverSetup = "unknown" self.windAvoidance = "ON" self.sunAvoidance = "ON" self.sunOffset = 0 self.sunDistance = 180 self.wind = 0 dao = ACSCorba.cdb().get_DAO_Servant(self.dao_path) self.windLimit = float(dao.get_field_data("WindLimit")) code = code.upper() Loading Loading @@ -123,25 +124,15 @@ class SupervisorImpl(POA, cc, services, lcycle): def getSunSafeLimit(self): return self.sunLimit def getSunOffset(self): return self.sunOffset def getSunDistance(self): return self.sunDistance def getAverageWind(self): return self.wind def isTracking(self): return True # TODO: fare un metodo/funzione che ottiene il component, passandole # il nome del component. Questo serve per il logging e per ogni volta # che ci occorre un client def windCheck(self): while True: if self.stop_threads: print("Stopping windCheck") break time.sleep(10) print("WIND: windAvoidance: ", self.windAvoidance) print("windCheck() stopped") def disconnect(self, client): try: if client.isLoggedIn(): Loading @@ -166,6 +157,111 @@ class SupervisorImpl(POA, cc, services, lcycle): finally: self.disconnect(client) def windCheck(self): print("windCheck() thread started") stow_notified = False mount_name = "ANTENNA/Mount" scheduler_name = "IDL:alma/Management/Scheduler:1.0" weather_name = "WEATHERSTATION/WeatherStation" antenna_name = "ANTENNA/Boss" wind_values = [] while True: for i in range(5): # Sleep for 5 seconds, check stop signal if self.stop_threads: break else: time.sleep(1) if self.stop_threads: print("Stopping windCheck() thread") break if self.windAvoidance == "OFF": continue # Sleep again client = PySimpleClient() try: el_mode = "" mount = client.getComponent(mount_name) el_mode, compl = mount.elevationMode.get_sync() except CannotGetComponentEx as ex: self.log( f"Can not get component {mount_name}", Management.C_WARNING, ) except Exception as ex: self.log(f"Can not get component {mount_name}: {ex}") try: ws = client.getComponent(weather_name) value = ws.getWindSpeedAverage() except CannotGetComponentEx as ex: self.log( f"Can not get component {weather_name}", Management.C_ERROR, ) except Exception as ex: self.log(f"Unexpected exception: {ex}") self.disconnect(client) continue # Sleep again if len(wind_values) < 30: wind_values.append(value) else: wind_values.pop() wind_values.insert(0, value) self.wind = sum(wind_values)/len(wind_values) if wind_values else 0 if self.wind >= self.windLimit: if str(el_mode) == "ACU_STOW": if not stow_notified: self.log( f"Antenna parked, too much wind", Management.C_WARNING, ) stow_notified = True self.disconnect(client) continue self.log(f"Supervisor: stopping antenna, windy") self.log(f"Safe limit -> {self.windLimit:.2f}", Management.C_INFO) self.log(f"Average wind -> {self.wind:.2f}", Management.C_INFO) try: scheduler = client.getDefaultComponent(scheduler_name) scheduler.stopSchedule() except CannotGetComponentEx as ex: self.log( f"Supervisor can not get {scheduler_name}", Management.C_WARNING, ) except Exception as ex: self.log(f"Can not get {scheduler_name}: {ex}") try: antenna = client.getComponent(antenna_name) except CannotGetComponentEx as ex: self.log( f"Can not get component {antenna_name}", Management.C_ERROR, ) except Exception as ex: self.log(f"Can not get {antenna_name}: {ex}") self.disconnect(client) continue # Sleep again try: antenna.park() # Finally park the antenna except Exception as ex: self.log(f"Can not park the antenna: {ex}") self.disconnect(client) continue # Sleep again stow_notified = False self.disconnect(client) print("sunCheck() thread stopped") def sunCheck(self): print("sunCheck() thread started") antenna_name = "ANTENNA/Boss" Loading @@ -192,7 +288,7 @@ class SupervisorImpl(POA, cc, services, lcycle): except CannotGetComponentEx as ex: self.log(f"Supervisor can not get {observatory_name}") except Exception as ex: print(f"Unexpected exception: {ex}") self.log(f"Can not get component {observatory_name}: {ex}") finally: self.disconnect(client) continue # Sleep again Loading Loading @@ -220,21 +316,32 @@ class SupervisorImpl(POA, cc, services, lcycle): self.disconnect(client) continue # Sleep again limit = self.sunLimit az_mode = el_mode = "" try: mount = client.getComponent(mount_name) az_mode, compl = mount.azimuthMode.get_sync() el_mode, compl = mount.elevationMode.get_sync() if str(az_mode) == str(el_mode) == "ACU_PRESET": limit = self.sunLimit * 3 except CannotGetComponentEx as ex: self.log( f"Can not get component {mount_name}", Management.C_WARNING, ) except Exception as ex: self.log(f"Can not get component {mount_name}: {ex}") obs.lat, obs.lon, obs.date = str(lat), str(lon), dt.utcnow() sun.compute(obs) sun_az, sun_el = degrees(sun.az), degrees(sun.alt) if (diff := abs(sun_az - az)) <= 180: delta_az = diff else: delta_az = 360 - diff distance = sqrt(delta_az**2 + (sun_el - el)**2) if distance < self.sunLimit: try: mount = client.getComponent(mount_name) az_mode, compl = mount.azimuthMode.get_sync() el_mode, compl = mount.elevationMode.get_sync() self.sunDistance = sqrt(delta_az**2 + (sun_el - el)**2) if self.sunDistance < limit: if str(az_mode) == str(el_mode) == "ACU_STOP": if not stop_notified: self.log( Loading @@ -242,20 +349,14 @@ class SupervisorImpl(POA, cc, services, lcycle): Management.C_WARNING, ) stop_notified = True continue except CannotGetComponentEx as ex: self.log( f"Can not get component {mount_name}", Management.C_WARNING, ) except Exception: pass self.disconnect(client) continue # Sleep again self.log(f"Supervisor: stopping antenna, pointing close to the Sun") self.log(f"Sun(az, el) -> ({sun_az:.2f}, {sun_el:.2f})", Management.C_INFO) self.log(f"Ant(az, el) -> ({az:.2f}, {el:.2f})", Management.C_INFO) self.log(f"Safe Limit -> {self.sunLimit:.2f}", Management.C_INFO) self.log(f"Distance from Sun -> {distance:.2f}", Management.C_INFO) self.log(f"Safe Limit -> {limit:.2f}", Management.C_INFO) self.log(f"Distance from Sun -> {self.sunDistance:.2f}", Management.C_INFO) try: antenna.stop() except Exception as ex: Loading Loading
Common/Interfaces/AntennaInterface/idl/Supervisor.idl +14 −8 Original line number Diff line number Diff line Loading @@ -15,7 +15,6 @@ module Antenna { struct SupervisorDataBlock { ACS::Time timeMark; boolean tracking; double sunAvoidanceOffset; }; const string SUPERVISOR_DATA_CHANNEL = "SupervisorData"; Loading Loading @@ -80,6 +79,20 @@ module Antenna { double getWindSafeLimit() raises (ComponentErrors::ComponentErrorsEx); /** Get the average wind value. * * @throw ComponentErrors::ComponentErrorsEx */ double getAverageWind() raises (ComponentErrors::ComponentErrorsEx); /** Distance from the Sun: sqrt(delta_az**2 + delta_el**2) * * @throw ComponentErrors::ComponentErrorsEx */ double getSunDistance() raises (ComponentErrors::ComponentErrorsEx); /** Set Sun avoidance to "ON" or "OFF" * * In case the Sun avoidance is "ON", the Supervisor component sets Loading Loading @@ -118,13 +131,6 @@ module Antenna { double getSunSafeLimit() raises (ComponentErrors::ComponentErrorsEx); /** Get the current offset applied to the antenna coordinates * * @throw ComponentErrors::ComponentErrorsEx */ double getSunOffset() raises (ComponentErrors::ComponentErrorsEx); /** Return true when the Supervisor is not setting any offset related * to the Sun avoidance * Loading
Common/Servers/PySupervisor/src/Supervisor/SupervisorImpl.py +145 −44 Original line number Diff line number Diff line Loading @@ -42,7 +42,8 @@ class SupervisorImpl(POA, cc, services, lcycle): 'supervisorGetSunAvoidance': ('getSunAvoidance', ()), 'supervisorSetSunSafeLimit': ('setSunSafeLimit', (float,)), 'supervisorGetSunSafeLimit': ('getSunSafeLimit', ()), 'supervisorGetSunOffset': ('getSunOffset', ()), 'supervisorGetSunDistance': ('getSunDistance', ()), 'supervisorGetWind': ('getAverageWind', ()), 'supervisorIsTracking': ('isTracking', ()), } Loading @@ -63,14 +64,14 @@ class SupervisorImpl(POA, cc, services, lcycle): def cleanUp(self): self.stop_threads = True # self.supplier.disconnect() def setup(self, code): self.log(f"Supervisor.setup({code})", Management.C_INFO) self.receiverSetup = "unknown" self.windAvoidance = "ON" self.sunAvoidance = "ON" self.sunOffset = 0 self.sunDistance = 180 self.wind = 0 dao = ACSCorba.cdb().get_DAO_Servant(self.dao_path) self.windLimit = float(dao.get_field_data("WindLimit")) code = code.upper() Loading Loading @@ -123,25 +124,15 @@ class SupervisorImpl(POA, cc, services, lcycle): def getSunSafeLimit(self): return self.sunLimit def getSunOffset(self): return self.sunOffset def getSunDistance(self): return self.sunDistance def getAverageWind(self): return self.wind def isTracking(self): return True # TODO: fare un metodo/funzione che ottiene il component, passandole # il nome del component. Questo serve per il logging e per ogni volta # che ci occorre un client def windCheck(self): while True: if self.stop_threads: print("Stopping windCheck") break time.sleep(10) print("WIND: windAvoidance: ", self.windAvoidance) print("windCheck() stopped") def disconnect(self, client): try: if client.isLoggedIn(): Loading @@ -166,6 +157,111 @@ class SupervisorImpl(POA, cc, services, lcycle): finally: self.disconnect(client) def windCheck(self): print("windCheck() thread started") stow_notified = False mount_name = "ANTENNA/Mount" scheduler_name = "IDL:alma/Management/Scheduler:1.0" weather_name = "WEATHERSTATION/WeatherStation" antenna_name = "ANTENNA/Boss" wind_values = [] while True: for i in range(5): # Sleep for 5 seconds, check stop signal if self.stop_threads: break else: time.sleep(1) if self.stop_threads: print("Stopping windCheck() thread") break if self.windAvoidance == "OFF": continue # Sleep again client = PySimpleClient() try: el_mode = "" mount = client.getComponent(mount_name) el_mode, compl = mount.elevationMode.get_sync() except CannotGetComponentEx as ex: self.log( f"Can not get component {mount_name}", Management.C_WARNING, ) except Exception as ex: self.log(f"Can not get component {mount_name}: {ex}") try: ws = client.getComponent(weather_name) value = ws.getWindSpeedAverage() except CannotGetComponentEx as ex: self.log( f"Can not get component {weather_name}", Management.C_ERROR, ) except Exception as ex: self.log(f"Unexpected exception: {ex}") self.disconnect(client) continue # Sleep again if len(wind_values) < 30: wind_values.append(value) else: wind_values.pop() wind_values.insert(0, value) self.wind = sum(wind_values)/len(wind_values) if wind_values else 0 if self.wind >= self.windLimit: if str(el_mode) == "ACU_STOW": if not stow_notified: self.log( f"Antenna parked, too much wind", Management.C_WARNING, ) stow_notified = True self.disconnect(client) continue self.log(f"Supervisor: stopping antenna, windy") self.log(f"Safe limit -> {self.windLimit:.2f}", Management.C_INFO) self.log(f"Average wind -> {self.wind:.2f}", Management.C_INFO) try: scheduler = client.getDefaultComponent(scheduler_name) scheduler.stopSchedule() except CannotGetComponentEx as ex: self.log( f"Supervisor can not get {scheduler_name}", Management.C_WARNING, ) except Exception as ex: self.log(f"Can not get {scheduler_name}: {ex}") try: antenna = client.getComponent(antenna_name) except CannotGetComponentEx as ex: self.log( f"Can not get component {antenna_name}", Management.C_ERROR, ) except Exception as ex: self.log(f"Can not get {antenna_name}: {ex}") self.disconnect(client) continue # Sleep again try: antenna.park() # Finally park the antenna except Exception as ex: self.log(f"Can not park the antenna: {ex}") self.disconnect(client) continue # Sleep again stow_notified = False self.disconnect(client) print("sunCheck() thread stopped") def sunCheck(self): print("sunCheck() thread started") antenna_name = "ANTENNA/Boss" Loading @@ -192,7 +288,7 @@ class SupervisorImpl(POA, cc, services, lcycle): except CannotGetComponentEx as ex: self.log(f"Supervisor can not get {observatory_name}") except Exception as ex: print(f"Unexpected exception: {ex}") self.log(f"Can not get component {observatory_name}: {ex}") finally: self.disconnect(client) continue # Sleep again Loading Loading @@ -220,21 +316,32 @@ class SupervisorImpl(POA, cc, services, lcycle): self.disconnect(client) continue # Sleep again limit = self.sunLimit az_mode = el_mode = "" try: mount = client.getComponent(mount_name) az_mode, compl = mount.azimuthMode.get_sync() el_mode, compl = mount.elevationMode.get_sync() if str(az_mode) == str(el_mode) == "ACU_PRESET": limit = self.sunLimit * 3 except CannotGetComponentEx as ex: self.log( f"Can not get component {mount_name}", Management.C_WARNING, ) except Exception as ex: self.log(f"Can not get component {mount_name}: {ex}") obs.lat, obs.lon, obs.date = str(lat), str(lon), dt.utcnow() sun.compute(obs) sun_az, sun_el = degrees(sun.az), degrees(sun.alt) if (diff := abs(sun_az - az)) <= 180: delta_az = diff else: delta_az = 360 - diff distance = sqrt(delta_az**2 + (sun_el - el)**2) if distance < self.sunLimit: try: mount = client.getComponent(mount_name) az_mode, compl = mount.azimuthMode.get_sync() el_mode, compl = mount.elevationMode.get_sync() self.sunDistance = sqrt(delta_az**2 + (sun_el - el)**2) if self.sunDistance < limit: if str(az_mode) == str(el_mode) == "ACU_STOP": if not stop_notified: self.log( Loading @@ -242,20 +349,14 @@ class SupervisorImpl(POA, cc, services, lcycle): Management.C_WARNING, ) stop_notified = True continue except CannotGetComponentEx as ex: self.log( f"Can not get component {mount_name}", Management.C_WARNING, ) except Exception: pass self.disconnect(client) continue # Sleep again self.log(f"Supervisor: stopping antenna, pointing close to the Sun") self.log(f"Sun(az, el) -> ({sun_az:.2f}, {sun_el:.2f})", Management.C_INFO) self.log(f"Ant(az, el) -> ({az:.2f}, {el:.2f})", Management.C_INFO) self.log(f"Safe Limit -> {self.sunLimit:.2f}", Management.C_INFO) self.log(f"Distance from Sun -> {distance:.2f}", Management.C_INFO) self.log(f"Safe Limit -> {limit:.2f}", Management.C_INFO) self.log(f"Distance from Sun -> {self.sunDistance:.2f}", Management.C_INFO) try: antenna.stop() except Exception as ex: Loading