Merge branch 'developer' into dev/rx_disable_datastream_port
Build on RHEL8 docker image / build (push) Successful in 6m24s
Build on RHEL9 docker image / build (push) Successful in 6m23s
Run Simulator Tests on local RHEL9 / build (push) Successful in 18m51s
Run Simulator Tests on local RHEL8 / build (push) Successful in 22m25s

This commit is contained in:
2026-07-07 15:20:02 +02:00
9 changed files with 197 additions and 114 deletions
+32 -1
View File
@@ -21,11 +21,42 @@ jobs:
cache: 'pip'
- run: pip install pytest numpy colorama
- uses: awalsh128/cache-apt-pkgs-action@latest
# using a stable action version instead of latest to create/restore cache for now
- uses: awalsh128/cache-apt-pkgs-action@v1.6.1
with:
packages: libhdf5-dev qtbase5-dev qt5-qmake libqt5svg5-dev libpng-dev libtiff-dev libfmt-dev
version: 1.0
# verify packages restored from cache are installed.
# This catches incomplete apt installs after cache restore.
- name: Verify apt packages
id: verify_packages
run: |
failed=""
for pkg in \
libhdf5-dev \
qtbase5-dev \
qt5-qmake \
libqt5svg5-dev \
libpng-dev \
libtiff-dev \
libfmt-dev
do
if ! dpkg -s "$pkg" >/dev/null 2>&1; then
echo "Missing: $pkg"
failed="$failed $pkg"
fi
done
if [ -n "$failed" ]; then
echo "Missing packages after cache restore: $failed. Try deleting the cache and rerunning the workflow."
exit 1
else
echo "All apt packages are installed"
fi
- name: Configure CMake
# Configure CMake in a 'build' subdirectory. `CMAKE_BUILD_TYPE` is only required if you are using a single-configuration generator such as make.
# See https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html?highlight=cmake_build_type
+27 -1
View File
@@ -20,11 +20,37 @@ jobs:
cache: 'pip'
- run: pip install pytest numpy colorama pyzmq
- uses: awalsh128/cache-apt-pkgs-action@latest
# using a stable action version instead of latest to create/restore cache for now
- uses: awalsh128/cache-apt-pkgs-action@v1.6.1
with:
packages: libhdf5-dev libfmt-dev
version: 1.0
# verify packages restored from cache are installed.
# This catches incomplete apt installs after cache restore.
- name: Verify apt packages
id: verify_packages
run: |
failed=""
for pkg in \
libhdf5-dev \
libfmt-dev
do
if ! dpkg -s "$pkg" >/dev/null 2>&1; then
echo "Missing: $pkg"
failed="$failed $pkg"
fi
done
if [ -n "$failed" ]; then
echo "Missing packages after cache restore: $failed. Try deleting the cache and rerunning the workflow."
exit 1
else
echo "All apt packages are installed"
fi
- name: Configure CMake
run: |
cmake -B ${{github.workspace}}/build \
@@ -1,10 +1,10 @@
// SPDX-License-Identifier: LGPL-3.0-or-other
// Copyright (C) 2021 Contributors to the SLS Detector Package
#include "clogger.h"
#include "sls/ansi.h"
#include <errno.h>
#include <fcntl.h> // File control definitions
#include <linux/i2c-dev.h> // I2C_SLAVE, __u8 reg
#include <fcntl.h> // File control definitions
#include <stdio.h>
#include <stdlib.h> // atoi
#include <string.h> // memset
@@ -12,80 +12,102 @@
#include <termios.h> /* POSIX terminal control definitions */
#include <unistd.h> // read, close
#define PORTNAME "/dev/ttyBF1"
#define GOODBYE 200
#define BUFFERSIZE 16
#define I2C_DEVICE_FILE "/dev/i2c-0"
#define I2C_DEVICE_ADDRESS 0x4C
// #define I2C_DEVICE_ADDRESS 0x48
#define I2C_REGISTER_ADDRESS 0x40
#define PORTNAME "/dev/ttyBF1"
#define GOODBYE 200
#define BUFFERSIZE 16
#define INFILE "/sys/devices/platform/i2c-bfin-twi.0/i2c-0/0-0048/in0_input"
#define OUTFILE "/sys/devices/platform/i2c-bfin-twi.0/i2c-0/0-0048/out0_output"
#define OUTENABLE \
"/sys/devices/platform/i2c-bfin-twi.0/i2c-0/0-0048/out0_enable"
int i2c_open(const char *file, unsigned int addr) {
// device file
int fd = open(file, O_RDWR);
if (fd < 0) {
LOG(logERROR, ("Warning: Unable to open file %s\n", file));
int set_hv(int dac_value) {
if ((dac_value > 255) || (dac_value < 0)) {
LOG(logERROR, ("Invalid dac value %d\n", dac_value));
return -1;
}
// device address
if (ioctl(fd, I2C_SLAVE, addr & 0x7F) < 0) {
LOG(logERROR, ("Warning: Unable to set slave address:0x%x \n", addr));
return -2;
}
return fd;
}
dac_value = dac_value * 10;
int i2c_read() {
int fd = i2c_open(I2C_DEVICE_FILE, I2C_DEVICE_ADDRESS);
__u8 reg = I2C_REGISTER_ADDRESS & 0xff;
unsigned char buf = reg;
if (write(fd, &buf, 1) != 1) {
LOG(logERROR,
("Warning: Unable to write read request to register %d\n", reg));
FILE *file;
file = fopen(OUTFILE, "w");
if (file == NULL) {
perror("set_hv:");
LOG(logERROR, ("Cannot open out0_output file\n"));
return -1;
}
// read and update value (but old value read out)
if (read(fd, &buf, 1) != 1) {
LOG(logERROR, ("Warning: Unable to read register %d\n", reg));
return -2;
if (setvbuf(file, NULL, _IONBF, 0) != 0) {
perror("set_hv:");
LOG(logERROR, ("Cannot disable buffering\n"));
return -1;
}
// read again to read the updated value
if (read(fd, &buf, 1) != 1) {
LOG(logERROR, ("Warning: Unable to read register %d\n", reg));
return -2;
if (fprintf(file, "%d", dac_value) < 1) {
ferror(file);
LOG(logERROR, ("Couldn't write to out0_output file\n"));
return -1;
}
close(fd);
return buf;
}
int i2c_write(unsigned int value) {
__u8 val = value & 0xff;
int fd = i2c_open(I2C_DEVICE_FILE, I2C_DEVICE_ADDRESS);
if (fd < 0)
return fd;
__u8 reg = I2C_REGISTER_ADDRESS & 0xff;
char buf[3];
buf[0] = reg;
buf[1] = val;
if (write(fd, buf, 2) != 2) {
LOG(logERROR,
("Warning: Unable to write %d to register %d\n", val, reg));
if (fclose(file) != 0) {
perror("set_hv:");
LOG(logERROR, ("Troubles closing out0_output file\n"));
return -1;
}
close(fd);
return 0;
}
int enable_hv(int val) {
if ((val > 1) || (val < 0))
return -1;
FILE *file;
file = fopen(OUTENABLE, "w");
if (file == NULL) {
perror("enable_hv:");
LOG(logERROR, ("Cannot open out0_enable file\n"));
return -1;
}
if (setvbuf(file, NULL, _IONBF, 0) != 0) {
perror("enable_hv:");
LOG(logERROR, ("Cannot disable buffering\n"));
return -1;
}
if (fprintf(file, "%d", val) < 1) {
ferror(file);
LOG(logERROR, ("Couldn't write to out0_enable file\n"));
return -1;
}
if (fclose(file) != 0) {
perror("enable_hv:");
LOG(logERROR, ("Troubles closing out0_enable file\n"));
return -1;
}
return 0;
}
int get_hv() {
int value;
FILE *file;
file = fopen(INFILE, "r");
if (file == NULL) {
perror("get_hv:");
LOG(logERROR, ("Cannot open in0_input file\n"));
return -1;
}
if (fscanf(file, "%d", &value) < 1) {
ferror(file);
LOG(logERROR, ("Couldn't read from in0_input file\n"));
return -1;
}
if (fclose(file) != 0) {
perror("get_hv:");
LOG(logERROR, ("Troubles closing out0_enable file\n"));
return -1;
}
return value / 10;
}
int main(int argc, char *argv[]) {
enable_hv(0);
set_hv(0);
int fd = open(PORTNAME, O_RDWR | O_NOCTTY | O_SYNC);
if (fd < 0) {
LOG(logERROR, ("Warning: Unable to open port %s\n", PORTNAME));
@@ -126,7 +148,7 @@ int main(int argc, char *argv[]) {
int ival = 0;
char buffer[BUFFERSIZE];
memset(buffer, 0, BUFFERSIZE);
buffer[BUFFERSIZE - 1] = '\n';
// buffer[BUFFERSIZE - 1] = '\n';
LOG(logINFO, ("Ready...\n"));
while (ret != GOODBYE) {
@@ -149,35 +171,51 @@ int main(int argc, char *argv[]) {
}
// ok/ fail
memset(buffer, 0, BUFFERSIZE);
buffer[BUFFERSIZE - 1] = '\n';
if (i2c_write(ival) < 0)
strcpy(buffer, "fail ");
// buffer[BUFFERSIZE - 1] = '\n';
if (set_hv(ival) < 0)
strcpy(buffer, "fail\n");
else if (enable_hv(ival > 0 ? 1 : 0) < 0)
strcpy(buffer, "fail\n");
else
strcpy(buffer, "success ");
strcpy(buffer, "success\n");
/*
if (i2c_write(ival) < 0)
strcpy(buffer, "fail ");
else
strcpy(buffer, "success ");
*/
LOG(logINFO, ("Sending: '%s'\n", buffer));
n = write(fd, buffer, BUFFERSIZE);
n = write(fd, buffer, strlen(buffer)); // BUFFERSIZE);
LOG(logDEBUG1, ("Sent %d Bytes\n", n));
break;
case 'g':
ival = i2c_read();
// ok/ fail
memset(buffer, 0, BUFFERSIZE);
buffer[BUFFERSIZE - 1] = '\n';
ival = get_hv();
if (ival < 0)
strcpy(buffer, "fail ");
strcpy(buffer, "fail\n");
else
strcpy(buffer, "success ");
n = write(fd, buffer, BUFFERSIZE);
strcpy(buffer, "success\n");
/*
ival = i2c_read();
// ok/ fail
memset(buffer, 0, BUFFERSIZE);
buffer[BUFFERSIZE - 1] = '\n';
if (ival < 0)
strcpy(buffer, "fail ");
else
strcpy(buffer, "success ");
*/
n = write(fd, buffer, strlen(buffer)); // BUFFERSIZE);
LOG(logINFO, ("Sending: '%s'\n", buffer));
LOG(logDEBUG1, ("Sent %d Bytes\n", n));
// value
memset(buffer, 0, BUFFERSIZE);
buffer[BUFFERSIZE - 1] = '\n';
// buffer[BUFFERSIZE - 1] = '\n';
if (ival >= 0) {
LOG(logINFO, ("Sending: '%d'\n", ival));
sprintf(buffer, "%d ", ival);
n = write(fd, buffer, BUFFERSIZE);
sprintf(buffer, "%d\n", ival);
n = write(fd, buffer, strlen(buffer)); // BUFFERSIZE);
LOG(logINFO, ("Sent %d Bytes\n", n));
} else
LOG(logERROR, ("%s\n", buffer));
@@ -41,9 +41,9 @@ $(PROGS): $(OBJS)
hv9m_blackfin_server:9mhvserial_bf.c
$(BLACKFIN_CC) -o hv9m_blackfin_server 9mhvserial_bf.c -Wall #-DVERBOSE
$(BLACKFIN_CC) $(CFLAGS) -o hv9m_blackfin_server 9mhvserial_bf.c -Wall #-DVERBOSE
mv hv9m_blackfin_server $(DESTDIR)
rm hv9m_blackfin_server.gdb $(main_src)*.o $(md5_dir)*.o
rm hv9m_blackfin_server.gdb
clean:
rm -rf $(DESTDIR)/$(PROGS) *.o $(DESTDIR)/hv9m_blackfin_server $(main_src)*.o $(md5_dir)*.o
+8 -7
View File
@@ -27,8 +27,8 @@ ClientSocket::ClientSocket(std::string stype, const std::string &host,
if (getaddrinfo(host.c_str(), nullptr, &hints, &result) != 0) {
auto msg = fmt::format("Cannot resolve {} hostname: '{}'", to_lower(socketType), host);
auto msg = fmt::format("Cannot resolve {} hostname: '{}'",
to_lower(socketType), host);
throwError(msg);
}
@@ -43,9 +43,8 @@ ClientSocket::ClientSocket(std::string stype, const std::string &host,
if (::connect(getSocketId(), (struct sockaddr *)&serverAddr,
sizeof(serverAddr)) != 0) {
freeaddrinfo(result);
auto msg = fmt::format(
"Cannot connect to {} on {}:{}\n",
to_lower(socketType), host, port);
auto msg = fmt::format("Cannot connect to {} on {}:{}\n",
to_lower(socketType), host, port);
throwError(msg);
}
@@ -58,7 +57,8 @@ ClientSocket::ClientSocket(std::string sType, struct sockaddr_in addr)
if (::connect(getSocketId(), (struct sockaddr *)&addr, sizeof(addr)) != 0) {
char address[INET_ADDRSTRLEN];
inet_ntop(AF_INET, &addr.sin_addr, address, INET_ADDRSTRLEN);
auto msg = fmt::format("Cannot connect to {} on {}:{}", to_lower(socketType), address, addr.sin_port);
auto msg = fmt::format("Cannot connect to {} on {}:{}",
to_lower(socketType), address, addr.sin_port);
throwError(msg);
}
}
@@ -99,7 +99,8 @@ void ClientSocket::readReply(int &ret, void *retval, size_t retval_size) {
}
// debugging
catch (SocketError &e) {
auto msg = fmt::format("While reading reply from {} {}", to_lower(socketType), e.what());
auto msg = fmt::format("While reading reply from {} {}",
to_lower(socketType), e.what());
throwError(msg);
}
}
+3 -4
View File
@@ -113,10 +113,9 @@ int DataSocket::Send(const void *buffer, size_t size) {
#endif
Timer timer;
while (bytes_sent < bytes_expected) {
this_send = ::send(
getSocketId(),
reinterpret_cast<const char *>(buffer) + bytes_sent,
bytes_expected - bytes_sent, send_flags);
this_send = ::send(getSocketId(),
reinterpret_cast<const char *>(buffer) + bytes_sent,
bytes_expected - bytes_sent, send_flags);
if (this_send < 0 && errno == EINTR)
continue; // interrupted by a signal, retry
if (this_send <= 0)
+1 -1
View File
@@ -78,7 +78,7 @@ std::pair<std::string, uint16_t> ParseHostPort(const std::string &s) {
std::string to_lower(const std::string &s) {
std::string result = s;
std::transform(result.begin(), result.end(), result.begin(),
[](unsigned char c) { return std::tolower(c); });
[](unsigned char c) { return std::tolower(c); });
return result;
}
+10 -20
View File
@@ -30,11 +30,8 @@ std::vector<char> echo_server(uint16_t port, size_t bytes_to_send,
std::vector<char> buffer(100, '\0');
s.Receive(buffer.data(), buffer.size());
if (port==1960){
struct linger ling = {
.l_onoff = 1,
.l_linger = 0
};
if (port == 1960) {
struct linger ling = {.l_onoff = 1, .l_linger = 0};
auto fd = s.getSocketId();
setsockopt(fd, SOL_SOCKET, SO_LINGER, &ling, sizeof ling);
@@ -199,7 +196,6 @@ TEST_CASE("Receiving with a socket error throws and reports the error",
CHECK_THAT(error_message, Catch::Matchers::Contains("read error:"));
}
TEST_CASE("Socket crash?", "[support]") {
std::vector<char> received_message(100, '\0');
std::vector<char> sent_message(100, '\0');
@@ -211,25 +207,20 @@ TEST_CASE("Socket crash?", "[support]") {
std::this_thread::sleep_for(std::chrono::milliseconds(100));
auto client = DetectorSocket("localhost", 1960);
client.Send(sent_message.data(), sent_message.size());
REQUIRE_THROWS(client.Receive(received_message.data(), received_message.size()));
//Now try to send more
// client.Send(sent_message.data(), sent_message.size());
REQUIRE_THROWS(
client.Receive(received_message.data(), received_message.size()));
// Now try to send more
// client.Send(sent_message.data(), sent_message.size());
}
TEST_CASE("ClientSocket throws on invalid hostname", "[support]") {
CHECK_THROWS(ReceiverSocket("invalidhostname", 1950));
CHECK_THROWS(DetectorSocket("invalidhostname", 1950));
CHECK_THROWS(GuiSocket("invalidhostname", 1950));
}
TEST_CASE("Using DetectorSocket to talk to a Server Socket", "[support]") {
constexpr uint16_t port = 1961;
constexpr int fnum = F_GET_DETECTOR_TYPE;
@@ -240,9 +231,8 @@ TEST_CASE("Using DetectorSocket to talk to a Server Socket", "[support]") {
auto client = DetectorSocket("localhost", port);
int retval = 0;
int ret =
client.sendCommandThenRead(fnum, &arg, sizeof(arg), &retval,
sizeof(retval));
int ret = client.sendCommandThenRead(fnum, &arg, sizeof(arg), &retval,
sizeof(retval));
client.close();
auto server_received = s.get();
@@ -294,8 +284,8 @@ TEST_CASE("Client cannot send the expected number of bytes", "[support]") {
// Server accepts but never reads; it stays open until we tell it the
// client is done, so it cannot close mid-transfer.
std::atomic<bool> client_done{false};
auto s = std::async(std::launch::async, non_reading_server, port,
&client_done);
auto s =
std::async(std::launch::async, non_reading_server, port, &client_done);
std::this_thread::sleep_for(std::chrono::milliseconds(100));
auto client = DetectorSocket("localhost", port);
@@ -148,8 +148,6 @@ TEST_CASE("to_lower does not modify the original string") {
REQUIRE(original == "MixedCase");
}
// TEST_CASE("concat things not being strings")
} // namespace sls