rangeelo
rangeelo

Reputation: 118

monitor system users on raspberry pi with akka actors

I've a raspberry pi on my network with an LED strip attached to it. My purpose is to create a jar file that will sit on the pi, monitor system events such as logins and load average, and drive the LED based on the those inputs.

To continuosly monitor the logged in users, I am trying to use akka actors. Using the examples provided here, this is what I've gotten so far :

import com.pi4j.io.gpio.GpioFactory
import com.pi4j.io.gpio.RaspiPin

import sys.process._

import akka.actor.{Actor, Props, ActorSystem}
import scala.concurrent.duration._


val who :String = "who".!!

class Blinker extends Actor {

  private def gpio = GpioFactory.getInstance
  private def led = gpio.provisionDigitalOutputPin(RaspiPin.GPIO_08)

  def receive = {
    case x if who.contains("pi") => led.blink(250)
    case x if who.contains("moocow") => println("falalalala")
  }

  val blinker = system.actorOf(Props(classOf[Blinker], this))

  val cancellable =  system.scheduler.schedule(
    0 milliseconds,
    50 milliseconds,
    blinker,
    who)
}

However, system is not recognised by my IDE (IntelliJ) and it says, cannot resolve symbol

I also have a main object like this:

object ledStrip  {

  def main(args: Array[String]): Unit = {

    val blink = new Blinker
    // blink.receive

  }

}

In main, I'm not quite sure how to initialise the application.

Needless to say, this my first time writing a scala program Help?

Edit::

Here is the updated program after incorporating what Michal has said

class Blinker extends Actor {

  val who: String = "who".!!

  private val gpio = GpioFactory.getInstance
  private val led = gpio.provisionDigitalOutputPin(RaspiPin.GPIO_08)

  def receive = {
    case x if who.contains("pi") => led.blink(250)
    case x if who.contains("moocow") => println("falalalala")
  }

  val system = ActorSystem()


}



object ledStrip  extends  Blinker {

  def main(args: Array[String]): Unit = {

    val blinker = system.actorOf(Props(classOf[Blinker], this))
    import system.dispatcher

    val cancellable =
    system.scheduler.schedule(
      50 milliseconds,
      5000 milliseconds,
      blinker,
      who)

  }

}

This program compiles fine, but throws the following error upon execution:

Exception in thread "main" java.lang.ExceptionInInitializerError at ledStrip.main(ledStrip.scala) Caused by: akka.actor.ActorInitializationException: You cannot create an instance of [ledStrip$] explicitly using the constructor (new). You have to use one of the 'actorOf' factory methods to create a new actor. See the documentation. at akka.actor.ActorInitializationException$.apply(Actor.scala:194) at akka.actor.Actor.$init$(Actor.scala:472) at Blinker.(ledStrip.scala:15) at ledStrip$.(ledStrip.scala:34) at ledStrip$.(ledStrip.scala) ... 1 more

Edit 2

Code that compiles and runs (behaviour is still not as desired)< blink(1500) is never executed when user: pi logs out from the shell>

object sysUser {
  val who: String = "who".!!
}

class Blinker extends Actor {

  private val gpio = GpioFactory.getInstance
  private val led = gpio.provisionDigitalOutputPin(RaspiPin.GPIO_08)

  def receive = {
    case x if x.toString.contains("pi")  => led.blink(50)
    case x if x.toString.contains("moocow")  => println("falalalala")
    case _ => led.blink(1500)
  }
}

object ledStrip  {
  def main(args: Array[String]): Unit = {
    val system = ActorSystem()

    val blinker = system.actorOf(Props[Blinker], "blinker")
    import system.dispatcher

    val cancellable =
      system.scheduler.schedule(
        50 milliseconds,
        5000 milliseconds,
        blinker,
        sysUser.who)
  }
}

Upvotes: 0

Views: 169

Answers (2)

atline
atline

Reputation: 31634

Seems it is just a akka usage issue. I don't know why you do something seems strange, so I change them for change1, change2, change3, FYI.

class Blinker extends Actor {
  val who: String = "who".!!

  private val gpio = GpioFactory.getInstance
  private val led = gpio.provisionDigitalOutputPin(RaspiPin.GPIO_08)

  def receive = {
    case x if who.contains("pi") => led.blink(250)
    case x if who.contains("moocow") => println("falalalala")
  }
}

object ledStrip { // change1
  def main(args: Array[String]): Unit = {
    val system = ActorSystem() // change2

    val blinker = system.actorOf(Props(classOf[Blinker])) // change3
    import system.dispatcher

    val cancellable =
    system.scheduler.schedule(
      50 milliseconds,
      5000 milliseconds,
      blinker,
      who)
  }
}

Upvotes: 1

Michal Borowiecki
Michal Borowiecki

Reputation: 4324

Well, it looks like you haven't defined "system" anywhere. See this example for instance: https://doc.akka.io/docs/akka/current/actors.html#here-is-another-example-that-you-can-edit-and-run-in-the-browser-

you'll find this line there:

 val system = ActorSystem("pingpong")

That's what creates the ActorSystem and defines the val called "system", which you then call methods on.

In the main, I don't think you want to create another instance with "new Blinker", just use:

system.actorOf(Props[Blinker], "blinker")

(which you are already doing and putting it into the "blinker" val)

Upvotes: 1

Related Questions