| | |
| | | <selectionStates> |
| | | <SelectionState runConfigName="app"> |
| | | <option name="selectionMode" value="DROPDOWN" /> |
| | | <DropdownSelection timestamp="2024-08-15T08:33:10.282255800Z"> |
| | | <DropdownSelection timestamp="2025-01-21T07:56:54.827595Z"> |
| | | <Target type="DEFAULT_BOOT"> |
| | | <handle> |
| | | <DeviceId pluginId="PhysicalDevice" identifier="serial=2MM0223916052360" /> |
| | | <DeviceId pluginId="PhysicalDevice" identifier="serial=30159834971" /> |
| | | </handle> |
| | | </Target> |
| | | </DropdownSelection> |
| | |
| | | package com.example.agvcontroller; |
| | | |
| | | public class AGVCar { |
| | | import java.io.Serializable; |
| | | |
| | | public class AGVCar implements Serializable { |
| | | private String clientId; |
| | | private String ip; |
| | | private int port; |
| | | private String agvNo; |
| | | private int status; |
| | | private int battery; |
| | | private int agvStatus; |
| | | private int positionID; |
| | | private int positionX; |
| | | private int positionY; |
| | | private int agvAngle; |
| | | private int gyroAngle; |
| | | private int forkHeight; |
| | | private int forkExtend; |
| | | private int forkAngle; |
| | | private int agvError; |
| | | |
| | | public AGVCar(String clientId, String ip, int port, String agvNo, int status) { |
| | | this.clientId = clientId; |
| | |
| | | this.agvNo = agvNo; |
| | | this.status = status; |
| | | } |
| | | |
| | | public AGVCar(String clientId, String ip, int port, String agvNo, int status, int battery, int agvStatus, int positionID, int positionX, int positionY, int agvAngle, int gyroAngle, int forkHeight, int forkExtend, int forkAngle, int agvError) { |
| | | this.clientId = clientId; |
| | | this.ip = ip; |
| | | this.port = port; |
| | | this.agvNo = agvNo; |
| | | this.status = status; |
| | | this.battery = battery; |
| | | this.agvStatus = agvStatus; |
| | | this.positionID = positionID; |
| | | this.positionX = positionX; |
| | | this.positionY = positionY; |
| | | this.agvAngle = agvAngle; |
| | | this.gyroAngle = gyroAngle; |
| | | this.forkHeight = forkHeight; |
| | | this.forkExtend = forkExtend; |
| | | this.forkAngle = forkAngle; |
| | | this.agvError = agvError; |
| | | } |
| | | |
| | | public int getBattery() { |
| | | return battery; |
| | | } |
| | | |
| | | public void setBattery(int battery) { |
| | | this.battery = battery; |
| | | } |
| | | |
| | | public int getAgvStatus() { |
| | | return agvStatus; |
| | | } |
| | | |
| | | public void setAgvStatus(int agvStatus) { |
| | | this.agvStatus = agvStatus; |
| | | } |
| | | |
| | | public int getPositionID() { |
| | | return positionID; |
| | | } |
| | | |
| | | public void setPositionID(int positionID) { |
| | | this.positionID = positionID; |
| | | } |
| | | |
| | | public int getPositionX() { |
| | | return positionX; |
| | | } |
| | | |
| | | public void setPositionX(int positionX) { |
| | | this.positionX = positionX; |
| | | } |
| | | |
| | | public int getPositionY() { |
| | | return positionY; |
| | | } |
| | | |
| | | public void setPositionY(int positionY) { |
| | | this.positionY = positionY; |
| | | } |
| | | |
| | | public int getAgvAngle() { |
| | | return agvAngle; |
| | | } |
| | | |
| | | public void setAgvAngle(int agvAngle) { |
| | | this.agvAngle = agvAngle; |
| | | } |
| | | |
| | | public int getGyroAngle() { |
| | | return gyroAngle; |
| | | } |
| | | |
| | | public void setGyroAngle(int gyroAngle) { |
| | | this.gyroAngle = gyroAngle; |
| | | } |
| | | |
| | | public int getForkHeight() { |
| | | return forkHeight; |
| | | } |
| | | |
| | | public void setForkHeight(int forkHeight) { |
| | | this.forkHeight = forkHeight; |
| | | } |
| | | |
| | | public int getForkExtend() { |
| | | return forkExtend; |
| | | } |
| | | |
| | | public void setForkExtend(int forkExtend) { |
| | | this.forkExtend = forkExtend; |
| | | } |
| | | |
| | | public int getForkAngle() { |
| | | return forkAngle; |
| | | } |
| | | |
| | | public void setForkAngle(int forkAngle) { |
| | | this.forkAngle = forkAngle; |
| | | } |
| | | |
| | | public int getAgvError() { |
| | | return agvError; |
| | | } |
| | | |
| | | public void setAgvError(int agvError) { |
| | | this.agvError = agvError; |
| | | } |
| | | |
| | | public String getClientId() {return clientId; } |
| | | |
| | | public String getIp() { |
| | |
| | | import android.view.View; |
| | | import android.view.ViewGroup; |
| | | import android.widget.EditText; |
| | | import android.widget.ImageButton; |
| | | |
| | | import androidx.annotation.NonNull; |
| | | import androidx.appcompat.widget.AppCompatImageButton; |
| | | import androidx.recyclerview.widget.RecyclerView; |
| | | |
| | | import java.util.List; |
| | |
| | | public static class ViewHolder extends RecyclerView.ViewHolder { |
| | | EditText agvNo; |
| | | EditText ip; |
| | | AppCompatImageButton btn; |
| | | ImageButton btn; |
| | | |
| | | public ViewHolder(@NonNull View itemView) { |
| | | super(itemView); |
| | |
| | | import android.widget.GridLayout; |
| | | import android.widget.RelativeLayout; |
| | | import android.widget.Switch; |
| | | import android.widget.TextView; |
| | | |
| | | import com.example.agvcontroller.action.AllResetAction; |
| | | import com.example.agvcontroller.action.BackPaddle; |
| | |
| | | |
| | | public static final Map<String, Object> map = new ConcurrentHashMap(); |
| | | public static final Map<String, Object> car_num = new ConcurrentHashMap(); |
| | | |
| | | private static TextView agvBattery; |
| | | |
| | | private Vibrator vibrator; |
| | | private Button stopBtn; // 急停按钮 |
| | |
| | | |
| | | private Button bodySwitchBtn; // 底盘/货叉切换 |
| | | private Socket socket; |
| | | private String AgvNo = "1"; |
| | | |
| | | private RelativeLayout layout_bottom; |
| | | private RelativeLayout layout_top; |
| | | private GridLayout layout_single; |
| | |
| | | return false; |
| | | } |
| | | }); |
| | | |
| | | static String AgvNo = "1"; |
| | | static String clientId; |
| | | NettyServerHandler nettyServerHandler; |
| | | |
| | | |
| | | |
| | | @Override |
| | | protected void onCreate(Bundle savedInstanceState) { |
| | | super.onCreate(savedInstanceState); |
| | | setContentView(R.layout.activity_main); |
| | | |
| | | agvBattery = findViewById(R.id.agv_battery); |
| | | |
| | | |
| | | |
| | | // 按钮震动 |
| | |
| | | |
| | | Intent intent = getIntent(); |
| | | if (intent != null) { |
| | | String newClientId = intent.getStringExtra("clientId"); |
| | | if (newClientId != null) { |
| | | clientId = newClientId; |
| | | AgvNo = intent.getStringExtra("agvNo"); |
| | | } |
| | | AGVCar car = (AGVCar) intent.getSerializableExtra("item"); |
| | | clientId = car.getClientId(); |
| | | AgvNo = car.getAgvNo(); |
| | | } |
| | | |
| | | Log.i("message1",clientId); |
| | |
| | | //socketManager.stopServer(); // 停止服务器 |
| | | } |
| | | |
| | | public static void upClient(String newClientId) { |
| | | clientId = newClientId; |
| | | public static void upClient(AGVCar agvCar) { |
| | | clientId = agvCar.getClientId(); |
| | | AgvNo = agvCar.getAgvNo(); |
| | | agvBattery.setText("电量:" + agvCar.getBattery() + "%"); |
| | | // updateAgvBatteryText("电量:" + agvCar.getBattery() + "%"); |
| | | } |
| | | |
| | | private static void updateAgvBatteryText(String batteryLevel) { |
| | | if (agvBattery != null) { |
| | | agvBattery.setText(batteryLevel); |
| | | } |
| | | } |
| | | } |
| | |
| | | public void onItemClick(View view, int position) { |
| | | Context context = view.getContext(); |
| | | Intent intent = new Intent(context,MainActivity.class); |
| | | String ip = items.get(position).getIp(); |
| | | String clientId = items.get(position).getClientId(); |
| | | String agvNo = items.get(position).getAgvNo(); |
| | | AGVCar item = items.get(position); |
| | | // String ip = items.get(position).getIp(); |
| | | // String clientId = items.get(position).getClientId(); |
| | | // String agvNo = items.get(position).getAgvNo(); |
| | | |
| | | |
| | | intent.putExtra("ip", ip); |
| | | intent.putExtra("agvNo", agvNo); |
| | | intent.putExtra("clientId", clientId); |
| | | // intent.putExtra("ip", ip); |
| | | // intent.putExtra("agvNo", agvNo); |
| | | // intent.putExtra("clientId", clientId); |
| | | intent.putExtra("item", item); |
| | | startActivityForResult(intent,1); |
| | | } |
| | | }); |
| | |
| | | } |
| | | |
| | | @Subscribe(threadMode = ThreadMode.MAIN) |
| | | public void onDeviceConnected(AGVCar deviceAddress) { |
| | | Log.i("EventBus", "Received device connected: " + deviceAddress); |
| | | public void onDeviceConnected(AGVCar car) { |
| | | Log.i("EventBus", "Received device connected: " + car); |
| | | |
| | | |
| | | if (!items.isEmpty()) { |
| | | int sameIp = 0; |
| | | for (AGVCar item : items) { |
| | | if (item.getIp().equals(deviceAddress.getIp())) { |
| | | item.setAgvNo(deviceAddress.getAgvNo()); |
| | | item.setPort(deviceAddress.getPort()); |
| | | item.setClientId(deviceAddress.getClientId()); |
| | | item.setStatus(deviceAddress.getStatus()); |
| | | if (item.getIp().equals(car.getIp())) { |
| | | item.setAgvNo(car.getAgvNo().isEmpty() ? car.getAgvNo() : item.getAgvNo()); |
| | | item.setPort(car.getPort()); |
| | | item.setClientId(car.getClientId()); |
| | | item.setStatus(car.getStatus()); |
| | | item.setBattery(car.getBattery() != 0 ? car.getBattery() : item.getBattery()); |
| | | adapter.notifyItemChanged(items.indexOf(item)); |
| | | MainActivity.upClient(deviceAddress.getClientId()); |
| | | MainActivity.upClient(car); |
| | | sameIp++; |
| | | } |
| | | Log.i("Item",item.getIp()); |
| | | Log.i("Item",item.getClientId()); |
| | | } |
| | | if (sameIp == 0) { |
| | | items.add(new AGVCar(deviceAddress.getClientId() |
| | | ,deviceAddress.getIp() |
| | | ,deviceAddress.getPort() |
| | | ,deviceAddress.getAgvNo() |
| | | ,deviceAddress.getStatus())); |
| | | items.add(car); |
| | | } |
| | | } else { |
| | | items.add(new AGVCar(deviceAddress.getClientId() |
| | | ,deviceAddress.getIp() |
| | | ,deviceAddress.getPort() |
| | | ,deviceAddress.getAgvNo() |
| | | ,deviceAddress.getStatus())); |
| | | items.add(car); |
| | | } |
| | | adapter.notifyDataSetChanged(); |
| | | } |
| | |
| | | // type |
| | | this.type = Utils.sliceWithReverse(bytes, 4, 1)[0]; |
| | | |
| | | this.battery = Utils.sliceWithReverse(bytes, 32, 1)[0]; |
| | | |
| | | |
| | | |
| | | |
| | | } |
| | | |
| | |
| | | |
| | | private byte type; |
| | | |
| | | private int battery; |
| | | |
| | | public int getBattery() { |
| | | return battery; |
| | | } |
| | | } |
| | | |
| | |
| | | return null; |
| | | } |
| | | |
| | | public String getDesc() { |
| | | return desc; |
| | | } |
| | | |
| | | } |
| | |
| | | package com.example.agvcontroller.protocol; |
| | | |
| | | |
| | | import android.util.Log; |
| | | |
| | | import com.example.agvcontroller.socket.RadixTools; |
| | | |
| | | import java.net.InetSocketAddress; |
| | | import java.util.logging.Logger; |
| | | |
| | | import io.netty.buffer.ByteBuf; |
| | |
| | | |
| | | @Override |
| | | protected void encode(ChannelHandlerContext ctx, Object obj, ByteBuf out) { |
| | | InetSocketAddress remoteAddress = (InetSocketAddress) ctx.channel().remoteAddress(); |
| | | String ip = remoteAddress.getAddress().getHostAddress(); |
| | | |
| | | if (obj instanceof ByteBuf){ |
| | | out.writeBytes((ByteBuf) obj); |
| | |
| | | |
| | | out.writerIndex(out.readableBytes() - 2); |
| | | out.writeShortLE(validCode); |
| | | // 生成整个报文的字节数组 |
| | | byte[] buffer = new byte[out.readableBytes()]; |
| | | out.getBytes(out.readerIndex(), buffer); |
| | | |
| | | // 将字节数组转换为 16 进制字符串 |
| | | String hexMessage = bytesToHex(buffer); |
| | | Log.d("updown", "下行: " + ip + "[" + action.getHandleCmdType().getDesc() + "]>>>" + hexMessage); |
| | | } else if (obj instanceof AgvPackage){ |
| | | |
| | | AgvPackage pac = (AgvPackage)obj; |
| | |
| | | |
| | | out.writerIndex(out.readableBytes() - 2); |
| | | out.writeShortLE(pac.getValidCode()); |
| | | // 生成整个报文的字节数组 |
| | | byte[] buffer = new byte[out.readableBytes()]; |
| | | out.getBytes(out.readerIndex(), buffer); |
| | | |
| | | // 将字节数组转换为 16 进制字符串 |
| | | String hexMessage = bytesToHex(buffer); |
| | | Log.d("updown", "下行: " + ip + "[" + pac.getHeader().getProtocolType().getDes() + "]>>>" + hexMessage); |
| | | } |
| | | |
| | | |
| | | } |
| | | |
| | | private String bytesToHex(byte[] bytes) { |
| | | StringBuilder sb = new StringBuilder(); |
| | | for (byte b : bytes) { |
| | | sb.append(String.format("%02X", b)); |
| | | } |
| | | return sb.toString(); |
| | | } |
| | | |
| | | // 将十六进制字符串转换为字节数组 |
| | | private byte[] hexStringToByteArray(String s) { |
| | | int len = s.length(); |
| | | byte[] data = new byte[len / 2]; |
| | | for (int i = 0; i < len; i += 2) { |
| | | data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4) |
| | | + Character.digit(s.charAt(i+1), 16)); |
| | | } |
| | | return data; |
| | | } |
| | | |
| | | // EE | 11 00 | 01 00 00 00 | 0C AB 12 64 | F0 | 01 00 | 01 01 | 00 00 00 00 | 4C F7 |
| | | // # | len | uniqueno | timestamp | cmd | content | crc |
| | | |
| | |
| | | if (null != ackType) { |
| | | AgvPackage ackPac = AckMsgBuilder.ofSuccess(pac, ackType); |
| | | AGV_F0_DOWN agv_f0_down = (AGV_F0_DOWN) ackPac.getBody().getMessageBody(); |
| | | Log.d("updown", "上行: " + ip + "[登录包]>>>" + pac.getSourceHexStr()); |
| | | ctx.writeAndFlush(ackPac); |
| | | } |
| | | final int battery = agv_f0_up.getBattery(); |
| | | // pac.getBody().getMessageBody() |
| | | agvNo = pac.getHeader().getUniqueNo(); |
| | | channelMap.put(clientId, ctx.channel()); |
| | | EventBus.getDefault().post(new AGVCar(clientId,ip,port,agvNo,1)); |
| | | AGVCar agvCar = new AGVCar(clientId, ip, port, agvNo, 1, battery,0,0,0,0,0,0,0,0,0,0); |
| | | EventBus.getDefault().post(agvCar); |
| | | break label; |
| | | |
| | | } |
| | |
| | | } |
| | | return sb.toString(); |
| | | } |
| | | |
| | | // 将十六进制字符串转换为字节数组 |
| | | private byte[] hexStringToByteArray(String s) { |
| | | int len = s.length(); |