doudi5892 2018-07-04 18:04
浏览 144
已采纳

在Go中通过MQTT解除编组JSON对象

I am receiving sensor data over MQTT. I want to check if the temperature is over 20 degrees, and if it is, send a message.

var f MQTT.MessageHandler = func(client MQTT.Client, msg MQTT.Message) {
    type Data struct {
        Sensor string        `json:"sensor"`
        Temp []int           `json: "temperature"`
        Hum []int           `json: "humidity"`
    }
    var sensorData []Data
    message := ""
    err := json.Unmarshal(msg.Payload(), &sensorData)
    if err != nil {
        panic(err)
    }else {

    //access certain element in the Data struct
        for _, i := range sensorData {
            if i.Temp[2] > 20 { //where the temperature is stored
                fmt.Println("Temperature too high")
                message = "Temperature too high"
            }else{
                fmt.Println("Perfect temperature")
                message = "Perfect temperature"
        }
    }

    }

    // Publish further instructions to "sensor/instruction"
    token := client.Publish("sensor/instruction", 0, false, message)
    token.Wait()
}

Currently I am publishing two JSON objects to be received. I think part of the problem is distinguishing between the two objects. This is the error I am getting panic: json: cannot unmarshal object into Go value of type []main.Data. These are the JSON objects I am publishing to a topic:

{'sensor': 'DHT22', 'temperature': [22.7, 22.7, 22.8], 'humidity': [51.9, 52.0, 52.0]}
{'actuator': 'arduinoLED', 'blink': ['false', 'false', 'false']}

The msg.Payload() gives

{"sensor": "DHT22", "temperature": [22.9, 22.9, 22.9], "humidity": [50.9, 50.9, 50.9]}
{"actuator": "arduinoLED", "blink": ["false", "false", "false"]

These objects are published constantly in a loop. I want to unmarshal the first object and access a specific element.

  • 写回答

2条回答 默认 最新

  • duangong937906 2018-07-04 18:07
    关注

    Slice vs single object

    You are declaring a slice:

    var sensorData []Data
    

    But then your payload is not an array but rather only one object:

    {'sensor': 'DHT22', 'temperature': [22.7, 22.7, 22.8], 'humidity': [51.9, 52.0, 52.0]}
    

    So that error message is telling you it cannot unmarshal a single object as a slice.

    Try changing that declaration to:

    var sensorData Data
    

    Then, instead of iterating over it, you need to just check that one instance of the data.

    Additional mismatches between the payload and the struct type

    After that, you'll probably get another error since the temperature and humidity array seem to contain decimal numbers:

    `{'sensor': 'DHT22', 'temperature': [22.7, 22.7, 22.8], 'humidity': [51.9, 52.0, 52.0]`
    

    But you are declaring those as int slices in your code:

    Temp []int           `json: "temperature"`
    Hum []int           `json: "humidity"`
    

    So you'll need to change those to be []float64

    Differentiating the two different payloads

    About differentiating the two object types, it'd be better if you try to do that, but even if you don't, Go's json library will ignore problems if field names do not match, so what will happen is that when de-serializing your actuator payloads into Data, all fields will have their default values, but no error will be received.

    This check will probably throw a panic, cause the array will be empty in that case:

    if i.Temp[2] > 20
    

    One "hacky" way of solving this issue would be to only process the data if the sensor field is not a blank string.

    Assuming you always receive a sensor name in the sensor messages, the only case when that will result in an empty string is if you just processed one of the other messages.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥50 comsol稳态求解器 找不到解,奇异矩阵有1个空方程返回的解不收敛。没有返回所有参数步长;pid控制
  • ¥15 怎么让wx群机器人发送音乐
  • ¥15 fesafe材料库问题
  • ¥35 beats蓝牙耳机怎么查看日志
  • ¥15 Fluent齿轮搅油
  • ¥15 八爪鱼爬数据为什么自己停了
  • ¥15 交替优化波束形成和ris反射角使保密速率最大化
  • ¥15 树莓派与pix飞控通信
  • ¥15 自动转发微信群信息到另外一个微信群
  • ¥15 outlook无法配置成功