Category Archives: Linux - Page 3

Raspbianでスクリーンショットを撮る

Raspbianでスクリーンショットを撮ろうと思ったらパッケージが入っていなかったようなのでインストールしてみました。

$ sudo apt-get install ksnapshot

左下メニューの”グラフィックス”→”KSnapshot”から起動出来ます。

snapshot2

Raspberry PiでC言語を使い2つのスレッドを200ミリ秒と2秒ごとに処理させる

Arduinoだとタイマー割り込みを使って処理したいところですが残念ながら私の調べた限りRaspberry Piでは無さそうなのでC言語とスレッドを利用し近い処理をさせることにしました。

$ vi thread_test.c

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>

void *thread_function1( void *ptr );
void *thread_function2( void *ptr );

int main(void){
     pthread_t thread1, thread2;
     useconds_t tick1 = 200000;
     useconds_t tick2 = 2000000;

     pthread_create( &thread1, NULL, thread_function1, (void *) &tick1);
     pthread_create( &thread2, NULL, thread_function2, (void *) &tick2);

     pthread_join( thread1, NULL);
     pthread_join( thread2, NULL);

     return 0;
}

void *thread_function1(void *ptr){
    useconds_t tick = *( int * )ptr;

    while(1){
        printf("function1\n");
        usleep(tick);
    }
}

void *thread_function2(void *ptr){
    useconds_t tick = *( int * )ptr;

    while(1){
        printf("function2\n");
        usleep(tick);
    }
}

コンパイルします
$ gcc thread_test.c -pthread

実行
$ ./a.out

しかし、これでは共有資源を利用したプログラムを書いた場合取り合いになり下手をするとデータが失われたりする場合があるため排他制御するようにします。

$ vi thread_test.c

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>

void *thread_function1( void *ptr );
void *thread_function2( void *ptr );

pthread_mutex_t mutex;
pthread_cond_t cond;
int count = 0;

useconds_t tick1 = 200000;
useconds_t tick2 = 2000000;

int main(void){
     pthread_t thread1, thread2;

     pthread_mutex_init(&mutex, NULL);

     pthread_create( &thread1, NULL, thread_function1, (void *) &tick1);
     pthread_create( &thread2, NULL, thread_function2, (void *) &tick2);

     pthread_join( thread1, NULL);
     pthread_join( thread2, NULL);

     pthread_mutex_destroy(&mutex);

     return 0;
}

void *thread_function1(void *ptr){
    useconds_t tick = *( int * )ptr;

    while(1){
        pthread_mutex_lock(&mutex);

        printf("function1 %d\n",count++);
        pthread_mutex_unlock(&mutex);
        usleep(tick);
    }
}

void *thread_function2(void *ptr){
    useconds_t tick = *( int * )ptr;

    while(1){
        pthread_mutex_lock(&mutex);

        printf("function2 %d\n",count++);
        pthread_mutex_unlock(&mutex);
        usleep(tick);
    }
}

コンパイルします
$ gcc thread_test.c -pthread

実行
$ ./a.out
function2 0
function1 1
function1 2
function1 3
function1 4
function1 5
function1 6
function1 7
function1 8
function1 9
function1 10
function2 11
function1 12
function1 13
function1 14
function1 15
function1 16
function1 17
function1 18

Raspberry PiでAdafruit製LCD(カラーバックライト+ボタン付きシールド)を利用する

Raspberry PiでAdafruit RGB Negative 16×2 LCD+Keypad Kit for Raspberry Pi – を使ったプログラムをAdafruitの公式ライブラリを使い書いてみました。

シールドの組立、ライブラリのインストールや使い方は公式の方をご覧ください。

下記のソースコードはRasbperry Piの時間とインターフェイス毎のIPアドレスをLCDに表示します。

インターフェイス毎のローカルIPアドレスを取得するために”netifaces”ライブラリを使用しております。
$ apt-get install python-netifaces

/LCDディレクトリを作成し公式ライブラリを入れておきます。
$ sudo mkdir /LCD

