Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ FROM simonsobs/ocs:v0.11.3-19-gd729e04
RUN apt-get update -y && apt-get install -y iputils-ping \
curl

RUN apt-get install -y libusb-1.0-0-dev libusb-1.0-0 && rm -rf /var/lib/apt/lists/*1~RUN apt-get update && apt-get install -y libusb-1.0-0-dev libusb-1.0-0 && rm -rf /var/lib/apt/lists/*

# Copy in and install requirements
COPY requirements.txt /app/pcs/requirements.txt
WORKDIR /app/pcs/
Expand Down
41 changes: 31 additions & 10 deletions pcs/agents/acu_interface/aculib.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,21 @@
#!/bin/python

import os, yaml
import time
import os, yaml, json, sys
import time, datetime
import socket, struct, requests

#: Global variable to hold the most-recent config block from calling

cache = None

#: Per-request HTTP timeout (seconds) for TCS calls. Without it a hung Go TCS
#: blocks the synchronous requests call indefinitely, freezing the reactor thread
#: and every Process on it, including the 200 Hz broadcast the constant_el_scan
#: slew gate polls. The (connect, read) tuple bounds both phases; the read budget
#: is generous so a slow-but-alive TCS is not killed mid-response (the scan loops
#: have their own wall-clock backstops on top).
TCS_HTTP_TIMEOUT = (5, 30) # (connect, read) seconds

def load_config(filename=None, update_cache=True):
'''Load ACU configuration file and return the settings content
as dict.
Expand Down Expand Up @@ -113,7 +121,8 @@ def post(self, cmd, data):

try:
response = self.session.post(
f"{self.url}{cmd}", json=data, verify=self.verify_cert #allow_redirects=True
f"{self.url}{cmd}", json=data, verify=self.verify_cert, #allow_redirects=True
timeout=TCS_HTTP_TIMEOUT
)
self.log.debug(f"response code: {response.status_code}")
except requests.exceptions.RequestException as e:
Expand All @@ -129,16 +138,23 @@ def post(self, cmd, data):

def get_status(self):
cmd = f"{self.url_prefix}/acu/status"
self.log.info(f"getting status from {self.url}{cmd}")
#cmd = "/Values?identifier=DataSets.StatusGeneral8100&format=JSON"
# cmd = "http://127.0.0.1:8100/Values?identifier=DataSets.StatusGeneral8100&format=JSON"
#self.log.info(f"getting status from {self.url}{cmd}")
try:
self.status = self.session.get(self.url + cmd, verify=self.verify_cert).json()
self.status = self.session.get(
self.url + cmd, verify=self.verify_cert, timeout=TCS_HTTP_TIMEOUT
).json()
#self.status = self.session.get(cmd, verify=self.verify_cert).json()
except requests.exceptions.ConnectionError as e:
self.log.error(
f"failed to connect on {self.url} check is server up, exiting"
#f"failed to connect on {cmd} check is server up, exiting"
)
sys.exit(-1)
return self.status


def abort(self):
cmd = f"{self.url_prefix}/abort"
r = self.post(cmd, "")
Expand All @@ -157,7 +173,11 @@ def move_to(self, azimuth: float, elevation: float):
cmd = f"{self.url_prefix}/move-to"
data = {"azimuth": azimuth, "elevation": elevation}
response = self.post(cmd, data)
self.log.info(response.json())
# ``post`` returns {} (not a Response) on HTTP 503; guard the .json()
# log so a 503 from /move-to does not raise AttributeError inside the
# client. The caller's status guard then handles the {} gracefully.
if hasattr(response, "json"):
self.log.info(response.json())
return response

def azimuth_scan(self, start_time: float, elevation: float,
Expand Down Expand Up @@ -185,7 +205,6 @@ def azimuth_scan(self, start_time: float, elevation: float,
return response

def scan_pattern(self, data):
dt = datetime.datetime.now() + datetime.timedelta(seconds=10)
cmd = f"{self.url_prefix}/path"
self.log.info(data)
response = self.post(cmd, data)
Expand All @@ -208,9 +227,11 @@ def scan_pattern_from_file(self, file_path):
"coordsys": "Horizon",
"points": points
}
self.scan_pattern(data)

return
# Return scan_pattern's value (Response on success, {} on a 503
# short-circuit) instead of None, matching every other command method, so
# the caller can read the status via tcs_response_status. Returning None
# made msg.status_code crash on EVERY call.
return self.scan_pattern(data)



Expand Down
Loading