low level com stuff

This commit is contained in:
Sally Marcher 2025-08-26 18:21:20 +02:00
parent 4368db004d
commit a2ffeff2da
7 changed files with 134 additions and 43 deletions

View file

@ -16,6 +16,9 @@ MainWindow::MainWindow(QWidget *parent)
connect(&ctrl, &ShimLCController::newConfigAv, this, &MainWindow::updateAvDevices);
connect(&ctrl, &ShimLCController::newStatusAv, this, &MainWindow::updateStatus);
// Status Timer
connect(&statusTimer, &QTimer::timeout, &ctrl, &ShimLCController::updateStatus);
spinner->setRoundness(70.0);
spinner->setMinimumTrailOpacity(15.0);
spinner->setTrailFadePercentage(70.0);
@ -87,22 +90,26 @@ void MainWindow::updateAvDevices()
ui->detectorSelectorBox->clear();
foreach(LCPort item, ctrl.configuration.detectors)
ui->detectorSelectorBox->addItem(QString("Port %1: %2").arg(item.port).arg(item.name));
ctrl.updateStatus();
statusTimer.start(2000);
}
void MainWindow::updateStatus()
{
// Stats
vdebug.updateStatus(ctrl.lastStatus);
ui->stateLabel->setText(vdebug.cur_stats.join(","));
// Autospampler
ui->autoSamplerStatus->setText(QString("Rack: %1").arg(ctrl.lastStatus.autosampler.rack));
// Pumps
ui->pumpPress->display(ctrl.lastStatus.pump[ui->pumpsSelectorBox->currentIndex()].actPressure);
ui->pumpFlow->setValue(ctrl.lastStatus.pump[ui->pumpsSelectorBox->currentIndex()].setFlow); // TODO: Not update if currently highlighted
if(not ui->pumpFlow->hasFocus())
ui->pumpFlow->setValue(ctrl.lastStatus.pump[ui->pumpsSelectorBox->currentIndex()].setFlow);
// Detectors
ui->detectorNmSpinBox->setValue(ctrl.lastStatus.detector[ui->detectorSelectorBox->currentIndex()].waveLen1);
if(not ui->detectorNmSpinBox->hasFocus())
ui->detectorNmSpinBox->setValue(ctrl.lastStatus.detector[ui->detectorSelectorBox->currentIndex()].waveLen1);
}

View file

@ -35,6 +35,8 @@ private:
ZoomableChart* mainChart = nullptr;
WaitingSpinnerWidget* spinner = nullptr;
QTimer statusTimer = QTimer(this);
private slots:
void updateConnectionState(QAbstractSocket::SocketState state);
void reconnect();

View file

@ -420,6 +420,19 @@
<item>
<widget class="ZoomableChartWidget" name="chartWidget" native="true"/>
</item>
<item>
<widget class="QLabel" name="stateLabel">
<property name="maximumSize">
<size>
<width>16777215</width>
<height>12</height>
</size>
</property>
<property name="text">
<string>Loading...</string>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QMenuBar" name="menubar">

View file

