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

报告相同问题?

悬赏问题

  • ¥20 判断两个表是否完全相同
  • ¥20 工控机出现散热器转一下停一下这种情况,是什么原因造成的
  • ¥15 双显卡,启动docker容器报错。
  • ¥15 想编写一个期货跨期套利的程序
  • ¥15 一个线程在sleep的时候set一个信号会起作用吗
  • ¥50 如何利用matlab将现有的地基雷达回波数据调制为机载雷达回波数据
  • ¥100 需求高精度PT100设计电路和算法
  • ¥15 单片机配网,继电器开关,广播
  • ¥60 Qcustomplot绘制实时动态曲线
  • ¥20 运用matlab画x-y图