$ sudo vi /LCD/MENU_LCD.py

#!/usr/bin/env python
from netifaces import interfaces, ifaddresses, AF_INET

from time import sleep
from Adafruit_I2C import Adafruit_I2C
from Adafruit_MCP230xx import Adafruit_MCP230XX
from Adafruit_CharLCDPlate import Adafruit_CharLCDPlate

from IPaddr_LCD import IPaddr_LCD
from DateTime_LCD import DateTime_LCD

import smbus

lcd = Adafruit_CharLCDPlate(busnum = 1)

class MENU_LCD():
    def get_const_list(self):
        const_list   = []

        ip   = IPaddr_LCD()
        time = DateTime_LCD()

        const_list.append(ip)
        const_list.append(time)

        return const_list

    def print_progress(self, sleep_time, message):
        lcd.clear()
        lcd.message(message)
        sleep(sleep_time)
        self.print_lcd()

    def print_lcd(self):
        pointer_id = 0
        push_flag  = 0

        lcd.clear()
        lcd.message("Please Push\nRite/Left Button")

        const_list = self.get_const_list()
        const_list_size = len(const_list) - 1

        while 1:
            if (lcd.buttonPressed(lcd.RIGHT) or lcd.buttonPressed(lcd.LEFT)):
                if (lcd.buttonPressed(lcd.RIGHT)):
                    if (pointer_id < const_list_size):
                        pointer_id += 1
                    else:
                        pointer_id = 0

                if (lcd.buttonPressed(lcd.LEFT)):
                    if (pointer_id > 0):
                        pointer_id -= 1
                    else:
                        pointer_id = const_list_size

                push_flag  = 1
                const_list[pointer_id].title()

            if (push_flag > 0 and lcd.buttonPressed(lcd.SELECT)):
                const_list[pointer_id].print_lcd()
                break

            if (push_flag > 0 and lcd.buttonPressed(lcd.UP)):
                break

            if (push_flag > 0 and lcd.buttonPressed(lcd.DOWN)):
                break

            sleep(.2)
        return self.print_progress(1, "Reinitializeing\nPlease wate....")

if __name__ == '__main__':
    try:
        menu = MENU_LCD()
        menu.print_progress(3, "Initializeing\nPlease wate....")
        menu.print_lcd()
    except KeyboardInterrupt:
        print("Exit\n")

$ sudo vi /LCD/DateTime_LCD.py

#!/usr/bin/env python
import datetime
import locale

from time import sleep
from Adafruit_I2C import Adafruit_I2C
from Adafruit_MCP230xx import Adafruit_MCP230XX
from Adafruit_CharLCDPlate import Adafruit_CharLCDPlate

import smbus

lcd = Adafruit_CharLCDPlate(busnum = 1)

class DateTime_LCD():
    def title(self):
        lcd.clear()
        lcd.message("Raspberry Pi\nDate Time")
        return

    def print_lcd(self):

        while 1:
            d = datetime.datetime.today()
            time = d.strftime("Date %Y/%m/%d\nTime  %H:%M:%S")

            lcd.clear()
            lcd.message(time)

            if (lcd.buttonPressed(lcd.RIGHT)):
                break

            if (lcd.buttonPressed(lcd.LEFT)):
                break

            sleep(.2)
        return


if __name__ == '__main__':
    try:
        time = DateTime_LCD()
        time.print_lcd()
    except KeyboardInterrupt:
        print("Exit\n")

$ sudo vi /LCD/IPaddr_LCD.py

#!/usr/bin/env python
from netifaces import interfaces, ifaddresses, AF_INET

from time import sleep
from Adafruit_I2C import Adafruit_I2C
from Adafruit_MCP230xx import Adafruit_MCP230XX
from Adafruit_CharLCDPlate import Adafruit_CharLCDPlate

import smbus

lcd = Adafruit_CharLCDPlate(busnum = 1)