@ -1,19 +1,31 @@
#include "shimlccontroller.h"
/* Encode Message and store to data
* 01 00 01 00 -> Generic Header
* ll 00 00 00 -> ll => Msg len+1 (becuase of 0d at the end) (maybe more than one byte?
* 01 00 01 00 -> Header: First 2 Bytes are type uint16 LE 1 called "info", second 2 bytes are uint8 LE 1 called "code"
* (other info, code numbers unknown, always 1?)
* xx xx xx xx => Msg len+1 (becuase of 0d at the end) uint32 LE
* ... msg in ASCII ...
* 0d -> End */
void cbmenc(QString message, QByteArray *data)
{
data->append("\x01\x00\x01\x00", 4);
data->append(message.length()+1);
data->append("\x00\x00\x00", 3);
data->append("\x01\x00\x01\x00", 4); // Fixed header
char buf[4];
qToLittleEndian((quint32)message.length()+1, buf);
data->append(buf, 4);
data->append(message.toLatin1());
data->append("\x0d");
}
void cbmenc(QByteArray *data)
{
quint32 len = data->length()+1;
char buf[4];
qToLittleEndian(len, buf);
data->prepend(buf, 4);
data->prepend("\x01\x00\x01\x00", 4);
data->append("\x0d");
}
// Encode Data with cbmenc and send to peer
void ShimTCPController::cbmquery(QString message)
{
@ -23,20 +35,36 @@ void ShimTCPController::cbmquery(QString message)
this->writeData(&data);
}
void ShimTCPController::cbmir(QByteArray *irDataRet)
/* Actual Read command
* 49 52 -> IR (Interface Read?)
* xx -> fileHandle
* xx xx -> size (max 1020!)
* Repeat until data complete, then exit */
void ShimTCPController::cbmir(quint8 filehandle, QByteArray *irDataRet)
{
QByteArray data{"\x01\x00\x01\x00\x05\x00\x00\x00IR\x00", 11};
QByteArray data{"IR"};
irFileHandle = filehandle;
char fh[1];
qToLittleEndian(filehandle, fh);
data.append(fh, 1);
char buf[2];
if(irMode == 0)
// Max Size 1020!
if(irPendingSize > 1020)
{
data.append("\xfc\x03", 2);
irData = irDataRet;
irData->clear(); // Clear current Data in Array
qToLittleEndian((quint16)1020, buf);
irPendingSize -= 1020;
}
else
data.append("\x72\x01", 2);
irMode+=1;
{
qToLittleEndian((quint16)irPendingSize, buf);
irPendingSize = 0;
}
data.append(buf, 2);
cbmenc(&data);
if(irDataRet != nullptr)
irData = irDataRet;
writeData(&data);
}
@ -113,7 +141,7 @@ void ShimTCPController::displayError(QAbstractSocket::SocketError socketError)
// Parse Data and reset parserFunction signal
void ShimTCPController::readData()
{
if(irMode == 0)
if(irPendingSize == -1)
parseCbmquery(socket->readAll());
else
parseCbmIr();
@ -135,7 +163,7 @@ void ShimTCPController::parseCbmquery(QByteArray data)
emit dataAvailable("-");
return;
}
data.removeLast();
//data.removeLast();
QTextCodec::ConverterState state;
QTextCodec *codec = QTextCodec::codecForName("ASCII");
const QString validText = codec->toUnicode(data.constData(), data.size(), &state);
@ -151,7 +179,7 @@ void ShimTCPController::parseCbmquery(QByteArray data)
void ShimTCPController::parseCbmIr()
{
if (irMode == -1)
if (irPendingSize == -2)
{
QByteArray resp = socket->readAll();
if(resp.at(10) != '0')
@ -159,7 +187,7 @@ void ShimTCPController::parseCbmIr()
qWarning("Did not exit IR mode!");
qDebug() << "Response:" << resp;
}
irMode = 0;
irPendingSize = -1;
emit irDone();
}
else
@ -173,17 +201,28 @@ void ShimTCPController::parseCbmIr()
{
qWarning("irData->length() != msgLen | Expected on 2nd request - FIXME");
qDebug() << "msgLen:" << msgLen;
qDebug() << "actual:" << irData->length() - len_before;
qDebug() << "actual:" << irData->length() - len_before << " | TOTAL: " << irData->length();
}
if(check != 0x0)
// More Data if last request was maxed out
if(irData->length() - len_before == 1024)
{
cbmir(nullptr);
cbmir((quint8)irFileHandle);
return;
}
// Close File
else
{
irMode = -1;
socket->write("\x01\x00\x01\x00\x03\x00\x00\x00\x49\x43\x00", 11);
if (irPendingSize != 0)
{
qDebug() << "File Size Configured wrong! Still pending " << irPendingSize << " but got STOP!";
}
QByteArray data{"IC"};
char fh[1];
qToLittleEndian((quint8)irFileHandle, fh);
data.append(fh, 1);
cbmenc(&data);
writeData(&data);
irPendingSize = -2;
}
}
}
@ -243,11 +282,11 @@ ShimLCCommandStack::~ShimLCCommandStack()
}
uint32_t ShimLCCommandStack::addCmd(char opcode, QString cmd, QByteArray* dest)
uint32_t ShimLCCommandStack::addCmd(char opcode, QString cmd, QByteArray* dest, uint iSize)
{
qDebug() << TAG << "added cmd: Opcode:" << opcode << "Cmd:" << cmd;
id ++;
stackIn.push_back(ShimLCCmd{id, opcode, cmd, dest});
stackIn.push_back(ShimLCCmd{id, opcode, cmd, dest, iSize});
qDebug() << TAG << "Current size of cmd stack:" << stackIn.size();
if(busy_id == 0)
this->next();
@ -280,6 +319,7 @@ void ShimLCCommandStack::next()
void ShimLCCommandStack::newResult(QByteArray data)
{
bool ok = 0;
if(stackIn.first().dest != nullptr)
switch(stackIn.first().opcode)
{
case 'K':
@ -292,11 +332,15 @@ void ShimLCCommandStack::newResult(QByteArray data)
break;
case 'I':
if(data.mid(2,1).toInt(&ok) == 0 && ok)
connection.cbmir(stackIn.first().dest);
{
quint8 fileHandle = data.mid(4,1).toHex().toUInt(nullptr, 16);
connection.irPendingSize = stackIn.first().iSize;
connection.cbmir(fileHandle, stackIn.first().dest);
}
else
qWarning() << TAG << "Got invalid I command! Cmd, resp:" << stackIn.first().cmd << data;
stackIn.pop_front();
return;
return; // Return without dataAV!
}
stackIn.pop_front();
@ -319,11 +363,6 @@ uint32_t ShimLCCommandStack::getActVal(QString cmd, QByteArray* dest)
char opcode = 'M';
return addCmd(opcode, cmd, dest);
}
uint32_t ShimLCCommandStack::iCmd(QString cmd, QByteArray* dest)
{
char opcode = 'I';
return addCmd(opcode, cmd, dest);
}
void ShimLCCommandStack::reconnect(QSettings *settings)
{
@ -342,20 +381,28 @@ void ShimLCCommandStack::exitedIr()
next();
}
uint32_t ShimLCCommandStack::readFile(QString filename, QByteArray* dest, uint size)
{
dest->clear();
return addCmd('I', "OR "+filename, dest, size);
}
// -----------------------------------------------------------------------------------------------------------------------------
void ShimLCController::updateConfig()
{
connect(&cmd, &ShimLCCommandStack::dataAvailable, this, &ShimLCController::parseLcnf);
ids[ID_CONF] = cmd.iCmd("OR lcnf.", &data);
ids[ID_CONF] = cmd.readFile("lcnf.", &data, 4236);
//ids[ID_CONF] = cmd.iCmd("OR lcnf.", &data);
}
void ShimLCController::updateStatus()
{
connect(&cmd, &ShimLCCommandStack::dataAvailable, this, &ShimLCController::parseStatus);
ids[ID_STATUS] = cmd.iCmd("OR lmon.", &data);
ids[ID_STATUS] = cmd.readFile("lmon.", &data, 1575);
//ids[ID_STATUS] = cmd.iCmd("OR lmon.", &data);
}
void ShimLCController::reconnect(QSettings *settings)
@ -366,6 +413,10 @@ void ShimLCController::reconnect(QSettings *settings)
disconnect(&cmd, &ShimLCCommandStack::dataAvailable, this, &ShimLCController::parseLcnf);
disconnect(&cmd, &ShimLCCommandStack::dataAvailable, this, &ShimLCController::parseStatus);
// Reconnect done, clear to send new commands
cmd.setVal("AUXOPE 64", nullptr);
cmd.setVal("FIX.CH -1", nullptr);
cmd.setVal("SETCBM", nullptr);
cmd.setVal("LMONLVL=000000000L", nullptr);
}
ShimLCController::ShimLCController(QObject *parent)
@ -432,6 +483,10 @@ void ShimLCController::parseStatus(uint32_t idVal)
lastStatus.stats.status2 += data.mid(4+591+i,1).toHex().toUInt(nullptr, 16) << 8*i;
}
lastStatus.autosampler.rack = 0;
for(int i = 0; i<4; i++)
lastStatus.autosampler.rack += data.mid(49+i,1).toHex().toInt(nullptr, 16) << 8*i;
// --- PUMPS ---
// Pressure is at A: data[4:8], B: data[8:12], C:[12:16] encoded in int LE! Unit: wtf... Conversion was done via curve fitting!
@ -461,7 +516,7 @@ void ShimLCController::parseStatus(uint32_t idVal)
}
// --- AUTOSAMPLER ---
lastStatus.autosampler.rack = data.mid(382,1).toHex().toInt();
//lastStatus.autosampler.rack = data.mid(382,1).toHex().toUInt();
qDebug() << lastStatus.autosampler.rack;

