Untitled
unknown
plain_text
a month ago
13 kB
6
Indexable
START PROMPT You are helping me build the client side for a Java SEP4 thermonet monitoring system. The server already exists. It is a JavaFX server-side monitoring/control application for a thermonet with decentralised heat pumps. The architecture is MVVM on the server side, and the socket communication follows the teaching patterns from VIA: Socket Connections, JSON Structured Data Transfer, DTOs, and simple separation between layers. Your task is to build the client-side Java program that simulates or represents one physical heat pump. Use simple Java. Do not overcomplicate the solution. Keep the classes separated, but easy to understand for a 4th semester Software Engineering student. The client must communicate with the existing server through sockets using JSON messages. Server connection details The server listens on: host: localhost port: 2910 Communication is line-based JSON over TCP sockets. The server uses: BufferedReader.readLine() PrintWriter.println(json) Therefore the client must also send one complete JSON message per line. Important: The client must keep the socket open and keep listening for commands from the server. Existing server DTOs and socket format The client must use DTO classes that match the server exactly. The server has these enums: CommandType: - SET_STATE - SET_TARGET_TEMPERATURE - REQUEST_DATA - PING PumpState: - HEATING - IDLE - OFF - ERROR - LOADSHIFTING MessageType: - STATE_COMMAND - PUMP_DATA - STATE_RESPONSE - ERROR The server wraps all messages in this structure: JsonMessage - Header header - Body body Header: - static VERSION = "1.0" - MessageType TYPE Important: The JSON field is currently named TYPE in the server because the field in Header is called TYPE. Do not rename it to type unless the server is changed too. Body can contain: - StateCommandDTO stateCommand - PumpDataDTO pumpData - StateResponseDTO stateResponse - String errorDescription The client must be able to receive STATE_COMMAND messages from the server and send PUMP_DATA and STATE_RESPONSE messages back. The client must copy or recreate these DTO/socket classes so the JSON format matches the server: - CommandType - PumpState - StateCommandDTO - PumpDataDTO - StateResponseDTO - JsonMessage - JsonUtil - MessageType Use Gson for JSON. JsonUtil must support LocalDateTime using ISO_LOCAL_DATE_TIME, exactly like the server. PumpDataDTO fields expected by the server right now The server currently expects these fields in PumpDataDTO: private int pumpId; private PumpState currentState; private double currentTemperature; private double targetTemperature; private double minimumTemperature; private String errorMessage; private LocalDateTime timestamp; private String address; private int sqMeter; private String pumpType; When the client connects for the first time, it must immediately send a PUMP_DATA message containing: - pumpId - address - sqMeter - pumpType - currentState - currentTemperature - targetTemperature - minimumTemperature - errorMessage - timestamp This is important because the server uses the first PUMP_DATA message to assign the socket connection to a pumpId. If the server does not already know the pumpId, it will create a new pump, create a folder for it, and save the base information. Expected client behaviour When the client starts: 1. Create a HeatPumpClientModel object with pump base information: - pumpId - address - sqMeter - pumpType 2. Connect to the server on localhost:2910. 3. Immediately send a PUMP_DATA registration/update message. 4. Start listening for messages from the server. 5. Keep the socket alive until the program stops. When the client receives a STATE_COMMAND message: - Read body.stateCommand - Check commandType If commandType == SET_STATE: - Change the local pump state to targetState - Send a STATE_RESPONSE message back to the server - The response should contain: - pumpId - requestedState - currentState - success - message - timestamp If commandType == SET_TARGET_TEMPERATURE: - Change local targetTemperature - Send STATE_RESPONSE with success true If commandType == REQUEST_DATA: - Generate or read the newest pump data - Send a PUMP_DATA message back to the server If commandType == PING: - Send a STATE_RESPONSE or simple response showing that the pump is alive Client-side class structure Create a simple Java project with these packages: dto - CommandType - PumpState - StateCommandDTO - PumpDataDTO - StateResponseDTO socket - JsonMessage - JsonUtil - MessageType - PumpClientSocket model - HeatPumpClientModel - PumpDataGenerator app - PumpClientMain - TestPumpSimulationRunner Class responsibilities PumpClientMain Purpose: Starts one pump client. Responsibilities: - Create one HeatPumpClientModel - Create one PumpClientSocket - Connect to the server - Send initial pump data - Start listening for server commands Example values: pumpId = 11 address = "Testvej 11, 8660 Tebstrup" sqMeter = 145 pumpType = "Vølund F1255" PumpClientSocket Purpose: Handles all socket communication. Fields: - Socket socket - BufferedReader in - PrintWriter out - HeatPumpClientModel model - boolean running Methods: - connect(String host, int port) - send(JsonMessage message) - listen() - handleMessage(JsonMessage message) - handleStateCommand(StateCommandDTO command) - close() Important: The socket class should not contain simulation logic. It should only handle communication and delegate pump behaviour to the model. HeatPumpClientModel Purpose: Represents the local heat pump. Fields: - int pumpId - String address - int sqMeter - String pumpType - PumpState currentState - double currentTemperature - double targetTemperature - double minimumTemperature - String errorMessage Methods: - createPumpDataDTO() - applyState(PumpState state) - setTargetTemperature(double targetTemperature) - createStateResponse(StateCommandDTO command, boolean success, String message) - updateSimulatedMeasurements() This model should own the current pump state. PumpDataGenerator Purpose: Generates realistic test data for the heat pump. Methods: - double generateCurrentTemperature(PumpState state, double targetTemperature) - double generateKwhUsage(PumpState state, int sqMeter, LocalDateTime time) - double generateFlowRate(PumpState state) - PumpDataDTO generatePumpData(HeatPumpClientModel model) The current server only reads the basic fields from PumpDataDTO, but design the generator so it is ready for measurement values later. If you add extra fields to PumpDataDTO for measurement data, use names that match the server's measurement JSON concept: - kwhUsage - electricityPrice - targetTankTemp - currentTankTemp - tankTemp - flowRate - status Important: If the server DTO does not yet contain these fields, Gson will ignore them on the server unless the server is updated. Therefore keep the core fields working first. Communication examples Initial registration message from client to server should be a JsonMessage with: header.TYPE = PUMP_DATA body.pumpData contains: pumpId currentState currentTemperature targetTemperature minimumTemperature errorMessage timestamp address sqMeter pumpType State command from server to client: header.TYPE = STATE_COMMAND body.stateCommand contains: pumpId commandType targetState targetTemperature timestamp State response from client to server: header.TYPE = STATE_RESPONSE body.stateResponse contains: pumpId requestedState currentState success message timestamp Very important behaviour The client must always include pumpId in every DTO it sends. The client must always include address, sqMeter and pumpType in PUMP_DATA messages, especially the first one. If the pump is OFF: - currentState should be OFF - kWh usage should be 0 or very low - flow rate should be 0 or very low - response to SET_STATE should still work If the pump is ERROR: - currentState should be ERROR - errorMessage should contain a readable message - kWh usage should be low - STATE_RESPONSE success can be true if the command was received, but message should explain the error state if relevant If the pump is LOADSHIFTING: - kWh usage should be reduced - temperature may slowly fall towards minimumTemperature - this represents flexibility in the thermonet during expensive electricity periods Expected simulation logic Use a simple realistic load profile. For a normal Danish house with heat pump: - low electricity use during night - higher in the morning around 06:00-08:30 - lower during midday - highest in the evening around 17:00-20:00 - lower again late evening Make simple half-hour based values. Example logic: - 00:00-05:00 low - 06:00-08:30 medium/high - 09:00-15:00 medium/low - 16:00-20:00 high - 21:00-23:30 medium/low Scale the kWh usage by house size: - small house: lower usage - large house: higher usage Keep the generated values realistic: - daily heat pump electricity use roughly 12-30 kWh depending on house size and scenario - half-hour kWh usage often around 0.2-1.5 kWh for one pump - larger peaks are okay during cold/heavy use periods Server request behaviour The final system idea is that the server requests updates every half hour. Therefore the client must support REQUEST_DATA. When the client receives: CommandType.REQUEST_DATA It must: 1. Generate current pump data 2. Wrap it in JsonMessage.createPumpDataMessage(data) 3. Send it to the server Do not make the client depend on a GUI. The client should be a console/background program. Test simulation class At the bottom of the solution, create a test class: TestPumpSimulationRunner Purpose: Simulate 10 pump clients connecting to the same server. It should create 10 HeatPumpClientModel objects with different: - pumpId - address - sqMeter - pumpType - initial state Use these example pumps: 1, "Bavnevænget 21, 8660 Tebstrup", 142, "Bosch Compress 7800i LW" 2, "Risvej 7, 8660 Tebstrup", 118, "Vølund F1155" 3, "Tranevej 8, 8660 Tebstrup", 156, "Metro Therm Miba 07" 4, "Bredmosevej 3, 8660 Tebstrup", 104, "Danfoss DHP-L Opti" 5, "Horsensvej 115, 8660 Tebstrup", 189, "Viessmann Vitocal 300-G" 6, "Kattrupvej 8, 8660 Tebstrup", 131, "NIBE S1255" 7, "Tebstrup Parkvej 1, 8660 Tebstrup", 167, "Thermia Calibra Eco" 8, "Højtoftevej 27, 8660 Tebstrup", 122, "Bosch Compress 7001i LW" 9, "Bjerggårdsvej 2, 8660 Tebstrup", 174, "Vaillant flexoTHERM exclusive" 10, "Kirstinelundsvej 8, 8660 Tebstrup", 145, "Vølund F1255" The test runner should: - Start 10 separate clients - Connect all of them to localhost:2910 - Send initial PUMP_DATA from each client - Keep all clients alive - Allow easy control over simulated scenarios Make it possible to choose scenarios such as: - NORMAL - HIGH_USAGE - LOW_USAGE - LOADSHIFTING - ERROR - OFFLINE Suggested design: Create enum SimulationScenario: - NORMAL - HIGH_USAGE - LOW_USAGE - LOADSHIFTING - ERROR - OFF Each HeatPumpClientModel should have a scenario field. The test class should allow changing: - currentState - targetTemperature - currentTemperature - simulated kWh usage - errorMessage Make the test runner simple. It can use console commands or hardcoded scenario changes. Example: After 30 seconds: - pump 3 goes ERROR - pump 5 goes LOADSHIFTING - pump 7 goes OFF After another 30 seconds: - pump 3 returns HEATING - pump 5 returns HEATING - pump 7 returns IDLE Because we do not want to wait real half hours during testing, add an optional accelerated mode: - every 5 seconds simulates one half-hour reading But still make sure the client can respond to real REQUEST_DATA messages from the server. Important separation Do not put socket code inside the model. Do not put simulation calculations inside the socket class. Do not put JSON parsing directly in Main. Use this separation: - PumpClientMain starts the program - PumpClientSocket handles socket communication - HeatPumpClientModel stores pump state - PumpDataGenerator creates simulated values - DTO classes only carry data - JsonUtil handles Gson conversion Expected final output Please create all necessary Java classes. Also explain: 1. How to start one pump client 2. How to start the 10-pump simulation 3. What JSON message is sent when the client connects 4. How the client reacts to SET_STATE 5. How the client reacts to REQUEST_DATA 6. What must match the server exactly Keep the implementation simple and readable. END PROMPT
Editor is loading...
Leave a Comment