class IPaddr_LCD():
    def title(self):
        lcd.clear()
        lcd.message("Raspberry Pi\nIP Address")
        return

    def get_ip_list(self):
        ipaddr_list   = []
        for ifaceName in interfaces():
            nic_ip_list = []
            addresses = [i['addr'] for i in ifaddresses(ifaceName).setdefault(AF_INET, [{'addr':'No IP addr'}] )]
            nic = '%s' % (ifaceName)
            ip  = '%s' % (', '.join(addresses))
            nic_ip_list.append(nic)
            nic_ip_list.append(ip)
            ipaddr_list.append(nic_ip_list)
        return ipaddr_list

    def print_lcd(self):
        pointer_id = 0

        lcd.clear()
        lcd.message("Please Push\nUp/Down Button")

        while 1:
            if (lcd.buttonPressed(lcd.UP) or lcd.buttonPressed(lcd.DOWN)):
                ipaddr_list = self.get_ip_list()
                ipaddr_list_size = len(ipaddr_list) - 1

                if (lcd.buttonPressed(lcd.UP)):
                    if (pointer_id < ipaddr_list_size):
                        pointer_id += 1
                    else:
                        pointer_id = 0

                if (lcd.buttonPressed(lcd.DOWN)):
                    if (pointer_id > 0):
                        pointer_id -= 1
                    else:
                        pointer_id = ipaddr_list_size

                lcd.clear()
                lcd.message(ipaddr_list[pointer_id][0] + "\n" + ipaddr_list[pointer_id][1])

            if (lcd.buttonPressed(lcd.RIGHT)):
                break

            if (lcd.buttonPressed(lcd.LEFT)):
                break

            sleep(.2)
        return

if __name__ == '__main__':
    try:
        ip = IPaddr_LCD()
        ip.print_lcd()
    except KeyboardInterrupt:
        print("Exit\n")

コマンド用の実行ファイルを作成しておきます
$ sudo vi /LCD/LCD_PRINTER

#!/usr/bin/env python
from MENU_LCD import MENU_LCD

if __name__ == '__main__':
    try:
        menu = MENU_LCD()
        menu.print_progress(3, "Initializeing\nPlease wate....")
        menu.print_lcd()
    except KeyboardInterrupt:
        print("Exit\n")

実行権限を与えどこからでもパスが通るように”/usr/bin/”の中にシンボリックを貼っておきます。
$ sudo chmod 700 /LCD/LCD_PRINTER
$ sudo ln -s /LCD/LCD_PRINTER /usr/bin/LCD_PRINTER

せっかくなので起動スクリプトも書いてみました。
$ sudo mkdir /LCD/init.d/
$ sudo vi /LCD/init.d/lcd_printer

#!/bin/sh
### BEGIN INIT INFO
# Provides:          LCD_PRINTER
# chkconfig:         2345 91 91
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Description:       LCD_PRINTER daemon script.
### END INIT INFO

. /lib/lsb/init-functions

PATH=/sbin:/bin:/usr/sbin:/usr/bin
DAEMON=/usr/bin/LCD_PRINTER
DAEMON_NAME=`basename $DAEMON`
PIDFILE="/var/run/lcd_printer.pid"

set -e

start() {
  log_daemon_msg "Starting $DAEMON_NAME"
  if ! start-stop-daemon --stop --quiet --pidfile ${PIDFILE} --signal 0; then
    start-stop-daemon --start --pidfile ${PIDFILE} --make-pidfile --quiet --background --exec ${DAEMON}
    log_end_msg $?
  else
    echo -n " already running."
    log_end_msg 1
  fi
}

stop() {
  log_daemon_msg "Stopping $DAEMON_NAME"
  start-stop-daemon --stop --pidfile ${PIDFILE}
  log_end_msg $?
}

case "$1" in
  start)
    start
    ;;
  stop)
    stop
    ;;
  restart)
    stop
    start
    ;;
  status)
    status_of_proc -p $PIDFILE $DAEMON $DAEMON_NAME && exit 0 || exit $?
    ;;
  *)
    echo $"Usage: $DAEMONNAME {start|stop|restart|status}" >&2
    exit 1
    ;;