View file

@ -12,6 +12,7 @@
#include <cmath>
#include <QAbstractSocket>
#include <QMessageBox>
#include <QtEndian>
struct ShimLCCmdStackResult
{
@ -27,8 +28,9 @@ class ShimTCPController : public QObject
{
Q_OBJECT
public:
int irPendingSize = -1;
void cbmquery(QString message);
void cbmir(QByteArray* irDataRet);
void cbmir(quint8 filehandle, QByteArray* irDataRet = nullptr);
explicit ShimTCPController(QObject *parent = 0);
~ShimTCPController();
@ -55,7 +57,7 @@ private:
QString TAG = "ShimTCPController";
QTcpSocket *socket;
QByteArray next_pkg{};
int irMode = 0;
int irFileHandle = -1;
QByteArray* irData = nullptr;
QByteArray* pendingData = nullptr;
};
@ -80,7 +82,7 @@ public:
uint32_t setVal(QString cmd, QByteArray *dest);
uint32_t getSetVal(QString cmd, QByteArray *dest);
uint32_t getActVal(QString cmd, QByteArray *dest);
uint32_t iCmd(QString cmd, QByteArray *dest);
uint32_t readFile(QString filename, QByteArray *dest, uint size);
void reconnect(QSettings *settings);
private:
@ -89,12 +91,13 @@ private:
using Connection = std::tuple<QObject*, const char*>;
struct ShimLCCmd
{
ShimLCCmd(uint32_t id, char opcode, QString cmd, QByteArray* dest)
: id(id), opcode(opcode), cmd(cmd), dest(dest) {}
ShimLCCmd(uint32_t id, char opcode, QString cmd, QByteArray* dest, uint32_t iSize)
: id(id), opcode(opcode), cmd(cmd), dest(dest), iSize(iSize) {}
uint32_t id;
char opcode;
QString cmd;
QByteArray* dest;
uint32_t iSize; // Only needed for I commands
};
ShimTCPController connection{};
QVector<ShimLCCmd> stackIn{};
@ -102,7 +105,7 @@ private:
uint32_t busy_id = 0;
void next();
uint32_t addCmd(char opcode, QString cmd, QByteArray* dest);
uint32_t addCmd(char opcode, QString cmd, QByteArray* dest, uint iSize = 0);
QObject* parent;
};

