Skip to content

Commit

Permalink
* added wake time disables screensaver feature (in progress)
Browse files Browse the repository at this point in the history
* refresh page when network disconnected or page error
* allow for utf-8 text in speak command for http
  • Loading branch information
thanksmister committed May 27, 2021
1 parent 7da979a commit 6fbf0eb
Show file tree
Hide file tree
Showing 12 changed files with 345 additions and 48 deletions.
42 changes: 41 additions & 1 deletion WallPanelApp/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,37 @@ apply plugin: 'com.google.firebase.crashlytics'
def versionMajor = 0
def versionMinor = 9
def versionPatch = 4
def versionBuild = 7 // bump for dog food builds, public betas, etc.
def versionBuild = 9 // bump for dog food builds, public betas, etc.

def CODE() {
Properties properties = new Properties()
properties.load(project.rootProject.file('local.properties').newDataInputStream())
return properties.getProperty("code");
}

def HASS_URL() {
Properties properties = new Properties()
properties.load(project.rootProject.file('local.properties').newDataInputStream())
return properties.getProperty("hassUrl");
}

def BROKER() {
Properties properties = new Properties()
properties.load(project.rootProject.file('local.properties').newDataInputStream())
return properties.getProperty("broker");
}

def BROKER_PASS() {
Properties properties = new Properties()
properties.load(project.rootProject.file('local.properties').newDataInputStream())
return properties.getProperty("brokerPass");
}

def BROKER_USERNAME() {
Properties properties = new Properties()
properties.load(project.rootProject.file('local.properties').newDataInputStream())
return properties.getProperty("brokerUsername");
}

