package main

import (
	"bytes"
	"encoding/json"
	"io/ioutil"
	"log"
	"math"
	"net"
	"net/http"
	"strconv"
	"sync"
	"time"

	"github.com/gin-contrib/cors"
	"github.com/gin-gonic/gin"
	_ "github.com/mattn/go-sqlite3"
)

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")
		v1.GET("/writeCommand", writeCommand)
	}

	router.LoadHTMLGlob("static/*")

	opsV1 := router.Group("/ops/v1")
	{
		opsV1.GET("/index", func(c *gin.Context) {
			c.HTML(http.StatusOK, "index.html", gin.H{
				"title": "hello Go",
			})
		})

	}

	api_port := strconv.Itoa(conf.APIPORT)

	router.Run(":" + api_port)
}

type DparkConf struct {
	ExtensionInTime   int `json:"in"`
	ExtensionOutTime  int `json:"out"`
	ExtensionInTime2  int `json:"in2"`
	ExtensionOutTime2 int `json:"out2"`
}

func writeCommand(c *gin.Context) {
	// var heartbeat []byte = []byte{0x01}
	addr := c.Query("addr")
	command := c.Query("command")
	// commandInt,err := strconv.Atoi(command)
	// if err !=nil{
	// 	c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "msg": "command"})
	// 	return;
	// }
	commands := []byte(command)
	byteAddr, ok := sensorMap.Load(addr)
	if !ok {
		c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "msg": "valid addr"})
		return
	}

	loraNode, ok := loraNodeMap.Load(addr)
	if !ok {
		c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "msg": "valid addr"})
		return
	}
	commands = []byte{0x01}
	if command == "1" {
		commands = []byte{0x01}
	} else if command == "2" {
		commands = []byte{0x02}
	} else {
		c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "msg": "valid command"})
		return
	}

	// strconv.Itoa

	var buffer bytes.Buffer
	buffer.Write(byteAddr.([]byte))
	// log.Println(commands)
	buffer.Write(commands)

	log.Println("loragws ", loraNode.(LoraNode).LORA_GWS)

	for _, loragwip := range loraNode.(LoraNode).LORA_GWS {
		loraconn, ok := loragwMap.Load(loragwip)
		if ok {
			log.Println("=======================begin push tcp command ", buffer.Bytes())
			_, err := loraconn.(net.Conn).Write(buffer.Bytes())
			if err != nil {
				log.Println("write msg error!", err)
				c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "msg": "fail"})
				return
			}
		} else {

		}

	}

	log.Println(addr)
	log.Println(command)
	log.Println("will send commands ", commands)
	c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "msg": "success"})
}

var dparkConf DparkConf

var connTest net.Conn

//获取数据防抖配置时间
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 err != nil {
		return
	}

	if dparkConf.ExtensionInTime == 0 && dparkConf.ExtensionOutTime == 0 {
		return
	}

	if dparkConf.ExtensionInTime < 0 {
		dparkConf.ExtensionInTime = 0
	}

	if dparkConf.ExtensionOutTime < 0 {
		dparkConf.ExtensionOutTime = 0
	}
	// time.
	extensionInTime = dparkConf.ExtensionInTime
	extensionOutTime = dparkConf.ExtensionOutTime

	// check(err)

}

//距离有效判断time.
var reactTof = 1650

//数据防抖 进入时间
var extensionInTime = 6

//数据防抖 离开时间
var extensionOutTime = 15

var extensionInTime2 = 0

var extensionOutTime2 = 0

var oldData1 = ""

var oldData2 = ""

var oldData3 = ""

var dataMap sync.Map

//接收传感器push来的数据,解析并上传到云端
func push(c *gin.Context) {

	data := c.PostForm("d")

	// go dealData(data)

	log.Println("data:", data)
	c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "data": data})

}

