diff --git a/app/build.gradle.kts b/app/build.gradle.kts index aaafd8e..59c4931 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -11,11 +11,10 @@ android { defaultConfig { applicationId = "com.magix.atcommand" - minSdk = 33 + minSdk = 30 targetSdk = 33 - versionCode = 3 - versionName = "0.0.2" - + versionCode = 5 + versionName = "0.0.4" testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" } @@ -48,7 +47,6 @@ dependencies { androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1") implementation("com.github.mik3y:usb-serial-for-android:3.7.0") implementation("com.google.android.gms:play-services-location:21.0.1") - } diff --git a/app/src/main/assets/assets/css/custom_index.css b/app/src/main/assets/assets/css/custom_index.css new file mode 100644 index 0000000..e960e3e --- /dev/null +++ b/app/src/main/assets/assets/css/custom_index.css @@ -0,0 +1,242 @@ +@import url('https://fonts.googleapis.com/css?family=Fira+Sans:400,500,600,700,800'); +* { + box-sizing: border-box; +} +body { +background-color: #FFE53B; +background-image: linear-gradient(147deg, #FFE53B 0%, #fd3838 74%); +min-height: 100vh; +font-family: 'Fira Sans', sans-serif; + display: flex; +} + +.blog-slider { + width: 95%; + position: relative; + max-width: 800px; + margin: auto; + background: #fff; + box-shadow: 0px 14px 80px rgba(34, 35, 58, 0.2); + padding: 25px; + border-radius: 25px; + height: 400px; + transition: all .3s; + + + @media screen and (max-width: 992px) { + max-width: 680px; + height: 400px; + } + + @media screen and (max-width: 768px) { + min-height: 500px; + height: auto; + margin: 180px auto; + } + + + @media screen and (max-height: 500px) and (min-width: 992px) { + height: 350px; + } + + &__item { + display: flex; + align-items: center; + + @media screen and (max-width: 768px) { + flex-direction: column; + } + + &.swiper-slide-active { + .blog-slider__img { + img { + opacity: 1; + transition-delay: .3s; + } + } + .blog-slider__content { + > * { + + opacity: 1; + transform: none; + + @for $i from 0 to 15 { + &:nth-child(#{$i + 1}) { + transition-delay: $i * 0.1 + 0.3s; + } + } + + } + } + } + + } + + &__img { + // width: 40%; + width: 300px; + flex-shrink: 0; + height: 300px; + background-image: linear-gradient(147deg, #fe8a39 0%, #fd3838 74%); + box-shadow: 4px 13px 30px 1px rgba(252, 56, 56, 0.2); + border-radius: 20px; + transform: translateX(-80px); + + overflow: hidden; + + &:after { + content: ''; + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + background-image: linear-gradient(147deg, #fe8a39 0%, #fd3838 74%); + border-radius: 20px; + opacity: 0.8; +} + + img { + width: 100%; + height: 100%; + object-fit: cover; + display: block; + opacity: 0; + border-radius: 20px; + transition: all .3s; + } + + + @media screen and (max-width: 992px) { + // width: 45%; + } + @media screen and (max-width: 768px) { + transform: translateY(-50%); + width: 90%; + } + @media screen and (max-width: 576px) { + width: 95%; + } + @media screen and (max-height: 500px) and (min-width: 992px) { + height: 270px; + } + } + + &__content { + // width: 60%; + padding-right: 25px; + @media screen and (max-width: 992px) { + // width: 55%; + } + @media screen and (max-width: 768px) { + margin-top: -80px; + text-align: center; + padding: 0 30px; + } + + @media screen and (max-width: 576px) { + padding: 0 + } + > * { + opacity: 0; + transform: translateY(25px); + transition: all .4s; + + + } + + } + + &__code { + color: #7b7992; + margin-bottom: 15px; + display: block; + font-weight: 500; + } + + &__title { + font-size: 24px; + font-weight: 700; + color: #0d0925; + margin-bottom: 20px; + } + + &__text { + color: #4e4a67; + margin-bottom: 30px; + line-height: 1.5em; + } + + &__button { + display: inline-flex; + background-image: linear-gradient(147deg, #fe8a39 0%, #fd3838 74%); + padding: 15px 35px; + border-radius: 50px; + color: #fff; + box-shadow: 0px 14px 80px rgba(252, 56, 56, 0.4); + text-decoration: none; + font-weight: 500; + justify-content: center; + text-align: center; + letter-spacing: 1px; + @media screen and (max-width: 576px) { + width: 100%; + } + + } + .swiper-container-horizontal>.swiper-pagination-bullets, .swiper-pagination-custom, .swiper-pagination-fraction { + bottom: 10px; + left: 0; + width: 100%; + +} + &__pagination { + position: absolute; + z-index: 21; + right: 20px; + width: 11px!important; + text-align: center; + left: auto!important; + top: 50%; + bottom: auto!important; + transform: translateY(-50%); + @media screen and (max-width: 768px) { + transform: translateX(-50%); + left: 50%!important; + top: 205px; + width: 100%!important; + display: flex; + justify-content: center; + align-items: center; + } + &.swiper-pagination-bullets .swiper-pagination-bullet { + margin: 8px 0; + @media screen and (max-width: 768px) { + margin: 0 5px; + } +} + + .swiper-pagination-bullet { + width: 11px; + height: 11px; + display: block; + border-radius: 10px; + background: #062744; + opacity: 0.2; + transition: all .3s; + &-active { + opacity: 1; + background: #fd3838; + height: 30px; + box-shadow: 0px 0px 20px rgba(252, 56, 56, 0.3); + + @media screen and (max-width: 768px) { + height: 11px; + width: 30px; + } +} +} + + } + +} \ No newline at end of file diff --git a/app/src/main/assets/assets/js/custom-chat.js b/app/src/main/assets/assets/js/custom-chat.js index 6794e8c..e20a495 100644 --- a/app/src/main/assets/assets/js/custom-chat.js +++ b/app/src/main/assets/assets/js/custom-chat.js @@ -499,6 +499,67 @@ function hideContacts() { }); } +// Disabilito la TextArea in caso di device disconnesso +function disableTextareaAndLoadingIndicator() { + var textareaElement = document.getElementById('messageInput'); + var loadingIndicator = document.getElementById('loadingIndicator'); + var sendButton = document.querySelector('.btn.btn-primary.btn-icon.send-icon.rounded-circle.text-light.mb-1'); + var locationLink = document.getElementById('buttonLocation'); + var dropdownMenu = document.querySelector('.dropdown-menu'); + var attachmentElement = document.querySelector('.attachment'); + + if (textareaElement && loadingIndicator && sendButton && locationLink && dropdownMenu && attachmentElement) { + textareaElement.disabled = true; // Disabilita l'area di testo + textareaElement.style.opacity = '0.8'; // Opacità al 50% per oscurare l'area di testo + textareaElement.style.color = 'black'; // Rende il testo della textarea nero + + loadingIndicator.style.display = 'block'; // Mostra l'indicatore di caricamento + + sendButton.style.pointerEvents = 'none'; // Disabilita gli eventi di puntatore sul pulsante + sendButton.style.opacity = '0'; // Opacità al 50% per oscurare il pulsante + + locationLink.style.display = 'none'; // Rende invisibile l'elemento con ID "buttonLocation" + + dropdownMenu.style.display = 'none'; // Rende invisibile l'elemento con classe "dropdown-menu" + + attachmentElement.style.display = 'none'; // Rende invisibile l'elemento con classe "attachment" + + textareaElement.value = 'In order to chat, connect the dev board.'; // Inserisce il testo nella textarea + } else { + console.log('Elementi non trovati'); + } +} + +//Funzione che ri-abilita la TextArea per un device connesso +function enableTextareaAndLoadingIndicator() { + var textareaElement = document.getElementById('messageInput'); + var loadingIndicator = document.getElementById('loadingIndicator'); + var sendButton = document.querySelector('.btn.btn-primary.btn-icon.send-icon.rounded-circle.text-light.mb-1'); + var locationLink = document.getElementById('buttonLocation'); + var dropdownMenu = document.querySelector('.dropdown-menu'); + var attachmentElement = document.querySelector('.attachment'); + + if (textareaElement && loadingIndicator && sendButton && locationLink && dropdownMenu && attachmentElement) { + textareaElement.disabled = false; // Riabilita l'area di testo + textareaElement.style.opacity = '1'; // Ripristina l'opacità + textareaElement.style.color = ''; // Ripristina il colore del testo della textarea + + loadingIndicator.style.display = 'none'; // Nasconde l'indicatore di caricamento + + sendButton.style.pointerEvents = ''; // Riattiva gli eventi di puntatore sul pulsante + sendButton.style.opacity = '1'; // Ripristina l'opacità del pulsante + + locationLink.style.display = ''; // Riattiva l'elemento con ID "buttonLocation" + + dropdownMenu.style.display = ''; // Riattiva l'elemento con classe "dropdown-menu" + + attachmentElement.style.display = ''; // Riattiva l'elemento con classe "attachment" + + textareaElement.value = ''; // Cancella il testo nella textarea + } else { + console.log('Elementi non trovati'); + } +} // Avviene quando la pagina è stata caricata window.onload = function() { diff --git a/app/src/main/assets/assets/js/custom-contacts-list.js b/app/src/main/assets/assets/js/custom-contacts-list.js index 9951c74..cca8d87 100644 --- a/app/src/main/assets/assets/js/custom-contacts-list.js +++ b/app/src/main/assets/assets/js/custom-contacts-list.js @@ -531,27 +531,28 @@ function bindingContactListButton(){ }); } -function enableEdit(configName,input) { - const currentValue = document.getElementById(configName).textContent; +function enableEdit(configName, input) { + const paraElement = document.getElementById(configName); const inputField = document.getElementById(input); - // Imposta il valore del campo di input con il valore attuale + // Salva il valore attuale e lo imposta come valore del campo di input + const currentValue = paraElement.textContent; inputField.value = currentValue; // Mostra il campo di input e nascondi il paragrafo inputField.classList.remove('d-none'); - document.getElementById(configName).classList.add('d-none'); + paraElement.classList.add('d-none'); - // Quando viene completata la modifica, chiama la funzione saveEdit() - inputField.addEventListener('blur', saveEdit); + // Aggiungi un listener per salvare automaticamente quando si perde il focus sull'input inputField.addEventListener('blur', function() { - saveEdit(configName,input); // Chiama saveEdit() passando il nuovo valore come argomento + saveEdit(configName, input); }); + // Imposta il focus sull'input inputField.focus(); } -function saveEdit(configName,input) { +function saveEdit(configName, input) { const newValue = document.getElementById(input).value; const paraElement = document.getElementById(configName); @@ -561,8 +562,52 @@ function saveEdit(configName,input) { // Nascondi il campo di input e mostra di nuovo il paragrafo paraElement.classList.remove('d-none'); document.getElementById(input).classList.add('d-none'); + + Android.editConfigurations(configName,newValue); +} + +function deviceDisconnected(){ + var elementoDaNascondere = document.querySelector('.list-group.list-group-flush'); + var statusElement = document.getElementById('hwStatus'); + + if (elementoDaNascondere) { + elementoDaNascondere.style.display = 'none'; + } else { + console.log('Elemento non trovato'); + } + + if (statusElement) { + statusElement.textContent = 'NOT CONNECTED'; + } else { + console.log('Elemento di status non trovato'); + } } +function deviceConnected() { + var elementoDaMostrare = document.querySelector('.list-group.list-group-flush'); + var statusElement = document.getElementById('hwStatus'); + var imageElement = document.getElementById('hwImage'); + + if (elementoDaMostrare) { + elementoDaMostrare.style.display = 'block'; // Mostra nuovamente l'elemento nascosto + } else { + console.log('Elemento non trovato'); + } + + if (statusElement) { + statusElement.textContent = 'CONNECTED'; // Ripristina il testo a "CONNECTED" + } else { + console.log('Elemento di status non trovato'); + } + + if (imageElement) { + imageElement.style.filter = 'none'; // Rimuove lo stile di bianco e nero + } else { + console.log('Elemento immagine non trovato'); + } +} + + // Avviene quando la pagina è stata caricata window.onload = function() { flushChatList(); diff --git a/app/src/main/assets/dark-skin/index.html b/app/src/main/assets/dark-skin/index.html index a740ba6..bf9804d 100644 --- a/app/src/main/assets/dark-skin/index.html +++ b/app/src/main/assets/dark-skin/index.html @@ -1221,7 +1221,7 @@
Susan K. Taylor
@@ -1308,10 +1308,11 @@
} -
-

