YHGW/router.go

711 lines
19 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package main
import (
"encoding/json"
"github.com/gin-contrib/cors"
"github.com/gin-gonic/gin"
_ "github.com/mattn/go-sqlite3"
"io/ioutil"
"log"
"math"
"net/http"
"strconv"
"strings"
"sync"
"time"
)
var router = gin.Default()
// GW网关api路由
func gw_router() {
router.Use(cors.Default())
v1 := router.Group("/api/v1")
{
v1.GET("/weather", gw_weather_api)
v1.POST("/renliu", get_renliu_api)
v1.POST("/feedback", get_pj_api)
v1.GET("/totalWater", sb_api)
v1.GET("/totalElectricity", db_api)
v1.GET("/environmentDate", kq_api)
v1.GET("/traffic", renliu_api)
v1.GET("/stink", aq_api)
v1.GET("/satisfaction", pj_api)
v1.GET("/seat/:id", seat_api)
v1.POST("/push", push)
v1.GET("/getConf")
}
router.Run(":10086")
}
type DparkConf struct {
ExtensionInTime int `json:"in"`
ExtensionOutTime int `json:"out"`
}
var dparkConf DparkConf
//获取数据防抖配置时间
func getConf() {
resp, err := http.Get("https://smartoilets.cn/socketServer/dpark/getConf")
if err != nil {
// handle error
log.Println("getConf.get.err", err)
return
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
// handle error
log.Println("getConf.readData.err", err)
return
}
if err := json.Unmarshal([]byte(body), &dparkConf); err == nil {
log.Println("yunhorndebug.getConf.success:", dparkConf)
}
if dparkConf.ExtensionInTime == 0 && dparkConf.ExtensionOutTime == 0 {
return
}
if dparkConf.ExtensionInTime < 0 {
dparkConf.ExtensionInTime = 0
}
if dparkConf.ExtensionOutTime < 0 {
dparkConf.ExtensionOutTime = 0
}
extensionInTime = dparkConf.ExtensionInTime
extensionOutTime = dparkConf.ExtensionOutTime
check(err)
}
//距离有效判断
var reactTof = 1650
//数据防抖 进入时间
var extensionInTime = 6
//数据防抖 离开时间
var extensionOutTime = 10
var oldData1 = ""
var oldData2 = ""
var oldData3 = ""
var dataMap sync.Map
//接收传感器push来的数据解析并上传到云端
func push(c *gin.Context) {
nowtime := time.Now()
data := c.PostForm("d")
log.Println("yunhorndeug.push.data|", data)
go pushCODE1007(data)
alldata := strings.Split(data, "#")
if len(alldata) != 2 {
c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "data": "ok"})
return
} else {
valuedata := strings.Split(alldata[1], "*")
if len(valuedata) < 1 {
c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "data": "ok"})
return
}
dtype, error := strconv.Atoi(valuedata[0])
if error != nil {
c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "data": "errtype"})
return
}
var nowTmpData = "1#0"
if dtype == 1 {
if len(valuedata) != 3 {
c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "data": "valuedata not 3"})
return
}
addr, error := strconv.Atoi(alldata[0])
if error != nil {
c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "data": "erraddr"})
return
}
cs2001, error := strconv.Atoi(valuedata[1])
if error != nil {
c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "data": "errcs2001"})
return
}
tof, error := strconv.Atoi(valuedata[2])
if error != nil {
c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "data": "errtof"})
return
}
if addr == 1 {
if cs2001 == 1 || tof < 1650 {
nowTmpData = "1#1"
}
if oldData1 != nowTmpData {
dataMap.Store(addr, nowtime)
if oldData1 == "" {
//为空 直接改变状态
maledemoDevice.DATA["data1"] = 0
if nowTmpData == "1#1" {
maledemoDevice.DATA["data1"] = 1
}
changeData(2, maledemoDevice)
}
//存储状态
oldData1 = nowTmpData
} else {
oldDevDataTime, ok := dataMap.Load(addr)
if !ok {
log.Println("load time err", ok)
}
if ok {
if oldDevDataTime != nil {
//log.Println("t2.Sub(t1)", nowtime.Sub(oldDevDataTime.(time.Time)))
var duration = nowtime.Sub(oldDevDataTime.(time.Time)).Seconds()
var durationAsInt64 = int(duration)
log.Printf("yunhorndebug.origin.%s|%s|%d|%d|%d|%d|%d", oldData1, nowTmpData, addr, dtype, cs2001, tof, durationAsInt64)
if nowTmpData == "1#0" {
if durationAsInt64 < extensionOutTime {
c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "data": "not enough time"})
return
}
} else {
if durationAsInt64 < extensionInTime {
c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "data": "not enough time"})
return
}
}
maledemoDevice.DATA["data1"] = 0
if nowTmpData == "1#1" {
maledemoDevice.DATA["data1"] = 1
}
changeData(2, maledemoDevice)
dataMap.Delete(addr)
}
}
}
} else if addr == 2 {
if cs2001 == 1 || tof < 1650 {
nowTmpData = "1#1"
}
if oldData2 != nowTmpData {
dataMap.Store(addr, nowtime)
if oldData2 == "" {
//为空 直接改变状态
maledemoDevice.DATA["data2"] = 0
if nowTmpData == "1#1" {
maledemoDevice.DATA["data2"] = 1
}
changeData(2, maledemoDevice)
}
//存储状态
oldData2 = nowTmpData
} else {
oldDevDataTime, ok := dataMap.Load(addr)
if !ok {
log.Println("load time err", ok)
}
if ok {
if oldDevDataTime != nil {
//log.Println("t2.Sub(t1)", nowtime.Sub(oldDevDataTime.(time.Time)))
var duration = nowtime.Sub(oldDevDataTime.(time.Time)).Seconds()
var durationAsInt64 = int(duration)
log.Printf("yunhorndebug.origin.%s|%s|%d|%d|%d|%d|%d", oldData2, nowTmpData, addr, dtype, cs2001, tof, durationAsInt64)
if nowTmpData == "1#0" {
if durationAsInt64 < extensionInTime {
c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "data": "not enough time"})
return
}
} else {
if durationAsInt64 < extensionOutTime {
c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "data": "not enough time"})
return
}
}
maledemoDevice.DATA["data2"] = 0
if nowTmpData == "1#1" {
maledemoDevice.DATA["data2"] = 1
}
changeData(2, maledemoDevice)
dataMap.Delete(addr)
}
}
}
}
} else if dtype == 2 {
//吸顶传感器 没有距离数据
if len(valuedata) != 2 {
c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "data": "valuedata not 2,type2"})
return
}
addr, error := strconv.Atoi(alldata[0])
if error != nil {
c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "data": "erraddr"})
return
}
cs2001, error := strconv.Atoi(valuedata[1])
if error != nil {
c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "data": "errcs2001"})
return
}
if cs2001 == 1 {
nowTmpData = "1#1"
}
if oldData3 != nowTmpData {
dataMap.Store(addr, nowtime)
if oldData3 == "" {
//为空 直接改变状态
femaledemoDevice.DATA["data1"] = 0
if nowTmpData == "1#1" {
femaledemoDevice.DATA["data1"] = 1
}
changeData(2, maledemoDevice)
}
//存储状态
oldData3 = nowTmpData
} else {
oldDevDataTime, ok := dataMap.Load(addr)
if !ok {
log.Println("load time err", ok)
}
if ok {
if oldDevDataTime != nil {
//log.Println("t2.Sub(t1)", nowtime.Sub(oldDevDataTime.(time.Time)))
var duration = nowtime.Sub(oldDevDataTime.(time.Time)).Seconds()
var durationAsInt64 = int(duration)
var tof = 0
log.Printf("yunhorndebug.origin.%s|%s|%d|%d|%d|%d|%d", oldData3, nowTmpData, addr, dtype, cs2001, tof, durationAsInt64)
if nowTmpData == "1#0" {
if durationAsInt64 < extensionInTime {
c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "data": "not enough time"})
return
}
} else {
if durationAsInt64 < extensionOutTime {
c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "data": "not enough time"})
return
}
}
femaledemoDevice.DATA["data1"] = 0
if nowTmpData == "1#1" {
femaledemoDevice.DATA["data1"] = 1
}
changeData(3, femaledemoDevice)
dataMap.Delete(addr)
}
}
}
}
}
log.Println("data:", data)
c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "data": data})
}
//发送code1007数据到云端
func pushCODE1007(data string) {
//resp, err := http.PostForm("https://smartoilets.cn/socketServer/static/push",
// url.Values{"d": {data}})
resp, err := http.Post("https://smartoilets.cn/socketServer/statis/push",
"application/x-www-form-urlencoded",
strings.NewReader("d="+data))
if err != nil {
log.Print("yunhorndebug.pushCODE1007.err", err)
}
defer resp.Body.Close()
}
func changeData(num int, device Device) {
log.Println("device:", device)
DEVICEDATAS.DATA[demoDevice.VERSION+"_"+strconv.Itoa(num)] = device
}
type EventNotificationAlert struct {
IPADDRESS string `xml:"ipAddress" json:"ipAddress"`
PROTOCOLTYPE string `xml:"protocolType" json:"protocolType"`
MACADDRESS string `xml:"macAddress" json:"macAddress"`
CHANNELID uint16 `xml:"channelID" json:"channelID"`
DATETIME string `xml:"dateTime" json:"dateTime"`
ACTIVEPOSTCOUNT uint16 `xml:"activePostCount" json:"activePostCount"`
EVENTTYPE string `xml:"eventType" json:"eventType"`
EVENTSTATE string `xml:"eventState" json:"eventState"`
EVENTDESCRIPTION string `xml:"eventDescription" json:"eventDescription"`
CHANNELNAME string `xml:"channelName" json:"channelName"`
PEOPLECOUNTING PeopleCounting `xml:"peopleCounting" json:"peopleCounting"`
}
type PeopleCounting struct {
STATISTICALMETHODS string `xml:"statisticalMethods" json:"statisticalMethods"`
TIMERANGE Timerange `xml:"TimeRange" json:"TimeRange"`
ENTER uint16 `xml:"enter" json:"enter"`
EXIT uint16 `xml:"exit" json:"exit"`
PASS uint16 `xml:"pass" json:"pass"`
}
type Timerange struct {
STARTTIME string `xml:"startTime" json:"startTime"`
ENDTIME string `xml:"endTime" json:"endTime"`
}
type FeedBack struct {
FEEDBACK string `json:"feedback"`
ID string `json:"id"`
}
var rl_data EventNotificationAlert
// 提交人流量api
func get_renliu_api(c *gin.Context) {
err := c.Bind(&rl_data)
if conf.DEBUG {
log.Println(rl_data)
}
check(err)
send_data(1004)
c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "data": rl_data})
}
var pj_data FeedBack
// 提交评价api
func get_pj_api(c *gin.Context) {
err = c.Bind(&pj_data)
check(err)
send_data(1006)
c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "data": pj_data})
}
// 获取水表api
func sb_api(c *gin.Context) {
DEVICEDATAS.RLock()
var data = make(map[string]uint16)
for _, i := range conf.DEVICES_LIST {
if i[2] == "yunhorn_sb_c_v1" {
if DEVICEDATAS.DATA[i[2]+"_"+i[3]].DATA["totalWater"] != nil {
data["totalWater"] = data["totalWater"] + DEVICEDATAS.DATA[i[2]+"_"+i[3]].DATA["totalWater"].(uint16)
}
}
}
DEVICEDATAS.RUnlock()
c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "data": data})
}
// 获取电表api
func db_api(c *gin.Context) {
DEVICEDATAS.RLock()
var data = make(map[string]float32)
for _, i := range conf.DEVICES_LIST {
if i[2] == "yunhorn_db_c_v1" {
if DEVICEDATAS.DATA[i[2]+"_"+i[3]].DATA["totalElectric"] != nil {
data["totalElectric"] = data["totalElectric"] + DEVICEDATAS.DATA[i[2]+"_"+i[3]].DATA["totalElectric"].(float32)
}
}
}
DEVICEDATAS.RUnlock()
c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "data": data})
}
// 获取空气数据api
func kq_api(c *gin.Context) {
DEVICEDATAS.RLock()
var sum float32
var toinitdata float32 = 0.0
var data = make(map[string]interface{})
for _, i := range conf.DEVICES_LIST {
if i[2] == "yunhorn_kq_c_v1" {
sum++
for k, j := range DEVICEDATAS.DATA[i[2]+"_"+i[3]].DATA {
if j != nil {
data[k] = toinitdata
data[k] = (data[k].(float32) + j.(float32)) / sum
}
}
}
}
DEVICEDATAS.RUnlock()
c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "data": data})
}
// 获取氨气数据api
func aq_api(c *gin.Context) {
DEVICEDATAS.RLock()
var sum uint16
var toinitdata uint16 = 0
var data_buf = make(map[string]interface{})
var data = make(map[string]interface{})
for _, i := range conf.DEVICES_LIST {
if i[2] == "yunhorn_aq_c_v1" {
sum++
if DEVICEDATAS.DATA[i[2]+"_"+i[3]].DATA["氨气"] != nil {
data_buf["氨气"] = toinitdata
data_buf["氨气"] = (data_buf["氨气"].(uint16) + DEVICEDATAS.DATA["yunhorn_aq_c_v1_"+i[3]].DATA["氨气"].(uint16)) / sum
}
}
}
if data_buf["氨气"] == nil {
data["stink"] = "无味"
} else {
if data_buf["氨气"].(uint16) <= 1 {
data["stink"] = "无味"
} else if data_buf["氨气"].(uint16) > 1 && data_buf["氨气"].(uint16) <= 10 {
data["stink"] = "有味"
} else if data_buf["氨气"].(uint16) > 10 && data_buf["氨气"].(uint16) <= 40 {
data["stink"] = "恶臭"
} else if data_buf["氨气"].(uint16) > 40 && data_buf["氨气"].(uint16) <= 100 {
data["stink"] = "超级恶臭"
}
}
DEVICEDATAS.RUnlock()
c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "data": data})
}
// 获取人流量api
func renliu_api(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "data": traffic_data})
}
// 获取评价api
func pj_api(c *gin.Context) {
var data float64
data = good / (good + bad)
satisfaction_data.SATISFACTION = Round(data, 2)
c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "data": satisfaction_data})
}
// 精确到小数点后n位
func Round(f float64, n int) float64 {
n10 := math.Pow10(n)
return math.Trunc((f+0.5/n10)*n10) / n10
}
type Seat_data struct {
POSITIONLIST []interface{} `json:"positionList"`
HASPERSONLIST []interface{} `json:"hasPersonList"`
EMPTYPOSITION uint16 `json:"emptyPosition"`
OCCUPYPOSITION uint16 `json:"occupyPosition"`
}
// 厕位占用api
func seat_api(c *gin.Context) {
DEVICEDATAS.RLock()
type_id := c.Param("id")
var data Seat_data
var conf_data [][]interface{}
//conf.GATEWAY_INFO.CONFIG 采集器配置信息
for _, i := range conf.GATEWAY_INFO.CONFIG {
//if i.ID == "deb03e28-ddcb-4e5d-aa31-d870a1f0f09b" {
// log.Println("begin debug")
//}
arr := get_seat_device_data(i.ID)
//获取到设备版本
version, num := arr[0], arr[1]
//if i.ID == "deb03e28-ddcb-4e5d-aa31-d870a1f0f09b" {
// log.Println("conf.data:", i.DATA)
// log.Println("devicedatas.data:", DEVICEDATAS.DATA)
//}
for k, j := range i.DATA {
if DEVICEDATAS.DATA[version+"_"+num].DATA != nil {
//if i.ID == "deb03e28-ddcb-4e5d-aa31-d870a1f0f09b" {
// log.Println("data:", DEVICEDATAS.DATA[version+"_"+num].DATA)
//}
log.Println("============================devicedatas.data:", DEVICEDATAS.DATA[version+"_"+num].DATA)
if DEVICEDATAS.DATA[version+"_"+num].DATA["data"+strconv.Itoa(k+1)] != nil {
log.Println("==========================do.data:", DEVICEDATAS.DATA[version+"_"+num].DATA["data"+strconv.Itoa(k+1)])
j = append(j, DEVICEDATAS.DATA[version+"_"+num].DATA["data"+strconv.Itoa(k+1)])
}
}
conf_data = append(conf_data, j)
}
}
log.Println("end conf.data:", conf_data)
switch type_id {
case "1":
data = scan_seat_from_confdata("男厕位", conf_data)
case "2":
data = scan_seat_from_confdata("男便池", conf_data)
case "3":
data = scan_seat_from_confdata("女厕位", conf_data)
case "4":
data = scan_seat_from_confdata("母婴", conf_data)
case "5":
data = scan_seat_from_confdata("残卫", conf_data)
}
DEVICEDATAS.RUnlock()
c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "data": data})
}
// 拼凑位置信息的数据
func get_seat_device_data(id string) []string {
//log.Println("begin get_seat_device_data.id:", id)
var data = make([]string, 2)
//配置表中devices_list
//例如["4E5D52DD-EB81-43C0-A2B6-04E432412EBA", "loraport", "yunhorn_kgl_l_v1", "1"],
for _, i := range conf.DEVICES_LIST {
// log.Println("&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&")
// log.Println(i)
if id == i[0] {
data[0], data[1] = i[2], i[3]
log.Println(data)
break
} else {
data[0], data[1] = "null", "null"
}
}
//log.Println("get_seat_device_data:", data)
return data
}
// 从配置文件中匹配对应的数据
func scan_seat_from_confdata(T string, conf_data [][]interface{}) Seat_data {
var data Seat_data
//实例化空集合
data.POSITIONLIST = make([]interface{}, 0)
data.HASPERSONLIST = make([]interface{}, 0)
for _, i := range conf_data {
if i[0] == T {
data.POSITIONLIST = append(data.POSITIONLIST, i[1])
if len(i) < 3 {
i = append(i, 0)
}
data.HASPERSONLIST = append(data.HASPERSONLIST, i[2])
switch i[2] {
case 0:
data.EMPTYPOSITION++
case 1:
data.OCCUPYPOSITION++
}
}
}
return data
}
type WEATHER struct {
SKYCON string `json:"skycon"`
ICON_URL string `json:"icon_url"`
O3 float32 `json:"o3"`
CO float32 `json:"co"`
SO2 float32 `json:"so2"`
NO2 float32 `json:"no2"`
TEMPERATURE float32 `json:"temperature"`
HUMIDITY float32 `json:"humidity"`
PM25 float32 `json:"pm25"`
PM10 float32 `json:"pm10"`
CLOUDRATE float32 `json:"cloudrate"`
AQI float32 `json:"aqi"`
DSWRF float32 `json:"dswrf"`
VISIBILITY float32 `json:"visibility"`
ULTRAVIOLET_DESC string `json:"ultraviolet_desc"`
PRES float32 `json:"pres"`
COMFORT_DESC string `json:"comfort_desc"`
WIND_DIRECTION float32 `json:"wind_direction"`
WIND_SPEED float32 `json:"wind_speed"`
TEMPERATURE_INDOOR interface{} `json:"temperature_indoor"`
HUMIDITY_INDOOR interface{} `json:"humidity_indoor"`
}
// 获取天气情况api
func gw_weather_api(c *gin.Context) {
DEVICEDATAS.RLock()
rows, _ := db.Query("SELECT skycon, icon_url, o3, co, so2, no2, temperature, humidity, pm25, pm10, cloudrate, aqi, dswrf, visibility, ultraviolet_desc, pres, comfort_desc, wind_direction, wind_speed FROM weather order by id DESC limit 1")
var data WEATHER
rows.Next()
rows.Scan(
&data.SKYCON,
&data.ICON_URL,
&data.O3,
&data.CO,
&data.SO2,
&data.NO2,
&data.TEMPERATURE,
&data.HUMIDITY,
&data.PM25,
&data.PM10,
&data.CLOUDRATE,
&data.AQI,
&data.DSWRF,
&data.VISIBILITY,
&data.ULTRAVIOLET_DESC,
&data.PRES,
&data.COMFORT_DESC,
&data.WIND_DIRECTION,
&data.WIND_SPEED)
rows.Close()
var sum float32
var toinitdata float32 = 0.0
var data_buf = make(map[string]interface{})
for _, i := range conf.DEVICES_LIST {
if i[2] == "yunhorn_kq_c_v1" {
sum++
for k, j := range DEVICEDATAS.DATA[i[2]+"_"+i[3]].DATA {
if j != nil {
data_buf[k] = toinitdata
data_buf[k] = (data_buf[k].(float32) + j.(float32)) / sum
}
}
}
}
data.TEMPERATURE_INDOOR = data_buf["温度"]
data.HUMIDITY_INDOOR = data_buf["湿度"]
DEVICEDATAS.RUnlock()
c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "data": data})
}