package udptcp; import java.net.ServerSocket; import java.net.Socket; import java.sql.SQLException; import java.util.*; import java.util.concurrent.*; import dell_targets.Dell_differentialBaseStation; import dell_targets.Dell_tag; import targets.DifferentialBaseStation; import targets.LocationTag; public class TCPDiffDataReceiver { private static final int PORT = 7002; private static final Map deviceConnections = new ConcurrentHashMap<>(); private static final ExecutorService executor = Executors.newCachedThreadPool(); public static void main(String[] args) { // Æô¶¯É豸Á¬½Ó¼àÌýÆ÷ new Thread(TCPDiffDataReceiver::listenForDeviceConnections).start(); // Æô¶¯²î·Ö»ùÕ¾Êý¾Ý´¦ÀíÆ÷ new Thread(TCPDiffDataReceiver::processDifferentialData).start(); } // ¼àÌýÉ豸Á¬½Ó private static void listenForDeviceConnections() { try (ServerSocket serverSocket = new ServerSocket(PORT)) { System.out.println("TCP Differential Server started on port " + PORT); while (true) { Socket deviceSocket = serverSocket.accept(); String deviceId = "device_" + UUID.randomUUID(); // ʵ¼ÊÓ¦´ÓÉ豸»ñÈ¡ID deviceConnections.put(deviceId, deviceSocket); } } catch (Exception e) { System.err.println("Device connection listener crashed: " + e.getMessage()); } } // ´¦Àí²î·Ö»ùÕ¾Êý¾Ý private static void processDifferentialData() { while (true) { try { // 1. »ñÈ¡ËùÓвî·Ö»ùÕ¾ List baseStations = Dell_differentialBaseStation.getAllBaseStations(); // 2. ´¦Àíÿ¸ö»ùÕ¾µÄÊý¾Ý for (DifferentialBaseStation station : baseStations) { // Ä£Äâ½ÓÊÕÊý¾Ý byte[] diffData = receiveDataFromBaseStation(station); station.setReceivenum(station.getReceivenum() + 1); // ¸üнÓÊÕ¼ÆÊý // 3. »ñÈ¡ÔÚÏßÉ豸 List onlineDevices = Dell_tag.getlocationTags().stream() .filter(tag -> "1".equals(tag.getOnlineStatus())) .toList(); // 4. ת·¢Êý¾Ýµ½É豸 forwardToDevices(station, diffData, onlineDevices); } // ÿÃë´¦ÀíÒ»´Î Thread.sleep(1000); } catch (Exception e) { System.err.println("Differential data processing error: " + e.getMessage()); } } } // ת·¢Êý¾Ýµ½É豸 private static void forwardToDevices(DifferentialBaseStation station, byte[] data, List devices) throws SQLException { if (devices.isEmpty()) return; // µ¥»ùÕ¾Çé¿ö£º¹ã²¥µ½ËùÓÐÉ豸 if (devices.size() == 1) { broadcastData(data); return; } // ¶à»ùÕ¾Çé¿ö£ºÑ¡Ôñ×î½üµÄ»ùÕ¾ for (LocationTag device : devices) { DifferentialBaseStation nearestStation = findNearestBaseStation( device, Dell_differentialBaseStation.getAllBaseStations() ); if (nearestStation.getId().equals(station.getId())) { sendToDevice(device.getDeviceNumber(), data); } } } // ²éÕÒ×î½üµÄ»ùÕ¾ private static DifferentialBaseStation findNearestBaseStation(LocationTag device, List stations) { return stations.stream() .min(Comparator.comparingDouble(station -> calculateDistance( Double.parseDouble(device.getLatitude()), Double.parseDouble(device.getLongitude()), Double.parseDouble(station.getLatitude()), Double.parseDouble(station.getLongitude()) )) .orElse(null); } // ¼ÆËã¾àÀ루Haversine¹«Ê½£© private static double calculateDistance(double lat1, double lon1, double lat2, double lon2) { final int R = 6371; // µØÇò°ë¾¶(km) double dLat = Math.toRadians(lat2 - lat1); double dLon = Math.toRadians(lon2 - lon1); double a = Math.sin(dLat/2) * Math.sin(dLat/2) + Math.cos(Math.toRadians(lat1)) * Math.cos(Math.toRadians(lat2)) * Math.sin(dLon/2) * Math.sin(dLon/2); double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a)); return R * c; } // ¹ã²¥Êý¾Ýµ½ËùÓÐÉ豸 private static void broadcastData(byte[] data) { deviceConnections.forEach((id, socket) -> { executor.execute(() -> sendData(socket, data)); }); } // ·¢ËÍÊý¾Ýµ½Ìض¨É豸 private static void sendToDevice(String deviceId, byte[] data) { Socket socket = deviceConnections.get(deviceId); if (socket != null) { executor.execute(() -> sendData(socket, data)); } } // ʵ¼Ê·¢ËÍÊý¾Ý private static void sendData(Socket socket, byte[] data) { try { socket.getOutputStream().write(data); socket.getOutputStream().flush(); } catch (Exception e) { System.err.println("Data sending failed: " + e.getMessage()); } } // Ä£Äâ»ùÕ¾Êý¾Ý½ÓÊÕ private static byte[] receiveDataFromBaseStation(DifferentialBaseStation station) { return ("Data from " + station.getDeviceNumber()).getBytes(); } }