Permalink
Switch branches/tags
Nothing to show
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
executable file 258 lines (232 sloc) 6.17 KB
package main
import (
"fmt"
"github.com/advancedclimatesystems/io/adc"
"github.com/advancedclimatesystems/io/spi/microchip"
"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/line/line-bot-sdk-go/linebot"
"github.com/quhar/bme280"
"github.com/robfig/cron"
"golang.org/x/exp/io/i2c"
"golang.org/x/exp/io/spi"
"log"
"math/rand"
"net/http"
"os"
"os/signal"
"strconv"
"strings"
"syscall"
"time"
)
const (
LetsencryptChain = "/etc/letsencrypt/archive/yourdomain/fullchain1.pem"
LetsencryptPrivate = "/etc/letsencrypt/archive/yourdomain/privkey1.pem"
SSLPort = ":443"
ChannelId = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
Secret = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
Token = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
)
var (
Bot *linebot.Client
Bme *bme280.BME280
Adc microchip.MCP3008
Dynamo *dynamodb.DynamoDB
ResNormal = map[int]string{
0: "message A",
1: "message B",
2: "message C",
}
ResTempLow = map[int]string{
0: "message A",
1: "message B",
2: "message C",
}
ResTempHigh = map[int]string{
0: "message A",
1: "message B",
2: "message C",
}
ResHumidLow = map[int]string{
0: "message A",
1: "message B",
2: "message C",
}
ResHumidHigh = map[int]string{
0: "message A",
1: "message B",
2: "message C",
}
)
func init() {
var err error
Bot, err = linebot.New(Secret, Token)
if err != nil {
fmt.Println(err)
return
}
dev, err := i2c.Open(&i2c.Devfs{Dev: "/dev/i2c-1"}, 0x76)
if err != nil {
fmt.Print(err)
}
Bme = bme280.New(dev)
Bme.Init()
conn, err := spi.Open(&spi.Devfs{
Dev: "/dev/spidev0.0",
Mode: spi.Mode0,
MaxSpeed: 3600000,
})
if err != nil {
panic(fmt.Sprintf("failed to open SPI device: %s", err))
}
Adc = microchip.MCP3008{
Conn: conn,
Vref: 5.0,
InputType: adc.PseudoDifferential,
}
Dynamo = dynamodb.New(session.New(), aws.NewConfig().WithRegion("ap-northeast-1"))
}
func main() {
sigchan := make(chan os.Signal)
signal.Notify(sigchan, os.Interrupt)
signal.Notify(sigchan, syscall.SIGTERM)
startMessage()
go func() {
var messages []linebot.Message
for {
c, _ := Adc.OutputCode(0)
switch true {
case (c < 600 && c >= 500):
message := linebot.NewTextMessage("humidity warn")
messages = append(messages, message)
Bot.PushMessage(ChannelId, messages...).Do()
case (c < 500):
message := linebot.NewTextMessage("low humdity")
messages = append(messages, message)
Bot.PushMessage(ChannelId, messages...).Do()
}
time.Sleep(3600 * time.Second)
}
}()
c := cron.New()
c.AddFunc("0 0-23/6 * * *", func() {
t, p, h, _ := Bme.EnvData()
hum, _ := Adc.OutputCode(0)
v, _ := Adc.Voltage(0)
pushGaugeData(t, p, h, hum, v)
})
c.Start()
go func() {
http.HandleFunc("/callback", callbackMessage)
err := http.ListenAndServeTLS(SSLPort, LetsencryptChain, LetsencryptPrivate, nil)
if err != nil {
log.Fatal(err)
}
}()
fmt.Println("Server Works!")
<-sigchan
}
func startMessage() {
message := linebot.NewTextMessage("bot start")
var messages []linebot.Message
messages = append(messages, message)
_, err := Bot.PushMessage(ChannelId, messages...).Do()
if err != nil {
fmt.Println(err)
return
}
}
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:
mess := resMessage(message.Text)
if _, err = Bot.ReplyMessage(event.ReplyToken, linebot.NewTextMessage(mess)).Do(); err != nil {
log.Print(err)
}
}
}
}
}
func resMessage(mess string) (response string) {
t, _, h, _ := Bme.EnvData()
hum, _ := Adc.OutputCode(0)
volt, _ := Adc.Voltage(0)
t = t - 2
if strings.Index(mess, "教えて") >= 0 || strings.Index(mess, "おしえて") >= 0 || strings.Index(mess, "くわしく") >= 0 || strings.Index(mess, "詳しく") >= 0 {
response = fmt.Sprintf("Temperature %s℃, Humidity %s%%, Soil humidity %d, Volt %s", strconv.FormatFloat(t, 'g', 4, 64), strconv.FormatFloat(h, 'f', 1, 64), hum, strconv.FormatFloat(volt, 'f', 1, 64))
} else {
var r int
switch true {
case (t >= 30.0):
r = rand.Intn(len(ResTempHigh))
response = ResTempHigh[r]
case (hum >= 900):
r = rand.Intn(len(ResHumidHigh))
response = ResHumidHigh[r]
case (hum <= 700):
r = rand.Intn(len(ResHumidLow))
response = ResHumidLow[r]
case (t <= 18.0):
r = rand.Intn(len(ResTempLow))
response = ResTempLow[r]
default:
r = rand.Intn(len(ResNormal))
response = ResNormal[r]
}
}
return response
}
func pushGaugeData(t float64, p float64, h float64, c int, v float64) {
now := time.Now()
param := &dynamodb.UpdateItemInput{
TableName: aws.String("YourDynamoSchema"),
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"),
"#humidity": aws.String("humidity"),
"#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)),
},
":humidity": {
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, #humidity = :humidity, #volt = :volt, #raw = :raw"),
ReturnConsumedCapacity: aws.String("NONE"),
ReturnItemCollectionMetrics: aws.String("NONE"),
ReturnValues: aws.String("NONE"),
}
_, err := Dynamo.UpdateItem(param)
if err != nil {
fmt.Println(err)
}
}