Raspberry PiとGo言語でミニトマトの栽培環境を監視してLINE Botで通知する


TOP
 



湿Raspberry PiLINE BotLINE

使



Raspberry Pi2 Model B

GW-USNANO2A

Soil Moisture Sensor

MCP3008

BME280

Raspberry Pi2 Model B


Amazon4,000

GW-USNANO2A


LANRaspbery Pi2LANUSBAmazon990

Soil Moisture Sensor


湿 500

MCP3008


A/D 220

BME280


i2c使 1,080


108

使湿湿AWSDynamoDBLINE Bot

 20176


LINE Bot webhook使HTTPS IPDNSDDNS使URLRaspberry Pi





LINE Developer Trial

AWS


LINE Developer TrialLINE Bot, AWSDynamoDB使

Wi-Fi


GW-USNANO2ARaspberry PiWi-Fi

 
raspberry pi2   LAN 
$ sudo sh -c 'wpa_passphrase [Wi-FiのSSID] [パスフレーズ] >> /etc/wpa_supplicant/wpa_supplicant.conf'
$ sudo /etc/init.d/networking restart

ifconfigwlan0IP
$ ifconfig
wlan0     Link encap:Ethernet  HWaddr xx:xx:xx:xx:xx:xx
          inet addr:192.168.0.2  Bcast:192.168.0.255  Mask:255.255.255.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:101017 errors:0 dropped:1127 overruns:0 frame:0
          TX packets:66969 errors:0 dropped:1 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:23361109 (22.2 MiB)  TX bytes:24062827 (22.9 MiB)


Raspberry Pi



f:id:g-editor:20170711112617j:plain
Soil Moisture SensorA/DMCP3008使 A/D12bitMCP3208MCP3008

MCP3008SPI使raspi-config SPIenable
# raspi-config

f:id:g-editor:20170711112648p:plain 9 Advanced Options

f:id:g-editor:20170711112659p:plain A6 SPI

f:id:g-editor:20170711112710p:plain Yes 

MCP3008Raspberry Pi

MCP3008Raspberry Pi
VDD+3.3V
VREF+3.3V
AGNDGND
CLKGPIO 11 (SCLK)
DOUTGPIO 9 (MISO)
DINGPIO 10 (MOSI)
CS/SHDNGPIP 8 (CE0)
DGNDGND


BME280 BME280Raspberry Pi i2c使MCP3008raspi-configi2c

i2cSPIrasp-configON

f:id:g-editor:20170711112723p:plain 9 Advanced Options

f:id:g-editor:20170711112734p:plain A7 I2C

f:id:g-editor:20170711112749p:plain Yes 

BME280j3i2c

WebK-09421

BME280Raspberry Pi

BME280Raspberry Pi
VDD+3.3V
GNDGND
SDIGPIO2 (SDA)
SDOGND
SCKGPIO3 (SCL)

Let's EncryptでSSL証明書を発行する


LINE BotwebhookURLhttpsLet's Encrypt使DDNS使DDNSmydns.jp120

Let's EncryptSSLcertbot
$ git clone https://github.com/certbot/certbot
$ cd certbot
$ sudo  ./certbot-auto certonly --standalone -d 自サーバのドメイン -m 連絡先メールアドレス --agree-tos -n

Le'ts Encrypthttpgolangroot
echo.go
package main

import (
  "fmt"
  "net/http"
)

func handler(w http.ResponseWriter, r *http.Request) {
  fmt.Fprintf(w, "I'm Here.")
}

func main() {
  http.HandleFunc("/", handler)
  http.ListenAndServe(":80", nil)
}



/etc/letsencrypt/

/etc/letsencrypt/archive// fullchain1.pem,privkey1.pem使
/etc/letsencrypt/archive/自サーバのドメイン/
├── fullchain1.pem
└── privkey1.pem

LINE Developer Trial


Raspberry PiWEBSSLLINE Developer Trial


https://business.line.me/ja/services/bot

Developer Trial PUSH使


GoGoIoT




github.com/line/line-bot-sdk-go/linebot
golang.org/x/exp/io/i2c
golang.org/x/exp/io/spi
github.com/quhar/bme280
github.com/advancedclimatesystems/io/spi/microchip
github.com/advancedclimatesystems/io/adc
github.com/aws/aws-sdk-go/aws
github.com/aws/aws-sdk-go/aws/session
github.com/aws/aws-sdk-go/service/dynamodb
github.com/robfig/cron

github.com/line/line-bot-sdk-go/linebotLINE Botgolang.org/x/exp/io/i2c,golang.org/x/exp/io/spii2c,spi

MCP3008github.com/advancedclimatesystems/io/spi/microchip,github.com/advancedclimatesystems/io/adc

BME280GoBotgithub.com/quhar/bme280使湿

github.com/aws/aws-sdk-go/GoAWS使SDK

github.com/robfig/croncron


Let's EncryptLINEconst
const (
    LetsencryptChain   = "/etc/letsencrypt/archive/yourdomain/fullchain1.pem"
    LetsencryptPrivate = "/etc/letsencrypt/archive/yourdomain/privkey1.pem"
    SSLPort            = ":443"
    ChannelId          = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
    Secret             = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
    Token              = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
)

