Πίνακας περιεχομένων:

SmartBin: 8 βήματα
SmartBin: 8 βήματα

Βίντεο: SmartBin: 8 βήματα

Βίντεο: SmartBin: 8 βήματα
Βίντεο: SmartBin in Action 2024, Νοέμβριος
Anonim
SmartBin
SmartBin

Εκπαιδευτικό σύστημα για την ευφυΐα των συστημάτων, δεν είναι δυνατή η πρόσβαση στο δίκτυο, αναγνωρίζοντας την ποσότητα που θα σας παρουσιάσουμε, θα σας βοηθήσουμε να λάβετε πληροφορίες, να υποβάλετε πληροφορίες για την ανάκτησή σας.

Para montar este projeto, é απαραίτητο:

  • NodeMCU
  • Αισθητήρας Ultrassônico de Distancia
  • Caixa de papelão
  • Protoboard
  • Cabos
  • Διαθέσιμο Android

Βήμα 1: Αισθητήρας Conectando O

Primeiramente, vamos efetuar a conexão entre o sensor ultrassônico e o NODEMCU. Παρά ταύτα, vamos conectar as portas trigger echo do sensor nas portas D4 e D3 do NodeMCU:

// καθορίζει τους αριθμούς των ακίδων #define pino_trigger 2 // D4

#define pino_echo 0 // D3

Παρακαλούμε να λάβετε υπόψη σας τον αισθητήρα, για να μάθετε πώς να μάθετε περισσότερα σχετικά με το FilipeFlop, disponível aqui.

float cmMsec, inMsec;

long microsec = ultrasonic.timing ();

cmMsec = ultrasonic.convert (microsec, Ultrasonic:: CM);

inMsec = ultrasonic.convert (microsec, Ultrasonic:: IN);

// Exibe informacoes no serial monitor

Serial.print ("Distancia em cm:");

Serial.print (cmMsec);

Serial.print (" - Distancia em polegadas:");

Serial.println (inMsec);

String data = String (cmMsec);

Serial.println (δεδομένα);

Βήμα 2: Montando a Lixeira

Agora, vamos montar a lixeira inteligente. Precisaremos conectar o sensor ultrassônico no “teto” da lixeira. Για παράδειγµα, χρησιµοποιήστε το cabo e fita isolante. Em seguida, temos que medir a distância inicial, para saber o valor para a lixeira vazia. No meu caso, foi de 26, 3εκ. Esse é o valor que konsiderrarmos para uma lixeira vazia.

Για παραδείγματα, μπορείτε να δείτε ότι μπορείτε να χρησιμοποιήσετε τον αισθητήρα υπερηχογραφίας, για να διαπιστώσετε τυχόν τυχαίες αποστάσεις σε 4 διαφορετικούς διαφορετικούς τρόπους.

// Simulando 4 lixeiras

μακρύ lixeiraID;

void loop () {

lixeiraID = τυχαίο (1, 5);

}

Βήμα 3: Ανεβάστε το Para a Nuvem

Agora, precisamos enviar estes dados para a nuvem. Eu escolhi o ThingSpeak, por familiaridade com o mesmo. Primeiramente, é απαραίτητο criar um novo canal, recebendo 4 parâmetros, referentes ao volume de cada lixeira.

Παρέχει τη δυνατότητα εφαρμογής του ThingSpeak, είναι απαραίτητο για τη σωστή λειτουργία του API στο κανάλι του κριτηρίου. Siga os passos descritos δεν υπάρχει επίσημος ιστότοπος.

De volta à aplicação, vamos utilizar a biblioteca ESP8266WiFi.h para efetuar conexão com o ThingSpeak, e transferir os dados.

Primeiramente, uma função para efetuar conexão com a rede (defina previamente duas variáveis, ssid e pass , contendo o identificador e a senha de sua rede).

void connectWifi () {

Serial.print ("Σύνδεση με"+ *ssid);

WiFi.begin (ssid, pass);

ενώ (WiFi.status ()! = WL_CONNECTED) {

καθυστέρηση (500)?

Serial.print (".");

}

Serial.println ("");

Serial.print ("Conectado na rede");

Serial.println (ssid);

Serial.print ("IP:");

Serial.println (WiFi.localIP ());

}

