From af9c3c9111d681208a165450c678e7322ad9aa6c Mon Sep 17 00:00:00 2001 From: AllanCapistrano Date: Thu, 26 Oct 2023 13:49:21 -0300 Subject: [PATCH 01/52] chore: deleting unused class --- .../node/tasks/NeedServiceTask.java | 41 ------------------- 1 file changed, 41 deletions(-) delete mode 100644 src/main/java/reputation/node/tasks/NeedServiceTask.java diff --git a/src/main/java/reputation/node/tasks/NeedServiceTask.java b/src/main/java/reputation/node/tasks/NeedServiceTask.java deleted file mode 100644 index bab7494..0000000 --- a/src/main/java/reputation/node/tasks/NeedServiceTask.java +++ /dev/null @@ -1,41 +0,0 @@ -package reputation.node.tasks; - -import java.util.TimerTask; -import java.util.logging.Logger; -import reputation.node.models.Node; - -/** - * Classe responsável pela tarefa de requisitar serviços para os demais nós. - * - * @author Allan Capistrano - * @version 1.0.0 - */ -public class NeedServiceTask extends TimerTask { - - private final Node node; - private static final Logger logger = Logger.getLogger( - NeedServiceTask.class.getName() - ); - - /** - * Método construtor - * - * @param node NodeType - Nó que realizará a requisição. - */ - public NeedServiceTask(Node node) { - this.node = node; - } - - @Override - public void run() { - if (!this.node.isRequestingService()) { - logger.info("Requesting service from node"); - - try { - this.node.requestServiceFromNode(); - } catch (InterruptedException e) { - logger.warning("Could not request a service from a node."); - } - } - } -} From 3a6db1559a5fb838c02dd17e12f44fca7f4c5ada Mon Sep 17 00:00:00 2001 From: AllanCapistrano Date: Thu, 26 Oct 2023 13:49:52 -0300 Subject: [PATCH 02/52] chore: update NodeServiceType --- .../node/enums/NodeServiceType.java | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/src/main/java/reputation/node/enums/NodeServiceType.java b/src/main/java/reputation/node/enums/NodeServiceType.java index f8819bf..5d7a2e1 100644 --- a/src/main/java/reputation/node/enums/NodeServiceType.java +++ b/src/main/java/reputation/node/enums/NodeServiceType.java @@ -2,10 +2,23 @@ /** * Enumerador com os tipos possíveis de serviços que um nó pode prestar. - * + * * @author Allan Capistrano - * @version 1.0.0 + * @version 1.1.0 */ public enum NodeServiceType { - RND_DEVICE_ID + THERMOMETER("Thermometer"), + HUMIDITY_SENSOR("HumiditySensor"), + PULSE_OXYMETER("PulseOxymeter"), + WIND_DIRECTION_SENSOR("WindDirectionSensor"); + + private String description; + + NodeServiceType(String description) { + this.description = description; + } + + public String getDescription() { + return description; + } } From 8ceb65576101058b0a219d08247fcde140be2877 Mon Sep 17 00:00:00 2001 From: AllanCapistrano Date: Thu, 26 Oct 2023 13:50:19 -0300 Subject: [PATCH 03/52] feat: create publishNodeServices and removing unnecessary methods --- .../java/reputation/node/models/Node.java | 356 ++++++++---------- 1 file changed, 156 insertions(+), 200 deletions(-) diff --git a/src/main/java/reputation/node/models/Node.java b/src/main/java/reputation/node/models/Node.java index 72effb6..3684730 100644 --- a/src/main/java/reputation/node/models/Node.java +++ b/src/main/java/reputation/node/models/Node.java @@ -4,14 +4,10 @@ import br.ufba.dcc.wiser.soft_iot.entities.Device; import br.ufba.dcc.wiser.soft_iot.entities.Sensor; import dlt.client.tangle.hornet.enums.TransactionType; +import dlt.client.tangle.hornet.model.DeviceSensorId; import dlt.client.tangle.hornet.model.transactions.IndexTransaction; -import dlt.client.tangle.hornet.model.transactions.TargetedTransaction; import dlt.client.tangle.hornet.model.transactions.Transaction; import dlt.client.tangle.hornet.model.transactions.reputation.ReputationService; -import dlt.client.tangle.hornet.model.transactions.reputation.ReputationServiceReply; -import dlt.client.tangle.hornet.model.transactions.reputation.ReputationServiceRequest; -import dlt.client.tangle.hornet.model.transactions.reputation.ReputationServiceResponse; -import dlt.client.tangle.hornet.services.ILedgerSubscriber; import java.io.IOException; import java.util.ArrayList; import java.util.List; @@ -26,10 +22,8 @@ import reputation.node.services.NodeTypeService; import reputation.node.tangle.LedgerConnector; import reputation.node.tasks.CheckDevicesTask; -import reputation.node.tasks.NeedServiceTask; import reputation.node.tasks.RequestDataTask; import reputation.node.tasks.WaitDeviceResponseTask; -import reputation.node.tasks.WaitNodeResponseTask; import reputation.node.utils.MQTTClient; /** @@ -37,24 +31,24 @@ * @author Allan Capistrano * @version 1.2.0 */ -public class Node implements NodeTypeService, ILedgerSubscriber { +public class Node implements NodeTypeService { private MQTTClient MQTTClient; private INodeType nodeType; private int checkDeviceTaskTime; private int requestDataTaskTime; - private int requestServiceTaskTime; + private int requestServiceTaskTime; // TODO: Verificar se ainda vai precisar private int waitDeviceResponseTaskTime; - private int waitNodeResponseTaskTime; + private int waitNodeResponseTaskTime; // TODO: Verificar se ainda vai precisar private List devices; private LedgerConnector ledgerConnector; private int amountDevices = 0; private IDevicePropertiesManager deviceManager; private ListenerDevices listenerDevices; private TimerTask waitDeviceResponseTask; - private TimerTask waitNodeResponseTask; + private TimerTask waitNodeResponseTask; // TODO: Verificar se ainda vai precisar private ReentrantLock mutex = new ReentrantLock(); - private boolean requestingService; + private boolean requestingService; // TODO: Verificar se ainda vai precisar private static final Logger logger = Logger.getLogger(Node.class.getName()); public Node() {} @@ -80,19 +74,6 @@ public void start() { this.requestDataTaskTime * 1000 ); - this.ledgerConnector.subscribe(TransactionType.REP_SVC.name(), this); - this.ledgerConnector.subscribe(TransactionType.REP_SVC_REPLY.name(), this); - this.ledgerConnector.subscribe(TransactionType.REP_SVC_REQ.name(), this); - this.ledgerConnector.subscribe(TransactionType.REP_SVC_RES.name(), this); - this.ledgerConnector.subscribe(TransactionType.REP_EVALUATION.name(), this); - - new Timer() - .scheduleAtFixedRate( - new NeedServiceTask(this), - 0, - this.requestServiceTaskTime * 1000 - ); - this.requestingService = false; } @@ -102,155 +83,9 @@ public void start() { public void stop() { this.devices.forEach(d -> this.listenerDevices.unsubscribe(d.getId())); - this.ledgerConnector.unsubscribe(TransactionType.REP_SVC.name(), this); - this.ledgerConnector.unsubscribe( - TransactionType.REP_SVC_REPLY.name(), - this - ); - this.ledgerConnector.unsubscribe(TransactionType.REP_SVC_REQ.name(), this); - this.ledgerConnector.unsubscribe(TransactionType.REP_SVC_RES.name(), this); - this.ledgerConnector.unsubscribe( - TransactionType.REP_EVALUATION.name(), - this - ); - this.MQTTClient.disconnect(); } - /** - * Método que lida com as transações da blockchain recebidas através do ZQM. - * - * @param object Object - Transação (precisa de casting para Transaction). - * @param object2 Object - Id da transação (precisa de casting para String). - */ - @Override - public void update(Object object, Object object2) { - String sourceReceivedTransaction = ((Transaction) object).getSource(); - - if (!sourceReceivedTransaction.equals(this.getNodeType().getNodeId())) { - Transaction receivedTransaction = (Transaction) object; - String nodeId = this.getNodeType().getNodeId(); - String nodeGroup = this.getNodeType().getNodeGroup(); - - Transaction transaction = null; - String transactionType = null; - - if (receivedTransaction.getType() == TransactionType.REP_SVC) { - /* Só responde se tiver pelo menos um dispositivo conectado ao nó. */ - if (this.amountDevices > 0) { - logger.info("Received a REP_SVC transaction."); - - transaction = - new ReputationServiceReply( - nodeId, - sourceReceivedTransaction, - nodeGroup, - TransactionType.REP_SVC_REPLY - ); - - transactionType = TransactionType.REP_SVC_REPLY.name(); - } - } else { - TargetedTransaction receivedTargetedTransaction = (TargetedTransaction) object; - - if (receivedTargetedTransaction.getTarget().equals(nodeId)) { - switch (receivedTargetedTransaction.getType()) { - case REP_SVC_REPLY: - if (!this.requestingService) { - logger.info("Received a REP_SVC_REPLY transaction"); - - transaction = - new ReputationServiceRequest( - nodeId, - sourceReceivedTransaction, - nodeGroup, - TransactionType.REP_SVC_REQ, - NodeServiceType.RND_DEVICE_ID.name() - ); - - transactionType = TransactionType.REP_SVC_REQ.name(); - - this.requestingService = true; - } - - break; - case REP_SVC_REQ: - String deviceId = this.getRandomDeviceId(); - - if (deviceId != null) { - logger.info("Received a REP_SVC_REQ transaction."); - - transaction = - new ReputationServiceResponse( - nodeId, - sourceReceivedTransaction, - nodeGroup, - TransactionType.REP_SVC_RES, - deviceId - ); - - transactionType = TransactionType.REP_SVC_RES.name(); - } - - break; - case REP_SVC_RES: - logger.info("Received a RECEIVED REP_SVC_RES transaction."); - - if (this.requestingService) { - /* Como recebeu o serviço, finaliza o timer, e avalia o nó - prestador. */ - if (this.waitNodeResponseTask != null) { - this.waitNodeResponseTask.cancel(); - } - - try { - this.getNodeType() - .getNode() - .evaluateServiceProvider(sourceReceivedTransaction, 1); - } catch (InterruptedException e) { - logger.warning( - "Could not add transaction on tangle network." - ); - } - } - - this.requestingService = false; - - break; - default: - break; - } - } - } - - if (transaction != null && transactionType != null) { - try { - /* Enviando a transação. */ - this.ledgerConnector.put( - new IndexTransaction(transactionType, transaction) - ); - } catch (InterruptedException ie) { - logger.warning( - "Could not sent the" + transactionType + " transaction." - ); - logger.warning(ie.getStackTrace().toString()); - } - - if (transactionType.equals(TransactionType.REP_SVC_REQ.name())) { - /* Timer para esperar a resposta do serviço requisitado. */ - this.waitNodeResponseTask = - new WaitNodeResponseTask( - sourceReceivedTransaction, - (this.waitNodeResponseTaskTime * 1000), - this - ); - - new Timer().scheduleAtFixedRate(this.waitNodeResponseTask, 0, 1000); - } - } - } - } - /** * Atualiza a lista de dispositivos conectados. * @@ -269,6 +104,16 @@ public void updateDeviceList() throws IOException { } finally { this.mutex.unlock(); } + + // TODO: Remover + if (this.amountDevices > 0) { + try { + this.publishNodeServices(); + } catch (InterruptedException ie) { + logger.warning("Could not sent the transaction."); + logger.warning(ie.getStackTrace().toString()); + } + } } /** @@ -308,44 +153,155 @@ public void requestDataFromRandomDevice() { } } - /** - * Retorna o ID de um dispositivo aleatório que está conectado ao nó. - * - * @return String - */ - private String getRandomDeviceId() { - String deviceId = null; - + // TODO: Está escrevendo errado o deviceSensorIdList + public void publishNodeServices() throws InterruptedException { if (this.amountDevices > 0) { + List deviceSensorIdList = new ArrayList<>(); + Transaction transaction = null; + String transactionType = null; + try { this.mutex.lock(); - int randomIndex = new Random().nextInt(this.amountDevices); + for (NodeServiceType serviceType : NodeServiceType.values()) { + deviceSensorIdList.clear(); + logger.info(serviceType.getDescription()); // TODO: Remover + + for (Device d : this.devices) { + d + .getSensors() + .stream() + .filter(s -> s.getType().equals(serviceType.getDescription())) + .forEach(s -> + deviceSensorIdList.add(new DeviceSensorId(d.getId(), s.getId())) + ); + } + + deviceSensorIdList.forEach(d -> logger.info(d.getSensorId())); + + switch (serviceType) { + case HUMIDITY_SENSOR: + logger.info("1"); // TODO: Remover + + transaction = + new ReputationService( + this.nodeType.getNodeId(), + this.nodeType.getNodeGroup(), + deviceSensorIdList, + TransactionType.REP_SVC_HUMIDITY_SENSOR + ); + + logger.info( + ((ReputationService) transaction).getServices() + .get(0) + .getSensorId() + ); // TODO: Remover - deviceId = this.devices.get(randomIndex).getId(); + transactionType = TransactionType.REP_SVC_HUMIDITY_SENSOR.name(); + + if (transaction != null && transactionType != null) { + this.ledgerConnector.put( + new IndexTransaction(transactionType, transaction) + ); + } + + break; + case PULSE_OXYMETER: + logger.info("2"); // TODO: Remover + + transaction = + new ReputationService( + this.nodeType.getNodeId(), + this.nodeType.getNodeGroup(), + deviceSensorIdList, + TransactionType.REP_SVC_PULSE_OXYMETER + ); + + logger.info( + ((ReputationService) transaction).getServices() + .get(0) + .getSensorId() + ); // TODO: Remover + + transactionType = TransactionType.REP_SVC_PULSE_OXYMETER.name(); + + if (transaction != null && transactionType != null) { + this.ledgerConnector.put( + new IndexTransaction(transactionType, transaction) + ); + } + + break; + case THERMOMETER: + logger.info("3"); // TODO: Remover + + transaction = + new ReputationService( + this.nodeType.getNodeId(), + this.nodeType.getNodeGroup(), + deviceSensorIdList, + TransactionType.REP_SVC_THERMOMETER + ); + + logger.info( + ((ReputationService) transaction).getServices() + .get(0) + .getSensorId() + ); // TODO: Remover + + transactionType = TransactionType.REP_SVC_THERMOMETER.name(); + + if (transaction != null && transactionType != null) { + this.ledgerConnector.put( + new IndexTransaction(transactionType, transaction) + ); + } + + break; + case WIND_DIRECTION_SENSOR: + logger.info("4"); // TODO: Remover + + transaction = + new ReputationService( + this.nodeType.getNodeId(), + this.nodeType.getNodeGroup(), + deviceSensorIdList, + TransactionType.REP_SVC_WIND_DIRECTION_SENSOR + ); + + logger.info( + ((ReputationService) transaction).getServices() + .get(0) + .getSensorId() + ); // TODO: Remover + + transactionType = + TransactionType.REP_SVC_WIND_DIRECTION_SENSOR.name(); + + if (transaction != null && transactionType != null) { + this.ledgerConnector.put( + new IndexTransaction(transactionType, transaction) + ); + } + + break; + default: + logger.severe("Unknown service type."); + break; + } + + // if (transaction != null && transactionType != null) { + // this.ledgerConnector.put( + // new IndexTransaction(transactionType, transaction) + // ); + // } + + logger.info("-----"); // TODO: Remover + } } finally { this.mutex.unlock(); } } - - return deviceId; - } - - /** - * Envia uma transação indicando que o nó precisa do serviço de um outro nó. - * - * @throws InterruptedException - */ - public void requestServiceFromNode() throws InterruptedException { - Transaction transaction = new ReputationService( - this.getNodeType().getNodeId(), - this.getNodeType().getNodeGroup(), - TransactionType.REP_SVC - ); - - this.ledgerConnector.put( - new IndexTransaction(TransactionType.REP_SVC.name(), transaction) - ); } /** From 2ec9ec90fd0e0076164babbdf666376ffb2ff04f Mon Sep 17 00:00:00 2001 From: AllanCapistrano Date: Fri, 27 Oct 2023 09:38:27 -0300 Subject: [PATCH 04/52] chore: removing unused properties and add publishNodeServiceTaskTime --- src/main/resources/OSGI-INF/blueprint/blueprint.xml | 6 ++---- .../resources/br.uefs.larsid.soft_iot.reputation_node.cfg | 7 ++----- 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/src/main/resources/OSGI-INF/blueprint/blueprint.xml b/src/main/resources/OSGI-INF/blueprint/blueprint.xml index 08d4b59..e86a581 100644 --- a/src/main/resources/OSGI-INF/blueprint/blueprint.xml +++ b/src/main/resources/OSGI-INF/blueprint/blueprint.xml @@ -27,9 +27,8 @@ - + - @@ -49,9 +48,8 @@ - + - diff --git a/src/main/resources/br.uefs.larsid.soft_iot.reputation_node.cfg b/src/main/resources/br.uefs.larsid.soft_iot.reputation_node.cfg index e1d6e7b..496c560 100644 --- a/src/main/resources/br.uefs.larsid.soft_iot.reputation_node.cfg +++ b/src/main/resources/br.uefs.larsid.soft_iot.reputation_node.cfg @@ -8,13 +8,10 @@ pass=karaf checkDeviceTaskTime=5 # Tempo (segundos) para o nó requisitar dados para um dos dispositivos conectados. requestDataTaskTime=30 -# Tempo (segundos) para o nó requisitar o serviço de um outro nó. -requestServiceTaskTime = 45 # Tempo máximo (segundos) de espera da resposta do dispositivo para a requisição feita pelo nó. # Obs: Tem que ser menor do que o 'requestDataTaskTime'. waitDeviceResponseTaskTime=10 -# Tempo máximo (segundos) de espera da resposta de um nó para a requisição de serviço feita pelo nó. -# Obs: Tem que ser menor do que o 'requestServiceTaskTime'. -waitNodeResponseTaskTime=15 +# Tempo (segundos) para o nó enviar quais são os serviços que o mesmo provê. +publishNodeServicesTaskTime=30 debugModeValue=true \ No newline at end of file From 203c743659f317769ac3c3189184eb060b30ca44 Mon Sep 17 00:00:00 2001 From: AllanCapistrano Date: Fri, 27 Oct 2023 09:38:50 -0300 Subject: [PATCH 05/52] feat: create PublishNodeServicesTask --- .../node/tasks/PublishNodeServicesTask.java | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 src/main/java/reputation/node/tasks/PublishNodeServicesTask.java diff --git a/src/main/java/reputation/node/tasks/PublishNodeServicesTask.java b/src/main/java/reputation/node/tasks/PublishNodeServicesTask.java new file mode 100644 index 0000000..7fae79b --- /dev/null +++ b/src/main/java/reputation/node/tasks/PublishNodeServicesTask.java @@ -0,0 +1,38 @@ +package reputation.node.tasks; + +import java.util.TimerTask; +import java.util.logging.Logger; +import reputation.node.models.Node; + +/** + * Classe responsável pela tarefa de publicar quais são os serviços providos + * pelo nó. + * + * @author Allan Capistrano + * @version 1.0.0 + */ +public class PublishNodeServicesTask extends TimerTask { + + private final Node node; + private static final Logger logger = Logger.getLogger( + PublishNodeServicesTask.class.getName() + ); + + public PublishNodeServicesTask(Node node) { + this.node = node; + } + + @Override + public void run() { + if (this.node.getAmountDevices() > 0) { + logger.info("Publishing the node services..."); + + try { + this.node.publishNodeServices(); + } catch (InterruptedException ie) { + logger.warning("Could not sent the transaction."); + logger.warning(ie.getStackTrace().toString()); + } + } + } +} From e92b7b90ee34e4a2f990933c0da02d2603baac7f Mon Sep 17 00:00:00 2001 From: AllanCapistrano Date: Fri, 27 Oct 2023 09:39:20 -0300 Subject: [PATCH 06/52] fix: pubishNodeServices and removing unused timeouts --- .../java/reputation/node/models/Node.java | 246 +++++++----------- 1 file changed, 90 insertions(+), 156 deletions(-) diff --git a/src/main/java/reputation/node/models/Node.java b/src/main/java/reputation/node/models/Node.java index 3684730..925cd8c 100644 --- a/src/main/java/reputation/node/models/Node.java +++ b/src/main/java/reputation/node/models/Node.java @@ -22,6 +22,7 @@ import reputation.node.services.NodeTypeService; import reputation.node.tangle.LedgerConnector; import reputation.node.tasks.CheckDevicesTask; +import reputation.node.tasks.PublishNodeServicesTask; import reputation.node.tasks.RequestDataTask; import reputation.node.tasks.WaitDeviceResponseTask; import reputation.node.utils.MQTTClient; @@ -37,9 +38,8 @@ public class Node implements NodeTypeService { private INodeType nodeType; private int checkDeviceTaskTime; private int requestDataTaskTime; - private int requestServiceTaskTime; // TODO: Verificar se ainda vai precisar private int waitDeviceResponseTaskTime; - private int waitNodeResponseTaskTime; // TODO: Verificar se ainda vai precisar + private int publishNodeServicesTaskTime; private List devices; private LedgerConnector ledgerConnector; private int amountDevices = 0; @@ -73,6 +73,12 @@ public void start() { 0, this.requestDataTaskTime * 1000 ); + new Timer() + .scheduleAtFixedRate( + new PublishNodeServicesTask(this), + 0, + this.publishNodeServicesTaskTime * 1000 + ); this.requestingService = false; } @@ -104,16 +110,6 @@ public void updateDeviceList() throws IOException { } finally { this.mutex.unlock(); } - - // TODO: Remover - if (this.amountDevices > 0) { - try { - this.publishNodeServices(); - } catch (InterruptedException ie) { - logger.warning("Could not sent the transaction."); - logger.warning(ie.getStackTrace().toString()); - } - } } /** @@ -153,20 +149,21 @@ public void requestDataFromRandomDevice() { } } - // TODO: Está escrevendo errado o deviceSensorIdList + /** + * Publica na blockchain quais são os serviços providos pelo nó. + * + * @throws InterruptedException + */ public void publishNodeServices() throws InterruptedException { if (this.amountDevices > 0) { - List deviceSensorIdList = new ArrayList<>(); Transaction transaction = null; String transactionType = null; - try { - this.mutex.lock(); - - for (NodeServiceType serviceType : NodeServiceType.values()) { - deviceSensorIdList.clear(); - logger.info(serviceType.getDescription()); // TODO: Remover + for (NodeServiceType serviceType : NodeServiceType.values()) { + List deviceSensorIdList = new ArrayList<>(); + try { + this.mutex.lock(); for (Device d : this.devices) { d .getSensors() @@ -176,130 +173,75 @@ public void publishNodeServices() throws InterruptedException { deviceSensorIdList.add(new DeviceSensorId(d.getId(), s.getId())) ); } + } finally { + this.mutex.unlock(); + } - deviceSensorIdList.forEach(d -> logger.info(d.getSensorId())); - - switch (serviceType) { - case HUMIDITY_SENSOR: - logger.info("1"); // TODO: Remover - - transaction = - new ReputationService( - this.nodeType.getNodeId(), - this.nodeType.getNodeGroup(), - deviceSensorIdList, - TransactionType.REP_SVC_HUMIDITY_SENSOR - ); - - logger.info( - ((ReputationService) transaction).getServices() - .get(0) - .getSensorId() - ); // TODO: Remover - - transactionType = TransactionType.REP_SVC_HUMIDITY_SENSOR.name(); - - if (transaction != null && transactionType != null) { - this.ledgerConnector.put( - new IndexTransaction(transactionType, transaction) - ); - } - - break; - case PULSE_OXYMETER: - logger.info("2"); // TODO: Remover - - transaction = - new ReputationService( - this.nodeType.getNodeId(), - this.nodeType.getNodeGroup(), - deviceSensorIdList, - TransactionType.REP_SVC_PULSE_OXYMETER - ); - - logger.info( - ((ReputationService) transaction).getServices() - .get(0) - .getSensorId() - ); // TODO: Remover - - transactionType = TransactionType.REP_SVC_PULSE_OXYMETER.name(); - - if (transaction != null && transactionType != null) { - this.ledgerConnector.put( - new IndexTransaction(transactionType, transaction) - ); - } - - break; - case THERMOMETER: - logger.info("3"); // TODO: Remover - - transaction = - new ReputationService( - this.nodeType.getNodeId(), - this.nodeType.getNodeGroup(), - deviceSensorIdList, - TransactionType.REP_SVC_THERMOMETER - ); - - logger.info( - ((ReputationService) transaction).getServices() - .get(0) - .getSensorId() - ); // TODO: Remover - - transactionType = TransactionType.REP_SVC_THERMOMETER.name(); - - if (transaction != null && transactionType != null) { - this.ledgerConnector.put( - new IndexTransaction(transactionType, transaction) - ); - } - - break; - case WIND_DIRECTION_SENSOR: - logger.info("4"); // TODO: Remover - - transaction = - new ReputationService( - this.nodeType.getNodeId(), - this.nodeType.getNodeGroup(), - deviceSensorIdList, - TransactionType.REP_SVC_WIND_DIRECTION_SENSOR - ); - - logger.info( - ((ReputationService) transaction).getServices() - .get(0) - .getSensorId() - ); // TODO: Remover - - transactionType = - TransactionType.REP_SVC_WIND_DIRECTION_SENSOR.name(); - - if (transaction != null && transactionType != null) { - this.ledgerConnector.put( - new IndexTransaction(transactionType, transaction) - ); - } - - break; - default: - logger.severe("Unknown service type."); - break; - } + deviceSensorIdList.forEach(d -> logger.info(d.getSensorId())); - // if (transaction != null && transactionType != null) { - // this.ledgerConnector.put( - // new IndexTransaction(transactionType, transaction) - // ); - // } + switch (serviceType) { + case HUMIDITY_SENSOR: + transaction = + new ReputationService( + this.nodeType.getNodeId(), + this.nodeType.getNodeGroup(), + deviceSensorIdList, + TransactionType.REP_SVC_HUMIDITY_SENSOR + ); - logger.info("-----"); // TODO: Remover + transactionType = TransactionType.REP_SVC_HUMIDITY_SENSOR.name(); + + break; + case PULSE_OXYMETER: + transaction = + new ReputationService( + this.nodeType.getNodeId(), + this.nodeType.getNodeGroup(), + deviceSensorIdList, + TransactionType.REP_SVC_PULSE_OXYMETER + ); + + transactionType = TransactionType.REP_SVC_PULSE_OXYMETER.name(); + + break; + case THERMOMETER: + transaction = + new ReputationService( + this.nodeType.getNodeId(), + this.nodeType.getNodeGroup(), + deviceSensorIdList, + TransactionType.REP_SVC_THERMOMETER + ); + + transactionType = TransactionType.REP_SVC_THERMOMETER.name(); + + break; + case WIND_DIRECTION_SENSOR: + transaction = + new ReputationService( + this.nodeType.getNodeId(), + this.nodeType.getNodeGroup(), + deviceSensorIdList, + TransactionType.REP_SVC_WIND_DIRECTION_SENSOR + ); + + transactionType = + TransactionType.REP_SVC_WIND_DIRECTION_SENSOR.name(); + + break; + default: + logger.severe("Unknown service type."); + break; + } + + /* + * Enviando a transação para a blockchain. + */ + if (transaction != null && transactionType != null) { + this.ledgerConnector.put( + new IndexTransaction(transactionType, transaction) + ); } - } finally { - this.mutex.unlock(); } } } @@ -361,14 +303,6 @@ public void setRequestDataTaskTime(int requestDataTaskTime) { this.requestDataTaskTime = requestDataTaskTime; } - public int getRequestServiceTaskTime() { - return requestServiceTaskTime; - } - - public void setRequestServiceTaskTime(int requestServiceTaskTime) { - this.requestServiceTaskTime = requestServiceTaskTime; - } - public int getAmountDevices() { return amountDevices; } @@ -397,14 +331,6 @@ public void setLedgerConnector(LedgerConnector ledgerConnector) { this.ledgerConnector = ledgerConnector; } - public int getWaitNodeResponseTaskTime() { - return waitNodeResponseTaskTime; - } - - public void setWaitNodeResponseTaskTime(int waitNodeResponseTaskTime) { - this.waitNodeResponseTaskTime = waitNodeResponseTaskTime; - } - public boolean isRequestingService() { return requestingService; } @@ -420,4 +346,12 @@ public TimerTask getWaitNodeResponseTask() { public void setWaitNodeResponseTask(TimerTask waitNodeResponseTask) { this.waitNodeResponseTask = waitNodeResponseTask; } + + public int getPublishNodeServicesTaskTime() { + return publishNodeServicesTaskTime; + } + + public void setPublishNodeServicesTaskTime(int publishNodeServicesTaskTime) { + this.publishNodeServicesTaskTime = publishNodeServicesTaskTime; + } } From 93eabd2864c37d2d20cc0837bd6242c6d4a08298 Mon Sep 17 00:00:00 2001 From: AllanCapistrano Date: Fri, 27 Oct 2023 10:17:17 -0300 Subject: [PATCH 07/52] feat: using nodeIp --- src/main/java/reputation/node/models/Node.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/java/reputation/node/models/Node.java b/src/main/java/reputation/node/models/Node.java index 925cd8c..b4bdf66 100644 --- a/src/main/java/reputation/node/models/Node.java +++ b/src/main/java/reputation/node/models/Node.java @@ -177,14 +177,13 @@ public void publishNodeServices() throws InterruptedException { this.mutex.unlock(); } - deviceSensorIdList.forEach(d -> logger.info(d.getSensorId())); - switch (serviceType) { case HUMIDITY_SENSOR: transaction = new ReputationService( this.nodeType.getNodeId(), this.nodeType.getNodeGroup(), + this.nodeType.getNodeIp(), deviceSensorIdList, TransactionType.REP_SVC_HUMIDITY_SENSOR ); @@ -197,6 +196,7 @@ public void publishNodeServices() throws InterruptedException { new ReputationService( this.nodeType.getNodeId(), this.nodeType.getNodeGroup(), + this.nodeType.getNodeIp(), deviceSensorIdList, TransactionType.REP_SVC_PULSE_OXYMETER ); @@ -209,6 +209,7 @@ public void publishNodeServices() throws InterruptedException { new ReputationService( this.nodeType.getNodeId(), this.nodeType.getNodeGroup(), + this.nodeType.getNodeIp(), deviceSensorIdList, TransactionType.REP_SVC_THERMOMETER ); @@ -221,6 +222,7 @@ public void publishNodeServices() throws InterruptedException { new ReputationService( this.nodeType.getNodeId(), this.nodeType.getNodeGroup(), + this.nodeType.getNodeIp(), deviceSensorIdList, TransactionType.REP_SVC_WIND_DIRECTION_SENSOR ); From fb5b727439b96dae5622cc45d3536d61b0e95096 Mon Sep 17 00:00:00 2001 From: AllanCapistrano Date: Tue, 31 Oct 2023 10:19:13 -0300 Subject: [PATCH 08/52] feat: create getNodesServices --- .../java/reputation/node/models/Node.java | 96 ++++++++++++++++++- 1 file changed, 95 insertions(+), 1 deletion(-) diff --git a/src/main/java/reputation/node/models/Node.java b/src/main/java/reputation/node/models/Node.java index b4bdf66..1ba6a9e 100644 --- a/src/main/java/reputation/node/models/Node.java +++ b/src/main/java/reputation/node/models/Node.java @@ -16,6 +16,7 @@ import java.util.TimerTask; import java.util.concurrent.locks.ReentrantLock; import java.util.logging.Logger; +import java.util.stream.Collectors; import node.type.services.INodeType; import reputation.node.enums.NodeServiceType; import reputation.node.mqtt.ListenerDevices; @@ -41,6 +42,7 @@ public class Node implements NodeTypeService { private int waitDeviceResponseTaskTime; private int publishNodeServicesTaskTime; private List devices; + private List nodesWithServices; private LedgerConnector ledgerConnector; private int amountDevices = 0; private IDevicePropertiesManager deviceManager; @@ -48,6 +50,7 @@ public class Node implements NodeTypeService { private TimerTask waitDeviceResponseTask; private TimerTask waitNodeResponseTask; // TODO: Verificar se ainda vai precisar private ReentrantLock mutex = new ReentrantLock(); + private ReentrantLock mutexNodesServices = new ReentrantLock(); private boolean requestingService; // TODO: Verificar se ainda vai precisar private static final Logger logger = Logger.getLogger(Node.class.getName()); @@ -60,6 +63,7 @@ public void start() { this.MQTTClient.connect(); this.devices = new ArrayList<>(); + this.nodesWithServices = new ArrayList<>(); this.listenerDevices = new ListenerDevices(this.MQTTClient, this); new Timer() .scheduleAtFixedRate( @@ -151,7 +155,7 @@ public void requestDataFromRandomDevice() { /** * Publica na blockchain quais são os serviços providos pelo nó. - * + * * @throws InterruptedException */ public void publishNodeServices() throws InterruptedException { @@ -248,6 +252,88 @@ public void publishNodeServices() throws InterruptedException { } } + /** + * Obtém uma lista com as transações a respeito de um serviço que os demais + * nós prestam. + * + * @param serviceType NodeServiceType - Tipo do serviço. + */ + public void getNodesServices(NodeServiceType serviceType) { + try { + this.mutexNodesServices.lock(); + + this.nodesWithServices.clear(); + + String index = ""; + + switch (serviceType) { + case HUMIDITY_SENSOR: + index = TransactionType.REP_SVC_HUMIDITY_SENSOR.name(); + break; + case PULSE_OXYMETER: + index = TransactionType.REP_SVC_PULSE_OXYMETER.name(); + break; + case THERMOMETER: + index = TransactionType.REP_SVC_THERMOMETER.name(); + break; + case WIND_DIRECTION_SENSOR: + index = TransactionType.REP_SVC_WIND_DIRECTION_SENSOR.name(); + break; + default: + logger.severe("Unknown service type."); + break; + } + + if (!index.equals("")) { + List transactions = + this.ledgerConnector.getLedgerReader().getTransactionsByIndex(index); + + /* + * Ordenação em ordem decrescente com relação a data/hora de criação da + * transação. + */ + transactions.sort((t1, t2) -> + Long.compare(t2.getCreatedAt(), t1.getCreatedAt()) + ); + + /** + * Tempo limite de 1 hora. + */ + long timeLimit = System.currentTimeMillis() - 60 * 60 * 1000; + + /** + * Removendo serviços duplicados de um mesmo nó, e as transações criadas + * a mais de 1 hora atrás. + */ + this.nodesWithServices = + transactions + .stream() + .collect( + Collectors.toMap( + Transaction::getSource, + obj -> obj, + (existing, replacement) -> existing + ) + ) + .values() + .stream() + .filter(obj -> obj.getCreatedAt() >= timeLimit) + .collect(Collectors.toList()); + } + } finally { + this.mutexNodesServices.unlock(); + } + + logger.info("-----------------"); // TODO: remover + + for (Transaction transaction : this.nodesWithServices) { // TODO: remover + logger.info(((ReputationService) transaction).getSource()); + logger.info( + Long.toString(((ReputationService) transaction).getCreatedAt()) + ); + } + } + /** * Se inscreve nos tópicos dos novos dispositivos. * @@ -356,4 +442,12 @@ public int getPublishNodeServicesTaskTime() { public void setPublishNodeServicesTaskTime(int publishNodeServicesTaskTime) { this.publishNodeServicesTaskTime = publishNodeServicesTaskTime; } + + public List getNodesWithServices() { + return nodesWithServices; + } + + public void setNodesWithServices(List nodesWithServices) { + this.nodesWithServices = nodesWithServices; + } } From 78c5c797568d9d0431267e393086a77cf5efc5a0 Mon Sep 17 00:00:00 2001 From: AllanCapistrano Date: Tue, 31 Oct 2023 10:29:20 -0300 Subject: [PATCH 09/52] chore: removing unused things --- .../java/reputation/node/models/Node.java | 22 +----- .../node/tasks/WaitNodeResponseTask.java | 69 ------------------- 2 files changed, 1 insertion(+), 90 deletions(-) delete mode 100644 src/main/java/reputation/node/tasks/WaitNodeResponseTask.java diff --git a/src/main/java/reputation/node/models/Node.java b/src/main/java/reputation/node/models/Node.java index 1ba6a9e..8cb6ed2 100644 --- a/src/main/java/reputation/node/models/Node.java +++ b/src/main/java/reputation/node/models/Node.java @@ -31,7 +31,7 @@ /** * * @author Allan Capistrano - * @version 1.2.0 + * @version 1.2.0 // TODO: Alterar quando finalizar o fluxo. */ public class Node implements NodeTypeService { @@ -48,10 +48,8 @@ public class Node implements NodeTypeService { private IDevicePropertiesManager deviceManager; private ListenerDevices listenerDevices; private TimerTask waitDeviceResponseTask; - private TimerTask waitNodeResponseTask; // TODO: Verificar se ainda vai precisar private ReentrantLock mutex = new ReentrantLock(); private ReentrantLock mutexNodesServices = new ReentrantLock(); - private boolean requestingService; // TODO: Verificar se ainda vai precisar private static final Logger logger = Logger.getLogger(Node.class.getName()); public Node() {} @@ -83,8 +81,6 @@ public void start() { 0, this.publishNodeServicesTaskTime * 1000 ); - - this.requestingService = false; } /** @@ -419,22 +415,6 @@ public void setLedgerConnector(LedgerConnector ledgerConnector) { this.ledgerConnector = ledgerConnector; } - public boolean isRequestingService() { - return requestingService; - } - - public void setRequestingService(boolean requestingService) { - this.requestingService = requestingService; - } - - public TimerTask getWaitNodeResponseTask() { - return waitNodeResponseTask; - } - - public void setWaitNodeResponseTask(TimerTask waitNodeResponseTask) { - this.waitNodeResponseTask = waitNodeResponseTask; - } - public int getPublishNodeServicesTaskTime() { return publishNodeServicesTaskTime; } diff --git a/src/main/java/reputation/node/tasks/WaitNodeResponseTask.java b/src/main/java/reputation/node/tasks/WaitNodeResponseTask.java deleted file mode 100644 index c07c964..0000000 --- a/src/main/java/reputation/node/tasks/WaitNodeResponseTask.java +++ /dev/null @@ -1,69 +0,0 @@ -package reputation.node.tasks; - -import java.util.TimerTask; -import java.util.logging.Logger; -import reputation.node.models.Node; - -/** - * Classe responsável por verificar se houve resposta de um nó à requisição de - * serviço feita pelo nó. - * - * @author Allan Capistrano - * @version 1.0.0 - */ -public class WaitNodeResponseTask extends TimerTask { - - private int timer, timeoutWaitNodeResponse; - private final String nodeServiceProviderId; - private final Node node; - private static final Logger logger = Logger.getLogger( - WaitNodeResponseTask.class.getName() - ); - - /** - * Método construtor. - * - * @param nodeServiceProviderId String - ID do nó que enviará a resposta - * @param timeoutWaitNodeResponse int - Tempo máximo para aguardar a - * resposta do nó. - * @param node Node - Nó o qual está esperando a resposta. - */ - public WaitNodeResponseTask( - String nodeServiceProviderId, - int timeoutWaitNodeResponse, - Node node - ) { - this.timeoutWaitNodeResponse = timeoutWaitNodeResponse; - this.nodeServiceProviderId = nodeServiceProviderId; - this.node = node; - } - - @Override - public void run() { - logger.info( - String.format( - "Waiting for %s response: %d...", - this.nodeServiceProviderId, - ++timer - ) - ); - - if ((timer * 1000) >= this.timeoutWaitNodeResponse) { - logger.warning( - "Timeout for waiting for " + this.nodeServiceProviderId + " response." - ); - - this.node.setRequestingService(false); - - // Avaliação de serviço prestado incorretamente. - try { - this.node.getNodeType() - .getNode() - .evaluateServiceProvider(this.nodeServiceProviderId, 0); - } catch (InterruptedException e) { - logger.warning("Could not add transaction on tangle network."); - } - this.cancel(); - } - } -} From 5e3ddfc770755c8ce530f5c2d34fffb440f1c3a4 Mon Sep 17 00:00:00 2001 From: AllanCapistrano Date: Tue, 31 Oct 2023 10:44:14 -0300 Subject: [PATCH 10/52] feat: create CheckNodesServicesTask --- .../node/tasks/CheckNodesServicesTask.java | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 src/main/java/reputation/node/tasks/CheckNodesServicesTask.java diff --git a/src/main/java/reputation/node/tasks/CheckNodesServicesTask.java b/src/main/java/reputation/node/tasks/CheckNodesServicesTask.java new file mode 100644 index 0000000..1dc6796 --- /dev/null +++ b/src/main/java/reputation/node/tasks/CheckNodesServicesTask.java @@ -0,0 +1,47 @@ +package reputation.node.tasks; + +import java.util.Random; +import java.util.TimerTask; +import java.util.logging.Logger; +import reputation.node.enums.NodeServiceType; +import reputation.node.models.Node; + +/** + * Classe responsável pela tarefa de obter os nós que prestam um determinado + * serviço + * + * @author Allan Capistrano + * @version 1.0.0 + */ +public class CheckNodesServicesTask extends TimerTask { + + private final Node node; + private static final Logger logger = Logger.getLogger( + CheckDevicesTask.class.getName() + ); + + /** + * Método construtor. + * + * @param node NodeType - Nó que verificará os serviços dos outros nós. + */ + public CheckNodesServicesTask(Node node) { + this.node = node; + } + + @Override + public void run() { + /** + * Serviço sendo escolhido de maneira aleatório. + */ + int randomIndex = new Random().nextInt(NodeServiceType.values().length); + + NodeServiceType nodeServiceType = NodeServiceType.values()[randomIndex]; + + logger.info( + "Checking nodes with " + nodeServiceType.getDescription() + " service." + ); + + this.node.getNodesServices(nodeServiceType); + } +} From 6b4f9aedb7c5d3d13db1595d3d727093ee29521c Mon Sep 17 00:00:00 2001 From: AllanCapistrano Date: Tue, 31 Oct 2023 10:44:39 -0300 Subject: [PATCH 11/52] feat: add checkNodesServicesTaskTime property --- src/main/resources/OSGI-INF/blueprint/blueprint.xml | 6 ++++-- .../resources/br.uefs.larsid.soft_iot.reputation_node.cfg | 5 ++++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/main/resources/OSGI-INF/blueprint/blueprint.xml b/src/main/resources/OSGI-INF/blueprint/blueprint.xml index e86a581..174a733 100644 --- a/src/main/resources/OSGI-INF/blueprint/blueprint.xml +++ b/src/main/resources/OSGI-INF/blueprint/blueprint.xml @@ -27,8 +27,9 @@ - + + @@ -48,8 +49,9 @@ - + + diff --git a/src/main/resources/br.uefs.larsid.soft_iot.reputation_node.cfg b/src/main/resources/br.uefs.larsid.soft_iot.reputation_node.cfg index 496c560..7769285 100644 --- a/src/main/resources/br.uefs.larsid.soft_iot.reputation_node.cfg +++ b/src/main/resources/br.uefs.larsid.soft_iot.reputation_node.cfg @@ -12,6 +12,9 @@ requestDataTaskTime=30 # Obs: Tem que ser menor do que o 'requestDataTaskTime'. waitDeviceResponseTaskTime=10 # Tempo (segundos) para o nó enviar quais são os serviços que o mesmo provê. -publishNodeServicesTaskTime=30 +publishNodeServicesTaskTime=30 +# Tempo (segundos) para o nó verificar quais são os serviços prestados pelos +# outros nós +checkNodesServicesTaskTime=60 debugModeValue=true \ No newline at end of file From d0140827eb203505d73df4f2467c74cd0fc873e5 Mon Sep 17 00:00:00 2001 From: AllanCapistrano Date: Tue, 31 Oct 2023 10:44:57 -0300 Subject: [PATCH 12/52] chore: using CheckNodesServicesTask --- src/main/java/reputation/node/models/Node.java | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/main/java/reputation/node/models/Node.java b/src/main/java/reputation/node/models/Node.java index 8cb6ed2..d187ff1 100644 --- a/src/main/java/reputation/node/models/Node.java +++ b/src/main/java/reputation/node/models/Node.java @@ -23,6 +23,7 @@ import reputation.node.services.NodeTypeService; import reputation.node.tangle.LedgerConnector; import reputation.node.tasks.CheckDevicesTask; +import reputation.node.tasks.CheckNodesServicesTask; import reputation.node.tasks.PublishNodeServicesTask; import reputation.node.tasks.RequestDataTask; import reputation.node.tasks.WaitDeviceResponseTask; @@ -41,6 +42,7 @@ public class Node implements NodeTypeService { private int requestDataTaskTime; private int waitDeviceResponseTaskTime; private int publishNodeServicesTaskTime; + private int checkNodesServicesTaskTime; private List devices; private List nodesWithServices; private LedgerConnector ledgerConnector; @@ -81,6 +83,12 @@ public void start() { 0, this.publishNodeServicesTaskTime * 1000 ); + new Timer() + .scheduleAtFixedRate( + new CheckNodesServicesTask(this), + 0, + this.checkNodesServicesTaskTime * 1000 + ); } /** @@ -295,7 +303,7 @@ public void getNodesServices(NodeServiceType serviceType) { /** * Tempo limite de 1 hora. */ - long timeLimit = System.currentTimeMillis() - 60 * 60 * 1000; + long timeLimit = System.currentTimeMillis() - 1 * 60 * 60 * 1000; /** * Removendo serviços duplicados de um mesmo nó, e as transações criadas @@ -430,4 +438,12 @@ public List getNodesWithServices() { public void setNodesWithServices(List nodesWithServices) { this.nodesWithServices = nodesWithServices; } + + public int getCheckNodesServicesTaskTime() { + return checkNodesServicesTaskTime; + } + + public void setCheckNodesServicesTaskTime(int checkNodesServicesTaskTime) { + this.checkNodesServicesTaskTime = checkNodesServicesTaskTime; + } } From 64d3ce9bd72ab25411722379aac8f29f91fca6e7 Mon Sep 17 00:00:00 2001 From: AllanCapistrano Date: Tue, 31 Oct 2023 11:03:38 -0300 Subject: [PATCH 13/52] feat: add TODO --- src/main/java/reputation/node/models/Node.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/reputation/node/models/Node.java b/src/main/java/reputation/node/models/Node.java index d187ff1..8b562f1 100644 --- a/src/main/java/reputation/node/models/Node.java +++ b/src/main/java/reputation/node/models/Node.java @@ -321,7 +321,7 @@ public void getNodesServices(NodeServiceType serviceType) { ) .values() .stream() - .filter(obj -> obj.getCreatedAt() >= timeLimit) + .filter(obj -> obj.getCreatedAt() >= timeLimit) // TODO: Adicionar filtro para não pegar a transação que o próprio nó enviou .collect(Collectors.toList()); } } finally { From b1e446fd10947b33ab1707e02999f81462f49865 Mon Sep 17 00:00:00 2001 From: AllanCapistrano Date: Thu, 9 Nov 2023 14:42:26 -0300 Subject: [PATCH 14/52] chore: removing unused classes, variables and methods --- .../java/reputation/node/models/Node.java | 36 +------------- .../node/tasks/CheckNodesServicesTask.java | 47 ------------------- .../node/tasks/PublishNodeServicesTask.java | 38 --------------- .../OSGI-INF/blueprint/blueprint.xml | 4 -- ...r.uefs.larsid.soft_iot.reputation_node.cfg | 5 -- 5 files changed, 2 insertions(+), 128 deletions(-) delete mode 100644 src/main/java/reputation/node/tasks/CheckNodesServicesTask.java delete mode 100644 src/main/java/reputation/node/tasks/PublishNodeServicesTask.java diff --git a/src/main/java/reputation/node/models/Node.java b/src/main/java/reputation/node/models/Node.java index 8b562f1..ead6fa6 100644 --- a/src/main/java/reputation/node/models/Node.java +++ b/src/main/java/reputation/node/models/Node.java @@ -23,8 +23,6 @@ import reputation.node.services.NodeTypeService; import reputation.node.tangle.LedgerConnector; import reputation.node.tasks.CheckDevicesTask; -import reputation.node.tasks.CheckNodesServicesTask; -import reputation.node.tasks.PublishNodeServicesTask; import reputation.node.tasks.RequestDataTask; import reputation.node.tasks.WaitDeviceResponseTask; import reputation.node.utils.MQTTClient; @@ -41,8 +39,6 @@ public class Node implements NodeTypeService { private int checkDeviceTaskTime; private int requestDataTaskTime; private int waitDeviceResponseTaskTime; - private int publishNodeServicesTaskTime; - private int checkNodesServicesTaskTime; private List devices; private List nodesWithServices; private LedgerConnector ledgerConnector; @@ -77,18 +73,6 @@ public void start() { 0, this.requestDataTaskTime * 1000 ); - new Timer() - .scheduleAtFixedRate( - new PublishNodeServicesTask(this), - 0, - this.publishNodeServicesTaskTime * 1000 - ); - new Timer() - .scheduleAtFixedRate( - new CheckNodesServicesTask(this), - 0, - this.checkNodesServicesTaskTime * 1000 - ); } /** @@ -162,7 +146,7 @@ public void requestDataFromRandomDevice() { * * @throws InterruptedException */ - public void publishNodeServices() throws InterruptedException { + public void publishNodeServices() throws InterruptedException { // TODO: Verificar se vai usar if (this.amountDevices > 0) { Transaction transaction = null; String transactionType = null; @@ -262,7 +246,7 @@ public void publishNodeServices() throws InterruptedException { * * @param serviceType NodeServiceType - Tipo do serviço. */ - public void getNodesServices(NodeServiceType serviceType) { + public void getNodesServices(NodeServiceType serviceType) { // TODO: Verificar se vai usar try { this.mutexNodesServices.lock(); @@ -423,14 +407,6 @@ public void setLedgerConnector(LedgerConnector ledgerConnector) { this.ledgerConnector = ledgerConnector; } - public int getPublishNodeServicesTaskTime() { - return publishNodeServicesTaskTime; - } - - public void setPublishNodeServicesTaskTime(int publishNodeServicesTaskTime) { - this.publishNodeServicesTaskTime = publishNodeServicesTaskTime; - } - public List getNodesWithServices() { return nodesWithServices; } @@ -438,12 +414,4 @@ public List getNodesWithServices() { public void setNodesWithServices(List nodesWithServices) { this.nodesWithServices = nodesWithServices; } - - public int getCheckNodesServicesTaskTime() { - return checkNodesServicesTaskTime; - } - - public void setCheckNodesServicesTaskTime(int checkNodesServicesTaskTime) { - this.checkNodesServicesTaskTime = checkNodesServicesTaskTime; - } } diff --git a/src/main/java/reputation/node/tasks/CheckNodesServicesTask.java b/src/main/java/reputation/node/tasks/CheckNodesServicesTask.java deleted file mode 100644 index 1dc6796..0000000 --- a/src/main/java/reputation/node/tasks/CheckNodesServicesTask.java +++ /dev/null @@ -1,47 +0,0 @@ -package reputation.node.tasks; - -import java.util.Random; -import java.util.TimerTask; -import java.util.logging.Logger; -import reputation.node.enums.NodeServiceType; -import reputation.node.models.Node; - -/** - * Classe responsável pela tarefa de obter os nós que prestam um determinado - * serviço - * - * @author Allan Capistrano - * @version 1.0.0 - */ -public class CheckNodesServicesTask extends TimerTask { - - private final Node node; - private static final Logger logger = Logger.getLogger( - CheckDevicesTask.class.getName() - ); - - /** - * Método construtor. - * - * @param node NodeType - Nó que verificará os serviços dos outros nós. - */ - public CheckNodesServicesTask(Node node) { - this.node = node; - } - - @Override - public void run() { - /** - * Serviço sendo escolhido de maneira aleatório. - */ - int randomIndex = new Random().nextInt(NodeServiceType.values().length); - - NodeServiceType nodeServiceType = NodeServiceType.values()[randomIndex]; - - logger.info( - "Checking nodes with " + nodeServiceType.getDescription() + " service." - ); - - this.node.getNodesServices(nodeServiceType); - } -} diff --git a/src/main/java/reputation/node/tasks/PublishNodeServicesTask.java b/src/main/java/reputation/node/tasks/PublishNodeServicesTask.java deleted file mode 100644 index 7fae79b..0000000 --- a/src/main/java/reputation/node/tasks/PublishNodeServicesTask.java +++ /dev/null @@ -1,38 +0,0 @@ -package reputation.node.tasks; - -import java.util.TimerTask; -import java.util.logging.Logger; -import reputation.node.models.Node; - -/** - * Classe responsável pela tarefa de publicar quais são os serviços providos - * pelo nó. - * - * @author Allan Capistrano - * @version 1.0.0 - */ -public class PublishNodeServicesTask extends TimerTask { - - private final Node node; - private static final Logger logger = Logger.getLogger( - PublishNodeServicesTask.class.getName() - ); - - public PublishNodeServicesTask(Node node) { - this.node = node; - } - - @Override - public void run() { - if (this.node.getAmountDevices() > 0) { - logger.info("Publishing the node services..."); - - try { - this.node.publishNodeServices(); - } catch (InterruptedException ie) { - logger.warning("Could not sent the transaction."); - logger.warning(ie.getStackTrace().toString()); - } - } - } -} diff --git a/src/main/resources/OSGI-INF/blueprint/blueprint.xml b/src/main/resources/OSGI-INF/blueprint/blueprint.xml index 174a733..4cd7779 100644 --- a/src/main/resources/OSGI-INF/blueprint/blueprint.xml +++ b/src/main/resources/OSGI-INF/blueprint/blueprint.xml @@ -28,8 +28,6 @@ - - @@ -50,8 +48,6 @@ - - diff --git a/src/main/resources/br.uefs.larsid.soft_iot.reputation_node.cfg b/src/main/resources/br.uefs.larsid.soft_iot.reputation_node.cfg index 7769285..05ac18f 100644 --- a/src/main/resources/br.uefs.larsid.soft_iot.reputation_node.cfg +++ b/src/main/resources/br.uefs.larsid.soft_iot.reputation_node.cfg @@ -11,10 +11,5 @@ requestDataTaskTime=30 # Tempo máximo (segundos) de espera da resposta do dispositivo para a requisição feita pelo nó. # Obs: Tem que ser menor do que o 'requestDataTaskTime'. waitDeviceResponseTaskTime=10 -# Tempo (segundos) para o nó enviar quais são os serviços que o mesmo provê. -publishNodeServicesTaskTime=30 -# Tempo (segundos) para o nó verificar quais são os serviços prestados pelos -# outros nós -checkNodesServicesTaskTime=60 debugModeValue=true \ No newline at end of file From 68e2e675a3216d63e040473379abbd4aa09f6e34 Mon Sep 17 00:00:00 2001 From: AllanCapistrano Date: Thu, 9 Nov 2023 14:47:36 -0300 Subject: [PATCH 15/52] fix: ReputationService constructor --- src/main/java/reputation/node/models/Node.java | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/main/java/reputation/node/models/Node.java b/src/main/java/reputation/node/models/Node.java index ead6fa6..2f714fd 100644 --- a/src/main/java/reputation/node/models/Node.java +++ b/src/main/java/reputation/node/models/Node.java @@ -174,9 +174,10 @@ public void publishNodeServices() throws InterruptedException { // TODO: Verific transaction = new ReputationService( this.nodeType.getNodeId(), - this.nodeType.getNodeGroup(), this.nodeType.getNodeIp(), + "Target", // TODO: Temporário deviceSensorIdList, + this.nodeType.getNodeGroup(), TransactionType.REP_SVC_HUMIDITY_SENSOR ); @@ -187,9 +188,10 @@ public void publishNodeServices() throws InterruptedException { // TODO: Verific transaction = new ReputationService( this.nodeType.getNodeId(), - this.nodeType.getNodeGroup(), this.nodeType.getNodeIp(), + "Target", deviceSensorIdList, + this.nodeType.getNodeGroup(), TransactionType.REP_SVC_PULSE_OXYMETER ); @@ -200,9 +202,10 @@ public void publishNodeServices() throws InterruptedException { // TODO: Verific transaction = new ReputationService( this.nodeType.getNodeId(), - this.nodeType.getNodeGroup(), this.nodeType.getNodeIp(), + "Target", // TODO: Temporário deviceSensorIdList, + this.nodeType.getNodeGroup(), TransactionType.REP_SVC_THERMOMETER ); @@ -213,9 +216,10 @@ public void publishNodeServices() throws InterruptedException { // TODO: Verific transaction = new ReputationService( this.nodeType.getNodeId(), - this.nodeType.getNodeGroup(), this.nodeType.getNodeIp(), + "Target", // TODO: Temporário deviceSensorIdList, + this.nodeType.getNodeGroup(), TransactionType.REP_SVC_WIND_DIRECTION_SENSOR ); From 79a17d7df435a51f02365000d1016dac5e209dc5 Mon Sep 17 00:00:00 2001 From: AllanCapistrano Date: Thu, 9 Nov 2023 15:05:19 -0300 Subject: [PATCH 16/52] feat: create checkNodesServicesTaskTime --- src/main/java/reputation/node/models/Node.java | 9 +++++++++ src/main/resources/OSGI-INF/blueprint/blueprint.xml | 2 ++ .../br.uefs.larsid.soft_iot.reputation_node.cfg | 2 ++ 3 files changed, 13 insertions(+) diff --git a/src/main/java/reputation/node/models/Node.java b/src/main/java/reputation/node/models/Node.java index 2f714fd..b08f5b7 100644 --- a/src/main/java/reputation/node/models/Node.java +++ b/src/main/java/reputation/node/models/Node.java @@ -39,6 +39,7 @@ public class Node implements NodeTypeService { private int checkDeviceTaskTime; private int requestDataTaskTime; private int waitDeviceResponseTaskTime; + private int checkNodesServicesTaskTime; private List devices; private List nodesWithServices; private LedgerConnector ledgerConnector; @@ -418,4 +419,12 @@ public List getNodesWithServices() { public void setNodesWithServices(List nodesWithServices) { this.nodesWithServices = nodesWithServices; } + + public int getCheckNodesServicesTaskTime() { + return checkNodesServicesTaskTime; + } + + public void setCheckNodesServicesTaskTime(int checkNodesServicesTaskTime) { + this.checkNodesServicesTaskTime = checkNodesServicesTaskTime; + } } diff --git a/src/main/resources/OSGI-INF/blueprint/blueprint.xml b/src/main/resources/OSGI-INF/blueprint/blueprint.xml index 4cd7779..54cfdb3 100644 --- a/src/main/resources/OSGI-INF/blueprint/blueprint.xml +++ b/src/main/resources/OSGI-INF/blueprint/blueprint.xml @@ -28,6 +28,7 @@ + @@ -48,6 +49,7 @@ + diff --git a/src/main/resources/br.uefs.larsid.soft_iot.reputation_node.cfg b/src/main/resources/br.uefs.larsid.soft_iot.reputation_node.cfg index 05ac18f..f60f4c2 100644 --- a/src/main/resources/br.uefs.larsid.soft_iot.reputation_node.cfg +++ b/src/main/resources/br.uefs.larsid.soft_iot.reputation_node.cfg @@ -11,5 +11,7 @@ requestDataTaskTime=30 # Tempo máximo (segundos) de espera da resposta do dispositivo para a requisição feita pelo nó. # Obs: Tem que ser menor do que o 'requestDataTaskTime'. waitDeviceResponseTaskTime=10 +# Tempo (segundos) para vericar quais nós tem um determinado serviço. +checkNodesServicesTaskTime=45 debugModeValue=true \ No newline at end of file From 473e686f82d66f029bca84d36d249e16fe3f2f6c Mon Sep 17 00:00:00 2001 From: AllanCapistrano Date: Thu, 9 Nov 2023 15:05:39 -0300 Subject: [PATCH 17/52] feat: create CheckNodesServicesTask --- .../node/tasks/CheckNodesServicesTask.java | 69 +++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 src/main/java/reputation/node/tasks/CheckNodesServicesTask.java diff --git a/src/main/java/reputation/node/tasks/CheckNodesServicesTask.java b/src/main/java/reputation/node/tasks/CheckNodesServicesTask.java new file mode 100644 index 0000000..fdddbec --- /dev/null +++ b/src/main/java/reputation/node/tasks/CheckNodesServicesTask.java @@ -0,0 +1,69 @@ +package reputation.node.tasks; + +import dlt.client.tangle.hornet.enums.TransactionType; +import dlt.client.tangle.hornet.model.transactions.IndexTransaction; +import dlt.client.tangle.hornet.model.transactions.Transaction; +import dlt.client.tangle.hornet.model.transactions.reputation.HasReputationService; +import java.util.Random; +import java.util.TimerTask; +import java.util.logging.Logger; +import reputation.node.enums.NodeServiceType; +import reputation.node.models.Node; + +/** + * Classe responsável pela tarefa de obter os nós que prestam um determinado + * serviço + * + * @author Allan Capistrano + * @version 1.0.0 + */ +public class CheckNodesServicesTask extends TimerTask { + + private final Node node; + private static final Logger logger = Logger.getLogger( + CheckDevicesTask.class.getName() + ); + + /** + * Método construtor. + * + * @param node NodeType - Nó que verificará os serviços dos outros nós. + */ + public CheckNodesServicesTask(Node node) { + this.node = node; + } + + @Override + public void run() { + /** + * Serviço sendo escolhido de maneira aleatório. + */ + int randomIndex = new Random().nextInt(NodeServiceType.values().length); + + NodeServiceType nodeServiceType = NodeServiceType.values()[randomIndex]; + + logger.info( + "Checking nodes with " + nodeServiceType.getDescription() + " service." + ); + + Transaction transaction = new HasReputationService( + this.node.getNodeType().getNodeId(), + this.node.getNodeType().getNodeGroup(), + nodeServiceType.name(), + TransactionType.REP_HAS_SVC + ); + + String transactionTypeString = TransactionType.REP_HAS_SVC.name(); + + try { + this.node.getLedgerConnector() + .getLedgerWriter() + .put(new IndexTransaction(transactionTypeString, transaction)); + } catch (InterruptedException ie) { + logger.warning( + "Error trying to create a " + transactionTypeString + " transaction." + ); + logger.warning(ie.getStackTrace().toString()); + } + } +} From e8e1027f2e9d918f2d73eb287b07d110441a5a9e Mon Sep 17 00:00:00 2001 From: AllanCapistrano Date: Thu, 9 Nov 2023 16:24:02 -0300 Subject: [PATCH 18/52] feat: start to develop node service --- .../java/reputation/node/models/Node.java | 231 +++++++++++------- 1 file changed, 148 insertions(+), 83 deletions(-) diff --git a/src/main/java/reputation/node/models/Node.java b/src/main/java/reputation/node/models/Node.java index b08f5b7..1dbe592 100644 --- a/src/main/java/reputation/node/models/Node.java +++ b/src/main/java/reputation/node/models/Node.java @@ -7,7 +7,9 @@ import dlt.client.tangle.hornet.model.DeviceSensorId; import dlt.client.tangle.hornet.model.transactions.IndexTransaction; import dlt.client.tangle.hornet.model.transactions.Transaction; +import dlt.client.tangle.hornet.model.transactions.reputation.HasReputationService; import dlt.client.tangle.hornet.model.transactions.reputation.ReputationService; +import dlt.client.tangle.hornet.services.ILedgerSubscriber; import java.io.IOException; import java.util.ArrayList; import java.util.List; @@ -23,6 +25,7 @@ import reputation.node.services.NodeTypeService; import reputation.node.tangle.LedgerConnector; import reputation.node.tasks.CheckDevicesTask; +import reputation.node.tasks.CheckNodesServicesTask; import reputation.node.tasks.RequestDataTask; import reputation.node.tasks.WaitDeviceResponseTask; import reputation.node.utils.MQTTClient; @@ -32,7 +35,7 @@ * @author Allan Capistrano * @version 1.2.0 // TODO: Alterar quando finalizar o fluxo. */ -public class Node implements NodeTypeService { +public class Node implements NodeTypeService, ILedgerSubscriber { private MQTTClient MQTTClient; private INodeType nodeType; @@ -74,6 +77,14 @@ public void start() { 0, this.requestDataTaskTime * 1000 ); + new Timer() + .scheduleAtFixedRate( + new CheckNodesServicesTask(this), + 0, + this.checkNodesServicesTaskTime * 1000 + ); + + this.subscribeToTransactionsTopics(); } /** @@ -82,6 +93,8 @@ public void start() { public void stop() { this.devices.forEach(d -> this.listenerDevices.unsubscribe(d.getId())); + this.unsubscribeToTransactionsTopics(); + this.MQTTClient.disconnect(); } @@ -147,99 +160,107 @@ public void requestDataFromRandomDevice() { * * @throws InterruptedException */ - public void publishNodeServices() throws InterruptedException { // TODO: Verificar se vai usar + private void publishNodeServices(String serviceType, String target) { + logger.info("B"); + /* Só responde se tiver pelo menos um dispositivo conectado ao nó. */ if (this.amountDevices > 0) { + logger.info("SERVICE TYPE: " + serviceType); // TODO: Remover + Transaction transaction = null; String transactionType = null; - for (NodeServiceType serviceType : NodeServiceType.values()) { - List deviceSensorIdList = new ArrayList<>(); + List deviceSensorIdList = new ArrayList<>(); - try { - this.mutex.lock(); - for (Device d : this.devices) { - d - .getSensors() - .stream() - .filter(s -> s.getType().equals(serviceType.getDescription())) - .forEach(s -> - deviceSensorIdList.add(new DeviceSensorId(d.getId(), s.getId())) - ); - } - } finally { - this.mutex.unlock(); + try { + this.mutex.lock(); + for (Device d : this.devices) { + d + .getSensors() + .stream() + .filter(s -> s.getType().equals(serviceType)) + .forEach(s -> + deviceSensorIdList.add(new DeviceSensorId(d.getId(), s.getId())) + ); } + } finally { + this.mutex.unlock(); + } - switch (serviceType) { - case HUMIDITY_SENSOR: - transaction = - new ReputationService( - this.nodeType.getNodeId(), - this.nodeType.getNodeIp(), - "Target", // TODO: Temporário - deviceSensorIdList, - this.nodeType.getNodeGroup(), - TransactionType.REP_SVC_HUMIDITY_SENSOR - ); - - transactionType = TransactionType.REP_SVC_HUMIDITY_SENSOR.name(); - - break; - case PULSE_OXYMETER: - transaction = - new ReputationService( - this.nodeType.getNodeId(), - this.nodeType.getNodeIp(), - "Target", - deviceSensorIdList, - this.nodeType.getNodeGroup(), - TransactionType.REP_SVC_PULSE_OXYMETER - ); - - transactionType = TransactionType.REP_SVC_PULSE_OXYMETER.name(); - - break; - case THERMOMETER: - transaction = - new ReputationService( - this.nodeType.getNodeId(), - this.nodeType.getNodeIp(), - "Target", // TODO: Temporário - deviceSensorIdList, - this.nodeType.getNodeGroup(), - TransactionType.REP_SVC_THERMOMETER - ); - - transactionType = TransactionType.REP_SVC_THERMOMETER.name(); - - break; - case WIND_DIRECTION_SENSOR: - transaction = - new ReputationService( - this.nodeType.getNodeId(), - this.nodeType.getNodeIp(), - "Target", // TODO: Temporário - deviceSensorIdList, - this.nodeType.getNodeGroup(), - TransactionType.REP_SVC_WIND_DIRECTION_SENSOR - ); - - transactionType = - TransactionType.REP_SVC_WIND_DIRECTION_SENSOR.name(); - - break; - default: - logger.severe("Unknown service type."); - break; - } + if ( + serviceType.equals(NodeServiceType.HUMIDITY_SENSOR.getDescription()) + ) { + transaction = + new ReputationService( + this.nodeType.getNodeId(), + this.nodeType.getNodeIp(), + target, + deviceSensorIdList, + this.nodeType.getNodeGroup(), + TransactionType.REP_SVC_HUMIDITY_SENSOR + ); - /* - * Enviando a transação para a blockchain. - */ - if (transaction != null && transactionType != null) { + transactionType = TransactionType.REP_SVC_HUMIDITY_SENSOR.name(); + } else if ( + serviceType.equals(NodeServiceType.PULSE_OXYMETER.getDescription()) + ) { + transaction = + new ReputationService( + this.nodeType.getNodeId(), + this.nodeType.getNodeIp(), + target, + deviceSensorIdList, + this.nodeType.getNodeGroup(), + TransactionType.REP_SVC_PULSE_OXYMETER + ); + + transactionType = TransactionType.REP_SVC_PULSE_OXYMETER.name(); + } else if ( + serviceType.equals(NodeServiceType.THERMOMETER.getDescription()) + ) { + transaction = + new ReputationService( + this.nodeType.getNodeId(), + this.nodeType.getNodeIp(), + target, + deviceSensorIdList, + this.nodeType.getNodeGroup(), + TransactionType.REP_SVC_THERMOMETER + ); + + transactionType = TransactionType.REP_SVC_THERMOMETER.name(); + } else if ( + serviceType.equals( + NodeServiceType.WIND_DIRECTION_SENSOR.getDescription() + ) + ) { + transaction = + new ReputationService( + this.nodeType.getNodeId(), + this.nodeType.getNodeIp(), + target, + deviceSensorIdList, + this.nodeType.getNodeGroup(), + TransactionType.REP_SVC_WIND_DIRECTION_SENSOR + ); + + transactionType = TransactionType.REP_SVC_WIND_DIRECTION_SENSOR.name(); + } else { + logger.severe("Unknown service type."); + } + + /* + * Enviando a transação para a blockchain. + */ + if (transaction != null && transactionType != null) { + try { this.ledgerConnector.put( new IndexTransaction(transactionType, transaction) ); + } catch (InterruptedException ie) { + logger.warning( + "Error trying to create a " + transactionType + " transaction." + ); + logger.warning(ie.getStackTrace().toString()); } } } @@ -327,6 +348,20 @@ public void getNodesServices(NodeServiceType serviceType) { // TODO: Verificar s } } + /** + * Se inscreve nos tópicos ZMQ das transações . + */ + private void subscribeToTransactionsTopics() { + this.ledgerConnector.subscribe(TransactionType.REP_HAS_SVC.name(), this); + } + + /** + * Se desinscreve dos tópicos ZMQ das transações . + */ + private void unsubscribeToTransactionsTopics() { + this.ledgerConnector.unsubscribe(TransactionType.REP_HAS_SVC.name(), this); + } + /** * Se inscreve nos tópicos dos novos dispositivos. * @@ -344,6 +379,36 @@ private void subscribeToDevicesTopics(int amountNewDevices) { } } + @Override + public void update(Object object, Object object2) { + // String sourceReceivedTransaction = ((Transaction) object).getSource(); + + // if (!sourceReceivedTransaction.equals(this.getNodeType().getNodeId())) { + // logger.info("OLA"); + // } else { + // logger.info("REMOVER"); + // } + + logger.info("UEEEE"); + String sourceReceivedTransaction = ((Transaction) object).getSource(); + + // if (!sourceReceivedTransaction.equals(this.getNodeType().getNodeId())) {} + + // TODO: Colocar dentro do 'if' + Transaction receivedTransaction = (Transaction) object; + + logger.info("AAAAAA"); + logger.info(receivedTransaction.getType().name()); + + if (receivedTransaction.getType() == TransactionType.REP_HAS_SVC) { + logger.info("A"); + this.publishNodeServices( + ((HasReputationService) receivedTransaction).getService(), // TODO: Esse método não foi chamado e aconteceu somente uma vez + receivedTransaction.getSource() + ); + } + } + public MQTTClient getMQTTClient() { return MQTTClient; } From 83f3ace2a206c7b1e7c3519d92c0ebbd0e30a757 Mon Sep 17 00:00:00 2001 From: AllanCapistrano Date: Fri, 10 Nov 2023 16:34:09 -0300 Subject: [PATCH 19/52] fix: node service type --- src/main/java/reputation/node/tasks/CheckNodesServicesTask.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/reputation/node/tasks/CheckNodesServicesTask.java b/src/main/java/reputation/node/tasks/CheckNodesServicesTask.java index fdddbec..8deedf8 100644 --- a/src/main/java/reputation/node/tasks/CheckNodesServicesTask.java +++ b/src/main/java/reputation/node/tasks/CheckNodesServicesTask.java @@ -49,7 +49,7 @@ public void run() { Transaction transaction = new HasReputationService( this.node.getNodeType().getNodeId(), this.node.getNodeType().getNodeGroup(), - nodeServiceType.name(), + nodeServiceType.getDescription(), TransactionType.REP_HAS_SVC ); From 6a2c0990f55a2c2377a83309b5e686206709dc85 Mon Sep 17 00:00:00 2001 From: AllanCapistrano Date: Fri, 10 Nov 2023 16:34:39 -0300 Subject: [PATCH 20/52] fix: communication between nodes by tangle hornet --- .../java/reputation/node/models/Node.java | 79 +++++++++---------- 1 file changed, 39 insertions(+), 40 deletions(-) diff --git a/src/main/java/reputation/node/models/Node.java b/src/main/java/reputation/node/models/Node.java index 1dbe592..529a420 100644 --- a/src/main/java/reputation/node/models/Node.java +++ b/src/main/java/reputation/node/models/Node.java @@ -156,18 +156,18 @@ public void requestDataFromRandomDevice() { } /** - * Publica na blockchain quais são os serviços providos pelo nó. + * Publica na blockchain quais são os serviços prestados pelo nó. * * @throws InterruptedException */ private void publishNodeServices(String serviceType, String target) { - logger.info("B"); /* Só responde se tiver pelo menos um dispositivo conectado ao nó. */ if (this.amountDevices > 0) { - logger.info("SERVICE TYPE: " + serviceType); // TODO: Remover + logger.info("Requested service type: " + serviceType); Transaction transaction = null; - String transactionType = null; + TransactionType transactionType; + String transactionTypeInString = null; List deviceSensorIdList = new ArrayList<>(); @@ -189,6 +189,8 @@ private void publishNodeServices(String serviceType, String target) { if ( serviceType.equals(NodeServiceType.HUMIDITY_SENSOR.getDescription()) ) { + transactionType = TransactionType.REP_SVC_HUMIDITY_SENSOR; + transaction = new ReputationService( this.nodeType.getNodeId(), @@ -196,13 +198,15 @@ private void publishNodeServices(String serviceType, String target) { target, deviceSensorIdList, this.nodeType.getNodeGroup(), - TransactionType.REP_SVC_HUMIDITY_SENSOR + transactionType ); - transactionType = TransactionType.REP_SVC_HUMIDITY_SENSOR.name(); + transactionTypeInString = transactionType.name(); } else if ( serviceType.equals(NodeServiceType.PULSE_OXYMETER.getDescription()) ) { + transactionType = TransactionType.REP_SVC_PULSE_OXYMETER; + transaction = new ReputationService( this.nodeType.getNodeId(), @@ -210,13 +214,15 @@ private void publishNodeServices(String serviceType, String target) { target, deviceSensorIdList, this.nodeType.getNodeGroup(), - TransactionType.REP_SVC_PULSE_OXYMETER + transactionType ); - transactionType = TransactionType.REP_SVC_PULSE_OXYMETER.name(); + transactionTypeInString = transactionType.name(); } else if ( serviceType.equals(NodeServiceType.THERMOMETER.getDescription()) ) { + transactionType = TransactionType.REP_SVC_THERMOMETER; + transaction = new ReputationService( this.nodeType.getNodeId(), @@ -224,15 +230,17 @@ private void publishNodeServices(String serviceType, String target) { target, deviceSensorIdList, this.nodeType.getNodeGroup(), - TransactionType.REP_SVC_THERMOMETER + transactionType ); - transactionType = TransactionType.REP_SVC_THERMOMETER.name(); + transactionTypeInString = transactionType.name(); } else if ( serviceType.equals( NodeServiceType.WIND_DIRECTION_SENSOR.getDescription() ) ) { + transactionType = TransactionType.REP_SVC_WIND_DIRECTION_SENSOR; + transaction = new ReputationService( this.nodeType.getNodeId(), @@ -240,10 +248,10 @@ private void publishNodeServices(String serviceType, String target) { target, deviceSensorIdList, this.nodeType.getNodeGroup(), - TransactionType.REP_SVC_WIND_DIRECTION_SENSOR + transactionType ); - transactionType = TransactionType.REP_SVC_WIND_DIRECTION_SENSOR.name(); + transactionTypeInString = transactionType.name(); } else { logger.severe("Unknown service type."); } @@ -251,14 +259,16 @@ private void publishNodeServices(String serviceType, String target) { /* * Enviando a transação para a blockchain. */ - if (transaction != null && transactionType != null) { + if (transaction != null && transactionTypeInString != null) { try { this.ledgerConnector.put( - new IndexTransaction(transactionType, transaction) + new IndexTransaction(transactionTypeInString, transaction) ); } catch (InterruptedException ie) { logger.warning( - "Error trying to create a " + transactionType + " transaction." + "Error trying to create a " + + transactionTypeInString + + " transaction." ); logger.warning(ie.getStackTrace().toString()); } @@ -381,31 +391,20 @@ private void subscribeToDevicesTopics(int amountNewDevices) { @Override public void update(Object object, Object object2) { - // String sourceReceivedTransaction = ((Transaction) object).getSource(); - - // if (!sourceReceivedTransaction.equals(this.getNodeType().getNodeId())) { - // logger.info("OLA"); - // } else { - // logger.info("REMOVER"); - // } - - logger.info("UEEEE"); - String sourceReceivedTransaction = ((Transaction) object).getSource(); - - // if (!sourceReceivedTransaction.equals(this.getNodeType().getNodeId())) {} - - // TODO: Colocar dentro do 'if' - Transaction receivedTransaction = (Transaction) object; - - logger.info("AAAAAA"); - logger.info(receivedTransaction.getType().name()); - - if (receivedTransaction.getType() == TransactionType.REP_HAS_SVC) { - logger.info("A"); - this.publishNodeServices( - ((HasReputationService) receivedTransaction).getService(), // TODO: Esse método não foi chamado e aconteceu somente uma vez - receivedTransaction.getSource() - ); + /** + * Somente caso a transação não tenha sido enviada pelo próprio nó. + */ + if ( + !((Transaction) object).getSource().equals(this.getNodeType().getNodeId()) + ) { + if (((Transaction) object).getType() == TransactionType.REP_HAS_SVC) { + HasReputationService receivedTransaction = (HasReputationService) object; + + this.publishNodeServices( + receivedTransaction.getService(), + receivedTransaction.getSource() + ); + } } } From f15564a73b16d9eb9ba817fa3cb7fb317f6a66c0 Mon Sep 17 00:00:00 2001 From: AllanCapistrano Date: Mon, 13 Nov 2023 14:29:28 -0300 Subject: [PATCH 21/52] chore: checking if a request is in progress --- .../node/tasks/CheckNodesServicesTask.java | 59 +++++++++++-------- 1 file changed, 35 insertions(+), 24 deletions(-) diff --git a/src/main/java/reputation/node/tasks/CheckNodesServicesTask.java b/src/main/java/reputation/node/tasks/CheckNodesServicesTask.java index 8deedf8..007c5a4 100644 --- a/src/main/java/reputation/node/tasks/CheckNodesServicesTask.java +++ b/src/main/java/reputation/node/tasks/CheckNodesServicesTask.java @@ -35,35 +35,46 @@ public CheckNodesServicesTask(Node node) { @Override public void run() { - /** - * Serviço sendo escolhido de maneira aleatório. - */ - int randomIndex = new Random().nextInt(NodeServiceType.values().length); + if (!this.node.isRequestingNodeServices()) { + /** + * Serviço sendo escolhido de maneira aleatório. + */ + int randomIndex = new Random().nextInt(NodeServiceType.values().length); - NodeServiceType nodeServiceType = NodeServiceType.values()[randomIndex]; + NodeServiceType nodeServiceType = NodeServiceType.values()[randomIndex]; - logger.info( - "Checking nodes with " + nodeServiceType.getDescription() + " service." - ); + /** + * Salvando qual foi o último tipo de serviço requisitado. + */ + this.node.setLastNodeServiceTransactionType( + nodeServiceType.getDescription() + ); - Transaction transaction = new HasReputationService( - this.node.getNodeType().getNodeId(), - this.node.getNodeType().getNodeGroup(), - nodeServiceType.getDescription(), - TransactionType.REP_HAS_SVC - ); - - String transactionTypeString = TransactionType.REP_HAS_SVC.name(); + logger.info( + "Checking nodes with " + nodeServiceType.getDescription() + " service." + ); - try { - this.node.getLedgerConnector() - .getLedgerWriter() - .put(new IndexTransaction(transactionTypeString, transaction)); - } catch (InterruptedException ie) { - logger.warning( - "Error trying to create a " + transactionTypeString + " transaction." + Transaction transaction = new HasReputationService( + this.node.getNodeType().getNodeId(), + this.node.getNodeType().getNodeGroup(), + nodeServiceType.getDescription(), + TransactionType.REP_HAS_SVC ); - logger.warning(ie.getStackTrace().toString()); + + String transactionTypeString = TransactionType.REP_HAS_SVC.name(); + + this.node.setRequestingNodeServices(true); + + try { + this.node.getLedgerConnector() + .getLedgerWriter() + .put(new IndexTransaction(transactionTypeString, transaction)); + } catch (InterruptedException ie) { + logger.warning( + "Error trying to create a " + transactionTypeString + " transaction." + ); + logger.warning(ie.getStackTrace().toString()); + } } } } From f08c33b7cc2881b121b57f9ff65233ffba881274 Mon Sep 17 00:00:00 2001 From: AllanCapistrano Date: Mon, 13 Nov 2023 14:30:13 -0300 Subject: [PATCH 22/52] feat: check the response of node service provider and add new topics to subscribe --- .../java/reputation/node/models/Node.java | 193 ++++++++++-------- 1 file changed, 110 insertions(+), 83 deletions(-) diff --git a/src/main/java/reputation/node/models/Node.java b/src/main/java/reputation/node/models/Node.java index 529a420..9ca3685 100644 --- a/src/main/java/reputation/node/models/Node.java +++ b/src/main/java/reputation/node/models/Node.java @@ -6,6 +6,7 @@ import dlt.client.tangle.hornet.enums.TransactionType; import dlt.client.tangle.hornet.model.DeviceSensorId; import dlt.client.tangle.hornet.model.transactions.IndexTransaction; +import dlt.client.tangle.hornet.model.transactions.TargetedTransaction; import dlt.client.tangle.hornet.model.transactions.Transaction; import dlt.client.tangle.hornet.model.transactions.reputation.HasReputationService; import dlt.client.tangle.hornet.model.transactions.reputation.ReputationService; @@ -18,7 +19,6 @@ import java.util.TimerTask; import java.util.concurrent.locks.ReentrantLock; import java.util.logging.Logger; -import java.util.stream.Collectors; import node.type.services.INodeType; import reputation.node.enums.NodeServiceType; import reputation.node.mqtt.ListenerDevices; @@ -52,6 +52,8 @@ public class Node implements NodeTypeService, ILedgerSubscriber { private TimerTask waitDeviceResponseTask; private ReentrantLock mutex = new ReentrantLock(); private ReentrantLock mutexNodesServices = new ReentrantLock(); + private String lastNodeServiceTransactionType = null; // TODO: Alterar de volta para 'null' quando o timer expirar ou quando terminar o processo + private boolean isRequestingNodeServices = false; // TODO: Alterar o valor para 'false' quando o timer expirar ou quando terminar o processo private static final Logger logger = Logger.getLogger(Node.class.getName()); public Node() {} @@ -276,93 +278,27 @@ private void publishNodeServices(String serviceType, String target) { } } - /** - * Obtém uma lista com as transações a respeito de um serviço que os demais - * nós prestam. - * - * @param serviceType NodeServiceType - Tipo do serviço. - */ - public void getNodesServices(NodeServiceType serviceType) { // TODO: Verificar se vai usar - try { - this.mutexNodesServices.lock(); - - this.nodesWithServices.clear(); - - String index = ""; - - switch (serviceType) { - case HUMIDITY_SENSOR: - index = TransactionType.REP_SVC_HUMIDITY_SENSOR.name(); - break; - case PULSE_OXYMETER: - index = TransactionType.REP_SVC_PULSE_OXYMETER.name(); - break; - case THERMOMETER: - index = TransactionType.REP_SVC_THERMOMETER.name(); - break; - case WIND_DIRECTION_SENSOR: - index = TransactionType.REP_SVC_WIND_DIRECTION_SENSOR.name(); - break; - default: - logger.severe("Unknown service type."); - break; - } - - if (!index.equals("")) { - List transactions = - this.ledgerConnector.getLedgerReader().getTransactionsByIndex(index); - - /* - * Ordenação em ordem decrescente com relação a data/hora de criação da - * transação. - */ - transactions.sort((t1, t2) -> - Long.compare(t2.getCreatedAt(), t1.getCreatedAt()) - ); - - /** - * Tempo limite de 1 hora. - */ - long timeLimit = System.currentTimeMillis() - 1 * 60 * 60 * 1000; - - /** - * Removendo serviços duplicados de um mesmo nó, e as transações criadas - * a mais de 1 hora atrás. - */ - this.nodesWithServices = - transactions - .stream() - .collect( - Collectors.toMap( - Transaction::getSource, - obj -> obj, - (existing, replacement) -> existing - ) - ) - .values() - .stream() - .filter(obj -> obj.getCreatedAt() >= timeLimit) // TODO: Adicionar filtro para não pegar a transação que o próprio nó enviou - .collect(Collectors.toList()); - } - } finally { - this.mutexNodesServices.unlock(); - } - - logger.info("-----------------"); // TODO: remover - - for (Transaction transaction : this.nodesWithServices) { // TODO: remover - logger.info(((ReputationService) transaction).getSource()); - logger.info( - Long.toString(((ReputationService) transaction).getCreatedAt()) - ); - } - } - /** * Se inscreve nos tópicos ZMQ das transações . */ private void subscribeToTransactionsTopics() { this.ledgerConnector.subscribe(TransactionType.REP_HAS_SVC.name(), this); + this.ledgerConnector.subscribe( + TransactionType.REP_SVC_HUMIDITY_SENSOR.name(), + this + ); + this.ledgerConnector.subscribe( + TransactionType.REP_SVC_PULSE_OXYMETER.name(), + this + ); + this.ledgerConnector.subscribe( + TransactionType.REP_SVC_THERMOMETER.name(), + this + ); + this.ledgerConnector.subscribe( + TransactionType.REP_SVC_WIND_DIRECTION_SENSOR.name(), + this + ); } /** @@ -370,6 +306,22 @@ private void subscribeToTransactionsTopics() { */ private void unsubscribeToTransactionsTopics() { this.ledgerConnector.unsubscribe(TransactionType.REP_HAS_SVC.name(), this); + this.ledgerConnector.unsubscribe( + TransactionType.REP_SVC_HUMIDITY_SENSOR.name(), + this + ); + this.ledgerConnector.unsubscribe( + TransactionType.REP_SVC_PULSE_OXYMETER.name(), + this + ); + this.ledgerConnector.unsubscribe( + TransactionType.REP_SVC_THERMOMETER.name(), + this + ); + this.ledgerConnector.unsubscribe( + TransactionType.REP_SVC_WIND_DIRECTION_SENSOR.name(), + this + ); } /** @@ -404,6 +356,63 @@ public void update(Object object, Object object2) { receivedTransaction.getService(), receivedTransaction.getSource() ); + } else { + TargetedTransaction receivedTransaction = (TargetedTransaction) object; + + /** + * Somente se o destino da transação for este nó. + */ + if ( + receivedTransaction.getTarget().equals(this.nodeType.getNodeId()) && + this.isRequestingNodeServices + ) { + TransactionType expectedTransactionType = null; + + /** + * Verificando se a transação de serviço que recebeu é do tipo que + * requisitou. + */ + if ( + this.lastNodeServiceTransactionType.equals( + NodeServiceType.HUMIDITY_SENSOR.getDescription() + ) + ) { + expectedTransactionType = TransactionType.REP_SVC_HUMIDITY_SENSOR; + } else if ( + this.lastNodeServiceTransactionType.equals( + NodeServiceType.PULSE_OXYMETER.getDescription() + ) + ) { + expectedTransactionType = TransactionType.REP_SVC_PULSE_OXYMETER; + } else if ( + this.lastNodeServiceTransactionType.equals( + NodeServiceType.THERMOMETER.getDescription() + ) + ) { + expectedTransactionType = TransactionType.REP_SVC_THERMOMETER; + } else if ( + this.lastNodeServiceTransactionType.equals( + NodeServiceType.WIND_DIRECTION_SENSOR.getDescription() + ) + ) { + expectedTransactionType = + TransactionType.REP_SVC_WIND_DIRECTION_SENSOR; + } + + /** + * Adicionando na lista as transações referente aos serviços prestados + * pelos outros nós. + */ + if (receivedTransaction.getType() == expectedTransactionType) { + try { + this.mutexNodesServices.lock(); + this.nodesWithServices.clear(); + this.nodesWithServices.add(receivedTransaction); + } finally { + this.mutexNodesServices.unlock(); + } + } + } } } } @@ -491,4 +500,22 @@ public int getCheckNodesServicesTaskTime() { public void setCheckNodesServicesTaskTime(int checkNodesServicesTaskTime) { this.checkNodesServicesTaskTime = checkNodesServicesTaskTime; } + + public String getLastNodeServiceTransactionType() { + return lastNodeServiceTransactionType; + } + + public void setLastNodeServiceTransactionType( + String lastNodeServiceTransactionType + ) { + this.lastNodeServiceTransactionType = lastNodeServiceTransactionType; + } + + public boolean isRequestingNodeServices() { + return isRequestingNodeServices; + } + + public void setRequestingNodeServices(boolean isRequestingNodeServices) { + this.isRequestingNodeServices = isRequestingNodeServices; + } } From 45663cc42b9bc312ee1cdf293f3a770785ff2373 Mon Sep 17 00:00:00 2001 From: AllanCapistrano Date: Mon, 13 Nov 2023 15:22:28 -0300 Subject: [PATCH 23/52] feat: create WaitNodesResponsesTask --- .../node/tasks/WaitNodesResponsesTask.java | 52 +++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 src/main/java/reputation/node/tasks/WaitNodesResponsesTask.java diff --git a/src/main/java/reputation/node/tasks/WaitNodesResponsesTask.java b/src/main/java/reputation/node/tasks/WaitNodesResponsesTask.java new file mode 100644 index 0000000..566d778 --- /dev/null +++ b/src/main/java/reputation/node/tasks/WaitNodesResponsesTask.java @@ -0,0 +1,52 @@ +package reputation.node.tasks; + +import java.util.TimerTask; +import java.util.logging.Logger; +import reputation.node.models.Node; + +/** + * Classe responsável por determinar um tempo limite para um nó receber as + * respostas dos outros nós à solicitação de serviços. + * + * @author Allan Capistrano + * @version 1.0.0 + */ +public class WaitNodesResponsesTask extends TimerTask { + + private int timer, timeoutWaitNodesResponses; + private final Node node; + private static final Logger logger = Logger.getLogger( + WaitNodesResponsesTask.class.getName() + ); + + /** + * Método construtor + * + * @param timeoutWaitNodesResponses int - Tempo máximo para aguardar a + * resposta dos nós. + * @param node Node - Nó o qual está esperando a resposta. + */ + public WaitNodesResponsesTask(int timeoutWaitNodesResponses, Node node) { + this.timeoutWaitNodesResponses = timeoutWaitNodesResponses; + this.node = node; + this.timer = 0; + } + + @Override + public void run() { + this.timer++; + + if ((timer * 1000) >= this.timeoutWaitNodesResponses) { + logger.info("Timeout waiting for Nodes responses."); + + /** + * Impede o nó de receber as respostas dos outros nós. + */ + this.node.setCanReceiveNodesResponse(false); + + // TODO: Adicionar a chamada da função para verificar a reputaçãos dos nós que responderam e estão na lista + + this.cancel(); + } + } +} From def69bbe58c36025827affc821d1431a24b82ff3 Mon Sep 17 00:00:00 2001 From: AllanCapistrano Date: Mon, 13 Nov 2023 15:23:24 -0300 Subject: [PATCH 24/52] feat: create waitNodesResponsesTaskTime property --- .../java/reputation/node/models/Node.java | 41 +++++++++++++++++-- .../OSGI-INF/blueprint/blueprint.xml | 2 + ...r.uefs.larsid.soft_iot.reputation_node.cfg | 3 ++ 3 files changed, 43 insertions(+), 3 deletions(-) diff --git a/src/main/java/reputation/node/models/Node.java b/src/main/java/reputation/node/models/Node.java index 9ca3685..1cb7189 100644 --- a/src/main/java/reputation/node/models/Node.java +++ b/src/main/java/reputation/node/models/Node.java @@ -28,6 +28,7 @@ import reputation.node.tasks.CheckNodesServicesTask; import reputation.node.tasks.RequestDataTask; import reputation.node.tasks.WaitDeviceResponseTask; +import reputation.node.tasks.WaitNodesResponsesTask; import reputation.node.utils.MQTTClient; /** @@ -43,6 +44,7 @@ public class Node implements NodeTypeService, ILedgerSubscriber { private int requestDataTaskTime; private int waitDeviceResponseTaskTime; private int checkNodesServicesTaskTime; + private int waitNodesResponsesTaskTime; private List devices; private List nodesWithServices; private LedgerConnector ledgerConnector; @@ -50,10 +52,12 @@ public class Node implements NodeTypeService, ILedgerSubscriber { private IDevicePropertiesManager deviceManager; private ListenerDevices listenerDevices; private TimerTask waitDeviceResponseTask; + private TimerTask waitNodesResponsesTask; private ReentrantLock mutex = new ReentrantLock(); private ReentrantLock mutexNodesServices = new ReentrantLock(); - private String lastNodeServiceTransactionType = null; // TODO: Alterar de volta para 'null' quando o timer expirar ou quando terminar o processo - private boolean isRequestingNodeServices = false; // TODO: Alterar o valor para 'false' quando o timer expirar ou quando terminar o processo + private String lastNodeServiceTransactionType = null; // TODO: Alterar de volta para 'null' quando terminar o processo + private boolean isRequestingNodeServices = false; // TODO: Alterar o valor para 'false' quando terminar o processo + private boolean canReceiveNodesResponse = false; private static final Logger logger = Logger.getLogger(Node.class.getName()); public Node() {} @@ -86,6 +90,12 @@ public void start() { this.checkNodesServicesTaskTime * 1000 ); + this.waitNodesResponsesTask = + new WaitNodesResponsesTask( + (this.waitNodesResponsesTaskTime * 1000), + this + ); + this.subscribeToTransactionsTopics(); } @@ -364,7 +374,8 @@ public void update(Object object, Object object2) { */ if ( receivedTransaction.getTarget().equals(this.nodeType.getNodeId()) && - this.isRequestingNodeServices + this.isRequestingNodeServices && + this.canReceiveNodesResponse ) { TransactionType expectedTransactionType = null; @@ -518,4 +529,28 @@ public boolean isRequestingNodeServices() { public void setRequestingNodeServices(boolean isRequestingNodeServices) { this.isRequestingNodeServices = isRequestingNodeServices; } + + public boolean isCanReceiveNodesResponse() { + return canReceiveNodesResponse; + } + + public void setCanReceiveNodesResponse(boolean canReceiveNodesResponse) { + this.canReceiveNodesResponse = canReceiveNodesResponse; + } + + public int getWaitNodesResponsesTaskTime() { + return waitNodesResponsesTaskTime; + } + + public void setWaitNodesResponsesTaskTime(int waitNodesResponsesTaskTime) { + this.waitNodesResponsesTaskTime = waitNodesResponsesTaskTime; + } + + public TimerTask getWaitNodesResponsesTask() { + return waitNodesResponsesTask; + } + + public void setWaitNodesResponsesTask(TimerTask waitNodesResponsesTask) { + this.waitNodesResponsesTask = waitNodesResponsesTask; + } } diff --git a/src/main/resources/OSGI-INF/blueprint/blueprint.xml b/src/main/resources/OSGI-INF/blueprint/blueprint.xml index 54cfdb3..2e4e81c 100644 --- a/src/main/resources/OSGI-INF/blueprint/blueprint.xml +++ b/src/main/resources/OSGI-INF/blueprint/blueprint.xml @@ -29,6 +29,7 @@ + @@ -50,6 +51,7 @@ + diff --git a/src/main/resources/br.uefs.larsid.soft_iot.reputation_node.cfg b/src/main/resources/br.uefs.larsid.soft_iot.reputation_node.cfg index f60f4c2..716107b 100644 --- a/src/main/resources/br.uefs.larsid.soft_iot.reputation_node.cfg +++ b/src/main/resources/br.uefs.larsid.soft_iot.reputation_node.cfg @@ -13,5 +13,8 @@ requestDataTaskTime=30 waitDeviceResponseTaskTime=10 # Tempo (segundos) para vericar quais nós tem um determinado serviço. checkNodesServicesTaskTime=45 +# Tempo máximo (segundos) de espera da resposta do nós para a requisição de pretação de serviço. +# Obs: Tem que ser menor do que o 'checkNodesServicesTaskTime'. +waitNodesResponsesTaskTime=30 debugModeValue=true \ No newline at end of file From 99eaa841116577d01c7b0320f00bada667d197e0 Mon Sep 17 00:00:00 2001 From: AllanCapistrano Date: Mon, 13 Nov 2023 15:23:46 -0300 Subject: [PATCH 25/52] chore: using WaitNodesResponsesTask --- .../node/tasks/CheckNodesServicesTask.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/main/java/reputation/node/tasks/CheckNodesServicesTask.java b/src/main/java/reputation/node/tasks/CheckNodesServicesTask.java index 007c5a4..4afd68a 100644 --- a/src/main/java/reputation/node/tasks/CheckNodesServicesTask.java +++ b/src/main/java/reputation/node/tasks/CheckNodesServicesTask.java @@ -5,6 +5,7 @@ import dlt.client.tangle.hornet.model.transactions.Transaction; import dlt.client.tangle.hornet.model.transactions.reputation.HasReputationService; import java.util.Random; +import java.util.Timer; import java.util.TimerTask; import java.util.logging.Logger; import reputation.node.enums.NodeServiceType; @@ -50,6 +51,11 @@ public void run() { nodeServiceType.getDescription() ); + /** + * Permitindo o nó a receber as respostas dos outros nós. + */ + this.node.setCanReceiveNodesResponse(true); + logger.info( "Checking nodes with " + nodeServiceType.getDescription() + " service." ); @@ -69,6 +75,12 @@ public void run() { this.node.getLedgerConnector() .getLedgerWriter() .put(new IndexTransaction(transactionTypeString, transaction)); + + /** + * Timer para aguardar as aceitar as respostas dos nós. + */ + new Timer() + .scheduleAtFixedRate(this.node.getWaitNodesResponsesTask(), 0, 1000); } catch (InterruptedException ie) { logger.warning( "Error trying to create a " + transactionTypeString + " transaction." From 2a84de2c8b2ac3be23d751c2e207471d76b0f5af Mon Sep 17 00:00:00 2001 From: AllanCapistrano Date: Tue, 14 Nov 2023 19:11:47 -0300 Subject: [PATCH 26/52] feat: create NodeReputation class --- .../node/models/NodeReputation.java | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 src/main/java/reputation/node/models/NodeReputation.java diff --git a/src/main/java/reputation/node/models/NodeReputation.java b/src/main/java/reputation/node/models/NodeReputation.java new file mode 100644 index 0000000..1f04eaa --- /dev/null +++ b/src/main/java/reputation/node/models/NodeReputation.java @@ -0,0 +1,39 @@ +package reputation.node.models; + +/** + * + * @author Allan Capistrano + * @version 1.0.0 + */ +public class NodeReputation { + + private String nodeId; + private Double reputation; + + /** + * Método construtor. + * + * @param nodeId String - ID do nó. + * @param reputation Double - Reputação do nó. + */ + public NodeReputation(String nodeId, Double reputation) { + this.nodeId = nodeId; + this.reputation = reputation; + } + + public String getNodeId() { + return nodeId; + } + + public void setNodeId(String nodeId) { + this.nodeId = nodeId; + } + + public Double getReputation() { + return reputation; + } + + public void setReputation(Double reputation) { + this.reputation = reputation; + } +} From a94c17707aa611e9d736c0f681ac81f96acde410 Mon Sep 17 00:00:00 2001 From: AllanCapistrano Date: Tue, 14 Nov 2023 19:12:15 -0300 Subject: [PATCH 27/52] feat: create checkNodesReputation method --- .../java/reputation/node/models/Node.java | 77 +++++++++++++++++++ 1 file changed, 77 insertions(+) diff --git a/src/main/java/reputation/node/models/Node.java b/src/main/java/reputation/node/models/Node.java index 1cb7189..1efaa00 100644 --- a/src/main/java/reputation/node/models/Node.java +++ b/src/main/java/reputation/node/models/Node.java @@ -19,6 +19,7 @@ import java.util.TimerTask; import java.util.concurrent.locks.ReentrantLock; import java.util.logging.Logger; +import java.util.stream.Collectors; import node.type.services.INodeType; import reputation.node.enums.NodeServiceType; import reputation.node.mqtt.ListenerDevices; @@ -288,6 +289,82 @@ private void publishNodeServices(String serviceType, String target) { } } + /** + * Verifica a reputação dos nós que responderam a requisição de serviço. + */ + public void checkNodesReputation() { + List nodesReputations = new ArrayList<>(); + Double reputation; + Double highestReputation = 0.0; + String highestReputationNodeId = null; + + /** + * Salvando a reputação de cada nó em uma lista. + */ + for (Transaction nodeWithService : this.nodesWithServices) { + String nodeId = nodeWithService.getSource(); + + List evaluationTransactions = + this.ledgerConnector.getLedgerReader().getTransactionsByIndex(nodeId); + + if (evaluationTransactions.isEmpty()) { + reputation = 0.5; + } else { + reputation = 0.0; // TODO: Implementar o cáculo da reputação e modificar essa variável. + } + + nodesReputations.add(new NodeReputation(nodeId, reputation)); + + if (reputation > highestReputation) { + highestReputation = reputation; + } + } + + final Double innerHighestReputation = Double.valueOf(highestReputation); + + /** + * Verificando quais nós possuem a maior reputação. + */ + List temp = nodesReputations + .stream() + .filter(nr -> nr.getReputation().equals(innerHighestReputation)) + .collect(Collectors.toList()); + + /** + * Obtendo o ID de um dos nós com a maior reputação. + */ + if (temp.size() > 1) { + int randomIndex = new Random().nextInt(temp.size()); + + highestReputationNodeId = temp.get(randomIndex).getNodeId(); + } else if (temp.size() == 0) { + highestReputationNodeId = temp.get(0).getNodeId(); + } else { + // TODO: Corrigir, de alguma forma está entrando aqui + logger.severe("Invalid amount of nodes with the highest reputation."); + } + + if (highestReputationNodeId != null) { + final String innerHighestReputationNodeId = String.valueOf( + highestReputationNodeId + ); + + /** + * Pegando a transação do nó com a maior reputação. + */ + ReputationService nodeWithService = (ReputationService) this.nodesWithServices.stream() + .filter(nws -> nws.getSource().equals(innerHighestReputationNodeId)) + .collect(Collectors.toList()) + .get(0); + + // TODO: Remover + logger.info("AAAAAA"); + logger.info(nodeWithService.getSourceIp()); + logger.info(nodeWithService.getServices().get(0).getDeviceId()); + logger.info(nodeWithService.getServices().get(0).getSensorId()); + } + } + /** * Se inscreve nos tópicos ZMQ das transações . */ From ec07ec655bb2ba94e859de1400a66ca2be5feec7 Mon Sep 17 00:00:00 2001 From: AllanCapistrano Date: Tue, 14 Nov 2023 19:12:54 -0300 Subject: [PATCH 28/52] chore: using checkNodesReputation --- .../java/reputation/node/tasks/WaitNodesResponsesTask.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/main/java/reputation/node/tasks/WaitNodesResponsesTask.java b/src/main/java/reputation/node/tasks/WaitNodesResponsesTask.java index 566d778..311d204 100644 --- a/src/main/java/reputation/node/tasks/WaitNodesResponsesTask.java +++ b/src/main/java/reputation/node/tasks/WaitNodesResponsesTask.java @@ -44,7 +44,11 @@ public void run() { */ this.node.setCanReceiveNodesResponse(false); - // TODO: Adicionar a chamada da função para verificar a reputaçãos dos nós que responderam e estão na lista + /** + * Verificando a reputação dos nós que responderam a requisição de + * serviço. + */ + this.node.checkNodesReputation(); this.cancel(); } From 11458b5923550093011c070cc00e898557f94acf Mon Sep 17 00:00:00 2001 From: AllanCapistrano Date: Wed, 15 Nov 2023 15:28:45 -0300 Subject: [PATCH 29/52] fix: invalid amount of nodes with highest reputation --- src/main/java/reputation/node/models/Node.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/main/java/reputation/node/models/Node.java b/src/main/java/reputation/node/models/Node.java index 1efaa00..a35178d 100644 --- a/src/main/java/reputation/node/models/Node.java +++ b/src/main/java/reputation/node/models/Node.java @@ -333,14 +333,13 @@ public void checkNodesReputation() { /** * Obtendo o ID de um dos nós com a maior reputação. */ - if (temp.size() > 1) { + if (temp.size() == 0) { + highestReputationNodeId = temp.get(0).getNodeId(); + } else if (temp.size() > 0) { int randomIndex = new Random().nextInt(temp.size()); highestReputationNodeId = temp.get(randomIndex).getNodeId(); - } else if (temp.size() == 0) { - highestReputationNodeId = temp.get(0).getNodeId(); } else { - // TODO: Corrigir, de alguma forma está entrando aqui logger.severe("Invalid amount of nodes with the highest reputation."); } From b08fa2c52b03bbe126ce70fcdd6ac8c030566380 Mon Sep 17 00:00:00 2001 From: AllanCapistrano Date: Wed, 15 Nov 2023 15:31:03 -0300 Subject: [PATCH 30/52] chore: set variables to default values if the process has not been completed --- src/main/java/reputation/node/models/Node.java | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/main/java/reputation/node/models/Node.java b/src/main/java/reputation/node/models/Node.java index a35178d..5c30a44 100644 --- a/src/main/java/reputation/node/models/Node.java +++ b/src/main/java/reputation/node/models/Node.java @@ -355,12 +355,9 @@ public void checkNodesReputation() { .filter(nws -> nws.getSource().equals(innerHighestReputationNodeId)) .collect(Collectors.toList()) .get(0); - - // TODO: Remover - logger.info("AAAAAA"); - logger.info(nodeWithService.getSourceIp()); - logger.info(nodeWithService.getServices().get(0).getDeviceId()); - logger.info(nodeWithService.getServices().get(0).getSensorId()); + } else { + this.setRequestingNodeServices(false); + this.setLastNodeServiceTransactionType(null); } } From ae9cbc9b3de6766c96074d06957dda6062146292 Mon Sep 17 00:00:00 2001 From: AllanCapistrano Date: Wed, 15 Nov 2023 16:26:14 -0300 Subject: [PATCH 31/52] fix: evaluating devices when receive a FLOW message by MQTT --- .../reputation/node/mqtt/ListenerDevices.java | 35 ++++++++++--------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/src/main/java/reputation/node/mqtt/ListenerDevices.java b/src/main/java/reputation/node/mqtt/ListenerDevices.java index af0130b..4aaa52f 100644 --- a/src/main/java/reputation/node/mqtt/ListenerDevices.java +++ b/src/main/java/reputation/node/mqtt/ListenerDevices.java @@ -66,26 +66,29 @@ public void messageArrived(String topic, MqttMessage message) throws Exception { final String mqttMessage = new String(message.getPayload()); - logger.info(mqttMessage); - JsonObject jsonResponse = new Gson() .fromJson(mqttMessage, JsonObject.class); - String deviceId = jsonResponse - .get("HEADER") - .getAsJsonObject() - .get("NAME") - .getAsString(); - logger.info("Device Id: " + deviceId); + if (jsonResponse.get("METHOD").getAsString().equals("GET")) { + logger.info(mqttMessage); - if (this.node.getWaitDeviceResponseTask() != null) { - this.node.getWaitDeviceResponseTask().cancel(); - } - // Avaliação de serviço prestado corretamente. - try { - this.node.getNodeType().getNode().evaluateServiceProvider(deviceId, 1); - } catch (Exception e) { - logger.warning("Could not add transaction on tangle network."); + String deviceId = jsonResponse + .get("HEADER") + .getAsJsonObject() + .get("NAME") + .getAsString(); + + logger.info("Device Id: " + deviceId); + + if (this.node.getWaitDeviceResponseTask() != null) { + this.node.getWaitDeviceResponseTask().cancel(); + } + // Avaliação de serviço prestado corretamente. + try { + this.node.getNodeType().getNode().evaluateServiceProvider(deviceId, 1); + } catch (Exception e) { + logger.warning("Could not add transaction on tangle network."); + } } } } From adabcbe973f6839ce23179a757e2249fc2c3d6bb Mon Sep 17 00:00:00 2001 From: AllanCapistrano Date: Wed, 15 Nov 2023 16:55:45 -0300 Subject: [PATCH 32/52] feat: create requestNodeService method --- .../java/reputation/node/models/Node.java | 184 +++++++++++++----- 1 file changed, 138 insertions(+), 46 deletions(-) diff --git a/src/main/java/reputation/node/models/Node.java b/src/main/java/reputation/node/models/Node.java index 5c30a44..d610130 100644 --- a/src/main/java/reputation/node/models/Node.java +++ b/src/main/java/reputation/node/models/Node.java @@ -3,6 +3,11 @@ import br.uefs.larsid.extended.mapping.devices.services.IDevicePropertiesManager; import br.ufba.dcc.wiser.soft_iot.entities.Device; import br.ufba.dcc.wiser.soft_iot.entities.Sensor; +import br.ufba.dcc.wiser.soft_iot.entities.SensorData; +import com.google.gson.Gson; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import com.google.gson.stream.JsonReader; import dlt.client.tangle.hornet.enums.TransactionType; import dlt.client.tangle.hornet.model.DeviceSensorId; import dlt.client.tangle.hornet.model.transactions.IndexTransaction; @@ -11,7 +16,13 @@ import dlt.client.tangle.hornet.model.transactions.reputation.HasReputationService; import dlt.client.tangle.hornet.model.transactions.reputation.ReputationService; import dlt.client.tangle.hornet.services.ILedgerSubscriber; +import java.io.BufferedReader; import java.io.IOException; +import java.io.InputStreamReader; +import java.io.StringReader; +import java.net.HttpURLConnection; +import java.net.MalformedURLException; +import java.net.URL; import java.util.ArrayList; import java.util.List; import java.util.Random; @@ -298,66 +309,147 @@ public void checkNodesReputation() { Double highestReputation = 0.0; String highestReputationNodeId = null; - /** - * Salvando a reputação de cada nó em uma lista. - */ - for (Transaction nodeWithService : this.nodesWithServices) { - String nodeId = nodeWithService.getSource(); + // TODO: Verificar se quando não tem ninguém respondendo a solicitação, se ele ainda fica checando de tempo em tempos + if (this.nodesWithServices.isEmpty()) { + this.setRequestingNodeServices(false); + this.setLastNodeServiceTransactionType(null); + logger.info("EEEEEEEEEEEEE"); + } else { + /** + * Salvando a reputação de cada nó em uma lista. + */ + for (Transaction nodeWithService : this.nodesWithServices) { + String nodeId = nodeWithService.getSource(); + + List evaluationTransactions = + this.ledgerConnector.getLedgerReader().getTransactionsByIndex(nodeId); + + if (evaluationTransactions.isEmpty()) { + reputation = 0.5; + } else { + reputation = 0.0; // TODO: Implementar o cáculo da reputação e modificar essa variável. + } + + nodesReputations.add(new NodeReputation(nodeId, reputation)); + + if (reputation > highestReputation) { + highestReputation = reputation; + } + } - List evaluationTransactions = - this.ledgerConnector.getLedgerReader().getTransactionsByIndex(nodeId); + final Double innerHighestReputation = Double.valueOf(highestReputation); - if (evaluationTransactions.isEmpty()) { - reputation = 0.5; + /** + * Verificando quais nós possuem a maior reputação. + */ + List temp = nodesReputations + .stream() + .filter(nr -> nr.getReputation().equals(innerHighestReputation)) + .collect(Collectors.toList()); + + /** + * Obtendo o ID de um dos nós com a maior reputação. + */ + if (temp.size() == 0) { + highestReputationNodeId = temp.get(0).getNodeId(); + } else if (temp.size() > 0) { + int randomIndex = new Random().nextInt(temp.size()); + + highestReputationNodeId = temp.get(randomIndex).getNodeId(); } else { - reputation = 0.0; // TODO: Implementar o cáculo da reputação e modificar essa variável. + logger.severe("Invalid amount of nodes with the highest reputation."); } - nodesReputations.add(new NodeReputation(nodeId, reputation)); + if (highestReputationNodeId != null) { + final String innerHighestReputationNodeId = String.valueOf( + highestReputationNodeId + ); - if (reputation > highestReputation) { - highestReputation = reputation; + /** + * Pegando a transação do nó com a maior reputação. + */ + ReputationService nodeWithService = (ReputationService) this.nodesWithServices.stream() + .filter(nws -> nws.getSource().equals(innerHighestReputationNodeId)) + .collect(Collectors.toList()) + .get(0); + + // TODO: Calcular a reputação de todos os dispositivos, e enviar as informações do dispositivo com a maior reputação + this.requestNodeService( + nodeWithService.getSourceIp(), + nodeWithService.getServices().get(0).getDeviceId(), + nodeWithService.getServices().get(0).getSensorId() + ); + } else { + this.setRequestingNodeServices(false); + this.setLastNodeServiceTransactionType(null); } } + } - final Double innerHighestReputation = Double.valueOf(highestReputation); - - /** - * Verificando quais nós possuem a maior reputação. - */ - List temp = nodesReputations - .stream() - .filter(nr -> nr.getReputation().equals(innerHighestReputation)) - .collect(Collectors.toList()); + // TODO: Adicionar documentação + private void requestNodeService( // TODO: Tem um bug, isso aqui não está funcionando corretamente + String nodeIp, + String deviceId, + String sensorId + ) { + boolean isNullable = false; + String response = null; - /** - * Obtendo o ID de um dos nós com a maior reputação. - */ - if (temp.size() == 0) { - highestReputationNodeId = temp.get(0).getNodeId(); - } else if (temp.size() > 0) { - int randomIndex = new Random().nextInt(temp.size()); + try { + URL url = new URL( + String.format( + "http://%s:8181/cxf/iot-service/devices/%s/%s", + nodeIp, + deviceId, + sensorId + ) + ); + HttpURLConnection conn = (HttpURLConnection) url.openConnection(); - highestReputationNodeId = temp.get(randomIndex).getNodeId(); - } else { - logger.severe("Invalid amount of nodes with the highest reputation."); - } + if (conn.getResponseCode() != HttpURLConnection.HTTP_OK) { + throw new RuntimeException( + "HTTP error code : " + conn.getResponseCode() + ); + } - if (highestReputationNodeId != null) { - final String innerHighestReputationNodeId = String.valueOf( - highestReputationNodeId + BufferedReader br = new BufferedReader( + new InputStreamReader((conn.getInputStream())) ); - /** - * Pegando a transação do nó com a maior reputação. - */ - ReputationService nodeWithService = (ReputationService) this.nodesWithServices.stream() - .filter(nws -> nws.getSource().equals(innerHighestReputationNodeId)) - .collect(Collectors.toList()) - .get(0); - } else { - this.setRequestingNodeServices(false); - this.setLastNodeServiceTransactionType(null); + String temp = null; + + while ((temp = br.readLine()) != null) { + if (temp.equals("null")) { + isNullable = true; + + break; + } + + response = temp; + } + + conn.disconnect(); + + // TODO: Colocar essa conversão em uma função + JsonReader reader = new JsonReader(new StringReader(response)); + + reader.setLenient(true); + + JsonObject jsonObject = JsonParser.parseReader(reader).getAsJsonObject(); + + Gson gson = new Gson(); + + SensorData sensorData = gson.fromJson(jsonObject, SensorData.class); + + // TODO: Remover + logger.info("-------------"); + logger.info(sensorData.getDevice().getId()); + logger.info(sensorData.getSensor().getId()); + logger.info(sensorData.getValue()); + } catch (MalformedURLException mue) { + logger.severe(mue.getMessage()); + } catch (IOException ioe) { + logger.severe(ioe.getMessage()); } } From e2812898df2eb9593f4fd049cedccc2780557b6d Mon Sep 17 00:00:00 2001 From: AllanCapistrano Date: Thu, 16 Nov 2023 13:59:53 -0300 Subject: [PATCH 33/52] fix: check nodes services task when no node responds --- src/main/java/reputation/node/models/Node.java | 18 ------------------ .../node/tasks/CheckNodesServicesTask.java | 9 ++++++++- 2 files changed, 8 insertions(+), 19 deletions(-) diff --git a/src/main/java/reputation/node/models/Node.java b/src/main/java/reputation/node/models/Node.java index d610130..87088f9 100644 --- a/src/main/java/reputation/node/models/Node.java +++ b/src/main/java/reputation/node/models/Node.java @@ -40,7 +40,6 @@ import reputation.node.tasks.CheckNodesServicesTask; import reputation.node.tasks.RequestDataTask; import reputation.node.tasks.WaitDeviceResponseTask; -import reputation.node.tasks.WaitNodesResponsesTask; import reputation.node.utils.MQTTClient; /** @@ -64,7 +63,6 @@ public class Node implements NodeTypeService, ILedgerSubscriber { private IDevicePropertiesManager deviceManager; private ListenerDevices listenerDevices; private TimerTask waitDeviceResponseTask; - private TimerTask waitNodesResponsesTask; private ReentrantLock mutex = new ReentrantLock(); private ReentrantLock mutexNodesServices = new ReentrantLock(); private String lastNodeServiceTransactionType = null; // TODO: Alterar de volta para 'null' quando terminar o processo @@ -102,12 +100,6 @@ public void start() { this.checkNodesServicesTaskTime * 1000 ); - this.waitNodesResponsesTask = - new WaitNodesResponsesTask( - (this.waitNodesResponsesTaskTime * 1000), - this - ); - this.subscribeToTransactionsTopics(); } @@ -309,11 +301,9 @@ public void checkNodesReputation() { Double highestReputation = 0.0; String highestReputationNodeId = null; - // TODO: Verificar se quando não tem ninguém respondendo a solicitação, se ele ainda fica checando de tempo em tempos if (this.nodesWithServices.isEmpty()) { this.setRequestingNodeServices(false); this.setLastNodeServiceTransactionType(null); - logger.info("EEEEEEEEEEEEE"); } else { /** * Salvando a reputação de cada nó em uma lista. @@ -710,12 +700,4 @@ public int getWaitNodesResponsesTaskTime() { public void setWaitNodesResponsesTaskTime(int waitNodesResponsesTaskTime) { this.waitNodesResponsesTaskTime = waitNodesResponsesTaskTime; } - - public TimerTask getWaitNodesResponsesTask() { - return waitNodesResponsesTask; - } - - public void setWaitNodesResponsesTask(TimerTask waitNodesResponsesTask) { - this.waitNodesResponsesTask = waitNodesResponsesTask; - } } diff --git a/src/main/java/reputation/node/tasks/CheckNodesServicesTask.java b/src/main/java/reputation/node/tasks/CheckNodesServicesTask.java index 4afd68a..853ab85 100644 --- a/src/main/java/reputation/node/tasks/CheckNodesServicesTask.java +++ b/src/main/java/reputation/node/tasks/CheckNodesServicesTask.java @@ -80,7 +80,14 @@ public void run() { * Timer para aguardar as aceitar as respostas dos nós. */ new Timer() - .scheduleAtFixedRate(this.node.getWaitNodesResponsesTask(), 0, 1000); + .scheduleAtFixedRate( + new WaitNodesResponsesTask( + (this.node.getWaitNodesResponsesTaskTime() * 1000), + this.node + ), + 0, + 1000 + ); } catch (InterruptedException ie) { logger.warning( "Error trying to create a " + transactionTypeString + " transaction." From 2b6e3fe0f8caa58ae30ecb20844765623d9f77f9 Mon Sep 17 00:00:00 2001 From: AllanCapistrano Date: Thu, 16 Nov 2023 15:21:53 -0300 Subject: [PATCH 34/52] feat: create enableDevicesPage and starting to evaluating the nodes --- .../java/reputation/node/models/Node.java | 69 +++++++++++++++---- 1 file changed, 54 insertions(+), 15 deletions(-) diff --git a/src/main/java/reputation/node/models/Node.java b/src/main/java/reputation/node/models/Node.java index 87088f9..373626e 100644 --- a/src/main/java/reputation/node/models/Node.java +++ b/src/main/java/reputation/node/models/Node.java @@ -3,8 +3,6 @@ import br.uefs.larsid.extended.mapping.devices.services.IDevicePropertiesManager; import br.ufba.dcc.wiser.soft_iot.entities.Device; import br.ufba.dcc.wiser.soft_iot.entities.Sensor; -import br.ufba.dcc.wiser.soft_iot.entities.SensorData; -import com.google.gson.Gson; import com.google.gson.JsonObject; import com.google.gson.JsonParser; import com.google.gson.stream.JsonReader; @@ -65,8 +63,8 @@ public class Node implements NodeTypeService, ILedgerSubscriber { private TimerTask waitDeviceResponseTask; private ReentrantLock mutex = new ReentrantLock(); private ReentrantLock mutexNodesServices = new ReentrantLock(); - private String lastNodeServiceTransactionType = null; // TODO: Alterar de volta para 'null' quando terminar o processo - private boolean isRequestingNodeServices = false; // TODO: Alterar o valor para 'false' quando terminar o processo + private String lastNodeServiceTransactionType = null; + private boolean isRequestingNodeServices = false; private boolean canReceiveNodesResponse = false; private static final Logger logger = Logger.getLogger(Node.class.getName()); @@ -317,7 +315,7 @@ public void checkNodesReputation() { if (evaluationTransactions.isEmpty()) { reputation = 0.5; } else { - reputation = 0.0; // TODO: Implementar o cáculo da reputação e modificar essa variável. + reputation = 0.5; // TODO: Implementar o cáculo da reputação e modificar essa variável. } nodesReputations.add(new NodeReputation(nodeId, reputation)); @@ -377,13 +375,48 @@ public void checkNodesReputation() { } // TODO: Adicionar documentação - private void requestNodeService( // TODO: Tem um bug, isso aqui não está funcionando corretamente + private void enableDevicesPage( String nodeIp, String deviceId, String sensorId ) { + try { + URL url = new URL( + String.format( + "http://%s:8181/cxf/iot-service/devices/%s/%s", + nodeIp, + deviceId, + sensorId + ) + ); + HttpURLConnection conn = (HttpURLConnection) url.openConnection(); + + if (conn.getResponseCode() != HttpURLConnection.HTTP_OK) { + throw new RuntimeException( + "HTTP error code : " + conn.getResponseCode() + ); + } + + conn.disconnect(); + } catch (MalformedURLException mue) { + logger.severe(mue.getMessage()); + } catch (IOException ioe) { + logger.severe(ioe.getMessage()); + } + } + + // TODO: Adicionar documentação + private void requestNodeService( + String nodeIp, + String deviceId, + String sensorId + ) { + this.enableDevicesPage(nodeIp, deviceId, sensorId); + boolean isNullable = false; String response = null; + String sensorValue = null; + int evaluationValue = 0; try { URL url = new URL( @@ -427,20 +460,26 @@ private void requestNodeService( // TODO: Tem um bug, isso aqui não está funci JsonObject jsonObject = JsonParser.parseReader(reader).getAsJsonObject(); - Gson gson = new Gson(); - - SensorData sensorData = gson.fromJson(jsonObject, SensorData.class); - - // TODO: Remover - logger.info("-------------"); - logger.info(sensorData.getDevice().getId()); - logger.info(sensorData.getSensor().getId()); - logger.info(sensorData.getValue()); + sensorValue = jsonObject.get("value").getAsString(); } catch (MalformedURLException mue) { logger.severe(mue.getMessage()); } catch (IOException ioe) { logger.severe(ioe.getMessage()); } + + if (!isNullable && sensorValue != null) { // Providenciou o serviço. + evaluationValue = 1; + } + + // TODO: Está com um bug, a avaliação funcionou somente uma vez + try { + this.nodeType.getNode().evaluateServiceProvider(nodeIp, evaluationValue); // TODO: Está errado, é para ser nodeId + } catch (InterruptedException ie) { + logger.severe(ie.getStackTrace().toString()); + } + + this.setRequestingNodeServices(false); + this.setLastNodeServiceTransactionType(null); } /** From b0c66b9a2cc6763c9ee9486b2aa9c0522f92afd0 Mon Sep 17 00:00:00 2001 From: AllanCapistrano Date: Fri, 17 Nov 2023 14:53:07 -0300 Subject: [PATCH 35/52] fix: evatuation when request some node service --- .../java/reputation/node/models/Node.java | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/src/main/java/reputation/node/models/Node.java b/src/main/java/reputation/node/models/Node.java index 373626e..e40cbb7 100644 --- a/src/main/java/reputation/node/models/Node.java +++ b/src/main/java/reputation/node/models/Node.java @@ -363,6 +363,7 @@ public void checkNodesReputation() { // TODO: Calcular a reputação de todos os dispositivos, e enviar as informações do dispositivo com a maior reputação this.requestNodeService( + nodeWithService.getSource(), nodeWithService.getSourceIp(), nodeWithService.getServices().get(0).getDeviceId(), nodeWithService.getServices().get(0).getSensorId() @@ -389,12 +390,13 @@ private void enableDevicesPage( sensorId ) ); + HttpURLConnection conn = (HttpURLConnection) url.openConnection(); if (conn.getResponseCode() != HttpURLConnection.HTTP_OK) { - throw new RuntimeException( - "HTTP error code : " + conn.getResponseCode() - ); + conn.disconnect(); + + return; } conn.disconnect(); @@ -407,6 +409,7 @@ private void enableDevicesPage( // TODO: Adicionar documentação private void requestNodeService( + String nodeId, String nodeIp, String deviceId, String sensorId @@ -430,9 +433,10 @@ private void requestNodeService( HttpURLConnection conn = (HttpURLConnection) url.openConnection(); if (conn.getResponseCode() != HttpURLConnection.HTTP_OK) { - throw new RuntimeException( - "HTTP error code : " + conn.getResponseCode() - ); + logger.severe("HTTP error code : " + conn.getResponseCode()); + conn.disconnect(); + + return; } BufferedReader br = new BufferedReader( @@ -471,9 +475,8 @@ private void requestNodeService( evaluationValue = 1; } - // TODO: Está com um bug, a avaliação funcionou somente uma vez try { - this.nodeType.getNode().evaluateServiceProvider(nodeIp, evaluationValue); // TODO: Está errado, é para ser nodeId + this.nodeType.getNode().evaluateServiceProvider(nodeId, evaluationValue); } catch (InterruptedException ie) { logger.severe(ie.getStackTrace().toString()); } From 2deeb43046d98dc481a87f714b45228ecb5cfa44 Mon Sep 17 00:00:00 2001 From: AllanCapistrano Date: Fri, 17 Nov 2023 14:57:16 -0300 Subject: [PATCH 36/52] docs: add docs to enableDevicesPage and requestNodeService --- src/main/java/reputation/node/models/Node.java | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/src/main/java/reputation/node/models/Node.java b/src/main/java/reputation/node/models/Node.java index e40cbb7..0ab4a80 100644 --- a/src/main/java/reputation/node/models/Node.java +++ b/src/main/java/reputation/node/models/Node.java @@ -375,7 +375,13 @@ public void checkNodesReputation() { } } - // TODO: Adicionar documentação + /** + * Habilita a página dos dispositivos faz uma requisição para a mesma. + * + * @param nodeIp String - IP do nó em que o dispositivo está conectado. + * @param deviceId String - ID do dispositivo. + * @param sensorId String - ID do sensor. + */ private void enableDevicesPage( String nodeIp, String deviceId, @@ -407,7 +413,14 @@ private void enableDevicesPage( } } - // TODO: Adicionar documentação + /** + * Requisita e avalia o serviço de um determinado nó. + * + * @param nodeId - ID do nó que irá requisitar o serviço. + * @param nodeIp - IP do nó que irá requisitar o serviço. + * @param deviceId - ID do dispositivo que fornecerá o serviço. + * @param sensorId - ID do sensor que fornecerá o serviço. + */ private void requestNodeService( String nodeId, String nodeIp, @@ -434,6 +447,7 @@ private void requestNodeService( if (conn.getResponseCode() != HttpURLConnection.HTTP_OK) { logger.severe("HTTP error code : " + conn.getResponseCode()); + conn.disconnect(); return; From c43bf5ed732c96ea7a8fac3c20d6184a96c978bd Mon Sep 17 00:00:00 2001 From: AllanCapistrano Date: Fri, 17 Nov 2023 15:05:34 -0300 Subject: [PATCH 37/52] feat: create JsonStringToJsonObject class --- .../node/utils/JsonStringToJsonObject.java | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 src/main/java/reputation/node/utils/JsonStringToJsonObject.java diff --git a/src/main/java/reputation/node/utils/JsonStringToJsonObject.java b/src/main/java/reputation/node/utils/JsonStringToJsonObject.java new file mode 100644 index 0000000..a24d707 --- /dev/null +++ b/src/main/java/reputation/node/utils/JsonStringToJsonObject.java @@ -0,0 +1,31 @@ +package reputation.node.utils; + +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import com.google.gson.stream.JsonReader; +import java.io.StringReader; + +/** + * + * @author Allan Capistrano + * @version 1.0.0 + */ +public final class JsonStringToJsonObject { + + /** + * Converte um JSON que está no formato de String em um JSON Object da + * biblioteca gson. + * + * @param jsonInString String - JSON no formato de String + * @return JsonObject + */ + public static JsonObject convert(String jsonInString) { + JsonReader reader = new JsonReader(new StringReader(jsonInString)); + + reader.setLenient(true); + + JsonObject jsonObject = JsonParser.parseReader(reader).getAsJsonObject(); + + return jsonObject; + } +} From 2f7bfaebaf3dfdf0dc3ef6ebbe67fc04a7a5573c Mon Sep 17 00:00:00 2001 From: AllanCapistrano Date: Fri, 17 Nov 2023 15:06:03 -0300 Subject: [PATCH 38/52] chore: using JsonStringToJsonObject --- .../java/reputation/node/models/Node.java | 22 ++++++++----------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/src/main/java/reputation/node/models/Node.java b/src/main/java/reputation/node/models/Node.java index 0ab4a80..9fe8a42 100644 --- a/src/main/java/reputation/node/models/Node.java +++ b/src/main/java/reputation/node/models/Node.java @@ -4,8 +4,6 @@ import br.ufba.dcc.wiser.soft_iot.entities.Device; import br.ufba.dcc.wiser.soft_iot.entities.Sensor; import com.google.gson.JsonObject; -import com.google.gson.JsonParser; -import com.google.gson.stream.JsonReader; import dlt.client.tangle.hornet.enums.TransactionType; import dlt.client.tangle.hornet.model.DeviceSensorId; import dlt.client.tangle.hornet.model.transactions.IndexTransaction; @@ -17,7 +15,6 @@ import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; -import java.io.StringReader; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; @@ -38,6 +35,7 @@ import reputation.node.tasks.CheckNodesServicesTask; import reputation.node.tasks.RequestDataTask; import reputation.node.tasks.WaitDeviceResponseTask; +import reputation.node.utils.JsonStringToJsonObject; import reputation.node.utils.MQTTClient; /** @@ -427,13 +425,13 @@ private void requestNodeService( String deviceId, String sensorId ) { - this.enableDevicesPage(nodeIp, deviceId, sensorId); - boolean isNullable = false; String response = null; String sensorValue = null; int evaluationValue = 0; + this.enableDevicesPage(nodeIp, deviceId, sensorId); + try { URL url = new URL( String.format( @@ -447,7 +445,7 @@ private void requestNodeService( if (conn.getResponseCode() != HttpURLConnection.HTTP_OK) { logger.severe("HTTP error code : " + conn.getResponseCode()); - + conn.disconnect(); return; @@ -471,12 +469,7 @@ private void requestNodeService( conn.disconnect(); - // TODO: Colocar essa conversão em uma função - JsonReader reader = new JsonReader(new StringReader(response)); - - reader.setLenient(true); - - JsonObject jsonObject = JsonParser.parseReader(reader).getAsJsonObject(); + JsonObject jsonObject = JsonStringToJsonObject.convert(response); sensorValue = jsonObject.get("value").getAsString(); } catch (MalformedURLException mue) { @@ -485,10 +478,13 @@ private void requestNodeService( logger.severe(ioe.getMessage()); } - if (!isNullable && sensorValue != null) { // Providenciou o serviço. + if (!isNullable && sensorValue != null) { // Prestou o serviço. evaluationValue = 1; } + /** + * Avaliando o serviço prestado pelo nó. + */ try { this.nodeType.getNode().evaluateServiceProvider(nodeId, evaluationValue); } catch (InterruptedException ie) { From 8730544b373834d7f196d279602bf92289bffc9d Mon Sep 17 00:00:00 2001 From: AllanCapistrano Date: Fri, 17 Nov 2023 15:21:31 -0300 Subject: [PATCH 39/52] refactor: start and publishNodeServices methods --- .../java/reputation/node/models/Node.java | 92 +++++++------------ 1 file changed, 35 insertions(+), 57 deletions(-) diff --git a/src/main/java/reputation/node/models/Node.java b/src/main/java/reputation/node/models/Node.java index 9fe8a42..c6b3546 100644 --- a/src/main/java/reputation/node/models/Node.java +++ b/src/main/java/reputation/node/models/Node.java @@ -77,25 +77,8 @@ public void start() { this.devices = new ArrayList<>(); this.nodesWithServices = new ArrayList<>(); this.listenerDevices = new ListenerDevices(this.MQTTClient, this); - new Timer() - .scheduleAtFixedRate( - new CheckDevicesTask(this), - 0, - this.checkDeviceTaskTime * 1000 - ); - new Timer() - .scheduleAtFixedRate( - new RequestDataTask(this), - 0, - this.requestDataTaskTime * 1000 - ); - new Timer() - .scheduleAtFixedRate( - new CheckNodesServicesTask(this), - 0, - this.checkNodesServicesTaskTime * 1000 - ); + this.createTasks(); this.subscribeToTransactionsTopics(); } @@ -178,7 +161,7 @@ private void publishNodeServices(String serviceType, String target) { logger.info("Requested service type: " + serviceType); Transaction transaction = null; - TransactionType transactionType; + TransactionType transactionType = null; String transactionTypeInString = null; List deviceSensorIdList = new ArrayList<>(); @@ -202,57 +185,25 @@ private void publishNodeServices(String serviceType, String target) { serviceType.equals(NodeServiceType.HUMIDITY_SENSOR.getDescription()) ) { transactionType = TransactionType.REP_SVC_HUMIDITY_SENSOR; - - transaction = - new ReputationService( - this.nodeType.getNodeId(), - this.nodeType.getNodeIp(), - target, - deviceSensorIdList, - this.nodeType.getNodeGroup(), - transactionType - ); - - transactionTypeInString = transactionType.name(); } else if ( serviceType.equals(NodeServiceType.PULSE_OXYMETER.getDescription()) ) { transactionType = TransactionType.REP_SVC_PULSE_OXYMETER; - - transaction = - new ReputationService( - this.nodeType.getNodeId(), - this.nodeType.getNodeIp(), - target, - deviceSensorIdList, - this.nodeType.getNodeGroup(), - transactionType - ); - - transactionTypeInString = transactionType.name(); } else if ( serviceType.equals(NodeServiceType.THERMOMETER.getDescription()) ) { transactionType = TransactionType.REP_SVC_THERMOMETER; - - transaction = - new ReputationService( - this.nodeType.getNodeId(), - this.nodeType.getNodeIp(), - target, - deviceSensorIdList, - this.nodeType.getNodeGroup(), - transactionType - ); - - transactionTypeInString = transactionType.name(); } else if ( serviceType.equals( NodeServiceType.WIND_DIRECTION_SENSOR.getDescription() ) ) { transactionType = TransactionType.REP_SVC_WIND_DIRECTION_SENSOR; + } else { + logger.severe("Unknown service type."); + } + if (transactionType != null) { transaction = new ReputationService( this.nodeType.getNodeId(), @@ -264,8 +215,6 @@ private void publishNodeServices(String serviceType, String target) { ); transactionTypeInString = transactionType.name(); - } else { - logger.severe("Unknown service type."); } /* @@ -541,6 +490,30 @@ private void unsubscribeToTransactionsTopics() { ); } + /** + * Cria todas as tasks que serão usadas pelo bundle. + */ + private void createTasks() { + new Timer() + .scheduleAtFixedRate( + new CheckDevicesTask(this), + 0, + this.checkDeviceTaskTime * 1000 + ); + new Timer() + .scheduleAtFixedRate( + new RequestDataTask(this), + 0, + this.requestDataTaskTime * 1000 + ); + new Timer() + .scheduleAtFixedRate( + new CheckNodesServicesTask(this), + 0, + this.checkNodesServicesTaskTime * 1000 + ); + } + /** * Se inscreve nos tópicos dos novos dispositivos. * @@ -558,6 +531,9 @@ private void subscribeToDevicesTopics(int amountNewDevices) { } } + /** + * Responsável por lidar com as mensagens recebidas pelo ZMQ (MQTT). + */ @Override public void update(Object object, Object object2) { /** @@ -635,6 +611,8 @@ public void update(Object object, Object object2) { } } + /*------------------------- Getters e Setters -----------------------------*/ + public MQTTClient getMQTTClient() { return MQTTClient; } From 0c4358123ef2312438d81166dfd9e19b52751b97 Mon Sep 17 00:00:00 2001 From: AllanCapistrano Date: Sat, 25 Nov 2023 10:45:12 -0300 Subject: [PATCH 40/52] chore: change class name --- src/main/java/reputation/node/models/Node.java | 6 +++--- ...{NodeReputation.java => ThingReputation.java} | 16 ++++++++-------- 2 files changed, 11 insertions(+), 11 deletions(-) rename src/main/java/reputation/node/models/{NodeReputation.java => ThingReputation.java} (61%) diff --git a/src/main/java/reputation/node/models/Node.java b/src/main/java/reputation/node/models/Node.java index c6b3546..e6036ef 100644 --- a/src/main/java/reputation/node/models/Node.java +++ b/src/main/java/reputation/node/models/Node.java @@ -241,7 +241,7 @@ private void publishNodeServices(String serviceType, String target) { * Verifica a reputação dos nós que responderam a requisição de serviço. */ public void checkNodesReputation() { - List nodesReputations = new ArrayList<>(); + List nodesReputations = new ArrayList<>(); Double reputation; Double highestReputation = 0.0; String highestReputationNodeId = null; @@ -265,7 +265,7 @@ public void checkNodesReputation() { reputation = 0.5; // TODO: Implementar o cáculo da reputação e modificar essa variável. } - nodesReputations.add(new NodeReputation(nodeId, reputation)); + nodesReputations.add(new ThingReputation(nodeId, reputation)); if (reputation > highestReputation) { highestReputation = reputation; @@ -277,7 +277,7 @@ public void checkNodesReputation() { /** * Verificando quais nós possuem a maior reputação. */ - List temp = nodesReputations + List temp = nodesReputations .stream() .filter(nr -> nr.getReputation().equals(innerHighestReputation)) .collect(Collectors.toList()); diff --git a/src/main/java/reputation/node/models/NodeReputation.java b/src/main/java/reputation/node/models/ThingReputation.java similarity index 61% rename from src/main/java/reputation/node/models/NodeReputation.java rename to src/main/java/reputation/node/models/ThingReputation.java index 1f04eaa..5eb34da 100644 --- a/src/main/java/reputation/node/models/NodeReputation.java +++ b/src/main/java/reputation/node/models/ThingReputation.java @@ -5,28 +5,28 @@ * @author Allan Capistrano * @version 1.0.0 */ -public class NodeReputation { +public class ThingReputation { - private String nodeId; + private String thingId; private Double reputation; /** * Método construtor. * - * @param nodeId String - ID do nó. + * @param thingId String - Identificador. * @param reputation Double - Reputação do nó. */ - public NodeReputation(String nodeId, Double reputation) { - this.nodeId = nodeId; + public ThingReputation(String thingId, Double reputation) { + this.thingId = thingId; this.reputation = reputation; } public String getNodeId() { - return nodeId; + return thingId; } - public void setNodeId(String nodeId) { - this.nodeId = nodeId; + public void setNodeId(String thingId) { + this.thingId = thingId; } public Double getReputation() { From ade96d81189d96d28ab21c9d9cb8c22b3897cf04 Mon Sep 17 00:00:00 2001 From: AllanCapistrano Date: Sat, 25 Nov 2023 11:19:55 -0300 Subject: [PATCH 41/52] chore: update get and set method name --- src/main/java/reputation/node/models/ThingReputation.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/reputation/node/models/ThingReputation.java b/src/main/java/reputation/node/models/ThingReputation.java index 5eb34da..3e467c1 100644 --- a/src/main/java/reputation/node/models/ThingReputation.java +++ b/src/main/java/reputation/node/models/ThingReputation.java @@ -21,11 +21,11 @@ public ThingReputation(String thingId, Double reputation) { this.reputation = reputation; } - public String getNodeId() { + public String getThingId() { return thingId; } - public void setNodeId(String thingId) { + public void setThingId(String thingId) { this.thingId = thingId; } From 4511fe0d5806bc4ec61676f057bb64242c1f128f Mon Sep 17 00:00:00 2001 From: AllanCapistrano Date: Sun, 26 Nov 2023 09:33:48 -0300 Subject: [PATCH 42/52] feat: create getDeviceWithHighestReputation method --- .../java/reputation/node/models/Node.java | 91 ++++++++++++++++++- 1 file changed, 86 insertions(+), 5 deletions(-) diff --git a/src/main/java/reputation/node/models/Node.java b/src/main/java/reputation/node/models/Node.java index e6036ef..54308f4 100644 --- a/src/main/java/reputation/node/models/Node.java +++ b/src/main/java/reputation/node/models/Node.java @@ -240,6 +240,7 @@ private void publishNodeServices(String serviceType, String target) { /** * Verifica a reputação dos nós que responderam a requisição de serviço. */ + // TODO: Refatorar código para separar as responsabilidades. Checagem do nó, e requsiição de fato do serviço public void checkNodesReputation() { List nodesReputations = new ArrayList<>(); Double reputation; @@ -286,11 +287,11 @@ public void checkNodesReputation() { * Obtendo o ID de um dos nós com a maior reputação. */ if (temp.size() == 0) { - highestReputationNodeId = temp.get(0).getNodeId(); + highestReputationNodeId = temp.get(0).getThingId(); } else if (temp.size() > 0) { int randomIndex = new Random().nextInt(temp.size()); - highestReputationNodeId = temp.get(randomIndex).getNodeId(); + highestReputationNodeId = temp.get(randomIndex).getThingId(); } else { logger.severe("Invalid amount of nodes with the highest reputation."); } @@ -308,12 +309,14 @@ public void checkNodesReputation() { .collect(Collectors.toList()) .get(0); - // TODO: Calcular a reputação de todos os dispositivos, e enviar as informações do dispositivo com a maior reputação + DeviceSensorId deviceSensorId = + this.getDeviceWithHighestReputation(nodeWithService.getServices()); + this.requestNodeService( nodeWithService.getSource(), nodeWithService.getSourceIp(), - nodeWithService.getServices().get(0).getDeviceId(), - nodeWithService.getServices().get(0).getSensorId() + deviceSensorId.getDeviceId(), + deviceSensorId.getSensorId() ); } else { this.setRequestingNodeServices(false); @@ -322,6 +325,84 @@ public void checkNodesReputation() { } } + // TODO: Adicionar documentação + private DeviceSensorId getDeviceWithHighestReputation( + List deviceSensorIdList + ) { + List devicesReputations = new ArrayList<>(); + Double reputation; + Double highestReputation = 0.0; + DeviceSensorId highestReputationDeviceSensorId = null; + + if (deviceSensorIdList.size() > 1) { + /** + * Salvando a reputação de cada dispositivo em uma lista. + */ + for (DeviceSensorId deviceSensorId : deviceSensorIdList) { + List evaluationTransactions = + this.ledgerConnector.getLedgerReader() + .getTransactionsByIndex(deviceSensorId.getDeviceId()); + + if (evaluationTransactions.isEmpty()) { + reputation = 0.5; + } else { + reputation = 0.5; // TODO: Implementar o cáculo da reputação dos dispositivos e modificar essa variável. + } + + devicesReputations.add( + new ThingReputation( + String.format( + "%s@%s", // Formato: deviceId@sensorId + deviceSensorId.getDeviceId(), + deviceSensorId.getSensorId() + ), + reputation + ) + ); + + if (reputation > highestReputation) { + highestReputation = reputation; + } + } + + final Double innerHighestReputation = Double.valueOf(highestReputation); + + /** + * Verificando quais dispositivos possuem a maior reputação. + */ + List temp = devicesReputations + .stream() + .filter(nr -> nr.getReputation().equals(innerHighestReputation)) + .collect(Collectors.toList()); + + int index = -1; + + /** + * Obtendo o ID de um dos dispositivos com a maior reputação. + */ + if (temp.size() == 0) { + index = 0; + } else if (temp.size() > 0) { + index = new Random().nextInt(temp.size()); + } else { + logger.severe("Invalid amount of devices with the highest reputation."); + } + + if (index != -1) { + String[] tempIds = temp.get(index).getThingId().split("@"); + + highestReputationDeviceSensorId = + new DeviceSensorId(tempIds[0], tempIds[1]); + } + } else if (deviceSensorIdList.size() == 1) { + highestReputationDeviceSensorId = deviceSensorIdList.get(0); + } else { + logger.severe("Invalid amount of devices."); + } + + return highestReputationDeviceSensorId; + } + /** * Habilita a página dos dispositivos faz uma requisição para a mesma. * From 6d36bc6bed38c18d3097362379a2cf0c991378b4 Mon Sep 17 00:00:00 2001 From: AllanCapistrano Date: Sun, 26 Nov 2023 09:36:37 -0300 Subject: [PATCH 43/52] docs: add docs to getDeviceWithHighestReputation --- src/main/java/reputation/node/models/Node.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/main/java/reputation/node/models/Node.java b/src/main/java/reputation/node/models/Node.java index 54308f4..a26160b 100644 --- a/src/main/java/reputation/node/models/Node.java +++ b/src/main/java/reputation/node/models/Node.java @@ -325,7 +325,13 @@ public void checkNodesReputation() { } } - // TODO: Adicionar documentação + /** + * Obtém os IDs do dispositivo e do sensor, com a maior reputação. + * + * @param deviceSensorIdList List - Lista com os IDs do + * dispositivo e sensor que se deseja obter o maior. + * @return DeviceSensorId + */ private DeviceSensorId getDeviceWithHighestReputation( List deviceSensorIdList ) { From e386db57f7b040db10fd8e144712b3e0569bf31b Mon Sep 17 00:00:00 2001 From: AllanCapistrano Date: Sun, 26 Nov 2023 09:45:26 -0300 Subject: [PATCH 44/52] chore: renaming method --- src/main/java/reputation/node/models/Node.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/reputation/node/models/Node.java b/src/main/java/reputation/node/models/Node.java index a26160b..dd54618 100644 --- a/src/main/java/reputation/node/models/Node.java +++ b/src/main/java/reputation/node/models/Node.java @@ -312,7 +312,7 @@ public void checkNodesReputation() { DeviceSensorId deviceSensorId = this.getDeviceWithHighestReputation(nodeWithService.getServices()); - this.requestNodeService( + this.requestAndEvaluateNodeService( nodeWithService.getSource(), nodeWithService.getSourceIp(), deviceSensorId.getDeviceId(), @@ -455,7 +455,7 @@ private void enableDevicesPage( * @param deviceId - ID do dispositivo que fornecerá o serviço. * @param sensorId - ID do sensor que fornecerá o serviço. */ - private void requestNodeService( + private void requestAndEvaluateNodeService( String nodeId, String nodeIp, String deviceId, From 67f37cdffad42f21a2abe26726a511c2b3f36536 Mon Sep 17 00:00:00 2001 From: AllanCapistrano Date: Sun, 26 Nov 2023 10:01:23 -0300 Subject: [PATCH 45/52] refactor: usenodeService method --- .../java/reputation/node/models/Node.java | 116 ++++++++++-------- .../node/tasks/WaitNodesResponsesTask.java | 6 +- 2 files changed, 67 insertions(+), 55 deletions(-) diff --git a/src/main/java/reputation/node/models/Node.java b/src/main/java/reputation/node/models/Node.java index dd54618..3f2adf5 100644 --- a/src/main/java/reputation/node/models/Node.java +++ b/src/main/java/reputation/node/models/Node.java @@ -238,63 +238,15 @@ private void publishNodeServices(String serviceType, String target) { } /** - * Verifica a reputação dos nós que responderam a requisição de serviço. + * Faz uso do serviço do nó com a maior reputação dentre aqueles que + * responderam a requisição, e ao final avalia-o. */ - // TODO: Refatorar código para separar as responsabilidades. Checagem do nó, e requsiição de fato do serviço - public void checkNodesReputation() { - List nodesReputations = new ArrayList<>(); - Double reputation; - Double highestReputation = 0.0; - String highestReputationNodeId = null; - + public void useNodeService() { if (this.nodesWithServices.isEmpty()) { this.setRequestingNodeServices(false); this.setLastNodeServiceTransactionType(null); } else { - /** - * Salvando a reputação de cada nó em uma lista. - */ - for (Transaction nodeWithService : this.nodesWithServices) { - String nodeId = nodeWithService.getSource(); - - List evaluationTransactions = - this.ledgerConnector.getLedgerReader().getTransactionsByIndex(nodeId); - - if (evaluationTransactions.isEmpty()) { - reputation = 0.5; - } else { - reputation = 0.5; // TODO: Implementar o cáculo da reputação e modificar essa variável. - } - - nodesReputations.add(new ThingReputation(nodeId, reputation)); - - if (reputation > highestReputation) { - highestReputation = reputation; - } - } - - final Double innerHighestReputation = Double.valueOf(highestReputation); - - /** - * Verificando quais nós possuem a maior reputação. - */ - List temp = nodesReputations - .stream() - .filter(nr -> nr.getReputation().equals(innerHighestReputation)) - .collect(Collectors.toList()); - - /** - * Obtendo o ID de um dos nós com a maior reputação. - */ - if (temp.size() == 0) { - highestReputationNodeId = temp.get(0).getThingId(); - } else if (temp.size() > 0) { - int randomIndex = new Random().nextInt(temp.size()); - - highestReputationNodeId = temp.get(randomIndex).getThingId(); - } else { - logger.severe("Invalid amount of nodes with the highest reputation."); - } + String highestReputationNodeId = this.getNodeIdWithHighestReputation(); if (highestReputationNodeId != null) { final String innerHighestReputationNodeId = String.valueOf( @@ -325,6 +277,66 @@ public void checkNodesReputation() { } } + /** + * Obtém o ID do nó com a maior reputação dentre aqueles que reponderam a + * requisição. + * + * @return String + */ + private String getNodeIdWithHighestReputation() { + List nodesReputations = new ArrayList<>(); + Double reputation; + Double highestReputation = 0.0; + String highestReputationNodeId = null; + + /** + * Salvando a reputação de cada nó em uma lista. + */ + for (Transaction nodeWithService : this.nodesWithServices) { + String nodeId = nodeWithService.getSource(); + + List evaluationTransactions = + this.ledgerConnector.getLedgerReader().getTransactionsByIndex(nodeId); + + if (evaluationTransactions.isEmpty()) { + reputation = 0.5; + } else { + reputation = 0.5; // TODO: Implementar o cáculo da reputação e modificar essa variável. + } + + nodesReputations.add(new ThingReputation(nodeId, reputation)); + + if (reputation > highestReputation) { + highestReputation = reputation; + } + } + + final Double innerHighestReputation = Double.valueOf(highestReputation); + + /** + * Verificando quais nós possuem a maior reputação. + */ + List temp = nodesReputations + .stream() + .filter(nr -> nr.getReputation().equals(innerHighestReputation)) + .collect(Collectors.toList()); + + /** + * Obtendo o ID de um dos nós com a maior reputação. + */ + if (temp.size() == 0) { + highestReputationNodeId = temp.get(0).getThingId(); + } else if (temp.size() > 0) { + int randomIndex = new Random().nextInt(temp.size()); + + highestReputationNodeId = temp.get(randomIndex).getThingId(); + } else { + logger.severe("Invalid amount of nodes with the highest reputation."); + } + + return highestReputationNodeId; + } + /** * Obtém os IDs do dispositivo e do sensor, com a maior reputação. * diff --git a/src/main/java/reputation/node/tasks/WaitNodesResponsesTask.java b/src/main/java/reputation/node/tasks/WaitNodesResponsesTask.java index 311d204..0a6157f 100644 --- a/src/main/java/reputation/node/tasks/WaitNodesResponsesTask.java +++ b/src/main/java/reputation/node/tasks/WaitNodesResponsesTask.java @@ -45,10 +45,10 @@ public void run() { this.node.setCanReceiveNodesResponse(false); /** - * Verificando a reputação dos nós que responderam a requisição de - * serviço. + * Usando e avaliando o serviço do nó com a maior reputação, e + * avaliando-o. */ - this.node.checkNodesReputation(); + this.node.useNodeService(); this.cancel(); } From 9b1503d689d2df5a6e63a493aa1ef61b1e3b79b2 Mon Sep 17 00:00:00 2001 From: AllanCapistrano Date: Sun, 26 Nov 2023 11:08:06 -0300 Subject: [PATCH 46/52] fix: thing id with highest reputation index --- .../java/reputation/node/models/Node.java | 26 +++++++++++++++---- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/src/main/java/reputation/node/models/Node.java b/src/main/java/reputation/node/models/Node.java index 3f2adf5..6a7b10b 100644 --- a/src/main/java/reputation/node/models/Node.java +++ b/src/main/java/reputation/node/models/Node.java @@ -29,6 +29,8 @@ import node.type.services.INodeType; import reputation.node.enums.NodeServiceType; import reputation.node.mqtt.ListenerDevices; +import reputation.node.reputation.IReputationCalc; +import reputation.node.reputation.ReputationCalc; import reputation.node.services.NodeTypeService; import reputation.node.tangle.LedgerConnector; import reputation.node.tasks.CheckDevicesTask; @@ -299,11 +301,17 @@ private String getNodeIdWithHighestReputation() { this.ledgerConnector.getLedgerReader().getTransactionsByIndex(nodeId); if (evaluationTransactions.isEmpty()) { + logger.info("Não era para entrar aqui 1!"); reputation = 0.5; } else { + logger.info("AAAAAA"); // TODO: Remover + IReputationCalc reputationCalc = new ReputationCalc(); reputation = 0.5; // TODO: Implementar o cáculo da reputação e modificar essa variável. + // reputation = reputationCalc.calc(evaluationTransactions); } + logger.info(reputation.toString()); // TODO: Remover + nodesReputations.add(new ThingReputation(nodeId, reputation)); if (reputation > highestReputation) { @@ -324,9 +332,9 @@ private String getNodeIdWithHighestReputation() { /** * Obtendo o ID de um dos nós com a maior reputação. */ - if (temp.size() == 0) { + if (temp.size() == 1) { highestReputationNodeId = temp.get(0).getThingId(); - } else if (temp.size() > 0) { + } else if (temp.size() > 1) { int randomIndex = new Random().nextInt(temp.size()); highestReputationNodeId = temp.get(randomIndex).getThingId(); @@ -362,11 +370,17 @@ private DeviceSensorId getDeviceWithHighestReputation( .getTransactionsByIndex(deviceSensorId.getDeviceId()); if (evaluationTransactions.isEmpty()) { + logger.info("Não era para entrar aqui 2!"); reputation = 0.5; } else { - reputation = 0.5; // TODO: Implementar o cáculo da reputação dos dispositivos e modificar essa variável. + logger.info("BBBBBBB"); // TODO: Remover + IReputationCalc reputationCalc = new ReputationCalc(); + reputation = 0.5; // TODO: Implementar o cáculo da reputação e modificar essa variável. + // reputation = reputationCalc.calc(evaluationTransactions); } + logger.info(reputation.toString()); // TODO: Remover + devicesReputations.add( new ThingReputation( String.format( @@ -384,6 +398,8 @@ private DeviceSensorId getDeviceWithHighestReputation( } final Double innerHighestReputation = Double.valueOf(highestReputation); + logger.info("CCCCCC"); + logger.info(innerHighestReputation.toString()); /** * Verificando quais dispositivos possuem a maior reputação. @@ -398,9 +414,9 @@ private DeviceSensorId getDeviceWithHighestReputation( /** * Obtendo o ID de um dos dispositivos com a maior reputação. */ - if (temp.size() == 0) { + if (temp.size() == 1) { index = 0; - } else if (temp.size() > 0) { + } else if (temp.size() > 1) { index = new Random().nextInt(temp.size()); } else { logger.severe("Invalid amount of devices with the highest reputation."); From f5eb5c19706e5b25f5622fe78db5350a891f0bdd Mon Sep 17 00:00:00 2001 From: AllanCapistrano Date: Sun, 26 Nov 2023 11:08:38 -0300 Subject: [PATCH 47/52] feat: create ReputationCalc class and interface --- .../node/reputation/IReputationCalc.java | 22 ++++++++++++++++ .../node/reputation/ReputationCalc.java | 25 +++++++++++++++++++ 2 files changed, 47 insertions(+) create mode 100644 src/main/java/reputation/node/reputation/IReputationCalc.java create mode 100644 src/main/java/reputation/node/reputation/ReputationCalc.java diff --git a/src/main/java/reputation/node/reputation/IReputationCalc.java b/src/main/java/reputation/node/reputation/IReputationCalc.java new file mode 100644 index 0000000..10c11d2 --- /dev/null +++ b/src/main/java/reputation/node/reputation/IReputationCalc.java @@ -0,0 +1,22 @@ +package reputation.node.reputation; + +import java.util.List; + +import dlt.client.tangle.hornet.model.transactions.Transaction; + +/** + * + * @author Allan Capistrano + * @version 1.0.0 + */ +public interface IReputationCalc { + + /** + * Calcula a reputação de uma coisa. + * + * @param evaluationTransactions List - Lista com as transações + * de avaliação da coisa. + * @return Double + */ + Double calc(List evaluationTransactions); +} diff --git a/src/main/java/reputation/node/reputation/ReputationCalc.java b/src/main/java/reputation/node/reputation/ReputationCalc.java new file mode 100644 index 0000000..3c60f53 --- /dev/null +++ b/src/main/java/reputation/node/reputation/ReputationCalc.java @@ -0,0 +1,25 @@ +package reputation.node.reputation; + +import dlt.client.tangle.hornet.model.transactions.Transaction; +import dlt.client.tangle.hornet.model.transactions.reputation.Evaluation; +import java.util.List; + +/** + * Responsável por calcular a reputação de uma coisa. + * + * @author Allan Capistrano + * @version 1.0.0 + */ +public class ReputationCalc implements IReputationCalc { + + @Override + public Double calc(List evaluationTransactions) { + // TODO: Implementar z-scores para verificar se um valor não está destoante da média + + return evaluationTransactions + .stream() + .mapToInt(et -> ((Evaluation) et).getValue()) + .average() + .orElse(0.0); + } +} From 68ace07594cf6fd83724b8724dcf801d64d33639 Mon Sep 17 00:00:00 2001 From: AllanCapistrano Date: Mon, 27 Nov 2023 10:36:08 -0300 Subject: [PATCH 48/52] chore: using reputation calc --- src/main/java/reputation/node/models/Node.java | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/main/java/reputation/node/models/Node.java b/src/main/java/reputation/node/models/Node.java index 6a7b10b..fd071d4 100644 --- a/src/main/java/reputation/node/models/Node.java +++ b/src/main/java/reputation/node/models/Node.java @@ -306,8 +306,8 @@ private String getNodeIdWithHighestReputation() { } else { logger.info("AAAAAA"); // TODO: Remover IReputationCalc reputationCalc = new ReputationCalc(); - reputation = 0.5; // TODO: Implementar o cáculo da reputação e modificar essa variável. - // reputation = reputationCalc.calc(evaluationTransactions); + // reputation = 0.5; // TODO: Implementar o cáculo da reputação e modificar essa variável. + reputation = reputationCalc.calc(evaluationTransactions); } logger.info(reputation.toString()); // TODO: Remover @@ -375,8 +375,8 @@ private DeviceSensorId getDeviceWithHighestReputation( } else { logger.info("BBBBBBB"); // TODO: Remover IReputationCalc reputationCalc = new ReputationCalc(); - reputation = 0.5; // TODO: Implementar o cáculo da reputação e modificar essa variável. - // reputation = reputationCalc.calc(evaluationTransactions); + // reputation = 0.5; // TODO: Implementar o cáculo da reputação e modificar essa variável. + reputation = reputationCalc.calc(evaluationTransactions); } logger.info(reputation.toString()); // TODO: Remover @@ -409,6 +409,9 @@ private DeviceSensorId getDeviceWithHighestReputation( .filter(nr -> nr.getReputation().equals(innerHighestReputation)) .collect(Collectors.toList()); + logger.info("DDDDDDD"); + logger.info(String.valueOf(temp.size())); + int index = -1; /** @@ -422,12 +425,16 @@ private DeviceSensorId getDeviceWithHighestReputation( logger.severe("Invalid amount of devices with the highest reputation."); } + logger.info("EEEEEEE"); + if (index != -1) { String[] tempIds = temp.get(index).getThingId().split("@"); highestReputationDeviceSensorId = new DeviceSensorId(tempIds[0], tempIds[1]); } + + logger.info("FFFFFFFF"); } else if (deviceSensorIdList.size() == 1) { highestReputationDeviceSensorId = deviceSensorIdList.get(0); } else { From 6af6bf0e97dc40ee646705edab4cbc4c93645833 Mon Sep 17 00:00:00 2001 From: AllanCapistrano Date: Mon, 27 Nov 2023 10:56:24 -0300 Subject: [PATCH 49/52] fix: starvation problem on the device list --- .../java/reputation/node/models/Node.java | 41 ++++++------------- 1 file changed, 13 insertions(+), 28 deletions(-) diff --git a/src/main/java/reputation/node/models/Node.java b/src/main/java/reputation/node/models/Node.java index fd071d4..12c6c02 100644 --- a/src/main/java/reputation/node/models/Node.java +++ b/src/main/java/reputation/node/models/Node.java @@ -165,24 +165,27 @@ private void publishNodeServices(String serviceType, String target) { Transaction transaction = null; TransactionType transactionType = null; String transactionTypeInString = null; - + List tempDevices = new ArrayList<>(); List deviceSensorIdList = new ArrayList<>(); try { this.mutex.lock(); - for (Device d : this.devices) { - d - .getSensors() - .stream() - .filter(s -> s.getType().equals(serviceType)) - .forEach(s -> - deviceSensorIdList.add(new DeviceSensorId(d.getId(), s.getId())) - ); - } + /* Cópia temporária para liberar a lista de dispositivos. */ + tempDevices.addAll(this.devices); } finally { this.mutex.unlock(); } + for (Device d : tempDevices) { + d + .getSensors() + .stream() + .filter(s -> s.getType().equals(serviceType)) + .forEach(s -> + deviceSensorIdList.add(new DeviceSensorId(d.getId(), s.getId())) + ); + } + if ( serviceType.equals(NodeServiceType.HUMIDITY_SENSOR.getDescription()) ) { @@ -301,17 +304,12 @@ private String getNodeIdWithHighestReputation() { this.ledgerConnector.getLedgerReader().getTransactionsByIndex(nodeId); if (evaluationTransactions.isEmpty()) { - logger.info("Não era para entrar aqui 1!"); reputation = 0.5; } else { - logger.info("AAAAAA"); // TODO: Remover IReputationCalc reputationCalc = new ReputationCalc(); - // reputation = 0.5; // TODO: Implementar o cáculo da reputação e modificar essa variável. reputation = reputationCalc.calc(evaluationTransactions); } - logger.info(reputation.toString()); // TODO: Remover - nodesReputations.add(new ThingReputation(nodeId, reputation)); if (reputation > highestReputation) { @@ -370,17 +368,12 @@ private DeviceSensorId getDeviceWithHighestReputation( .getTransactionsByIndex(deviceSensorId.getDeviceId()); if (evaluationTransactions.isEmpty()) { - logger.info("Não era para entrar aqui 2!"); reputation = 0.5; } else { - logger.info("BBBBBBB"); // TODO: Remover IReputationCalc reputationCalc = new ReputationCalc(); - // reputation = 0.5; // TODO: Implementar o cáculo da reputação e modificar essa variável. reputation = reputationCalc.calc(evaluationTransactions); } - logger.info(reputation.toString()); // TODO: Remover - devicesReputations.add( new ThingReputation( String.format( @@ -398,8 +391,6 @@ private DeviceSensorId getDeviceWithHighestReputation( } final Double innerHighestReputation = Double.valueOf(highestReputation); - logger.info("CCCCCC"); - logger.info(innerHighestReputation.toString()); /** * Verificando quais dispositivos possuem a maior reputação. @@ -409,9 +400,6 @@ private DeviceSensorId getDeviceWithHighestReputation( .filter(nr -> nr.getReputation().equals(innerHighestReputation)) .collect(Collectors.toList()); - logger.info("DDDDDDD"); - logger.info(String.valueOf(temp.size())); - int index = -1; /** @@ -425,8 +413,6 @@ private DeviceSensorId getDeviceWithHighestReputation( logger.severe("Invalid amount of devices with the highest reputation."); } - logger.info("EEEEEEE"); - if (index != -1) { String[] tempIds = temp.get(index).getThingId().split("@"); @@ -434,7 +420,6 @@ private DeviceSensorId getDeviceWithHighestReputation( new DeviceSensorId(tempIds[0], tempIds[1]); } - logger.info("FFFFFFFF"); } else if (deviceSensorIdList.size() == 1) { highestReputationDeviceSensorId = deviceSensorIdList.get(0); } else { From bd3e1611f8a94a8e19b394caa637d5ee0bf552f5 Mon Sep 17 00:00:00 2001 From: AllanCapistrano Date: Mon, 27 Nov 2023 11:48:36 -0300 Subject: [PATCH 50/52] chore: disabling evaluation JSON messages view --- src/main/java/reputation/node/models/Node.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/reputation/node/models/Node.java b/src/main/java/reputation/node/models/Node.java index 12c6c02..bb845ac 100644 --- a/src/main/java/reputation/node/models/Node.java +++ b/src/main/java/reputation/node/models/Node.java @@ -301,7 +301,8 @@ private String getNodeIdWithHighestReputation() { String nodeId = nodeWithService.getSource(); List evaluationTransactions = - this.ledgerConnector.getLedgerReader().getTransactionsByIndex(nodeId); + this.ledgerConnector.getLedgerReader() + .getTransactionsByIndex(nodeId, false); if (evaluationTransactions.isEmpty()) { reputation = 0.5; @@ -365,7 +366,7 @@ private DeviceSensorId getDeviceWithHighestReputation( for (DeviceSensorId deviceSensorId : deviceSensorIdList) { List evaluationTransactions = this.ledgerConnector.getLedgerReader() - .getTransactionsByIndex(deviceSensorId.getDeviceId()); + .getTransactionsByIndex(deviceSensorId.getDeviceId(), false); if (evaluationTransactions.isEmpty()) { reputation = 0.5; @@ -419,7 +420,6 @@ private DeviceSensorId getDeviceWithHighestReputation( highestReputationDeviceSensorId = new DeviceSensorId(tempIds[0], tempIds[1]); } - } else if (deviceSensorIdList.size() == 1) { highestReputationDeviceSensorId = deviceSensorIdList.get(0); } else { From 6f941c42e8171395ed4f670bfbfb365f15d5a5c8 Mon Sep 17 00:00:00 2001 From: AllanCapistrano Date: Sun, 10 Dec 2023 15:02:17 -0300 Subject: [PATCH 51/52] chore: removing TODO --- src/main/java/reputation/node/reputation/ReputationCalc.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/main/java/reputation/node/reputation/ReputationCalc.java b/src/main/java/reputation/node/reputation/ReputationCalc.java index 3c60f53..90b36b0 100644 --- a/src/main/java/reputation/node/reputation/ReputationCalc.java +++ b/src/main/java/reputation/node/reputation/ReputationCalc.java @@ -6,7 +6,7 @@ /** * Responsável por calcular a reputação de uma coisa. - * + * * @author Allan Capistrano * @version 1.0.0 */ @@ -14,8 +14,6 @@ public class ReputationCalc implements IReputationCalc { @Override public Double calc(List evaluationTransactions) { - // TODO: Implementar z-scores para verificar se um valor não está destoante da média - return evaluationTransactions .stream() .mapToInt(et -> ((Evaluation) et).getValue()) From 68d7f220d3fc3d962cf6edbde9cc03b02f919350 Mon Sep 17 00:00:00 2001 From: AllanCapistrano Date: Sun, 10 Dec 2023 15:02:45 -0300 Subject: [PATCH 52/52] chore: update class version --- src/main/java/reputation/node/models/Node.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/reputation/node/models/Node.java b/src/main/java/reputation/node/models/Node.java index bb845ac..4c522b6 100644 --- a/src/main/java/reputation/node/models/Node.java +++ b/src/main/java/reputation/node/models/Node.java @@ -43,7 +43,7 @@ /** * * @author Allan Capistrano - * @version 1.2.0 // TODO: Alterar quando finalizar o fluxo. + * @version 1.3.0 */ public class Node implements NodeTypeService, ILedgerSubscriber {