Skip to content
Snippets Groups Projects
Scenari.java 7.09 KiB
Newer Older
  • Learn to ignore specific revisions
  • package scenari;
    
    
    import java.io.IOException;
    import java.util.ArrayList;
    import java.util.Date;
    
    import org.eclipse.paho.client.mqttv3.MqttClient;
    import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
    import org.eclipse.paho.client.mqttv3.MqttException;
    
    import org.eclipse.paho.client.mqttv3.MqttMessage;
    
    import org.eclipse.paho.client.mqttv3.MqttTopic;
    import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;
    import org.json.JSONException;
    import org.json.JSONObject;
    
    import utility.Esecutore;
    import utility.Helper;
    import utility.SubscribeCallback;
    
    public class Scenari {
    
    	private static String brokerUrl;
    	private String learnTrigger;
    	private String attivaScenari;
    	private static ArrayList<String> topicsSub;
    	private String clientId = Long.toString(new Date().getTime()) + "-scenari"; // unique client id
    	private Automa automa;
    
    	private String mqttDomain;
    	private String mqttSubdomain;
    	private static String mqttTree;
    
    	
    	public MqttClient mqttClient;
    	
    	public Scenari(Automa automa) throws JSONException, IOException, MqttException {
    		this.automa = automa;
    		
    		JSONObject config = new JSONObject(Helper.leggiFile("./CONF/conf.json"));
    		brokerUrl = config.getString("protocol") + "://" + config.getString("broker") + ":" + config.getInt("port");
    
    		mqttDomain = config.getString("mqttDomain");
    		mqttSubdomain = config.getString("mqttSubdomain");
    		makeMqttTree();
    
    		
    		topicsSub = new ArrayList<String>();
    		topicsSub.add("to/all"); //mandare la mia descrizione json
    
    		topicsSub.add("rpc/"+mqttTree+"scenari"); //mandare lo stato attuale
    
    		
    		// inutile aggiungere i topic, perche subbo gia' tutto gpio/#
    		config = new JSONObject(Helper.leggiFile("./CONF/zona.json"));
    		learnTrigger = config.getString("learn-trigger");
    
    //		topicsSub.add("from/"+Scenari.getMqttTree()+"gpio/" + learnTrigger); // Sottoscrivo i messaggi che notificano il cambiamento di stato dell'interruttore
    
    		attivaScenari = config.getString("attiva-scenari");
    
    //		topicsSub.add("from/"+Scenari.getMqttTree()+"gpio/"+attivaScenari);
    
    		
    //		interruttoreOutputSuono = config.getString("outputSuono");
    
    //		topicsSub.add("from/"+Scenari.getMqttTree()+"gpio/" + interruttoreOutputSuono); // Sottoscrivo i messaggi che notificano il cambiamento di stato dell'interruttore
    //		topicsSub.add("to/"+Scenari.getMqttTree()+"scenari/learn");
    		topicsSub.add("from/"+mqttTree+"gpio/#");
    
    		
    		this.mqttClient = new MqttClient(brokerUrl, clientId, new MemoryPersistence());
    		//memory persistence serve per non avere errori in console
    		// https://github.com/eclipse/paho.mqtt.java/issues/794
    	}
    	
    
    	public void startClient(Esecutore esec/*, Publisher publisher*/) throws MqttException {
    
    		MqttConnectOptions options = new MqttConnectOptions();
    		options.setUserName("gruppo2");
    		options.setPassword("funziona".toCharArray());
    		options.setCleanSession(false);
    
    		mqttClient.setCallback(new SubscribeCallback(this/*, publisher*/, learnTrigger, attivaScenari, esec, automa));
    
    		
    		mqttClient.connect(options);
    		
    		for(String t: topicsSub) 
    			mqttClient.subscribe(t);
    	}
    	
    
    	public void sendMqttMessage(String topic, String msg) throws MqttException {
    		final MqttTopic msgTopic = mqttClient.getTopic(topic);
    		msgTopic.publish(new MqttMessage(msg.getBytes()));
    	}
    	
    
    	private void makeMqttTree() {
    		if(mqttTree != null)
    			return;
    		mqttTree = mqttDomain + "/" + mqttSubdomain + "/";
    	}
    	
    	public static String getMqttTree() {
    		return mqttTree;
    	}
    
    	
    	
    	
    	/*
    	 * Abbiamo 3 tipi di eventi:
    	 * 		to 		Command Events - mi viene richiesto di eseguire un comando --> sottoscrivo 
    	 * 		from 	Status Events - io annuncio un cambiamento di stato  	
    	 * 								(inviato a tutti i client che hanno sottoscritto il topic su cui faccio la publish)
    	 * 		rpc 	Query Events - richiesta di inviare uno stato a un client (o microservizio). --> sottoscrivo 
    	 * 			  				   Query implementati come coppia di eventi: <query event, status event>
    	 * RICORDIAMO COME ABBIAMO IMPLEMENTATO LA RPC SU MQTT
    	 * 
    	 * 
    	 * 
    	 * Il cuore della nostra business logic è un metodo in cui mi metto in attesa su mqtt e: 
    	 * 		se arriva un comando, chiamo il metodo responsabile per eseguire quel comando;
    	 * 		se arriva un evento di stato, chiamo il metodo responsabile per gestire quell'evento di stato;
    	 * 		se arriva una remote procedure call, attivo la risposta sulla remote procedure call 
    	 * 
    	 * 
    	 * 
    	 * Capire come gestire sistema a regole (vedi slide "Esempio" in "Applicazioni IoT "Cloud Based"")
    	 * 
    	 * 
    	 * 
    	 * Sicurezza gestita con TLS
    	 * 
    	 * 
    	 * 
    	 * FILE DA FARE per un servizio: (?)
    	 * 		file che contiene le informazioni per connettersi al mosquitto locale 
    	 * 		file che dice qual'è la porta che lui deve esporre
    	 * 		file che mi dice tutte le cose che lo configurano, ad esempio quanti device deve guardare
    	 * 		...
    	 * 
    	 * 	I file di configurazione sono in JSON o in XML
    	 * I dati persistiti si troveranno nella sottodirectory (chiamata con il nome del servizio) di Home
    	 * 
    	 * 
    	 * Nella fase di configurazione potremo ancora modificare i file di configurazione (ad esempio aggiungendo device, 
    	 * regole). Dopodiché quando si fa partire il servizio si inizierà a usare l'altra parte di file system (ovvero il Local 
    	 * Dynamic File System) dove si andranno a salvare gli stati per renderli persistenti.
    	 * 
    	 * 
    	 * 
    	 * Ho un processo principale che come unico compito ha quello di fare una fork() e creare un processo figlio. 
    	 * Sarà questo processo figlio a eseguire effettivamente il programma. Se il processo figlio termina (PER UN QUALCHE 
    	 * PROBLEMA), allora il processo padre se ne accorge e fa ripartire un nuovo processo figlio.
    	 * 
    	 *  
    	 * Devo avere una thread di configurazione che obbedisce ai miei comandi (dati sulla HAT interface andando su 
    	 * 	192.168.0.101:9001/configure.html (dove 192.168.0.101 è l'indirizzo della beaglebone)
    	 * 
    	 * 
    	 * Ho una classe che implementa l'automa a stati finiti
    	 * 
    	 * 
    	*/
    	
    	public static void main(String args[]) throws JSONException, IOException, MqttException {
    		System.out.println("started");
    		//PER TESTARE PRIMA TOGLI IL TRY CATCH !!!!! POI QUANDO TUTTO FUNZIONA, METTI IL TRY CATCH, togli le throws E IMPLEMENTA LA RIPARTENZA!
    		
    //		while(true) {
    //			try {
    				startSystem();
    //			}
    //			catch(Exception e) {
    //				// DA FARE:
    //				// qui metto il codice per far ripartire il processo: rileggo lo stato dei sensori e dell'interruttore, 
    //				// capisco di conseguenza in quale stato dell'automa mi trovo e riparto.
    //				startSystem();
    //			}
    //		}
    //		Scenari antifurto = 
    //		new Scenari(new Automa());
    	}
    	
    	
    	private static void startSystem() throws JSONException, IOException, MqttException {
    		
    //		MyQueue<Integer> codaVal = new MyQueue<Integer>();
    //		MyQueue<Pair> codaMsg = ;
    		Automa automa = new Automa();
    		Scenari scenari = new Scenari(automa);
    
    //		Publisher publisher = new Publisher(new MyQueue<Pair>(), scenari);
    
    //		Esecutore esec = new Esecutore(publisher, codaVal, automa, antifurto.interruttoreOutputSuono);
    
    		Esecutore esec = new Esecutore(/*publisher,*/automa,scenari);
    
    //		Timer timer = new Timer(30000,-5,esec,automa);
    		
    
    		scenari.startClient(esec/*,publisher*/);//, publisher);
    //		publisher.start();