Δυνατότητα ρύθμισης, προειδοποίηση και προειδοποίηση για μια συναλλαγή.

void setup () {

Serial.begin (9600);

Serial.println ("Lendo dados do sensor…");

// Conectando ao Wi-Fi

connectWifi ();

}

E, para enviar os dados para o ThingSpeak, basta abrir uma conexão HTTP padrão, passando o número da API e os parâmetros.

void sendDataTS (float cmMsec, long id) {

if (client.connect (διακομιστής, 80)) {

Serial.println ("Enviando dados para o ThingSpeak");

String postStr = apiKey;

postStr += "& πεδίο";

postStr += id;

postStr += "=";

postStr += String (cmMsec);

postStr += "\ r / n / r / n";

Serial.println (postStr);

client.print ("POST /ενημέρωση HTTP /1.1 / n");

client.print ("Host: api.thingspeak.com / n");

client.print ("Σύνδεση: κλείσιμο / n");

client.print ("X-THINGSPEAKAPIKEY:" + apiKey + "\ n");

client.print ("Content-Type: application/x-www-form-urlencoded / n");

client.print ("Περιεχόμενο-Μήκος:");

client.print (postStr.length ());

client.print ("\ n / n");

client.print (postStr);

καθυστέρηση (1000)?

}

client.stop ();

}

O primeiro parâmetro αντιστοιχούν à distância em centímetros encontrada pelo sensor ultrassônico. O segundo parâmetro é o ID da lixeira que foi lida (que foi gerado randomicamente, um número de 1 a 4).

O ID da lixeira serve também para identificar para qual campo será feito ή upload do valor lido.

Βήμα 4: Recuperando Dados Do ThingSpeak

O ThingSpeak permite efetuar leitura dos dados do seu canal, através de um serviço retornando um JSON. As diferentes opções para leitura do feed do seu canal estão descritas aqui:

www.mathworks.com/help/thingspeak/get-a-ch…

Neste projeto, optou-se por ler diretamente os dados de cada campo. Παρακαλούμε χρησιμοποιήστε τη διεύθυνση URL για την αξιολόγησή σας:

api.thingspeak.com/channels/CHANNEL_ID/fields/FIELD_NUMBER/last.json?api_key=API_KEY&status=true

Cada campo está descrito χωρίς σύνδεσμο για προγενέστερη ενημέρωση. Os mais importantes para o projeto são:

  • CHANNEL_ID: número do seu canal
  • FIELD_NUMBER: o número do campo
  • API_KEY: chave de API do seu canal

Είναι μια διεύθυνση URL που συνδέεται με την εφαρμογή του Android, για την ανάκτηση των λειτουργιών του ThingSpeak.

Βήμα 5: Criando and Aplicação Android

Δεν υπάρχει Android Studio, δεν χρειάζεται να δημιουργήσετε Android. Για να λειτουργήσετε σωστά, πρέπει να ρυθμίσετε τις παραμέτρους του, καθώς επιτρέπεται να λειτουργεί χωρίς AndroidManifest.

Για χρήση από τους Χάρτες Google, είναι απαραίτητο να κάνετε κλικ στο Google. Siga os passos descritos no link Obter chave de API.

Uma vez com a chave, você deve também configurá-la na aplicação.

Το κλειδί API για API που βασίζονται στους Χάρτες Google ορίζεται ως πόρος συμβολοσειράς.

(Δείτε το αρχείο "res/values/google_maps_api.xml").

Λάβετε υπόψη ότι το κλειδί API συνδέεται με το κλειδί κρυπτογράφησης που χρησιμοποιείται για την υπογραφή του APK. Χρειάζεστε ένα διαφορετικό κλειδί API για κάθε κλειδί κρυπτογράφησης, συμπεριλαμβανομένου του κλειδιού έκδοσης που χρησιμοποιείται για την υπογραφή του APK για δημοσίευση. Μπορείτε να ορίσετε τα κλειδιά για τους στόχους εντοπισμού σφαλμάτων και απελευθέρωσης στο src/debug/και src/release/.

<μεταδεδομένα

android: name = "com.google.android.geo. API_KEY"

android: value = "@string /google_maps_key" />

Μια πλήρης διαμόρφωση είναι διαθέσιμη για το AndroidManifest anexado ao projeto.

