Tuesday, August 6, 2013

Autostart Lua script on RasPi+Archlinux+Mihini at power up

After having setup Mihini on my Raspberry Pi/ArchLinux and having blinked a few LEDs via GPIOs, I wanted to try out configuring Mihini to start a Lua script at power up.

Benjamin Cab√© (blog | twitter) and the mihini contributors (twitter) pointed me in the right direction: Creating Launcher & Installing App | Appmon Daemon

First up, here is a code to blink four LEDs. How is it better than the previous code that blinked four LEDs together? Well, this one used the sched module to blink the four different LEDs at different rates using 4 tasks in parallel. 4 instances of tasks are created from the same function blink() using the sched.run. For each instance, we pass different parameters to blink a different LED at a different rate. We use sched.wait() within a task to relinquish control to another task waiting in queue - this is how collaborative multitasking is implemented here using the sched module.

blinky.lua:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
-- All four LEDs blinking at different rates (cooperative multitasking)

package.path = '/opt/mihini/lua/?.lua;/opt/mihini/lua/?/init.lua;' .. package.path
package.cpath = '/opt/mihini/lua/?.so;' .. package.cpath

local sched = require "sched"
local gpio = require"gpio"

local clock = os.clock

local function sleep(n)  -- seconds
  local t0 = clock()
  while clock() - t0 <= n do end
end

local function toggle_pin(n)
  local stat = gpio.read(n)
  if stat == 1 then
    gpio.write(n,0)
  elseif stat == 0 then
    gpio.write(n,1)
  end
end

local function blink(pin,timeout_secs)
  gpio.configure(pin, {direction="out", edge="both", activelow="0"})
  gpio.write(pin, 1)
  while true do
    toggle_pin(pin)
    sched.wait(timeout_secs)
  end
end

sched.run(blink,22,0.25)
sched.run(blink,23,0.5)
sched.run(blink,24,1)
sched.run(blink,25,2)
sched.loop()

Next step was to configure my Raspberry Pi to start executing this script every time at boot up. Here is how I got that done:
  1. Open a new ssh terminal to access Raspberry Pi's console. You can do this from within Eclipse itself - switch to "Remote System Explorer" perspective, make sure your Raspberry Pi's IP address is listed in the Remote Systems pane. Then ensure that a connection to Raspberry Pi is established (Right click on IP address and click connect). Further on, right click on "Ssh Terminals" listed under your RPi's IP address and select "Launch Terminal"
  2. In the terminal, issue the command "netstat -lptu". Ensure that app_daemon is listening on 4242 as shown below, if it is not, then you may have to redo the steps listed under "Finalizing mihini installation" here
    using netstat to check if app_demon is running on port 4242
  3. Now use the Sftp Files feature of Remote System Explorer within Eclipse LDT to create a new folder in your home directory. Since I have logged in as root, my home folder is /root.
    Name this folder "blinky"
    Creating a new folder called "blinky" in /root
  4. Within the blinky folder, create two blank files named "blinky.lua" and "run".
  5. You can double click on these files while in Remote Systems Explorer view and a new pane will open up allowing you to edit them.
  6. In "blinky.lua", paste the LED blinking code presented above and save it.
  7. In "run" paste the following two lines and save:
    #!/bin/sh
    lua blinky.lua

    Editing "blinky.lua" and "run" present in /root/blinky on the Raspberry Pi remotely
    from within Eclipse LDT
  8. We are running Eclipse on Windows, where as Raspberry Pi is running Linux, hence there is a need to convert the line endings from windows format to unix format especially for the run script. To do this, issue the command:
    pacman -Syu dos2unix
    via the SSH Terminal to RPi to install the dos2unix utility. Further, issue the command :
    dos2unix ~/blinky/run
    to convert the run scripts to unix format. On successful execution, you will see the message:
    dos2unix: converting file /root/blinky/run to Unix format ...
  9. Now we need to communicate with the mihini runtime and install the blinky app in the app container. Mihini telnet server on port 2000. To connect to it issue the following commend to RPi (via SSH Terminal):
    telnet localhost 2000
    You will be greeted with the following message:
    Trying 127.0.0.1...
    Connected to localhost.
    Escape character is '^]'.
    Lua interactive shell
    >
  10. Now you can issue commands to the runtime. The first thing we need to do is to enable the app container, issue the following command to the runtime:
    agent.config.appcon.activate = true
  11. Press "Ctrl+D" to exit the runtime and restart your RPi by issuing the command "reboot". Allow a few seconds for RPi to bootup, and then reconnect to it using the Remote Systems Explorer and open a SSH Terminal. Also re-enter the Mihni runtime by issuing the command "telnet localhost 2000"
  12. Issue the following two commands to install your blinky app:
    > appcon = require 'agent.appcon'
    > = appcon.install('blinky', '/root/blinky', true)

    If successful, Mihini will respond with an "=ok". Observe that the third argument passed to install() is true which means that the app will autostart at boot up.
  13. You will see the LEDs blinking now. Even if you restart your Raspberry Pi, the LED, the blinky app will start running immediately after the system has booted. 
  14. If you want to check the list of installed apps you can do so by issuing the command ":appcon.list()" to the Mihini runtime.
    > appcon = require 'agent.appcon'
    > :appcon.list()
    = { blinky = {
          autostart = true,
          runnable = true } }
  15. To uninstall the app, you can use the uninstall() function like so:
    > appcon = require 'agent.appcon'
    > :appcon.uninstall('blinky')
    = "ok"
    = nil
  16. Note: Every time you reboot and reconnect to SSH Terminal on RPi, you will have to issue the command telnet localhost 2000 to connect to the Mihini runtime. To communicate with the app container, make sure to issue appcon = require 'agent.appcon'as the first command when you enter the mihini interactive shell. Use Ctrl+D to exit the shell whenever needed.
video

NOTE: During my trials, I observed that the LEDs started blinking around 20 seconds after the application of power to RPi. This is when the Raspberry Pi was plugged into my WiFi Router via Ethernet. So 20 seconds was the time for Linux to boot up and for app_daemon to start executing the blinky.lua script.
When I powered the Raspberry Pi without any network connection, the interval from power up till the time the LEDs started blinking was 40 seconds. I guess the DHCP fails and retries must have caused the additional delays.

NOTE2: Mihini's appmon_daemon sends log messages to syslog. If you want to capture and view these messages, make sure to install syslog-ng (pacman -Syu syslog-ng). Also enable syslog-ng service (systemctl enable syslog-ng). To view only those messages which are logged by appmon_daemon, use the command cat /var/log/everything.log | grep appmon

0 comments:

Post a Comment