|
|
|
@@ -6,6 +6,7 @@ import com.ffii.fpsms.modules.jobOrder.entity.JobOrder |
|
|
|
import com.ffii.fpsms.modules.jobOrder.entity.JobOrderRepository |
|
|
|
import com.ffii.fpsms.modules.jobOrder.web.model.LaserBag2SendRequest |
|
|
|
import com.ffii.fpsms.modules.jobOrder.web.model.LaserBag2SendResponse |
|
|
|
import com.ffii.fpsms.modules.jobOrder.web.model.LaserBag2MarkInfoResponse |
|
|
|
import com.ffii.fpsms.modules.jobOrder.web.model.LaserBag2SettingsResponse |
|
|
|
import com.ffii.fpsms.modules.jobOrder.web.model.LaserLastReceiveSuccessDto |
|
|
|
import com.ffii.fpsms.modules.jobOrder.web.model.PrintRequest |
|
|
|
@@ -351,6 +352,91 @@ class PlasticBagPrinterService( |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* TCP text queries on the same [LASER_PRINT] host/port as Bag2 send (UTF-8, line-terminated commands). |
|
|
|
* Uses one connection per command so the plugin can answer independently. |
|
|
|
*/ |
|
|
|
fun getLaserBag2MarkInfo(): LaserBag2MarkInfoResponse { |
|
|
|
val host = resolveLaserBag2Host() |
|
|
|
val port = resolveLaserBag2Port() |
|
|
|
val (dataVal, dataErr) = sendLaserBag2QueryCommand(host, port, "GetMarkData") |
|
|
|
val (statusVal, statusErr) = sendLaserBag2QueryCommand(host, port, "GetMarkStatus") |
|
|
|
val (countVal, countErr) = sendLaserBag2QueryCommand(host, port, "GetMarkedCount") |
|
|
|
val statusInt = statusVal?.let { parseFirstIntToken(it) } |
|
|
|
val countInt = countVal?.let { parseFirstIntToken(it) } |
|
|
|
val errs = listOfNotNull( |
|
|
|
dataErr?.let { "GetMarkData:$it" }, |
|
|
|
statusErr?.let { "GetMarkStatus:$it" }, |
|
|
|
countErr?.let { "GetMarkedCount:$it" }, |
|
|
|
) |
|
|
|
return LaserBag2MarkInfoResponse( |
|
|
|
host = host, |
|
|
|
port = port, |
|
|
|
markData = dataVal, |
|
|
|
markStatus = statusInt, |
|
|
|
markStatusLabel = markStatusToLabel(statusInt), |
|
|
|
markedCount = countInt, |
|
|
|
rawMarkStatus = statusVal, |
|
|
|
rawMarkedCount = countVal, |
|
|
|
error = errs.joinToString(";").ifBlank { null }, |
|
|
|
) |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Sends [command] as UTF-8 with LF, half-closes output, reads one response chunk (same pattern as job send ack read). |
|
|
|
* @return Pair(trimmed response or null, error message or null) |
|
|
|
*/ |
|
|
|
private fun sendLaserBag2QueryCommand(ip: String, port: Int, command: String): Pair<String?, String?> { |
|
|
|
var socket: Socket? = null |
|
|
|
try { |
|
|
|
socket = Socket() |
|
|
|
socket.soTimeout = 3000 |
|
|
|
socket.connect(InetSocketAddress(ip, port), 3000) |
|
|
|
val line = command.trim() + "\n" |
|
|
|
val out = socket.getOutputStream() |
|
|
|
out.write(line.toByteArray(StandardCharsets.UTF_8)) |
|
|
|
out.flush() |
|
|
|
try { |
|
|
|
socket.shutdownOutput() |
|
|
|
} catch (_: Exception) { |
|
|
|
} |
|
|
|
socket.soTimeout = 2500 |
|
|
|
val buf = ByteArray(8192) |
|
|
|
val n = socket.getInputStream().read(buf) |
|
|
|
val raw = if (n > 0) { |
|
|
|
String(buf, 0, n, StandardCharsets.UTF_8).trim() |
|
|
|
} else { |
|
|
|
"" |
|
|
|
} |
|
|
|
return raw to null |
|
|
|
} catch (e: ConnectException) { |
|
|
|
return null to "無法連線" |
|
|
|
} catch (e: SocketTimeoutException) { |
|
|
|
return null to "讀取逾時" |
|
|
|
} catch (e: Exception) { |
|
|
|
return null to (e.message ?: e.javaClass.simpleName) |
|
|
|
} finally { |
|
|
|
try { |
|
|
|
socket?.close() |
|
|
|
} catch (_: Exception) { |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
private fun parseFirstIntToken(text: String): Int? { |
|
|
|
val t = text.trim() |
|
|
|
if (t.isEmpty()) return null |
|
|
|
t.toIntOrNull()?.let { return it } |
|
|
|
return Regex("""-?\d+""").find(t)?.value?.toIntOrNull() |
|
|
|
} |
|
|
|
|
|
|
|
private fun markStatusToLabel(v: Int?): String? = when (v) { |
|
|
|
0 -> "待機" |
|
|
|
1 -> "打標中" |
|
|
|
2 -> "其他狀態" |
|
|
|
else -> null |
|
|
|
} |
|
|
|
|
|
|
|
fun generatePrintJobBundle( |
|
|
|
itemCode: String, |
|
|
|
lotNo: String, |
|
|
|
|