| 
									
										
										
										
											2017-11-10 18:44:02 +09:00
										 |  |  | import json | 
					
						
							|  |  |  | import boto3 | 
					
						
							| 
									
										
										
										
											2021-10-18 19:44:29 +00:00
										 |  |  | import sure  # noqa # pylint: disable=unused-import | 
					
						
							| 
									
										
										
										
											2020-10-06 07:54:49 +02:00
										 |  |  | import pytest | 
					
						
							| 
									
										
										
										
											2017-11-10 18:44:02 +09:00
										 |  |  | from botocore.exceptions import ClientError | 
					
						
							| 
									
										
										
										
											2022-02-10 08:02:40 -01:00
										 |  |  | 
 | 
					
						
							|  |  |  | import moto.iotdata.models | 
					
						
							|  |  |  | from moto import mock_iotdata, mock_iot, settings | 
					
						
							| 
									
										
										
										
											2022-08-13 09:49:43 +00:00
										 |  |  | from moto.core import DEFAULT_ACCOUNT_ID as ACCOUNT_ID | 
					
						
							| 
									
										
										
										
											2017-11-10 18:44:02 +09:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @mock_iot | 
					
						
							|  |  |  | @mock_iotdata | 
					
						
							|  |  |  | def test_basic(): | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     iot_client = boto3.client("iot", region_name="ap-northeast-1") | 
					
						
							|  |  |  |     client = boto3.client("iot-data", region_name="ap-northeast-1") | 
					
						
							|  |  |  |     name = "my-thing" | 
					
						
							| 
									
										
										
										
											2017-11-10 18:44:02 +09:00
										 |  |  |     raw_payload = b'{"state": {"desired": {"led": "on"}}}' | 
					
						
							|  |  |  |     iot_client.create_thing(thingName=name) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-06 07:54:49 +02:00
										 |  |  |     with pytest.raises(ClientError): | 
					
						
							| 
									
										
										
										
											2017-11-10 18:44:02 +09:00
										 |  |  |         client.get_thing_shadow(thingName=name) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     res = client.update_thing_shadow(thingName=name, payload=raw_payload) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     payload = json.loads(res["payload"].read()) | 
					
						
							| 
									
										
										
										
											2017-11-10 18:44:02 +09:00
										 |  |  |     expected_state = '{"desired": {"led": "on"}}' | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     payload.should.have.key("state").which.should.equal(json.loads(expected_state)) | 
					
						
							|  |  |  |     payload.should.have.key("metadata").which.should.have.key( | 
					
						
							|  |  |  |         "desired" | 
					
						
							|  |  |  |     ).which.should.have.key("led") | 
					
						
							|  |  |  |     payload.should.have.key("version").which.should.equal(1) | 
					
						
							|  |  |  |     payload.should.have.key("timestamp") | 
					
						
							| 
									
										
										
										
											2017-11-10 18:44:02 +09:00
										 |  |  | 
 | 
					
						
							|  |  |  |     res = client.get_thing_shadow(thingName=name) | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     payload = json.loads(res["payload"].read()) | 
					
						
							| 
									
										
										
										
											2017-11-10 18:44:02 +09:00
										 |  |  |     expected_state = b'{"desired": {"led": "on"}, "delta": {"led": "on"}}' | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     payload.should.have.key("state").which.should.equal(json.loads(expected_state)) | 
					
						
							|  |  |  |     payload.should.have.key("metadata").which.should.have.key( | 
					
						
							|  |  |  |         "desired" | 
					
						
							|  |  |  |     ).which.should.have.key("led") | 
					
						
							|  |  |  |     payload.should.have.key("version").which.should.equal(1) | 
					
						
							|  |  |  |     payload.should.have.key("timestamp") | 
					
						
							| 
									
										
										
										
											2017-11-10 18:44:02 +09:00
										 |  |  | 
 | 
					
						
							|  |  |  |     client.delete_thing_shadow(thingName=name) | 
					
						
							| 
									
										
										
										
											2020-10-06 07:54:49 +02:00
										 |  |  |     with pytest.raises(ClientError): | 
					
						
							| 
									
										
										
										
											2017-11-10 18:44:02 +09:00
										 |  |  |         client.get_thing_shadow(thingName=name) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @mock_iot | 
					
						
							|  |  |  | @mock_iotdata | 
					
						
							|  |  |  | def test_update(): | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     iot_client = boto3.client("iot", region_name="ap-northeast-1") | 
					
						
							|  |  |  |     client = boto3.client("iot-data", region_name="ap-northeast-1") | 
					
						
							|  |  |  |     name = "my-thing" | 
					
						
							| 
									
										
										
										
											2017-11-10 18:44:02 +09:00
										 |  |  |     raw_payload = b'{"state": {"desired": {"led": "on"}}}' | 
					
						
							|  |  |  |     iot_client.create_thing(thingName=name) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # first update | 
					
						
							|  |  |  |     res = client.update_thing_shadow(thingName=name, payload=raw_payload) | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     payload = json.loads(res["payload"].read()) | 
					
						
							| 
									
										
										
										
											2017-11-10 18:44:02 +09:00
										 |  |  |     expected_state = '{"desired": {"led": "on"}}' | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     payload.should.have.key("state").which.should.equal(json.loads(expected_state)) | 
					
						
							|  |  |  |     payload.should.have.key("metadata").which.should.have.key( | 
					
						
							|  |  |  |         "desired" | 
					
						
							|  |  |  |     ).which.should.have.key("led") | 
					
						
							|  |  |  |     payload.should.have.key("version").which.should.equal(1) | 
					
						
							|  |  |  |     payload.should.have.key("timestamp") | 
					
						
							| 
									
										
										
										
											2017-11-10 18:44:02 +09:00
										 |  |  | 
 | 
					
						
							|  |  |  |     res = client.get_thing_shadow(thingName=name) | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     payload = json.loads(res["payload"].read()) | 
					
						
							| 
									
										
										
										
											2017-11-10 18:44:02 +09:00
										 |  |  |     expected_state = b'{"desired": {"led": "on"}, "delta": {"led": "on"}}' | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     payload.should.have.key("state").which.should.equal(json.loads(expected_state)) | 
					
						
							|  |  |  |     payload.should.have.key("metadata").which.should.have.key( | 
					
						
							|  |  |  |         "desired" | 
					
						
							|  |  |  |     ).which.should.have.key("led") | 
					
						
							|  |  |  |     payload.should.have.key("version").which.should.equal(1) | 
					
						
							|  |  |  |     payload.should.have.key("timestamp") | 
					
						
							| 
									
										
										
										
											2017-11-10 18:44:02 +09:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # reporting new state | 
					
						
							|  |  |  |     new_payload = b'{"state": {"reported": {"led": "on"}}}' | 
					
						
							|  |  |  |     res = client.update_thing_shadow(thingName=name, payload=new_payload) | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     payload = json.loads(res["payload"].read()) | 
					
						
							| 
									
										
										
										
											2017-11-10 18:44:02 +09:00
										 |  |  |     expected_state = '{"reported": {"led": "on"}}' | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     payload.should.have.key("state").which.should.equal(json.loads(expected_state)) | 
					
						
							|  |  |  |     payload.should.have.key("metadata").which.should.have.key( | 
					
						
							|  |  |  |         "reported" | 
					
						
							|  |  |  |     ).which.should.have.key("led") | 
					
						
							|  |  |  |     payload.should.have.key("version").which.should.equal(2) | 
					
						
							|  |  |  |     payload.should.have.key("timestamp") | 
					
						
							| 
									
										
										
										
											2017-11-10 18:44:02 +09:00
										 |  |  | 
 | 
					
						
							|  |  |  |     res = client.get_thing_shadow(thingName=name) | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     payload = json.loads(res["payload"].read()) | 
					
						
							| 
									
										
										
										
											2017-11-10 18:44:02 +09:00
										 |  |  |     expected_state = b'{"desired": {"led": "on"}, "reported": {"led": "on"}}' | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     payload.should.have.key("state").which.should.equal(json.loads(expected_state)) | 
					
						
							|  |  |  |     payload.should.have.key("metadata").which.should.have.key( | 
					
						
							|  |  |  |         "desired" | 
					
						
							|  |  |  |     ).which.should.have.key("led") | 
					
						
							|  |  |  |     payload.should.have.key("version").which.should.equal(2) | 
					
						
							|  |  |  |     payload.should.have.key("timestamp") | 
					
						
							| 
									
										
										
										
											2017-11-25 02:22:53 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-26 13:28:56 +09:00
										 |  |  |     raw_payload = b'{"state": {"desired": {"led": "on"}}, "version": 1}' | 
					
						
							| 
									
										
										
										
											2020-10-06 07:54:49 +02:00
										 |  |  |     with pytest.raises(ClientError) as ex: | 
					
						
							| 
									
										
										
										
											2019-08-26 13:28:56 +09:00
										 |  |  |         client.update_thing_shadow(thingName=name, payload=raw_payload) | 
					
						
							| 
									
										
										
										
											2020-10-06 08:04:09 +02:00
										 |  |  |     ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(409) | 
					
						
							|  |  |  |     ex.value.response["Error"]["Message"].should.equal("Version conflict") | 
					
						
							| 
									
										
										
										
											2019-08-26 13:28:56 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-25 02:22:53 +09:00
										 |  |  | 
 | 
					
						
							|  |  |  | @mock_iotdata | 
					
						
							|  |  |  | def test_publish(): | 
					
						
							| 
									
										
										
										
											2022-02-10 08:02:40 -01:00
										 |  |  |     region_name = "ap-northeast-1" | 
					
						
							|  |  |  |     client = boto3.client("iot-data", region_name=region_name) | 
					
						
							| 
									
										
										
										
											2023-01-03 21:21:52 +00:00
										 |  |  |     client.publish(topic="test/topic1", qos=1, payload=b"pl1") | 
					
						
							|  |  |  |     client.publish(topic="test/topic2", qos=1, payload=b"pl2") | 
					
						
							|  |  |  |     client.publish(topic="test/topic3", qos=1, payload=b"pl3") | 
					
						
							| 
									
										
										
										
											2022-02-10 08:02:40 -01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if not settings.TEST_SERVER_MODE: | 
					
						
							| 
									
										
										
										
											2022-08-13 09:49:43 +00:00
										 |  |  |         mock_backend = moto.iotdata.models.iotdata_backends[ACCOUNT_ID][region_name] | 
					
						
							| 
									
										
										
										
											2023-01-03 21:21:52 +00:00
										 |  |  |         mock_backend.published_payloads.should.have.length_of(3) | 
					
						
							|  |  |  |         mock_backend.published_payloads.should.contain(("test/topic1", "pl1")) | 
					
						
							|  |  |  |         mock_backend.published_payloads.should.contain(("test/topic2", "pl2")) | 
					
						
							|  |  |  |         mock_backend.published_payloads.should.contain(("test/topic3", "pl3")) | 
					
						
							| 
									
										
										
										
											2021-06-30 00:15:45 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @mock_iot | 
					
						
							|  |  |  | @mock_iotdata | 
					
						
							|  |  |  | def test_delete_field_from_device_shadow(): | 
					
						
							|  |  |  |     test_thing_name = "TestThing" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     iot_raw_client = boto3.client("iot", region_name="eu-central-1") | 
					
						
							|  |  |  |     iot_raw_client.create_thing(thingName=test_thing_name) | 
					
						
							|  |  |  |     iot = boto3.client("iot-data", region_name="eu-central-1") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     iot.update_thing_shadow( | 
					
						
							|  |  |  |         thingName=test_thing_name, | 
					
						
							|  |  |  |         payload=json.dumps({"state": {"desired": {"state1": 1, "state2": 2}}}), | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     response = json.loads( | 
					
						
							|  |  |  |         iot.get_thing_shadow(thingName=test_thing_name)["payload"].read() | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     assert len(response["state"]["desired"]) == 2 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     iot.update_thing_shadow( | 
					
						
							|  |  |  |         thingName=test_thing_name, | 
					
						
							|  |  |  |         payload=json.dumps({"state": {"desired": {"state1": None}}}), | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     response = json.loads( | 
					
						
							|  |  |  |         iot.get_thing_shadow(thingName=test_thing_name)["payload"].read() | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     assert len(response["state"]["desired"]) == 1 | 
					
						
							|  |  |  |     assert "state2" in response["state"]["desired"] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     iot.update_thing_shadow( | 
					
						
							|  |  |  |         thingName=test_thing_name, | 
					
						
							|  |  |  |         payload=json.dumps({"state": {"desired": {"state2": None}}}), | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     response = json.loads( | 
					
						
							|  |  |  |         iot.get_thing_shadow(thingName=test_thing_name)["payload"].read() | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     assert "desired" not in response["state"] |