aboutsummaryrefslogtreecommitdiffstats
path: root/demo/Main.qml
blob: d234eaed849612a87718464dfbee14e35c9bd7d2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
pragma ComponentBehavior: Bound

import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import Xpl2

ApplicationWindow {
    id: root

    height: 600
    title: "XPL2 Demo"
    visible: true
    width: 800

    Connections {
        function onCommandSocketResponseReceived(response: string) {
            debugConsole.appendLog("Command: " + response);
            responseModel.append({
                                     text: "[Command] " + response
                                 });
        }

        function onConnectedChanged() {
            debugConsole.appendLog(Xpl2Client.connected ? "Connected" :
                                                          "Disconnected");
        }

        function onErrorOccurred(error: string) {
            debugConsole.appendLog("ERROR: " + error);
        }

        function onImagingSocketResponseReceived(response: string) {
            debugConsole.appendLog("Imaging: " + response);
            responseModel.append({
                                     text: "[Imaging] " + response
                                 });
        }

        function onStatusMessage(message: string) {
            debugConsole.appendLog(message);
        }

        function onStatusSocketResponseReceived(response: string) {
            debugConsole.appendLog("Status: " + response);
            responseModel.append({
                                     text: "[Status] " + response
                                 });
        }

        target: Xpl2Client
    }

    ColumnLayout {
        anchors.fill: parent
        spacing: 0

        ColumnLayout {
            Layout.fillHeight: true
            Layout.fillWidth: true
            Layout.margins: 16
            spacing: 12

            // --- Connection ---
            GroupBox {
                Layout.fillWidth: true
                title: "Connection"

                GridLayout {
                    anchors.fill: parent
                    columns: 2

                    Label {
                        text: "Host:"
                    }

                    TextField {
                        id: hostField

                        Layout.fillWidth: true
                        text: Xpl2Client.host

                        onEditingFinished: Xpl2Client.host = text
                    }

                    Label {
                        text: "Command port:"
                    }

                    TextField {
                        id: commandPortField

                        Layout.fillWidth: true
                        text: Xpl2Client.commandPort

                        validator: IntValidator {
                            bottom: 1
                            top: 65535
                        }

                        onEditingFinished: Xpl2Client.commandPort = parseInt(
                                               text)
                    }

                    Label {
                        text: "Imaging port:"
                    }

                    TextField {
                        id: imagingPortField

                        Layout.fillWidth: true
                        text: Xpl2Client.imagingPort

                        validator: IntValidator {
                            bottom: 1
                            top: 65535
                        }

                        onEditingFinished: Xpl2Client.imagingPort = parseInt(
                                               text)
                    }

                    Label {
                        text: "Status port:"
                    }

                    TextField {
                        id: statusPortField

                        Layout.fillWidth: true
                        text: Xpl2Client.statusPort

                        validator: IntValidator {
                            bottom: 1
                            top: 65535
                        }

                        onEditingFinished: Xpl2Client.statusPort = parseInt(
                                               text)
                    }

                    Button {
                        Layout.alignment: Qt.AlignRight
                        Layout.columnSpan: 2
                        text: Xpl2Client.connected ? "Disconnect" : "Connect"

                        onClicked: {
                            if (Xpl2Client.connected)
                            Xpl2Client.disconnectFromServer();
                            else
                            Xpl2Client.connectToServer();
                        }
                    }
                }
            }

            // --- Send Message ---
            GroupBox {
                Layout.fillWidth: true
                enabled: Xpl2Client.connected
                title: "Send"

                RowLayout {
                    anchors.fill: parent

                    ComboBox {
                        id: portCombo

                        model: ["Command", "Imaging", "Status"]
                    }

                    TextField {
                        id: cmdField

                        Layout.fillWidth: true
                        placeholderText: "Enter message…"

                        onAccepted: sendBtn.clicked()
                    }

                    Button {
                        id: sendBtn

                        text: "Send"

                        onClicked: {
                            if (cmdField.text.length === 0)
                            return;
                            if (portCombo.currentIndex === 0)
                            Xpl2Client.sendToCommandSocket(cmdField.text);
                            else if (portCombo.currentIndex === 1)
                            Xpl2Client.sendToImagingSocket(cmdField.text);
                            else
                            Xpl2Client.sendToStatusSocket(cmdField.text);
                            cmdField.text = "";
                        }
                    }
                }
            }

            // --- Responses ---
            GroupBox {
                Layout.fillHeight: true
                Layout.fillWidth: true
                title: "Responses"

                ListView {
                    id: responseView

                    anchors.fill: parent
                    clip: true

                    delegate: Text {
                        id: responseDelegate

                        required property string text

                        font.family: "monospace"
                        font.pixelSize: 13
                        text: responseDelegate.text
                        width: responseView.width
                        wrapMode: Text.Wrap
                    }
                    model: ListModel {
                        id: responseModel

                    }
                }
            }
        }

        // --- Debug Console ---
        Rectangle {
            id: debugConsole

            function appendLog(msg) {
                let ts = new Date().toLocaleTimeString(Qt.locale(), "HH:mm:ss");
                debugLog.text += "[" + ts + "] " + msg + "\n";
                debugLog.cursorPosition = debugLog.text.length;
            }

            Layout.fillWidth: true
            Layout.preferredHeight: 120
            border.color: "#444"
            color: "#1e1e1e"
            radius: 4

            ScrollView {
                anchors.fill: parent
                anchors.margins: 4

                TextArea {
                    id: debugLog

                    background: null
                    color: "#cccccc"
                    font.family: "monospace"
                    font.pointSize: 9
                    readOnly: true
                    wrapMode: TextEdit.Wrap
                }
            }
        }
    }
}
pan>Q_INVOKABLE void phSetJettingParams (int printheadId, int dutyCycle, int pwmFreq, int drive, int nozzleDriveFreq, int nozzleDriveDutyCycle); /** Get jetting parameters from one printhead. */ Q_INVOKABLE void phGetJettingParams (int printheadId); /** Save calibration for all printheads. */ Q_INVOKABLE void jcSaveCalibration (); /** Save calibration for one printhead. */ Q_INVOKABLE void phSaveCalibration (int printheadId); /** Reset calibration for all printheads. */ Q_INVOKABLE void jcResetCalibration (); /** Reset calibration for one printhead. */ Q_INVOKABLE void phResetCalibration (int printheadId); /** Set purge settings for all printheads on the controller. */ Q_INVOKABLE void jcSetPurgeSettings (int purgeIntervalMs, int purgeTimeMs); /** Switch off purge for all printheads on the controller. */ Q_INVOKABLE void jcSwitchOffPurge (); /** Set a JC setting by setter ID. */ Q_INVOKABLE void jcSetter (bool saveNewValue, int setterId, const QString &newValue); /** Set a PH setting by setter ID. */ Q_INVOKABLE void phSetter (int printheadId, bool saveNewValue, int setterId, const QString &newValue); /** Get a JC setting by getter ID. */ Q_INVOKABLE void jcGetter (bool getSavedValue, int getterId); /** Get a PH setting by getter ID. */ Q_INVOKABLE void phGetter (int printheadId, bool getSavedValue, int getterId); /** Reset settings for all printheads on the controller. */ Q_INVOKABLE void jcResetSettingsAllPrintheads (); /** Reset all settings for one printhead. */ Q_INVOKABLE void phResetAllSettings (int printheadId); /** Reboot all printheads on the controller. */ Q_INVOKABLE void jcRebootAllPrintheads (); /** Reboot one printhead. */ Q_INVOKABLE void phReboot (int printheadId); /** Reset the Jetting Controller software. */ Q_INVOKABLE void jcResetControllerSoftware (); /** Restart the Jetting Controller. */ Q_INVOKABLE void jcRestart (); /** Shut down the Jetting Controller. */ Q_INVOKABLE void jcShutdown (); /** Save settings for all printheads on the controller. */ Q_INVOKABLE void jcSaveAllPrintheadSettings (); /** Save settings for one printhead. */ Q_INVOKABLE void phSaveSettings (int printheadId); /* -- Imaging (m/n) commands --------------------------------------- */ /** Start imaging at the given speed. */ Q_INVOKABLE void imagingStart (double speed); /** Stop imaging. */ Q_INVOKABLE void imagingStop (); /** Send image mask start (front of formatted message, 180 chars). */ Q_INVOKABLE void imageMaskStart (const QString &mask); /** Send image mask end (triggers transmission to JC). */ Q_INVOKABLE void imageMaskEnd (const QString &tail); /** Send duty cycle mask start (hex, 2 chars per PH). */ Q_INVOKABLE void dutyCycleMaskStart (const QString &mask); /** Send duty cycle mask end (triggers transmission to JC). */ Q_INVOKABLE void dutyCycleMaskEnd (const QString &tail); /** Check remaining image line count. */ Q_INVOKABLE void imageCount (); signals: void listeningChanged (); void connectedChanged (); void errorOccurred (const QString &error); void statusMessage (const QString &message); void jcVersionReceived (); void phVersionReceived (int controllerId, int printheadId, const QString &mcuFirmwareVersion, const QString &mcuHardwareVersion, const QString &mcuFirmwareVariant, const QString &fpgaFirmwareVersion, const QString &fpgaHardwareVersion, const QString &bootloaderVersion); /* CN_ response signals */ void jettingAllOnResult (int controllerId, bool success); void jettingOnResult (int controllerId, bool success); void jettingOffResult (int controllerId, bool success); void phJettingOnResult (int controllerId, int printheadId, bool success); void phJettingOffResult (int controllerId, int printheadId, bool success); void jcIdLedOnResult (int controllerId, bool success); void jcIdLedOffResult (int controllerId, bool success); void phIdLedOnResult (int controllerId, int printheadId, bool success); void phIdLedOffResult (int controllerId, int printheadId, bool success); void jcCalibrationResult (int controllerId, bool success); void phCalibrationResult (int controllerId, int printheadId, bool success); void phCalibrationDataReceived (int controllerId, int printheadId, const QVariantList &frequencies); void phCalibrationRawDataReceived (int controllerId, int printheadId, const QVariantList &frequencies); void phCalibratedBaseFrequencyReceived (int controllerId, int printheadId, double baseFrequency, double activeBaseFrequency); void jcStatusMessagingStartResult (int controllerId, int statusLevel, int sendIntervalMs, bool success); void jcStatusMessagingStopResult (int controllerId, bool success); void phStatusMessagingStartResult (int controllerId, int statusLevel, int sendIntervalMs, bool success); void phStatusMessagingStopResult (int controllerId, bool success); void jcResetFaultCodesResult (int controllerId, bool success); void phResetFaultCodesResult (int controllerId, int printheadId, bool success); void phNozzlesDisabledResult (int controllerId, int printheadId, bool success); /* CF_ response signals */ void phSetIdResult (int controllerId, int printheadId, bool success); void phDeassignIdResult (int controllerId, bool success); void jcSetJettingParamsResult (int controllerId, int dutyCycle, int pwmFreq, int drive, int nozzleDriveFreq, int nozzleDriveDutyCycle, Xpl2Protocol::JettingParamsResult result); void phSetJettingParamsResult (int controllerId, int printheadId, int dutyCycle, int pwmFreq, int drive, int nozzleDriveFreq, int nozzleDriveDutyCycle, Xpl2Protocol::JettingParamsResult result); void phGetJettingParamsResult (int controllerId, int printheadId, int dutyCycle, int pwmFreq, int drive, int nozzleDriveFreq, int nozzleDriveDutyCycle, Xpl2Protocol::JettingParamsResult result); void jcSaveCalibrationResult (int controllerId, bool success); void phSaveCalibrationResult (int controllerId, int printheadId, bool success); void jcResetCalibrationResult (int controllerId, bool success); void phResetCalibrationResult (int controllerId, int printheadId, bool success); void jcSetPurgeSettingsResult (int controllerId, int purgeIntervalMs, int purgeTimeMs, bool success); void jcSwitchOffPurgeResult (int controllerId, bool success); void jcSetterResult (int controllerId, bool saveNewValue, int setterId, const QString &newValue, Xpl2Protocol::SetterResult result); void phSetterResult (int controllerId, int printheadId, bool saveNewValue, int setterId, const QString &newValue, Xpl2Protocol::SetterResult result); void jcGetterResult (int controllerId, bool savedValue, int getterId, const QString &currentValue, bool success); void phGetterResult (int controllerId, int printheadId, bool savedValue, int getterId, const QString &currentValue, bool success); void jcResetSettingsAllPrintheadsResult (int controllerId, bool success); void phResetAllSettingsResult (int controllerId, int printheadId, bool success); void jcRebootAllPrintheadsResult (int controllerId, bool success); void phRebootResult (int controllerId, int printheadId, bool success); void jcResetControllerSoftwareResult (int controllerId, bool success); void jcRestartResult (int controllerId, bool success); void jcShutdownResult (int controllerId, bool success); void jcSaveAllPrintheadSettingsResult (int controllerId, bool success); void phSaveSettingsResult (int controllerId, int printheadId, bool success); /* EV_ event signals */ void shuttingDown (); void phConnectionChanged (int controllerId, int printheadId, bool connected); void jcErrorCode (int controllerId, int errorCode, const QStringList &params); void phErrorCode (int controllerId, int printheadId, int errorCode, const QStringList &params); void imgErrorCode (int controllerId, int errorCode, const QStringList &params); void statusErrorCode (int controllerId, int errorCode, const QStringList &params); void jcStatusReceived (const Xpl2JcStatus &status); void phStatusReceived (const Xpl2PhStatus &status); /* Imaging response signals */ void imagingReply (int imageLines); void imagingStopResult (bool success); private slots: void onNewConnection (); void onSocketDisconnected (); void onSocketMessageReady (); void onSocketError (QAbstractSocket::SocketError error); private: void setupServer (QTcpServer &server, quint16 port); QTcpSocket *&socketForServer (QTcpServer *server); void sendCommand (QTcpSocket *socket, const QByteArray &command, const QVariantList &params = {}); void dispatchCommandMessage (const Xpl2Protocol::ParsedMessage &msg); void dispatchImagingMessage (const Xpl2Protocol::ParsedMessage &msg); void dispatchStatusMessage (const Xpl2Protocol::ParsedMessage &msg); void handleKaPing (QTcpSocket *socket); void handleGsJcVersion (const QVariantList &params); void handleGsPhVersion (const QVariantList &params); enum class ResponseShape { JcSuccess, PhSuccess, CalData, BaseFreq, StatusStart, PurgeSettings, JcJettingParams, PhJettingParams, JcSetter, PhSetter, JcGetter, PhGetter, PhConnectionChanged, ErrorCode, PhErrorCode }; struct ResponseEntry { ResponseShape shape; int minParams; std::function<void (Xpl2Client *, const QVariantList &)> emitter; }; static const QHash<QByteArray, ResponseEntry> s_responseTable; bool dispatchResponse (const QByteArray &command, const QVariantList &params, const QTcpSocket *socket); void handleEvStatusMsgJc (const QVariantList &params); void handleEvStatusMsgPh (const QVariantList &params); void updateConnectedState (); QString logTag (const QTcpSocket *socket) const; QTcpServer m_commandServer; QTcpServer m_imagingServer; QTcpServer m_statusServer; QTcpSocket *m_commandSocket = nullptr; QTcpSocket *m_imagingSocket = nullptr; QTcpSocket *m_statusSocket = nullptr; quint16 m_commandPort = 9110; quint16 m_imagingPort = 9111; quint16 m_statusPort = 9112; bool m_listening = false; bool m_connected = false; static bool s_wireDebug; int m_controllerId = 0; QString m_firmwareVersion; QString m_hardwareVersion; int m_printheadCount = 0; };