func dealDatav3(data []byte, loragwip string) string {

	nowtime := time.Now()

	log.Println("yunhorndeug.push.data|", data)

	strs := data

	buffer := new(bytes.Buffer)
	for _, b := range data[:4] {
		s := strconv.FormatInt(int64(b&0xff), 16)
		if len(s) == 1 {
			buffer.WriteString("0")
		}
		buffer.WriteString(s)
	}

	adr := buffer.String()

	var readyData bytes.Buffer

	datatype := data[5]

	if datatype == 0 {

		var R_data P1004_6
		R_data.CODE = 1008
		R_data.ID = adr
		//尿布台
		R_data.VERSION = "sts_hps_3ir"
		R_data.ONLINE = true
		R_data.DATA = make(map[string]interface{})
		R_data.DATA["restart"] = data[6]

		data_bufTmp, _ := json.Marshal(R_data)
		data_buf := string(data_bufTmp)
		go post_to_server(data_buf)

	} else if datatype == 1 || datatype == 2 {

		//dpark 1-尿布台 2-吸顶

		//过滤无效数据 adr

		cs2001 := data[6]

		var R_data P1004_6
		R_data.CODE = 1008
		R_data.ID = adr
		//尿布台
		R_data.VERSION = "sts_hps_3ir"
		R_data.ONLINE = true
		R_data.DATA = make(map[string]interface{})
		R_data.DATA["cs2001"] = cs2001
		R_data.DATA["data"] = cs2001

		datatypeStr := strconv.FormatInt(int64(data[5]&0xff), 16)

		cs2001Str := strconv.FormatInt(int64(data[6]&0xff), 16)

		//地址
		readyData.WriteString(buffer.String())
		readyData.WriteString("#")
		//类型
		readyData.WriteString(datatypeStr)
		readyData.WriteString("*")
		//红外人体感应
		readyData.WriteString(cs2001Str)

		newdtype := strs[5]

		tmp := []byte{0, 0}
		tof := tmp[0]

		if newdtype == 1 {
			tof = data[7]
			R_data.VERSION = "sts_lts_01"
			R_data.DATA["tof"] = tof
			tofTmp := strconv.FormatInt(int64(data[7]&0xff), 10)
			readyData.WriteString("*")
			readyData.WriteString(tofTmp)
		}
		R_data.TIMESTAMP = time.Now().UnixNano() / 1e6

		data_bufTmp, _ := json.Marshal(R_data)
		data_buf := string(data_bufTmp)
		go post_to_server(data_buf)

		// log.Println("readyData:",readyData.String())

		//默认当前无人占用
		current := 0

		if datatype == 1 {
			//尿布台类型
			if cs2001 == 1 || tof < 130 {
				//有人占用
				current = 1
			}
		} else if datatype == 2 {
			//吸顶类型
			if cs2001 == 1 {
				//有人占用
				current = 1
			}
		}

		// log.Println("loraNodeMap:",loraNodeMap)
		loraNode, ok := loraNodeMap.Load(adr)
		if !ok {
			log.Println("load loraNode fail ", adr)
			return ""
		}
		// log.Println("load loraNode:",loraNode)

		//log.Println("yunhorndeug.push.data.cuurent_data,current",loraNode.(LoraNode).CURRENT_DATA,current)
		if loraNode.(LoraNode).CURRENT_DATA != current {
			//不相同,直接改变状态,更新时间

			// loraNode.(LoraNode).CURRENT_DATA = current
			// loraNode.(LoraNode).TIME = time.Now()
			// loraNode.(LoraNode).CHECK_TIME = true

			newLoraNode := LoraNode{}
			newLoraNode.CURRENT_DATA = current
			newLoraNode.TIME = time.Now()
			newLoraNode.CHECK_TIME = true

			newLoraNode.LOCATION_TYPE = loraNode.(LoraNode).LOCATION_TYPE
			newLoraNode.LOCATION_CODE = loraNode.(LoraNode).LOCATION_CODE
			newLoraNode.LOCATION_DATA = loraNode.(LoraNode).LOCATION_DATA
			newLoraNode.DEVICE = loraNode.(LoraNode).DEVICE

			if !Contains(newLoraNode.LORA_GWS, loragwip) {
				newLoraNode.LORA_GWS = append(newLoraNode.LORA_GWS, loragwip)
			}

			loraNodeMap.Store(adr, newLoraNode)

			//初次启动
			if loraNode.(LoraNode).CURRENT_DATA == -1 {
				changeDataV2(newLoraNode)
			}

			if datatype == 2 && (extensionInTime2 <= 0 || extensionOutTime2 <= 0) {
				newLoraNode.CURRENT_DATA = current
				changeDataV2(newLoraNode)
			}

		} else {
			// 非首次
			if loraNode.(LoraNode).CHECK_TIME {

				var duration = nowtime.Sub(loraNode.(LoraNode).TIME).Seconds()
				var durationAsInt64 = int(duration)

				// log.Println("yunhorndeug.push.data.durationAsInt64:",durationAsInt64)

				if current == 0 {
					//类型2 吸顶
					if datatype == 2 {
						if durationAsInt64 < extensionOutTime2 && extensionOutTime2 > 0 {
							return ""
						}
					} else {
						if durationAsInt64 < extensionOutTime && extensionOutTime > 0 {
							return ""
						}
					}

				} else {
					//类型2 吸顶
					if datatype == 2 {
						if durationAsInt64 < extensionInTime2 && extensionInTime2 > 0 {
							return ""
						}
					} else {
						if durationAsInt64 < extensionInTime && extensionInTime > 0 {
							return ""
						}
					}

				}

				//改变状态
				// loraNode.(LoraNode).CHECK_TIME = false

				newLoraNode := LoraNode{}
				newLoraNode.CURRENT_DATA = current
				newLoraNode.TIME = loraNode.(LoraNode).TIME
				newLoraNode.CHECK_TIME = false

				newLoraNode.LOCATION_TYPE = loraNode.(LoraNode).LOCATION_TYPE
				newLoraNode.LOCATION_CODE = loraNode.(LoraNode).LOCATION_CODE
				newLoraNode.LOCATION_DATA = loraNode.(LoraNode).LOCATION_DATA
				newLoraNode.DEVICE = loraNode.(LoraNode).DEVICE
				if !Contains(newLoraNode.LORA_GWS, loragwip) {
					newLoraNode.LORA_GWS = append(newLoraNode.LORA_GWS, loragwip)
				}
				loraNodeMap.Store(adr, newLoraNode)

				changeDataV2(newLoraNode)
			} else {
				// loraNode.(LoraNode).CHECK_TIME = true

				newLoraNode := LoraNode{}
				newLoraNode.CURRENT_DATA = loraNode.(LoraNode).CURRENT_DATA
				newLoraNode.TIME = time.Now()
				newLoraNode.CHECK_TIME = true

				newLoraNode.LOCATION_TYPE = loraNode.(LoraNode).LOCATION_TYPE
				newLoraNode.LOCATION_CODE = loraNode.(LoraNode).LOCATION_CODE
				newLoraNode.LOCATION_DATA = loraNode.(LoraNode).LOCATION_DATA
				newLoraNode.DEVICE = loraNode.(LoraNode).DEVICE
				if !Contains(newLoraNode.LORA_GWS, loragwip) {
					newLoraNode.LORA_GWS = append(newLoraNode.LORA_GWS, loragwip)
				}

				if datatype == 2 && (extensionInTime2 <= 0 || extensionOutTime2 <= 0) {
					newLoraNode.CURRENT_DATA = current
					changeDataV2(newLoraNode)
				}

				loraNodeMap.Store(adr, newLoraNode)

			}
		}

	} else if datatype == 3 {
		var R_data P1004_6
		R_data.CODE = 1005
		R_data.ID = adr
		// "853c0000"
		//尿布台
		R_data.VERSION = "yunhorn_door_c_v1"
		R_data.ONLINE = true
		R_data.DATA = make(map[string]interface{})
		R_data.DATA["data"] = int64(data[6])
		data_bufTmp, _ := json.Marshal(R_data)
		data_buf := string(data_bufTmp)
		go post_to_server(data_buf)

	} else if datatype == 4 {
		buffer := new(bytes.Buffer)

		// log.Println("data[9]",int64(data[9]))
		// log.Println("data[10]",int64(data[10]))

		log.Println("aqdata|all:", data)

		if data[6] == 0 {
			buffer.WriteString("-")
		}

		wdint1 := strconv.FormatInt(int64(data[7]&0xff), 10)
		buffer.WriteString(wdint1)
		buffer.WriteString(".")
		wdfh := int(data[10])
		wdint2 := strconv.FormatInt(int64(data[8]&0xff), 10)
		if wdfh < 10 {
			buffer.WriteString("0")
		}
		buffer.WriteString(wdint2)

		// log.Println("aqdata|wdfh",data[6])

		wddata := buffer.String()
		// log.Println("aqdata|wddata",wddata)

		buffer = new(bytes.Buffer)

		sdint1 := strconv.FormatInt(int64(data[9]&0xff), 10)
		buffer.WriteString(sdint1)
		buffer.WriteString(".")
		sdint2 := strconv.FormatInt(int64(data[10]&0xff), 10)
		if wdfh < 10 {
			buffer.WriteString("0")
		}
		buffer.WriteString(sdint2)

		sddata := buffer.String()
		// log.Println("aqdata|sddata",sddata)

		buffer = new(bytes.Buffer)

		nh3int1 := strconv.Itoa(int(data[11]))
		buffer.WriteString(nh3int1)
		buffer.WriteString(".")
		nh3int2 := strconv.Itoa(int(data[12]))
		if int64(data[12]) < 10 {
			buffer.WriteString("0")
		}
		buffer.WriteString(nh3int2)
		nh3data := buffer.String()

		// log.Println("aqdata|nh3",nh3data)

		buffer = new(bytes.Buffer)
		h2sint1 := strconv.Itoa(int(data[13]))
		buffer.WriteString(h2sint1)
		buffer.WriteString(".")
		h2sint2 := strconv.Itoa(int(data[14]))
		if int64(data[14]) < 10 {
			buffer.WriteString("0")
		}
		buffer.WriteString(h2sint2)
		h2sdata := buffer.String()
		// log.Println("aqdata|h2s",h2sdata)

		buffer = new(bytes.Buffer)
		ch2o1 := strconv.Itoa(int(data[15]))
		buffer.WriteString(ch2o1)
		buffer.WriteString(".")
		ch2o2 := strconv.Itoa(int(data[16]))
		if int64(data[16]) < 10 {
			buffer.WriteString("0")
		}
		buffer.WriteString(ch2o2)
		ch2o := buffer.String()

		// ch2o := uint32(data[14])*256+uint32(data[15])
		// log.Println("aqdata|ch2o",ch2o)

		co2data := uint32(data[17])*256 + uint32(data[18])
		// log.Println("aqdata|co2data",co2data)

		tvocdata := data[19]
		// log.Println("aqdata|tvocdata",tvocdata)

		// log.Println("pm25data1",data[19])
		// log.Println("pm25data2",data[20])
		pm25data := uint32(data[20])*256 + uint32(data[21])
		// log.Println("aqdata|pm25data",pm25data)

		// log.Println("pm10data1",data[21])
		// log.Println("pm10data2",data[22])
		pm10data := uint32(data[22])*256 + uint32(data[23])
		// log.Println("aqdata|pm10data",pm10data)

		//wdfh
		log.Printf("aqdata|wddata|sddata|nh3data|h2sdata|ch2o|co2data|tvocdata|pm25data|pm10data")
		log.Printf("aqdata|%s|%s|%s|%s|%s|%d|%d|%d|%d", wddata, sddata, nh3data, h2sdata, ch2o, co2data, tvocdata, pm25data, pm10data)

		var R_data P1004_6
		R_data.CODE = 1005
		R_data.ID = adr
		// "dc390000"
		//尿布台
		R_data.VERSION = "yunhorn_kq_c_v1"
		R_data.ONLINE = true
		R_data.DATA = make(map[string]interface{})
		R_data.DATA["temperature"] = wddata
		R_data.DATA["humidity"] = sddata

		R_data.DATA["nh3"] = nh3data
		R_data.DATA["h2s"] = h2sdata
		R_data.DATA["ch2o"] = ch2o
		R_data.DATA["co2"] = co2data
		R_data.DATA["tvoc"] = tvocdata
		R_data.DATA["pm25"] = pm25data
		R_data.DATA["pm10"] = pm10data

		data_bufTmp, _ := json.Marshal(R_data)
		data_buf := string(data_bufTmp)
		go post_to_server(data_buf)

	}

	// log.Println("current:",current)
	// log.Println("loraNode:",loraNode)
	// log.Println("loraNode.time.is nil",(loraNode==nil))

	return ""
}

