chore: upload current WMS changes

This commit is contained in:
zgw
2026-07-24 08:51:42 +08:00
parent 3789aa6420
commit 98db537218
408 changed files with 91747 additions and 2107 deletions

View File

@@ -0,0 +1,120 @@
package com.ruoyi.Dzp;
import com.ruoyi.Dzp.domain.basLed;
import com.ruoyi.Dzp.mapper.BasLedMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.io.IOException;
import java.util.List;
@RestController
@RequestMapping("/api2dzp")
public class DzpSend {
@Autowired
private BasLedMapper mapper;
@Scheduled(fixedDelay = 1000)
public void InLed() throws IOException {
basLed basLed = new basLed();
basLed.setSendFlag("0");
basLed.setId(1);
List<com.ruoyi.Dzp.domain.basLed> basLeds = mapper.selectBasLedList(basLed);
if (basLeds != null && basLeds.size() > 0 && (basLeds.get(0).getModel().equals("1") || basLeds.get(0).getModel().equals("2"))) {
MyUdpSocket myUdpSocket = new MyUdpSocket(6666);
ProtocolDemo.my_udp = myUdpSocket;
String ip = basLeds.get(0).getIpAddress();
String msgProductTitle = "物资编码:";
String msgProduct = basLeds.get(0).getProduct_id();
String msgSpecTitle = "物资规格:";
String msgSpec = basLeds.get(0).getSpec();
String msg3 = "托盘条码:" + basLeds.get(0).getTrayCode();
String msg4 = null;
if (basLeds.get(0).getModel().equals("1")) {
msg4 = "入库数量:";
} else {
msg4 = "出库数量:";
}
String ms7 = "物资名称:";
String msg8 = basLeds.get(0).getProductName();
String msgQuantity = basLeds.get(0).getQuantity();
if (ProtocolDemo.demo_play_chapterschedule4(ip, msgProductTitle, msgSpecTitle, msg4, msg3, msgSpec, msgProduct, ms7, msg8, msgQuantity)) {
basLeds.get(0).setSendFlag("1");
mapper.updateBasLed(basLeds.get(0));
}
myUdpSocket.close();
}
basLed basLed2 = new basLed();
basLed2.setSendFlag("0");
basLed2.setId(2);
List<com.ruoyi.Dzp.domain.basLed> basLeds2 = mapper.selectBasLedList(basLed2);
if (basLeds2 != null && basLeds2.size() > 0 && (basLeds2.get(0).getModel().equals("1") || basLeds2.get(0).getModel().equals("2"))) {
MyUdpSocket myUdpSocket = new MyUdpSocket(6666);
ProtocolDemo.my_udp = myUdpSocket;
String ip = basLeds2.get(0).getIpAddress();
String msgProductTitle = "物资编码:";
String msgProduct = basLeds2.get(0).getProduct_id();
String msgSpecTitle = "物资规格:";
String msgSpec = basLeds2.get(0).getSpec();
String msg3 = "托盘条码:" + basLeds2.get(0).getTrayCode();
String msg4 = null;
if (basLeds2.get(0).getModel().equals("1")) {
msg4 = "入库数量:";
} else {
msg4 = "出库数量:";
}
String ms7 = "物资名称:";
String msg8 = basLeds2.get(0).getProductName();
String msgQuantity = basLeds2.get(0).getQuantity();
if (ProtocolDemo.demo_play_chapterschedule4(ip, msgProductTitle, msgSpecTitle, msg4, msg3, msgSpec, msgProduct, ms7, msg8, msgQuantity)) {
basLeds2.get(0).setSendFlag("1");
mapper.updateBasLed(basLeds2.get(0));
}
myUdpSocket.close();
}
}
@Scheduled(fixedDelay = 1000)
public void ErrorLed() throws IOException {
basLed basLed = new basLed();
basLed.setSendFlag("0");
basLed.setId(1);
List<com.ruoyi.Dzp.domain.basLed> basLeds = mapper.selectBasLedList(basLed);
if (basLeds != null && basLeds.size() > 0 && basLeds.get(0).getModel().equals("3")) {
MyUdpSocket myUdpSocket = new MyUdpSocket(6666);
ProtocolDemo.my_udp = myUdpSocket;
String ip = basLeds.get(0).getIpAddress();
if (ProtocolDemo.demo_play_chapterschedule2(ip, "报警信息", basLeds.get(0).getErrorMsg())) {
basLeds.get(0).setSendFlag("1");
mapper.updateBasLed(basLeds.get(0));
}
myUdpSocket.close();
}
basLed basLed2 = new basLed();
basLed2.setSendFlag("0");
basLed2.setId(2);
List<com.ruoyi.Dzp.domain.basLed> basLeds2 = mapper.selectBasLedList(basLed2);
if (basLeds2 != null && basLeds2.size() > 0 && basLeds2.get(0).getModel().equals("3")) {
MyUdpSocket myUdpSocket = new MyUdpSocket(6666);
ProtocolDemo.my_udp = myUdpSocket;
String ip = basLeds2.get(0).getIpAddress();
if (ProtocolDemo.demo_play_chapterschedule2(ip, "报警信息", basLeds2.get(0).getErrorMsg())) {
basLeds2.get(0).setSendFlag("1");
mapper.updateBasLed(basLeds2.get(0));
}
myUdpSocket.close();
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,164 @@
package com.ruoyi.Dzp;
public class Lzss {
static int N = 4096;
static int F = 18;
static int THRESHOLD = 2;
static int NIL = N;
static int textsize = 0;
static int codesize = 0;
static int printcount = 0;
static int text_buf[];
static int match_position, match_length;
static int lson[], rson[], dad[];
public Lzss() {
lson = new int[N + 1];
rson = new int[N + 257];
dad = new int[N + 1];
text_buf = new int[N + F - 1];
}
private static void InitTree() /* initialize trees */
{
int i;
textsize = 0; codesize = 0; printcount = 0;
for (i = N + 1; i <= N + 256; i++) rson[i] = NIL;
for (i = 0; i < N; i++) dad[i] = NIL;
}
private static void InsertNode(int r)
{
int i, p, cmp;
//unsigned char *key;
//key = &text_buf[r];
cmp = 1; p = N + 1 + text_buf[r];
rson[r] = NIL; lson[r] = NIL; match_length = 0;
for ( ; ; ) {
if (cmp >= 0) {
if (rson[p] != NIL) p = rson[p];
else { rson[p] = r; dad[r] = p; return; }
} else {
if (lson[p] != NIL) p = lson[p];
else { lson[p] = r; dad[r] = p; return; }
}
for (i = 1; i < F; i++)
if ((cmp = text_buf[r + i] - text_buf[p + i]) != 0) break;
if (i > match_length) {
match_position = p;
if ((match_length = i) >= F) break;
}
}
dad[r] = dad[p]; lson[r] = lson[p]; rson[r] = rson[p];
dad[lson[p]] = r; dad[rson[p]] = r;
if (rson[dad[p]] == p) rson[dad[p]] = r;
else lson[dad[p]] = r;
dad[p] = NIL;
}
private static void DeleteNode(int p)
{
int q;
if (dad[p] == NIL) return;
if (rson[p] == NIL) q = lson[p];
else if (lson[p] == NIL) q = rson[p];
else {
q = lson[p];
if (rson[q] != NIL) {
do { q = rson[q]; } while (rson[q] != NIL);
rson[dad[q]] = lson[q]; dad[lson[q]] = dad[q];
lson[q] = lson[p]; dad[lson[p]] = q;
}
rson[q] = rson[p]; dad[rson[p]] = q;
}
dad[q] = dad[p];
if (rson[dad[p]] == p) rson[dad[p]] = q; else lson[dad[p]] = q;
dad[p] = NIL;
}
public int Encode(byte[] ibuf, int istart, int isize, byte[] obuf, int ostart)
{
int i, c, len, r, s, last_match_length, code_buf_ptr;
int[] code_buf = new int[17];
int mask;
int x, x1;
x=x1=0;
InitTree();
code_buf[0] = 0;
code_buf_ptr = mask = 1;
s = 0; r = N - F;
for (i = s; i < r; i++) text_buf[i] = ' ';
for (len = 0, c = 0; len < F && c < isize; len++, c++)
{
if (ibuf[istart + x] >= 0)
text_buf[r + len] = ibuf[istart + x];
else
text_buf[r + len] = 0x100 + ibuf[istart + x];
x++;
}
if ((textsize = len) == 0) return 0;
for (i = 1; i <= F; i++) InsertNode(r - i);
InsertNode(r);
do {
if (match_length > len) match_length = len;
if (match_length <= THRESHOLD) {
match_length = 1;
code_buf[0] |= mask;
code_buf[code_buf_ptr++] = text_buf[r];
} else {
code_buf[code_buf_ptr++] = match_position & 0xff;
code_buf[code_buf_ptr++] = ((((match_position >> 4) & 0xf0) | (match_length - (THRESHOLD + 1))) & 0xff);
}
mask <<= 1;
mask &= 0xff;
if (mask == 0) {
if (codesize + code_buf_ptr > isize) return 0;
for (i = 0; i < code_buf_ptr; i++)
{
obuf[ostart + x1] = (byte)code_buf[i];
x1++;
}
codesize += code_buf_ptr;
code_buf[0] = 0; code_buf_ptr = mask = 1;
}
last_match_length = match_length;
for (i = 0; i < last_match_length && c < isize; i++, c++) {
DeleteNode(s); /* Delete old strings and */
if (ibuf[istart + x] >= 0)
text_buf[s] = ibuf[istart + x];
else
text_buf[s] = 0x100 + ibuf[istart + x];
if (s < F - 1)
{
if (ibuf[istart + x] >= 0)
text_buf[s + N] = ibuf[istart + x];
else
text_buf[s + N] = 0x100 + ibuf[istart + x];
}
s = (s + 1) & (N - 1); r = (r + 1) & (N - 1);
InsertNode(r); /* Register the string in text_buf[r..r+F-1] */
x++;
}
while (i++ < last_match_length) {
DeleteNode(s);
s = (s + 1) & (N - 1); r = (r + 1) & (N - 1);
len--;
if (len > 0) InsertNode(r);
}
} while (len > 0);
if (code_buf_ptr > 1) {
for (i = 0; i < code_buf_ptr; i++)
{
obuf[ostart + x1] = (byte)(code_buf[i]&0xff);
x1++;
}
codesize += code_buf_ptr;
}
return x1;
}
}

View File

@@ -0,0 +1,93 @@
package com.ruoyi.Dzp;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.DatagramChannel;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.util.Set;
public class MyUdpSocket {
private DatagramChannel channel;
private Selector selector;
private final int MAX_SIZE = 1280;
private static int client_port;
private static String client_ip;
ByteBuffer receive_buffer = ByteBuffer.allocate(MAX_SIZE);
public MyUdpSocket(int port) throws IOException {
channel = DatagramChannel.open();
selector = Selector.open();
try {
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͨ<EFBFBD><CDA8>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģʽ
channel.configureBlocking(false);
//<2F><>ȡ<EFBFBD><C8A1><EFBFBD>׽<EFBFBD><D7BD><EFBFBD>ͨ<EFBFBD><CDA8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>׽<EFBFBD><D7BD>֣<EFBFBD><D6A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>׽<EFBFBD><D7BD>ְ󶨵<D6B0><F3B6A8B5><EFBFBD><EFBFBD><EFBFBD>ָ<EFBFBD><D6B8><EFBFBD>˿<EFBFBD>
channel.socket().bind(new InetSocketAddress(port));
//Ϊͨ<CEAA><CDA8>ѡ<EFBFBD><D1A1><EFBFBD><EFBFBD>ע<EFBFBD><D7A2>ͨ<EFBFBD><CDA8><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ָ<EFBFBD><D6B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѡ<EFBFBD><D1A1><EFBFBD><EFBFBD><EFBFBD>
channel.register(selector, SelectionKey.OP_READ);
} catch (IOException e) {
e.printStackTrace();
}
}
public final void send(String ip, int port, byte[] buffer, int size) throws IOException {
InetSocketAddress client = new InetSocketAddress(ip, port);
channel.send(ByteBuffer.wrap(buffer, 0, size), client); //<2F><>EchoClient<6E>ظ<EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD>ݱ<EFBFBD>
}
public final void close() throws IOException {
selector.close();
channel.close();
}
public final int get_client_port() {
return client_port;
}
public final String get_client_ip() {
return client_ip;
}
public final void get_receive_buffer(byte[] buffer) {
receive_buffer.get(buffer);
}
public final int receive() {
try {
receive_buffer.clear();
if (selector.select(10) != 0) {
Set<SelectionKey> readyKeys = selector.selectedKeys();
for (SelectionKey key : readyKeys) {
readyKeys.remove(key);
if (key.isReadable()) {
DatagramChannel dc = (DatagramChannel) key.channel();
InetSocketAddress client = (InetSocketAddress) dc.receive(receive_buffer); //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB>Client<6E><74><EFBFBD><EFBFBD><EFBFBD>ݱ<EFBFBD>
if (client != null) {
client_ip = client.getAddress().getHostAddress();
client_port = client.getPort();
//System.out.println(client_ip+":"+client_port+" size="+receive_buffer.position());
key.interestOps(SelectionKey.OP_READ);
return receive_buffer.position();
} else {
return 0;
}
} else {
return 0;
}
}
}
} catch (IOException e) {
e.printStackTrace();
}
return 0;
}
public final void get_receive_packet(byte[] packet, int size) {
int i;
for (i = 0; i < size; i++) {
packet[i] = receive_buffer.array()[i];
}
}
}

View File

@@ -0,0 +1,995 @@
package com.ruoyi.Dzp;
import java.awt.*;
//import java.util.Calendar;
public class ProtocolDemo {
// ====<3D><><EFBFBD>붯<EFBFBD><EBB6AF><EFBFBD><EFBFBD>ʽ<EFBFBD>б<EFBFBD>(<28><>ֵ<EFBFBD><D6B5>0<EFBFBD><30>ʼ)====
// 0 = '<27><><EFBFBD>',
// 1 = '<27><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʾ',
// 2 = '<27><><EFBFBD><EFBFBD><EFBFBD>ʾ',
// 3 = '<27>Ϲ<EFBFBD><CFB9><EFBFBD>ʾ',
// 4 = '<27>ҹ<EFBFBD><D2B9><EFBFBD>ʾ',
// 5 = '<27>¹<EFBFBD><C2B9><EFBFBD>ʾ',
// 6 = '<27><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʾ',
// 7 = '<27><><EFBFBD><EFBFBD><EFBFBD>Ϲ<EFBFBD><CFB9><EFBFBD>ʾ',
// 8 = '<27><><EFBFBD><EFBFBD><EFBFBD>ҹ<EFBFBD>',
// 9 = '<27><><EFBFBD><EFBFBD><EFBFBD>¹<EFBFBD>',
// 10 = '<27>м<EFBFBD><D0BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>չ<EFBFBD><D5B9>',
// 11 = '<27>м<EFBFBD><D0BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>չ<EFBFBD><D5B9>',
// 12 = '<27>м<EFBFBD><D0BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>չ<EFBFBD><D5B9>',
// 13 = '<27><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>',
// 14 = '<27><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>',
// 15 = '<27><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>չ<EFBFBD><D5B9>',
// 16 = '<27><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>չ<EFBFBD><D5B9>',
// 17 = '<27><><EFBFBD><EFBFBD><EFBFBD>Ͻ<EFBFBD><CFBD><EFBFBD><EFBFBD><EFBFBD>',
// 18 = '<27><><EFBFBD><EFBFBD><EFBFBD>½<EFBFBD><C2BD><EFBFBD><EFBFBD><EFBFBD>',
// 19 = '<27><><EFBFBD><EFBFBD><EFBFBD>Ͻ<EFBFBD><CFBD><EFBFBD><EFBFBD><EFBFBD>',
// 20 = '<27><><EFBFBD><EFBFBD><EFBFBD>½<EFBFBD><C2BD><EFBFBD><EFBFBD><EFBFBD>',
// 21 = '<27><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>',
// 22 = '<27><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>',
// 23 = '<27><><EFBFBD><EFBFBD><EFBFBD>Ҷ<EFBFBD><D2B6>',
// 24 = '<27><><EFBFBD><EFBFBD><EFBFBD>Ҷ<EFBFBD><D2B6>',
// =====================================
// ====<3D><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʽ<EFBFBD>б<EFBFBD>(<28><>ֵ<EFBFBD><D6B5>0<EFBFBD><30>ʼ)====
// 0 = '<27><><EFBFBD>',
// 1 = '<27><><EFBFBD><EFBFBD>ʧ',
// 2 = '<27><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʧ',
// 3 = '<27><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>м<EFBFBD><D0BC>£',
// 4 = '<27><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>м<EFBFBD><D0BC>£',
// 5 = '<27><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>м<EFBFBD><D0BC>£',
// 6 = '<27><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƴ<EFBFBD>',
// 7 = '<27><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƴ<EFBFBD>',
// 8 = '<27><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>£',
// 9 = '<27><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Һ<EFBFBD>£',
// 10 = '<27><><EFBFBD><EFBFBD><EFBFBD>Ͻ<EFBFBD><CFBD>Ƴ<EFBFBD>',
// 11 = '<27><><EFBFBD><EFBFBD><EFBFBD>½<EFBFBD><C2BD>Ƴ<EFBFBD>',
// 12 = '<27><><EFBFBD><EFBFBD><EFBFBD>Ͻ<EFBFBD><CFBD>Ƴ<EFBFBD>',
// 13 = '<27><><EFBFBD><EFBFBD><EFBFBD>½<EFBFBD><C2BD>Ƴ<EFBFBD>',
// 14 = '<27><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƴ<EFBFBD>',
// 15 = '<27><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƴ<EFBFBD>',
// 16 = '<27><><EFBFBD><EFBFBD><EFBFBD>Ҷ<EFBFBD><D2B6>',
// 17 = '<27><><EFBFBD><EFBFBD><EFBFBD>Ҷ<EFBFBD><D2B6>'
// =====================================
// ====ͣ<><CDA3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʽ<EFBFBD>б<EFBFBD>(<28><>ֵ<EFBFBD><D6B5>0<EFBFBD><30>ʼ)====
// 0 = '<27><>̬<EFBFBD><CCAC>ʾ',
// 1 = '<27><>˸<EFBFBD><CBB8>ʾ'
// =====================================
public static MyUdpSocket my_udp;
public static LEDSender2010 ledsender = new LEDSender2010();
//public static String ledhost = "127.0.0.1";
public static String ledhost = "10.170.23.237";
public static int ledport = 6666;
public static int addr = 0;
public static void mysleep(int msec) {
try {
Thread.sleep(msec);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//<2F><><EFBFBD><EFBFBD>UDP<44><50><EFBFBD><EFBFBD>bufferΪ<72><CEAA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݣ<EFBFBD>sizeΪ<65><CEAA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݳ<EFBFBD><DDB3><EFBFBD>
public static void udp_send(byte[] buffer, int size) {
byte[] packet = new byte[size];
ledsender.blockCopy(packet, 0, buffer, 0, size);
ledsender.print_stream(packet, size);
try {
my_udp.send(ledhost, ledport, packet, size);
} catch (Exception ex) {
ex.printStackTrace();
}
}
public static void udp_send1(String ip, byte[] buffer, int size) {
byte[] packet = new byte[size];
ledsender.blockCopy(packet, 0, buffer, 0, size);
ledsender.print_stream(packet, size);
try {
my_udp.send(ip, ledport, packet, size);
} catch (Exception ex) {
ex.printStackTrace();
}
}
//<2F><><EFBFBD><EFBFBD>UDP<44><50><EFBFBD><EFBFBD>bufferΪ<72><CEAA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݣ<EFBFBD>sizeΪ<65><CEAA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݳ<EFBFBD><DDB3><EFBFBD>
public static int udp_receive(byte[] buffer) {
int size = 0;
size = my_udp.receive();
if (size > 0) {
my_udp.get_receive_packet(buffer, size);
}
return size;
}
public static int do_command(byte[] buffer, int size) {
byte[] packet = new byte[1280];
int tx, tx_repeat = 5;
int isize = 0;
int i;
for (tx = 0; tx < tx_repeat; tx++) {
udp_send(buffer, size);
for (i = 0; i < 50; i++) {
isize = udp_receive(packet);
if (isize > 0 && ledsender.parse_cmd_respond(packet, isize) == 1) {
return 1;
}
}
}
System.out.println("<EFBFBD><EFBFBD>ʱ");
return 0;
}
public static void demo_reset_display() {
int size;
byte[] packet = new byte[1280];
size = ledsender.pkg_reset_display(packet, (byte) addr, 1);
System.out.println("<EFBFBD><EFBFBD>λ<EFBFBD><EFBFBD>Ŀ<EFBFBD><EFBFBD>ʾ...");
do_command(packet, size);
}
public static void demo_power_on() {
int size;
byte[] packet = new byte[1280];
size = ledsender.pkg_set_power(packet, (byte) addr, 1);
System.out.println("<EFBFBD>򿪵<EFBFBD>Դ...");
do_command(packet, size);
}
public static void demo_power_off() {
int size;
byte[] packet = new byte[1280];
size = ledsender.pkg_set_power(packet, (byte) addr, 0);
System.out.println("<EFBFBD>رյ<EFBFBD>Դ...");
do_command(packet, size);
}
public static void demo_get_power() {
int size;
byte[] packet = new byte[1280];
size = ledsender.pkg_get_power(packet, (byte) addr);
System.out.println("<EFBFBD><EFBFBD>ȡ<EFBFBD><EFBFBD>Դ״̬...");
do_command(packet, size);
}
public static void demo_set_bright() {
int size;
byte[] packet = new byte[1280];
size = ledsender.pkg_set_bright(packet, (byte) addr, 7);
System.out.println("<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>...");
do_command(packet, size);
}
public static void demo_get_bright() {
int size;
byte[] packet = new byte[1280];
size = ledsender.pkg_get_bright(packet, (byte) addr);
System.out.println("<EFBFBD><EFBFBD>ȡ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>...");
do_command(packet, size);
}
public static void demo_adjust_time() {
int size;
byte[] packet = new byte[1280];
//Calendar calendar = Calendar.getInstance();
//ָ<><D6B8>ʱ<EFBFBD><CAB1>Уʱ<D0A3><CAB1>12Сʱ<D0A1><CAB1>
//size=ledsender.pkg_adjust_time_ex(packet, (byte)addr, calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH)+1, calendar.get(Calendar.DAY_OF_WEEK)-1, calendar.get(Calendar.DAY_OF_MONTH), calendar.get(Calendar.HOUR), calendar.get(Calendar.MINUTE), calendar.get(Calendar.SECOND));
//ָ<><D6B8>ʱ<EFBFBD><CAB1>Уʱ<D0A3><CAB1>24Сʱ<D0A1><CAB1>
//size=ledsender.pkg_adjust_time_ex(packet, (byte)addr, calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH)+1, calendar.get(Calendar.DAY_OF_WEEK)-1, calendar.get(Calendar.DAY_OF_MONTH), calendar.get(Calendar.HOUR_OF_DAY), calendar.get(Calendar.MINUTE), calendar.get(Calendar.SECOND));
//<2F>Ե<EFBFBD>ǰϵͳʱ<CDB3><CAB1>Уʱ
size = ledsender.pkg_adjust_time(packet, (byte) addr);
System.out.println("У<EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD>...");
do_command(packet, size);
}
public static void demo_switch_on() {
int size;
byte[] packet = new byte[1280];
size = ledsender.pkg_set_switch(packet, (byte) addr, 1);
System.out.println("<EFBFBD><EFBFBD><EFBFBD><EFBFBD>5V<EFBFBD><EFBFBD><EFBFBD>...");
do_command(packet, size);
}
public static void demo_switch_off() {
int size;
byte[] packet = new byte[1280];
size = ledsender.pkg_set_switch(packet, (byte) addr, 0);
System.out.println("<EFBFBD>ر<EFBFBD>5V<EFBFBD><EFBFBD><EFBFBD>...");
do_command(packet, size);
}
public static void demo_get_boardparam() {
int size;
byte[] packet = new byte[1280];
size = ledsender.pkg_get_boardparam(packet, (byte) addr);
System.out.println("<EFBFBD><EFBFBD>ȡ<EFBFBD><EFBFBD><EFBFBD>ƿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>...");
do_command(packet, size);
}
public static void demo_set_boardparam_ip(String ip) {
int size;
byte[] packet = new byte[1280];
byte[] ips = new byte[4];
int i, k, k1, x;
size = ledsender.pkg_get_boardparam(packet, (byte) addr);
System.out.println("<EFBFBD><EFBFBD>ȡ<EFBFBD><EFBFBD><EFBFBD>ƿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>...");
if (do_command(packet, size) == 1) {
k = 0;
x = 0;
ip = ip + '.';
for (i = 0; i < 4; i++) {
k1 = ip.indexOf('.', k);
if (k1 > k) {
ips[i] = (byte) Integer.parseInt(ip.substring(k, k1));
k = k1 + 1;
x++;
}
}
if (x == 4) {
size = ledsender.pkg_set_boardparam_ip(packet, (byte) addr, ips);
if (size > 0) {
do_command(packet, size);
}
}
}
}
public static void demo_power_schedule() {
int size;
byte[] packet = new byte[1280];
//<2F><>һ<EFBFBD><D2BB>7<EFBFBD><37>ÿ<EFBFBD>ն<EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ÿ<EFBFBD>տ<EFBFBD><D5BF>Զ<EFBFBD><D4B6><EFBFBD>3<EFBFBD><33>ʱ<EFBFBD><CAB1>
size = ledsender.pkg_power_schedule_weekday(packet, (byte) addr, true);
//<2F><>ָ<EFBFBD><D6B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֹ<EFBFBD><D6B9><EFBFBD><EFBFBD>ʱ<EFBFBD>䲥<EFBFBD>ţ<EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD>Զ<EFBFBD><D4B6><EFBFBD>21<32><31>ʱ<EFBFBD><CAB1>
//size=ledsender.pkg_power_schedule_period(packet, (byte)addr, true);
System.out.println("<EFBFBD><EFBFBD><EFBFBD>ö<EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ƻ<EFBFBD>...");
do_command(packet, size);
}
//dib_bufferΪ<72><CEAA><EFBFBD><EFBFBD>ͼƬ<CDBC><C6AC>RGB<47><42><EFBFBD>飬<EFBFBD><E9A3AC><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>飬<EFBFBD><E9A3AC><EFBFBD><EFBFBD><EFBFBD>ÿ<EFBFBD><C3BF><EFBFBD><EFBFBD>Ԫ<EFBFBD><D4AA><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD>ص<EFBFBD><D8B5>RGBֵ
// <20><><EFBFBD>ص<EFBFBD>(X,Y)<29><>RGBֵ<42><D6B5><EFBFBD><EFBFBD>һ<EFBFBD><D2BB>һ<EFBFBD><D2BB>˳<EFBFBD><CBB3><EFBFBD><EFBFBD><EFBFBD>У<EFBFBD><D0A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD>64<36><34><EFBFBD><EFBFBD>32<33><32><EFBFBD><EFBFBD>
// (0,0),(0,1),(0,2),...(0,31) (1,0),(1,1),(1,2),...(1,31) (2,0),(2,1),(2,2),...(2,31) ... (63,0),(63,1),(63,2),...(63,31)
// <20><><EFBFBD>ص<EFBFBD><D8B5>RGBֵ<42><D6B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʾ<EFBFBD><CABE>0-7λ<37><CEBB>ʾ<EFBFBD><CABE>ɫ<EFBFBD><C9AB>8-15λ<35><CEBB>ʾ<EFBFBD><CABE>ɫ<EFBFBD><C9AB>16-23<32><33>ʾ<EFBFBD><CABE>ɫ<EFBFBD><C9AB>24-31λ<31><CEBB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>0
// <20><><EFBFBD><EFBFBD>dib_buffer[n]&0xFF <20><>ʾ<EFBFBD><CABE>ɫ
// (dib_buffer[n]>>8)&0xFF <20><>ʾ<EFBFBD><CABE>ɫ
// (dib_buffer[n]>>16)&0xFF <20><>ʾ<EFBFBD><CABE>ɫ
public static int dib_width = 64;
public static int dib_height = 64;
public static int dib_buffer_size = dib_width * dib_height;
public static int[] dib_buffer = new int[dib_buffer_size];
public static void draw_dib() {
int x, y, z = 0;
int seek = 0;
int color = 0xFF;
for (x = 0; x < dib_width; x++) {
for (y = 0; y < dib_height; y++) {
dib_buffer[seek++] = color;
}
z++;
if (z >= 4) {
switch (color) {
case 0xFF:
color = 0xFF00;
break;
case 0xFF00:
color = 0xFFFF;
break;
case 0xFFFF:
color = 0xFF;
break;
default:
color = 0xFF;
break;
}
z = 0;
}
}
}
public static void send_data() {
int size = 0;
byte[] packet = new byte[1280];
int i, j, k, x, r;
int tx, tx_repeat = 5;
boolean ok;
//<2F><><EFBFBD><EFBFBD>ΪͨѶ<CDA8><D1B6><EFBFBD>룬<EFBFBD><EBA3AC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݵIJ<DDB5>ִ<EFBFBD><D6B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>UDPͨѶ<CDA8><D1B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
if (ledsender.GetDataSize() > (1 << 21)) {
System.out.println("LED<EFBFBD><EFBFBD>Ŀ<EFBFBD><EFBFBD><EFBFBD>ݳ<EFBFBD><EFBFBD>ȳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʾ<EFBFBD><EFBFBD><EFBFBD>洢<EFBFBD>ռ<EFBFBD>");
return;
}
System.out.println("LED<EFBFBD><EFBFBD>Ŀѹ<EFBFBD><EFBFBD>ǰ<EFBFBD><EFBFBD><EFBFBD>ݳ<EFBFBD><EFBFBD><EFBFBD>" + ledsender.GetDataSize() + "<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݰ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>" + ledsender.get_pkg_count(512));
ledsender.Compress();
System.out.println("LED<EFBFBD><EFBFBD>Ŀѹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݳ<EFBFBD><EFBFBD><EFBFBD>" + ledsender.GetDataSize() + "<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݰ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>" + ledsender.get_pkg_count(512));
//<2F><>ʼ<EFBFBD><CABC>
ok = false;
//System.out.println("<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʼ<EFBFBD><CABC>...<2E><><EFBFBD><EFBFBD><EFBFBD>к<EFBFBD>=0");
for (tx = 0; tx < tx_repeat; tx++) {
size = ledsender.pkg_begin(packet, addr);
udp_send(packet, size);
for (x = 0; x < 50; x++) {
size = udp_receive(packet);
if (size > 0 && ledsender.parse_trans_respond(packet, size, LEDSender2010.PKC_BEGIN, 0) > 0) {
//System.out.println("<22><>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɣ<EFBFBD><C9A3><EFBFBD><EFBFBD>к<EFBFBD>=0");
ok = true;
break;
}
}
if (ok) break;
}
if (!ok) {
System.out.println("<EFBFBD><EFBFBD>ʱ");
return;
}
//<2F><><EFBFBD>ݰ<EFBFBD>
k = ledsender.get_pkg_count(512);
i = 1;
while (i <= k) {
ok = false;
//System.out.println("<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݰ<EFBFBD>...<2E><><EFBFBD><EFBFBD><EFBFBD>к<EFBFBD>="+i);
for (tx = 0; tx < tx_repeat; tx++) {
j = i;
size = ledsender.pkg_data(packet, addr, i, 512);
udp_send(packet, size);
for (x = 0; x < 50; x++) {
size = udp_receive(packet);
if (size > 0) {
r = ledsender.parse_trans_respond(packet, size, LEDSender2010.PKC_DATA, i);
switch (r) {
case 0x1:
//System.out.println("<22><><EFBFBD>ݰ<EFBFBD><DDB0><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɣ<EFBFBD><C9A3><EFBFBD><EFBFBD>к<EFBFBD>="+i);
ok = true;
j = i + 1;
break;
case 0x2:
//System.out.println("<22><><EFBFBD>ݰ<EFBFBD><DDB0><EFBFBD><EFBFBD>к<EFBFBD>У<EFBFBD>Դ<EFBFBD><D4B4><EFBFBD>Ӧ<EFBFBD><D3A6>="+i+"<22><>ʵ<EFBFBD><CAB5>="+ledsender.fix_serialno);
j = ledsender.fix_serialno;
break;
}
//ok=true;
//break;
}
if (ok) break;
}
i = j;
if (ok) break;
}
if (!ok) {
System.out.println("<EFBFBD><EFBFBD>ʱ");
return;
}
}
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
ok = false;
//System.out.println("<22><><EFBFBD>ͽ<EFBFBD><CDBD><EFBFBD><EFBFBD><EFBFBD>...<2E><><EFBFBD><EFBFBD><EFBFBD>к<EFBFBD>="+i);
for (tx = 0; tx < tx_repeat; tx++) {
size = ledsender.pkg_end(packet, addr, i);
udp_send(packet, size);
for (x = 0; x < 50; x++) {
size = udp_receive(packet);
if (size > 0 && ledsender.parse_trans_respond(packet, size, LEDSender2010.PKC_END, i) > 0) {
//System.out.println("<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɣ<EFBFBD><C9A3><EFBFBD><EFBFBD>к<EFBFBD>="+i);
ok = true;
break;
}
}
if (ok) break;
}
if (!ok) {
System.out.println("<EFBFBD><EFBFBD>ʱ");
return;
}
/*
ok=false;
for (x=0; x<100; x++){
size=udp_receive(packet);
switch (ledsender.parse_notify(packet, size)){
case LEDSender2010.NOTIFY_ROOT_PLAY:
System.out.println("<22><><EFBFBD>ͽ<EFBFBD>Ŀ<EFBFBD><C4BF><EFBFBD><EFBFBD>У<EFBFBD><D0A3>ɹ<EFBFBD>");
ok=true;
break;
case LEDSender2010.NOTIFY_ROOT_DOWNLOAD:
System.out.println("<22><><EFBFBD>ؽ<EFBFBD>Ŀ<EFBFBD><C4BF><EFBFBD><EFBFBD>У<EFBFBD><D0A3>ɹ<EFBFBD>");
ok=true;
break;
}
if (ok) break;
}
if (!ok) System.out.println("<22><>Ŀ<EFBFBD><C4BF><EFBFBD><EFBFBD>У<EFBFBD><D0A3><EFBFBD><EFBFBD>󣬷<EFBFBD><F3A3ACB7><EFBFBD>/<2F><><EFBFBD><EFBFBD>ʧ<EFBFBD><CAA7>");
*/
}
public static boolean send_data1(String ip) {
int size = 0;
byte[] packet = new byte[1280];
int i, j, k, x, r;
int tx, tx_repeat = 5;
boolean ok;
// 下面为通讯代码,包括数据的拆分打包、发送
// 由于是UDP通讯,增加
// 如果数据量大于上限,直接返回失败
if (ledsender.GetDataSize() > (1 << 21)) {
System.out.println("LED节目数据长度超出显示屏存储空间");
return false;
}
ledsender.Compress();
// 起始包发送
ok = false;
for (tx = 0; tx < tx_repeat; tx++) {
size = ledsender.pkg_begin(packet, addr);
udp_send1(ip, packet, size);
for (x = 0; x < 50; x++) {
size = udp_receive(packet);
if (size > 0 && ledsender.parse_trans_respond(packet, size, LEDSender2010.PKC_BEGIN, 0) > 0) {
ok = true;
break;
}
}
if (ok) break;
}
// 起始包超时,返回失败
if (!ok) {
System.out.println("起始包发送超时");
return false;
}
// 数据包发送
k = ledsender.get_pkg_count(512);
i = 1;
while (i <= k) {
ok = false;
for (tx = 0; tx < tx_repeat; tx++) {
j = i;
size = ledsender.pkg_data(packet, addr, i, 512);
udp_send1(ip, packet, size);
for (x = 0; x < 50; x++) {
size = udp_receive(packet);
if (size > 0) {
r = ledsender.parse_trans_respond(packet, size,LEDSender2010.PKC_DATA, i);
switch (r) {
case 0x1:
ok = true;
j = i + 1;
break;
case 0x2:
j = ledsender.fix_serialno;
break;
}
}
if (ok) break;
}
i = j;
if (ok) break;
}
// 数据包超时,返回失败
if (!ok) {
System.out.println("数据包发送超时");
return false;
}
}
// 结束包发送
ok = false;
for (tx = 0; tx < tx_repeat; tx++) {
size = ledsender.pkg_end(packet, addr, i);
udp_send1(ip, packet, size);
for (x = 0; x < 50; x++) {
size = udp_receive(packet);
if (size > 0 && ledsender.parse_trans_respond(packet, size, LEDSender2010.PKC_END, i) > 0) {
ok = true;
break;
}
}
if (ok) break;
}
// 结束包超时,返回失败
if (!ok) {
System.out.println("结束包发送超时");
return false;
}
// 所有步骤执行成功,返回true
System.out.println("数据发送全部完成");
return true;
}
public static void demo_upgrade() {
ledsender.Upgrade("d:\\vsd.bin");
send_data();
}
public static void demo_play() {
//String[] formats={"#y", "<22><>", "#m", "<22><>", "#d", "<22><>", " ", "#h", ":", "#n", ":", "#s"};
//String[] formats={"#h", ":", "#n", ":", "#s"};
//<2F><><EFBFBD>ɽ<EFBFBD>Ŀ<EFBFBD><C4BF><EFBFBD><EFBFBD>
ledsender.MakeRoot(LEDSender2010.ROOT_PLAY,LEDSender2010.COLOR_TYPE_DOUBLE);
//ledsender.MakeRoot(LEDSender2010.ROOT_PLAY, LEDSender2010.COLOR_TYPE_THREE);
//ledsender.MakeRoot(LEDSender2010.ROOT_PLAY, LEDSender2010.COLOR_TYPE_FULL);
ledsender.AddChapter(1, 1000);
ledsender.AddRegion(0, 0, 256, 64);
/*
//<2F><><EFBFBD><EFBFBD>ͼƬ
ledsender.AddLeaf(1, 2000);
//draw_dib();
//ledsender.AddDib(0, 0, 64, 64, dib_buffer, dib_buffer_size, dib_width, dib_height, 1, 5, 2, 5, 0, 0, 1000);
BufferedImage bi;
try {
bi = LEDSender2010.createImageEx("<22>л<EFBFBD><D0BB><EFBFBD><EFBFBD>񹲺͹<F1B9B2BA>", new Font("<22><><EFBFBD><EFBFBD>", Font.BOLD, 24), Color.BLACK, Color.CYAN, 0, false, 64);
System.out.println("width:"+bi.getWidth()+"height:"+bi.getHeight());
ledsender.AddWindow(0, 0, 64, 64, LEDSender2010.getBufferedImageRGB(bi), bi.getWidth() * bi.getHeight(), bi.getWidth(), bi.getHeight(), 2, 0, 2, 0, 0, 0, 0);
} catch (Exception e) {
e.printStackTrace();
}
*/
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>֣<EFBFBD><D6A3><EFBFBD><EFBFBD>У<EFBFBD>֧<EFBFBD>ֶ<EFBFBD><D6B6>뷽ʽ<EBB7BD><CABD>
ledsender.AddLeaf(1, 2000);
//ledsender.AddTextJuhao(0, 0, 64, 32, "<22><>ӭ<EFBFBD><D3AD><EFBFBD>١<EFBFBD>лл<D0BB>ݹˡ<DDB9>", "<22><><EFBFBD><EFBFBD>", 24, Color.BLACK, Color.RED, 0, 2, true, 2, 0, 2, 0, 0, 0, 0);
ledsender.AddTextEx(0, 0, 128, 32, "<EFBFBD><EFBFBD>ӭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>",LEDSender2010.ALIGN_LEFT,LEDSender2010.ALIGN_TOP, "<EFBFBD><EFBFBD><EFBFBD><EFBFBD>", 16, Color.BLACK, new Color(255, 0, 0), 0, 1, 0, 2, 0, 0, 0, 0);
//ledsender.AddTextEx(128, 0, 160, 32, "лл<D0BB>ݹ<EFBFBD>", LEDSender2010.ALIGN_LEFT, LEDSender2010.ALIGN_TOP, "<22><><EFBFBD><EFBFBD>", 16, Color.BLACK, Color.RED, 0, 1, 0, 2, 0, 0, 0, 0);
//ledsender.AddLeaf(1, 2000);
//ledsender.AddTextEx(0, 0, 128, 32, "ͬһ<CDAC><D2BB><EFBFBD>й<EFBFBD>", LEDSender2010.ALIGN_LEFT, LEDSender2010.ALIGN_TOP, "<22><><EFBFBD><EFBFBD>", 16, Color.BLACK, Color.RED, 0, 1, 0, 2, 0, 0, 0, 0);
//ledsender.AddTextEx(128, 0, 160, 32, "ͬһ<CDAC><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>", LEDSender2010.ALIGN_LEFT, LEDSender2010.ALIGN_TOP, "<22><><EFBFBD><EFBFBD>", 16, Color.BLACK, Color.RED, 0, 1, 0, 2, 0, 0, 0, 0);
/*
//24<32><34><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
ledsender.AddLeaf(1, 2000);
ledsender.AddString(0, 0, 64, 32, "<22><>ӭ<EFBFBD><D3AD><EFBFBD><EFBFBD>abc", 2, 0, 2, 0, 0, 0, 0, 0xFF, 1);
//24<32><34><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD>䣬<EFBFBD><E4A3AC>ʽyyyy<79><79>mm<6D><6D>dd<64><64>
ledsender.AddLeaf(1, 2000);
ledsender.AddStringDateTime(0, 0, 256, 32, 0xFFFF, 1, formats, 6);
*/
send_data();
}
public static void demo_play2() {
//<2F><><EFBFBD>ɽ<EFBFBD>Ŀ<EFBFBD><C4BF><EFBFBD><EFBFBD>
ledsender.MakeRoot(LEDSender2010.ROOT_DOWNLOAD,LEDSender2010.COLOR_TYPE_DOUBLE);
//ledsender.MakeRoot(LEDSender2010.ROOT_PLAY, LEDSender2010.COLOR_TYPE_THREE);
ledsender.AddChapter(1, 1000000);
ledsender.AddRegion(0, 0, 256, 64);
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>֣<EFBFBD><D6A3><EFBFBD><EFBFBD>У<EFBFBD>֧<EFBFBD>ֶ<EFBFBD><D6B6>뷽ʽ<EBB7BD><CABD>
ledsender.AddLeaf(1, 200000);
ledsender.AddWindows(0, 0, 64, 32);
ledsender.AddChildText("<EFBFBD><EFBFBD>ӭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>", "<EFBFBD><EFBFBD><EFBFBD><EFBFBD>", 16, Color.BLACK, Color.RED, 0, 0, false, 6, 0, 2, 0, 0, 0, 0);
ledsender.AddChildText("лл<EFBFBD>ݹ<EFBFBD>", "<EFBFBD><EFBFBD><EFBFBD><EFBFBD>", 16, Color.BLACK, Color.RED, 0, 0, false, 6, 0, 2, 0, 0, 0, 0);
send_data();
}
public static void demo_play_chapterschedule() {
//String[] formats={"#y", "<22><>", "#m", "<22><>", "#d", "<22><>", " ", "#h", ":", "#n", ":", "#s"};
//String[] formats={"#h", ":", "#n", ":", "#s"};
//<2F><><EFBFBD>ɽ<EFBFBD>Ŀ<EFBFBD><C4BF><EFBFBD><EFBFBD>
ledsender.MakeRoot(LEDSender2010.ROOT_PLAY,LEDSender2010.COLOR_TYPE_DOUBLE);
ledsender.AddChapterEx(1, 1000, 1, 1, 0x7F, 2016, 8, 17, 0, 0, 0, 2016, 12, 27, 23, 59, 59);
ledsender.AddRegion(0, 0, 64, 64);
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>֣<EFBFBD><D6A3>Զ<EFBFBD><D4B6><EFBFBD><EFBFBD>У<EFBFBD>
ledsender.AddLeaf(1, 2000);
ledsender.AddText(0, 0, 64, 32, "<EFBFBD><EFBFBD>ӭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>abc", "<EFBFBD><EFBFBD><EFBFBD><EFBFBD>", 14, Color.BLACK, Color.RED, 0, 2, true, 3, 0, 2, 0, 0, 0, 0);
ledsender.AddChapterEx(1, 1000, 1, 1, 0x7F, 2016, 4, 28, 10, 10, 0, 2016, 12, 27, 23, 15, 0);
ledsender.AddRegion(0, 0, 64, 64);
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>֣<EFBFBD><D6A3><EFBFBD><EFBFBD>У<EFBFBD>֧<EFBFBD>ֶ<EFBFBD><D6B6>뷽ʽ<EBB7BD><CABD>
ledsender.AddLeaf(1, 2000);
ledsender.AddTextEx(0, 0, 64, 32, "лл<EFBFBD>ݹ<EFBFBD>abc",LEDSender2010.ALIGN_CENTER,LEDSender2010.ALIGN_TOP, "<EFBFBD><EFBFBD><EFBFBD><EFBFBD>", 14, Color.BLACK, Color.RED, 0, 1, 0, 2, 0, 0, 0, 0);
send_data();
}
public static void demo_play_picture() {
//<2F><><EFBFBD>ɽ<EFBFBD>Ŀ<EFBFBD><C4BF><EFBFBD><EFBFBD>
ledsender.MakeRoot(LEDSender2010.ROOT_PLAY,LEDSender2010.COLOR_TYPE_DOUBLE);
ledsender.AddChapter(1, 1000);
ledsender.AddRegion(0, 0, 64, 64);
ledsender.AddLeaf(1, 2000);
ledsender.AddPicture(0, 0, 64, 64, "c:\\demo.bmp", 1, 0, 2, 0, 0, 0, 0);
send_data();
}
public static void demo_play_voice() {
//<2F><><EFBFBD>ɽ<EFBFBD>Ŀ<EFBFBD><C4BF><EFBFBD><EFBFBD>
ledsender.MakeRoot(LEDSender2010.ROOT_PLAY,LEDSender2010.COLOR_TYPE_DOUBLE);
ledsender.AddChapter(1, 1000);
ledsender.AddRegion(0, 0, 64, 64);
ledsender.AddLeaf(1, 2000);
ledsender.AddTextEx(0, 0, 64, 32, "<EFBFBD><EFBFBD>ӭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>",LEDSender2010.ALIGN_CENTER,LEDSender2010.ALIGN_TOP, "<EFBFBD><EFBFBD><EFBFBD><EFBFBD>", 16, Color.BLACK, Color.RED, 0, 1, 0, 2, 0, 0, 0, 0);
ledsender.AddVoice("<EFBFBD><EFBFBD>ӭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>", 5000, 10, 0, 5, 5, 1);
send_data();
}
public static void demo_datetime_play() {
String[] formats_datetime = {"#y", "<EFBFBD><EFBFBD>", "#m", "<EFBFBD><EFBFBD>", "#d", "<EFBFBD><EFBFBD>", " ", "#h", ":", "#n", ":", "#s"};
String[] formats_date = {"#y", "<EFBFBD><EFBFBD>", "#m", "<EFBFBD><EFBFBD>", "#d", "<EFBFBD><EFBFBD>"};
String[] formats_time = {"#h", ":", "#n", ":", "#s"};
String[] formats_week = {"<EFBFBD><EFBFBD><EFBFBD><EFBFBD>", "#w"};
//<2F><><EFBFBD>ɽ<EFBFBD>Ŀ<EFBFBD><C4BF><EFBFBD><EFBFBD>
ledsender.MakeRoot(LEDSender2010.ROOT_PLAY,LEDSender2010.COLOR_TYPE_DOUBLE);
//ledsender.MakeRoot(LEDSender2010.ROOT_PLAY, LEDSender2010.COLOR_TYPE_THREE);
ledsender.AddChapter(1, 10000);
ledsender.AddRegion(0, 0, 64, 64);
ledsender.AddLeaf(1, 2000);
ledsender.AddDateTime(0, 0, 64, 32, formats_datetime, 12, "<EFBFBD><EFBFBD><EFBFBD><EFBFBD>", 14, Color.BLACK, Color.YELLOW, 0);
ledsender.AddLeaf(1, 2000);
ledsender.AddDateTime(0, 0, 64, 32, formats_date, 6, "<EFBFBD><EFBFBD><EFBFBD><EFBFBD>", 14, Color.BLACK, Color.RED, 0);
ledsender.AddLeaf(1, 2000);
ledsender.AddDateTime(0, 0, 64, 32, formats_time, 5, "<EFBFBD><EFBFBD><EFBFBD><EFBFBD>", 14, Color.BLACK, Color.GREEN, 0);
ledsender.AddLeaf(1, 2000);
ledsender.AddDateTime(0, 0, 64, 32, formats_week, 2, "<EFBFBD><EFBFBD><EFBFBD><EFBFBD>", 14, Color.BLACK, Color.RED, 0);
send_data();
}
public static void demo_schedule_child_play() {
//<2F><><EFBFBD>ɽ<EFBFBD>Ŀ<EFBFBD><C4BF><EFBFBD><EFBFBD>
//String[] formats_datetime={"#y", "<22><>", "#m", "<22><>", "#d", "<22><>", " ", "#h", ":", "#n", ":", "#s"};
ledsender.MakeRoot(LEDSender2010.ROOT_PLAY,LEDSender2010.COLOR_TYPE_DOUBLE);
ledsender.AddChapter(1, 10000);
ledsender.AddRegion(0, 0, 64, 64);
ledsender.AddLeaf(1, 2000);
ledsender.AddWindows(0, 0, 64, 32);
//ledsender.AddChildText("abc", "<22><><EFBFBD><EFBFBD>", 14, Color.BLACK, Color.RED, 0, false, 1, 0, 2, 0, 0, 0, 0);
ledsender.AddChildScheduleText("<EFBFBD><EFBFBD>ӭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>", "<EFBFBD><EFBFBD><EFBFBD><EFBFBD>", 14, Color.BLACK, Color.RED, 0, 0, false, 1, 0, 2, 0, 0, 0, 2000, 2, 0x0, 2018, 2, 5, 7, 10, 0, 2018, 2, 6, 23, 15, 0);
ledsender.AddChildScheduleText("лл<EFBFBD>ݹ<EFBFBD>", "<EFBFBD><EFBFBD><EFBFBD><EFBFBD>", 14, Color.BLACK, Color.RED, 0, 0, false, 1, 0, 2, 0, 0, 0, 2000, 2, 0x0, 2018, 2, 5, 7, 10, 0, 2018, 2, 6, 23, 15, 0);
ledsender.AddChildScheduleText("ͬһ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>", "<EFBFBD><EFBFBD><EFBFBD><EFBFBD>", 14, Color.BLACK, Color.RED, 0, 0, false, 1, 0, 2, 0, 0, 0, 2000, 2, 0x0, 2018, 2, 8, 7, 10, 0, 2018, 2, 9, 23, 15, 0);
ledsender.AddChildScheduleText("ͬһ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>", "<EFBFBD><EFBFBD><EFBFBD><EFBFBD>", 14, Color.BLACK, Color.RED, 0, 0, false, 1, 0, 2, 0, 0, 0, 2000, 2, 0x0, 2018, 2, 8, 7, 10, 0, 2018, 2, 9, 23, 15, 0);
send_data();
}
public static void demo_fontset_import(MyUdpSocket udp, String ip, int num, String text) {
byte[] packet = new byte[1024];
byte[] s;
int i, size;
int c;
size = 0;
try {
s = text.getBytes("GB2312");
size = 0;
packet[size++] = 0x55;
packet[size++] = 0x25;
packet[size++] = 0x3E;
packet[size++] = (byte) (((num / 100) % 10) + 0x30);
packet[size++] = (byte) (((num / 10) % 10) + 0x30);
packet[size++] = (byte) ((num % 10) + 0x30);
for (i = 0; i < s.length; i++) {
if (s[i] >= 0) c = s[i];
else c = (256 + s[i]);
switch (c >> 4) {
case 0:
packet[size++] = 0x30;
break;
case 1:
packet[size++] = 0x31;
break;
case 2:
packet[size++] = 0x32;
break;
case 3:
packet[size++] = 0x33;
break;
case 4:
packet[size++] = 0x34;
break;
case 5:
packet[size++] = 0x35;
break;
case 6:
packet[size++] = 0x36;
break;
case 7:
packet[size++] = 0x37;
break;
case 8:
packet[size++] = 0x38;
break;
case 9:
packet[size++] = 0x39;
break;
case 10:
packet[size++] = 0x61;
break;
case 11:
packet[size++] = 0x62;
break;
case 12:
packet[size++] = 0x63;
break;
case 13:
packet[size++] = 0x64;
break;
case 14:
packet[size++] = 0x65;
break;
case 15:
packet[size++] = 0x66;
break;
default:
packet[size++] = 0x30;
break;
}
switch (c & 0xF) {
case 0:
packet[size++] = 0x30;
break;
case 1:
packet[size++] = 0x31;
break;
case 2:
packet[size++] = 0x32;
break;
case 3:
packet[size++] = 0x33;
break;
case 4:
packet[size++] = 0x34;
break;
case 5:
packet[size++] = 0x35;
break;
case 6:
packet[size++] = 0x36;
break;
case 7:
packet[size++] = 0x37;
break;
case 8:
packet[size++] = 0x38;
break;
case 9:
packet[size++] = 0x39;
break;
case 10:
packet[size++] = 0x61;
break;
case 11:
packet[size++] = 0x62;
break;
case 12:
packet[size++] = 0x63;
break;
case 13:
packet[size++] = 0x64;
break;
case 14:
packet[size++] = 0x65;
break;
case 15:
packet[size++] = 0x66;
break;
default:
packet[size++] = 0x30;
break;
}
}
packet[size++] = 0x23;
packet[size++] = (byte) 0xAA;
} catch (Exception e) {
}
if (size > 0) {
try {
udp = new MyUdpSocket(8868);
udp.send(ip, 6666, packet, size);
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
//ֻ<><D6BB><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD>Ŀ
public static void demo_play_sub_chapter() {
ledsender.MakeChapter(LEDSender2010.ROOT_PLAY_CHAPTER,LEDSender2010.COLOR_TYPE_DOUBLE, 1, 0, 1, 1000);
ledsender.AddRegion(0, 0, 64, 64);
ledsender.AddLeaf(1, 2000);
ledsender.AddTextEx(0, 0, 64, 32, "abc",LEDSender2010.ALIGN_CENTER,LEDSender2010.ALIGN_TOP, "<EFBFBD><EFBFBD><EFBFBD><EFBFBD>", 14, Color.BLACK, Color.RED, 0, 1, 0, 2, 0, 0, 0, 0);
send_data();
}
public static void demo_play_sub_chapter_ex() {
ledsender.MakeChapterEx(LEDSender2010.ROOT_PLAY_CHAPTER,LEDSender2010.COLOR_TYPE_DOUBLE, 1, 0, 1, 1000, 1, 1, 0x7F, 2016, 8, 17, 0, 0, 0, 2016, 12, 27, 23, 59, 59);
ledsender.AddRegion(0, 0, 64, 64);
ledsender.AddLeaf(1, 2000);
ledsender.AddTextEx(0, 0, 64, 32, "abc",LEDSender2010.ALIGN_CENTER,LEDSender2010.ALIGN_TOP, "<EFBFBD><EFBFBD><EFBFBD><EFBFBD>", 14, Color.BLACK, Color.RED, 0, 1, 0, 2, 0, 0, 0, 0);
send_data();
}
//ֻ<><D6BB><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
public static void demo_play_sub_region() {
ledsender.MakeRegion(LEDSender2010.ROOT_PLAY_REGION,LEDSender2010.COLOR_TYPE_DOUBLE, 1, 0, 1, 0, 16, 128, 16);
ledsender.AddLeaf(1, 2000);
ledsender.AddTextEx(0, 0, 64, 32, "abc",LEDSender2010.ALIGN_CENTER,LEDSender2010.ALIGN_TOP, "<EFBFBD><EFBFBD><EFBFBD><EFBFBD>", 14, Color.BLACK, Color.RED, 0, 1, 0, 2, 0, 0, 0, 0);
send_data();
}
//ֻ<><D6BB><EFBFBD><EFBFBD>һ<EFBFBD><D2BB>ҳ<EFBFBD><D2B3>
public static void demo_play_sub_leaf() {
String[] formats_datetime = {"#h", ":", "#n", ":", "#s"};
ledsender.MakeLeaf(LEDSender2010.ROOT_PLAY_LEAF,LEDSender2010.COLOR_TYPE_DOUBLE, 1, 0, 0, 1, 1, 1000);
ledsender.AddTextEx(0, 0, 64, 16, "abc",LEDSender2010.ALIGN_CENTER,LEDSender2010.ALIGN_TOP, "<EFBFBD><EFBFBD><EFBFBD><EFBFBD>", 14, Color.BLACK, Color.RED, 0, 1, 0, 2, 0, 0, 0, 0);
ledsender.AddDateTime(0, 16, 64, 16, formats_datetime, 12, "<EFBFBD><EFBFBD><EFBFBD><EFBFBD>", 14, Color.BLACK, Color.YELLOW, 0);
send_data();
}
//ֻ<><D6BB><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
public static void demo_play_sub_object() {
ledsender.MakeObject(LEDSender2010.ROOT_PLAY_OBJECT,LEDSender2010.COLOR_TYPE_DOUBLE, 1, 0, 0, 0, 1);
//<2F>˴<EFBFBD>ֻ<EFBFBD><D6BB><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
ledsender.AddTextEx(0, 0, 64, 32, "abc",LEDSender2010.ALIGN_CENTER,LEDSender2010.ALIGN_TOP, "<EFBFBD><EFBFBD><EFBFBD><EFBFBD>", 12, Color.BLACK, Color.RED, 0, 1, 0, 2, 0, 0, 0, 0);
send_data();
}
//<2F>Զ<EFBFBD><D4B6>巽<EFBFBD><E5B7BD> <20><>̬<EFBFBD><CCAC>ʾ<EFBFBD><CABE><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ
public static void demo_play_chapterschedule1(String ip, String msg) {
//<2F><><EFBFBD>ɽ<EFBFBD>Ŀ<EFBFBD><C4BF><EFBFBD><EFBFBD>
ledsender.MakeRoot(LEDSender2010.ROOT_PLAY,LEDSender2010.COLOR_TYPE_DOUBLE);
ledsender.AddChapterEx(1, 1000, 1, 1, 0x7F, 2016, 8, 17, 0, 0, 0, 2016, 12, 27, 23, 59, 59);
ledsender.AddRegion(0, 0, 192, 64);
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>֣<EFBFBD><D6A3>Զ<EFBFBD><D4B6><EFBFBD><EFBFBD>У<EFBFBD>
ledsender.AddLeaf(1, 2000);
ledsender.AddText(8, 24, 192, 64, msg, "<EFBFBD><EFBFBD><EFBFBD><EFBFBD>", 16, Color.BLACK, Color.YELLOW, 0, 2, false, 1, 0, 2, 0, 0, 5, 10000);
send_data1(ip);
}
//<2F>Զ<EFBFBD><D4B6>巽<EFBFBD><E5B7BD> <20><>̬<EFBFBD><CCAC>ʾ<EFBFBD><CABE><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ
public static boolean demo_play_chapterschedule2(String ip, String msg1, String msg2) {
//<2F><><EFBFBD>ɽ<EFBFBD>Ŀ<EFBFBD><C4BF><EFBFBD><EFBFBD>
ledsender.MakeRoot(LEDSender2010.ROOT_PLAY,LEDSender2010.COLOR_TYPE_DOUBLE);
ledsender.AddChapterEx(1, 1000, 1, 1, 0x7F, 2016, 8, 17, 0, 0, 0, 2016, 12, 27, 23, 59, 59);
ledsender.AddRegion(0, 0, 192, 64);
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>֣<EFBFBD><D6A3>Զ<EFBFBD><D4B6><EFBFBD><EFBFBD>У<EFBFBD>
ledsender.AddLeaf(1, 2000);
ledsender.AddText(0, 11, 192, 32, msg1, "<EFBFBD><EFBFBD><EFBFBD><EFBFBD>", 16, Color.BLACK, Color.YELLOW, 0, 2, false, 1, 0, 2, 0, 0, 5, 10000);
ledsender.AddText(0, 37, 192, 32, msg2, "<EFBFBD><EFBFBD><EFBFBD><EFBFBD>", 16, Color.BLACK, Color.YELLOW, 0, 2, false, 1, 0, 2, 0, 0, 5, 10000);
return send_data1(ip);
}
//<2F>Զ<EFBFBD><D4B6>巽<EFBFBD><E5B7BD><EFBFBD><EFBFBD>ʾ<EFBFBD><CABE><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
public static void demo_play_chapterschedule3(String ip, String msg1, String msg2, String msg3, String msg4, String msg5, String msg) {
//<2F><><EFBFBD>ɽ<EFBFBD>Ŀ<EFBFBD><C4BF><EFBFBD><EFBFBD>
ledsender.MakeRoot(LEDSender2010.ROOT_PLAY,LEDSender2010.COLOR_TYPE_DOUBLE);
ledsender.AddChapterEx(1, 1000, 1, 1, 0x7F, 2016, 8, 17, 0, 0, 0, 2016, 12, 27, 23, 59, 59);
ledsender.AddRegion(0, 0, 400, 300);
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>֣<EFBFBD><D6A3>Զ<EFBFBD><D4B6><EFBFBD><EFBFBD>У<EFBFBD>
ledsender.AddLeaf(1, 2000);
ledsender.AddText(0, 0, 192, 21, msg, "<EFBFBD><EFBFBD><EFBFBD><EFBFBD>", 13, Color.BLACK, Color.YELLOW, 0, 2, false, 1, 0, 2, 0, 0, 5, 10000);
ledsender.AddText(0, 12, 192, 21, msg1, "<EFBFBD><EFBFBD><EFBFBD><EFBFBD>", 13, Color.BLACK, Color.YELLOW, 0, 2, false, 1, 0, 2, 0, 0, 5, 10000);
ledsender.AddText(0, 24, 192, 21, msg2, "<EFBFBD><EFBFBD><EFBFBD><EFBFBD>", 13, Color.BLACK, Color.YELLOW, 0, 2, false, 1, 0, 2, 0, 0, 5, 10000);
ledsender.AddText(0, 36, 192, 22, msg3, "<EFBFBD><EFBFBD><EFBFBD><EFBFBD>", 13, Color.BLACK, Color.YELLOW, 0, 2, false, 1, 0, 2, 0, 0, 5, 10000);
// ledsender.AddText(0, 48, 192, 22, msg4, "<22><><EFBFBD><EFBFBD>", 13, Color.BLACK, Color.YELLOW, 0, 2, false, 1, 0, 2, 0, 0, 5, 10000);
// ledsender.AddText(0, 50, 192, 22, msg5, "<22><><EFBFBD><EFBFBD>", 13, Color.BLACK, Color.YELLOW, 0, 2, false, 1, 0, 2, 0, 0, 5, 10000);
send_data1(ip);
}
//<2F>Զ<EFBFBD><D4B6>巽<EFBFBD><E5B7BD><EFBFBD><EFBFBD>ʾ<EFBFBD><CABE><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
public static void demo_play_chapterschedule4(String ip, String msg1, String msg2, String msg3, String msg, String msgSpec, String msgProduct, String ms7, String msg8) {
//<2F><><EFBFBD>ɽ<EFBFBD>Ŀ<EFBFBD><C4BF><EFBFBD><EFBFBD>
ledsender.MakeRoot(LEDSender2010.ROOT_PLAY,LEDSender2010.COLOR_TYPE_DOUBLE);
ledsender.AddChapterEx(1, 1000, 1, 1, 0x7F, 2016, 8, 17, 0, 0, 0, 2016, 12, 27, 23, 59, 59);
ledsender.AddRegion(0, 0, 400, 300);
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>֣<EFBFBD><D6A3>Զ<EFBFBD><D4B6><EFBFBD><EFBFBD>У<EFBFBD>
ledsender.AddLeaf(1, 2000);
ledsender.AddText(0, 0, 192, 21, msg, "<EFBFBD><EFBFBD><EFBFBD><EFBFBD>", 13, Color.BLACK, Color.YELLOW, 0, 2, false, 1, 0, 2, 0, 0, 5, 10000);
ledsender.AddText(0, 15, 192, 21, msg1, "<EFBFBD><EFBFBD><EFBFBD><EFBFBD>", 13, Color.BLACK, Color.YELLOW, 0, 2, false, 1, 0, 2, 0, 0, 5, 10000);
ledsender.AddText(0, 30, 192, 21, msg2, "<EFBFBD><EFBFBD><EFBFBD><EFBFBD>", 13, Color.BLACK, Color.YELLOW, 0, 2, false, 1, 0, 2, 0, 0, 5, 10000);
ledsender.AddText(0, 45, 192, 22, msg3, "<EFBFBD><EFBFBD><EFBFBD><EFBFBD>", 13, Color.BLACK, Color.YELLOW, 0, 2, false, 1, 0, 2, 0, 0, 5, 10000);
// ledsender.AddText(0, 48, 192, 22, msg4, "<22><><EFBFBD><EFBFBD>", 13, Color.BLACK, Color.YELLOW, 0, 2, false, 1, 0, 2, 0, 0, 5, 10000);
// ledsender.AddText(0, 50, 192, 22, msg5, "<22><><EFBFBD><EFBFBD>", 13, Color.BLACK, Color.YELLOW, 0, 2, false, 1, 0, 2, 0, 0, 5, 10000);
send_data1(ip);
}
public static boolean demo_play_chapterschedule4(String ip, String msg1, String msg2, String msg3, String msg,String msg5,String msg6,String msg7,String msg8, String msgQuantity) {
//<2F><><EFBFBD>ɽ<EFBFBD>Ŀ<EFBFBD><C4BF><EFBFBD><EFBFBD>
ledsender.MakeRoot(LEDSender2010.ROOT_PLAY,LEDSender2010.COLOR_TYPE_DOUBLE);
ledsender.AddChapterEx(1, 1000, 1, 1, 0x7F, 2016, 8, 17, 0, 0, 0, 2016, 12, 27, 23, 59, 59);
ledsender.AddRegion(0, 0, 400, 300);
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>֣<EFBFBD><D6A3>Զ<EFBFBD><D4B6><EFBFBD><EFBFBD>У<EFBFBD>
ledsender.AddLeaf(1, 2000);
ledsender.AddText(0, 0, 192, 21, msg, "<EFBFBD><EFBFBD><EFBFBD><EFBFBD>", 13, Color.BLACK, Color.YELLOW, 0, 2, false, 1, 0, 2, 0, 0, 5, 10000);
ledsender.AddText(0, 15, 192, 21, msg1, "<EFBFBD><EFBFBD><EFBFBD><EFBFBD>", 13, Color.BLACK, Color.YELLOW, 0, 2, false, 1, 0, 2, 0, 0, 5, 10000);
ledsender.AddText(65, 15, 192, 21, msg6, "<EFBFBD><EFBFBD><EFBFBD><EFBFBD>", 13, Color.BLACK, Color.YELLOW, 0, 2, false, 1, 0, 7, 0, 0, 5, 3000);
ledsender.AddText(0, 30, 192, 21, msg2, "<EFBFBD><EFBFBD><EFBFBD><EFBFBD>", 13, Color.BLACK, Color.YELLOW, 0, 2, false, 1, 0, 2, 0, 0, 5, 10000);
ledsender.AddText(65, 30, 192, 21, msg5, "<EFBFBD><EFBFBD><EFBFBD><EFBFBD>", 13, Color.BLACK, Color.YELLOW, 0, 2, false, 1, 0, 7, 0, 0, 5, 3000);
ledsender.AddText(0, 45, 192, 22, msg3, "<EFBFBD><EFBFBD><EFBFBD><EFBFBD>", 13, Color.BLACK, Color.YELLOW, 0, 2, false, 1, 0, 2, 0, 0, 5, 10000);
ledsender.AddText(65, 45, 192, 22, msgQuantity, "<EFBFBD><EFBFBD><EFBFBD><EFBFBD>", 13, Color.BLACK, Color.YELLOW, 0, 2, false, 1, 0, 7, 0, 0, 5, 3000);
ledsender.AddText(0, 60, 192, 21, msg7, "<EFBFBD><EFBFBD><EFBFBD><EFBFBD>", 13, Color.BLACK, Color.YELLOW, 0, 2, false, 1, 0, 2, 0, 0, 5, 10000);
ledsender.AddText(65, 60, 192, 21, msg8, "<EFBFBD><EFBFBD><EFBFBD><EFBFBD>", 13, Color.BLACK, Color.YELLOW, 0, 2, false, 1, 0, 7, 0, 0, 5, 3000);
return send_data1(ip);
}
public static void main(String[] args) {
// TODO Auto-generated method stub
try {
my_udp = new MyUdpSocket(8818);
} catch (Exception ex) {
ex.printStackTrace();
}
//demo_play();
//demo_play_voice();
//demo_fontset_import(my_udp, "192.168.1.99", 0, "<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>123");
//demo_reset_display();
//demo_play_chapterschedule();
//demo_upgrade();
//demo_datetime_play();
//demo_play_picture();
//demo_schedule_child_play();
demo_get_boardparam();
//demo_set_boardparam_ip("192.168.1.99");
//demo_power_off();
//demo_power_on();
//demo_get_power();
//demo_set_bright();
//demo_get_bright();
//demo_adjust_time();
//demo_switch_on();
//demo_switch_off();
//demo_power_schedule();
System.out.println("<EFBFBD><EFBFBD><EFBFBD>н<EFBFBD><EFBFBD><EFBFBD>.");
}
}

View File

@@ -0,0 +1,27 @@
package com.ruoyi.Dzp.domain;
import com.ruoyi.common.core.domain.BaseEntity;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
@Getter
@Setter
@NoArgsConstructor
public class basLed extends BaseEntity {
private int id;
private String product_id;
private String spec;
private String quantity;
private String sendFlag;
private String ipAddress;
private String trayCode;
private String model;
private String productName;
private String errorMsg;
}

View File

@@ -0,0 +1,15 @@
package com.ruoyi.Dzp.mapper;
import com.ruoyi.Dzp.domain.basLed;
import java.util.List;
public interface BasLedMapper {
List<basLed> selectBasLedList(basLed BasLed);
void updateBasLed(basLed BasLed);
}

View File

@@ -1,9 +1,11 @@
package com.ruoyi;
import java.security.Security;
import java.util.Arrays;
import java.util.stream.Collectors;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.scheduling.annotation.EnableScheduling;
/**
@@ -17,6 +19,7 @@ public class RuoYiApplication
{
public static void main(String[] args)
{
enableSqlServerLegacyTls();
// System.setProperty("spring.devtools.restart.enabled", "false");
SpringApplication.run(RuoYiApplication.class, args);
System.out.println("""
@@ -24,4 +27,25 @@ public class RuoYiApplication
This is a text block with Unicode characters.
""");
}
private static void enableSqlServerLegacyTls()
{
if (!Boolean.parseBoolean(System.getProperty("ruoyi.sqlserver.legacyTls.enabled", "true")))
{
return;
}
String propertyName = "jdk.tls.disabledAlgorithms";
String disabledAlgorithms = Security.getProperty(propertyName);
if (disabledAlgorithms == null || disabledAlgorithms.isBlank())
{
return;
}
String compatibleAlgorithms = Arrays.stream(disabledAlgorithms.split(","))
.map(String::trim)
.filter(algorithm -> !"TLSv1".equalsIgnoreCase(algorithm))
.collect(Collectors.joining(", "));
Security.setProperty(propertyName, compatibleAlgorithms);
}
}

View File

@@ -0,0 +1,13 @@
package com.ruoyi.algorithm.wms;
import com.ruoyi.job.mydojob.domain.MydoJob;
public record InboundAllocationResult(boolean success, String code, String message, MydoJob job) {
public static InboundAllocationResult success(MydoJob job) {
return new InboundAllocationResult(true, "READY", "Allocation completed", job);
}
public static InboundAllocationResult failure(String code, String message) {
return new InboundAllocationResult(false, code, message, null);
}
}

View File

@@ -0,0 +1,78 @@
package com.ruoyi.algorithm.wms;
import com.ruoyi.algorithm.inbound.InboundAssignment;
import com.ruoyi.algorithm.integration.SchedulingFacade;
import com.ruoyi.algorithm.repository.ReservationStatus;
import com.ruoyi.algorithm.service.InboundPlanningResult;
import com.ruoyi.algorithm.service.InboundReservationOutcome;
import com.ruoyi.job.mydojob.domain.MydoJob;
import com.ruoyi.job.mydojob.mapper.MydoJobMapper;
import org.springframework.dao.CannotAcquireLockException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
public class InboundAllocationTransaction {
private final SchedulingFacade facade;
private final WmsAlgorithmMapper algorithmMapper;
private final MydoJobMapper jobMapper;
public InboundAllocationTransaction(SchedulingFacade facade, WmsAlgorithmMapper algorithmMapper,
MydoJobMapper jobMapper) {
this.facade = facade;
this.algorithmMapper = algorithmMapper;
this.jobMapper = jobMapper;
}
@Transactional(rollbackFor = Exception.class)
public MydoJob reserveAndCommit(MydoJob job, String projectNo, InboundPlanningResult planned) {
InboundAssignment assignment = planned.plan().assignment().orElseThrow(
() -> new IllegalArgumentException("Only an accepted inbound plan can be committed"));
String reservationId = InboundReservationIds.forJob(job.getJobId());
String warehouseId = nonBlank(job.getWarehouseId()) ? job.getWarehouseId() : facade.defaultWarehouseId();
InboundReservationOutcome reservation = facade.reserveInbound(reservationId, warehouseId, projectNo, planned);
if (reservation.reservation().status() != ReservationStatus.RESERVED) {
String reason = reservation.reservation().reasonCode() == null
? "Reservation conflict" : reservation.reservation().reasonCode();
throw new CannotAcquireLockException(reason);
}
int claimed = algorithmMapper.claimInboundSpace(reservationId, warehouseId,
assignment.laneCode(), assignment.spaceId(), job.getTrayCode());
if (claimed != 1) {
throw new CannotAcquireLockException("Inbound target changed after planning");
}
if (algorithmMapper.assignInboundJob(job.getJobId(), assignment.spaceId()) != 1) {
throw new CannotAcquireLockException("Inbound job changed after planning");
}
MydoJob committed = jobMapper.selectInJobByTaskNo(job.getTaskNo());
if (committed == null) {
throw new IllegalStateException("Committed inbound job cannot be reloaded");
}
return committed;
}
private boolean nonBlank(String value) {
return value != null && !value.isBlank();
}
@Transactional(rollbackFor = Exception.class)
public MydoJob release(MydoJob job) {
String oldSpaceId = job.getCargoSpaceId();
if (oldSpaceId == null || oldSpaceId.isBlank()) {
return job;
}
int released = algorithmMapper.releaseInboundSpace(job.getJobId(), job.getWarehouseId(),
oldSpaceId, job.getTrayCode());
if (released != 1) {
throw new CannotAcquireLockException("Old inbound target changed or contains stock");
}
if (algorithmMapper.clearInboundJobAssignment(job.getJobId(), oldSpaceId) != 1) {
throw new CannotAcquireLockException("Inbound job changed while releasing old target");
}
MydoJob cleared = jobMapper.selectInJobByTaskNo(job.getTaskNo());
if (cleared == null) {
throw new IllegalStateException("Released inbound job cannot be reloaded");
}
return cleared;
}
}

View File

@@ -0,0 +1,16 @@
package com.ruoyi.algorithm.wms;
import java.nio.charset.StandardCharsets;
import java.util.UUID;
final class InboundReservationIds {
private InboundReservationIds() {
}
static String forJob(String jobId) {
if (jobId == null || jobId.isBlank()) {
throw new IllegalArgumentException("jobId is required");
}
return UUID.nameUUIDFromBytes(("fortucky-inbound:" + jobId).getBytes(StandardCharsets.UTF_8)).toString();
}
}

View File

@@ -0,0 +1,38 @@
package com.ruoyi.algorithm.wms;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.function.Function;
public record InboundTaskContext(String projectNo, String productId, String lotNo) {
public static InboundTaskContext from(List<InboundTaskItem> items) {
List<InboundTaskItem> values = items == null ? List.of() : items;
Set<String> projects = distinct(values, InboundTaskItem::projectNo);
if (projects.size() != 1) {
throw new IllegalArgumentException("Inbound task must resolve to exactly one project");
}
return new InboundTaskContext(projects.iterator().next(), uniqueOrNull(values, InboundTaskItem::productId),
uniqueOrNull(values, InboundTaskItem::lotNo));
}
private static String uniqueOrNull(List<InboundTaskItem> values,
Function<InboundTaskItem, String> extractor) {
Set<String> distinct = distinct(values, extractor);
return distinct.size() == 1 ? distinct.iterator().next() : null;
}
private static Set<String> distinct(List<InboundTaskItem> values,
Function<InboundTaskItem, String> extractor) {
Set<String> result = new LinkedHashSet<>();
values.stream().filter(Objects::nonNull).map(extractor).map(InboundTaskContext::trimToNull)
.filter(Objects::nonNull).forEach(result::add);
return result;
}
private static String trimToNull(String value) {
return value == null || value.isBlank() ? null : value.trim();
}
}

View File

@@ -0,0 +1,4 @@
package com.ruoyi.algorithm.wms;
public record InboundTaskItem(String projectNo, String productId, String lotNo) {
}

View File

@@ -0,0 +1,20 @@
package com.ruoyi.algorithm.wms;
import com.ruoyi.algorithm.integration.SchedulingDecisionStatus;
import com.ruoyi.algorithm.outbound.OutboundAssignment;
public record OutboundAllocationResult(SchedulingDecisionStatus status, String code, String message,
OutboundAssignment assignment) {
public static OutboundAllocationResult ready(String code, String message, OutboundAssignment assignment) {
return new OutboundAllocationResult(SchedulingDecisionStatus.READY, code, message, assignment);
}
public static OutboundAllocationResult waiting(String code, String message) {
return new OutboundAllocationResult(SchedulingDecisionStatus.WAITING, code, message, null);
}
public static OutboundAllocationResult rejected(String code, String message) {
return new OutboundAllocationResult(SchedulingDecisionStatus.REJECTED, code, message, null);
}
}

View File

@@ -0,0 +1,5 @@
package com.ruoyi.algorithm.wms;
public record OutboundStockReference(String stockId, String trayCode, String spaceId,
String warehouseId, String projectNo, String productId) {
}

View File

@@ -0,0 +1,19 @@
package com.ruoyi.algorithm.wms;
public record OutboundWorkflowAdvance(
boolean matched,
boolean workflowCompleted,
OutboundWorkflowRuntime workflow) {
public static OutboundWorkflowAdvance noMatch() {
return new OutboundWorkflowAdvance(false, false, null);
}
public static OutboundWorkflowAdvance advanced(OutboundWorkflowRuntime workflow) {
return new OutboundWorkflowAdvance(true, false, workflow);
}
public static OutboundWorkflowAdvance completed(OutboundWorkflowRuntime workflow) {
return new OutboundWorkflowAdvance(true, true, workflow);
}
}

View File

@@ -0,0 +1,14 @@
package com.ruoyi.algorithm.wms;
import com.ruoyi.algorithm.outbound.OutboundAssignment;
import com.ruoyi.out.outStockout.domain.OutStockout;
import com.ruoyi.out.outStockoutDetail.domain.OutStockoutDetail;
public interface OutboundWorkflowCoordinator {
OutboundAllocationResult start(OutStockout stockout, OutStockoutDetail detail,
OutboundStockReference selectedStock, OutboundAssignment assignment);
OutboundWorkflowAdvance onJobFinished(String jobId);
OutboundWorkflowAdvance confirmOutbound(String trayCode);
}

View File

@@ -0,0 +1,17 @@
package com.ruoyi.algorithm.wms;
public record OutboundWorkflowHeaderState(
String workflowId,
String requestId,
String stockoutDetailId,
String warehouseId,
String sourceStockId,
String selectedTrayCode,
String sourceSpaceId,
String laneCode,
int floorNo,
String exitId,
String status,
int currentStep,
int totalSteps) {
}

View File

@@ -0,0 +1,8 @@
package com.ruoyi.algorithm.wms;
public record OutboundWorkflowRuntime(
String workflowId,
String requestId,
String warehouseId,
int floorNo) {
}

View File

@@ -0,0 +1,7 @@
package com.ruoyi.algorithm.wms;
public record OutboundWorkflowSpaceLock(
String workflowId,
String warehouseId,
String spaceId) {
}

View File

@@ -0,0 +1,25 @@
package com.ruoyi.algorithm.wms;
public record OutboundWorkflowStepState(
String assignmentId,
String workflowId,
String stockoutDetailId,
String warehouseId,
int floorNo,
String requestId,
String exitId,
String phase,
String sourceSpaceId,
String targetSpaceId,
int workflowStep,
int workflowTotalSteps,
String dependsOnAssignmentId,
String stockId,
String trayCode,
String status,
String jobId) {
public OutboundWorkflowRuntime runtime() {
return new OutboundWorkflowRuntime(workflowId, requestId, warehouseId, floorNo);
}
}

View File

@@ -0,0 +1,352 @@
package com.ruoyi.algorithm.wms;
import com.ruoyi.algorithm.outbound.OutboundAssignment;
import com.ruoyi.algorithm.outbound.OutboundWorkflow;
import com.ruoyi.algorithm.outbound.OutboundWorkflowPhase;
import com.ruoyi.algorithm.outbound.OutboundWorkflowStep;
import com.ruoyi.algorithm.integration.SchedulingFacade;
import com.ruoyi.algorithm.repository.DeepWorkflowMutationResult;
import com.ruoyi.out.outStockout.domain.OutStockout;
import com.ruoyi.out.outStockout.mapper.OutStockoutMapper;
import com.ruoyi.out.outStockoutDetail.domain.OutStockoutDetail;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
@Service
public class OutboundWorkflowTransaction {
private static final String PENDING = "PENDING";
private static final String RUNNING = "RUNNING";
private static final String AT_EXIT = "AT_EXIT";
private final WmsAlgorithmMapper mapper;
private final OutStockoutMapper stockoutMapper;
private final SchedulingFacade facade;
public OutboundWorkflowTransaction(WmsAlgorithmMapper mapper, OutStockoutMapper stockoutMapper,
SchedulingFacade facade) {
this.mapper = mapper;
this.stockoutMapper = stockoutMapper;
this.facade = facade;
}
@Transactional(rollbackFor = Exception.class)
public OutboundAllocationResult commitShallow(OutStockout stockout, OutStockoutDetail detail,
OutboundStockReference selected, OutboundAssignment assignment) {
if (assignment.workflow().isPresent()) {
throw new IllegalArgumentException("A shallow outbound assignment is required");
}
String warehouseId = warehouseId(stockout);
OutboundStockReference live = mapper.selectOutboundShallowCommitStockForUpdate(
selected.stockId(), warehouseId, selected.spaceId(),
selected.trayCode(), selected.projectNo());
if (!sameStock(selected, live)
|| !Objects.equals(warehouseId, live.warehouseId())
|| !Objects.equals(assignment.sourceSpaceId(), live.spaceId())
|| !Objects.equals(assignment.trayNo(), live.trayCode())) {
return OutboundAllocationResult.waiting("SHALLOW_COMMIT_CONFLICT",
"Selected outbound stock or its outer lane positions changed before commit");
}
HashMap<String, String> parameters = new HashMap<>();
parameters.put("v_stockout_detail_id", detail.getStockoutDetailId());
parameters.put("v_stock_id", live.stockId());
parameters.put("v_result", null);
parameters.put("v_resultmsg", null);
stockoutMapper.manualAllot(parameters);
String result = String.valueOf(parameters.get("v_result"));
String message = String.valueOf(parameters.get("v_resultmsg"));
return "10".equals(result)
? OutboundAllocationResult.ready("READY", message, assignment)
: OutboundAllocationResult.rejected("LEGACY_" + result, message);
}
@Transactional(rollbackFor = Exception.class)
public OutboundAllocationResult start(OutStockout stockout, OutStockoutDetail detail,
OutboundStockReference targetStock, OutboundAssignment assignment) {
OutboundWorkflow workflow = assignment.workflow().orElseThrow(
() -> new IllegalArgumentException("A deep outbound workflow is required"));
String warehouseId = warehouseId(stockout);
validateStartInputs(stockout, detail, targetStock, workflow);
OutboundStockReference liveTargetStock = mapper.selectOutboundWorkflowStartStockForUpdate(
targetStock.stockId());
validateLiveTargetStock(warehouseId, targetStock, liveTargetStock, assignment, workflow);
Map<String, OutboundStockReference> blockersBySource = resolveBlockers(
warehouseId, workflow.steps());
List<OutboundWorkflowStepState> states = workflow.steps().stream()
.map(step -> stateFor(warehouseId, stockout, detail, liveTargetStock, assignment, workflow,
step, blockersBySource))
.toList();
OutboundWorkflowHeaderState header = new OutboundWorkflowHeaderState(
workflow.workflowId(), detail.getStockoutDetailId(), detail.getStockoutDetailId(),
warehouseId, liveTargetStock.stockId(), liveTargetStock.trayCode(),
workflow.sourceSpaceId(), workflow.laneCode(), workflow.floorNo(), stockout.getExitId(),
"ACTIVE", 0, workflow.steps().size());
requireOne(mapper.insertOutboundWorkflow(header), "insert workflow header");
for (OutboundWorkflowStepState state : states) {
requireOne(mapper.insertOutboundWorkflowStep(state),
"insert workflow step " + state.assignmentId());
}
Set<String> spaces = new LinkedHashSet<>(workflow.lockedLaneSpaceIds());
spaces.addAll(workflow.lockedBufferSpaceIds());
for (String spaceId : spaces) {
requireOne(mapper.lockOutboundWorkflowSpace(new OutboundWorkflowSpaceLock(
workflow.workflowId(), warehouseId, spaceId)),
"lock workflow space " + spaceId);
}
OutboundWorkflowStepState first = mapper.selectNextPendingWorkflowStep(workflow.workflowId());
if (first == null || phase(first) != OutboundWorkflowPhase.MOVE_OUT) {
throw new IllegalStateException("Deep workflow has no executable first MOVE_OUT step");
}
createMoveJob(first);
return OutboundAllocationResult.ready("WORKFLOW_STARTED",
"Deep outbound workflow started", assignment);
}
@Transactional(readOnly = true)
public boolean hasActiveWorkflow(String requestId, String warehouseId, int floorNo) {
return mapper.countActiveOutboundWorkflow(requestId, warehouseId, floorNo) > 0;
}
@Transactional(rollbackFor = Exception.class)
public OutboundWorkflowAdvance completeJob(String jobId) {
if (jobId == null || jobId.isBlank()) {
return OutboundWorkflowAdvance.noMatch();
}
OutboundWorkflowStepState current = mapper.selectOutboundWorkflowStepByJobId(jobId.trim());
if (current == null) {
return OutboundWorkflowAdvance.noMatch();
}
if (!RUNNING.equals(current.status())) {
return OutboundWorkflowAdvance.noMatch();
}
OutboundWorkflowPhase phase = phase(current);
if (phase == OutboundWorkflowPhase.OUTBOUND) {
requireOne(mapper.markOutboundWorkflowStepAtExit(current.assignmentId()),
"mark outbound step at exit");
return OutboundWorkflowAdvance.advanced(current.runtime());
}
if (mapper.countStockAtSpaceByTray(current.targetSpaceId(), current.trayCode()) < 1) {
throw new IllegalStateException("Tray " + current.trayCode()
+ " has not reached workflow target " + current.targetSpaceId());
}
requireOne(mapper.markOutboundWorkflowStepCompleted(current.assignmentId()),
"complete workflow step " + current.assignmentId());
return advanceAfterCompleted(current);
}
@Transactional(rollbackFor = Exception.class)
public OutboundWorkflowAdvance confirmOutbound(String trayCode) {
if (trayCode == null || trayCode.isBlank()) {
return OutboundWorkflowAdvance.noMatch();
}
OutboundWorkflowStepState outbound = mapper.selectOutboundWorkflowStepForTray(trayCode.trim());
if (outbound == null) {
return OutboundWorkflowAdvance.noMatch();
}
if (phase(outbound) != OutboundWorkflowPhase.OUTBOUND || !AT_EXIT.equals(outbound.status())) {
return OutboundWorkflowAdvance.noMatch();
}
if (mapper.countStockAtSpaceByTray(outbound.sourceSpaceId(), outbound.trayCode()) != 0) {
throw new IllegalStateException("Outbound stock still exists at its original source space");
}
requireOne(mapper.markOutboundWorkflowStepCompleted(outbound.assignmentId()),
"complete confirmed outbound step");
OutboundWorkflowStepState next = mapper.selectNextPendingWorkflowStep(outbound.workflowId());
if (next == null || phase(next) != OutboundWorkflowPhase.RESTORE) {
throw new IllegalStateException("Confirmed deep outbound has no executable RESTORE step");
}
requireOne(mapper.relockOutboundWorkflowSpace(
next.workflowId(), next.warehouseId(), next.targetSpaceId()),
"re-lock first restore target space");
createMoveJob(next);
return OutboundWorkflowAdvance.advanced(outbound.runtime());
}
private OutboundWorkflowAdvance advanceAfterCompleted(OutboundWorkflowStepState current) {
OutboundWorkflowStepState next = mapper.selectNextPendingWorkflowStep(current.workflowId());
if (next == null) {
if (phase(current) != OutboundWorkflowPhase.RESTORE) {
throw new IllegalStateException("Workflow ended before its final RESTORE step");
}
requireOne(mapper.completeOutboundWorkflow(current.workflowId()), "complete workflow");
int released = mapper.unlockOutboundWorkflowSpaces(current.workflowId());
if (released < 1) {
throw new IllegalStateException("Completed workflow released no cargo spaces");
}
DeepWorkflowMutationResult floorReleased = facade.releaseDeepWorkflowLock(
current.warehouseId(), current.requestId(), current.floorNo());
if (!floorReleased.changed()) {
throw new IllegalStateException("Completed outbound workflow floor lock was not released");
}
return OutboundWorkflowAdvance.completed(current.runtime());
}
OutboundWorkflowPhase nextPhase = phase(next);
if (nextPhase == OutboundWorkflowPhase.MOVE_OUT) {
createMoveJob(next);
} else if (nextPhase == OutboundWorkflowPhase.OUTBOUND) {
allocateOutbound(next);
} else if (nextPhase == OutboundWorkflowPhase.RESTORE) {
createMoveJob(next);
} else {
throw new IllegalStateException("Unexpected executable workflow phase " + next.phase());
}
return OutboundWorkflowAdvance.advanced(current.runtime());
}
private void allocateOutbound(OutboundWorkflowStepState step) {
requireOne(mapper.unlockOutboundWorkflowSpace(
step.workflowId(), step.warehouseId(), step.sourceSpaceId()),
"unlock selected outbound source space");
HashMap<String, String> parameters = new HashMap<>();
parameters.put("v_stockout_detail_id", step.stockoutDetailId());
parameters.put("v_stock_id", step.stockId());
parameters.put("v_result", null);
parameters.put("v_resultmsg", null);
stockoutMapper.manualAllot(parameters);
if (!"10".equals(String.valueOf(parameters.get("v_result")))) {
throw new IllegalStateException("Exact-stock allocation failed: "
+ String.valueOf(parameters.get("v_resultmsg")));
}
String jobId = mapper.selectActiveOutboundJobId(step.stockId(), step.stockoutDetailId());
if (jobId == null || jobId.isBlank()) {
throw new IllegalStateException("Exact-stock allocation created no resolvable outbound job");
}
requireOne(mapper.markOutboundWorkflowStepRunning(step.assignmentId(), jobId),
"start outbound workflow step");
}
private void createMoveJob(OutboundWorkflowStepState step) {
OutboundWorkflowPhase phase = phase(step);
if (phase != OutboundWorkflowPhase.MOVE_OUT && phase != OutboundWorkflowPhase.RESTORE) {
throw new IllegalStateException("Only MOVE_OUT and RESTORE steps create relocation jobs");
}
requireOne(mapper.insertOutboundWorkflowMoveJob(step),
"create relocation job " + step.assignmentId());
requireOne(mapper.markOutboundWorkflowStepRunning(step.assignmentId(), step.assignmentId()),
"start relocation workflow step " + step.assignmentId());
}
private Map<String, OutboundStockReference> resolveBlockers(String warehouseId,
List<OutboundWorkflowStep> steps) {
Map<String, OutboundStockReference> blockers = new LinkedHashMap<>();
for (OutboundWorkflowStep step : steps) {
if (step.phase() != OutboundWorkflowPhase.MOVE_OUT) {
continue;
}
List<OutboundStockReference> stocks = mapper.selectOutboundStocksAtSpace(
warehouseId, step.sourceSpaceId());
if (stocks == null || stocks.isEmpty()) {
throw new IllegalStateException("No blocker stock at " + step.sourceSpaceId());
}
OutboundStockReference selected = stocks.get(0);
boolean inconsistent = stocks.stream().anyMatch(stock ->
!selected.trayCode().equals(stock.trayCode())
|| !step.sourceSpaceId().equals(stock.spaceId())
|| !warehouseId.equals(stock.warehouseId()));
if (inconsistent) {
throw new IllegalStateException("Blocker space has inconsistent stock/tray rows: "
+ step.sourceSpaceId());
}
blockers.put(step.sourceSpaceId(), selected);
blockers.put(step.targetSpaceId(), selected);
}
return blockers;
}
private OutboundWorkflowStepState stateFor(String warehouseId, OutStockout stockout,
OutStockoutDetail detail,
OutboundStockReference targetStock, OutboundAssignment assignment, OutboundWorkflow workflow,
OutboundWorkflowStep step, Map<String, OutboundStockReference> blockers) {
OutboundStockReference stock = switch (step.phase()) {
case OUTBOUND -> targetStock;
case MOVE_OUT -> blockers.get(step.sourceSpaceId());
case RESTORE -> blockers.get(step.sourceSpaceId());
};
if (stock == null) {
throw new IllegalStateException("Cannot resolve stock for workflow step " + step.assignmentId());
}
return new OutboundWorkflowStepState(step.assignmentId(), workflow.workflowId(),
detail.getStockoutDetailId(), warehouseId, workflow.floorNo(),
detail.getStockoutDetailId(), stockout.getExitId(), step.phase().name(), step.sourceSpaceId(),
step.targetSpaceId(), step.workflowStep(), step.workflowTotalSteps(),
step.dependsOnAssignmentId(), stock.stockId(), stock.trayCode(), PENDING, null);
}
private void validateStartInputs(OutStockout stockout, OutStockoutDetail detail,
OutboundStockReference targetStock, OutboundWorkflow workflow) {
required(detail.getStockoutDetailId(), "stockoutDetailId");
required(stockout.getExitId(), "exitId");
required(targetStock.stockId(), "stockId");
if (workflow.steps().isEmpty()) {
throw new IllegalArgumentException("Outbound workflow has no steps");
}
}
private void validateLiveTargetStock(String warehouseId, OutboundStockReference planned,
OutboundStockReference live, OutboundAssignment assignment, OutboundWorkflow workflow) {
if (live == null
|| !Objects.equals(planned.stockId(), live.stockId())
|| !Objects.equals(planned.trayCode(), live.trayCode())
|| !Objects.equals(planned.spaceId(), live.spaceId())
|| !Objects.equals(planned.warehouseId(), live.warehouseId())
|| !Objects.equals(warehouseId, live.warehouseId())
|| !Objects.equals(assignment.sourceSpaceId(), live.spaceId())
|| !Objects.equals(assignment.trayNo(), live.trayCode())
|| !Objects.equals(workflow.sourceSpaceId(), live.spaceId())) {
throw new IllegalStateException("Selected outbound stock changed after workflow planning");
}
}
private boolean sameStock(OutboundStockReference planned, OutboundStockReference live) {
return live != null
&& Objects.equals(planned.stockId(), live.stockId())
&& Objects.equals(planned.trayCode(), live.trayCode())
&& Objects.equals(planned.spaceId(), live.spaceId())
&& Objects.equals(planned.warehouseId(), live.warehouseId())
&& Objects.equals(planned.projectNo(), live.projectNo());
}
private OutboundWorkflowPhase phase(OutboundWorkflowStepState step) {
try {
return OutboundWorkflowPhase.valueOf(step.phase());
} catch (RuntimeException exception) {
throw new IllegalStateException("Unknown outbound workflow phase " + step.phase(), exception);
}
}
private void requireOne(int affected, String action) {
if (affected != 1) {
throw new IllegalStateException("Failed to " + action + "; affected rows=" + affected);
}
}
private String warehouseId(OutStockout stockout) {
String warehouseId = stockout.getWarehouseId();
if (warehouseId == null || warehouseId.isBlank()) {
warehouseId = facade.defaultWarehouseId();
}
return required(warehouseId, "warehouseId").trim();
}
private String required(String value, String name) {
if (value == null || value.isBlank()) {
throw new IllegalArgumentException(name + " is required");
}
return value;
}
}

View File

@@ -0,0 +1,103 @@
package com.ruoyi.algorithm.wms;
import com.ruoyi.algorithm.integration.SchedulingDecisionStatus;
import com.ruoyi.algorithm.integration.SchedulingFacade;
import com.ruoyi.algorithm.outbound.OutboundAssignment;
import com.ruoyi.algorithm.outbound.OutboundWorkflow;
import com.ruoyi.algorithm.repository.DeepWorkflowMutationResult;
import com.ruoyi.out.outStockout.domain.OutStockout;
import com.ruoyi.out.outStockoutDetail.domain.OutStockoutDetail;
import org.springframework.stereotype.Service;
@Service
public class PersistentOutboundWorkflowCoordinator implements OutboundWorkflowCoordinator {
private final SchedulingFacade facade;
private final OutboundWorkflowTransaction transaction;
public PersistentOutboundWorkflowCoordinator(SchedulingFacade facade,
OutboundWorkflowTransaction transaction) {
this.facade = facade;
this.transaction = transaction;
}
@Override
public OutboundAllocationResult start(OutStockout stockout, OutStockoutDetail detail,
OutboundStockReference selectedStock, OutboundAssignment assignment) {
OutboundWorkflow workflow = assignment.workflow().orElseThrow(
() -> new IllegalArgumentException("A persistent outbound workflow is required"));
String warehouseId = required(stockout.getWarehouseId(), "warehouseId");
String requestId = required(detail.getStockoutDetailId(), "stockoutDetailId");
DeepWorkflowMutationResult acquired = facade.acquireDeepWorkflowLock(
warehouseId, requestId, workflow.floorNo());
if (!acquired.changed()) {
return OutboundAllocationResult.waiting("WAITING_CHANNEL",
"Another deep outbound workflow owns this floor");
}
try {
OutboundAllocationResult result = transaction.start(stockout, detail, selectedStock, assignment);
if (result.status() != SchedulingDecisionStatus.READY) {
if (transaction.hasActiveWorkflow(requestId, warehouseId, workflow.floorNo())) {
return alreadyActive(assignment);
}
releaseAfterFailedStart(warehouseId, requestId, workflow.floorNo(), null);
}
return result;
} catch (RuntimeException failure) {
if (transaction.hasActiveWorkflow(requestId, warehouseId, workflow.floorNo())) {
return alreadyActive(assignment);
}
releaseAfterFailedStart(warehouseId, requestId, workflow.floorNo(), failure);
throw failure;
}
}
@Override
public OutboundWorkflowAdvance onJobFinished(String jobId) {
if (!facade.routingPolicy().algorithmOwnsDecision()) {
return OutboundWorkflowAdvance.noMatch();
}
return transaction.completeJob(jobId);
}
@Override
public OutboundWorkflowAdvance confirmOutbound(String trayCode) {
if (!facade.routingPolicy().algorithmOwnsDecision()) {
return OutboundWorkflowAdvance.noMatch();
}
return transaction.confirmOutbound(trayCode);
}
private OutboundAllocationResult alreadyActive(OutboundAssignment assignment) {
return OutboundAllocationResult.ready("WORKFLOW_ALREADY_ACTIVE",
"Deep outbound workflow is already active", assignment);
}
private void releaseAfterFailedStart(String warehouseId, String requestId, int floorNo,
RuntimeException originalFailure) {
try {
DeepWorkflowMutationResult released = facade.releaseDeepWorkflowLock(
warehouseId, requestId, floorNo);
if (!released.changed()) {
IllegalStateException releaseFailure = new IllegalStateException(
"Failed outbound workflow floor lock was not released");
if (originalFailure == null) {
throw releaseFailure;
}
originalFailure.addSuppressed(releaseFailure);
}
} catch (RuntimeException releaseFailure) {
if (originalFailure == null) {
throw releaseFailure;
}
originalFailure.addSuppressed(releaseFailure);
}
}
private String required(String value, String name) {
if (value == null || value.isBlank()) {
throw new IllegalArgumentException(name + " is required");
}
return value.trim();
}
}

View File

@@ -0,0 +1,181 @@
package com.ruoyi.algorithm.wms;
import com.ruoyi.algorithm.inbound.BatchLaneMode;
import com.ruoyi.algorithm.inbound.InboundPlan;
import com.ruoyi.algorithm.inbound.InboundRequest;
import com.ruoyi.algorithm.integration.SchedulingDecisionStatus;
import com.ruoyi.algorithm.integration.SchedulingFacade;
import com.ruoyi.algorithm.integration.SchedulingRoutingPolicy;
import com.ruoyi.algorithm.repository.ReservationStatus;
import com.ruoyi.algorithm.repository.ReservationResult;
import com.ruoyi.algorithm.service.InboundPlanningResult;
import com.ruoyi.job.mydojob.domain.MydoJob;
import com.ruoyi.job.mydojob.mapper.MydoJobMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.HashMap;
import java.util.Set;
@Service
public class WmsInboundAllocationService {
private static final Logger log = LoggerFactory.getLogger(WmsInboundAllocationService.class);
private final SchedulingFacade facade;
private final WmsAlgorithmMapper algorithmMapper;
private final MydoJobMapper jobMapper;
private final InboundAllocationTransaction transaction;
private final com.ruoyi.algorithm.wms.tidy.ExecutionAdmissionService admission;
public WmsInboundAllocationService(SchedulingFacade facade, WmsAlgorithmMapper algorithmMapper,
MydoJobMapper jobMapper, InboundAllocationTransaction transaction) {
this(facade, algorithmMapper, jobMapper, transaction, null);
}
@Autowired
public WmsInboundAllocationService(SchedulingFacade facade, WmsAlgorithmMapper algorithmMapper,
MydoJobMapper jobMapper, InboundAllocationTransaction transaction,
com.ruoyi.algorithm.wms.tidy.ExecutionAdmissionService admission) {
this.facade = facade;
this.algorithmMapper = algorithmMapper;
this.jobMapper = jobMapper;
this.transaction = transaction;
this.admission = admission;
}
@Transactional(rollbackFor = Exception.class)
public InboundAllocationResult allocate(MydoJob job, String deviceCode) {
admit(job);
SchedulingRoutingPolicy routing = facade.routingPolicy();
if (!routing.runAlgorithm()) {
return legacy(job, deviceCode);
}
InboundTaskContext context;
InboundPlanningResult planned;
try {
context = InboundTaskContext.from(algorithmMapper.selectInboundTaskItems(job.getJobId()));
planned = facade.planInbound(warehouseId(job), toRequest(job, context));
} catch (RuntimeException exception) {
log.error("Java inbound planning failed for job {}", job.getJobId(), exception);
if (routing.runLegacy(SchedulingDecisionStatus.TECHNICAL_ERROR)) {
return legacy(job, deviceCode);
}
return InboundAllocationResult.failure("ALGORITHM_TECHNICAL_ERROR", safeMessage(exception));
}
InboundPlan plan = planned.plan();
SchedulingDecisionStatus status = plan.assignment().isPresent()
? SchedulingDecisionStatus.READY : SchedulingDecisionStatus.REJECTED;
if (routing.runLegacy(status)) {
InboundAllocationResult legacy = legacy(job, deviceCode);
String javaSpace = plan.assignment().map(value -> value.spaceId()).orElse(null);
String legacySpace = legacy.job() == null ? null : legacy.job().getCargoSpaceId();
log.info("Inbound shadow comparison job={} javaSpace={} legacySpace={} javaRejected={}",
job.getJobId(), javaSpace, legacySpace, plan.rejection().map(value -> value.code().name()).orElse(null));
return legacy;
}
if (plan.rejection().isPresent()) {
var rejection = plan.rejection().orElseThrow();
return InboundAllocationResult.failure(rejection.code().name(), rejection.reason());
}
try {
return InboundAllocationResult.success(transaction.reserveAndCommit(job, context.projectNo(), planned));
} catch (RuntimeException exception) {
log.warn("Inbound commit conflicted after reservation for job {}", job.getJobId(), exception);
return InboundAllocationResult.failure("REPLAN_REQUIRED", safeMessage(exception));
}
}
@Transactional(rollbackFor = Exception.class)
public InboundAllocationResult reallocate(MydoJob job, String deviceCode) {
admit(job);
MydoJob cleared;
try {
cleared = transaction.release(job);
} catch (RuntimeException exception) {
log.warn("Inbound reallocation cannot release old target for job {}", job.getJobId(), exception);
return InboundAllocationResult.failure("REASSIGNMENT_CONFLICT", safeMessage(exception));
}
SchedulingRoutingPolicy routing = facade.routingPolicy();
if (routing.algorithmOwnsDecision()) {
try {
String reservationId = InboundReservationIds.forJob(job.getJobId());
ReservationResult released = facade.releaseInboundReservation(warehouseId(job), reservationId);
if (released.status() != ReservationStatus.RELEASED
&& released.status() != ReservationStatus.NOT_FOUND) {
return InboundAllocationResult.failure("RESERVATION_RELEASE_FAILED",
released.reasonCode() == null ? "Old reservation cannot be released"
: released.reasonCode());
}
} catch (RuntimeException exception) {
log.error("Inbound reallocation cannot release algorithm reservation for job {}",
job.getJobId(), exception);
return InboundAllocationResult.failure("RESERVATION_RELEASE_FAILED", safeMessage(exception));
}
}
return allocate(cleared, deviceCode);
}
public void completeInbound(MydoJob job) {
if (!facade.routingPolicy().algorithmOwnsDecision()) {
return;
}
String reservationId = InboundReservationIds.forJob(job.getJobId());
ReservationResult released = facade.releaseInboundReservation(warehouseId(job), reservationId);
if (released.status() != ReservationStatus.RELEASED
&& released.status() != ReservationStatus.NOT_FOUND) {
throw new IllegalStateException("Inbound reservation cannot be released: "
+ (released.reasonCode() == null ? released.status().name() : released.reasonCode()));
}
}
private InboundAllocationResult legacy(MydoJob job, String deviceCode) {
HashMap<String, Object> parameters = new HashMap<>();
parameters.put("v_tray_code", job.getTrayCode());
parameters.put("v_code", deviceCode);
parameters.put("v_result", null);
parameters.put("v_resultmsg", null);
jobMapper.allotInJobSpace(parameters);
String result = String.valueOf(parameters.get("v_result"));
if (!"10".equals(result)) {
return InboundAllocationResult.failure("LEGACY_" + result,
String.valueOf(parameters.get("v_resultmsg")));
}
MydoJob allocated = jobMapper.selectInJobByTaskNo(job.getTaskNo());
return allocated == null
? InboundAllocationResult.failure("LEGACY_RESULT_MISSING", "Allocated job cannot be reloaded")
: InboundAllocationResult.success(allocated);
}
private void admit(MydoJob job) {
if (admission != null) {
admission.assertAllowed(warehouseId(job),
com.ruoyi.algorithm.wms.tidy.ExecutionWorkType.INBOUND);
}
}
private InboundRequest toRequest(MydoJob job, InboundTaskContext context) {
String requestId = nonBlank(job.getTaskNo()) ? job.getTaskNo() : job.getJobId();
return new InboundRequest(requestId, job.getTrayCode(), context.projectNo(), context.productId(),
context.lotNo(), null, null, null, Set.of(), BatchLaneMode.OPEN);
}
private String warehouseId(MydoJob job) {
return nonBlank(job.getWarehouseId()) ? job.getWarehouseId() : facade.defaultWarehouseId();
}
private boolean nonBlank(String value) {
return value != null && !value.isBlank();
}
private String safeMessage(RuntimeException exception) {
return exception.getMessage() == null ? exception.getClass().getSimpleName() : exception.getMessage();
}
}

View File

@@ -0,0 +1,211 @@
package com.ruoyi.algorithm.wms;
import com.ruoyi.algorithm.integration.SchedulingDecisionStatus;
import com.ruoyi.algorithm.integration.SchedulingFacade;
import com.ruoyi.algorithm.integration.SchedulingRoutingPolicy;
import com.ruoyi.algorithm.outbound.OutboundAssignment;
import com.ruoyi.algorithm.outbound.OutboundPlan;
import com.ruoyi.algorithm.outbound.OutboundPlanStatus;
import com.ruoyi.algorithm.outbound.OutboundRequest;
import com.ruoyi.out.outStockout.domain.OutStockout;
import com.ruoyi.out.outStockout.mapper.OutStockoutMapper;
import com.ruoyi.out.outStockoutDetail.domain.OutStockoutDetail;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.HashMap;
import java.util.Comparator;
import java.util.List;
@Service
public class WmsOutboundAllocationService {
private static final Logger log = LoggerFactory.getLogger(WmsOutboundAllocationService.class);
private final SchedulingFacade facade;
private final WmsAlgorithmMapper algorithmMapper;
private final OutStockoutMapper stockoutMapper;
private final OutboundWorkflowCoordinator workflowCoordinator;
private final OutboundWorkflowTransaction workflowTransaction;
private final com.ruoyi.algorithm.wms.tidy.ExecutionAdmissionService admission;
public WmsOutboundAllocationService(SchedulingFacade facade, WmsAlgorithmMapper algorithmMapper,
OutStockoutMapper stockoutMapper, OutboundWorkflowCoordinator workflowCoordinator,
OutboundWorkflowTransaction workflowTransaction) {
this(facade, algorithmMapper, stockoutMapper, workflowCoordinator, workflowTransaction, null);
}
@Autowired
public WmsOutboundAllocationService(SchedulingFacade facade, WmsAlgorithmMapper algorithmMapper,
OutStockoutMapper stockoutMapper, OutboundWorkflowCoordinator workflowCoordinator,
OutboundWorkflowTransaction workflowTransaction,
com.ruoyi.algorithm.wms.tidy.ExecutionAdmissionService admission) {
this.facade = facade;
this.algorithmMapper = algorithmMapper;
this.stockoutMapper = stockoutMapper;
this.workflowCoordinator = workflowCoordinator;
this.workflowTransaction = workflowTransaction;
this.admission = admission;
}
@Transactional(rollbackFor = Exception.class)
public OutboundAllocationResult allocateProject(OutStockout stockout, OutStockoutDetail detail) {
admit(stockout);
SchedulingRoutingPolicy routing = facade.routingPolicy();
if (!routing.runAlgorithm()) {
return legacyAuto(detail);
}
String projectNo = trimToNull(detail.getSpare4());
if (projectNo == null) {
return OutboundAllocationResult.rejected("PROJECT_NO_REQUIRED",
"Outbound detail has no project number");
}
OutboundRequest request = new OutboundRequest(detail.getStockoutDetailId(), null, projectNo,
null, "OFF", 0, 1, true);
return planAndRoute(stockout, detail, request, null, true, routing);
}
@Transactional(rollbackFor = Exception.class)
public OutboundAllocationResult allocateExactStock(OutStockout stockout, OutStockoutDetail detail,
String stockId) {
admit(stockout);
SchedulingRoutingPolicy routing = facade.routingPolicy();
if (!routing.runAlgorithm()) {
return legacyManual(detail, stockId, null);
}
OutboundStockReference selected = algorithmMapper.selectOutboundStockReference(stockId);
if (selected == null || !warehouseId(stockout).equals(selected.warehouseId())) {
return OutboundAllocationResult.rejected("STOCK_NOT_FOUND",
"Selected stock does not exist in this warehouse");
}
OutboundRequest request = new OutboundRequest(detail.getStockoutDetailId() + ":" + stockId,
selected.trayCode(), null, null, "OFF", 0, 1, true);
return planAndRoute(stockout, detail, request, selected, false, routing);
}
private OutboundAllocationResult planAndRoute(OutStockout stockout, OutStockoutDetail detail,
OutboundRequest request, OutboundStockReference exactStock, boolean projectRequest,
SchedulingRoutingPolicy routing) {
OutboundPlan plan;
try {
plan = facade.planOutbound(warehouseId(stockout), request);
} catch (RuntimeException exception) {
log.error("Java outbound planning failed for detail {}", detail.getStockoutDetailId(), exception);
if (routing.runLegacy(SchedulingDecisionStatus.TECHNICAL_ERROR)) {
return projectRequest ? legacyAuto(detail) : legacyManual(detail, exactStock.stockId(), null);
}
return OutboundAllocationResult.rejected("ALGORITHM_TECHNICAL_ERROR", safeMessage(exception));
}
SchedulingDecisionStatus decision = decision(plan);
if (routing.runLegacy(decision)) {
OutboundAllocationResult legacy = projectRequest ? legacyAuto(detail)
: legacyManual(detail, exactStock.stockId(), null);
log.info("Outbound shadow comparison detail={} javaStatus={} javaCode={} legacyCode={}",
detail.getStockoutDetailId(), plan.status(), planCode(plan), legacy.code());
return legacy;
}
if (plan.status() == OutboundPlanStatus.WAITING) {
var waiting = plan.waiting().orElseThrow();
return OutboundAllocationResult.waiting(waiting.code().name(), waiting.reason());
}
if (plan.status() == OutboundPlanStatus.ERROR) {
var error = plan.error().orElseThrow();
return OutboundAllocationResult.rejected(error.code().name(), error.message());
}
OutboundAssignment assignment = plan.assignment().orElseThrow();
OutboundStockReference selected = exactStock == null
? resolveProjectStock(stockout, detail, assignment) : exactStock;
if (selected == null) {
return OutboundAllocationResult.rejected("AMBIGUOUS_STOCK",
"Algorithm assignment no longer resolves to one available stock row");
}
if (!assignment.sourceSpaceId().equals(selected.spaceId())
|| !assignment.trayNo().equals(selected.trayCode())) {
return OutboundAllocationResult.rejected("ASSIGNMENT_CHANGED",
"Selected stock moved after outbound planning");
}
if (assignment.workflow().isPresent()) {
return workflowCoordinator.start(stockout, detail, selected, assignment);
}
return workflowTransaction.commitShallow(stockout, detail, selected, assignment);
}
private OutboundStockReference resolveProjectStock(OutStockout stockout, OutStockoutDetail detail,
OutboundAssignment assignment) {
List<OutboundStockReference> matches = algorithmMapper.selectOutboundStockReferences(
warehouseId(stockout), assignment.sourceSpaceId(), assignment.trayNo(),
trimToNull(detail.getSpare4()));
return matches.stream()
.min(Comparator.comparing(OutboundStockReference::stockId))
.orElse(null);
}
private OutboundAllocationResult legacyAuto(OutStockoutDetail detail) {
HashMap<String, String> parameters = new HashMap<>();
parameters.put("v_stockout_detail_id", detail.getStockoutDetailId());
parameters.put("v_result", null);
parameters.put("v_resultmsg", null);
stockoutMapper.autoAllot(parameters);
return procedureResult(parameters, null);
}
private OutboundAllocationResult legacyManual(OutStockoutDetail detail, String stockId,
OutboundAssignment assignment) {
HashMap<String, String> parameters = new HashMap<>();
parameters.put("v_stockout_detail_id", detail.getStockoutDetailId());
parameters.put("v_stock_id", stockId);
parameters.put("v_result", null);
parameters.put("v_resultmsg", null);
stockoutMapper.manualAllot(parameters);
return procedureResult(parameters, assignment);
}
private OutboundAllocationResult procedureResult(HashMap<String, String> parameters,
OutboundAssignment assignment) {
String result = String.valueOf(parameters.get("v_result"));
String message = String.valueOf(parameters.get("v_resultmsg"));
return "10".equals(result)
? OutboundAllocationResult.ready("READY", message, assignment)
: OutboundAllocationResult.rejected("LEGACY_" + result, message);
}
private SchedulingDecisionStatus decision(OutboundPlan plan) {
return switch (plan.status()) {
case READY -> SchedulingDecisionStatus.READY;
case WAITING -> SchedulingDecisionStatus.WAITING;
case ERROR -> SchedulingDecisionStatus.REJECTED;
};
}
private String planCode(OutboundPlan plan) {
return switch (plan.status()) {
case READY -> "READY";
case WAITING -> plan.waiting().orElseThrow().code().name();
case ERROR -> plan.error().orElseThrow().code().name();
};
}
private String warehouseId(OutStockout stockout) {
String value = trimToNull(stockout.getWarehouseId());
return value == null ? facade.defaultWarehouseId() : value;
}
private String trimToNull(String value) {
return value == null || value.isBlank() ? null : value.trim();
}
private String safeMessage(RuntimeException exception) {
return exception.getMessage() == null ? exception.getClass().getSimpleName() : exception.getMessage();
}
private void admit(OutStockout stockout) {
if (admission != null) {
admission.assertAllowed(warehouseId(stockout),
com.ruoyi.algorithm.wms.tidy.ExecutionWorkType.OUTBOUND);
}
}
}

View File

@@ -0,0 +1,32 @@
package com.ruoyi.algorithm.wms.tidy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import java.util.Objects;
@Service
public class ExecutionAdmissionService {
private final TidyModeService modeService;
public ExecutionAdmissionService(TidyModeService modeService) {
this.modeService = modeService;
}
@Transactional(propagation = Propagation.MANDATORY)
public void assertAllowed(String warehouseId, ExecutionWorkType workType) {
Objects.requireNonNull(workType, "workType");
TidyEffectiveState state = modeService.statusForAdmission(requireWarehouse(warehouseId)).effectiveState();
if (!workType.allowedIn(state)) {
throw new ExecutionBlockedByTidyModeException(state, workType);
}
}
private String requireWarehouse(String warehouseId) {
if (warehouseId == null || warehouseId.isBlank()) {
throw new IllegalArgumentException("warehouseId is required");
}
return warehouseId.trim();
}
}

View File

@@ -0,0 +1,7 @@
package com.ruoyi.algorithm.wms.tidy;
public class ExecutionBlockedByTidyModeException extends IllegalStateException {
public ExecutionBlockedByTidyModeException(TidyEffectiveState state, ExecutionWorkType workType) {
super("Execution work " + workType + " is blocked while tidy mode is " + state);
}
}

View File

@@ -0,0 +1,20 @@
package com.ruoyi.algorithm.wms.tidy;
public enum ExecutionWorkType {
DOCUMENT_RECEIPT,
INBOUND,
OUTBOUND,
OUTBOUND_RELOCATION,
AUTO_TIDY,
MANUAL_TIDY;
public boolean allowedIn(TidyEffectiveState state) {
if (this == DOCUMENT_RECEIPT) {
return true;
}
if (state == TidyEffectiveState.NORMAL) {
return this != MANUAL_TIDY;
}
return state == TidyEffectiveState.TIDY_ACTIVE && this == MANUAL_TIDY;
}
}

View File

@@ -0,0 +1,78 @@
package com.ruoyi.algorithm.wms.tidy;
import com.ruoyi.algorithm.integration.AlgorithmProperties;
import com.ruoyi.algorithm.integration.SchedulingFacade;
import com.ruoyi.algorithm.tidy.TidyCandidate;
import com.ruoyi.algorithm.wms.WmsAlgorithmMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.time.Instant;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
@Component
public class ManualTidyScheduler {
private static final Logger log = LoggerFactory.getLogger(ManualTidyScheduler.class);
private final TidyModeService modeService;
private final WcsVehicleSnapshotClient vehicleClient;
private final TidyVehicleCapacity capacity = new TidyVehicleCapacity();
private final SchedulingFacade facade;
private final TidyWorkflowTransaction workflows;
private final TidyWorkflowRecoveryService recovery;
private final WmsAlgorithmMapper mapper;
private final String warehouseId;
private final AlgorithmProperties properties;
public ManualTidyScheduler(TidyModeService modeService, WcsVehicleSnapshotClient vehicleClient,
SchedulingFacade facade, TidyWorkflowTransaction workflows, TidyWorkflowRecoveryService recovery,
WmsAlgorithmMapper mapper,
AlgorithmProperties properties) {
this.modeService = modeService;
this.vehicleClient = vehicleClient;
this.facade = facade;
this.workflows = workflows;
this.recovery = recovery;
this.mapper = mapper;
this.warehouseId = properties.getWarehouseId();
this.properties = properties;
}
@Scheduled(fixedDelayString = "${fortucky.algorithm.tidy-reconcile-ms:5000}")
public void reconcileAndFill() {
if (properties.getMode() != com.ruoyi.algorithm.integration.SchedulingMode.ACTIVE
|| !properties.isDatabaseWritesEnabled()) return;
recovery.reconcile(warehouseId);
TidyModeSnapshot mode = modeService.reconcile(warehouseId);
if (mode.effectiveState() != TidyEffectiveState.TIDY_ACTIVE || !mode.requestedEnabled()) return;
List<VehicleSnapshot> vehicles = vehicleClient.fetch();
Set<String> assigned = new HashSet<>(mapper.selectActiveManualTidyVehicleIds(warehouseId));
TidyVehicleCapacity.CapacityResult result = capacity.calculate(
vehicles, mapper.countActiveManualTidy(warehouseId), assigned);
if (result.newSlots() == 0) return;
Iterator<VehicleSnapshot> vehicleIterator = vehicles.stream()
.filter(VehicleSnapshot::availableForManualTidy)
.filter(vehicle -> !assigned.contains(vehicle.vehicleId()))
.iterator();
Iterator<TidyCandidate> candidateIterator = facade.planTidy(warehouseId, Instant.now())
.candidates().iterator();
int remaining = result.newSlots();
while (remaining-- > 0 && vehicleIterator.hasNext() && candidateIterator.hasNext()) {
VehicleSnapshot vehicle = vehicleIterator.next();
TidyCandidate candidate = candidateIterator.next();
try {
var workflowId = workflows.start(TidyOrigin.MANUAL_TIDY, warehouseId, candidate);
mapper.assignTidyWorkflowVehicle(workflowId.toString(), vehicle.vehicleId());
} catch (RuntimeException ex) {
log.warn("Unable to start manual tidy workflow for vehicle {}", vehicle.vehicleId(), ex);
}
}
}
}

View File

@@ -0,0 +1,41 @@
package com.ruoyi.algorithm.wms.tidy;
import com.ruoyi.algorithm.integration.AlgorithmProperties;
import com.ruoyi.algorithm.integration.SchedulingMode;
import com.ruoyi.algorithm.wms.WmsAlgorithmMapper;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;
@Component
public class ReplayExecutionGuard implements ApplicationRunner {
private final AlgorithmProperties properties;
private final WmsAlgorithmMapper mapper;
public ReplayExecutionGuard(AlgorithmProperties properties, WmsAlgorithmMapper mapper) {
this.properties = properties;
this.mapper = mapper;
}
@Override
public void run(ApplicationArguments args) {
validate();
}
public void validate() {
if (properties.getReplayRunId() == null || properties.getReplayRunId().isBlank()) {
return;
}
if (properties.getMode() != SchedulingMode.ACTIVE || !properties.isDatabaseWritesEnabled()) {
throw new IllegalStateException("REPLAY_REQUIRES_ACTIVE_WRITES");
}
if (properties.getReplayDatabase() == null || properties.getReplayDatabase().isBlank()) {
throw new IllegalStateException("REPLAY_DATABASE_REQUIRED");
}
String actual = mapper.selectDatabaseName();
if (!properties.getReplayDatabase().equalsIgnoreCase(actual)) {
throw new IllegalStateException("REPLAY_DATABASE_MISMATCH expected="
+ properties.getReplayDatabase() + " actual=" + actual);
}
}
}

View File

@@ -0,0 +1,42 @@
package com.ruoyi.algorithm.wms.tidy;
import com.ruoyi.algorithm.integration.AlgorithmProperties;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Map;
@RestController
@RequestMapping("/algorithm/tidy")
public class TidyController extends BaseController {
private final TidyModeService modeService;
private final AlgorithmProperties properties;
public TidyController(TidyModeService modeService, AlgorithmProperties properties) {
this.modeService = modeService;
this.properties = properties;
}
@PreAuthorize("@ss.hasPermi('algorithm:tidy:query')")
@GetMapping("/status")
public AjaxResult status() {
return AjaxResult.success(modeService.status(properties.getWarehouseId()));
}
@PreAuthorize("@ss.hasPermi('algorithm:tidy:edit')")
@PutMapping("/mode")
public AjaxResult mode(@RequestBody Map<String, Object> body) {
Object enabled = body == null ? null : body.get("enabled");
if (!(enabled instanceof Boolean)) {
return AjaxResult.error("enabled must be true or false");
}
return AjaxResult.success(modeService.requestManualMode(
properties.getWarehouseId(), (Boolean) enabled, getUsername()));
}
}

View File

@@ -0,0 +1,8 @@
package com.ruoyi.algorithm.wms.tidy;
public enum TidyEffectiveState {
NORMAL,
ENTERING_TIDY,
TIDY_ACTIVE,
EXITING_TIDY
}

View File

@@ -0,0 +1,28 @@
package com.ruoyi.algorithm.wms.tidy;
import java.sql.Timestamp;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.UUID;
public record TidyLaneClaim(String warehouseId, String laneCode, long dirtyVersion,
UUID claimToken, LocalDateTime leaseExpiresAt) {
public TidyLaneClaim(String warehouseId, String laneCode, long dirtyVersion,
UUID claimToken, Instant leaseExpiresAt) {
this(warehouseId, laneCode, dirtyVersion, claimToken,
leaseExpiresAt == null ? null : LocalDateTime.ofInstant(leaseExpiresAt, ZoneOffset.UTC));
}
public TidyLaneClaim(String warehouseId, String laneCode, long dirtyVersion,
String claimToken, Timestamp leaseExpiresAt) {
this(warehouseId, laneCode, dirtyVersion,
claimToken == null ? null : UUID.fromString(claimToken),
leaseExpiresAt == null ? null : leaseExpiresAt.toLocalDateTime());
}
public boolean validAt(Instant now) {
return claimToken != null && leaseExpiresAt != null
&& leaseExpiresAt.isAfter(LocalDateTime.ofInstant(now, ZoneOffset.UTC));
}
}

View File

@@ -0,0 +1,126 @@
package com.ruoyi.algorithm.wms.tidy;
import com.ruoyi.algorithm.wms.WmsAlgorithmMapper;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
@Service
public class TidyModeService {
private static final String SYSTEM_ACTOR = "system";
private final WmsAlgorithmMapper mapper;
public TidyModeService(WmsAlgorithmMapper mapper) {
this.mapper = mapper;
}
@Transactional(readOnly = true)
public TidyModeSnapshot status(String warehouseId) {
return requireMode(mapper.selectTidyMode(requireWarehouse(warehouseId)), warehouseId);
}
@Transactional(propagation = Propagation.MANDATORY)
public TidyModeSnapshot statusForAdmission(String warehouseId) {
String normalizedWarehouse = requireWarehouse(warehouseId);
return requireMode(mapper.selectTidyModeForUpdate(normalizedWarehouse), normalizedWarehouse);
}
@Transactional(rollbackFor = Exception.class)
public TidyModeSnapshot requestManualMode(String warehouseId, boolean enabled, String actor) {
String normalizedWarehouse = requireWarehouse(warehouseId);
String normalizedActor = requireActor(actor);
TidyModeSnapshot current = requireMode(
mapper.selectTidyModeForUpdate(normalizedWarehouse), normalizedWarehouse);
if (current.requestedEnabled() == enabled) {
return current;
}
TidyEffectiveState nextState = enabled
? TidyEffectiveState.ENTERING_TIDY
: TidyEffectiveState.EXITING_TIDY;
String reason = enabled ? "MANUAL_MODE_REQUESTED" : "MANUAL_MODE_RELEASED";
return update(current, enabled, nextState, current.drainCount(),
current.activeTidyCount(), reason, normalizedActor);
}
@Transactional(rollbackFor = Exception.class)
public TidyModeSnapshot reconcile(String warehouseId) {
String normalizedWarehouse = requireWarehouse(warehouseId);
TidyModeSnapshot current = requireMode(
mapper.selectTidyModeForUpdate(normalizedWarehouse), normalizedWarehouse);
int businessCount = mapper.countActiveBusinessExecution(normalizedWarehouse);
int tidyCount = mapper.countActiveManualTidy(normalizedWarehouse);
Transition transition = transition(current, businessCount, tidyCount);
if (transition == null) {
return current.withRuntimeCounts(businessCount, tidyCount);
}
return update(current, transition.requestedEnabled(), transition.state(),
businessCount, tidyCount, transition.reason(), SYSTEM_ACTOR);
}
private Transition transition(TidyModeSnapshot current, int businessCount, int tidyCount) {
if (current.requestedEnabled()) {
if (current.effectiveState() == TidyEffectiveState.NORMAL) {
return new Transition(true, TidyEffectiveState.ENTERING_TIDY, "MANUAL_MODE_REQUESTED");
}
if (current.effectiveState() == TidyEffectiveState.ENTERING_TIDY && businessCount == 0) {
return new Transition(true, TidyEffectiveState.TIDY_ACTIVE, "BUSINESS_DRAINED");
}
if (current.effectiveState() == TidyEffectiveState.EXITING_TIDY) {
TidyEffectiveState state = businessCount == 0
? TidyEffectiveState.TIDY_ACTIVE
: TidyEffectiveState.ENTERING_TIDY;
return new Transition(true, state, "MANUAL_MODE_REENABLED");
}
return null;
}
if (current.effectiveState() == TidyEffectiveState.NORMAL) {
return null;
}
if (current.effectiveState() != TidyEffectiveState.EXITING_TIDY) {
return new Transition(false, TidyEffectiveState.EXITING_TIDY, "MANUAL_MODE_RELEASED");
}
if (businessCount == 0 && tidyCount == 0) {
return new Transition(false, TidyEffectiveState.NORMAL, "TIDY_DRAINED");
}
return null;
}
private TidyModeSnapshot update(TidyModeSnapshot current, boolean requested,
TidyEffectiveState state, int businessCount, int tidyCount, String reason, String actor) {
int updated = mapper.setTidyModeRequest(current.warehouseId(), requested, state.name(),
reason, actor, current.version());
if (updated != 1) {
throw new IllegalStateException("TIDY_MODE_VERSION_CONFLICT warehouse=" + current.warehouseId()
+ " expectedVersion=" + current.version());
}
return current.transition(requested, state, businessCount, tidyCount, reason, actor);
}
private TidyModeSnapshot requireMode(TidyModeSnapshot snapshot, String warehouseId) {
if (snapshot == null) {
throw new IllegalStateException("TIDY_MODE_NOT_INITIALIZED warehouse=" + warehouseId);
}
return snapshot;
}
private String requireWarehouse(String warehouseId) {
if (warehouseId == null || warehouseId.isBlank()) {
throw new IllegalArgumentException("warehouseId is required");
}
return warehouseId.trim();
}
private String requireActor(String actor) {
if (actor == null || actor.isBlank()) {
throw new IllegalArgumentException("actor is required");
}
return actor.trim();
}
private record Transition(boolean requestedEnabled, TidyEffectiveState state, String reason) {
}
}

View File

@@ -0,0 +1,26 @@
package com.ruoyi.algorithm.wms.tidy;
import java.time.LocalDateTime;
public record TidyModeSnapshot(
String warehouseId,
boolean requestedEnabled,
TidyEffectiveState effectiveState,
int drainCount,
int activeTidyCount,
String statusReason,
long version,
String updatedBy,
LocalDateTime updatedAt) {
public TidyModeSnapshot transition(boolean requested, TidyEffectiveState state,
int businessCount, int tidyCount, String reason, String actor) {
return new TidyModeSnapshot(warehouseId, requested, state, businessCount, tidyCount,
reason, version + 1, actor, LocalDateTime.now());
}
public TidyModeSnapshot withRuntimeCounts(int businessCount, int tidyCount) {
return new TidyModeSnapshot(warehouseId, requestedEnabled, effectiveState,
businessCount, tidyCount, statusReason, version, updatedBy, updatedAt);
}
}

View File

@@ -0,0 +1,3 @@
package com.ruoyi.algorithm.wms.tidy;
public enum TidyOrigin { AUTO_TIDY, MANUAL_TIDY }

View File

@@ -0,0 +1,99 @@
package com.ruoyi.algorithm.wms.tidy;
import com.ruoyi.algorithm.integration.SchedulingFacade;
import com.ruoyi.algorithm.tidy.TidyCandidate;
import com.ruoyi.algorithm.tidy.TidyPlan;
import com.ruoyi.algorithm.wms.WmsAlgorithmMapper;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import java.time.Instant;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
@Component
public class TidyScheduler {
private final TidyModeService modeService;
private final ExecutionAdmissionService admission;
private final WmsAlgorithmMapper mapper;
private final SchedulingFacade facade;
private final TidyWorkflowStarter starter;
private final String warehouseId;
private final int leaseSeconds;
private final com.ruoyi.algorithm.integration.AlgorithmProperties properties;
public TidyScheduler(TidyModeService modeService, ExecutionAdmissionService admission,
WmsAlgorithmMapper mapper, SchedulingFacade facade, TidyWorkflowStarter starter,
com.ruoyi.algorithm.integration.AlgorithmProperties properties) {
this.modeService = modeService;
this.admission = admission;
this.mapper = mapper;
this.facade = facade;
this.starter = starter;
this.warehouseId = properties.getWarehouseId();
this.leaseSeconds = properties.getTidyClaimLeaseSeconds();
this.properties = properties;
}
@Scheduled(fixedDelayString = "${fortucky.algorithm.tidy-auto-scan-ms:600000}")
@Transactional(rollbackFor = Exception.class)
public void scanAutomatic() {
if (properties.getMode() != com.ruoyi.algorithm.integration.SchedulingMode.ACTIVE
|| !properties.isDatabaseWritesEnabled()) return;
if (modeService.status(warehouseId).effectiveState() != TidyEffectiveState.NORMAL) return;
TidyPlan plan = facade.planTidy(warehouseId, Instant.now());
Map<String, TidyCandidate> candidatesByLane = indexCandidatesBySourceLane(plan);
admission.assertAllowed(warehouseId, ExecutionWorkType.AUTO_TIDY);
if (mapper.countActiveBusinessExecution(warehouseId) > 0 || mapper.countActiveAutomaticTidy() > 0) return;
if (candidatesByLane.isEmpty()) {
completeOneUnmatchedClaim();
return;
}
String eligibleLaneCodes = String.join(",", candidatesByLane.keySet());
TidyLaneClaim claim = mapper.claimTidyLaneFromCandidates(
warehouseId, eligibleLaneCodes, "tidy-scheduler", leaseSeconds);
if (claim == null || !claim.validAt(Instant.now())) {
completeOneUnmatchedClaim();
return;
}
try {
TidyCandidate candidate = candidatesByLane.get(claim.laneCode());
if (candidate == null) {
releaseClaims(List.of(claim), false, "PLANNED_LANE_CLAIM_MISMATCH");
return;
}
starter.startAutomatic(claim, candidate);
} catch (RuntimeException exception) {
releaseClaims(List.of(claim), false, exception.getMessage());
}
}
private void completeOneUnmatchedClaim() {
TidyLaneClaim claim = mapper.claimTidyLane(warehouseId, "tidy-scheduler", leaseSeconds);
if (claim != null && claim.validAt(Instant.now())) {
releaseClaims(List.of(claim), true, "NO_SAFE_CANDIDATE");
}
}
private Map<String, TidyCandidate> indexCandidatesBySourceLane(TidyPlan plan) {
Map<String, TidyCandidate> candidatesByLane = new LinkedHashMap<>();
for (TidyCandidate candidate : plan.candidates()) {
candidate.moves().forEach(move -> {
String laneCode = mapper.selectLaneCodeForSpace(warehouseId, move.fromSpaceId());
if (laneCode != null) candidatesByLane.putIfAbsent(laneCode, candidate);
});
}
return candidatesByLane;
}
private void releaseClaims(List<TidyLaneClaim> claims, boolean completed, String reason) {
for (TidyLaneClaim held : claims) {
mapper.releaseTidyLane(held.warehouseId(), held.laneCode(), held.claimToken(),
held.dirtyVersion(), completed, reason);
}
}
}

View File

@@ -0,0 +1,21 @@
package com.ruoyi.algorithm.wms.tidy;
import java.util.List;
import java.util.Set;
public final class TidyVehicleCapacity {
public CapacityResult calculate(List<VehicleSnapshot> vehicles, int activeManualWorkflows,
Set<String> assignedManualVehicleIds) {
int effective = (int) vehicles.stream()
.filter(VehicleSnapshot::availableForManualTidy)
.count();
int assigned = assignedManualVehicleIds == null ? 0 : (int) assignedManualVehicleIds.stream()
.filter(id -> vehicles.stream().anyMatch(v -> v.vehicleId().equals(id)
&& v.online() && v.healthy()))
.count();
int available = Math.max(0, effective - Math.max(activeManualWorkflows, assigned));
return new CapacityResult(effective, available);
}
public record CapacityResult(int effectiveCapacity, int newSlots) { }
}

View File

@@ -0,0 +1,23 @@
package com.ruoyi.algorithm.wms.tidy;
import com.ruoyi.algorithm.tidy.TidyCandidate;
import org.springframework.stereotype.Service;
import java.util.UUID;
@Service
public class TidyWorkflowCoordinator {
private final TidyWorkflowTransaction transaction;
public TidyWorkflowCoordinator(TidyWorkflowTransaction transaction) {
this.transaction = transaction;
}
public UUID start(TidyOrigin origin, String warehouseId, TidyCandidate candidate) {
return transaction.start(origin, warehouseId, candidate);
}
public boolean onJobFinished(String jobId, String callbackStage) {
return transaction.onJobFinished(jobId, callbackStage);
}
}

View File

@@ -0,0 +1,9 @@
package com.ruoyi.algorithm.wms.tidy;
import com.ruoyi.algorithm.tidy.TidyCandidate;
import java.util.UUID;
public interface TidyWorkflowStarter {
UUID startAutomatic(TidyLaneClaim claim, TidyCandidate candidate);
}

View File

@@ -0,0 +1,8 @@
package com.ruoyi.algorithm.wms.tidy;
public record VehicleSnapshot(String vehicleId, boolean online, boolean healthy,
boolean idle, String taskType) {
public boolean availableForManualTidy() {
return online && healthy && idle;
}
}

View File

@@ -0,0 +1,62 @@
package com.ruoyi.algorithm.wms.tidy;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONUtil;
import com.ruoyi.algorithm.integration.AlgorithmProperties;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.Map;
@Component
public class WcsVehicleSnapshotClient {
private static final Logger log = LoggerFactory.getLogger(WcsVehicleSnapshotClient.class);
private final AlgorithmProperties properties;
public WcsVehicleSnapshotClient(AlgorithmProperties properties) {
this.properties = properties;
}
public List<VehicleSnapshot> fetch() {
String url = properties.getTidyWcsSnapshotUrl();
if (url == null || url.isBlank()) {
return List.of();
}
try {
String body = HttpUtil.get(url, 3_000);
if (body == null || body.isBlank()) {
return List.of();
}
var response = JSONUtil.parseObj(body);
Object data = response.get("data");
if (data == null || !JSONUtil.isTypeJSON(data.toString())) {
return List.of();
}
return JSONUtil.parseArray(data).stream()
.map(JSONUtil::parseObj)
.map(row -> new VehicleSnapshot(
firstNonBlank(row, "vehicleId", "guid", "deviceName", "deviceId"),
bool(row.get("online")), bool(row.get("healthy")), bool(row.get("idle")),
String.valueOf(row.getOrDefault("taskType", ""))))
.toList();
} catch (Exception ex) {
log.warn("Unable to fetch WCS tidy vehicle snapshot from {}", url, ex);
return List.of();
}
}
private static String firstNonBlank(Map<String, Object> row, String... keys) {
for (String key : keys) {
Object value = row.get(key);
if (value != null && !value.toString().isBlank()) return value.toString();
}
return "unknown";
}
private static boolean bool(Object value) {
return Boolean.TRUE.equals(value) || "1".equals(value) || "true".equalsIgnoreCase(String.valueOf(value));
}
}

View File

@@ -0,0 +1,78 @@
package com.ruoyi.api.controller;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
public class BatchNoGenerator{
// 日期格式化模板:固定生成 yyyyMMdd 格式
private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyyMMdd");
// 原子引用:存储当前日期,CAS保证【日期判断+重置】的原子性
private static final AtomicReference<String> CURRENT_DATE =
new AtomicReference<>(LocalDate.now().format(DATE_FORMATTER));
// 原子整数:流水号计数器,CPU级指令保证自增原子性
private static final AtomicInteger SERIAL_NUMBER = new AtomicInteger(1);
// 流水号最大长度(4位,最大值9999)
private static final int MAX_SERIAL = 9999;
private static final String SERIAL_FORMAT = "%04d";
/**
* 生成唯一批号(多线程安全,原子操作)
* @return yyyyMMdd+4位流水号
*/
public static String generateBatchNo() {
// 获取当前系统日期
String today = LocalDate.now().format(DATE_FORMATTER);
// CAS自旋:保证日期判断、重置、计数的原子性
while (true) {
// 读取缓存的日期
String cacheDate = CURRENT_DATE.get();
// 场景1:当天未跨天,直接生成流水号
if (today.equals(cacheDate)) {
// 原子自增获取当前序号
int currentNum = SERIAL_NUMBER.getAndIncrement();
// 防止4位流水号溢出(超过9999)
if (currentNum > MAX_SERIAL) {
// 重置序号,抛出异常提示
SERIAL_NUMBER.set(1);
throw new RuntimeException("当日批号已达上限:" + MAX_SERIAL);
}
// 拼接日期+4位流水号,返回结果
return today + String.format(SERIAL_FORMAT, currentNum);
}
// 场景2:跨天了,CAS原子更新日期并重置流水号
if (CURRENT_DATE.compareAndSet(cacheDate, today)) {
// 只有一个线程能执行到这里,重置为1
SERIAL_NUMBER.set(1);
return today + String.format(SERIAL_FORMAT, 1);
}
// CAS更新失败:说明其他线程已完成跨天重置,重新循环
}
}
public static void main(String[] args) throws InterruptedException {
// 模拟20个线程同时生成批号
for (int i = 0; i < 20; i++) {
new Thread(() -> {
String batchNo = generateBatchNo();
System.out.println("线程:" + Thread.currentThread().getName() + ",生成批号:" + batchNo);
}).start();
}
Thread.sleep(1000);
System.out.println("=== 所有批号生成完成,无重复、无乱序 ===");
}
}

View File

@@ -1,13 +1,19 @@
package com.ruoyi.api.controller;
import cn.hutool.json.JSONUtil;
import com.ruoyi.api.moveMsg.domain.MoveMsg;
import com.ruoyi.api.service.IToErpService;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.log.service.IRequestLogService;
import com.ruoyi.pda.mapper.PdaMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.web.bind.annotation.*;
import com.ruoyi.api.domain.DeliveryNoticeVo;
import java.util.HashMap;
/**
* 作业统计 Controller
*/
@@ -19,6 +25,8 @@ public class ToErpApiController {
private IToErpService toErpService;
@Autowired
private IRequestLogService requestLogService;
@Autowired
private PdaMapper pdaMapper;
/**
* 接收入出库通知单
@@ -28,7 +36,7 @@ public class ToErpApiController {
public AjaxResult receiveDeliveryNotice(@RequestBody DeliveryNoticeVo deliveryNoticeVo) {
AjaxResult ajaxResult = toErpService.receiveDeliveryNotice(deliveryNoticeVo);
requestLogService.insertRequestLog(requestLogService.getRequestLog(deliveryNoticeVo.toString(), "接收入出库通知单", ajaxResult));
requestLogService.insertRequestLog(requestLogService.getRequestLogERP(JSONUtil.toJsonStr(deliveryNoticeVo), "接收入出库通知单", ajaxResult));
return ajaxResult;
@@ -36,22 +44,107 @@ public class ToErpApiController {
/**
* 回传其他入库单
* 回传入库单
*/
// @Scheduled(fixedDelay = 1500)
@Scheduled(fixedDelay = 1500)
@RequestMapping("/callbackInDeliveryNotice")
@ResponseBody
public void callbackInDeliveryNotice() {
toErpService.callbackInDeliveryNotice();
public void callbackInDeliveryNoticeNew() {
toErpService.callbackInDeliveryNoticeNew();
}
/**
* 回传出库单(新)
*/
@Scheduled(fixedDelay = 1500)
@RequestMapping("/callbackOutDeliveryNotice")
@ResponseBody
public void callbackDeliveryOutNoticeNew() {
toErpService.callbackDeliveryOutNoticeNew();
}
// @Scheduled(fixedDelay = 1500)
// @RequestMapping("/callbackOutDeliveryNotice")
// @ResponseBody
// public void callbackDeliveryOutNoticeNewS() {
// toErpService.callbackDeliveryOutNoticeNews();
// }
// /**
// * 回传其他入库单
// */
// @Scheduled(fixedDelay = 1500)
// @RequestMapping("/callbackInDeliveryNotice")
// @ResponseBody
// public void callbackInDeliveryNotice() {
// toErpService.callbackInDeliveryNotice();
// }
//
// /**
// * 回传其他出库单
// */
// @Scheduled(fixedDelay = 1500)
// @RequestMapping("/callbackOutDeliveryNotice")
// @ResponseBody
// public void callbackDeliveryOutNotice() {
// toErpService.callbackoutDeliveryNotice();
// }
/**
* 移库回调接口
*/
@Scheduled(fixedDelay = 1500)
@RequestMapping("/moveCargoSpace")
@ResponseBody
public void moveCargoSpace() {
toErpService.moveCargoSpace();
}
/**
* 回传其他出库单
* 自动确认入库单据
*/
@RequestMapping("/callbackOutDeliveryNotice")
@Scheduled(fixedDelay = 10000)
// @RequestMapping("/FillFinishAllot")
@ResponseBody
public void callbackDeliveryOutNotice() {
toErpService.callbackoutDeliveryNotice();
public void FillFinishAllot() {
HashMap<String, Object> map = new HashMap<>();
map.put("v_result", null);
map.put("v_result_msg", null);
pdaMapper.FillFinishAllot(map);
String result = map.get("v_result").toString();
String msg = map.get("v_result_msg").toString();
if ("10".equals(result)) {
System.err.println(msg);
} else {
// System.err.println(msg);
}
}
/**
* 自动确认出库单据
*/
@Scheduled(fixedDelay = 10000)
// @RequestMapping("/FillFinishAllot")
@ResponseBody
public void FillFinishAllotOut() {
HashMap<String, Object> map = new HashMap<>();
map.put("v_result", null);
map.put("v_result_msg", null);
pdaMapper.FillFinishAllotOut(map);
String result = map.get("v_result").toString();
String msg = map.get("v_result_msg").toString();
if ("10".equals(result)) {
System.err.println(msg);
} else {
// System.err.println(msg);
}
}
}

View File

@@ -1,5 +1,6 @@
package com.ruoyi.api.controller;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.ruoyi.api.domain.ErpProduct;
import com.ruoyi.api.domain.ReMaterialParam;
@@ -11,6 +12,10 @@ import com.ruoyi.bas.BasProduct.service.IBasProductService;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.device.agv.domain.AgvContainerTask;
import com.ruoyi.device.agv.service.IAgvContainerTaskService;
import com.ruoyi.job.mydojob.domain.MydoJob;
import com.ruoyi.job.mydojob.mapper.MydoJobMapper;
import com.ruoyi.log.domain.RequestLog;
import com.ruoyi.log.service.IRequestLogService;
import com.ruoyi.out.outStockout.domain.OutStockoutVo;
@@ -19,7 +24,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import java.util.Map;
import java.util.*;
/**
* 作业统计 Controller
@@ -36,6 +41,10 @@ public class ToWmsApiController {
private IOutStockoutService outStockoutService;
@Autowired
private IBasProductService basProductService;
@Autowired
private MydoJobMapper mapper;
@Autowired
private IAgvContainerTaskService agvContainerTaskService;
/**
* 入库请求生成作业
@@ -43,18 +52,50 @@ public class ToWmsApiController {
@PostMapping("/requestEnterByTrayCode")
public AjaxResult requestEnterByTrayCode(@RequestBody RequestEnter requestEnter) {
AjaxResult ajaxResult = toWmsService.requestEnterByTrayCode(requestEnter);
RequestLog requestLog = requestLogService.getRequestLog(JSONUtil.toJsonStr(requestEnter), "入库任务创建请求",ajaxResult);
RequestLog requestLog = requestLogService.getRequestLog(JSONUtil.toJsonStr(requestEnter), "入库任务创建请求", ajaxResult);
requestLogService.insertRequestLog(requestLog);
return ajaxResult;
}
// 入库分货位
@PostMapping("/sendCargoSpace")
public AjaxResult sendCargoSpace(@RequestBody RequestEnter requestEnter) {
AjaxResult ajaxResult = toWmsService.requestEnterByTaskNo(requestEnter);
RequestLog requestLog = requestLogService.getRequestLog(JSONUtil.toJsonStr(requestEnter), "入库请求分配货位", ajaxResult);
requestLogService.insertRequestLog(requestLog);
return ajaxResult;
}
// 出库到位更新LED显示屏
@PostMapping("/updateLed")
public AjaxResult updateLed(@RequestBody RequestEnter requestEnter) {
HashMap<String, Object> map = new HashMap<>();
map.put("v_task_no", requestEnter.getTaskNo());
map.put("v_code", requestEnter.getDeviceCode());
mapper.updateLed(map);
return AjaxResult.success();
}
// 线体报警更新报警信息
@PostMapping("/updateLedError")
public AjaxResult updateLedError(@RequestBody RequestEnter requestEnter) {
HashMap<String, Object> map = new HashMap<>();
map.put("v_code", requestEnter.getDeviceCode());
map.put("v_error_code", requestEnter.getErrorCode());
mapper.updateLedError(map);
return AjaxResult.success();
}
/**
* 请求补码作业
*/
@RequestMapping("/requestByNoTrayCode")
public AjaxResult requestByNoTrayCode(@RequestBody RequestEnter requestEnter) {
AjaxResult ajaxResult = toWmsService.selectMydoJobByEntranceId(requestEnter);
RequestLog requestLog = requestLogService.getRequestLog(JSONUtil.toJsonStr(requestEnter), "请求补码作业",ajaxResult);
RequestLog requestLog = requestLogService.getRequestLog(JSONUtil.toJsonStr(requestEnter), "请求补码作业", ajaxResult);
requestLogService.insertRequestLog(requestLog);
return ajaxResult;
}
@@ -65,7 +106,7 @@ public class ToWmsApiController {
@RequestMapping("/requestEnterByTrayCodeAndEntranceId")
public AjaxResult requestEnterByTrayCodeAndEntranceId(@RequestBody RequestEnter requestEnter) {
AjaxResult ajaxResult = toWmsService.requestEnterByTrayCodeAndEntranceId(requestEnter);
RequestLog requestLog = requestLogService.getRequestLog(JSONUtil.toJsonStr(requestEnter), "获取入库作业",ajaxResult);
RequestLog requestLog = requestLogService.getRequestLog(JSONUtil.toJsonStr(requestEnter), "获取入库作业", ajaxResult);
requestLogService.insertRequestLog(requestLog);
return ajaxResult;
}
@@ -74,18 +115,17 @@ public class ToWmsApiController {
/**
* 入库、出库 任务完成回传
* Map<String, String>
* "wmsType": "任务类型" 1-入库 2-出库 3-agv搬运,
* taskNo:出库 入库任务号
* trayCode:托盘码
* positionCode1:起点
* positionCode2:终点
* containerCode:容器编码
*
* "wmsType": "任务类型" 1-入库 2-出库 3-agv搬运,
* taskNo:出库 入库任务号
* trayCode:托盘码
* positionCode1:起点
* positionCode2:终点
* containerCode:容器编码
*/
@PostMapping("/jobFinish")
public AjaxResult jobFinish(@RequestBody WmsJobRequest wmsJobRequest) {
AjaxResult ajaxResult = toWmsService.jobFinish(wmsJobRequest);
RequestLog requestLog = requestLogService.getRequestLog(JSONUtil.toJsonStr(wmsJobRequest), "jobFinish",ajaxResult);
RequestLog requestLog = requestLogService.getRequestLog(JSONUtil.toJsonStr(wmsJobRequest), "jobFinish", ajaxResult);
requestLogService.insertRequestLog(requestLog);
return ajaxResult;
}
@@ -96,7 +136,7 @@ public class ToWmsApiController {
@PostMapping("/reAssign")
public AjaxResult reAssign(@RequestBody ReMaterialParam reMaterialParam) {
AjaxResult ajaxResult = toWmsService.reAssign(reMaterialParam);
RequestLog requestLog = requestLogService.getRequestLog(JSONUtil.toJsonStr(reMaterialParam), "reAssign",ajaxResult);
RequestLog requestLog = requestLogService.getRequestLog(JSONUtil.toJsonStr(reMaterialParam), "reAssign", ajaxResult);
requestLogService.insertRequestLog(requestLog);
return ajaxResult;
}
@@ -107,13 +147,12 @@ public class ToWmsApiController {
@PostMapping("/reMaterial")
public AjaxResult reMaterial(@RequestBody ReMaterialParam reMaterialParam) {
AjaxResult ajaxResult = toWmsService.reMaterial(reMaterialParam);
RequestLog requestLog = requestLogService.getRequestLog(JSONUtil.toJsonStr(reMaterialParam), "reMaterial",ajaxResult);
RequestLog requestLog = requestLogService.getRequestLog(JSONUtil.toJsonStr(reMaterialParam), "reMaterial", ajaxResult);
requestLogService.insertRequestLog(requestLog);
return ajaxResult;
}
/**
* 出库单据保存
*
@@ -137,8 +176,7 @@ public class ToWmsApiController {
*/
@Log(title = "接收物料", businessType = BusinessType.INSERT)
@PutMapping("/receiveProduct")
public AjaxResult receiveProduct(@RequestBody ErpProduct erpProduct)
{
public AjaxResult receiveProduct(@RequestBody ErpProduct erpProduct) {
AjaxResult ajaxResult = toWmsService.receiveProduct(erpProduct);
RequestLog requestLog = requestLogService.getRequestLog(JSONUtil.toJsonStr(erpProduct), "接收物料", ajaxResult);
requestLogService.insertRequestLog(requestLog);
@@ -150,8 +188,7 @@ public class ToWmsApiController {
*/
@Log(title = "修改物料管理", businessType = BusinessType.UPDATE)
@PutMapping("/updateProduct")
public AjaxResult updateProduct(@RequestBody ErpProduct erpProduct)
{
public AjaxResult updateProduct(@RequestBody ErpProduct erpProduct) {
AjaxResult ajaxResult = toWmsService.updateProduct(erpProduct);
RequestLog requestLog = requestLogService.getRequestLog(JSONUtil.toJsonStr(erpProduct), "修改物料管理", ajaxResult);
requestLogService.insertRequestLog(requestLog);
@@ -163,12 +200,76 @@ public class ToWmsApiController {
*/
@Log(title = "作废物料", businessType = BusinessType.UPDATE)
@PutMapping("/InvalidProduct")
public AjaxResult InvalidProduct(@RequestBody ErpProduct erpProduct)
{
public AjaxResult InvalidProduct(@RequestBody ErpProduct erpProduct) {
AjaxResult ajaxResult = toWmsService.InvalidProduct(erpProduct);
RequestLog requestLog = requestLogService.getRequestLog(JSONUtil.toJsonStr(erpProduct), "作废物料", ajaxResult);
requestLogService.insertRequestLog(requestLog);
return ajaxResult;
}
/**
* 请求AGV执行队列
*/
// @Log(title = "请求未下发的AGV执行队列", businessType = BusinessType.OTHER)
@RequestMapping("/queryAgvQuene")
public AjaxResult queryAgvQuene() {
AgvContainerTask agvContainerTask = new AgvContainerTask();
agvContainerTask.setStatus("0");
List<AgvContainerTask> agvContainerTasks = agvContainerTaskService.selectAgvContainerTaskList(agvContainerTask);
RequestLog requestLog = requestLogService.getRequestLog(JSONUtil.toJsonStr(""), "请求未下发的AGV执行队列", AjaxResult.success(agvContainerTasks));
requestLogService.insertRequestLog(requestLog);
if (agvContainerTasks != null && agvContainerTasks.size() > 0) {
for (AgvContainerTask containerTask : agvContainerTasks) {
containerTask.setStatus("1");
agvContainerTaskService.updateAgvContainerTask(containerTask);
}
return AjaxResult.success(agvContainerTasks.get(0));
} else {
return AjaxResult.error("无队列");
}
}
/**
* 请求AGV执行队列
*/
@Log(title = "完成AGV执行队列", businessType = BusinessType.UPDATE)
@RequestMapping("/finishAgvQuene")
public AjaxResult finishAgvQuene(@RequestBody JSONObject jsonObject) {
String order = (String) jsonObject.get("order");
agvContainerTaskService.deleteAgvJobByOrder(order);
return AjaxResult.success();
}
@Log(title = "自动生成Agv搬运队列到线边", businessType = BusinessType.INSERT)
@PutMapping("/insertAgvQuene")
public AjaxResult insertAgvQuene(@RequestBody WmsJobRequest wmsJobRequest) {
String taskNo = wmsJobRequest.getTaskNo();// 到位任务号
String code = wmsJobRequest.getCode();// 线体号
AgvContainerTask agvContainerTask = new AgvContainerTask();
agvContainerTask.setTaskNo(taskNo);
List<AgvContainerTask> agvContainerTasks = agvContainerTaskService.selectAgvContainerTaskList(agvContainerTask);
if (Objects.isNull(agvContainerTasks)) {
MydoJob mydoJob = new MydoJob();
mydoJob.setTaskNo(taskNo);
List<MydoJob> mydoJobs = mapper.selectMydoJobList(mydoJob);
AgvContainerTask agvContainerTask1 = new AgvContainerTask();
agvContainerTask1.setContainer(UUID.randomUUID().toString());
agvContainerTask1.setTaskNo(taskNo);
agvContainerTask1.setStartPoint(code);
agvContainerTask1.setEndPoint(mydoJobs.get(0).getEndPoint());//TODO 需要修改
agvContainerTask1.setSpare2(mydoJobs.get(0).getTrayCode());
// 10缓存区到线边 11立库到线边 12 立库到缓存区 13 缓存到立库
agvContainerTask1.setSpare1("11");
agvContainerTask1.setStatus("0");
agvContainerTaskService.insertAgvContainerTask(agvContainerTask1);
}
RequestLog requestLog = requestLogService.getRequestLog(JSONUtil.toJsonStr(wmsJobRequest), "自动生成Agv搬运队列到线边", AjaxResult.success());
requestLogService.insertRequestLog(requestLog);
return AjaxResult.success();
}
}

View File

@@ -7,6 +7,7 @@ import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.annotation.Anonymous;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@@ -23,6 +24,7 @@ public class TwinController {
@Autowired
private ITwinService twinService;
//获取所有货位
@Anonymous
@GetMapping("/getEmptyCargoSpace")
public AjaxResult getEmptyCargoSpace() {
@@ -30,10 +32,25 @@ public class TwinController {
return AjaxResult.success(list);
}
//获取统计信息
@Anonymous
@GetMapping("/getStockList")
public Map<String, Object> getStockList() {
return twinService.getStockListOverview();
}
//根据货位号获取库存中的物料信息
@Anonymous
@GetMapping("/getCargo/{cargoSpaceName}")
public Map<String, Object> getCargo(@PathVariable("cargoSpaceName") String cargoSpaceName) {
return twinService.getCargo(cargoSpaceName);
}
//根据任务号获取作业表中的物料信息
@Anonymous
@GetMapping("/getTaskCargo/{taskNo}")
public Map<String, Object> getTaskCargo(@PathVariable("taskNo") String taskNo) {
return twinService.getTaskCargo(taskNo);
}
}

View File

@@ -0,0 +1,70 @@
package com.ruoyi.api.domain;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import java.io.Serializable;
import java.util.List;
@NoArgsConstructor
@Data
@Getter
@Setter
public class CallBackErp implements Serializable {
/**
* | 方向 | 字段名 | 对应方向 | 字段名 |
* | ------- | ---------------- | -------- | -------- |
* | ERP→WMS | companyShortName | WMS→ERP | ccompany | 公司简称
* | ERP→WMS | accountSetNo | WMS→ERP | cacc_id | 账套号
* | ERP→WMS | warehouseId | WMS→ERP | cwhcode | 仓库
* | ERP→WMS | customerId | WMS→ERP | cvencode | 客户
* | ERP→WMS | customerName | WMS→ERP | cvenname | 客户名称
* | ERP→WMS | remark | WMS→ERP | cmemo |
*
*/
// 公司名称
@JsonProperty("ccompany")
private String ccompany;
// WMS单据号
@JsonProperty("ccode")
private String ccode;
// 操作日期
@JsonProperty("ddate")
private String ddate;
// 业务类型
@JsonProperty("cintype")
private String cintype;
// 供应商编码
@JsonProperty("cvencode")
private String cvencode;
// 供应商名称
@JsonProperty("cvenname")
private String cvenname;
// 出/入库人 操作人
@JsonProperty("coptname")
private String coptname;
// 仓库编码
@JsonProperty("cwhcode")
private String cwhcode;
// 仓库名称
@JsonProperty("cwhname")
private String cwhname;
// 备注
@JsonProperty("cmemo")
private String cmemo;
// 账套号
@JsonProperty("cacc_id")
private String cacc_id;
// 子明细
@JsonProperty("details")
private List<CallBackErpItems> details;
}

View File

@@ -0,0 +1,68 @@
package com.ruoyi.api.domain;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import java.io.Serializable;
import java.util.List;
@NoArgsConstructor
@Data
@Getter
@Setter
public class CallBackErpItems implements Serializable {
/**
*
* | 方向 | 字段名 | 对应方向 | 字段名 |
* | ------- | ------------- | -------- | --------- |
* | ERP→WMS | lineNo | WMS→ERP | srcrowno |
* | ERP→WMS | sourceLineId | WMS→ERP | srcids |
* | ERP→WMS | oldProjectNo | WMS→ERP | cxmh |
* | ERP→WMS | projectNo | WMS→ERP | cnewxmh |
* | ERP→WMS | isBatchManage | WMS→ERP | binvbatch |
* | ERP→WMS | lotNo | WMS→ERP | cbatch |
*/
@JsonProperty("cinvcode")
private String cinvcode;
@JsonProperty("cinvname")
private String cinvname;
@JsonProperty("cinvstd")
private String cinvstd;
@JsonProperty("cinvm_unit")
private String cinvm_unit;
@JsonProperty("cposcode")
private String cposcode;
@JsonProperty("cposname")
private String cposname;
@JsonProperty("ctrayname")
private String ctrayname;
@JsonProperty("cbatch")
private String cbatch;
@JsonProperty("iquantity")
private Integer iquantity;
@JsonProperty("cxmh")
private String cxmh;
@JsonProperty("cnewxmh")
private String cnewxmh;
@JsonProperty("srccode")
private String srccode;
@JsonProperty("srcids")
private Integer srcids;
@JsonProperty("srcrowno")
private String srcrowno;
@JsonProperty("binvbatch")
private Integer binvbatch;
@JsonProperty("jobid")
private String jobid;
@JsonProperty("stg_location")
private String stg_location;
@JsonProperty("groupNum")
private String groupNum;
}

View File

@@ -4,6 +4,9 @@ import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
import org.w3c.dom.stylesheets.LinkStyle;
import java.util.List;
/**
* 出入库通知单-子表接收对象
@@ -42,7 +45,38 @@ public class DeliveryNoticeItemVo {
/** 备注 */
private String remark;
private List<LocationDetail> locations;
/**货位*/
private String area;
/**托盘*/
private String location;
private String areaBefore;
private String locationBefore;
/** 项目号 */
private String projectNo;
/**
* erp子表主键
***/
private String sourceLineId;
/**
* 条码号
***/
private String barCode;
/**
* 是否批次管理
**/
private String isBatchManage;
/**旧项目号**/
private String oldProjectNo;
/**组件号**/
private String groupNum;
/**存放地点 1 立库 2平库*/
private String stg_location;
}

View File

@@ -49,6 +49,17 @@ public class DeliveryNoticeVo {
private String warehouseId;
/** 备注 */
private String remark;
/** 配送终点 */
private String destination;
/** 领料车间 */
private String workshop;
private String companyShortName;
/** 账套号**/
private String accountSetNo;
/** 子表明细列表 */
private List<DeliveryNoticeItemVo> detailList;
}

View File

@@ -0,0 +1,44 @@
package com.ruoyi.api.domain;
public class LocationDetail {
private String locationNo;
private String areaNo;
private String quantity;
private String lotNo;
public String getLocationNo() {
return locationNo;
}
public void setLocationNo(String locationNo) {
this.locationNo = locationNo;
}
public String getAreaNo() {
return areaNo;
}
public void setAreaNo(String areaNo) {
this.areaNo = areaNo;
}
public String getQuantity() {
return quantity;
}
public void setQuantity(String quantity) {
this.quantity = quantity;
}
public String getLotNo() {
return lotNo;
}
public void setLotNo(String lotNo) {
this.lotNo = lotNo;
}
}

View File

@@ -20,4 +20,8 @@ public class RequestEnter {
private String type;
private String flag;
private String taskNo;
private String deviceCode;
private String code;
private String errorCode;
}

View File

@@ -24,4 +24,6 @@ public class WmsJobRequest {
private String positionCode2;
//任务id
private String jobId;
//线体号
private String code;
}

View File

@@ -0,0 +1,104 @@
package com.ruoyi.api.moveMsg.controller;
import java.util.List;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.api.moveMsg.domain.MoveMsg;
import com.ruoyi.api.moveMsg.service.IMoveMsgService;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.common.core.page.TableDataInfo;
/**
* 移库信息回传Controller
*
* @author ruoyi
* @date 2026-01-29
*/
@RestController
@RequestMapping("/api/moveMsg")
public class MoveMsgController extends BaseController
{
@Autowired
private IMoveMsgService moveMsgService;
/**
* 查询移库信息回传列表
*/
@PreAuthorize("@ss.hasPermi('api:moveMsg:list')")
@GetMapping("/list")
public TableDataInfo list(MoveMsg moveMsg)
{
startPage();
List<MoveMsg> list = moveMsgService.selectMoveMsgList(moveMsg);
return getDataTable(list);
}
/**
* 导出移库信息回传列表
*/
@PreAuthorize("@ss.hasPermi('api:moveMsg:export')")
@Log(title = "移库信息回传", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(HttpServletResponse response, MoveMsg moveMsg)
{
List<MoveMsg> list = moveMsgService.selectMoveMsgList(moveMsg);
ExcelUtil<MoveMsg> util = new ExcelUtil<MoveMsg>(MoveMsg.class);
util.exportExcel(response, list, "移库信息回传数据");
}
/**
* 获取移库信息回传详细信息
*/
@PreAuthorize("@ss.hasPermi('api:moveMsg:query')")
@GetMapping(value = "/{id}")
public AjaxResult getInfo(@PathVariable("id") String id)
{
return success(moveMsgService.selectMoveMsgById(id));
}
/**
* 新增移库信息回传
*/
@PreAuthorize("@ss.hasPermi('api:moveMsg:add')")
@Log(title = "移库信息回传", businessType = BusinessType.INSERT)
@PostMapping
public AjaxResult add(@RequestBody MoveMsg moveMsg)
{
return toAjax(moveMsgService.insertMoveMsg(moveMsg));
}
/**
* 修改移库信息回传
*/
@PreAuthorize("@ss.hasPermi('api:moveMsg:edit')")
@Log(title = "移库信息回传", businessType = BusinessType.UPDATE)
@PutMapping
public AjaxResult edit(@RequestBody MoveMsg moveMsg)
{
return toAjax(moveMsgService.updateMoveMsg(moveMsg));
}
/**
* 删除移库信息回传
*/
@PreAuthorize("@ss.hasPermi('api:moveMsg:remove')")
@Log(title = "移库信息回传", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public AjaxResult remove(@PathVariable String[] ids)
{
return toAjax(moveMsgService.deleteMoveMsgByIds(ids));
}
}

View File

@@ -0,0 +1,202 @@
package com.ruoyi.api.moveMsg.domain;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import com.ruoyi.common.annotation.Excel;
import com.ruoyi.common.core.domain.BaseEntity;
/**
* 移库信息回传对象 move_msg
*
* @author ruoyi
* @date 2026-01-29
*/
public class MoveMsg extends BaseEntity
{
private static final long serialVersionUID = 1L;
/** 序号 */
private String id;
/** 托盘条码 */
@Excel(name = "托盘条码")
private String trayCode;
/** 原货位 */
@Excel(name = "原货位")
private String oldSpace;
/** 新货位 */
@Excel(name = "新货位")
private String newSpace;
/** 状态 */
@Excel(name = "状态")
private String status;
/** 发送时间 */
@Excel(name = "发送时间")
private String sendTime;
/** 信息 */
@Excel(name = "信息")
private String msg;
/** 备用 */
@Excel(name = "备用")
private String spare1;
/** 备用 */
@Excel(name = "备用")
private String spare2;
/** 备用 */
@Excel(name = "备用")
private String spare3;
/** 备用 */
@Excel(name = "备用")
private String spare4;
/** 备用 */
@Excel(name = "备用")
private String spare5;
public void setId(String id)
{
this.id = id;
}
public String getId()
{
return id;
}
public void setTrayCode(String trayCode)
{
this.trayCode = trayCode;
}
public String getTrayCode()
{
return trayCode;
}
public void setOldSpace(String oldSpace)
{
this.oldSpace = oldSpace;
}
public String getOldSpace()
{
return oldSpace;
}
public void setNewSpace(String newSpace)
{
this.newSpace = newSpace;
}
public String getNewSpace()
{
return newSpace;
}
public void setStatus(String status)
{
this.status = status;
}
public String getStatus()
{
return status;
}
public void setSendTime(String sendTime)
{
this.sendTime = sendTime;
}
public String getSendTime()
{
return sendTime;
}
public void setMsg(String msg)
{
this.msg = msg;
}
public String getMsg()
{
return msg;
}
public void setSpare1(String spare1)
{
this.spare1 = spare1;
}
public String getSpare1()
{
return spare1;
}
public void setSpare2(String spare2)
{
this.spare2 = spare2;
}
public String getSpare2()
{
return spare2;
}
public void setSpare3(String spare3)
{
this.spare3 = spare3;
}
public String getSpare3()
{
return spare3;
}
public void setSpare4(String spare4)
{
this.spare4 = spare4;
}
public String getSpare4()
{
return spare4;
}
public void setSpare5(String spare5)
{
this.spare5 = spare5;
}
public String getSpare5()
{
return spare5;
}
@Override
public String toString() {
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
.append("id", getId())
.append("trayCode", getTrayCode())
.append("oldSpace", getOldSpace())
.append("newSpace", getNewSpace())
.append("status", getStatus())
.append("sendTime", getSendTime())
.append("msg", getMsg())
.append("spare1", getSpare1())
.append("spare2", getSpare2())
.append("spare3", getSpare3())
.append("spare4", getSpare4())
.append("spare5", getSpare5())
.toString();
}
}

View File

@@ -0,0 +1,61 @@
package com.ruoyi.api.moveMsg.mapper;
import java.util.List;
import com.ruoyi.api.moveMsg.domain.MoveMsg;
/**
* 移库信息回传Mapper接口
*
* @author ruoyi
* @date 2026-01-29
*/
public interface MoveMsgMapper
{
/**
* 查询移库信息回传
*
* @param id 移库信息回传主键
* @return 移库信息回传
*/
public MoveMsg selectMoveMsgById(String id);
/**
* 查询移库信息回传列表
*
* @param moveMsg 移库信息回传
* @return 移库信息回传集合
*/
public List<MoveMsg> selectMoveMsgList(MoveMsg moveMsg);
/**
* 新增移库信息回传
*
* @param moveMsg 移库信息回传
* @return 结果
*/
public int insertMoveMsg(MoveMsg moveMsg);
/**
* 修改移库信息回传
*
* @param moveMsg 移库信息回传
* @return 结果
*/
public int updateMoveMsg(MoveMsg moveMsg);
/**
* 删除移库信息回传
*
* @param id 移库信息回传主键
* @return 结果
*/
public int deleteMoveMsgById(String id);
/**
* 批量删除移库信息回传
*
* @param ids 需要删除的数据主键集合
* @return 结果
*/
public int deleteMoveMsgByIds(String[] ids);
}

View File

@@ -0,0 +1,61 @@
package com.ruoyi.api.moveMsg.service;
import java.util.List;
import com.ruoyi.api.moveMsg.domain.MoveMsg;
/**
* 移库信息回传Service接口
*
* @author ruoyi
* @date 2026-01-29
*/
public interface IMoveMsgService
{
/**
* 查询移库信息回传
*
* @param id 移库信息回传主键
* @return 移库信息回传
*/
public MoveMsg selectMoveMsgById(String id);
/**
* 查询移库信息回传列表
*
* @param moveMsg 移库信息回传
* @return 移库信息回传集合
*/
public List<MoveMsg> selectMoveMsgList(MoveMsg moveMsg);
/**
* 新增移库信息回传
*
* @param moveMsg 移库信息回传
* @return 结果
*/
public int insertMoveMsg(MoveMsg moveMsg);
/**
* 修改移库信息回传
*
* @param moveMsg 移库信息回传
* @return 结果
*/
public int updateMoveMsg(MoveMsg moveMsg);
/**
* 批量删除移库信息回传
*
* @param ids 需要删除的移库信息回传主键集合
* @return 结果
*/
public int deleteMoveMsgByIds(String[] ids);
/**
* 删除移库信息回传信息
*
* @param id 移库信息回传主键
* @return 结果
*/
public int deleteMoveMsgById(String id);
}

View File

@@ -0,0 +1,93 @@
package com.ruoyi.api.moveMsg.service.impl;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.api.moveMsg.mapper.MoveMsgMapper;
import com.ruoyi.api.moveMsg.domain.MoveMsg;
import com.ruoyi.api.moveMsg.service.IMoveMsgService;
/**
* 移库信息回传Service业务层处理
*
* @author ruoyi
* @date 2026-01-29
*/
@Service
public class MoveMsgServiceImpl implements IMoveMsgService
{
@Autowired
private MoveMsgMapper moveMsgMapper;
/**
* 查询移库信息回传
*
* @param id 移库信息回传主键
* @return 移库信息回传
*/
@Override
public MoveMsg selectMoveMsgById(String id)
{
return moveMsgMapper.selectMoveMsgById(id);
}
/**
* 查询移库信息回传列表
*
* @param moveMsg 移库信息回传
* @return 移库信息回传
*/
@Override
public List<MoveMsg> selectMoveMsgList(MoveMsg moveMsg)
{
return moveMsgMapper.selectMoveMsgList(moveMsg);
}
/**
* 新增移库信息回传
*
* @param moveMsg 移库信息回传
* @return 结果
*/
@Override
public int insertMoveMsg(MoveMsg moveMsg)
{
return moveMsgMapper.insertMoveMsg(moveMsg);
}
/**
* 修改移库信息回传
*
* @param moveMsg 移库信息回传
* @return 结果
*/
@Override
public int updateMoveMsg(MoveMsg moveMsg)
{
return moveMsgMapper.updateMoveMsg(moveMsg);
}
/**
* 批量删除移库信息回传
*
* @param ids 需要删除的移库信息回传主键
* @return 结果
*/
@Override
public int deleteMoveMsgByIds(String[] ids)
{
return moveMsgMapper.deleteMoveMsgByIds(ids);
}
/**
* 删除移库信息回传信息
*
* @param id 移库信息回传主键
* @return 结果
*/
@Override
public int deleteMoveMsgById(String id)
{
return moveMsgMapper.deleteMoveMsgById(id);
}
}

View File

@@ -1,6 +1,7 @@
package com.ruoyi.api.service;
import com.ruoyi.api.domain.DeliveryNoticeVo;
import com.ruoyi.api.moveMsg.domain.MoveMsg;
import com.ruoyi.bas.BasProduct.domain.BasProduct;
import com.ruoyi.common.core.domain.AjaxResult;
@@ -16,5 +17,13 @@ public interface IToErpService {
void callbackoutDeliveryNotice();
void moveCargoSpace();
AjaxResult createWorkshopInboundOrder(BasProduct basProduct);
void callbackInDeliveryNoticeNew();
void callbackDeliveryOutNoticeNew();
void callbackDeliveryOutNoticeNews();
}

View File

@@ -59,4 +59,6 @@ public interface IToWmsService {
* 作废物料
*/
AjaxResult InvalidProduct(ErpProduct erpProduct);
AjaxResult requestEnterByTaskNo(RequestEnter requestEnter);
}

View File

@@ -4,5 +4,7 @@ import java.util.Map;
public interface ITwinService {
Map<String, Object> getStockListOverview();
Map<String, Object> getCargo(String cargoSpaceName);
Map<String, Object> getTaskCargo(String taskNo);
}

View File

@@ -33,7 +33,7 @@ public class ToWcsServiceImpl implements IToWcsService {
@Autowired
private IAgvContainerTaskService agvContainerTaskService;
public static final String PUSH_OUT_MYDO_JOB = "http://localhost:8081/wcs2Wms/api/receiveOutMydoJob";
public static final String PUSH_OUT_MYDO_JOB = "http://192.168.188.236:8081/wcs2Wms/api/receiveOutMydoJob";
public static final String PUSH_IN_MYDO_JOB = "http://localhost:8081/wcs2Wms/api/receiveInMydoJob";
public static final String PUSH_AGV_MOVE_JOB = "http://localhost:8081/agv/api/receiveAgvMoveJob";
public static final String OUT_MYDOJOB_MS = "http://localhost:8081/wcs2Wms/api/outMydojobMakesure";
@@ -43,15 +43,12 @@ public class ToWcsServiceImpl implements IToWcsService {
@Override
// @Scheduled(fixedDelay=1500)
@Scheduled(fixedDelay=1500)
public void pushOutMydoJob() {
//查询所有未推送的料箱出库作业
MydoJob mydoJobParam = new MydoJob();
mydoJobParam.setStatus("1");
List<String> list = new ArrayList<>();
list.add("21");
list.add("26");
mydoJobParam.setInOutIds(list);
mydoJobParam.setInOut("2");
List<MydoJob> outMydoJobs = mydoJobService.selectMydoJobListApi(mydoJobParam);
for (MydoJob outMydoJob : outMydoJobs) {
RequestLog requestLog = requestLogService.getRequestLog(PUSH_OUT_MYDO_JOB, JSONUtil.toJsonStr(outMydoJob), "推送出库任务","wms","wcs");

View File

@@ -6,6 +6,10 @@ import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.ruoyi.algorithm.wms.InboundAllocationResult;
import com.ruoyi.algorithm.wms.OutboundWorkflowCoordinator;
import com.ruoyi.algorithm.wms.WmsInboundAllocationService;
import com.ruoyi.algorithm.wms.tidy.TidyWorkflowTransaction;
import com.ruoyi.api.domain.*;
import com.ruoyi.api.service.IToErpService;
import com.ruoyi.api.service.IToWmsService;
@@ -34,6 +38,7 @@ import com.ruoyi.job.mydojob.mapper.MydoJobMapper;
import com.ruoyi.job.mydojob.service.IMydoJobService;
import com.ruoyi.job.mydojobdetail.domain.MydoJobDetail;
import com.ruoyi.job.mydojobdetail.service.IMydoJobDetailService;
import com.ruoyi.job.mydojobfinish.service.IMydoJobFinishService;
import com.ruoyi.log.service.IRequestLogService;
import com.ruoyi.out.outStockout.service.IOutStockoutService;
import com.ruoyi.stock.stock.domain.BasStock;
@@ -57,6 +62,8 @@ public class ToWmsServiceImpl implements IToWmsService {
@Autowired
private IMydoJobService mydoJobService;
@Autowired
private IMydoJobFinishService mydoJobFinishService;
@Autowired
private IMydoJobDetailService mydoJobDetailService;
@Autowired
private IBasContainerService basContainerService;
@@ -90,30 +97,38 @@ public class ToWmsServiceImpl implements IToWmsService {
private IBasStockService stockService;
@Autowired
private MydoJobMapper mydoJobMapper;
@Autowired
private WmsInboundAllocationService inboundAllocationService;
@Autowired
private OutboundWorkflowCoordinator outboundWorkflowCoordinator;
@Autowired
private TidyWorkflowTransaction tidyWorkflowTransaction;
@Override
@Transactional(rollbackFor = Exception.class)
public AjaxResult requestEnterByTrayCode(RequestEnter requestEnter) {
String trayCode = requestEnter.getTrayCode();
MydoJob inJob = mydoJobMapper.selectInJobByTrayCode(trayCode);
if(inJob != null && Integer.parseInt(inJob.getInOrOut()) < 20){
if(inJob.getCargoSpaceId() != null && !"".equals(inJob.getCargoSpaceId())){
return AjaxResult.success(JSONUtil.toJsonStr(inJob));
}else{
//分配货位
HashMap<String, Object> map = new HashMap<>();
// if(inJob.getCargoSpaceId() != null && !"".equals(inJob.getCargoSpaceId())){
// return AjaxResult.success(inJob);
// }else{
// //分配货位
// HashMap<String, Object> map = new HashMap<>();
//
// map.put("v_tray_code", trayCode);
// mydoJobMapper.allotInJobSpace(map);
// if (!"10".equals(map.get("v_result").toString())) {
// return AjaxResult.error(map.get("v_resultmsg").toString());
// }else{
//
// }
// }
// MydoJob inJob2 = mydoJobMapper.selectInJobByTrayCode(trayCode);
return AjaxResult.success(inJob);
map.put("v_tray_code", trayCode);
mydoJobMapper.allotInJobSpace(map);
if (!"10".equals(map.get("v_result").toString())) {
return AjaxResult.error(map.get("v_resultmsg").toString());
}else{
MydoJob inJob2 = mydoJobMapper.selectInJobByTrayCode(trayCode);
return AjaxResult.success(JSONUtil.toJsonStr(inJob2));
}
}
}else{
return AjaxResult.error("该条码无入库任务,请扫码绑定!");
}
@@ -135,7 +150,7 @@ public class ToWmsServiceImpl implements IToWmsService {
String productId = mydoJobDetail.getProductId();
BasProduct basProduct = basProductService.selectBasProductByProductId(productId);
int size = Convert.toInt(basProduct.getSpare10());
int size = Convert.toInt(basProduct.getSpare10(), 0);
//超大托盘不处理 直接返回
if (size == 5) {
return new AjaxResult(3, "超大托盘");
@@ -164,6 +179,7 @@ public class ToWmsServiceImpl implements IToWmsService {
}
@Override
@Transactional(rollbackFor = Exception.class)
public AjaxResult jobFinish(WmsJobRequest wmsJobRequest) {
MydoJob mydoJobParam = new MydoJob();
switch (wmsJobRequest.getWmsType()) {
@@ -180,10 +196,14 @@ public class ToWmsServiceImpl implements IToWmsService {
mydoJobParam.setJobId(wmsJobRequest.getJobId());
List<MydoJob> inMydoJobs = mydoJobService.selectMydoJobListApi(mydoJobParam);
if (inMydoJobs.isEmpty()) {
if (mydoJobFinishService.selectMydoJobFinishByJobId(wmsJobRequest.getJobId()) != null) {
return AjaxResult.success();
}
return AjaxResult.error("任务不存在");
}
MydoJob inMydoJob = inMydoJobs.get(0);
mydoJobService.manualCompleted(inMydoJob, 1);
inboundAllocationService.completeInbound(inMydoJob);
break;
case "2":
@@ -197,8 +217,28 @@ public class ToWmsServiceImpl implements IToWmsService {
return AjaxResult.error("任务不存在");
}
MydoJob outJob = outMydoJobs.get(0);
//出库作业
outJob.setExecutionPhase("2");
mydoJobService.updateMydoJob(outJob);
if (tidyWorkflowTransaction != null
&& tidyWorkflowTransaction.onJobFinished(outJob.getJobId(), "OUTBOUND_FINISHED")) {
break;
}
outboundWorkflowCoordinator.onJobFinished(outJob.getJobId());
break;
case "7":
//移库作业
mydoJobParam.setTaskNo(wmsJobRequest.getTaskNo());
List<MydoJob> ykMydoJobs = mydoJobService.selectMydoJobListApi(mydoJobParam);
if (ykMydoJobs.isEmpty()) {
return AjaxResult.error("任务不存在");
}
MydoJob ykJob = ykMydoJobs.get(0);
mydoJobService.ykCompleted(ykJob);
if (tidyWorkflowTransaction == null
|| !tidyWorkflowTransaction.onJobFinished(ykJob.getJobId(), "MOVE_FINISHED")) {
outboundWorkflowCoordinator.onJobFinished(ykJob.getJobId());
}
break;
default:
@@ -210,22 +250,17 @@ public class ToWmsServiceImpl implements IToWmsService {
@Override
public AjaxResult reAssign(ReMaterialParam reMaterialParam) {
//重新分配货位
MydoJob mydoJob = mydoJobService.selectMydoJobByJobId(reMaterialParam.getJobId());
String warehouseId = mydoJob.getWarehouseId();
BasCargoSpace basCargoSpaceParam = new BasCargoSpace();
basCargoSpaceParam.setWarehouseId(warehouseId);
basCargoSpaceParam.setRoadwayId(mydoJob.getRoadwayId());
BasCargoSpace basCargoSpace = basCargoSpaceService.selectEmptyCargoSpaceByWarehouseId(basCargoSpaceParam);
if (basCargoSpace == null) {
log.error("没有空货位");
return AjaxResult.error(MessageUtils.message("error.message20"));
} else {
mydoJob.setCargoSpaceId(basCargoSpace.getCargoSpaceId());
mydoJob.setFaultFlag("1");
mydoJobService.updateMydoJob(mydoJob);
return AjaxResult.success(new RequestEnterResponse(basCargoSpace.getCargoSpaceId(), null, mydoJob.getJobId()));
if (mydoJob == null) {
return AjaxResult.error("任务不存在");
}
InboundAllocationResult allocation = inboundAllocationService.reallocate(mydoJob, mydoJob.getEntranceId());
if (!allocation.success()) {
return AjaxResult.error(allocation.message()).put("algorithmCode", allocation.code());
}
MydoJob allocated = allocation.job();
return AjaxResult.success(new RequestEnterResponse(allocated.getCargoSpaceId(),
allocated.getTrayCode(), allocated.getJobId()));
}
@Override
@@ -385,5 +420,24 @@ public class ToWmsServiceImpl implements IToWmsService {
return AjaxResult.error(erpProduct.getSys_MainId()+"物料不存在");
}
@Override
public AjaxResult requestEnterByTaskNo(RequestEnter requestEnter) {
String taskNo = requestEnter.getTaskNo();
String deviceCode = requestEnter.getDeviceCode();
MydoJob inJob = mydoJobMapper.selectInJobByTaskNo(taskNo);
if(inJob != null && Integer.parseInt(inJob.getInOrOut()) < 20){
if(inJob.getCargoSpaceId() != null && !"".equals(inJob.getCargoSpaceId())){
return AjaxResult.success(inJob);
}
InboundAllocationResult allocation = inboundAllocationService.allocate(inJob, deviceCode);
if (!allocation.success()) {
return AjaxResult.error(allocation.message()).put("algorithmCode", allocation.code());
}
return AjaxResult.success(allocation.job());
}else{
return AjaxResult.error("该条码无入库任务,请扫码绑定!");
}
}
}

View File

@@ -5,6 +5,10 @@ import com.ruoyi.bas.cargoSpace.domain.BasCargoSpace;
import com.ruoyi.bas.cargoSpace.service.IBasCargoSpaceService;
import com.ruoyi.in.stockinfinish.domain.InStockinFinish;
import com.ruoyi.in.stockinfinish.service.IInStockinFinishService;
import com.ruoyi.job.mydojob.domain.MydoJob;
import com.ruoyi.job.mydojob.service.IMydoJobService;
import com.ruoyi.job.mydojobdetail.domain.MydoJobDetail;
import com.ruoyi.job.mydojobdetail.service.IMydoJobDetailService;
import com.ruoyi.out.outStockoutFinish.domain.OutStockoutFinish;
import com.ruoyi.out.outStockoutFinish.service.IOutStockoutFinishService;
import com.ruoyi.stock.stock.domain.BasStock;
@@ -33,6 +37,10 @@ public class TwinServiceImpl implements ITwinService {
private IInStockinFinishService inStockinFinishService;
@Autowired
private IOutStockoutFinishService outStockoutFinishService;
@Autowired
private IMydoJobService mydoJobService;
@Autowired
private IMydoJobDetailService mydoJobDetailService;
@Override
public Map<String, Object> getStockListOverview() {
@@ -250,4 +258,62 @@ public class TwinServiceImpl implements ITwinService {
result.put("monthOutStock", monthOutStock);
return result;
}
@Override
public Map<String, Object> getCargo(String cargoSpaceName) {
BasStock basStock = new BasStock();
basStock.setCargoSpaceId(cargoSpaceName);
List<BasStock> list = basStockService.selectBasStockList(basStock);
List<Map<String, String>> dataList = new ArrayList<>();
for (BasStock stock : list) {
Map<String, String> dataMap = new HashMap<>();
dataMap.put("productId", stock.getProductId());
dataMap.put("productName", stock.getProductName());
dataMap.put("quantity", stock.getQuantity());
dataMap.put("trayCode", stock.getTrayCode());
dataList.add(dataMap);
}
Map<String, Object> result = new HashMap<>();
result.put("data", dataList);
return result;
}
@Override
public Map<String, Object> getTaskCargo(String taskNo) {
MydoJob mydoJob = new MydoJob();
mydoJob.setTaskNo(taskNo);
List<MydoJob> jobList = mydoJobService.selectMydoJobList(mydoJob);
List<Map<String, String>> dataList = new ArrayList<>();
if (jobList != null && !jobList.isEmpty()) {
MydoJob job = jobList.get(0);
String jobId = job.getJobId();
String inOrOutStr = job.getInOrOut();
int inOrOut = 0;
try {
inOrOut = Integer.parseInt(inOrOutStr);
} catch (Exception e) {
// Ignore parse error
}
List<MydoJobDetail> details = mydoJobDetailService.selectMydoJobDetailListByJobId(jobId);
for (MydoJobDetail detail : details) {
Map<String, String> dataMap = new HashMap<>();
dataMap.put("productId", detail.getProductId());
dataMap.put("productName", detail.getProductName());
String quantity = "0";
if (inOrOut < 20) {
quantity = detail.getInQuantity();
} else {
quantity = detail.getOutQuantity();
}
dataMap.put("quantity", quantity);
dataMap.put("trayCode", detail.getTrayCode());
dataList.add(dataMap);
}
}
Map<String, Object> result = new HashMap<>();
result.put("data", dataList);
return result;
}
}

View File

@@ -0,0 +1,104 @@
package com.ruoyi.bas.agvPoint.controller;
import java.util.List;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.bas.agvPoint.domain.AgvPoint;
import com.ruoyi.bas.agvPoint.service.IAgvPointService;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.common.core.page.TableDataInfo;
/**
* agv站点Controller
*
* @author ruoyi
* @date 2026-03-17
*/
@RestController
@RequestMapping("/bas/agvPoint")
public class AgvPointController extends BaseController
{
@Autowired
private IAgvPointService agvPointService;
/**
* 查询agv站点列表
*/
@PreAuthorize("@ss.hasPermi('bas:agvPoint:list')")
@GetMapping("/list")
public TableDataInfo list(AgvPoint agvPoint)
{
startPage();
List<AgvPoint> list = agvPointService.selectAgvPointList(agvPoint);
return getDataTable(list);
}
/**
* 导出agv站点列表
*/
@PreAuthorize("@ss.hasPermi('bas:agvPoint:export')")
@Log(title = "agv站点", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(HttpServletResponse response, AgvPoint agvPoint)
{
List<AgvPoint> list = agvPointService.selectAgvPointList(agvPoint);
ExcelUtil<AgvPoint> util = new ExcelUtil<AgvPoint>(AgvPoint.class);
util.exportExcel(response, list, "agv站点数据");
}
/**
* 获取agv站点详细信息
*/
@PreAuthorize("@ss.hasPermi('bas:agvPoint:query')")
@GetMapping(value = "/{id}")
public AjaxResult getInfo(@PathVariable("id") String id)
{
return success(agvPointService.selectAgvPointById(id));
}
/**
* 新增agv站点
*/
@PreAuthorize("@ss.hasPermi('bas:agvPoint:add')")
@Log(title = "agv站点", businessType = BusinessType.INSERT)
@PostMapping
public AjaxResult add(@RequestBody AgvPoint agvPoint)
{
return toAjax(agvPointService.insertAgvPoint(agvPoint));
}
/**
* 修改agv站点
*/
@PreAuthorize("@ss.hasPermi('bas:agvPoint:edit')")
@Log(title = "agv站点", businessType = BusinessType.UPDATE)
@PutMapping
public AjaxResult edit(@RequestBody AgvPoint agvPoint)
{
return toAjax(agvPointService.updateAgvPoint(agvPoint));
}
/**
* 删除agv站点
*/
@PreAuthorize("@ss.hasPermi('bas:agvPoint:remove')")
@Log(title = "agv站点", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public AjaxResult remove(@PathVariable String[] ids)
{
return toAjax(agvPointService.deleteAgvPointByIds(ids));
}
}

View File

@@ -0,0 +1,113 @@
package com.ruoyi.bas.agvPoint.domain;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import com.ruoyi.common.annotation.Excel;
import com.ruoyi.common.core.domain.BaseEntity;
/**
* agv站点对象 agv_point
*
* @author ruoyi
* @date 2026-03-17
*/
public class AgvPoint extends BaseEntity
{
private static final long serialVersionUID = 1L;
/** 序号 */
private String id;
/** 站点编号 */
@Excel(name = "站点编号")
private String station;
/** 类型 */
@Excel(name = "类型")
private String type;
/** $column.columnComment */
@Excel(name = "${comment}", readConverterExp = "$column.readConverterExp()")
private String spare1;
/** $column.columnComment */
@Excel(name = "${comment}", readConverterExp = "$column.readConverterExp()")
private String spare2;
/** $column.columnComment */
@Excel(name = "${comment}", readConverterExp = "$column.readConverterExp()")
private String spare3;
public void setId(String id)
{
this.id = id;
}
public String getId()
{
return id;
}
public void setStation(String station)
{
this.station = station;
}
public String getStation()
{
return station;
}
public void setType(String type)
{
this.type = type;
}
public String getType()
{
return type;
}
public void setSpare1(String spare1)
{
this.spare1 = spare1;
}
public String getSpare1()
{
return spare1;
}
public void setSpare2(String spare2)
{
this.spare2 = spare2;
}
public String getSpare2()
{
return spare2;
}
public void setSpare3(String spare3)
{
this.spare3 = spare3;
}
public String getSpare3()
{
return spare3;
}
@Override
public String toString() {
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
.append("id", getId())
.append("station", getStation())
.append("type", getType())
.append("remark", getRemark())
.append("spare1", getSpare1())
.append("spare2", getSpare2())
.append("spare3", getSpare3())
.toString();
}
}

View File

@@ -0,0 +1,22 @@
package com.ruoyi.bas.agvPoint.domain;
import lombok.Getter;
import lombok.Setter;
import java.io.Serializable;
@lombok.Data
@Getter
@Setter
public class AgvTask implements Serializable {
private String startPoint;
private String endPoint;
private String type;
private String trayCode;
}

View File

@@ -0,0 +1,61 @@
package com.ruoyi.bas.agvPoint.mapper;
import java.util.List;
import com.ruoyi.bas.agvPoint.domain.AgvPoint;
/**
* agv站点Mapper接口
*
* @author ruoyi
* @date 2026-03-17
*/
public interface AgvPointMapper
{
/**
* 查询agv站点
*
* @param id agv站点主键
* @return agv站点
*/
public AgvPoint selectAgvPointById(String id);
/**
* 查询agv站点列表
*
* @param agvPoint agv站点
* @return agv站点集合
*/
public List<AgvPoint> selectAgvPointList(AgvPoint agvPoint);
/**
* 新增agv站点
*
* @param agvPoint agv站点
* @return 结果
*/
public int insertAgvPoint(AgvPoint agvPoint);
/**
* 修改agv站点
*
* @param agvPoint agv站点
* @return 结果
*/
public int updateAgvPoint(AgvPoint agvPoint);
/**
* 删除agv站点
*
* @param id agv站点主键
* @return 结果
*/
public int deleteAgvPointById(String id);
/**
* 批量删除agv站点
*
* @param ids 需要删除的数据主键集合
* @return 结果
*/
public int deleteAgvPointByIds(String[] ids);
}

View File

@@ -0,0 +1,61 @@
package com.ruoyi.bas.agvPoint.service;
import java.util.List;
import com.ruoyi.bas.agvPoint.domain.AgvPoint;
/**
* agv站点Service接口
*
* @author ruoyi
* @date 2026-03-17
*/
public interface IAgvPointService
{
/**
* 查询agv站点
*
* @param id agv站点主键
* @return agv站点
*/
public AgvPoint selectAgvPointById(String id);
/**
* 查询agv站点列表
*
* @param agvPoint agv站点
* @return agv站点集合
*/
public List<AgvPoint> selectAgvPointList(AgvPoint agvPoint);
/**
* 新增agv站点
*
* @param agvPoint agv站点
* @return 结果
*/
public int insertAgvPoint(AgvPoint agvPoint);
/**
* 修改agv站点
*
* @param agvPoint agv站点
* @return 结果
*/
public int updateAgvPoint(AgvPoint agvPoint);
/**
* 批量删除agv站点
*
* @param ids 需要删除的agv站点主键集合
* @return 结果
*/
public int deleteAgvPointByIds(String[] ids);
/**
* 删除agv站点信息
*
* @param id agv站点主键
* @return 结果
*/
public int deleteAgvPointById(String id);
}

View File

@@ -0,0 +1,93 @@
package com.ruoyi.bas.agvPoint.service.impl;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.bas.agvPoint.mapper.AgvPointMapper;
import com.ruoyi.bas.agvPoint.domain.AgvPoint;
import com.ruoyi.bas.agvPoint.service.IAgvPointService;
/**
* agv站点Service业务层处理
*
* @author ruoyi
* @date 2026-03-17
*/
@Service
public class AgvPointServiceImpl implements IAgvPointService
{
@Autowired
private AgvPointMapper agvPointMapper;
/**
* 查询agv站点
*
* @param id agv站点主键
* @return agv站点
*/
@Override
public AgvPoint selectAgvPointById(String id)
{
return agvPointMapper.selectAgvPointById(id);
}
/**
* 查询agv站点列表
*
* @param agvPoint agv站点
* @return agv站点
*/
@Override
public List<AgvPoint> selectAgvPointList(AgvPoint agvPoint)
{
return agvPointMapper.selectAgvPointList(agvPoint);
}
/**
* 新增agv站点
*
* @param agvPoint agv站点
* @return 结果
*/
@Override
public int insertAgvPoint(AgvPoint agvPoint)
{
return agvPointMapper.insertAgvPoint(agvPoint);
}
/**
* 修改agv站点
*
* @param agvPoint agv站点
* @return 结果
*/
@Override
public int updateAgvPoint(AgvPoint agvPoint)
{
return agvPointMapper.updateAgvPoint(agvPoint);
}
/**
* 批量删除agv站点
*
* @param ids 需要删除的agv站点主键
* @return 结果
*/
@Override
public int deleteAgvPointByIds(String[] ids)
{
return agvPointMapper.deleteAgvPointByIds(ids);
}
/**
* 删除agv站点信息
*
* @param id agv站点主键
* @return 结果
*/
@Override
public int deleteAgvPointById(String id)
{
return agvPointMapper.deleteAgvPointById(id);
}
}

View File

@@ -71,6 +71,7 @@ public class BasTraycodeController extends BaseController
@PostMapping
public AjaxResult add(@RequestBody BasTraycode basTraycode)
{
return toAjax(basTraycodeService.insertBasTraycode(basTraycode));
}

View File

@@ -16,16 +16,16 @@ public class BasTraycode extends BaseEntity
private static final long serialVersionUID = 1L;
/** id */
@Excel(name = "${bas.Traycode.id}")
// @Excel(name = "${bas.Traycode.id}")
private Long id;
/** 条码类型id */
@Excel(name = "${bas.Traycode.formatId}")
// @Excel(name = "${bas.Traycode.formatId}")
private Long formatId;
private String formatName;
/** 条码 */
@Excel(name = "${bas.Traycode.trayCode}")
@Excel(name = "条码")
private String trayCode;
/** 备用字段1 */
@@ -33,7 +33,7 @@ public class BasTraycode extends BaseEntity
private String spare1;
/** 备用字段2 */
// @Excel(name = "${bas.Traycode.spare2}")
@Excel(name = "是否可用",dictType = "sys_yes_no")
private String spare2;
/** 备用字段3 */

View File

@@ -61,4 +61,6 @@ public interface BasTraycodeMapper
public int deleteBasTraycodeByIds(Long[] ids);
void insertBasTraycodeList(List<BasTraycode> list);
Integer selectBasTrayCodeMax();
}

View File

@@ -61,4 +61,6 @@ public interface IBasTraycodeService
public int deleteBasTraycodeById(Long id);
void insertBasTraycodeList(List<BasTraycode> traycodeList);
Integer selectBasTrayCodeMax();
}

View File

@@ -1,9 +1,12 @@
package com.ruoyi.bas.traycode.service.impl;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import com.ruoyi.bas.traycode.domain.BasTraycode;
import com.ruoyi.bas.traycode.mapper.BasTraycodeMapper;
import com.ruoyi.bas.traycode.service.IBasTraycodeService;
import com.ruoyi.bas.traycodeformat.domain.BasTraycodeFormat;
import com.ruoyi.bas.traycodeformat.service.IBasTraycodeFormatService;
import com.ruoyi.common.utils.DateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@@ -21,6 +24,8 @@ public class BasTraycodeServiceImpl implements IBasTraycodeService
{
@Autowired
private BasTraycodeMapper basTraycodeMapper;
@Autowired
private IBasTraycodeFormatService basTraycodeFormatService;
/**
* 查询条码信息
@@ -55,8 +60,33 @@ public class BasTraycodeServiceImpl implements IBasTraycodeService
@Override
public int insertBasTraycode(BasTraycode basTraycode)
{
basTraycode.setCreateTime(DateUtils.getNowDate());
return basTraycodeMapper.insertBasTraycode(basTraycode);
try {
BasTraycodeFormat basTraycodeFormat = basTraycodeFormatService.selectBasTraycodeFormatById(basTraycode.getFormatId());
int i1 = Integer.parseInt(basTraycode.getSpare1());
//如果i<4位数,前面补0
String code = "";
for (int j = 0; j < i1; j++) {
code = String.format("%07d",Convert.toInt( basTraycodeFormat.getSerialRule()) + 1 + j);
if(basTraycodeFormat.getMaxNum() < Convert.toLong( code)){
throw new RuntimeException("已生成最大值");
}
String finalCode = basTraycodeFormat.getBarcodeFormat()+code;
basTraycode.setTrayCode(finalCode);
basTraycode.setSpare1(null);
basTraycode.setCreateTime(DateUtils.getNowDate());
basTraycode.setSpare2("Y");
basTraycodeMapper.insertBasTraycode(basTraycode);
}
basTraycodeFormat.setSerialRule(Convert.toLong( code).toString());
basTraycodeFormatService.updateBasTraycodeFormat(basTraycodeFormat);
} catch (Exception e) {
throw new RuntimeException(e);
}
return 1;
}
/**
@@ -103,4 +133,9 @@ public class BasTraycodeServiceImpl implements IBasTraycodeService
basTraycodeMapper.insertBasTraycodeList(list);
}
}
@Override
public Integer selectBasTrayCodeMax() {
return basTraycodeMapper.selectBasTrayCodeMax();
}
}

View File

@@ -1,17 +1,13 @@
package com.ruoyi.bas.traycodeformat.service.impl;
import cn.hutool.core.util.StrUtil;
import com.ruoyi.bas.traycode.domain.BasTraycode;
import com.ruoyi.bas.traycode.service.IBasTraycodeService;
import com.ruoyi.bas.traycodeformat.domain.BasTraycodeFormat;
import com.ruoyi.bas.traycodeformat.mapper.BasTraycodeFormatMapper;
import com.ruoyi.bas.traycodeformat.service.IBasTraycodeFormatService;
import com.ruoyi.common.core.text.Convert;
import com.ruoyi.common.utils.DateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
/**
@@ -79,20 +75,7 @@ public class BasTraycodeFormatServiceImpl implements IBasTraycodeFormatService
public int updateBasTraycodeFormat(BasTraycodeFormat basTraycodeFormat)
{
BasTraycodeFormat old = selectBasTraycodeFormatById(basTraycodeFormat.getId());
int oldSerialRule = Convert.toInt(old.getSerialRule());
int newSerialRule = Convert.toInt(basTraycodeFormat.getSerialRule());
List<BasTraycode> traycodeList = new ArrayList<>();
for (int i = oldSerialRule; i < newSerialRule; i++) {
BasTraycode basTraycode = new BasTraycode();
basTraycode.setFormatId(basTraycodeFormat.getId());
String traycode = old.getBarcodeFormat()+ StrUtil.padPre(Convert.toStr(i),5,'0');
basTraycode.setTrayCode(traycode);
traycodeList.add(basTraycode);
}
basTraycodeFormat.setUpdateTime(DateUtils.getNowDate());
//插入条码信息
basTraycodeService.insertBasTraycodeList(traycodeList);
return basTraycodeFormatMapper.updateBasTraycodeFormat(basTraycodeFormat);
}

View File

@@ -182,8 +182,8 @@ public class CheckStockinServiceImpl implements ICheckStockinService {
CheckStockinDetail checkStockinDetail = detailList.get(i);
checkStockinDetail.setStockCheckDetailId(stockCheckId + "-" + (i + 1));
checkStockinDetail.setStockCheckId(stockCheckId);
BasProduct basProduct = productService.selectBasProductByProductId(checkStockinDetail.getProductId());
checkStockinDetail.setProductGuid(basProduct.getProductGuid());
// BasProduct basProduct = productService.selectBasProductByProductId(checkStockinDetail.getProductId());
// checkStockinDetail.setProductGuid(basProduct.getProductGuid());
checkStockinDetail.setStockCheckGuid(checkStockin.getStockGuid());
checkStockinDetail.setScanNum("0");
checkStockinDetail.setAssignNum("0");
@@ -229,7 +229,7 @@ public class CheckStockinServiceImpl implements ICheckStockinService {
checkStockinMapper.autoAllot(map);
builder.append("行明细:" + checkStockinDetail.getStockCheckDetailId() + ",分配结果:" + map.get("v_resultmsg") + "<br />");
}
iToWcsService.pushOutMydoJob();
//iToWcsService.pushOutMydoJob();
return AjaxResult.success(builder.toString());

View File

@@ -60,4 +60,6 @@ public interface AgvContainerTaskMapper
public int deleteAgvContainerTaskByIds(Long[] ids);
void insertHistory(Long id);
void deleteAgvJobByOrder(String order);
}

View File

@@ -60,4 +60,6 @@ public interface IAgvContainerTaskService
public int deleteAgvContainerTaskById(Long id);
void insertHistory(Long id);
void deleteAgvJobByOrder(String order);
}

View File

@@ -97,4 +97,9 @@ public class AgvContainerTaskServiceImpl implements IAgvContainerTaskService
public void insertHistory(Long id) {
agvContainerTaskMapper.insertHistory(id);
}
@Override
public void deleteAgvJobByOrder(String order) {
agvContainerTaskMapper.deleteAgvJobByOrder(order);
}
}

View File

@@ -102,8 +102,54 @@ public class InStockin extends BaseEntity
private String lotNo;
private String materialDesc;
private String productId;
private String startDate;
private String companyShortName;
private String accountSetNo;
private String cargoNo;
private String stockinDetailId;
public String getProductId() {
return productId;
}
public void setProductId(String productId) {
this.productId = productId;
}
public String getStockinDetailId() {
return stockinDetailId;
}
public void setStockinDetailId(String stockinDetailId) {
this.stockinDetailId = stockinDetailId;
}
public String getCargoNo() {
return cargoNo;
}
public void setCargoNo(String cargoNo) {
this.cargoNo = cargoNo;
}
public String getCompanyShortName() {
return companyShortName;
}
public void setCompanyShortName(String companyShortName) {
this.companyShortName = companyShortName;
}
public String getAccountSetNo() {
return accountSetNo;
}
public void setAccountSetNo(String accountSetNo) {
this.accountSetNo = accountSetNo;
}
private List<String> typeData;
public String getStartDate() {

View File

@@ -66,4 +66,6 @@ public interface InStockinMapper
void insertInStockinHistory(InStockin inStockin);
List<InStockin> selectStockinByDetail(String stockinDetailId);
List<InStockin> selectInStockinListBill(InStockin param);
}

View File

@@ -73,4 +73,6 @@ public interface IInStockinService
public int deleteInStockinByStockinGuid(String stockinGuid);
public List<InStockin> selectStockinByDetail(String stockinDetailId);
List<InStockin> selectInStockinListBill(InStockin param);
}

View File

@@ -255,4 +255,9 @@ public class InStockinServiceImpl implements IInStockinService
public List<InStockin> selectStockinByDetail(String stockinDetailId) {
return inStockinMapper.selectStockinByDetail(stockinDetailId);
}
@Override
public List<InStockin> selectInStockinListBill(InStockin param) {
return inStockinMapper.selectInStockinListBill(param);
}
}

View File

@@ -95,6 +95,24 @@ public class InStockinBack extends BaseEntity
private String sendTime;
private String msg;
private String companyShortName;
private String accountSetNo;
public String getCompanyShortName() {
return companyShortName;
}
public void setCompanyShortName(String companyShortName) {
this.companyShortName = companyShortName;
}
public String getAccountSetNo() {
return accountSetNo;
}
public void setAccountSetNo(String accountSetNo) {
this.accountSetNo = accountSetNo;
}
public String getSendStatus() {
return sendStatus;

View File

@@ -152,6 +152,44 @@ public class InStockinDetailBack extends BaseEntity
private String msg;
private String sourceLineId;
private String barCode;
private String isBatchManage;
private String oldProjectNo;
public String getSourceLineId() {
return sourceLineId;
}
public void setSourceLineId(String sourceLineId) {
this.sourceLineId = sourceLineId;
}
public String getBarCode() {
return barCode;
}
public void setBarCode(String barCode) {
this.barCode = barCode;
}
public String getIsBatchManage() {
return isBatchManage;
}
public void setIsBatchManage(String isBatchManage) {
this.isBatchManage = isBatchManage;
}
public String getOldProjectNo() {
return oldProjectNo;
}
public void setOldProjectNo(String oldProjectNo) {
this.oldProjectNo = oldProjectNo;
}
public String getSendStatus() {
return sendStatus;
}

View File

@@ -4,6 +4,7 @@ import java.util.List;
import com.ruoyi.in.stockin.domain.InStockin;
import com.ruoyi.in.stockindeatilback.domain.InStockinDetailBack;
import org.apache.ibatis.annotations.Param;
/**
* 入库单据子信息Mapper接口
@@ -61,4 +62,8 @@ public interface InStockinDetailBackMapper
* @return 结果
*/
public int deleteInStockinDetailBackByStockinDetailIds(String[] stockinDetailIds);
void insertInStockInDetailBackFinish(@Param("list") List<InStockinDetailBack> inStockinDetailParam);
void deleteInStockInDetailList(@Param("idList") List<InStockinDetailBack> inStockinDetails);
}

View File

@@ -58,4 +58,8 @@ public interface IInStockinDetailBackService
* @return 结果
*/
public int deleteInStockinDetailBackByStockinDetailId(String stockinDetailId);
void insertInStockInDetailBackFinish(List<InStockinDetailBack> inStockinDetails);
void deleteInStockInDetailList(List<InStockinDetailBack> inStockinDetails);
}

View File

@@ -90,4 +90,14 @@ public class InStockinDetailBackServiceImpl implements IInStockinDetailBackServi
{
return inStockinDetailBackMapper.deleteInStockinDetailBackByStockinDetailId(stockinDetailId);
}
@Override
public void insertInStockInDetailBackFinish(List<InStockinDetailBack> inStockinDetails) {
inStockinDetailBackMapper.insertInStockInDetailBackFinish(inStockinDetails);
}
@Override
public void deleteInStockInDetailList(List<InStockinDetailBack> inStockinDetails) {
inStockinDetailBackMapper.deleteInStockInDetailList(inStockinDetails);
}
}

View File

@@ -143,9 +143,13 @@ public class InStockinDetail extends BaseEntity
private String status;
private ExtraField extraField;
private String erpBill;
private String warehouseName;
private String warehouseId;
private String sourceLineId;
private String barCode;
private String isBatchManage;
private String oldProjectNo;
}

View File

@@ -69,4 +69,6 @@ public interface InStockinDetailMapper
void deleteInStockinDetailByStockinGuid(String stockinGuid);
InStockinDetail selectStockinByDetailById(InStockinDetail inStockinDetail);
List<InStockinDetail> selectStockInByDetailByBarCode(String barCode);
}

View File

@@ -81,4 +81,6 @@ public interface IInStockinDetailService
public InStockinDetail selectStockinByDetailById(InStockinDetail inStockinDetail);
List<InStockinDetail> selectStockInByDetailByBarCode(String barCode);
}

View File

@@ -127,4 +127,9 @@ public class InStockinDetailServiceImpl implements IInStockinDetailService
return inStockinDetailMapper.selectStockinByDetailById(inStockinDetail);
}
@Override
public List<InStockinDetail> selectStockInByDetailByBarCode(String barCode) {
return inStockinDetailMapper.selectStockInByDetailByBarCode(barCode);
}
}

View File

@@ -89,6 +89,15 @@ public class InStockinFinish extends BaseEntity
/** 备用字段5 */
@Excel(name = "备用字段5")
private String spare5;
private String stockinDetailId;
public String getStockinDetailId() {
return stockinDetailId;
}
public void setStockinDetailId(String stockinDetailId) {
this.stockinDetailId = stockinDetailId;
}
public void setStockinGuid(String stockinGuid)
{

View File

@@ -102,7 +102,7 @@ public class InStockinFinishServiceImpl implements IInStockinFinishService
}
@Override
@DataScope(warehouseAlias = "is2")
// @DataScope(warehouseAlias = "is2")
public List<InStockin> selectInStockinFinishListByInStockin(InStockin inStockin) {
return inStockinFinishMapper.selectInStockinFinishListByInStockin(inStockin);
}

View File

@@ -124,6 +124,9 @@ public class MydoJob extends BaseEntity
/** 重分标记 */
@Excel(name = "重分标记")
private String faultFlag;
private String endPoint;
private String inOut;
@@ -133,6 +136,23 @@ public class MydoJob extends BaseEntity
private String createRightTime;
private String productId;
private String stockinDetailId;
public String getEndPoint() {
return endPoint;
}
public void setEndPoint(String endPoint) {
this.endPoint = endPoint;
}
public String getStockinDetailId() {
return stockinDetailId;
}
public void setStockinDetailId(String stockinDetailId) {
this.stockinDetailId = stockinDetailId;
}
public String getProductId() {
return productId;

View File

@@ -82,5 +82,16 @@ public interface MydoJobMapper
MydoJob selectInJobByTrayCode(@Param("trayCode") String trayCode);
MydoJob selectInJobByTaskNo(@Param("taskNo") String taskNo);
void allotInJobSpace(HashMap<String, Object> map);
void ykCompleted(HashMap<String, Object> map);
void completeAlgorithmMove(HashMap<String, Object> map);
void updateLed(HashMap<String, Object> map);
void updateLedError(HashMap<String, Object> map);
}

View File

@@ -109,4 +109,6 @@ public interface IMydoJobService
MydoJob selectMydoJobByEntranceId(MydoJob mydoJob);
List<MydoJob> getInJobBySerial(String serial);
void ykCompleted(MydoJob outJob);
}

View File

@@ -192,7 +192,7 @@ public class MydoJobServiceImpl implements IMydoJobService {
List<MydoJobDetail> mydoJobDetails = mydoJobDetailService.selectMydoJobDetailList(param);
for (MydoJobDetail mydoJobDetail : mydoJobDetails) {
String inOrOutDId = mydoJobDetail.getInOrOutDId();
String inOrOutDId = mydoJobDetail.getStockinDetailId();
InStockinDetail inStockinDetail = inStockinDetailService.selectInStockinDetailByStockinDetailId(inOrOutDId);
BigDecimal stockInNum = Convert.toBigDecimal(inStockinDetail.getScanNum());
BigDecimal jobInNum = Convert.toBigDecimal(mydoJobDetail.getInQuantity());
@@ -506,7 +506,7 @@ public class MydoJobServiceImpl implements IMydoJobService {
msg = map.get("v_resultmsg").toString();
builder.append("托盘:" + basStock.getTrayCode() + ",分配结果:" + msg + "<br/>");
}
iToWcsService.pushOutMydoJob();
//iToWcsService.pushOutMydoJob();
if (!StrUtil.isEmpty(builder)) {
return AjaxResult.warn(builder.toString());
}
@@ -527,4 +527,25 @@ public class MydoJobServiceImpl implements IMydoJobService {
public List<MydoJob> getInJobBySerial(String trayCode) {
return mydoJobMapper.getInJobBySerial(trayCode);
}
@Override
public void ykCompleted(MydoJob outJob) {
HashMap<String, Object> map = new HashMap<>();
map.put("v_job_id", outJob.getJobId());
map.put("v_result", null);
boolean algorithmMove = "28".equals(outJob.getInOrOut());
if (algorithmMove) {
mydoJobMapper.completeAlgorithmMove(map);
} else {
mydoJobMapper.ykCompleted(map);
}
if (!"10".equals(String.valueOf(map.get("v_result")))) {
log.error("移库任务处理异常 异常代码{}", map.get("v_result"));
if (algorithmMove) {
throw new IllegalStateException("Algorithm move completion failed for job " + outJob.getJobId());
}
}else{
log.info("移库任务处理成功 jobId:[{}] trayCode:[{}]", outJob.getJobId(), outJob.getTrayCode());
}
}
}

Some files were not shown because too many files have changed in this diff Show More