LINE::Bot::APIとIRKitで部屋の家電を制御するサンプルコード。

解説書いてる時間がなかったのでサンプルコードだけ貼っておきます。そのうち書く。

LINEのmessage apiを使おうと思ってuse LWP::UserAgentとuse JSONでゴリゴリ書いてたら普通にPerlのSDKがあったときの顔をしていました。SDK充実しててすごい。
line/line-bot-sdk-perl: LINE: :API – SDK of the LINE Messaging API for Perl

私はWebhookのcallback先を自宅サーバ(Raspberry Pi 2)に設置してるのでIRKit Device HTTP APIを使用できます。というかInternet HTTP API使うのめんどくさいから自宅サーバをcallback先にしたというのもあります。
IBM BluemixとかHerokuとか使ってる人はInternet HTTP APIを使ってください。
アプリはhypnotoadとMojolicious::Liteで動かしていて、リバースプロキシに(無駄に)h2oを使ってるのですが、あまり意味は無いですね。

#!/usr/bin/perl

# 2017/01/26 ちょっと書き直した

use utf8;
use strict;
use warnings;

use LINE::Bot::API;
use LINE::Bot::API::Builder::SendMessage;
use LINE::Bot::API::Builder::TemplateMessage;
use LWP::UserAgent;
use Mojolicious::Lite;

my $ua = new LWP::UserAgent();

my $CHANNEL_ACCCESS_TOKEN = "xxx"; 
my $CHANNEL_SECRET="xxx";

# API認証情報
my $bot = LINE::Bot::API->new(
    channel_secret       => $CHANNEL_SECRET,
    channel_access_token => $CHANNEL_ACCCESS_TOKEN,
    );

app->config(
    hypnotoad => {
    listen => ['http://*:8092'],
    },
     );

# 当初いろんなリクエストを送る予定だった
sub call_api(){
  my $url = shift;
  my $method = shift;
  my $headers = shift;
  my $content = shift;

  my $req = HTTP::Request->new($method, $url);
  while (my ($key, $value) = each(%$headers)){
    $req->header($key => $value);
  }
  $req->content($content);
  return $ua->request($req);
}

# IRKitのAPIを呼び出す
sub call_irkit(){
  my $content = shift;
  my $IRKIT = "http://192.168.10.150/messages";
  my %IRKIT_H = ("X-Requested-With" => "curl");
  return &call_api($IRKIT, "POST", %IRKIT_H, $content);
}

get '/' => sub {
  my $self = shift;
  return $self->render(template => 'index', format => 'html');
} => 'index'; #別になくても良い

post '/callback' => sub {
  my $self = shift;

  # LINEから受信したリクエストボディ
  my $source = $self->req->body;
  # シグネチャ検証
  unless ($bot->validate_signature($source, $self->req->headers->header('X-Line-Signature')) ) {
    return $self->render(json => {'status' => "failed to validate signature"});
  }

  my $events = $bot->parse_events_from_json($source);
  my $event = ${ $events }[0]; #多分先頭のイベントしか使わないので
  unless($event->is_message_event && $event->is_text_message){
    return $self->render(json => {'status' => "not text event"});
  }

  # 自分以外の人が操作できないようにする
  unless($event->user_id eq "my LINE ID"){
    return $self->render(json => {'status' => "You are not me."});
  }

  my $reply_text = $event->text;
  if($reply_text eq "コマンド教えて"){ # carouselの動作確認も兼ねてヘルプ

    my $carousel = LINE::Bot::API::Builder::TemplateMessage->new_carousel(
      alt_text => 'コマンドを教えます',
    );

    my @commands = ("電気つけて", "電気消して", "エアコンつけて", "エアコン消して");
    for my $i (@commands) { #carouselは5つまで
      my $column = LINE::Bot::API::Builder::TemplateMessage::Column->new(
        title     => "commands",
        text      => "利用頻度の高いコマンドです",
      )->add_message_action(
        label => $i,
        text  => $i,
      );
      $carousel->add_column($column->build);
    }
    my $messages = LINE::Bot::API::Builder::SendMessage->new()->add_template($carousel->build);
    $bot->reply_message($event->reply_token, $messages->build);
    return $self->render(json => {'status' => "200OK"});
  }
  my $messages = LINE::Bot::API::Builder::SendMessage->new;
  $messages->add_text( text => "命令を実行します!" );
  $messages->add_text( text => $reply_text );

  my $commands = {
    "電気つけて" => '{"format":"raw","freq":38,"data":[18031,...]}',
    "電気消して" => ...,
    #etc...,
  };
  # 受け取ったメッセージに対応するJSONをIRKitに送信する
  my $command = $commands->{$reply_text};
  if ($command){
    &call_irkit($command);
  } else { # ここの挙動をヘルプにするのもありだと思います
    $messages->add_text( text => "その命令は受け付けられません!" );
  }

  $bot->reply_message($event->reply_token, $messages->build);
  return $self->render(json => {'status' => "200OK"});
} => 'callback';

app->start;