esac
exit 0

実行権限を与え、起動スクリプトとして”/etc/init.d/”の中にシンボリックを貼っておきます。
$ sudo chmod 755 /LCD/init.d/lcd_printer
$ sudo ln -s /LCD/init.d/lcd_printer /etc/init.d/lcd_printer

起動するか確認してみます。
$ sudo service lcd_printer start

自動起動するように設定します。
$ sudo update-rc.d lcd_printer defaults

自動起動するか確認します。完全に電源を落とすためrebootではなくシャットダウンして電源を入れます。
$ sudo shutdown -h now

余談ですがRedHat系はchkconfigで設定するのですがDebian系は違うのですね・・・勉強になりました。

Raspberry Pi wiringpi WiringPi-Python インストール

GPIOを使うのに標準のライブラリよりも使い勝手のよさそうなライブラリを発見したためこちらを使うことにした。

$ sudo apt-get install git python-dev python-setuptools # 必要なパッケージをインストールする
$ cd /tmp # 当然だが/tmpは再起動すると中身が削除されるため注意する
$ git clone https://github.com/WiringPi/WiringPi-Python.git
$ cd WiringPi-Python
$ git submodule update –init
$ sudo cp WiringPi/wiringPi/*.h /usr/include/ # ヘッダーファイルが無いと怒られるためコピーしておく
$ sudo python setup.py install
$ cd

サンプルコード

#!/usr/bin/env python
# -*- coding:utf-8 -*-

import wiringpi
import time

if __name__ == '__main__':
    io = wiringpi.GPIO(wiringpi.GPIO.WPI_MODE_GPIO)
    io.pinMode(23,io.OUTPUT)
    io.digitalWrite(23,io.HIGH)
    while True:
        io.digitalWrite(23,io.LOW)  # on
        time.sleep(1)
        io.digitalWrite(23,io.HIGH) # off
        time.sleep(1)

参考サイト
Raspberry Pi GPIO with Python (without root) – Sirmc.net
fatal error: wiringPi.h: No such file or directory · Issue #7 · WiringPi/WiringPi-Python · GitHub

PerlとSendmailとBccのメーリングリスト配信スクリプト

昨日うっかりBccとCcを間違えてしまう大失態を演じてしまったため簡易ながら不特定多数にBccでメールを一斉配信してくれるスクリプトをPerlでサクッと書いてみました。
そしてどうせ書いたのならば久々に公開して有意義に使っていただこうと思い公開します。

コマンドラインベースで動けばいいかなということで機能自体には特にこだわりは無いのですが必要のある方がおりましたらご自由にコピーしてお使いください。
※ 当スクリプトを利用するにはPerlモジュールのインストールができるレベルの知識を必要とします。

実行用スクリプト
# vi infoEmail.pl

#!/usr/bin/perl
use utf8;
use strict;
use warnings;

binmode(STDOUT, ":utf8");

require "infoEmail.pm";

#
# メールマガジン配信スクリプト
#

my $mm   = infoEmail->new();
my $mime = $mm->mailer();

print $mime->as_string;
print '*' x 50 . "\n";
print "上記の内容で配信してもよろしいですか? (y/N)\n";
print '*' x 50 . "\n";
print "> ";
my $input = <STDIN>;
chomp($input);

if($input eq 'y' || $input eq 'yes'){
        $mm->sendmail($mime);
        print "メールを配信しました\n";
}else{
        print "メールの配信をキャンセルしました\n";
}

モジュール(プログラム本体)
# vi infoEmail.pm

#!/usr/bin/perl
package infoEmail;

use utf8;
use strict;
use warnings;

use Config::Simple;
use Mail::Krohn;
use Mail::Krohn::Sendmail;
use Email::MIME;
use Email::MIME::Creator;
use Encode;

sub new {
        my $class = shift;
        my $cfg = new Config::Simple('./infoEmail.conf') or die Config::Simple->error();
        my $self = {
                from         => $cfg->param('From'),
                to           => $cfg->param('To'),
                subject      => $cfg->param('Subject'),
                x_mailer     => $cfg->param('X-Mailer'),
                bccfilepath  => $cfg->param('BccFilePath'),
                bodyfilepath => $cfg->param('BodyFilePath')
        };
        return bless $self , $class;
}

sub mailer {
        my $self     = shift;
        my $bcc      = $self->read_config($self->{ bccfilepath });
        my $body     = $self->read_config($self->{ bodyfilepath });
        my $from     = $self->{ from };
        my $to       = $self->{ to };
        my $subject  = $self->{ subject };
        my $x_mailer = $self->{ x_mailer };
        my $mime = Email::MIME->create(
                header => [
                        From       => encode('MIME-Header-ISO_2022_JP' => decode('utf-8',$from)),
                        To         => encode('MIME-Header-ISO_2022_JP' => decode('utf-8',$to)),
                        Bcc        => encode('MIME-Header-ISO_2022_JP' => decode('utf-8',$bcc)),
                        Subject    => encode('MIME-Header-ISO_2022_JP' => decode('utf-8',$subject)),
                        'X-Mailer' => decode('utf-8',$x_mailer),
                ],
                attributes => {
                        content_type => 'text/plain',
                        charset      => 'ISO-2022-JP',
                        encoding     => '7bit',
                },
                body => encode('iso-2022-jp' => decode('utf-8',$body)),
        );
        return $mime;
}

sub sendmail {
        my $self = shift;
        my $mime = shift;
        my $mailer = Mail::Krohn->new();
        $mailer->send($mime);
        return 0;
}

sub read_config {
        my $self = shift;
        my $file_path = shift;

        open(my $fh, "<", $file_path) || die("Can not open file $file_path");
        my $file_contents;
        while( my $line = readline $fh ){
                $file_contents .= $line;
        }
        chomp($file_contents);
        return $file_contents;
}

1;

設定ファイル
# vi infoEmail.conf

############################################################
# メールマガジン設定ファイル
############################################################
# 送信元
From         = "ぼっちちゃん" <めーる@あどらあ>
# 送信先
To           = "ぼっちちゃん" <めーる@あどらあ>
# 件名
Subject      = ぼっちちゃんと愉快な仲間たちめーりんぐりすと
# メーラー名
X-Mailer     = My Best Friends Mailing List
############################################################
# 送り先リストの記述されたファイル
BccFilePath  = ./infoEmail_bcc.tmp
# 本文の記述されたファイル
BodyFilePath = ./infoEmail_body.tmp
############################################################

配信用メール本文
# vi infoEmail_body.tmp

お友達100人できるかな?

=======================================
"ぼっちちゃん" <めーる@あどらあ~>
ぼっちちゃんと愉快な仲間たちめーりんぐりすと
=======================================

配信対象のアドレスリスト
# vi infoEmail_bcc.tmp

おともだち1@あどらあ, めーる2@あどらあ, めーる3@あどらあ, めーる4@あどらあ, めーる5@あどらあ

久々にPerl触ったらだいぶ忘れてました(^_^;)

参考サイト
第20回 Email::Sender:メールを送信する:モダンPerlの世界へようこそ|gihyo.jp … 技術評論社

PerlでメールをBccで送信する Email::MIME + Mail::Krohn

メールをEmail::Sendを利用し送信しようとしたところ下記のように色々と怒られたため調べてみたところ
スクリプト起動時にReturn::Value::NO_CLUCKに値を入れれば良いということが分かったが実にスマートではないので代わりになるモジュールを探してみた

Return::Value is deprecated at /usr/lib/perl5/site_perl/5.8.8/Return/Value.pm line 13
        require Return/Value.pm called at /usr/lib/perl5/site_perl/5.8.8/Email/Send.pm line 11
        Email::Send::BEGIN() called at /usr/lib/perl5/site_perl/5.8.8/Return/Value.pm line 0
        eval {...} called at /usr/lib/perl5/site_perl/5.8.8/Return/Value.pm line 0
        require Email/Send.pm called at infoEmail.pl line 6
        main::BEGIN() called at /usr/lib/perl5/site_perl/5.8.8/Return/Value.pm line 0
        eval {...} called at /usr/lib/perl5/site_perl/5.8.8/Return/Value.pm line 0

必要なモジュールをインストールする
# cpan install parent
# cpan install Class::Accessor::Lite
# cpan install Mail::Krohn

#!/usr/bin/perl
use strict;
use warnings;

use utf8;
use Mail::Krohn;
use Mail::Krohn::Sendmail;
use Email::MIME;
use Email::MIME::Creator;
use Encode;

MAIN:{
    my $mime = Email::MIME->create(
        header => [
            From => 'そうしんもとめーる@あどれす',
            To   => 'そうしんもとめーる@あどれす',
            Bcc  => 'そうしんさきめーる@あどれす',
            Subject => Encode::encode( 'MIME-Header-ISO_2022_JP', 'テストメールです' ),
            'X-Mailer' => 'TestMailer',
        ],
        attributes => {
            content_type => 'text/plain',
            charset      => 'iso-2022-jp',
            encoding     => '7bit',
        },
        parts => [
                Encode::encode( 'iso-2022-jp', 'でばっぐおいしー!!' ),
        ],
    );

    my $mailer = Mail::Krohn->new();
    $mailer->send($mime);
}

参考サイト
Email::MIME::CreatorとEmail::Sendでメール送信
[Perl]Email::SendつかったらReturn::Valueにdeprecatedだと怒られた

CentOS5.7 Email::Send インストール

# cpan install Perl::OSType <- make testでエラーが起きる # yum --enablerepo=epel install perl-Perl-OSType # cpan install Module::Build # cpan install Module::Pluggable # cpan install Email::Send

atコマンドがエラーを起こす

$ echo “xmms -p” |sudo at 0900
warning: commands will be executed using /bin/sh
Cannot open lockfile /var/spool/cron/atjobs/.SEQ: No such file or directory

atdを再起動させても解決しなかったため手動でロックファイルを作成したところ解決しました

$ sudo touch /var/spool/cron/atjobs/.SEQ
$ sudo chown daemon:daemon /var/spool/cron/atjobs/.SEQ

MacBook Air Late 2011 BackTrack5 グラフィックドライバ

MacBook Air Late 2011 のグラフィックカードはnvidiaではなくi5に組み込まれているGPUらしいのでIntel HD Graphics 3000 384 MBを使っているようです。

調べたところリポジトリを追加することで手軽にインストールできるようなのでメモしておきます。

sudo add-apt-repository ppa:glasen/intel-driver
sudo apt-get update
sudo apt-get upgrade
sudo apt-get install linux-image-generic-lts-backport-natty linux-headers-generic-lts-backport-natty

Ubuntu11.10でffmpegのlibfaacを使う Unknown encoder ‘libfaac’

調べたところライセンスが関係して機能を削っているようですね。

使えるようにするにはソースからビルドする時にオプションを追加する方法等あるようですがすごくめんどくさい・・・・

そんな訳で、他の方法を探してみました。

非公式リポジトリのMedibuntuには予めオプションを追加してビルドしたパッケージが用意されているようなのでそれを利用したいと思う。

リポジトリの追加

$ sudo wget http://www.medibuntu.org/sources.list.d/`lsb_release -cs`.list –output-document=/etc/apt/sources.list.d/medibuntu.list && sudo apt-get -q update && sudo apt-get –yes -q –allow-unauthenticated install medibuntu-keyring && sudo apt-get -q update

ffmpegを再インストール
$ sudo apt-get -reinstall install ffmpeg libavcodec-extra-53

※ Ubuntu11.10のffmpegはlibavcodec-extra-52ではなくlibavcodec-extra-53のようなのでこちらを指定する。

これで、Unknown encoder ‘libfaac’が出なくなると思う。