Lチカセブン

7つの言語でLチカ。

1. C
2. Go
3. Node.js
4. Python
5. Ruby
6. Rust
7. Swift

タイトル先行なので、なんの目的もございません。
言語の選びは適当です。

## 環境

||version|
|:--|:--|
|Model|Raspberry Pi 3 Model B Rev 1.2p|
|OS|Raspbian GNU/Linux 9 (stretch)|

### Dockerで実行環境構築

以前、ラズパイでの開発にDockerを導入する記事を投稿しました。
[Raspberry Pi で TensorFlow する Docker 環境構築](https://qiita.com/kohbis/items/53c27ce6c62a7039aaa2#raspberrypi-%E3%81%AB-docker-%E3%82%92%E3%81%88%E3%81%84%E3%82%84)

* Raspbianにプリインストール & GPIO制御可能なもの  
`C` `Python`  
* Raspbianに言語 or GPIO制御するライブラリのインストールが必要なもの  
`Go` `Node.js` `Ruby` `Rust` `Swift`  

せっかくなので後者についてはDockerで実行環境を手に入れます。
もちろんラズパイのローカルにインストールしても問題ありません。

```bash
docker run -ti --name {任意のcontainer名} --rm --privileged -v $PWD:/usr/src:rw -d {使用するlanguage_image} /bin/bash
```
Swift以外は公開されているimageだけで動作可能です。

## Lチカ

1秒間隔で7回チカらせます。
![wiring.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123634/8199e84f-4992-6949-563c-f23066555a3a.png)

---

### C

|library|
|:--:|
|[wiringPi](http://wiringpi.com/)|

```bash
# wiringPiライブラリをリンク
gcc -o led-blinker led-blinker.c -lwiringPi
```

```c:led-blinker.c
#include <wiringPi.h>

#define GPIO2 2

int main(void)
{
    wiringPiSetupGpio();

    pinMode(GPIO2, OUTPUT);

    for (int i = 0; i < 7; i++)
    {
        digitalWrite(GPIO2, HIGH);
        delay(1000);
        digitalWrite(GPIO2, LOW);
        delay(1000);
    }

    return 0;
}
```

---

### Go

|version|library|
|:--:|:--:|
|1.12.5|[go-rpio](https://github.com/stianeikeland/go-rpio)|

```bash
go version

go get github.com/stianeikeland/go-rpio
```

```golang
package main

import (
	"os"
	"fmt"
	"time"
	"github.com/stianeikeland/go-rpio"
)

var (
	pin = rpio.Pin(2)
)

func main()  {
	
	err := rpio.Open()

	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}

	pin.Output()

	for i := 0; i < 7; i++ {
		pin.High()
		time.Sleep(1 * time.Second)
		pin.Low()
		time.Sleep(1 * time.Second)
	} 

	rpio.Close()
}
```

---

### Node.js

|version|library|
|:--:|:--:|
|12.2.0|[onoff](https://github.com/fivdi/onoff)|

```bash
node --version

npm install onoff
```

```javascript
'use strict';

const Gpio = require('onoff').Gpio;
const pin = new Gpio(2, 'out');

const sleep = (ms) => {
  return new Promise(resolve => setTimeout(resolve, ms))
}

const main = async () => {
  try {
    for (let i = 0; i < 7; i++) {
      pin.writeSync(1);
      await sleep(1000);
      pin.writeSync(0);
      await sleep(1000);
    }
  } catch (err) {
    console.log(err);
  } finally {
    pin.unexport();
  }
}

main();
```

---

### Python

|version|library|
|:--:|:--:|
|3.5.3|[RPi.GPIO](https://pypi.org/project/RPi.GPIO/)|

```bash
python3 --version
```

```python
import RPi.GPIO as GPIO
import time

GPIO.setmode(GPIO.BCM)

pin_out = 2
GPIO.setup(pin_out, GPIO.OUT)

for _ in range(7):
    GPIO.output(pin_out, GPIO.HIGH)
    time.sleep(1)
    GPIO.output(pin_out, GPIO.LOW)
    time.sleep(1)

GPIO.cleanup()
```

---

### Ruby

|version|library|
|:--:|:--:|
|2.6.3|[pi_piper](https://github.com/jwhitehorn/pi_piper)|

```bash
ruby --version

gem install pi_piper
```

```ruby
require 'pi_piper'

pin = PiPiper::Pin.new(:pin => 2, :direction => :out)

7.times do
  pin.on
  sleep 1
  pin.off
  sleep 1
end
```

---

### Rust

|version|library|
|:--:|:--:|
|1.18.2|[rppal](https://github.com/golemparts/rppal)|

```bash
rustup -V

cargo init led_blinker

# edit Cargo.toml
# edit src/main.rs

cargo run
```

```toml:Cargo.toml
## 省略 ##

[dependencies]
rppal = "0.11.2"
```

```rust:main.rs
use std::error::Error;
use std::thread;
use std::time::Duration;

use rppal::gpio::Gpio;

const GPIO_LED: u8 = 2;

fn main() -> Result<(), Box<dyn Error>> {

    let mut pin = Gpio::new()?.get(GPIO_LED)?.into_output();

    for _ in 0..7 {
        pin.set_high();
        thread::sleep(Duration::from_secs(1));
        pin.set_low();
        thread::sleep(Duration::from_secs(1));
    };

    Ok(())
}
```

---

### Swift

|version|library|
|:--:|:--:|
|4.2.3|[SwiftyGPIO](https://github.com/uraimo/SwiftyGPIO.git)|

Swiftは自前でimageをbuildします。  
`docker build -t {任意のimage名} .`

```Dockerfile:Dockerfile
FROM resin/rpi-raspbian:stretch

ENV APP_ROOT /usr/src
WORKDIR $APP_ROOT
ADD . $APP_ROOT

RUN apt-get update
RUN apt-get install libxml2-dev git

# install swift4
# https://packagecloud.io/swift-arm/release/packages/raspbian/stretch/swift4_4.2.3_armhf.deb
RUN curl -s https://packagecloud.io/install/repositories/swift-arm/release/script.deb.sh | sudo bash
RUN apt-get install swift4=4.2.3
```

buildが完了したら他の言語と同様 `docker run` します。

```bash
swift --version

mkdir led-blinker && cd led-blinker
swift package init --type executable

# edit Package.swift
# edit Sources/led-blinker/main.swift 

swift build
```

```swift:Package.swift
import PackageDescription

let package = Package(
    name: "led-blinker",
    dependencies: [
        .package(url: "https://github.com/uraimo/SwiftyGPIO.git", from: "1.0.0")
    ]
)
```

```swift:main.swift
import Glibc
import SwiftyGPIO

let gpios = SwiftyGPIO.GPIOs(for:.RaspberryPi3)
var gp = gpios[.P2]!

gp.direction = .OUT

for _ in 1...7 {
    gp.value = 1
    sleep(1)
    gp.value = 0
    sleep(1)
}
```

参考  
> [ラズパイとサーバーサイドSwiftでLチカ！ ( Raspberry Pi 2 + SwiftyGPIO ) by n0bisukeさん](https://qiita.com/n0bisuke/items/9e06be9672373fa44f02)

---

単純に `/sys/class/gpio` を操作する方法もありますが、今回は各言語のライブラリを使用するようにしてみました。 
RaspberryPiではPythonが選ばれることが多いですが、たまには他の言語でやってみるのも楽しそうですね。