În laboratorul trecut ne-am familiarizat cu aplicația web (serverul) care primește imaginile trimise prin MQTT. În cadrul acestui laborator ne vom axa pe clientul mobil responsabil de transmiterea imaginilor.
Pentru parcurgerea acestui laborator, vă sugerăm următoarele:
| Setare | Opțiune |
|---|---|
| Device | Pixel 6 |
| API | 31 |
| System image | Google APIs Intel x86_64 Atom System Image |
| Camera rear | VirtualScene |
| Default boot | Cold |
| Internal storage | 6 GB |
| Expanded storage | None |
| CPU cores | 4 |
| Graphics acceleration | Automatic |
| RAM | 4 GB |
| VM heap size | 512 MB |
advancedFeatures.ini în directorul ~/.android cu următorul conținut:
Vulkan = off GLDirectMem = on
Asigurați-vă că aveți instalat un broker MQTT, de exemplu Mosquitto
Creați în root-ul scheletului de laborator un director de test, iar în interiorul acestuia definiți un fișier de configurare cu următorul conținut:
listener 1883 allow_anonymous true
Într-un terminal rulați următoarele comenzi:
sudo systemctl stop mosquitto.service mosquitto -c mqtt.conf -v
Un good practice în Python este să folosim virtual environment-uri, astfel rulați într-un terminal:
python -m venv .mqtt_env source .mqtt_env/bin/activate pip install paho-mqtt
Creați și rulați un client simplu MQTT care face automat subscribe la topicul ssproject/images și salvează imaginile primite într-un director separat.
import paho.mqtt.client as mqtt from paho.mqtt.enums import CallbackAPIVersion import os import time BROKER = "127.0.0.1" PORT = 1883 TOPIC = "ssproject/images" OUTPUT_DIR = "received_images" if not os.path.exists(OUTPUT_DIR): os.makedirs(OUTPUT_DIR) def on_connect(client, userdata, flags, reason_code, properties): print(f"Connected (reason code: {reason_code})") client.subscribe(TOPIC) def on_message(client, userdata, msg): timestamp = int(time.time() * 1000) filename = f"{OUTPUT_DIR}/image_{timestamp}.jpg" try: with open(filename, "wb") as f: f.write(msg.payload) print(f"Image saved: {filename} ({len(msg.payload)} bytes)") except Exception as e: print(f"Error saving image: {e}") client = mqtt.Client(callback_api_version=CallbackAPIVersion.VERSION2) client.on_connect = on_connect client.on_message = on_message print(f"Connecting to {BROKER}...") client.connect(BROKER, PORT, 60) print("Exit with Ctrl+C") print("Waiting for images...") client.loop_forever()
Mai jos este prezentată structura simplificată a scheletului aplicației Android, evidențiind componentele ce vor fi analizate și modificate pe parcursul semestrului:
ss-mobile
└── app
├── src
│ ├── main
│ │ ├── java/ro/pub/cs/systems/ssproject
│ │ │ ├── mqtt # Logică comunicație MQTT
│ │ │ ├── ui # Activități și interfață utilizator
│ │ │ └── utils # Clase utilitare
│ │ ├── res/layout # Fișiere XML pentru UI
│ │ └── AndroidManifest.xml # Configurație aplicație
│ ├── test # Unit Tests (logică pură)
│ └── androidTest # Instrumented Tests
└── build.gradle.kts # Configurații de build
mqtt/ – Conține implementarea clientului MQTT (folosind Paho) și constantele pentru topice.ui/ – Conține codul pentru ecranele aplicației.MainActivity – captură și trimitere imagini.SetupActivity – setări de conexiune.utils/ – Include:ImageUtils – procesare formate imagine (YUV → NV21, rotație)PermissionHandler – gestionare permisiunitest/ – Conține teste unitare care rulează direct pe JVM și sunt folosite pentru a testa logica ce nu depinde de framework-ul Android.androidTest/ – Teste instrumentate (rulează pe dispozitiv/emulator), folosite pentru a testa componente ce depind de contextul Android.
Livrabil: Directorul received_photos populat cu imaginile capturate din aplicația mobilă