「OKグーグル領収書印刷して！」をobnizとGoogleホームで作る

UARTで印刷できるプリンターが[amazon](https://www.amazon.co.jp/サーマルプリンタユニット-感熱紙プリンタ-TTLシリアル制御-DC5-9V-58mm幅ロール紙/dp/B07DTGXCHD/ref=sr_1_1?ie=UTF8&qid=1543672589&sr=8-1&keywords=uart+プリンタ)で売っているのを発見しました。
UARTならobnizから出せる！しかも（きっと）UARTで送った文字がそのまま印刷されるはず！

せっかくなのでGoogleHome連携させて、「領収書印刷して」の一言でレシートを出せるようにすれば、イベントで大活躍しそうです。
ということでやってみました。

![Untitled.gif](https://qiita-image-store.s3.amazonaws.com/0/258216/26f12bae-d7bc-b5dc-2b00-30365e1c5fc1.gif)

## obnizとは

[obniz](https://obniz.io/)はマイコンではなく、クラウド＋専用回路でクラウドのAPIを叩くことでIOやUARTなどが利用できるというサービスです。専用回路はamazonなどで購入できます。

<img width="1212" alt="Screen Shot 2018-12-01 at 23.23.48.png" src="https://qiita-image-store.s3.amazonaws.com/0/258216/4d50290d-76da-a9f2-4551-de49ee399832.png">

そして一度購入すればクラウドライセンスがついてきてクラウドが無料で利用できます。ライセンスにはサーバーレスファンクションも無料でついてくるので、webhookでクラウド上でプログラムを動かすことが可能。

これを使って、
GoogleHome->IFTTT->webhook->obnizのサーバーレス->obnizから印刷
という流れで印刷してみたいと思います。

## 接続

obnizとプリンターを接続します。
このプリンターは5v-9vで動くらしいので、obnizから電源も含めて直接動かしてみます。

プリンタの裏側にコネクタがあります、わざわざケーブルが親切にもついてくるので、それをつなぎます。
ちなみにRX　TXはUARTのことですが、プリンタ側のRX,TXになってます。
つまりRXにたいして、obnizから送信する　ということになります。

![IMG_0305.JPG](https://qiita-image-store.s3.amazonaws.com/0/258216/f048d9db-d0ee-fa0e-3f79-97acd86aa53c.jpeg)

そして、obnizに直接つなぎます。

![IMG_8972.JPG](https://qiita-image-store.s3.amazonaws.com/0/258216/0722accf-b48e-f34c-a9b8-a1c95c2398fb.jpeg)

## テスト印刷

何も考えず印刷してみましょう。きっとUARTで送れば文字が出るはず。

まずはobnizにつなぐためにSDKを取り込んで、`new Obniz()`でobnizにつなぎます。
そしてプリンタの電源を供給して、HTMLのボタンきっかけでuartに文字を送ります。

```html
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <script src="https://obniz.io/js/jquery-3.2.1.min.js"></script>
  <script src="https://unpkg.com/obniz@1.13.1/obniz.js" crossorigin="anonymous"></script>
</head>
<body>

<div id="obniz-debug"></div>
<h1>printer</h1>
<button id="send">send</button>

<script>
var obniz = new Obniz("OBNIZ_ID_HERE");
obniz.onconnect = async function () {

  obniz.io0.output(false);
  obniz.io2.output(true);
  obniz.io9.output(false);
  await obniz.wait(100);

  const uart = obniz.getFreeUart();
  uart.start({tx:10, rx:11, baud:9600});
  
  $("#send").click(function(){
    uart.send("Hello World \r\n obniz \r");
  })
   
}

</script>
</body>
</html>
```

印刷できた！プリンタのボタンを押すと送りができるので、送るとちゃんと印刷できてるのが見えます。

[![video](http://img.youtube.com/vi/N6zVeNW8LQA/0.jpg)](http://www.youtube.com/watch?v=N6zVeNW8LQA)

ただ、これだと横に長い文字がうまく出せませんでした。

印刷するときの温度設定を変えないといけないようです。そこでデータシートなど確認してちゃんと印刷できるように！
レシートっぽいものを出してみいました。

```html
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <script src="https://obniz.io/js/jquery-3.2.1.min.js"></script>
  <script src="https://unpkg.com/obniz@1.13.1/obniz.js" crossorigin="anonymous"></script>
</head>
<body>

<div id="obniz-debug"></div>
<h1>printer</h1>
<button id="send">send</button>
<div id="print"></div>

<script>
var obniz = new Obniz("OBNIZ_ID_HERE");
obniz.onconnect = async function () {

  /* power up */
  obniz.io0.output(false);
  obniz.io2.output(true);
  obniz.io9.output(false);
  await obniz.wait(100);
  
  /* Prepare uart */
  const ESC_CHAR = 0x1B;
  const uart = obniz.getFreeUart();
  uart.start({tx:10, rx:11, baud:9600});
  await obniz.wait(50);
  
  /* initialize printer */
  init();

  $("#send").click(()=>{
    printReceipt();
  });
  
  function init() {
    uart.send([0xff]); // return from sleep
    obniz.wait(50);
    uart.send([ESC_CHAR], 0x38, 0, 0); // [ESC 8]never sleep
    uart.send([ESC_CHAR, 0x44, 4, 8, 12, 16, 20, 24, 28, 0]); // [ESC D] set tabs 4
    uart.send([ESC_CHAR], 0x37, 11, 120, 40);　// [ESC 7] configure heating params
    
    reset();
  }
  
  function reset() {
    uart.send([ESC_CHAR, 0x40]); // [ESC @] Initialize. Clear buffer
  }
  
  function printReceipt() {
    sendLines([
      " ",
      "CambrianRobotics Inc.",
      " ",
      "HKArchBuilding 2F",
      "3-51-5, MinamiOtsuka",
      "Toshimaku, Tokyo",
      "170-0005",
      " ",
      "****************************",
      "PURCHASE",
      " ",
      "obniz x 1 5,000yen",
      " ",
      "TOTAL 5,000yen",
      " ",
      "Thank you!",
      " ",
      " ",
      "Enjoy Ogaki Mini Maker Faire",
      " ",
      " ",
      " "
    ]);
  }
  
  async function sendLines(lines) {
    for (let i=0; i<lines.length; i++) {
      const line = lines[i];
      uart.send(line + '\r');
      obniz.wait(line.length * 10 + 100);
    }
  }
}

</script>
</body>
</html>
```

HTMLのボタンを押して印刷すると見事に出せました！

![Untitled.gif](https://qiita-image-store.s3.amazonaws.com/0/258216/26f12bae-d7bc-b5dc-2b00-30365e1c5fc1.gif)

## Webhook化

obnizクラウドにサーバーレスを設定して、さっきのプログラムをwebhookからクラウド上で動くようにします。

まず、さっきのプログラムを少し変更して、

```javascript
  $("#send").click(()=>{
      printReceipt();
    });
```

のところを

```javascript
  if (typeof done === "function") {
    /* Webhook */
    printReceipt();  
    await obniz.wait(10 * 1000);
    done();
    
  } else {
    /* HTML button */
    $("#send").click(()=>{
      printReceipt();
    });
  }
```

にします。これでクラウド上での実行だった場合は、すぐに印刷してdone()を呼ぶ　ということができます。
そして、このプログラムはobnizクラウドに作った自分のリポジトリの中に入れておきます。

次にobnizクラウド上でイベントを設定します。
名前を適当につけて、実行するプログラムとしてさっきのプログラムを選びます。
そしてきっかけはwebhookにします。

<img width="573" alt="Screen Shot 2018-12-01 at 22.08.41.png" src="https://qiita-image-store.s3.amazonaws.com/0/258216/9678f6a3-a509-b0eb-c8eb-9b8d0275ae7b.png">

これで保存します。

ここまででイベントの「テスト実行」ボタンを押したらプリンタからちゃんと印刷されます。

## GooleHome連携

あとは、GoogleHomeとつなぎます。
IFTTTをつかうとキーワードで簡単にwebhookがたたけます。
スマホにIFTTTアプリをいれて、新規アプレットを作ります。

IFにはGoogleアシスタントを選び、シンプルフレーズを選択します。

キーワードは「領収書印刷して」

![IMG_E41D6C923415-1.jpeg](https://qiita-image-store.s3.amazonaws.com/0/258216/2e50b3ff-2cf4-c68f-7576-416c481c5006.jpeg)

THENにはWebhookを選びます。
webhookのURLはobnizクラウドで作ったイベントのwebhook URLを入れます。

![IMG_969700B0FB34-1.jpeg](https://qiita-image-store.s3.amazonaws.com/0/258216/7dd15e1b-68a5-9955-2e01-cad030cfdcd0.jpeg)

これで準備完了！google Homeに「領収書印刷して」といえば、webhookが飛んで、obnizクラウドで実行されて、印刷されるはず！

[![video](http://img.youtube.com/vi/wZ99b8AnTho/0.jpg)](http://www.youtube.com/watch?v=wZ99b8AnTho)

無事出せました！

## Future work

これだと固定文字しか出せないのですが、実はIFTTTのグーグルアシスタントはパラメーターにも対応しているので、出す領収書を選んだりすることも簡単にできます。

更に、今回はそこまでできてないのですが、ビットマップの描画も可能です。

お客さんにウェブサイト上でサインしてもらって、それをビットマップで印刷しても楽しそうですね！