ν

Βήμα 6: Recuperando O Feed No Android

Na atividade principal no Android, MainActivity, crie 4 variáveis para identificar cada um dos canais do ThingΜιλήστε για μια σειρά:

private String url_a = "https://api.thingspeak.com/channels/429823/fields/1/last.json?api_key="+API_THINGSPEAK_KEY+"&status=true"; private String url_b = "https://api.thingspeak.com/channels/429823/fields/2/last.json?api_key="+API_THINGSPEAK_KEY+"&status=true"; private String url_c = "https://api.thingspeak.com/channels/429823/fields/3/last.json?api_key="+API_THINGSPEAK_KEY+"&status=true"; private String url_d = "https://api.thingspeak.com/channels/429823/fields/4/last.json?api_key="+API_THINGSPEAK_KEY+"&status=true";

Για να αποκτήσετε μια ευχάριστη χρήση, μπορείτε να χρησιμοποιήσετε την εφαρμογή του Android, chamada JSONObject. Mais uma vez, vamos criar um objeto για cada URL:

JSONObject respondLixeiraA; JSONObject responseLixeiraB; JSONObject responseLixeiraC; JSONObject respondLixeiraD;

Παρακαλείστε να λάβετε υπόψη σας ως urls, vamos usar criar uma classe auxiliar, chamada HttpJsonParser. Μπορείτε να απαντήσετε στο abrir uma conexão com um URL, να λάβετε πληροφορίες σχετικά με τους κωδικούς πρόσβασης, να ανατρέξετε ή να υποβάλετε το JSON montado.

δημόσιο JSONObject makeHttpRequest (url συμβολοσειράς, μέθοδος συμβολοσειράς, παράθυρα χαρτών) {

προσπαθήστε {

Uri. Builder builder = νέο Uri. Builder (); URL urlObj; String encodedParams = ""; if (params! = null) {for (Map. Entry entry: params.entrySet ()) {builder.appendQueryParameter (entry.getKey (), entry.getValue ()); }} if (builder.build (). getEncodedQuery ()! = null) {encodedParams = builder.build (). getEncodedQuery ();

}

if ("GET".equals (method)) {url = url + "?" + κωδικοποιημέναParams; urlObj = νέο URL (url); urlConnection = (HttpURLConnection) urlObj.openConnection (); urlConnection.setRequestMethod (μέθοδος);

} αλλο {

urlObj = νέο URL (url); urlConnection = (HttpURLConnection) urlObj.openConnection (); urlConnection.setRequestMethod (μέθοδος); urlConnection.setRequestProperty ("Τύπος περιεχομένου", "εφαρμογή/x-www-form-urlencoded"); urlConnection.setRequestProperty ("Content-Length", String.valueOf (encodedParams.getBytes (). μήκος)); urlConnection.getOutputStream (). εγγραφή (encodedParams.getBytes ()); } // Σύνδεση στο διακομιστή urlConnection.connect (); // Διαβάστε την απάντηση είναι = urlConnection.getInputStream (); BufferedReader reader = νέο BufferedReader (νέο InputStreamReader (είναι)); StringBuilder sb = νέο StringBuilder (); Γραμμή συμβολοσειράς

// Αναλύστε την απάντηση

while ((line = reader.readLine ())! = null) {sb.append (γραμμή + "\ n"); } είναι κοντά(); json = sb.toString (); // Μετατροπή της απόκρισης σε αντικείμενο JSON jObj = νέο JSONObject (json);

} catch (UnsupportedEncodingException e) {

e.printStackTrace (); } catch (ProtocolException e) {e.printStackTrace (); } catch (IOException e) {e.printStackTrace (); } catch (JSONException e) {Log.e ("JSON Parser", "Error parsing data" + e.toString ()); } catch (Εξαίρεση ε) {Log.e ("Εξαίρεση", "Σφάλμα ανάλυσης δεδομένων" + e.toString ()); }

// επιστροφή αντικειμένου JSON

επιστροφή jObj?

}

}

De volta a atividade principal, vamos efetuar a chamada às urls de forma assíncrona, escrevendo este código dentro do método doInBackground.

