Skip to content

Commit

Permalink
Now supporting getZones() via JSON over RSocket (#323, #324)
Browse files Browse the repository at this point in the history
  • Loading branch information
climategadgets committed Aug 30, 2024
1 parent 289b8bc commit b867aa9
Show file tree
Hide file tree
Showing 10 changed files with 293 additions and 113 deletions.
3 changes: 3 additions & 0 deletions app/hcc-cli/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,15 @@ application {
dependencies {

implementation(libs.httpclient)
implementation(libs.jackson.datatype.jsr310)
implementation(libs.jcommander)
implementation(libs.reactor.tools)
implementation(libs.springboot.starter)
implementation(libs.springboot.starter.log4j2)
implementation(libs.springboot.starter.rsocket)

implementation(project(":modules:hcc-data-source-api"))
implementation(project(":modules:hcc-model"))
}

configurations {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@
import com.beust.jcommander.Parameter;
import com.beust.jcommander.ParameterException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.homeclimatecontrol.hcc.client.http.HccHttpClient;
import com.homeclimatecontrol.hcc.client.http.HttpClient;
import com.homeclimatecontrol.hcc.client.rsocket.RSocketClient;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.ThreadContext;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import reactor.tools.agent.ReactorDebugAgent;

import java.io.IOException;
import java.net.URL;
Expand All @@ -20,22 +22,34 @@ public class HccCLI implements CommandLineRunner {

private static final Logger logger = LogManager.getLogger(HccCLI.class);

private static final String COMMAND_GET_META = "get-meta";
private static final String COMMAND_MDNS_SCAN = "mdns-scan";
private static final String COMMAND_GET_META = "get-meta";
private static final String COMMAND_GET_ZONES = "get-zones";

private final ObjectMapper objectMapper = new ObjectMapper();
private final HccHttpClient httpClient = new HccHttpClient();
private final HttpClient httpClient = new HttpClient();
private final RSocketClient rsocketClient = new RSocketClient();

public abstract class CommandBase {

@Parameter(names = { "--url" }, description = "URL to connect to", required = true)
@Parameter(names = { "--url" }, description = "HCC meta URL to connect to", required = true)
String url;
}

public class CommandGetMeta extends CommandBase {

}

public abstract class CommandRSocket extends CommandBase {

@Parameter(names = { "--serialization" }, description = "Serialization method")
String serialization = "JSON";
}

public class CommandGetZones extends CommandRSocket {

}

public class CommandMdnsScan {

@Parameter(names = { "--timeout" }, description = "Scan timeout in seconds")
Expand All @@ -44,6 +58,8 @@ public class CommandMdnsScan {

public static void main(String[] args) {

ReactorDebugAgent.init();

var builder = new SpringApplicationBuilder(HccCLI.class);

builder.headless(false);
Expand All @@ -56,13 +72,15 @@ public static void main(String[] args) {
@Override
public void run(String... args) throws Exception {

var commandGetMeta = new CommandGetMeta();
var commandMdnsScan = new CommandMdnsScan();
var commandGetMeta = new CommandGetMeta();
var commandGetZones = new CommandGetZones();

var jc = JCommander
.newBuilder()
.addCommand(COMMAND_GET_META, commandGetMeta)
.addCommand(COMMAND_MDNS_SCAN, commandMdnsScan)
.addCommand(COMMAND_GET_META, commandGetMeta)
.addCommand(COMMAND_GET_ZONES, commandGetZones)
.build();

try {
Expand All @@ -75,8 +93,9 @@ public void run(String... args) throws Exception {

switch (jc.getParsedCommand()) {

case COMMAND_GET_META -> getMeta(commandGetMeta.url);
case COMMAND_MDNS_SCAN -> mdnsScan();
case COMMAND_GET_META -> getMeta(commandGetMeta.url);
case COMMAND_GET_ZONES -> getZones(commandGetZones.url, commandGetZones.serialization);

}

Expand All @@ -90,6 +109,15 @@ public void run(String... args) throws Exception {
}
}

private void mdnsScan() {
ThreadContext.push("mdnsScan");
try {
throw new UnsupportedOperationException("Stay tuned");
} finally {
ThreadContext.pop();
}
}

private void getMeta(String url) throws IOException {
ThreadContext.push("getMeta");
try {
Expand All @@ -103,10 +131,16 @@ private void getMeta(String url) throws IOException {
}
}

private void mdnsScan() {
ThreadContext.push("mdnsScan");
private void getZones(String url, String serialization) throws IOException {
ThreadContext.push("getZones");
try {
throw new UnsupportedOperationException("Stay tuned");
logger.info("url={}", url);

var httpUrl = new URL(url);
// First need to get this to determine the host and port to connect RSocket to
var meta = httpClient.getMeta(httpUrl);
rsocketClient.getZones(httpUrl.getHost(), meta.instance().duplexPort(), serialization);

} finally {
ThreadContext.pop();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import com.fasterxml.jackson.databind.ObjectMapper;
import com.homeclimatecontrol.hcc.meta.EndpointMeta;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.HttpClientBuilder;
Expand All @@ -18,14 +17,14 @@
*
* @author Copyright &copy; <a href="mailto:[email protected]">Vadim Tkachenko</a> 2001-2024
*/
public class HccHttpClient {
public class HttpClient {

private final Logger logger = LogManager.getLogger();
private final ObjectMapper objectMapper = new ObjectMapper();

private HttpClient httpClient;
private org.apache.http.client.HttpClient httpClient;

private synchronized HttpClient getHttpClient() {
private synchronized org.apache.http.client.HttpClient getHttpClient() {

if (httpClient == null) {

Expand All @@ -37,7 +36,7 @@ private synchronized HttpClient getHttpClient() {
return httpClient;
}

private HttpClient createClient() {
private org.apache.http.client.HttpClient createClient() {

// VT: NOTE: Copypasted with abbreviations from HttpClientFactory (search the whole project).
// Important fact not to forget: https://github.com/home-climate-control/dz/issues/80
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package com.homeclimatecontrol.hcc.client.rsocket;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.netty.buffer.ByteBufAllocator;
import io.netty.buffer.ByteBufUtil;
import io.rsocket.core.RSocketConnector;
import io.rsocket.metadata.TaggingMetadataCodec;
import io.rsocket.metadata.WellKnownMimeType;
import io.rsocket.transport.netty.client.TcpClientTransport;
import io.rsocket.util.ByteBufPayload;
import net.sf.dz3r.signal.hvac.ZoneStatus;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.util.Collections;
import java.util.List;
import java.util.Map;

/**
* HCC remote client using RSocket protocol.
*
* @author Copyright &copy; <a href="mailto:[email protected]">Vadim Tkachenko</a> 2001-2024
*/
public class RSocketClient {

private final Logger logger = LogManager.getLogger();
private final ObjectMapper objectMapper = new ObjectMapper();

public List<ZoneStatus> getZones(String bindAddress, int port, String serialization) throws JsonProcessingException {

var socket = RSocketConnector
.create()
.metadataMimeType(WellKnownMimeType.MESSAGE_RSOCKET_ROUTING.getString())
.connect(TcpClientTransport.create(bindAddress, port))
.block();

var routeMetadata =
TaggingMetadataCodec
.createTaggingContent(ByteBufAllocator.DEFAULT, Collections.singletonList(serialization));

var payload = socket
.requestResponse(
ByteBufPayload.create(
ByteBufUtil.writeUtf8(ByteBufAllocator.DEFAULT, "zones"), routeMetadata))
.log()
.block();

try {

var response = payload.getDataUtf8();
var zones = objectMapper.readValue(response, Map.class);

logger.info("ZONES:\n{}", objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(zones));

return null;
} finally {
payload.release();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package net.sf.dz3r.view.webui.v2;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import net.sf.dz3r.model.UnitDirector;
import net.sf.dz3r.view.UnitObserver;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.util.Map;

public class Endpoint {

protected final Logger logger = LogManager.getLogger();
protected final ObjectMapper objectMapper = new ObjectMapper();

protected final Map<UnitDirector, UnitObserver> unit2observer;

public Endpoint(Map<UnitDirector, UnitObserver> unit2observer) {
this.unit2observer = unit2observer;
objectMapper.registerModule(new JavaTimeModule());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@
import net.sf.dz3r.signal.Signal;
import net.sf.dz3r.signal.hvac.ZoneStatus;
import net.sf.dz3r.view.UnitObserver;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.ThreadContext;
import org.springframework.http.CacheControl;
import org.springframework.http.MediaType;
Expand All @@ -19,7 +17,6 @@
import org.springframework.web.reactive.function.server.ServerResponse;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import reactor.netty.http.server.HttpServer;

import java.io.IOException;
import java.lang.management.ManagementFactory;
Expand All @@ -34,22 +31,20 @@

import static org.springframework.web.reactive.function.server.ServerResponse.ok;

public class HttpEndpoint {
public class HttpServer extends Endpoint {

private final Logger logger = LogManager.getLogger();
private static final DurationFormatter uptimeFormatter = new DurationFormatter();

private final String interfaces;
private final int port;
private final EndpointMeta endpointMeta;
private final Map<UnitDirector, UnitObserver> unit2observer;

public HttpEndpoint(String interfaces, int port, EndpointMeta endpointMeta, Map<UnitDirector, UnitObserver> unit2observer) {
public HttpServer(String interfaces, int port, EndpointMeta endpointMeta, Map<UnitDirector, UnitObserver> unit2observer) {
super(unit2observer);

this.interfaces = interfaces;
this.port = port;
this.endpointMeta = endpointMeta;
this.unit2observer = unit2observer;
}

void run(Instant startedAt) {
Expand All @@ -59,7 +54,7 @@ void run(Instant startedAt) {
var httpHandler = RouterFunctions.toHttpHandler(new RoutingConfiguration().monoRouterFunction(this));
var adapter = new ReactorHttpHandlerAdapter(httpHandler);

var server = HttpServer.create().host(interfaces).port(port);
var server = reactor.netty.http.server.HttpServer.create().host(interfaces).port(port);
var disposableServer = server.handle(adapter).bind().block();

logger.info("started in {}ms", Duration.between(startedAt, Instant.now()).toMillis());
Expand Down
Loading

0 comments on commit b867aa9

Please sign in to comment.