package main

import (
    "encoding/binary"
    "github.com/tarm/serial"
    "log"
    "strconv"
    "sync"
)

type Devicedatas struct {
    sync.RWMutex
    DATA map[string]Device
}


type Device struct {
    sync.RWMutex
    ID      string                 `json:"id"`
    VERSION string                 `json:"version"`
    ONLINE  bool                   `json:"online"`
    DATA    map[string]interface{} `json:"data"`
}

func yunhorn_ys_l_v1(data_buf []byte){

  // for _, i := range conf.RS485DEVICES {
    // log.Println("################################",i)
  // }

	//log.Println(data_buf)
  // for i, k := range b_buf {
      // log.Println(binary.BigEndian.Uint16(append([]byte{0x00}, k))
  // }

  data_int := Bytes2Bits(data_buf[3:4])

  log.Println("data_int:",data_int[0])
	var device Device
	device.ID=demoDevice.ID
	device.VERSION=demoDevice.VERSION
	device.ONLINE=demoDevice.ONLINE
  demoDevice.DATA["data"+strconv.Itoa(7)]=data_int[0]
	device.DATA=demoDevice.DATA

	if conf.DEBUG {
      log.Println(device)
  }
     send_data(1005, device)

}

func yunhorn_lorawan_l_v1(s *serial.Port) {
    for {
        buf := make([]byte, 128)
        b_buf := make([]byte, 0)
        nn := 0
        for {
            n, err := s.Read(buf)
            nn = n + nn
            b_buf = append(b_buf, buf[:n]...)
            if err != nil {
                break
            }
        }
        switch nn {
        case 4:
            go yunhorn_kgl_l_v1(b_buf[:nn])
        }
    }
}

func yunhorn_kgl_l_v1(data_buf []byte) {
    log.Println(data_buf)
    var device Device
    device.Lock()
    device.ID = "4E5D52DD-EB81-43C0-A2B6-04E432412EBA"
    device.VERSION = "yunhorn_kgl_l_v1"
    device.ONLINE = true
    device.DATA = make(map[string]interface{})
    device.DATA["data1"] = 0
    device.Unlock()
    DEVICEDATAS.Lock()
    DEVICEDATAS.DATA["yunhorn_kgl_l_v1_1"] = device
    DEVICEDATAS.Unlock()

    if conf.DEBUG {
        log.Println(device)
    }

    send_data(1005, device)
}

// 采集并解析水表数据
func yunhorn_sb_c_v1(s *serial.Port, device_id string, command [][]byte, num string) {
    _, err = s.Write([]byte(command[0]))
    check(err)
    if conf.DEBUG {
        log.Printf("命令:\t%x", []byte(command[0]))
    }
    buf := make([]byte, 128)
    b_buf := make([]byte, 0)
    var nn int
    for {
        n, err := s.Read(buf)
        nn = n + nn
        b_buf = append(b_buf, buf[:n]...)
        if err != nil {
            break
        }
    }
    if nn != 39 {
        return
    }
    data_buf := b_buf[17 : nn-20]

    var device Device
    device.Lock()
    device.ID = device_id
    device.VERSION = "yunhorn_sb_c_v1"
    device.ONLINE = true
    device.DATA = make(map[string]interface{})
    device.DATA["totalWater"] = binary.BigEndian.Uint16(data_buf)
    device.Unlock()
    DEVICEDATAS.Lock()
    DEVICEDATAS.DATA["yunhorn_sb_c_v1_"+num] = device
    DEVICEDATAS.Unlock()

    if conf.DEBUG {
        log.Println(device)
    }
}

// 采集并解析洗手液数据
func yunhorn_xsy_l_v1(s *serial.Port, device_id string, command [][]byte, num string) {
    _, err = s.Write([]byte(command[0]))
    check(err)
    if conf.DEBUG {
        log.Printf("命令:\t%x", []byte(command[0]))
    }
    buf := make([]byte, 128)
    b_buf := make([]byte, 0)
    var nn int
    for {
        n, err := s.Read(buf)
        nn = n + nn
        b_buf = append(b_buf, buf[:n]...)
        if err != nil {
            break
        }
    }
    if nn != 9 {
        return
    }
    data_buf := b_buf[3 : nn-4]

    DEVICEDATAS.RLock()
    var olddata = DEVICEDATAS.DATA["yunhorn_xsy_l_v1_"+num]
    DEVICEDATAS.RUnlock()

    var device Device
    device.Lock()
    device.ID = device_id
    device.VERSION = "yunhorn_xsy_l_v1"
    device.ONLINE = true
    device.DATA = make(map[string]interface{})
    device.DATA["data"] = binary.BigEndian.Uint16(data_buf)
    device.Unlock()
    DEVICEDATAS.Lock()
    DEVICEDATAS.DATA["yunhorn_xsy_l_v1_"+num] = device
    DEVICEDATAS.Unlock()

    if device.DATA["data"] != olddata.DATA["data"] {
        send_data(1005, device)
    }
    if conf.DEBUG {
        log.Println(device)
    }
}