func changeData(num int, device Device) {
	log.Println("device:", device)
	DEVICEDATAS.DATA[demoDevice.VERSION+"_"+strconv.Itoa(num)] = device
}

func changeDataV2(loraNode LoraNode) {
	// log.Println("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@")
	// log.Println("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@00000:",loraNode)
	// log.Println("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@11111:",DEVICEDATAS.DATA[loraNode.DEVICE])
	// DEVICEDATAS.RLock()
	DEVICEDATAS.Lock()
	if DEVICEDATAS.DATA != nil {
		_, ok := DEVICEDATAS.DATA[loraNode.DEVICE]
		if ok {
			DEVICEDATAS.DATA[loraNode.DEVICE].DATA[loraNode.LOCATION_DATA] = loraNode.CURRENT_DATA
			log.Println("yunhorndeug.push.data.change:", DEVICEDATAS.DATA[loraNode.DEVICE])
		} else {
			log.Println("changeDataV2.DEVICEDATAS load not ok:", loraNode.DEVICE)
		}
	} else {
		log.Println("changeDataV2.DEVICEDATAS not init:", loraNode.DEVICE)
	}
	DEVICEDATAS.Unlock()
	// log.Println("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@")
}

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) {

	var rl_data EventNotificationAlert

	// var debugInt = 2
	// if debugInt > 1 {
	// 	c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "data": rl_data})
	// 	return
	// }

	err := c.Bind(&rl_data)
	if conf.DEBUG {
		log.Println(rl_data)
	}

	check(err)
	// send_data(1004)

	var R_data P1004_6
	R_data.CODE = 1004
	R_data.ID = rl_data.MACADDRESS
	R_data.VERSION = "hk_kll_v1"
	R_data.ONLINE = true
	R_data.DATA = make(map[string]interface{})
	R_data.DATA["starttime"] = rl_data.PEOPLECOUNTING.TIMERANGE.STARTTIME
	R_data.DATA["endtime"] = rl_data.PEOPLECOUNTING.TIMERANGE.ENDTIME
	R_data.DATA["enter"] = rl_data.PEOPLECOUNTING.ENTER
	R_data.DATA["pass"] = rl_data.PEOPLECOUNTING.PASS
	R_data.DATA["exit"] = rl_data.PEOPLECOUNTING.EXIT
	traffic_data.TRAFFIC = traffic_data.TRAFFIC + rl_data.PEOPLECOUNTING.ENTER
	data_buf, _ := json.Marshal(R_data)
	post_to_server(string(data_buf))

	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")
	//locationCode := c.Param("locationCode")
	var data Seat_data
	var conf_data [][]interface{}
	//conf.GATEWAY_INFO.CONFIG 采集器配置信息
	// log.Println("DEVICEDATAS.data:",DEVICEDATAS.DATA)
	for _, i := range conf.GATEWAY_INFO.CONFIG {

		//if i.LOCATION_CODE != locationCode{
		//	continue
		//}

		arr := get_seat_device_data(i.ID)
		//获取到设备版本
		version, num := arr[0], arr[1]

		if version == "null" || num == "null" {
			continue
		}
		if DEVICEDATAS.DATA[version+"_"+num].DATA != nil {
			log.Println("^^^^^^^^^^^^^^^^^^DEVICEDATAS.DATA-version_num", DEVICEDATAS.DATA[version+"_"+num])
			for k, j := range i.DATA {
				//log.Println("@@@@@@@@@@@@@@@@@@@@@@@@@@,i.DATA-j",j)
				// log.Println("============================devicedatas.data:", DEVICEDATAS.DATA[version+"_"+num].DATA)
				if DEVICEDATAS.DATA[version+"_"+num].DATA["data"+strconv.Itoa(k+1)] != nil {
					//这里不会改变DEVICEDATAS.DATA的数据,只是判断一下有没有数据,如果有,则加上
					// 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("@@@@@@@@@@@@@@@@@@@@@@@@@@,i.DATA-j,appended.conf_data",conf_data)
			}
		}
	}

	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 {
		if id == i[0] {
			data[0], data[1] = i[2], i[3]
			log.Println("get_seat_device_data", 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 {
		//T 男厕位 女厕位
		//conf_data  [[男厕位 1],[女厕位 1]]
		// 第一位是数据类型 第二位是位置 第三位是有无人占用
		//conf_data [男厕位 1 0/1]

		//把当前符合类型的数据加入到返回集合中
		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})
// }