Skip to content

Commit

Permalink
Fix #350, fix #351, updated minor_servos (#352)
Browse files Browse the repository at this point in the history
* Fix #35, fix #351, updated minor_servos

This branch will not be merged until the component is updated as well

* Updated timer for tests

* Upgraded minor_servos with setup table

* Fixed CSV file

* Updated air blade logic

* Fix #353, added minor_servos minimal REST Api
  • Loading branch information
giuseppe-carboni authored May 28, 2024
1 parent 1a8db89 commit d5ffaf3
Show file tree
Hide file tree
Showing 6 changed files with 215 additions and 42 deletions.
4 changes: 4 additions & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,8 @@
'Operating System :: OS Independent',
'Programming Language :: Python :: 3.10.7',
],
include_package_data=True,
package_data={
'simulators': ['minor_servos/setup.csv']
}
)
92 changes: 63 additions & 29 deletions simulators/minor_servos/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import time
import re
import random
import os
try:
from numpy import sign
except ImportError as ex: # skip coverage
Expand All @@ -17,7 +16,9 @@
from multiprocessing import Value
from bisect import bisect_left
from socketserver import ThreadingTCPServer
from http.server import HTTPServer
from simulators.common import ListeningSystem
from simulators.minor_servos.helpers import setup_import, VBrainRequestHandler


# Each system module (like active_surface.py, acu.py, etc.) has to
Expand All @@ -28,7 +29,8 @@
# subscribe and unsibscribe methods, while kwargs is a dict of optional
# extra arguments.
servers = [(('0.0.0.0', 12800), (), ThreadingTCPServer, {})]
TIMER_VALUE = 1 if os.environ.get('CI') == 'true' else 5
httpserver_address = ('0.0.0.0', 12799)
DEFAULT_TIMER_VALUE = 5


def _change_atomic_value(variable, value):
Expand Down Expand Up @@ -76,7 +78,7 @@ def plc_time(now=None):
'BWG4': {'ID': 24},
}

def __init__(self):
def __init__(self, timer_value=DEFAULT_TIMER_VALUE, rest_api=True):
self.msg = ''
self.configuration = 0
self.simulation = 1
Expand All @@ -86,23 +88,38 @@ def __init__(self):
self.emergency = 2
self.gregorian_cap = Value(c_int, 1)
self.last_executed_command = 0
self.timer_value = timer_value
self.servos = {
'PFP': PFP(),
'SRP': SRP(),
'M3R': M3R(),
'GFR': GFR(),
'DerotatoreGFR1': Derotator('GFR1'),
'DerotatoreGFR2': Derotator('GFR2'),
'DerotatoreGFR3': Derotator('GFR3'),
'DerotatorePFP': Derotator('PFP'),
'DR_GFR1': Derotator('GFR1'),
'DR_GFR2': Derotator('GFR2'),
'DR_GFR3': Derotator('GFR3'),
'DR_PFP': Derotator('PFP'),
}
setup_import(
list(self.servos.keys()) + ['GREGORIAN_CAP'],
self.configurations
)
self.stop = Value(c_bool, False)
self.update_thread = Thread(
target=self._update,
args=(self.stop, self.servos)
)
self.update_thread.daemon = True
self.update_thread.start()
self.rest_api = rest_api
if self.rest_api:
self.httpserver = HTTPServer(
httpserver_address,
VBrainRequestHandler
)
self.server_thread = Thread(
target=self.httpserver.serve_forever
)
self.server_thread.start()
self.cover_timer = Timer(1, lambda: None)

def __del__(self):
Expand All @@ -118,6 +135,9 @@ def system_stop(self):
self.cover_timer.join()
except RuntimeError:
pass
if self.rest_api:
self.httpserver.shutdown()
self.server_thread.join()
return super().system_stop()