// 采集并解析电表数据
func yunhorn_db_c_v1(s *serial.Port, device_id string, command [][]byte, num string) {
    _, err = s.Write([]byte(command[0]))
    check(err)
    if conf.DEBUG {
        log.Printf("命令:\t%x", []byte(command[0]))
    }
    buf := make([]byte, 128)
    bb_buf := make([]byte, 0)
    var nn int
    for {
        n, err := s.Read(buf)
        nn = n + nn
        bb_buf = append(bb_buf, buf[:n]...)
        if err != nil {
            break
        }
    }
    if nn != 20 {
        return
    }
    data_buf := bb_buf[nn-6 : nn-2]
    for i, x := range data_buf {
        data_buf[i] = x - 0x33

    }
    Len := len(data_buf) - 1
    for i, k := 0, Len; i < k; i++ {
        data_buf[i], data_buf[k] = data_buf[k], data_buf[i]
        k--
    }
    U8 := make([]byte, 0)
    for i := 0; i < 4; i++ {
        U8 = append(U8, data_buf[i]>>4)
        U8 = append(U8, data_buf[i]<<4>>4)
    }
    b_buf := make([]byte, 0)
    var db_data uint32
    b_buf = append([]byte{0, 0, 0}, U8[0])
    db_data = binary.BigEndian.Uint32(b_buf) * 10000000
    b_buf = append([]byte{0, 0, 0}, U8[1])
    db_data = db_data + binary.BigEndian.Uint32(b_buf)*1000000
    b_buf = append([]byte{0, 0, 0}, U8[2])
    db_data = db_data + binary.BigEndian.Uint32(b_buf)*100000
    b_buf = append([]byte{0, 0, 0}, U8[3])
    db_data = db_data + binary.BigEndian.Uint32(b_buf)*10000
    b_buf = append([]byte{0, 0, 0}, U8[4])
    db_data = db_data + binary.BigEndian.Uint32(b_buf)*1000
    b_buf = append([]byte{0, 0, 0}, U8[5])
    db_data = db_data + binary.BigEndian.Uint32(b_buf)*100
    b_buf = append([]byte{0, 0, 0}, U8[6])
    db_data = db_data + binary.BigEndian.Uint32(b_buf)*10
    b_buf = append([]byte{0, 0, 0}, U8[7])
    db_data = db_data + binary.BigEndian.Uint32(b_buf)

    var device Device
    device.Lock()
    device.ID = device_id
    device.VERSION = "yunhorn_db_c_v1"
    device.ONLINE = true
    device.DATA = make(map[string]interface{})
    device.DATA["totalElectric"] = float32(db_data) / 100
    device.Unlock()
    DEVICEDATAS.Lock()
    DEVICEDATAS.DATA["yunhorn_db_c_v1_"+num] = device
    DEVICEDATAS.Unlock()

    if conf.DEBUG {
        log.Println(device)
    }
}

// 采集并解析空气数据
func yunhorn_kq_c_v1(s *serial.Port, device_id string, command [][]byte, num string) {
    _, err = s.Write([]byte(command[0]))
    check(err)
    if conf.DEBUG {
        log.Printf("命令:\t%x", []byte(command[0]))
    }
    buf := make([]byte, 128)
    b_buf := make([]byte, 0)
    var nn int
    for {
        n, err := s.Read(buf)
        nn = n + nn
        b_buf = append(b_buf, buf[:n]...)
        if err != nil {
            break
        }
    }
    if nn != 19 {
        return
    }
    data_buf := b_buf[3 : nn-2]

    var device Device
    device.Lock()
    device.ID = device_id
    device.VERSION = "yunhorn_kq_c_v1"
    device.ONLINE = true
    device.DATA = make(map[string]interface{})
    device.DATA["二氧化碳"] = float32(binary.BigEndian.Uint16(data_buf[0:2]))
    device.DATA["TVOC"] = float32(binary.BigEndian.Uint16(data_buf[2:4])) / 10
    device.DATA["甲醛"] = float32(binary.BigEndian.Uint16(data_buf[4:6])) / 10
    device.DATA["pm2.5"] = float32(binary.BigEndian.Uint16(data_buf[6:8]))
    device.DATA["湿度"] = float32(binary.BigEndian.Uint16(data_buf[8:10])) / 10
    device.DATA["温度"] = float32(binary.BigEndian.Uint16(data_buf[10:13])) / 10
    device.DATA["PM10"] = float32(binary.BigEndian.Uint16(data_buf[12:14]))
    device.Unlock()
    DEVICEDATAS.Lock()
    DEVICEDATAS.DATA["yunhorn_kq_c_v1_"+num] = device
    DEVICEDATAS.Unlock()

    if conf.DEBUG {
        log.Println(device)
    }
}