View file

@ -17,12 +17,16 @@ ViewDebugStatus::~ViewDebugStatus()
void ViewDebugStatus::updateStatus(LCStatus &status)
{
ui->listWidget->clear();
cur_stats.clear();
uint32_t i = 0;
ui->listWidget->addItem(QString(">> SILST = %1").arg(status.stats.silst));
foreach(QString itm, status.stats.silst_labels)
{
if(status.stats.silst & (0b1 << i))
{
ui->listWidget->addItem(QString("\t%1").arg(itm));
cur_stats.push_back(itm);
}
i++;
}
@ -31,7 +35,10 @@ void ViewDebugStatus::updateStatus(LCStatus &status)
foreach(QString itm, status.stats.status1_labels)
{
if(status.stats.status1 & (0b1 << i))
{
ui->listWidget->addItem(QString("\t%1").arg(itm));
cur_stats.push_back(itm);
}
i++;
}
@ -40,7 +47,10 @@ void ViewDebugStatus::updateStatus(LCStatus &status)
foreach(QString itm, status.stats.status2_labels)
{
if(status.stats.status2 & (0b1 << i))
{
ui->listWidget->addItem(QString("\t%1").arg(itm));
cur_stats.push_back(itm);
}
i++;
}

View file

@ -16,6 +16,7 @@ public:
explicit ViewDebugStatus(QWidget *parent = nullptr);
~ViewDebugStatus();
void updateStatus(LCStatus &status);
QStringList cur_stats{};
private:
Ui::ViewDebugStatus *ui;