@Override προστατευμένη συμβολοσειρά doInBackground (συμβολοσειρά… params) {HttpJsonParser jsonParser = new HttpJsonParser ();

respondLixeiraA = jsonParser.makeHttpRequest (url_a, "GET", null);

respondLixeiraB = jsonParser.makeHttpRequest (url_b, "GET", null); respondLixeiraC = jsonParser.makeHttpRequest (url_c, "GET", null); respondLixeiraD = jsonParser.makeHttpRequest (url_d, "GET", null);

return null;}

Quando o método doInBackgroundé encerrado, o controle de execução για Android passa para o método onPostExecute. Neste método, vamos criar os objetos Lixeira, e popular com os dados recuperados do ThingSpeak:

προστατευμένο κενό onPostExecute (αποτέλεσμα συμβολοσειράς) {pDialog.dismiss (); runOnUiThread (νέο Runnable () {public void run () {

// ListView listView = (ListView) findViewById (R.id.feedList);

Προβολή mainView = (Προβολή) findViewById (R.id.activity_main); if (success == 1) {try {// Cria feedDetail para cada lixeira Lixeira feedDetails1 = new Lixeira (); Lixeira feedDetails2 = νέα Lixeira (); Lixeira feedDetails3 = νέα Lixeira (); Lixeira feedDetails4 = νέα Lixeira ();

feedDetails1.setId ('A');

feedDetails1.setPesoLixo (Double.parseDouble (respondLixeiraA.getString (KEY_FIELD1))); feedDetails1.setVolumeLixo (Double.parseDouble (respondLixeiraA.getString (KEY_FIELD1))));

feedDetails2.setId ('B');

feedDetails2.setPesoLixo (Double.parseDouble (respondLixeiraB.getString (KEY_FIELD2))); feedDetails2.setVolumeLixo (Double.parseDouble (respondLixeiraB.getString (KEY_FIELD2))));

feedDetails3.setId ('C');

feedDetails3.setPesoLixo (Double.parseDouble (respondLixeiraC.getString (KEY_FIELD3)))); feedDetails3.setVolumeLixo (Double.parseDouble (respondLixeiraC.getString (KEY_FIELD3))));

feedDetails4.setId ('D');

feedDetails4.setPesoLixo (Double.parseDouble (respondLixeiraD.getString (KEY_FIELD4)))); feedDetails4.setVolumeLixo (Double.parseDouble (respondLixeiraD.getString (KEY_FIELD4))));

feedList.add (feedDetails1);

feedList.add (feedDetails2); feedList.add (feedDetails3); feedList.add (feedDetails4);

// Υπολογισμός dados das lixeiras

SmartBinService calculator = νέα SmartBinService (); calculator.montaListaLixeiras (feedList);

// Recupera componentes

TextView createDate = (TextView) mainView.findViewById (R.id.date); ListView listaDeLixeiras = (ListView) findViewById (R.id.lista); adapter.addAll (feedList);

// Δεδομένα atual

Ημερομηνία currentTime = Calendar.getInstance (). GetTime (); SimpleDateFormat simpleDate = νέα SimpleDateFormat ("ηη/ΜΜ/εεεε"); Συμβολοσειρά currentDate = simpleDate.format (currentTime); createDate.setText (KEY_DATE + currentDate + ""); listaDeLixeiras.setAdapter (προσαρμογέας);

} catch (JSONException e) {

e.printStackTrace (); }

} αλλο {

Toast.makeText (MainActivity.this, "Παρουσιάστηκε κάποιο σφάλμα κατά τη φόρτωση δεδομένων", Toast. LENGTH_LONG). Show ();

}

} }); }

Agora, na tela inicial do aplicativo, serão listados os dados de cada lixeira.

Βήμα 7: Mostrando No Mapa

Mostrando No Mapa
Mostrando No Mapa

Ainda na atividade principal, vamos adicionar uma ação a ser relacionada ao botão Mapa, na tela inicial.

/ ** Καλείται όταν ο χρήστης αγγίζει το κουμπί Mapa*/ public void openMaps (Προβολή προβολής) {Intent purpose = new Intent (this, LixeiraMapsActivity.class);

// Passa a lista de lixeiras

Bundle bundle = νέο Bundle (); bundle.putParcelableArrayList ("lixeiras", feedList); πρόθεση.putExtras (πακέτο);

startActivity (πρόθεση)?

}