// 采集并解析氨气数据
func yunhorn_aq_c_v1(s *serial.Port, device_id string, command [][]byte, num string) {
    _, err = s.Write([]byte(command[0]))
    check(err)
    if conf.DEBUG {
        log.Printf("命令:\t%x", []byte(command[0]))
    }
    buf := make([]byte, 128)
    b_buf := make([]byte, 0)
    var nn int
    for {
        n, err := s.Read(buf)
        nn = n + nn
        b_buf = append(b_buf, buf[:n]...)
        if err != nil {
            break
        }
    }
    if nn != 7 {
        return
    }
    data_buf := b_buf[3 : nn-2]

    var device Device
    device.Lock()
    device.ID = device_id
    device.VERSION = "yunhorn_aq_c_v1"
    device.ONLINE = true
    device.DATA = make(map[string]interface{})
    device.DATA["氨气"] = binary.BigEndian.Uint16(data_buf)
    device.Unlock()
    DEVICEDATAS.Lock()
    DEVICEDATAS.DATA["yunhorn_aq_c_v1_"+num] = device
    DEVICEDATAS.Unlock()

    if conf.DEBUG {
        log.Println(device)
    }
}

// 采集并解析硫化氢数据
func yunhorn_lhq_c_v1(s *serial.Port, device_id string, command [][]byte, num string) {
    _, err = s.Write([]byte(command[0]))
    check(err)
    if conf.DEBUG {
        log.Printf("命令:\t%x", []byte(command[0]))
    }
    buf := make([]byte, 128)
    b_buf := make([]byte, 0)
    var nn int
    for {
        n, err := s.Read(buf)
        nn = n + nn
        b_buf = append(b_buf, buf[:n]...)
        if err != nil {
            break
        }
    }
    if nn != 7 {
        return
    }
    data_buf := b_buf[3 : nn-2]

    var device Device
    device.Lock()
    device.ID = device_id
    device.VERSION = "yunhorn_lhq_c_v1"
    device.ONLINE = true
    device.DATA = make(map[string]interface{})
    device.DATA["硫化氢"] = binary.BigEndian.Uint16(data_buf)
    device.Unlock()
    DEVICEDATAS.Lock()
    DEVICEDATAS.DATA["yunhorn_lhq_c_v1_"+num] = device
    DEVICEDATAS.Unlock()

    if conf.DEBUG {
        log.Println(device)
    }
}

// 采集并解析开关量数据
func yunhorn_kgl_c8_v1(s *serial.Port, device_id string, command [][]byte, num string) {
    buf := make([]byte, 128)
    b_buf := make([]byte, 0)
    for _, i := range command {
        _, err = s.Write([]byte(i))
        check(err)
        if conf.DEBUG {
            log.Printf("命令:\t%x", []byte(i))
        }
        _, err = s.Read(buf)
        if err != nil {
            return
        }
        b_buf = append(b_buf, buf[3])
    }
    DEVICEDATAS.RLock()
    var olddata = DEVICEDATAS.DATA["yunhorn_kgl_c8_v1_"+num]
    DEVICEDATAS.RUnlock()
    var device Device
    device.Lock()
    device.ID = device_id
    device.VERSION = "yunhorn_kgl_c8_v1"
    device.ONLINE = true
    device.DATA = make(map[string]interface{})
    for i, k := range b_buf {
        device.DATA["data"+strconv.Itoa(i+1)] = binary.BigEndian.Uint16(append([]byte{0x00}, k))
    }
    device.Unlock()
    DEVICEDATAS.Lock()
    DEVICEDATAS.DATA["yunhorn_kgl_c8_v1_"+num] = device
    DEVICEDATAS.Unlock()
    for i, k := range device.DATA {
        if k != olddata.DATA[i] {
            send_data(1005, device)
            break
        }
    }
    if conf.DEBUG {
        log.Println(device)
    }
}

// 采集并解析开关量数据
func yunhorn_kgl_c16_v1(s *serial.Port, device_id string, command [][]byte, num string) {
    buf := make([]byte, 128)
    _, err = s.Write([]byte(command[0]))
    check(err)
    if conf.DEBUG {
        log.Printf("命令:\t%x", []byte(command[0]))
    }
    _, err = s.Read(buf)
    if err != nil {
        return
    }
    b_buf := Bytes2Bits(buf[3:5])

    DEVICEDATAS.RLock()
    var olddata = DEVICEDATAS.DATA["yunhorn_kgl_c16_v1_"+num]
    DEVICEDATAS.RUnlock()
    var device Device
    device.Lock()
    device.ID = device_id
    device.VERSION = "yunhorn_kgl_c16_v1"
    device.ONLINE = true
    device.DATA = make(map[string]interface{})
    for i, k := range b_buf {
        device.DATA["data"+strconv.Itoa(i+1)] = k
    }
    device.Unlock()
    DEVICEDATAS.Lock()
    DEVICEDATAS.DATA["yunhorn_kgl_c16_v1_"+num] = device
    DEVICEDATAS.Unlock()
    for i, k := range device.DATA {
        if k != olddata.DATA[i] {
            send_data(1005, device)
            break
        }
    }
    if conf.DEBUG {
        log.Println(device)
    }
}

// byte数据转换成uint16
func Bytes2Bits(data []byte) []uint16 {
    dst := make([]uint16, 0)
    for _, v := range data {
        for i := 0; i < 8; i++ {
            move := uint(i)
            dst = append(dst, uint16((v>>move)&1))
        }
    }
    return dst
}