CubeCell – AB01 Dev-Board

- HTTCAB01 -
+
+

CubeCell – AB01 Dev-Board

+ HTTCAB01 +

CONNECTED

+
@@ -3841,7 +3841,6 @@ - \ No newline at end of file diff --git a/app/src/main/assets/index.html b/app/src/main/assets/index.html index 17da52d..17805fc 100644 --- a/app/src/main/assets/index.html +++ b/app/src/main/assets/index.html @@ -19,8 +19,9 @@ - + + diff --git a/app/src/main/java/com/magix/atcommand/MainActivity.kt b/app/src/main/java/com/magix/atcommand/MainActivity.kt index 26acd34..047dbb1 100644 --- a/app/src/main/java/com/magix/atcommand/MainActivity.kt +++ b/app/src/main/java/com/magix/atcommand/MainActivity.kt @@ -37,7 +37,6 @@ import java.util.concurrent.Executors import android.Manifest import android.app.Activity import android.app.Application -import android.content.res.Resources import android.database.SQLException import android.hardware.usb.UsbDeviceConnection import android.location.Location @@ -139,6 +138,7 @@ class MainActivity : AppCompatActivity() { private var timeoutTimer: Timer? = null private var isAppInForeground = false private var isReadSerialActive = false + private var timer: Timer? = null /***************************** DATABASE *****************************************/ private lateinit var db: SQLiteDatabase @@ -204,6 +204,11 @@ class MainActivity : AppCompatActivity() { override fun onPageFinished(view: WebView?, url: String?) { currentPage = url?.let { checkCurrentPage(it) }.toString() Log.d("Webview","L'utente si trova in $currentPage") + if (currentPage == "Chat"){ + if (!isDeviceConnected) { + disableTextareaAndLoadingIndicator() + } + } } } @@ -227,10 +232,10 @@ class MainActivity : AppCompatActivity() { */ userUUID = getDeviceUUID(this) myUUID = userUUID - inserisciConfigurazione(db,"userUUID",userUUID,"User UUID") + inserisciConfigurazione(db,"userUUID",userUUID,"User UUID",true) /* - Assegnazione dei valori delle stringhe + Assegnazione dei valori di default delle stringhe */ loraFreq = getString(R.string.lora_freq) loraPower = getString(R.string.lora_power) @@ -260,6 +265,9 @@ class MainActivity : AppCompatActivity() { "$loraPreambleLength,$loraCRC,$loraIQInvert,$loraSaveToFlash").toByteArray() atCmdSetLoraReceiveTimeout = (atPrefix + "RX=" + loraReceiveTimeout).toByteArray() + /* + Inserisco i valori sul DB se non sono già esistenti + */ inserisciConfigurazione(db,"loraFreq",loraFreq,"Lora Frequency") inserisciConfigurazione(db,"loraPower",loraPower,"Lora Power") inserisciConfigurazione(db,"loraSF",loraSF,"Lora Spread Factory") @@ -471,6 +479,12 @@ class MainActivity : AppCompatActivity() { super.onStart() } + override fun onStop() { + super.onStop() + Log.d("USBSerial","Stopping..") + stopCheckReadSerialStatus() + } + private fun configureDevice(){ if (!isDeviceConfigured) { val usbManager = getSystemService(Context.USB_SERVICE) as UsbManager @@ -508,40 +522,40 @@ class MainActivity : AppCompatActivity() { port = driver.ports[0] port.open(connection) port.setParameters(115200, 8, UsbSerialPort.STOPBITS_1, UsbSerialPort.PARITY_NONE) + + /* + Configurazione del dispositivo + */ + isDeviceConfigured = setDeviceConfig(port) + if (isDeviceConfigured) { + Log.d("USBManager", "Device configurato correttamente,popolo i dati sul db.") + val mName = port.device.manufacturerName + val mVendorId = port.device.vendorId + val mDeviceId = port.device.deviceId + val mProductId = port.device.productId + val mProductName = port.device.productName + val mSerialNumber = port.device.serialNumber + val mVersion = port.device.version + if (mName != null) { + inserisciConfigurazione(db, "mName", mName, "Manufacture Name",true) + } + inserisciConfigurazione(db, "mVendorId", mVendorId.toString(), "Manufacture Vendor ID",true) + inserisciConfigurazione(db, "mDeviceId", mDeviceId.toString(), "Manufacture Device ID",true) + inserisciConfigurazione(db, "mProductId", mProductId.toString(), "Manufacture Product ID",true) + if (mProductName != null) { + inserisciConfigurazione(db, "mProductName", mProductName, "Manufacture Product Name",true) + } + if (mSerialNumber != null) { + inserisciConfigurazione(db, "mSerialNumber", mSerialNumber, "Manufacture Serial Number",true) + } + inserisciConfigurazione(db, "mVersion", mVersion, "Manufacture Version",true) + } + } catch (e: Exception) { // Handle exceptions here e.printStackTrace() // Or perform other error handling tasks } - - /* - Configurazione del dispositivo - */ - isDeviceConfigured = setDeviceConfig(port) - if (isDeviceConfigured) { - Log.d("USBManager", "Device configurato correttamente,popolo i dati sul db.") - val mName = port.device.manufacturerName - val mVendorId = port.device.vendorId - val mDeviceId = port.device.deviceId - val mProductId = port.device.productId - val mProductName = port.device.productName - val mSerialNumber = port.device.serialNumber - val mVersion = port.device.version - if (mName != null) { - inserisciConfigurazione(db, "mName", mName, "Manufacture Name") - } - inserisciConfigurazione(db, "mVendorId", mVendorId.toString(), "Manufacture Vendor ID") - inserisciConfigurazione(db, "mDeviceId", mDeviceId.toString(), "Manufacture Device ID") - inserisciConfigurazione(db, "mProductId", mProductId.toString(), "Manufacture Product ID") - if (mProductName != null) { - inserisciConfigurazione(db, "mProductName", mProductName, "Manufacture Product Name") - } - if (mSerialNumber != null) { - inserisciConfigurazione(db, "mSerialNumber", mSerialNumber, "Manufacture Serial Number") - } - inserisciConfigurazione(db, "mVersion", mVersion, "Manufacture Version") - } } - } /* @@ -583,16 +597,17 @@ class MainActivity : AppCompatActivity() { } } else { isReadSerialActive = false - Log.d("Buffering", "Thread fermato in questo momento...") + Log.d("USBSerial", "Thread fermato in questo momento...") } } + Log.d("USBSerial","Thrad interrotto!") } if (!isThreadReadingRunning) { - Log.d("Buffering", "Avvio il Thread di lettura.") + Log.d("USBSerial", "Avvio il Thread di lettura.") readThread.start() } else { - Log.d("Buffering", "Thread di lettura già avviato.") + Log.d("USBSerial", "Thread di lettura già avviato.") } } @@ -606,8 +621,8 @@ class MainActivity : AppCompatActivity() { return } - val timer = Timer() - timer.scheduleAtFixedRate(timerTask { + timer = Timer() + timer!!.scheduleAtFixedRate(timerTask { if (isReadSerialActive) { Log.d("USBSerial", "La funzione readSerial() è attiva.") removeOverlayDeviceDisconnected() @@ -628,6 +643,15 @@ class MainActivity : AppCompatActivity() { isCheckSerialStatusStarted = true } + /* + Fermo il thread di controllo seriale + */ + fun stopCheckReadSerialStatus() { + timer?.cancel() + timer = null + isCheckSerialStatusStarted = false + } + /* Conteggio delle new lines */ @@ -1001,6 +1025,19 @@ class MainActivity : AppCompatActivity() { context.startActivity(notificationIntent) } + fun updateConfiguration(configName: String, configValue: String, db: SQLiteDatabase): Boolean { + val values = ContentValues() + values.put("configValue", configValue) + + val rowsAffected = db.update( + "configurations", + values, + "configName = ?", + arrayOf(configName) + ) + + return rowsAffected > 0 + } /* @@ -1210,13 +1247,13 @@ class MainActivity : AppCompatActivity() { configName: String, configValue: String, configDescription: String, + modifyIfExists: Boolean = false ): Long { val contentValues = ContentValues().apply { put("configName", configName) put("configValue", configValue) put("configDescription", configDescription) } - Log.d("DbHandler", "Ho inserito la configurazione: $configName,$configValue,$configDescription") val existingConfigCursor = db.query( "configurations", @@ -1229,13 +1266,19 @@ class MainActivity : AppCompatActivity() { ) val exists = existingConfigCursor.count > 0 existingConfigCursor.close() + return if (exists) { - db.update("configurations", contentValues, "configName = ?", arrayOf(configName)).toLong() + if (modifyIfExists) { + db.update("configurations", contentValues, "configName = ?", arrayOf(configName)).toLong() + } else { + -1 // Se non si modifica e esiste già, restituisci -1 + } } else { db.insert("configurations", null, contentValues) } } + /* Inserire un messaggio */ @@ -1556,12 +1599,23 @@ class MainActivity : AppCompatActivity() { } } + /* + Chiama la funzione JavaScript 'disableTextareaAndLoadingIndicator' + */ + fun disableTextareaAndLoadingIndicator() { + runOnUiThread { + webView.evaluateJavascript("disableTextareaAndLoadingIndicator();") { + } + } + } + /* Chiama la funzione JavaScript 'addOverlay' */ fun addOverlayDeviceDisconnected() { + isDeviceConnected = false runOnUiThread { - webView.evaluateJavascript("addOverlayDeviceDisconnected();") { + webView.evaluateJavascript("deviceDisconnected();") { } } } @@ -1572,7 +1626,7 @@ class MainActivity : AppCompatActivity() { fun removeOverlayDeviceDisconnected() { isDeviceConnected = true runOnUiThread { - webView.evaluateJavascript("removeOverlayDeviceDisconnected();") { + webView.evaluateJavascript("deviceConnected();") { } } } @@ -1918,6 +1972,12 @@ class WebAppInterface(private val mainActivity: MainActivity) { mainActivity.sendJsonToJSConfigList(jsonString) } + @JavascriptInterface + fun editConfigurations(configName: String,configValue: String) { + val messages = mainActivity.updateConfiguration(configName,configValue,db) + Log.d("DBHadnler", "messages è: $messages") + } + } /**