android {
kapt {
Expand Down Expand Up @@ -61,6 +91,11 @@ android {
buildConfigField "String", BASE_ENVIRONMENT, '"DEV_ENVIRONMENT"'
applicationId "com.thanksmister.iot.wallpanel"
versionName "${versionMajor}.${versionMinor}.${versionPatch} Build ${versionBuild}-DEV"
buildConfigField 'Integer', 'CODE', CODE()
buildConfigField 'String', 'HASS_URL', "\"" + HASS_URL() +"\""
buildConfigField 'String', 'BROKER', "\"" + BROKER() +"\""
buildConfigField 'String', 'BROKER_PASS', "\"" + BROKER_PASS() +"\""
buildConfigField 'String', 'BROKER_USERNAME', "\"" + BROKER_USERNAME() +"\""
}
qa {
dimension "default"
Expand All @@ -73,6 +108,11 @@ android {
buildConfigField "String", BASE_ENVIRONMENT, '"PROD_ENVIRONMENT"'
applicationId "com.thanksmister.iot.wallpanel"
versionName "${versionMajor}.${versionMinor}.${versionPatch} Build ${versionBuild}"
buildConfigField 'Integer', 'CODE', '1234'
buildConfigField 'String', 'HASS_URL', '""'
buildConfigField 'String', 'BROKER', '""'
buildConfigField 'String', 'BROKER_USERNAME', '""'
buildConfigField 'String', 'BROKER_PASS', '""'
}
}

Expand Down
25 changes: 20 additions & 5 deletions WallPanelApp/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,25 @@
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />

<!-- Permission to record video -->
<uses-permission android:name="android.permission.CAMERA" />

<!-- Permissions to record audio from web page -->
<uses-permission android:name="android.permission.MICROPHONE" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />

<!-- Permission to change the screen brightness -->
<uses-permission
android:name="android.permission.WRITE_SETTINGS"
tools:ignore="ProtectedPermissions" />

<!-- Features supported -->
<uses-feature android:name="android.hardware.audio.low_latency" />
<uses-feature android:name="android.hardware.audio.pro" />
<uses-feature android:name="android.hardware.microphone" />

<uses-feature
android:name="android.hardware.camera"
android:required="false" />
Expand All @@ -58,13 +71,14 @@
<activity
android:name="com.thanksmister.iot.wallpanel.ui.activities.BrowserActivityNative"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true"
android:enabled="true"
android:exported="true"
android:hardwareAccelerated="true"
android:label="@string/app_name"
android:theme="@style/AppThemeFullScreen">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.HOME" />
<category android:name="android.intent.category.LAUNCHER" />
<category android:name="android.intent.category.DEFAULT" />
Expand All @@ -91,10 +105,11 @@
android:enabled="true"
android:exported="true">
<intent-filter>
<category android:name="android.intent.category.DEFAULT"/>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
<action android:name="android.intent.action.LOCKED_BOOT_COMPLETED"/>
<action android:name="android.intent.action.QUICKBOOT_POWERON"/>
<category android:name="android.intent.category.DEFAULT" />

<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="android.intent.action.LOCKED_BOOT_COMPLETED" />
<action android:name="android.intent.action.QUICKBOOT_POWERON" />
</intent-filter>
</receiver>

Expand Down
34 changes: 34 additions & 0 deletions WallPanelApp/src/main/assets/error_page.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<!--
~ Copyright (c) 2021 ThanksMister LLC
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software distributed
~ under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="styles.css">
</head>
<body>

<div class="wrapper">
<div class="box">
<center>
<img src="icon.png" width="360px" height="360px">
<h1>Connection Error</h1>
<p>This page will automatically reload when connected.</p>
</center>
</div>
</div>

</body>
</html>
Binary file added WallPanelApp/src/main/assets/icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
62 changes: 62 additions & 0 deletions WallPanelApp/src/main/assets/styles.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
html { box-sizing: border-box; }

*,
*::before,
*::after { box-sizing: inherit; }

body * {
margin: 0;
padding: 0;
}

body {
font: normal 100%/1.15 "Merriweather", serif;
background-color: #ffffff;
color: #fff;
}

.wrapper {
position: relative;
max-width: 1298px;
height: auto;
margin: 1em auto 0 auto;
}

/* https://www.flaticon.com/authors/vectors-market */
/* https://www.flaticon.com/authors/icomoon */
.box {
max-width: 70%;
min-height: auto;
margin: 0 auto;
padding: 2em 0em;
text-align: center;
}

h1, p:not(:last-of-type) { }

h1 {
margin: 0 0 1rem 0;
font-size: 2em;
color: #216f79;
}

p {
margin-top: 0.5em;
margin-bottom: 0.5em;
font-size: 1.5em;
text-align: center;
color: #216f79;
}

p:first-of-type { margin-top: 0em; }

p > a {
border-bottom: 1px dashed #216f79;
font-style: italic;
text-decoration: none;
color: #216f79;
}

p > a:hover { text-shadow: 0 0 6px #216f79; }

p img { vertical-align: bottom; }
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import com.koushikdutta.async.http.body.JSONObjectBody
import com.koushikdutta.async.http.body.StringBody
import com.koushikdutta.async.http.server.AsyncHttpServer
import com.koushikdutta.async.http.server.AsyncHttpServerResponse
import com.koushikdutta.async.util.Charsets
import com.thanksmister.iot.wallpanel.R
import com.thanksmister.iot.wallpanel.modules.*
import com.thanksmister.iot.wallpanel.persistence.Configuration
Expand Down Expand Up @@ -71,6 +72,9 @@ import org.json.JSONException
import org.json.JSONObject
import timber.log.Timber
import java.io.IOException
import java.net.URLDecoder
import java.net.URLEncoder
import java.net.URLEncoder.encode
import java.nio.ByteBuffer
import java.util.*
import java.util.concurrent.atomic.AtomicBoolean
Expand Down Expand Up @@ -127,7 +131,7 @@ class WallPanelService : LifecycleService(), MQTTModule.MQTTListener {
mqttAlertMessageShown = false
mqttConnecting = false
if (!mqttConnected) {
sendToastMessage(getString(R.string.toast_connect_retry))
//sendToastMessage(getString(R.string.toast_connect_retry))
mqttModule?.restart()
}
}
Expand Down Expand Up @@ -414,10 +418,18 @@ class WallPanelService : LifecycleService(), MQTTModule.MQTTListener {
}
}

// TODO text to speech requies content type 'Content-Type': 'application/json; charset=UTF-8'
private fun startHttp() {
if (httpServer == null && configuration.httpEnabled) {
Timber.d("startHttp")

// TODO this is a hack to get utf-8 working, we need to switch http server libraries
val charsetsClass = Charsets::class.java
val us_ascii = charsetsClass.getDeclaredField("US_ASCII")
us_ascii.isAccessible = true
us_ascii.set(Charsets::class.java, Charsets.UTF_8)
httpServer = AsyncHttpServer()

httpServer?.addAction("*", "*") { request, response ->
Timber.i("Unhandled Request Arrived")
response.code(404)
Expand All @@ -432,7 +444,8 @@ class WallPanelService : LifecycleService(), MQTTModule.MQTTListener {
var result = false
if (request.body is JSONObjectBody) {
Timber.i("POST Json Arrived (command)")
result = processCommand((request.body as JSONObjectBody).get())
val body = (request.body as JSONObjectBody).get()
result = processCommand(body)
} else if (request.body is StringBody) {
Timber.i("POST String Arrived (command)")
result = processCommand((request.body as StringBody).get())
Expand Down Expand Up @@ -576,8 +589,12 @@ class WallPanelService : LifecycleService(), MQTTModule.MQTTListener {
}
if (commandJson.has(COMMAND_WAKE)) {
if (commandJson.getBoolean(COMMAND_WAKE).or(false)) {
val wakeTime = commandJson.optLong(COMMAND_WAKETIME, SCREEN_WAKE_TIME / 1000) * 1000
wakeScreenOn(wakeTime)
val wakeTime = commandJson.optLong(COMMAND_WAKETIME, 0) * 1000
if(wakeTime > 0) {
wakeScreenOn(wakeTime)
} else {
wakeScreen()
}
} else {
wakeScreenOff()
}
Expand Down Expand Up @@ -663,16 +680,17 @@ class WallPanelService : LifecycleService(), MQTTModule.MQTTListener {
audioPlayer?.setVolume(vol, vol)
}

// TODO we need to url decode incoming strings to support other languages
private fun speakMessage(message: String) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
if (textToSpeechModule != null) {
textToSpeechModule!!.speakText(message)
}
textToSpeechModule?.speakText(message)
} else {
sendAlertMessage("Text to Speech is not supported on this device's version of Android")
}
}

// TODO temporarily wake screen
private fun switchScreen() {
private fun wakeScreen() {
val intent = Intent(BROADCAST_SCREEN_WAKE)
val bm = LocalBroadcastManager.getInstance(applicationContext)
bm.sendBroadcast(intent)
Expand All @@ -682,19 +700,21 @@ class WallPanelService : LifecycleService(), MQTTModule.MQTTListener {
private fun wakeScreenOn(wakeTime: Long) {
if (partialWakeLock != null && !partialWakeLock!!.isHeld) {
partialWakeLock?.acquire(wakeTime)
wakeScreenHandler.postDelayed({
wakeScreenOff()
}, wakeTime)
wakeScreenHandler.postDelayed(clearWakeScreenRunnable, wakeTime)
sendWakeScreenOn()
}
}

@SuppressLint("WakelockTimeout")
private val clearWakeScreenRunnable = Runnable {
wakeScreenOff()
}

private fun wakeScreenOff() {
wakeScreenHandler.removeCallbacks(clearWakeScreenRunnable)
if (partialWakeLock != null && partialWakeLock!!.isHeld) {
partialWakeLock?.release()
sendWakeScreenOff()
partialWakeLock!!.release()
}
sendWakeScreenOff()
}

private fun changeScreenBrightness(brightness: Int) {
Expand Down Expand Up @@ -1014,7 +1034,7 @@ class WallPanelService : LifecycleService(), MQTTModule.MQTTListener {
override fun onMotionDetected() {
Timber.i("Motion detected")
if (configuration.cameraMotionWake) {
switchScreen()
wakeScreen()
}
publishMotionDetected()
}
Expand All @@ -1028,7 +1048,7 @@ class WallPanelService : LifecycleService(), MQTTModule.MQTTListener {
Timber.d("configuration.cameraMotionBright ${configuration.cameraMotionBright}")
if (configuration.cameraFaceWake) {
configurePowerOptions()
switchScreen() // temp turn on screen
wakeScreen() // temp turn on screen
}
publishFaceDetected()
}
Expand All @@ -1052,5 +1072,6 @@ class WallPanelService : LifecycleService(), MQTTModule.MQTTListener {
const val BROADCAST_SCREEN_WAKE_ON = "BROADCAST_SCREEN_WAKE_ON"
const val BROADCAST_SCREEN_WAKE_OFF = "BROADCAST_SCREEN_WAKE_OFF"
const val BROADCAST_SCREEN_BRIGHTNESS_CHANGE = "BROADCAST_SCREEN_BRIGHTNESS_CHANGE"
const val BROADCAST_CONNTED = "BROADCAST_SCREEN_BRIGHTNESS_CHANGE"
}
}
Loading

0 comments on commit 6fbf0eb

Please sign in to comment.