344 lines
7.7 KiB
Go
344 lines
7.7 KiB
Go
package service
|
||
|
||
import (
|
||
"encoding/hex"
|
||
"encoding/json"
|
||
"errors"
|
||
"fmt"
|
||
"io/ioutil"
|
||
"net/http"
|
||
"strings"
|
||
"time"
|
||
|
||
MQTT "github.com/eclipse/paho.mqtt.golang"
|
||
"github.com/shirou/gopsutil/cpu"
|
||
"github.com/shirou/gopsutil/disk"
|
||
"github.com/shirou/gopsutil/mem"
|
||
"github.com/sirupsen/logrus"
|
||
"github.com/spf13/viper"
|
||
"github.com/vmihailenco/msgpack"
|
||
"myschools.me/wyh/ble-april/mosquitto"
|
||
)
|
||
|
||
var m map[string]*IBeancon
|
||
var chn chan *IBeancon
|
||
var token string
|
||
var expiretime time.Time
|
||
|
||
func init() {
|
||
m = make(map[string]*IBeancon, 500)
|
||
chn = make(chan *IBeancon, 500)
|
||
}
|
||
|
||
type Bletoken struct {
|
||
AppKey string
|
||
AppSecret string
|
||
}
|
||
|
||
type BleResponse struct {
|
||
Code int
|
||
Msg string
|
||
Data struct {
|
||
Token string
|
||
Expire int64
|
||
}
|
||
}
|
||
|
||
func Bletokeninit() {
|
||
for {
|
||
if time.Now().Before(expiretime) {
|
||
time.Sleep(5 * time.Minute)
|
||
continue
|
||
}
|
||
|
||
bb, err := json.Marshal(&Bletoken{
|
||
AppKey: viper.GetString("api.appkey"),
|
||
AppSecret: viper.GetString("api.appsecret"),
|
||
})
|
||
if err != nil {
|
||
logrus.WithFields(logrus.Fields{
|
||
"func": "Bletokeninit",
|
||
}).Warnf("%s", err.Error())
|
||
continue
|
||
}
|
||
reader := strings.NewReader(string(bb))
|
||
//生成要访问的url
|
||
url := fmt.Sprintf("%s/oauth", viper.GetString("srv.host"))
|
||
resp, err := http.Post(url, "application/json;charset=UTF-8", reader)
|
||
if err != nil {
|
||
logrus.WithFields(logrus.Fields{
|
||
"func": "BleMessagePush",
|
||
}).Warnf("http.post: %s", err.Error())
|
||
continue
|
||
}
|
||
|
||
body, err := ioutil.ReadAll(resp.Body)
|
||
if err != nil {
|
||
logrus.Println("ioutil.ReadAll:", err.Error())
|
||
continue
|
||
}
|
||
logrus.Println("body", string(body))
|
||
// 解析返回值,正确时添加入内存
|
||
retbody := &BleResponse{}
|
||
err = json.Unmarshal(body, retbody)
|
||
if err != nil {
|
||
logrus.Println("err: ", err)
|
||
}
|
||
token = retbody.Data.Token
|
||
expire := retbody.Data.Expire
|
||
expiretime = time.Now().Add(time.Duration(time.Duration(expire) * time.Second))
|
||
|
||
}
|
||
|
||
}
|
||
|
||
//蓝牙接收服务
|
||
|
||
var connHandler MQTT.OnConnectHandler = func(client MQTT.Client) {
|
||
token := client.Subscribe("gw/april", 0, serviceHandler)
|
||
if token.Wait() && token.Error() != nil {
|
||
fmt.Println(token.Error())
|
||
}
|
||
}
|
||
|
||
var connLostHandler MQTT.ConnectionLostHandler = func(client MQTT.Client, err error) {
|
||
fmt.Println(err.Error())
|
||
}
|
||
|
||
//具体业务订阅的处理,此处为示例
|
||
var serviceHandler MQTT.MessageHandler = func(client MQTT.Client, msg MQTT.Message) {
|
||
out1 := make(map[string]interface{}, 0)
|
||
if err := msgpack.Unmarshal(msg.Payload(), &out1); err != nil {
|
||
logrus.WithFields(logrus.Fields{
|
||
"func": "NewiBeacon",
|
||
}).Warnf("%s", err.Error())
|
||
return
|
||
}
|
||
// 解析out1.device
|
||
bles := BleDecode(out1["devices"].([]interface{}))
|
||
for _, d := range bles {
|
||
chn <- &IBeancon{
|
||
DeviceID: fmt.Sprintf("%s:%s:%s:%s:%s:%s", d.Mac[0:2], d.Mac[2:4], d.Mac[4:6], d.Mac[6:8], d.Mac[8:10], d.Mac[10:12]),
|
||
HappenTime: time.Now(),
|
||
Updated: time.Now().Unix(),
|
||
}
|
||
}
|
||
}
|
||
|
||
func BleDelivery() {
|
||
if err := mosquitto.Subscribe(connHandler, connLostHandler); err != nil {
|
||
logrus.WithFields(logrus.Fields{
|
||
"func": "BleDelivery",
|
||
}).Warnf("%s", err.Error())
|
||
return
|
||
}
|
||
|
||
}
|
||
|
||
// 取出数据进行处理
|
||
func BleMessagePush() {
|
||
|
||
for {
|
||
if b, ok := <-chn; ok {
|
||
// // 上传服务器
|
||
bb, err := json.Marshal(b)
|
||
if err != nil {
|
||
continue
|
||
}
|
||
reader := strings.NewReader(string(bb))
|
||
// 发送请求
|
||
url := fmt.Sprintf("%s/receive", viper.GetString("srv.host"))
|
||
|
||
client := &http.Client{}
|
||
//生成要访问的url
|
||
|
||
//提交请求
|
||
reqest, err := http.NewRequest("POST", url, reader)
|
||
//增加header选项
|
||
reqest.Header.Set("token", token)
|
||
reqest.Header.Set("Content-Type", "application/json;charset=UTF-8")
|
||
if err != nil {
|
||
logrus.WithFields(logrus.Fields{
|
||
"func": "BleMessagePush",
|
||
}).Warnf("%s", err.Error())
|
||
continue
|
||
}
|
||
//处理返回结果
|
||
resp, err := client.Do(reqest)
|
||
if err != nil {
|
||
logrus.WithFields(logrus.Fields{
|
||
"func": "BleMessagePush",
|
||
}).Warnf("%s", err.Error())
|
||
continue
|
||
}
|
||
defer resp.Body.Close()
|
||
body, err := ioutil.ReadAll(resp.Body)
|
||
if err != nil {
|
||
logrus.Println("ioutil.ReadAll:", err.Error())
|
||
continue
|
||
}
|
||
logrus.Println("body", string(body))
|
||
// 解析返回值,正确时添加入内存
|
||
i := make(map[string]interface{}, 0)
|
||
err = json.Unmarshal(body, &i)
|
||
if err != nil {
|
||
logrus.Println("err: ", err.Error())
|
||
continue
|
||
}
|
||
if i["msg"] == "ok" {
|
||
m[b.DeviceID] = b
|
||
}
|
||
}
|
||
|
||
}
|
||
}
|
||
|
||
type IBeancon struct {
|
||
DeviceID string
|
||
HappenTime time.Time
|
||
Updated int64 `json:"-"`
|
||
}
|
||
|
||
type BleHeart struct {
|
||
Cpu float64
|
||
Mem float64
|
||
Disk float64
|
||
}
|
||
|
||
func BleHeartBeat() {
|
||
|
||
for {
|
||
time.Sleep(1 * time.Minute)
|
||
// 判断60内有无通讯
|
||
if len(m) != 0 {
|
||
continue
|
||
}
|
||
percent, _ := cpu.Percent(time.Second, false)
|
||
memInfo, _ := mem.VirtualMemory()
|
||
parts, _ := disk.Partitions(true)
|
||
diskInfo, _ := disk.Usage(parts[0].Mountpoint)
|
||
|
||
heart := &BleHeart{
|
||
Cpu: percent[0],
|
||
Mem: memInfo.UsedPercent,
|
||
Disk: diskInfo.UsedPercent,
|
||
}
|
||
ht, err := json.Marshal(heart)
|
||
if err != nil {
|
||
logrus.Println("json.Marshal: ", err.Error())
|
||
continue
|
||
}
|
||
reader := strings.NewReader(string(ht))
|
||
// 发送请求
|
||
url := fmt.Sprintf("%s/heart", viper.GetString("srv.host"))
|
||
|
||
client := &http.Client{}
|
||
//生成要访问的url
|
||
|
||
//提交请求
|
||
reqest, err := http.NewRequest("POST", url, reader)
|
||
//增加header选项
|
||
reqest.Header.Set("token", token)
|
||
reqest.Header.Set("Content-Type", "application/json;charset=UTF-8")
|
||
if err != nil {
|
||
logrus.WithFields(logrus.Fields{
|
||
"func": "BleMessagePush",
|
||
}).Warnf("%s", err.Error())
|
||
continue
|
||
}
|
||
//处理返回结果
|
||
resp, err := client.Do(reqest)
|
||
if err != nil {
|
||
logrus.WithFields(logrus.Fields{
|
||
"func": "BleMessagePush",
|
||
}).Warnf("%s", err.Error())
|
||
continue
|
||
}
|
||
defer resp.Body.Close()
|
||
body, err := ioutil.ReadAll(resp.Body)
|
||
if err != nil {
|
||
logrus.Println("ioutil.ReadAll:", err.Error())
|
||
continue
|
||
}
|
||
|
||
logrus.Println("heart", string(body))
|
||
// 解析返回值,正确时添加入内存
|
||
i := make(map[string]interface{}, 0)
|
||
err = json.Unmarshal(body, &i)
|
||
if err != nil {
|
||
logrus.Println("err: ", err.Error())
|
||
continue
|
||
}
|
||
if i["msg"] != "ok" {
|
||
logrus.WithFields(logrus.Fields{
|
||
"func": "BleHeartBeat",
|
||
}).Warnf("%s", errors.New("Push Heart Fail"))
|
||
continue
|
||
}
|
||
// 没有通讯发送请求,cpu,内存,磁盘占用率
|
||
}
|
||
}
|
||
|
||
type BeaconAprilBag struct {
|
||
VFirmware string `json:"v-firmware"`
|
||
MID uint `json:"mid"`
|
||
Time int64 `json:"time"`
|
||
IP string `json:"ip"`
|
||
Mac string `json:"mac"`
|
||
Devices []byte `json:"devices"`
|
||
}
|
||
|
||
type BeaconApril struct {
|
||
AdvType string
|
||
Mac string
|
||
Rssi string
|
||
AdvertisementData string
|
||
}
|
||
|
||
// func NewiBeacon(data []byte, mac string) (*IBeancon, error) {
|
||
|
||
// // bytes.Split()
|
||
|
||
// if len(data) < 25 || binary.BigEndian.Uint32(data) != 0x4c000215 {
|
||
// return nil, errors.New("not an iBeacon")
|
||
// }
|
||
// beacon := new(IBeancon)
|
||
// beacon.DeviceID = blespril.Mac
|
||
// beacon.HappenTime = time.Now()
|
||
// beacon.Updated = time.Now().Unix()
|
||
// return beacon, nil
|
||
// }
|
||
|
||
// 清除缓存
|
||
func BleCacheClear() {
|
||
t := viper.GetInt64("option.interval")
|
||
if t < 30 {
|
||
t = 30
|
||
}
|
||
for {
|
||
now := time.Now().Unix()
|
||
for k, v := range m {
|
||
if now-v.Updated > t {
|
||
delete(m, k)
|
||
}
|
||
}
|
||
|
||
time.Sleep(time.Duration(t/5) * time.Second)
|
||
}
|
||
}
|
||
|
||
// 蓝牙解密
|
||
func BleDecode(data []interface{}) []*BeaconApril {
|
||
bles := make([]*BeaconApril, 0)
|
||
for _, val := range data {
|
||
vals := strings.ToUpper(hex.EncodeToString(val.([]byte)))
|
||
bles = append(bles, &BeaconApril{
|
||
AdvType: vals[0:2],
|
||
Mac: vals[2:14],
|
||
Rssi: vals[14:16],
|
||
AdvertisementData: vals[16:],
|
||
})
|
||
}
|
||
return bles
|
||
}
|