shadowとwillとretainを活用してAWS IoT CoreとPubSubする⑩mosquittoでshadow update

## この記事について  

[shadowとwillとretainを活用してAWS IoT CoreとPubSubする⑨mosquittoでpubsub](https://qiita.com/Saito5656/items/1398200115bb9c47116a)で行ったmosquittoでのmessage pubsubに続いてshadowをupdate/getします。

今回もラズパイに接続された仮想device_0の正常稼働とdevice停止をAWS IoTのdevice shadowに反映させます。

<br>

<img width= 700 src = https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/565396/6a3df83a-84fe-e120-7f16-772ef8c039e5.png>


## shadowのtopic  

[paho-mqtt]()と[AWS IoT Device SDK for Python]()で扱ったと同じく、/getと/updateの操作をします。

### shadow update  

/update にdesiredとreportedのstateをラズパイからpubすると、AWS IoT Coreより各項目のレスポンスがtopicにpubされます。  

| 名前                | アクション   | MQTT トピック                                                      |
|-------------------|---------|----------------------------------------------------------------|
| /update           | **発行**      | $aws/things/MQTTServer1/shadow/name/device_0/update            |
| /update/delta     | サブスクライブ | $aws/things/MQTTServer1/shadow/name/device_0/update/delta      |
| /update/accepted  | サブスクライブ | $aws/things/MQTTServer1/shadow/name/device_0/update/accepted   |
| /update/documents | サブスクライブ | $aws/things/MQTTServer1/shadow/name/device_0/update/documents  |
| /update/rejected  | サブスクライブ | $aws/things/MQTTServer1/shadow/name/device_0/update/rejected   |  

### shadow get  

/get に空のtopicをラズパイからpubすると、AWS IoT Coreより各項目のレスポンスがtopicにpubされます。  

| 名前                | アクション   | MQTT トピック                                                      |
|-------------------|---------|----------------------------------------------------------------|
| /get              | **発行**      | $aws/things/MQTTServer1/shadow/name/device_0/get               |
| /get/accepted     | サブスクライブ | $aws/things/MQTTServer1/shadow/name/device_0/get/accepted      |
| /get/rejected     | サブスクライブ | $aws/things/MQTTServer1/shadow/name/device_0/get/rejected      |  

### /etc/mosquitto/conf.d/bridge.confにtopic追加

shadow update/getに使うtopicを[/etc/mosquitto/conf.d/bridge.conf](https://qiita.com/Saito5656/items/1398200115bb9c47116a#bridge)に追加します。

```sh:/etc/mosquitto/conf.d/bridge.conf
#以下を追加
topic $aws/things/MQTTServer1/shadow/name/# both 1
```
  
## shadow update  

今まで同様にstate、payload、topicを準備します。pubの前にコマンドラインから入力します。

先にsubscriberを立ち上げておきます。topic一つずつ確認します。
payloadに改行が入るのでsub側のスクリプトを対応させておきます。
```sh:sub
THING_NAME=$(grep 'THING_NAME' ./parameters.conf | awk -F'=' '{print $2}' | tr -d '\r\n')
PROJECT_NAME=$(grep 'PROJECT_NAME' ./parameters.conf | awk -F'=' '{print $2}' | tr -d '\r\n')
password=$(grep 'MOS_PW' ./parameters.conf | awk -F'=' '{print $2}' | tr -d '\r\n')
username=$(grep 'MOS_USR' ./parameters.conf | awk -F'=' '{print $2}' | tr -d '\r\n')

#topics
topic="\$aws/things/${THING_NAME}/shadow/name/+/update/accepted"
#topic="\$aws/things/${THING_NAME}/shadow/name/+/update/rejected"
#topic="\$aws/things/${THING_NAME}/shadow/name/+/update/documents"
#topic="\$aws/things/${THING_NAME}/shadow/name/+/update/delta"
echo $topic

# Subscribe to the MQTT topic and decode the payload
mosquitto_sub -h 127.0.0.1 -u "${username}" -P "${password}" -t "$topic" -v | while read -r topic payload; do
  echo "Received message on topic: $topic"
  echo "Payload: $payload"
  
  # Decode the payload (assuming JSON)
  decoded_payload=$(echo "$payload" | jq .)
  echo "Decoded Payload: $decoded_payload"
done
```

stateは今まで同様に行きますヨシッ👉

```sh:pub
desired_state="ヨシッ👉"
state_ok="ヨシッ👉"
state_ng="ダメ🙅"
state=$state_ok

payload="{\"state\": {\"desired\": {\"device_no\": \"device_0\",\"state\": \"${desired_state}\"},\"reported\": {\"device_no\": \"device_0\",\"state\": \"${state}\"}}}"
echo $payload

topic="\$aws/things/${THING_NAME}/shadow/name/device_0/update"
echo $topic
```

pubします。


```sh:pub
mosquitto_pub -h 127.0.0.1 -u ${username} -P ${password} -t $topic -m "$payload"
```

### OK state  

各topicへ返されたレスポンスです。
成功しているので/rejectedにはレスポンスなし、OKなので/deltaへもレスポンスがpubされてません。

```sh:/update/accepted
Received message on topic: $aws/things/MQTTServer1/shadow/name/device_0/update/accepted
Payload: {"state":{"desired":{"device_no":"device_0","state":"ヨシッ\uD83D\uDC49"},"reported":{"device_no":"device_0","state":"ヨシッ\uD83D\uDC49"}},"metadata":{"desired":{"device_no":{"timestamp":1720176208},"state":{"timestamp":1720176208}},"reported":{"device_no":{"timestamp":1720176208},"state":{"timestamp":1720176208}}},"version":643,"timestamp":1720176208}
Decoded Payload: {
  "state": {
    "desired": {
      "device_no": "device_0",
      "state": "ヨシッ👉"
    },
    "reported": {
      "device_no": "device_0",
      "state": "ヨシッ👉"
    }
  },
  "metadata": {
    "desired": {
      "device_no": {
        "timestamp": 1720176208
      },
      "state": {
        "timestamp": 1720176208
      }
    },
    "reported": {
      "device_no": {
        "timestamp": 1720176208
      },
      "state": {
        "timestamp": 1720176208
      }
    }
  },
  "version": 643,
  "timestamp": 1720176208
}
```

```sh: /update/documents
Received message on topic: $aws/things/MQTTServer1/shadow/name/device_0/update/documents
Payload: {"previous":{"state":{"desired":{"device_no":"device_0","state":"ヨシッ\uD83D\uDC49"},"reported":{"device_no":"device_0","state":"ヨシッ\uD83D\uDC49"}},"metadata":{"desired":{"device_no":{"timestamp":1720176989},"state":{"timestamp":1720176989}},"reported":{"device_no":{"timestamp":1720176989},"state":{"timestamp":1720176989}}},"version":644},"current":{"state":{"desired":{"device_no":"device_0","state":" ヨシッ\uD83D\uDC49"},"reported":{"device_no":"device_0","state":"ヨシッ\uD83D\uDC49"}},"metadata":{"desired":{"device_no":{"timestamp":1720177007},"state":{"timestamp":1720177007}},"reported":{"device_no":{"timestamp":1720177007},"state":{"timestamp":1720177007}}},"version":645},"timestamp":1720177007}
Decoded Payload: {
  "previous": {
    "state": {
      "desired": {
        "device_no": "device_0",
        "state": "ヨシッ👉"
      },
      "reported": {
        "device_no": "device_0",
        "state": "ヨシッ👉"
      }
    },
    "metadata": {
      "desired": {
        "device_no": {
          "timestamp": 1720176989
        },
        "state": {
          "timestamp": 1720176989
        }
      },
      "reported": {
        "device_no": {
          "timestamp": 1720176989
        },
        "state": {
          "timestamp": 1720176989
        }
      }
    },
    "version": 644
  },
  "current": {
    "state": {
      "desired": {
        "device_no": "device_0",
        "state": "ヨシッ👉"
      },
      "reported": {
        "device_no": "device_0",
        "state": "ヨシッ👉"
      }
    },
    "metadata": {
      "desired": {
        "device_no": {
          "timestamp": 1720177007
        },
        "state": {
          "timestamp": 1720177007
        }
      },
      "reported": {
        "device_no": {
          "timestamp": 1720177007
        },
        "state": {
          "timestamp": 1720177007
        }
      }
    },
    "version": 645
  },
  "timestamp": 1720177007
}
```

### NG state  

次にNG stateを見ます。

```sh:pub state
desired_state="ヨシッ👉"
state_ok="ヨシッ👉"
state_ng="ダメ🙅"
state=$state_ng
```

pubします。


```sh:pub
mosquitto_pub -h 127.0.0.1 -u ${username} -P ${password} -t $topic -m "$payload"
```

/deltaへのレスポンスが確認できました。

```sh:/update/delta
Received message on topic: $aws/things/MQTTServer1/shadow/name/device_0/update/delta
Payload: {"version":647,"timestamp":1720177393,"state":{"state":"ヨシッ\uD83D\uDC49"},"metadata":{"state":{"timestamp":1720177393}}}
Decoded Payload: {
  "version": 647,
  "timestamp": 1720177393,
  "state": {
    "state": "ヨシッ👉"
  },
  "metadata": {
    "state": {
      "timestamp": 1720177393
    }
  }
}
```

## shadow get  

こちらは/getに対して/get/acceptedと/get/rejectedのみです。/update同様にpubが成功していると/rejectedはpubされません。

先にsubscriberを立ち上げておきます。
```sh:sub
THING_NAME=$(grep 'THING_NAME' ./parameters.conf | awk -F'=' '{print $2}' | tr -d '\r\n')
PROJECT_NAME=$(grep 'PROJECT_NAME' ./parameters.conf | awk -F'=' '{print $2}' | tr -d '\r\n')
password=$(grep 'MOS_PW' ./parameters.conf | awk -F'=' '{print $2}' | tr -d '\r\n')
username=$(grep 'MOS_USR' ./parameters.conf | awk -F'=' '{print $2}' | tr -d '\r\n')

#topics
topic="\$aws/things/${THING_NAME}/shadow/name/+/get/accepted"
#topic="\$aws/things/${THING_NAME}/shadow/name/+/get/rejected"
echo $topic

# Subscribe to the MQTT topic and decode the payload
mosquitto_sub -h 127.0.0.1 -u "${username}" -P "${password}" -t "$topic" -v | while read -r topic payload; do
  echo "Received message on topic: $topic"
  echo "Payload: $payload"
  
  # Decode the payload (assuming JSON)
  decoded_payload=$(echo "$payload" | jq .)
  echo "Decoded Payload: $decoded_payload"
done
```

pubします。
```sh:pub
THING_NAME=$(grep 'THING_NAME' ./parameters.conf | awk -F'=' '{print $2}' | tr -d '\r\n')
PROJECT_NAME=$(grep 'PROJECT_NAME' ./parameters.conf | awk -F'=' '{print $2}' | tr -d '\r\n')
password=$(grep 'MOS_PW' ./parameters.conf | awk -F'=' '{print $2}' | tr -d '\r\n')
username=$(grep 'MOS_USR' ./parameters.conf | awk -F'=' '{print $2}' | tr -d '\r\n')

payload=""
echo $payload

topic="\$aws/things/${THING_NAME}/shadow/name/device_0/get"
echo $topic

mosquitto_pub -h 127.0.0.1 -u ${username} -P ${password} -t $topic -m "$payload"
```

### OK state  

```sh:/get/accepted：OK
Received message on topic: $aws/things/MQTTServer1/shadow/name/device_0/get/accepted
Payload: {"state":{"desired":{"device_no":"device_0","state":"ヨシッ\uD83D\uDC49"},"reported":{"device_no":"device_0","state":"ヨシッ\uD83D\uDC49"}},"metadata":{"desired":{"device_no":{"timestamp":1720177763},"state":{"timestamp":1720177763}},"reported":{"device_no":{"timestamp":1720177763},"state":{"timestamp":1720177763}}},"version":648,"timestamp":1720177774}
Decoded Payload: {
  "state": {
    "desired": {
      "device_no": "device_0",
      "state": "ヨシッ👉"
    },
    "reported": {
      "device_no": "device_0",
      "state": "ヨシッ👉"
    }
  },
  "metadata": {
    "desired": {
      "device_no": {
        "timestamp": 1720177763
      },
      "state": {
        "timestamp": 1720177763
      }
    },
    "reported": {
      "device_no": {
        "timestamp": 1720177763
      },
      "state": {
        "timestamp": 1720177763
      }
    }
  },
  "version": 648,
  "timestamp": 1720177774
}
```

### NG state  

deltaが確認できます。

```sh:/get/accepted：NG
Received message on topic: $aws/things/MQTTServer1/shadow/name/device_0/get/accepted
Payload: {"state":{"desired":{"device_no":"device_0","state":"ヨシッ\uD83D\uDC49"},"reported":{"device_no":"device_0","state":"ダメ\uD83D\uDE45"},"delta":{"state":"ヨシッ\uD83D\uDC49"}},"metadata":{"desired":{"device_no":{"timestamp":1720177393},"state":{"timestamp":1720177393}},"reported":{"device_no":{"timestamp":1720177393},"state":{"timestamp":1720177393}}},"version":647,"timestamp":1720177706}
Decoded Payload: {
  "state": {
    "desired": {
      "device_no": "device_0",
      "state": "ヨシッ👉"
    },
    "reported": {
      "device_no": "device_0",
      "state": "ダメ🙅"
    },
    "delta": {
      "state": "ヨシッ👉"
    }
  },
  "metadata": {
    "desired": {
      "device_no": {
        "timestamp": 1720177393
      },
      "state": {
        "timestamp": 1720177393
      }
    },
    "reported": {
      "device_no": {
        "timestamp": 1720177393
      },
      "state": {
        "timestamp": 1720177393
      }
    }
  },
  "version": 647,
  "timestamp": 1720177706
}
```


## 次回  
いよいよシリーズ最終回です。
[shadowとwillとretainを活用してAWS IoT CoreとPubSubする⑪mosquittoでretainとwill](https://qiita.com/Saito5656/items/aa99f6a026c93235c776)