aws-sdk-goaws使~/.aws/credentials
[default]
aws_access_key_id = XXXXXXXXXX
aws_secret_access_key = XXXXXXXXXXXX

HTTPS


httpshttp.ListenAndServeTLSWEBGohttproot
err := http.ListenAndServeTLS(SSLPort, LetsencryptChain, LetsencryptPrivate, nil)
if err != nil {
    log.Fatal(err)
}

BME280湿


BME280i2c
dev, err := i2c.Open(&i2c.Devfs{Dev: "/dev/i2c-1"}, 0x76)

&i2c.Devfs  i2cdetect 

BME280  bme280.EnvData() 使
bme := bme280.New(dev)
bme.Init()
t, p, h, err := bme.EnvData()

湿

Soil Moisture Sensor  MCP3008 湿


A/DSPI
conn, err := spi.Open(&spi.Devfs{
    Dev:      "/dev/spidev0.0",
    Mode:     spi.Mode0,
    MaxSpeed: 3600000,
})

MCP3008
adc = microchip.MCP3008{
    Conn:      conn,
    Vref:      5.0,
    InputType: adc.PseudoDifferential,
}

MCP3008.OutputCode(0)
hum, err := adc.OutputCode(0)

MCP3008.Voltage(0)
v, err := adc.Voltage(0)

Raspberry Pi


linebot.New() LINE Bot
bot, err = linebot.New(Secret, Token)

linebot.PushMessage()使PUSH
var messages []linebot.Message
message := linebot.NewTextMessage("Soil humidity is less.")
messages = append(messages, message)
bot.PushMessage(ChannelId, messages...).Do()


LINE BotcallbackHandleFunc
http.HandleFunc("/callback", callbackMessage)

callback

linebot.ParseRequest(*http.Request)Botlinebot.ReplyMessage().Do()
func callbackMessage(w http.ResponseWriter, r *http.Request) {
    events, err := bot.ParseRequest(r)
    if err != nil {
        if err == linebot.ErrInvalidSignature {
            fmt.Println(err)
        }
        return
    }

    for _, event := range events {
        if event.Type == linebot.EventTypeMessage {
            switch message := event.Message.(type) {
            case *linebot.TextMessage:
                if _, err = bot.ReplyMessage(event.ReplyToken, linebot.NewTextMessage("Hello!")).Do(); err != nil {
                    log.Print(err)
                }
            }
        }
    }
}

dynamodb
dynamo := dynamodb.New(session.New(), aws.NewConfig().WithRegion("ap-northeast-1"))
func pushGaugeData(tfloat64, p float64, h float64, c int, v float64) {
    now := time.Now()
    param := &dynamodb.UpdateItemInput{
        TableName: aws.String("DynamoDBTable"),
        Key: map[string]*dynamodb.AttributeValue{
            "id": {
                N: aws.String(fmt.Sprint(now.Unix())),
            },
        },
        ExpressionAttributeNames: map[string]*string{
            "#temperature": aws.String("temperature"),
            "#pressure":    aws.String("pressure"),
            "#hydro":       aws.String("hydro"),
            "#volt":        aws.String("volt"),
            "#raw":         aws.String("raw"),
        },
        ExpressionAttributeValues: map[string]*dynamodb.AttributeValue{
            ":temperature": {
                N: aws.String(strconv.FormatFloat(t, 'f', 2, 64)),
            },
            ":pressure": {
                N: aws.String(strconv.FormatFloat(p, 'f', 2, 64)),
            },
            ":hydro": {
                N: aws.String(strconv.FormatFloat(h, 'f', 2, 64)),
            },
            ":volt": {
                N: aws.String(strconv.FormatFloat(v, 'f', 2, 64)),
            },
            ":raw": {
                N: aws.String(fmt.Sprint(c)),
            },
        },
        UpdateExpression: aws.String("set #temperature = :temperature, #pressure = :pressure, #hydro = :hydro, #volt = :volt, #raw = :raw"),

        ReturnConsumedCapacity:      aws.String("NONE"),
        ReturnItemCollectionMetrics: aws.String("NONE"),
        ReturnValues:                aws.String("NONE"),
    }
    dynamo.UpdateItem(param)
}

croncroncron
c := cron.New()
c.AddFunc("0 0 6 * * *", func() { fmt.Println("Wake me up!") })
c.Start()


go buildBot使使

Bot使

5


Gohttp443bindroot

LINE Bot f:id:g-editor:20170711112830p:plain
LINE BotRaspberry Piwebhook f:id:g-editor:20170711112857p:plain
Bot f:id:g-editor:20170711112916p:plain
Soil Moisture Sensor rawraw500 f:id:g-editor:20170711112924j:plain


Soil Moisture SensorMCP3008BME280使

GitHub

gnavi-blog/tomato


長谷川
ぐるなびビッグデータを使った商品開発を行っています。 2児の父親で、プライベートでは子供が喜ぶような何かを作ったりしてますが、どれも反応がいまいちなのが悲しいです。