@staticmethod
Expand Down Expand Up @@ -184,22 +204,27 @@ def _setup(self, args):
configuration = args[0]
if configuration not in self.configurations:
return self.bad
self.configuration = self.configurations.get(configuration)['ID']
for _, servo in self.servos.items():
configuration = self.configurations.get(configuration)
self.configuration = configuration['ID']
for servo_name, servo in self.servos.items():
coordinates = configuration[servo_name]
servo.operative_mode_timer.cancel()
_change_atomic_value(servo.operative_mode, 0)
servo.operative_mode_timer = Timer(
TIMER_VALUE,
self.timer_value,
_change_atomic_value,
args=(servo.operative_mode, 10) # SETUP
)
servo.operative_mode_timer.daemon = True
servo.operative_mode_timer.start()
gregorian_cap_position = 1 if self.configuration == 1 else 2
if self.gregorian_cap.value != gregorian_cap_position:
servo.set_coords(coordinates)
gregorian_cap_position = configuration['GREGORIAN_CAP'][0]
if (gregorian_cap_position
and self.gregorian_cap.value != gregorian_cap_position):
self.cover_timer.cancel()
_change_atomic_value(self.gregorian_cap, 0)
self.cover_timer = Timer(
TIMER_VALUE,
self.timer_value,
_change_atomic_value,
args=(self.gregorian_cap, gregorian_cap_position)
)
Expand All @@ -212,30 +237,37 @@ def _stow(self, args):
if len(args) != 2:
return self.bad
servo_id = args[0]
if servo_id not in list(self.servos) + ['Gregoriano']:
if servo_id not in list(self.servos) + ['GREGORIAN_CAP']:
return self.bad
try:
stow_pos = int(args[1]) # STOW POSITION
except ValueError:
return self.bad
if servo_id == 'Gregoriano':
if stow_pos not in [1, 2]:
if servo_id == 'GREGORIAN_CAP':
if stow_pos not in range(5):
return self.bad
if self.gregorian_cap.value != stow_pos:
_change_atomic_value(self.gregorian_cap, 0)
self.cover_timer = Timer(
TIMER_VALUE,
_change_atomic_value,
args=(self.gregorian_cap, stow_pos)
)
self.cover_timer.daemon = True
self.cover_timer.start()
self.cover_timer.cancel()
if self.gregorian_cap.value <= 1 or stow_pos == 1:
_change_atomic_value(self.gregorian_cap, 0)
self.cover_timer = Timer(
self.timer_value,
_change_atomic_value,
args=(self.gregorian_cap, stow_pos)
)
self.cover_timer.daemon = True
self.cover_timer.start()
else:
_change_atomic_value(
self.gregorian_cap,
stow_pos
)
else:
servo = self.servos.get(servo_id)
servo.operative_mode_timer.cancel()
_change_atomic_value(servo.operative_mode, 0)
servo.operative_mode_timer = Timer(
TIMER_VALUE,
self.timer_value,
_change_atomic_value,
args=(servo.operative_mode, 20) # STOW
)
Expand All @@ -254,7 +286,7 @@ def _stop(self, args):
servo.operative_mode_timer.cancel()
_change_atomic_value(servo.operative_mode, 0)
servo.operative_mode_timer = Timer(
TIMER_VALUE,
self.timer_value,
_change_atomic_value,
args=(servo.operative_mode, 30) # STOP
)
Expand All @@ -281,7 +313,7 @@ def _preset(self, args):
servo.operative_mode_timer.cancel()
_change_atomic_value(servo.operative_mode, 0)
servo.operative_mode_timer = Timer(
TIMER_VALUE,
self.timer_value,
_change_atomic_value,
args=(servo.operative_mode, 40) # PRESET
)
Expand Down Expand Up @@ -488,7 +520,9 @@ def get_status(self, now):

def set_coords(self, coords):
for index, value in enumerate(coords):
self.coords[index] = value
if value is None:
continue
self.coords[index] = value + self.offsets[index]

def set_offsets(self, coords):
for index, value in enumerate(coords):
Expand Down Expand Up @@ -618,7 +652,7 @@ def __init__(self, name):
self.max_coord = [220.0]
self.min_coord = [-220.0]
self.max_delta = [3.3]
super().__init__(name)
super().__init__(f'DR_{name}')

def get_status(self, now):
answer = super().get_status(now)
Expand Down
72 changes: 72 additions & 0 deletions simulators/minor_servos/helpers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import os
import csv
import json
from http.server import BaseHTTPRequestHandler
import pkg_resources