Χωρίς μάπα, ο κατάλογος είναι ένας εκτελεστής:

  1. marcar a posição atual do caminha de lixo
  2. ανταποκριτής marcar os pontos a cada lixeira no mapa
  3. traçar a rota entre os pontos

Για εκτελέσεις os passos acima, vamos usar a API Google Directions. Για να μάθετε πώς μπορείτε να μάθετε Σχεδίαση οδηγιών διαδρομής μεταξύ δύο τοποθεσιών χρησιμοποιώντας τις Οδηγίες Google στο Google Map Android API V2

Primeiro, vamos criar localidades para cada um dos pontos que desejamos marcar:

// Τοποθεσίες

ιδιωτικό ρεύμα LatLng;

ιδιωτικό LatLng lixeiraA; ιδιωτικό LatLng lixeiraB; ιδιωτικό LatLng lixeiraC; ιδιωτικό LatLng lixeiraD;.

Για προτάσεις που δεν επιτρέπουν τη χρήση της κάρτας σας, μπορείτε να δείτε:

private void checkLocationandAddToMap () {// Έλεγχος αν ο χρήστης έχει χορηγήσει την άδεια εάν ACCESS_COARSE_LOCATION)! = PackageManager. PERMISSION_GRANTED) {// Ζητώντας άδεια τοποθεσίας ActivityCompat.requestPermissions (this, new String {android. Manifest.permission. ACCESS_FINE_LOCATION}, LOCATION_REQUEST_CODE); ΕΠΙΣΤΡΟΦΗ; }

// Ανάκτηση της τελευταίας γνωστής θέσης χρησιμοποιώντας το Fus

Τοποθεσία τοποθεσίας = LocationServices. FusedLocationApi.getLastLocation (googleApiClient);

// MarkerOptions χρησιμοποιούνται για τη δημιουργία ενός νέου δείκτη. Μπορείτε να καθορίσετε την τοποθεσία, τον τίτλο κ.λπ. με το MarkerOptions

this.current = νέο LatLng (location.getLatitude (), location.getLongitude ()); MarkerOptions markerOptions = new MarkerOptions (). Position (current).title ("Posição atual");

// Προσθήκη του δημιουργημένου δείκτη στο χάρτη, μετακίνηση της κάμερας στη θέση

markerOptions.icon (BitmapDescriptorFactory.defaultMarker (BitmapDescriptorFactory. HUE_GREEN)); System.out.println ("++++++++++++++ Passei aqui! +++++++++++++++"); mMap.addMarker (markerOptions);

// Μετακινήστε τη φωτογραφική μηχανή αμέσως στη θέση με ζουμ 15.

mMap.moveCamera (CameraUpdateFactory.newLatLngZoom (τρέχον, 15));

// Μεγέθυνση, εμψύχωση της κάμερας.

mMap.animateCamera (CameraUpdateFactory.zoomTo (14), 2000, null);

}

Em seguida, para cada lixeira, foram criados métodos similares ao abaixo:

private void addBinALocation () {// Έλεγχος αν ο χρήστης έχει χορηγήσει την άδεια εάν (ActivityCompat.checkSelfPermission (this, android. Manifest.permission. ACCESS_FINE_LOCATION)! = PackageManager. PERMISSION_GRANTED && ActivityCompat.checkSelfPermission (this, ACCESS_COARSE_LOCATION)! = PackageManager. PERMISSION_GRANTED) {// Ζητώντας άδεια τοποθεσίας ActivityCompat.requestPermissions (this, new String {android. Manifest.permission. ACCESS_FINE_LOCATION}, LOCATION_REQUEST_CODE); ΕΠΙΣΤΡΟΦΗ; }

// Praça da Estação

διπλό γεωγραφικό πλάτος = -19,9159578; διπλό γεωγραφικό μήκος = -43,9387856; this.lixeiraA = νέο LatLng (γεωγραφικό πλάτος, γεωγραφικό μήκος);

MarkerOptions markerOptions = new MarkerOptions (). Position (lixeiraA).title ("Lixeira A");

markerOptions.icon (BitmapDescriptorFactory.defaultMarker (BitmapDescriptorFactory. HUE_RED)); mMap.addMarker (markerOptions); }

