diff --git a/README.md b/README.md index d1ca62d..9b3ccc9 100644 --- a/README.md +++ b/README.md @@ -69,7 +69,7 @@ Add the platform-tools to you PATH to use 'adb' command: export PATH="$PATH:/home/mark/Android/Sdk/platform-tools/" ``` -Run the 'adb devices' and 'adb usb' to verify your Android device is in development mode and allows connections. +Run the 'adb devices' and 'adb usb' to verify your Android networkService is in development mode and allows connections. ### MacOS diff --git a/src/main/java/biz/nellemann/mdexpl/DeviceCell.java b/src/main/java/biz/nellemann/mdexpl/NetworkServiceCell.java similarity index 52% rename from src/main/java/biz/nellemann/mdexpl/DeviceCell.java rename to src/main/java/biz/nellemann/mdexpl/NetworkServiceCell.java index d59043c..0295097 100644 --- a/src/main/java/biz/nellemann/mdexpl/DeviceCell.java +++ b/src/main/java/biz/nellemann/mdexpl/NetworkServiceCell.java @@ -1,44 +1,41 @@ package biz.nellemann.mdexpl; -import biz.nellemann.mdexpl.model.Device; -import biz.nellemann.mdexpl.model.Devices; +import biz.nellemann.mdexpl.model.NetworkService; import com.gluonhq.charm.glisten.control.CharmListCell; import com.gluonhq.charm.glisten.control.ListTile; -import javafx.scene.image.Image; import javafx.scene.image.ImageView; -public class DeviceCell extends CharmListCell { +public class NetworkServiceCell extends CharmListCell { private final ListTile tile; private final ImageView imageView; - public DeviceCell() { + public NetworkServiceCell() { this.tile = new ListTile(); imageView = new ImageView(); imageView.setFitHeight(15); imageView.setFitWidth(25); tile.setPrimaryGraphic(imageView); + tile.setOnMouseClicked(e -> { System.out.println("Selected -> " + itemProperty().get().getName() ); }); setText(null); } @Override - public void updateItem(Device item, boolean empty) { + public void updateItem(NetworkService item, boolean empty) { super.updateItem(item, empty); if (item != null && !empty) { - tile.textProperty().setAll(item.getName() + " (" + item.getAbbr() + ")", - "Capital: " + item.getCapital() + - ", Population (M): " + String.format("%.2f", item.getPopulation() / 1_000_000d), - "Area (km" + "\u00B2" + "): " + item.getArea() + - ", Density (pop/km" + "\u00B2" + "): " + String.format("%.1f", item.getDensity()) + tile.textProperty().setAll(item.getName() + " (" + item.getType() + ")", + "App: " + item.getApp(), "URL: " + item.getUrl() ); - final Image image = Devices.getImage(item.getFlag()); - if (image != null) { + //final Image image = Devices.getImage(item.getFlag()); + /*if (image != null) { imageView.setImage(image); - } + }*/ setGraphic(tile); } else { setGraphic(null); } } + } diff --git a/src/main/java/biz/nellemann/mdexpl/NetworkServiceListener.java b/src/main/java/biz/nellemann/mdexpl/NetworkServiceListener.java index a33c9b5..bd7c76e 100644 --- a/src/main/java/biz/nellemann/mdexpl/NetworkServiceListener.java +++ b/src/main/java/biz/nellemann/mdexpl/NetworkServiceListener.java @@ -1,24 +1,27 @@ package biz.nellemann.mdexpl; +import biz.nellemann.mdexpl.model.NetworkService; +import javafx.application.Platform; +import javafx.collections.ObservableList; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.jmdns.ServiceEvent; import javax.jmdns.ServiceInfo; import javax.jmdns.ServiceListener; -import java.util.HashMap; public class NetworkServiceListener implements ServiceListener { private static final Logger log = LoggerFactory.getLogger(NetworkServiceListener.class); - private final HashMap onlineList = new HashMap<>(); - private final String serviceType; + private final ObservableList observableList; - public NetworkServiceListener(String type) { + public NetworkServiceListener(String type, ObservableList observableList) { log.info("NetworkServiceListener() - type: {}", type); this.serviceType = type; + this.observableList = observableList; + } @Override @@ -30,8 +33,11 @@ public class NetworkServiceListener implements ServiceListener { ServiceInfo serviceInfo = event.getInfo(); if (serviceInfo != null) { String name = serviceInfo.getName(); - onlineList.remove(name); - log.info("serviceRemoved() - Removed service: " + name); + log.info("serviceRemoved() - Service: " + name); + NetworkService oldNetworkService = new NetworkService(name, serviceType, serviceInfo.getApplication(), serviceInfo.getURLs()[0]); + Platform.runLater(() -> { + observableList.remove(oldNetworkService); + }); } } @@ -42,9 +48,13 @@ public class NetworkServiceListener implements ServiceListener { String url = serviceInfo.getURLs()[0]; String name = serviceInfo.getName(); String app = serviceInfo.getApplication(); - log.debug(serviceInfo.toString()); - onlineList.put(name, url); - log.info("serviceResolved() - Found {}: {} with url {}", app, name, url); + log.info("serviceResolved() - Service: {} - {} with url {}", app, name, url); + NetworkService newNetworkService = new NetworkService(name, serviceType, app, url); + Platform.runLater(() -> { + if(!observableList.contains(newNetworkService)) { + observableList.add(newNetworkService); + } + }); } } diff --git a/src/main/java/biz/nellemann/mdexpl/model/Device.java b/src/main/java/biz/nellemann/mdexpl/model/Device.java deleted file mode 100644 index d37c4e0..0000000 --- a/src/main/java/biz/nellemann/mdexpl/model/Device.java +++ /dev/null @@ -1,87 +0,0 @@ -package biz.nellemann.mdexpl.model; - -public class Device { - - private String name; - private String abbr; - private String capital; - private int population; - private int area; /* km^2 */ - private String flag; - - public Device(String name, String abbr, String capital, int population, int area, String flag) { - this.name = name; - this.abbr = abbr; - this.capital = capital; - this.population = population; - this.area = area; - this.flag = flag; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getAbbr() { - return abbr; - } - - public void setAbbr(String abbr) { - this.abbr = abbr; - } - - public String getCapital() { - return capital; - } - - public void setCapital(String capital) { - this.capital = capital; - } - - public int getPopulation() { - return population; - } - - public void setPopulation(int population) { - this.population = population; - } - - public int getArea() { - return area; - } - - public void setArea(int area) { - this.area = area; - } - - public String getFlag() { - return flag; - } - - public void setFlag(String flag) { - this.flag = flag; - } - - /** - * Population density - * @return population density (pop. per km^2) - */ - public double getDensity() { - if (area > 0) { - return (double) population / (double) area; - } - return 0; - } - - @Override - public String toString() { - return name + " (" + abbr + "), capital=" + capital + ", population=" + population + ", area=" + area; - } - -} - - diff --git a/src/main/java/biz/nellemann/mdexpl/model/Devices.java b/src/main/java/biz/nellemann/mdexpl/model/Devices.java deleted file mode 100644 index 6a12e4a..0000000 --- a/src/main/java/biz/nellemann/mdexpl/model/Devices.java +++ /dev/null @@ -1,65 +0,0 @@ -package biz.nellemann.mdexpl.model; - -import com.gluonhq.attach.cache.Cache; -import com.gluonhq.attach.cache.CacheService; -import javafx.collections.FXCollections; -import javafx.collections.ObservableList; -import javafx.scene.image.Image; - -public class Devices { - - private static final Cache CACHE; - - static { - CACHE = CacheService.create() - .map(cache -> cache.getCache("images")) - .orElseThrow(() -> new RuntimeException("No CacheService available")); - } - - private static final String URL_PATH = "https://upload.wikimedia.org/wikipedia/commons/thumb/"; - - public static ObservableList statesList = FXCollections.observableArrayList( - new Device("Alabama", "AL", "Montgomery", 4903185, 135767, URL_PATH + "5/5c/Flag_of_Alabama.svg/23px-Flag_of_Alabama.svg.png"), - new Device("Alaska", "AK", "Juneau", 731545, 1723337, URL_PATH + "e/e6/Flag_of_Alaska.svg/21px-Flag_of_Alaska.svg.png"), - new Device("Arizona", "AZ", "Phoenix", 7278717, 295233, URL_PATH + "9/9d/Flag_of_Arizona.svg/23px-Flag_of_Arizona.svg.png"), - new Device("Arkansas", "AR", "Little Rock", 3017804, 137733, URL_PATH + "9/9d/Flag_of_Arkansas.svg/23px-Flag_of_Arkansas.svg.png"), - new Device("California", "CA", "Sacramento", 39512223, 423968, URL_PATH + "0/01/Flag_of_California.svg/23px-Flag_of_California.svg.png"), - new Device("Colorado", "CO", "Denver", 5758736, 269602, URL_PATH + "4/46/Flag_of_Colorado.svg/23px-Flag_of_Colorado.svg.png"), - new Device("Connecticut", "CT", "Hartford", 3565287, 14356, URL_PATH + "9/96/Flag_of_Connecticut.svg/20px-Flag_of_Connecticut.svg.png"), - new Device("Delaware", "DE", "Dover", 973764, 6446, URL_PATH + "c/c6/Flag_of_Delaware.svg/23px-Flag_of_Delaware.svg.png"), - new Device("Florida", "FL", "Tallahassee", 21477737, 170312, URL_PATH + "f/f7/Flag_of_Florida.svg/23px-Flag_of_Florida.svg.png"), - new Device("Georgia", "GA", "Atlanta", 10617423, 153910, URL_PATH + "5/54/Flag_of_Georgia_%28U.S._state%29.svg/23px-Flag_of_Georgia_%28U.S._state%29.svg.png"), - new Device("Hawaii", "HI", "Honolulu", 1415872, 28314, URL_PATH + "e/ef/Flag_of_Hawaii.svg/23px-Flag_of_Hawaii.svg.png"), - new Device("Idaho", "ID", "Boise", 1787065, 216443, URL_PATH + "a/a4/Flag_of_Idaho.svg/19px-Flag_of_Idaho.svg.png"), - new Device("Illinois", "IL", "Springfield", 12671821, 149997, URL_PATH + "0/01/Flag_of_Illinois.svg/23px-Flag_of_Illinois.svg.png") - - ); - - public static Image getUSFlag() { - return getImage(URL_PATH + "a/a4/Flag_of_the_United_States.svg/320px-Flag_of_the_United_States.svg.png"); - } - - /** - * This method will always return the required image. - * It will cache the image and return from cache if still there. - * @param image: A valid url to retrieve the image - * @return an Image - */ - public static Image getImage(String image) { - if (image == null || image.isEmpty()) { - return null; - } - Image cachedImage = CACHE.get(image); - if (cachedImage == null) { - cachedImage = new Image(image, true); - cachedImage.errorProperty().addListener((obs, ov, nv) -> { - if (nv) { - CACHE.remove(image); - } - }); - CACHE.put(image, cachedImage); - } - return cachedImage; - } - -} diff --git a/src/main/java/biz/nellemann/mdexpl/model/NetworkService.java b/src/main/java/biz/nellemann/mdexpl/model/NetworkService.java new file mode 100644 index 0000000..f5f9b8b --- /dev/null +++ b/src/main/java/biz/nellemann/mdexpl/model/NetworkService.java @@ -0,0 +1,66 @@ +package biz.nellemann.mdexpl.model; + +public class NetworkService { + + private String name; + private String type; + private String app; + private String url; + + public NetworkService(String name, String type, String app, String url) { + this.name = name; + this.type = type; + this.app = app; + this.url = url; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public String getApp() { + return app; + } + + public void setApp(String app) { + this.app = app; + } + + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + + @Override + public String toString() { + return name + " (" + type + "), app=" + app + ", url=" + url; + } + + @Override + public boolean equals(Object o) { + if (o == this) return true; + if (!(o instanceof NetworkService networkService)) { + return false; + } + return networkService.name.equals(name) && networkService.type.equals(type) && networkService.url.equals(url); + } + +} + + diff --git a/src/main/java/biz/nellemann/mdexpl/service/DiscoveryService.java b/src/main/java/biz/nellemann/mdexpl/service/DiscoveryService.java index 63696a5..cf3352e 100644 --- a/src/main/java/biz/nellemann/mdexpl/service/DiscoveryService.java +++ b/src/main/java/biz/nellemann/mdexpl/service/DiscoveryService.java @@ -1,16 +1,15 @@ package biz.nellemann.mdexpl.service; import biz.nellemann.mdexpl.NetworkServiceListener; +import biz.nellemann.mdexpl.model.NetworkService; +import javafx.collections.ObservableList; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.annotation.PostConstruct; import javax.inject.Singleton; import javax.jmdns.JmDNS; -import javax.jmdns.ServiceInfo; import java.io.IOException; -import java.net.InetAddress; -import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -20,29 +19,39 @@ public class DiscoveryService { private final static Logger log = LoggerFactory.getLogger(DiscoveryService.class); - // http://www.dns-sd.org/serviceTypes.html + private ObservableList observableList; + + private JmDNS jmdns; + + // From: http://www.dns-sd.org/serviceTypes.html + some guesses private final List services = Arrays.asList( "http", "https", "upnp", "ssh", "sip", "rdp", "ntp", "rdp", "rtsp", "ntp", "smb", "nfs", "llrp", "ftp", "ep", "daap", "ipp", "ipps", - "googlecast", "appletv", "appletv-itunes", "smartenergy", "skype", "bittorrent", - "sonos", "airplay" + "googlecast", "sonos", "airplay", "smartenergy", "skype", "bittorrent" ); @PostConstruct public void initialize() { log.info("initialize()"); try { - JmDNS jmdns = JmDNS.create(null, "mdnsExplorer"); - services.forEach(service -> { - String serviceType = String.format("_%s._%s.local.", service, "tcp"); - NetworkServiceListener networkServiceListener = new NetworkServiceListener(serviceType); - jmdns.addServiceListener(serviceType, networkServiceListener); - }); + jmdns = JmDNS.create(null, "mdnsExplorer"); } catch (IOException e) { log.error("initialize() - {}", e.getMessage()); } } + public void register() { + + } + + public void setObservableList(ObservableList list) { + this.observableList = list; + services.forEach(service -> { + String serviceType = String.format("_%s._%s.local.", service, "tcp"); + NetworkServiceListener networkServiceListener = new NetworkServiceListener(serviceType, observableList); + jmdns.addServiceListener(serviceType, networkServiceListener); + }); + } } diff --git a/src/main/java/biz/nellemann/mdexpl/view/MainPresenter.java b/src/main/java/biz/nellemann/mdexpl/view/MainPresenter.java index 00c975c..0969767 100644 --- a/src/main/java/biz/nellemann/mdexpl/view/MainPresenter.java +++ b/src/main/java/biz/nellemann/mdexpl/view/MainPresenter.java @@ -1,20 +1,20 @@ package biz.nellemann.mdexpl.view; +import biz.nellemann.mdexpl.NetworkServiceCell; +import biz.nellemann.mdexpl.model.NetworkService; import biz.nellemann.mdexpl.model.MainModel; import biz.nellemann.mdexpl.service.DiscoveryService; import com.gluonhq.charm.glisten.application.AppManager; import com.gluonhq.charm.glisten.control.AppBar; import com.gluonhq.charm.glisten.control.CharmListView; -import com.gluonhq.charm.glisten.control.Icon; import com.gluonhq.charm.glisten.control.LifecycleEvent; import com.gluonhq.charm.glisten.mvc.View; import com.gluonhq.charm.glisten.visual.MaterialDesignIcon; -import javafx.beans.property.DoubleProperty; -import javafx.beans.property.SimpleDoubleProperty; +import javafx.collections.FXCollections; +import javafx.collections.ObservableList; import javafx.fxml.FXML; -import javafx.geometry.Orientation; -import javafx.scene.control.ScrollPane; -import javafx.scene.image.ImageView; +import javafx.scene.input.MouseEvent; +import javafx.scene.input.TouchEvent; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -41,6 +41,8 @@ public class MainPresenter { @FXML private CharmListView charmListView; + private ObservableList devicesList = FXCollections.observableArrayList(); + @FXML public void initialize() { @@ -56,19 +58,19 @@ public class MainPresenter { appManager.getDrawer().open())); appBar.setTitleText("mDNS Explorer"); - //appBar.getActionItems().add(progressIndicator); } }); + discoveryService.setObservableList(devicesList); + charmListView.setItems(devicesList); + charmListView.setCellFactory(p -> new NetworkServiceCell()); } @FXML protected void onButtonRefresh() { log.info("onButtonRefresh()"); - - }