Newer
Older
import java.io.BufferedReader;
import java.io.FileReader;
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.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
public class Antifurto {
private static String brokerUrl;
private String interruttore;
private String interruttoreOutputSuono;
private String nomeOutputAntifurto;
private static JSONArray sensori; // sensori di movimento
private static ArrayList<String> topicsSub;
private Date date = new Date();
private String clientId = Long.toString(date.getTime()) + "-sub-pub"; // unique client id
private Automa automa;
private static String mqttDomain;
private static String mqttSubdomain;
public static final String CONF_ZONA = "../res/CONF/zona.json";
public Antifurto(Automa automa) throws JSONException, IOException, MqttException {
this.automa = automa;
JSONObject jsonObject = new JSONObject(Helper.leggiFile(CONF_FILE));
brokerUrl = jsonObject.getString("protocol") + "://" + jsonObject.getString("broker") + ":" + jsonObject.getInt("port");
mqttDomain = jsonObject.getString("mqttDomain");
mqttSubdomain = jsonObject.getString("mqttSubdomain");
// Su questo topic ricevero' un messaggio del tipo {request:description}
topicsSub.add("to/all");
// Su questo topic ricevero' le richieste di inviare il mio stato attuale
topicsSub.add("rpc/"+getMqttTree()+"/antifurto");
jsonObject = new JSONObject(Helper.leggiFile(CONF_ZONA));
interruttore = jsonObject.getString("interruttore");
topicsSub.add("from/"+getMqttTree()+"/gpio/" + interruttore); // Sottoscrivo i messaggi che notificano il cambiamento di stato dell'interruttore
// Per ogni sensore di movimento, sottoscrivo i messaggi che notificano il loro cambiamento di stato
sensori = jsonObject.getJSONArray("sensoriMovimento");
topicsSub.add("from/"+getMqttTree()+"/gpio/" + sensori.get(i));
nomeOutputAntifurto = jsonObject.getString("nomeOutputAntifurto");
topicsSub.add("from/"+getMqttTree()+"/gpio/" + nomeOutputAntifurto);
interruttoreOutputSuono = jsonObject.getString("outputSuono");
topicsSub.add("from/"+getMqttTree()+"/gpio/" + interruttoreOutputSuono); // Sottoscrivo i messaggi che notificano il cambiamento di stato dell'interruttore
topicsSub.add("to/"+getMqttTree()+"/antifurto/soglia"); // Su questo topic mi arrivera' un messaggio {"soglia": 30} e dovrò impostare la soglia di conseguenza
topicsSub.add("conf/"+getMqttTree()+"/antifurto/sensore"); // Su questo topic mi arrivera' un messaggio per l'aggiunta di un sensore di movimento.
// Ad esempio se mi arriva il messaggio {"in": "IN3", "delta":33 } devo aggiungere il sensore di movimento che si
// chiama IN3, il cui valore di delta e' 33 (devo quindi aggiornare il file deltaSensoriMovimento.json
topicsSub.add("to/"+getMqttTree()+"/antifurto/luceAntifurto");
this.mqttClient = new MqttClient(brokerUrl, clientId, new MemoryPersistence());
public void startClient(Esecutore esec, Publisher publisher) throws MqttException {
MqttConnectOptions options = new MqttConnectOptions();
options.setCleanSession(false);
mqttClient.setCallback(new SubscribeCallback(this, publisher, interruttore, interruttoreOutputSuono, esec, automa, nomeOutputAntifurto));
for(String t: topicsSub)
// sottoscrive il topic passato come parametro
public void addTopicToSubscribe(String topic) throws MqttException {
mqttClient.subscribe(topic);
public void publishMethod(String topic, String msg) throws MqttException {
final MqttTopic msgTopic = mqttClient.getTopic(topic);
msgTopic.publish(new MqttMessage(msg.getBytes()));
}
* 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"")
* 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)
*
*
*
*
* DA FARE:
* All'avvio, leggo il file stato e mi imposto di conseguenza. Poi interrogo la beaglebone per sapere SOLO lo stato
* dell'antifurto (luce rossa), ovvero se l'antifurto e' on o off. Lo stato del sensore di suono, non mi interessa: poiche'
* sono solo io a impostarlo (la web app si comporta in conseguenza dei miei messaggi).
* Mi serve interrogare la beaglebone per lo stato dell'antifurto perche' puo' succedere che l'antifurto abbia avuto
* dei problemi e quindi non abbia funzionato per un po' e nel mentre l'utente ha attivato l'antifurto dagli scenari.
* Quindi proprio perche' sia il mio antifurto sia gli scenari comandano lo stesso antifurto, devo fare questa richiesta
* alla beaglebone.
* Dopo aver chiesto lo stato dell'antifurto alla beaglebone, so esattamente lo stato in cui devo essere --> mi imposto
public static void main(String args[]) throws JSONException, IOException, MqttException {
//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();
// }
// }
}
private static void startSystem() throws JSONException, IOException, MqttException {
MyQueue<Integer> codaVal = new MyQueue<Integer>();
MyQueue<Pair> codaMsg = new MyQueue<Pair>();
Automa automa = new Automa();
Antifurto antifurto = new Antifurto(automa);
Publisher publisher = new Publisher(codaMsg, antifurto);
Esecutore esec = new Esecutore(publisher, codaVal, automa, antifurto.interruttoreOutputSuono);
Timer timer = new Timer(6000,-1,esec,automa);
antifurto.startClient(esec, publisher);
publisher.start();
esec.start();
timer.start();
}
public static void stopSystem() {
public static String getMqttTree() {
return mqttDomain+"/"+mqttSubdomain;
}
public static JSONArray getSensori() {
return sensori;
}
public static void addSensore(String newSensore) { // aggiunge un sensore di movimento
sensori.put(newSensore);
}