Δεδομένου ότι το γεωγραφικό πλάτος και το γεωγραφικό πλάτος μπορούν να χρησιμοποιηθούν για την αναζήτηση των Χαρτών Google, μπορείτε να διορθώσετε κανένα κωδικό. Idealmente, estes valores ficariam salvos em um banco de dados (για παράδειγμα, Firebase). Será a primeira evolução deste projeto!

O último passo agora é traçar as rotas entre os pontos. Παρά ταλ, um conceito muito importante, και que será utilisado neste projeto, são os Waypoints!

Foi criado um método para traçar a rota entre dois dados pontos:

private String getDirectionsUrl (LatLng προέλευσης, LatLng dest, List waypointsList) {

// Προέλευση διαδρομής

String str_origin = "origin ="+origin.latitude+","+origin.longitude;

// Προορισμός διαδρομής

String str_dest = "προορισμός ="+dest.latitude+","+dest.longitude;

// Σημεία πορείας κατά μήκος της διαδρομής

//waypoints=optimize:true|-19.9227365, -43.9473546 | -19.9168006, -43.9361124 String waypoints = "waypoints = optimize: true"; for (LatLng point: waypointsList) {waypoints += "|" + point.latitude + "," + point.longitude; }

// Ο αισθητήρας είναι ενεργοποιημένος

Αισθητήρας συμβολοσειράς = "αισθητήρας = ψευδής";

// Δημιουργία παραμέτρων για την υπηρεσία Ιστού

Παράμετροι συμβολοσειράς = str_origin+"&"+str_dest+"&"+sensor+"&"+waypoints;

// Μορφή εξόδου

Έξοδος συμβολοσειράς = "json";

// Δημιουργία url στην υπηρεσία Ιστού

Url συμβολοσειράς = "https://maps.googleapis.com/maps/api/directions/"+output+"?"+parameters; System.out.println ("++++++++++++++++"+url);

url επιστροφής?

}

E, por fim, juntando tudo no método principal da classe, onMapReady:

@Override public void onMapReady (GoogleMap googleMap) {mMap = googleMap;

checkLocationandAddToMap ();

if (lixeirasList.get (0).getVolumeLixo ()> Lixeira. MIN_VOLUME_GARBAGE

|| lixeirasList.get (0).getPesoLixo ()-10> Lixeira. MIN_SIZE_GARBAGE) {addBinALocation (); } if (lixeirasList.get (1).getVolumeLixo ()> Lixeira. MIN_VOLUME_GARBAGE || lixeirasList.get (1).getPesoLixo ()> Lixeira. MIN_SIZE_GARBAGE) {addBinBLocation (); } if (lixeirasList.get (2).getVolumeLixo ()> Lixeira. MIN_VOLUME_GARBAGE || lixeirasList.get (2).getPesoLixo ()> Lixeira. MIN_SIZE_GARBAGE) {addBinCLocation (); } if (lixeirasList.get (3).getVolumeLixo ()> Lixeira. MIN_VOLUME_GARBAGE || lixeirasList.get (3).getPesoLixo ()> Lixeira. MIN_SIZE_GARBAGE) {addBinDLocation (); }

// Σχεδιάστε διαδρομές

// Λήψη URL στο API Οδηγιών Google

Σημεία λίστας = νέα ArrayList (); points.add (lixeiraB); points.add (lixeiraC); points.add (lixeiraD);

Url συμβολοσειράς = getDirectionsUrl (τρέχον, lixeiraA, σημεία);

DownloadTask downloadTask = νέο DownloadTask (); // Ξεκινήστε τη λήψη δεδομένων json από το Google Directions API downloadTask.execute (url). }

Aqui passamos apenas pelos pontos principais. Μπορείτε να ολοκληρώσετε το έργο σας για να διαβιβάσετε τις συμβουλές σας.

Βήμα 8: Συμπέρασμα

Este foi um projeto trabalhando conceitos de IoT, mostrando uma das várias opções de conectar dispositivos através da nuvem, και efetuar tomada de decisões sem interferência humana direta. Για παράδειγμα, επιλέξτε και ολοκληρώστε, για παράδειγμα, για γραμματοσειρές που δεν έχουν Android.

Συνιστάται: