Skip to content

Latest commit

 

History

History
167 lines (120 loc) · 4.95 KB

README.md

File metadata and controls

167 lines (120 loc) · 4.95 KB

Lectures Exercises

Lecture 5 - Case Study - Implementing an Alerting Service

Content:

  • Problem Definition
  • Architecture
  • Rollout
  • Further Improvements

Problem Definition

LoudHailer is a voice recognition and alerting service to help people getting help when they are in need.

https://github.com/qaismyname/Loudhailer

img

img

Architecture

img

Akka Streams (Scala)

img

Schematic structure of Akka streams applications

Backend

Source.tick(0 second, 5 seconds, ())
        .map(sample)
        .map(analyse)
        .runForeach(act)
def sample: Unit => Sample = _ => SoundRecorder.sample
def analyse: Sample => Future[Hypothesis] = {
    case Xor.Left(e) => Future.failed(e)
    case Xor.Right(data) =>
      for {
        response <- request(data)
        hypothesis <- Unmarshal(response.entity).to[Hypothesis]
      } yield hypothesis
  }
  
def request: Array[Byte] => Future[HttpResponse] = data =>
  Http().singleRequest(HttpRequest(
    method = HttpMethods.POST,
    uri = witUrl,
    headers = List(headers.RawHeader("Authorization", s"Bearer $witToken")),
    entity = HttpEntity(contentType = `audio/wav`, data)))
def act: Future[Hypothesis] => Unit = f => {
    f.onComplete {
      case Success(h) => if (blackList.contains(response.hypothesis)) broadcastEvent()
      case Failure(e) => e.printStackTrace()
    }
  }
  
def broadcastEvent() = {
    val body = Map(
      "to" -> "/topics/alert".asJson,
      "data" -> Map(
        "message" -> "An incident occurred.".asJson
      ).asJson
    ).asJson

    Http().singleRequest(
      HttpRequest(
        method = HttpMethods.POST,
        uri = fireBaseUrl,
        headers = List(headers.RawHeader("Authorization", s"key=$fireBaseToken")),
        entity = HttpEntity(contentType = `application/json`, body.noSpaces)))
  }

img

Source

img

Mobile (Android Kotlin)

class MyFirebaseMessagingService : FirebaseMessagingService() {

    override fun onMessageReceived(remoteMessage: RemoteMessage?) {

        // Check if the message contains a data payload.
        if (remoteMessage != null && remoteMessage.data.size > 0) {
            val message: String? = remoteMessage.data["message"]
            if (message != null)
                sendNotification(message)
        }

    }

    private fun sendNotification(message: String) {
        val intent = Intent(this, AlarmActivity::class.java)
        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
        intent.putExtra(AlarmActivity.MESSAGE, message)
        startActivity(intent)
    }
 <activity android:name=".MainActivity">
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>

<service android:name=".MyFirebaseMessagingService">
    <intent-filter>
        <action android:name="com.google.firebase.MESSAGING_EVENT" />
    </intent-filter>
</service>

<activity
    android:name=".AlarmActivity"
    android:configChanges="orientation|keyboardHidden|screenSize"
    android:label="@string/title_activity_alarm"
    android:theme="@style/FullscreenTheme">
</activity>

img

Source

Rollout

img

img

img

Further Improvements

Create Feedback Loop

img