def setup_import(servos, configurations):
filename = os.environ.get('ACS_CDB', '/')
filename = os.path.join(
filename,
'CDB',
'alma',
'DataBlock',
'MinorServo',
'Tabella Setup.csv'
)
if not os.path.exists(filename):
filename = pkg_resources.resource_filename(
'simulators',
'minor_servos/setup.csv'
)
with open(filename, 'r', encoding='utf-8') as csvfile:
reader = csv.reader(csvfile, delimiter=';')
indexes = {}
for line in reader:
if not indexes:
for servo in servos:
temp = [e for e in line if e.startswith(servo)]
indexes[servo] = [line.index(e) for e in temp]
continue
for servo, servo_indexes in indexes.items():
coordinates = []
for index in servo_indexes:
coord = line[index]
try:
if servo == 'GREGORIAN_CAP':
coord = int(coord)
else:
coord = float(coord)
except ValueError:
coord = None
coordinates.append(coord)
configurations[line[0]][servo] = coordinates


class VBrainRequestHandler(BaseHTTPRequestHandler):

emergency = 'INAF_SRT_OR7_EMG_RESET_CMD'
alarm = 'INAF_SRT_OR7_RESET_CMD'
baseurl = '/Exporting/json/ExecuteCommand?name'
urls = [
f'{baseurl}={emergency}',
f'{baseurl}={alarm}'
]
answer = {'Message': 'OUTPUT:GOOD', 'Status': 'Good'}

def do_GET(self):
try:
if self.path in self.urls:
self.send_response(200)
self.send_header('Content-type', 'application/json')
self.end_headers()
self.wfile.write(json.dumps(self.answer).encode())
else:
self.send_response(404)
self.end_headers()
except BrokenPipeError: # skip coverage
pass

def log_message(self, *_):
pass
14 changes: 14 additions & 0 deletions simulators/minor_servos/setup.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
CONFIGURATION;PFP_TX;PFP_TZ;PFP_RTHETA;SRP_TX;SRP_TY;SRP_TZ;SRP_RX;SRP_RY;SRP_RZ;M3R_RZ;GFR_RZ;DR_GFR1;DR_GFR2;DR_GFR3;DR_PFP;GREGORIAN_CAP;
Primario;0;0;0;-5;5;-120;0;0;0;*;*;*;*;*;*;1;
Gregoriano1;0;0;0;-1.5;11.1393650793988;1.08830677049999;0.049894179898239;-0.036111111111111;0;*;-88.70659;*;*;*;*;2;
Gregoriano2;0;0;0;-1.5;11.1393650793988;1.08830677049999;0.049894179898239;-0.036111111111111;0;*;-159.8899;*;*;*;*;2;
Gregoriano3;0;0;0;-1.5;11.1393650793988;1.08830677049999;0.049894179898239;-0.036111111111111;0;*;90.97161;*;*;*;*;2;
Gregoriano4;0;0;0;-1.5;11.1393650793988;1.08830677049999;0.049894179898239;-0.036111111111111;0;*;162.771;*;*;*;*;2;
Gregoriano5;0;0;0;-1.5;11.1393650793988;1.08830677049999;0.049894179898239;-0.036111111111111;0;*;55.373967;*;*;*;*;2;
Gregoriano6;0;0;0;-1.5;11.1393650793988;1.08830677049999;0.049894179898239;-0.036111111111111;0;*;-51.82117;*;*;*;*;2;
Gregoriano7;0;0;0;*;*;*;*;*;*;*;*;*;*;*;*;*;
Gregoriano8;0;0;0;*;*;*;*;*;*;*;*;*;*;*;*;*;
BWG1;0;0;0;-1.5;11.1393650793988;0.358165166130078;0.049894179898239;-0.036111111111111;0;10;0;*;*;*;*;2;
BWG2;0;0;0;*;*;*;*;*;*;*;*;*;*;*;*;*;
BWG3;0;0;0;-1.5;11.1393650793988;-3.77159716192807;0.049894179898239;-0.036111111111111;0;20;0;*;*;*;*;2;
BWG4;0;0;0;*;*;*;*;*;*;*;*;*;*;*;*;*;
Empty file added tests/__init__.py
Empty file.
Loading

0 comments on commit d5ffaf3

Please sign in to comment.