def setUp(self):
        self.zmq = ZMQConnection(config.gws_zmq_endpoint)
        self.zmq.accept(lambda m: "gateway_id" in m)
        self.zmq.open()

        self.ws = websocket.WebSocket()
        self.ws.connect(config.gws_ws_uri)

        registerGateway(self, self.ws, config.gateway_id)

        event = self.zmq.pop_data()
        self.assertEqual("on-connected", event["event"])
        self.assertEqual(config.gateway_id, event["gateway_id"])
Ejemplo n.º 2
0
 def setUp(self):
     self.zmq = ZMQConnection(config.gws_zmq_endpoint)
     self.zmq.accept(lambda m: "gateway_id" in m)
     self.zmq.open()
Ejemplo n.º 3
0
class TestRegister(unittest.TestCase):
    def setUp(self):
        self.zmq = ZMQConnection(config.gws_zmq_endpoint)
        self.zmq.accept(lambda m: "gateway_id" in m)
        self.zmq.open()

    def tearDown(self):
        self.zmq.close()

    """
	Register the gateway with a valid registration message. Expect successful
	registration and open connection.
	"""

    def test1_register_success(self):
        ws = websocket.WebSocket()
        ws.connect(config.gws_ws_uri)

        msg = json.dumps({
            "gateway_id": config.gateway_id,
            "ip_address": "192.168.1.1",
            "message_type": "gateway_register",
            "version": "v1.0"
        })

        ws.send(msg)
        msg = json.loads(ws.recv())

        self.assertEqual("gateway_accepted", msg["message_type"])
        assureNotClosed(self, ws)

        event = self.zmq.pop_data()
        self.assertEqual("on-connected", event["event"])
        self.assertEqual(config.gateway_id, event["gateway_id"])

        ws.close()

        event = self.zmq.pop_data()
        self.assertEqual("on-disconnected", event["event"])
        self.assertEqual(config.gateway_id, event["gateway_id"])

    """
	Register the gateway with invalid id and expect closed connection.
	"""

    def test2_register_fail_bad_id(self):
        ws = websocket.WebSocket()
        ws.connect(config.gws_ws_uri)

        msg = json.dumps({
            "gateway_id": "123",
            "ip_address": "192.168.1.1",
            "message_type": "gateway_register",
            "version": "v1.0"
        })

        ws.send(msg)
        assureIsClosed(self, ws)

    """
	Send invalid message before registration and expect closed connection.
	"""

    def test3_send_random_data_without_registration(self):
        ws = websocket.WebSocket()
        ws.connect(config.gws_ws_uri)

        ws.send("hello")

        assureIsClosed(self, ws)
        ws.close()

    """
	Register the same gateway twice without closing first connection. Expect,
	that the second registration closes the first connection.
	"""

    def test4_register_success_repeatedly(self):
        ws0 = websocket.WebSocket()
        ws1 = websocket.WebSocket()

        msg = json.dumps({
            "gateway_id": config.gateway_id,
            "ip_address": "192.168.1.1",
            "message_type": "gateway_register",
            "version": "v1.0"
        })

        ws0.connect(config.gws_ws_uri)
        ws0.send(msg)
        response = json.loads(ws0.recv())

        self.assertEqual("gateway_accepted", response["message_type"])
        assureNotClosed(self, ws0)

        event = self.zmq.pop_data()
        self.assertEqual("on-connected", event["event"])
        self.assertEqual(config.gateway_id, event["gateway_id"])

        ws1.connect(config.gws_ws_uri)
        ws1.send(msg)
        response = json.loads(ws1.recv())

        self.assertEqual("gateway_accepted", response["message_type"])
        assureIsClosed(self, ws0)
        assureNotClosed(self, ws1)

        event = self.zmq.pop_data()
        self.assertEqual("on-reconnected", event["event"])
        self.assertEqual(config.gateway_id, event["gateway_id"])

        ws1.close()

        event = self.zmq.pop_data()
        self.assertEqual("on-disconnected", event["event"])
        self.assertEqual(config.gateway_id, event["gateway_id"])
class TestControlFrames(unittest.TestCase):
    def setUp(self):
        self.zmq = ZMQConnection(config.gws_zmq_endpoint)
        self.zmq.accept(lambda m: "gateway_id" in m)
        self.zmq.open()

        self.ws = websocket.WebSocket()
        self.ws.connect(config.gws_ws_uri)

        registerGateway(self, self.ws, config.gateway_id)

        event = self.zmq.pop_data()
        self.assertEqual("on-connected", event["event"])
        self.assertEqual(config.gateway_id, event["gateway_id"])

    def tearDown(self):
        self.ws.close()

        try:
            event = self.zmq.pop_data()
            self.assertEqual("on-disconnected", event["event"])
            self.assertEqual(config.gateway_id, event["gateway_id"])
        finally:
            self.zmq.close()

    """
	Opcode PONG is not processed on server and any such frame should lead
	to connection close. This should happen for any other unhandled control
	frame.
	"""

    def test1_unhandled_control(self):
        self.ws.pong("short but should close connection")
        assureIsClosed(self, self.ws)

    """
	Opcode CONT is not processed by server. It just leads to closing the
	connection. There is no way how to determine the reason from the server.
	"""

    def test2_unhandled_data(self):
        self.ws.send("should close connection due to opcode",
                     opcode=websocket.ABNF.OPCODE_CONT)
        assureIsClosed(self, self.ws)

    """
	Control opcodes must be max 125 B long. All such frames must be ignored
	on server and such connection would be closed.
	"""

    def test3_too_long_frame(self):
        self.ws.ping("X" * 1024)
        assureIsClosed(self, self.ws)

    """
	Valid PING frame should lead to an appropriate PONG response.
	"""

    def test4_ping_pong(self):
        self.ws.ping("testing connection")
        frame = self.ws.recv_frame()

        self.assertEqual(websocket.ABNF.OPCODE_PONG, frame.opcode)
        self.assertEqual("testing connection", str(frame.data, "utf-8"))
Ejemplo n.º 5
0
class TestNewDeviceGroup(unittest.TestCase):
    def setUp(self):
        self.zmq = ZMQConnection(config.gws_zmq_endpoint)
        self.zmq.accept(lambda m: "gateway_id" in m)
        self.zmq.open()

        self.ws = websocket.WebSocket()
        self.ws.connect(config.gws_ws_uri)

        registerGateway(self, self.ws, config.gateway_id)

        event = self.zmq.pop_data()
        self.assertEqual("on-connected", event["event"])
        self.assertEqual(config.gateway_id, event["gateway_id"])

    def tearDown(self):
        self.ws.close()

        try:
            event = self.zmq.pop_data()
            self.assertEqual("on-disconnected", event["event"])
            self.assertEqual(config.gateway_id, event["gateway_id"])
        finally:
            self.zmq.close()

    """
	Register device group with valid types. It should be accepted without any issue.
	"""

    def test1_new_device_group_success(self):
        id = str(uuid.uuid4())

        msg = json.dumps({
            "message_type":
            "new_device_group_request",
            "id":
            id,
            "group_name":
            "BeeeOn Group",
            "vendor":
            "BeeeOn",
            "devices": [{
                "device_id":
                "0xa100998877665511",
                "product_name":
                "Internal Pressure v1.0",
                "refresh_time":
                30,
                "module_types": [{
                    "type": "pressure",
                    "attributes": [{
                        "attribute": "inner"
                    }]
                }]
            }, {
                "device_id":
                "0xa100998877665522",
                "product_name":
                "Temperature Humidity v1.0",
                "refresh_time":
                30,
                "module_types": [{
                    "type": "temperature",
                    "attributes": [{
                        "attribute": "inner"
                    }]
                }, {
                    "type": "temperature",
                    "attributes": [{
                        "attribute": "outer"
                    }]
                }, {
                    "type": "humidity",
                    "attributes": [{
                        "attribute": "inner"
                    }]
                }, {
                    "type": "battery",
                    "attributes": []
                }, {
                    "type": "rssi",
                    "attributes": []
                }]
            }]
        })

        self.ws.send(msg)
        msg = json.loads(self.ws.recv())

        self.assertEqual("generic_response", msg["message_type"])
        self.assertEqual(id, msg["id"])
        self.assertEqual(1, msg["status"])
        assureNotClosed(self, self.ws)

        event = self.zmq.pop_data()
        self.assertEqual("on-new-device", event["event"])
        self.assertEqual("0xa100998877665511", event["device_id"])
        self.assertEqual(config.gateway_id, event["gateway_id"])

        event = self.zmq.pop_data()
        self.assertEqual("on-new-device", event["event"])
        self.assertEqual("0xa100998877665522", event["device_id"])
        self.assertEqual(config.gateway_id, event["gateway_id"])

    """
	Register device that does not match to any types known on the
	server. The server must fail to register this devices and provide
	an appropriate response. The response has to have same id as the
	request and the status of response has to be 2 (failure).
	"""

    def test2_new_device_group_fail_invalid_product(self):
        id = str(uuid.uuid4())

        msg = json.dumps({
            "message_type":
            "new_device_group_request",
            "id":
            id,
            "group_name":
            "Awesome Group",
            "vendor":
            "Good Company",
            "devices": [{
                "device_id":
                "0xa100998877665533",
                "product_name":
                "Nice Product",
                "refresh_time":
                30,
                "module_types": [{
                    "type": "pressure",
                    "attributes": [{
                        "attribute": "inner"
                    }]
                }]
            }]
        })

        self.ws.send(msg)
        msg = json.loads(self.ws.recv())

        self.assertEqual("generic_response", msg["message_type"])
        self.assertEqual(id, msg["id"])
        self.assertEqual(2, msg["status"])
        assureNotClosed(self, self.ws)

        event = self.zmq.pop_data()
        self.assertEqual("on-refused-new-device", event["event"])
        self.assertEqual("0xa100998877665533", event["device_id"])
        self.assertEqual(config.gateway_id, event["gateway_id"])

    """
	Server must deny accepting of device with an invalid device ID.
	The type of the device would be valid and acceptable otherwise.
	"""

    def test3_new_device_group_disconnect_invalid_id(self):
        id = str(uuid.uuid4())

        msg = json.dumps({
            "message_type":
            "new_device_group_request",
            "id":
            id,
            "group_name":
            "Group",
            "vendor":
            "BeeeOn",
            "devices": [{
                "device_id":
                "123",
                "product_name":
                "Internal Pressure v1.0",
                "refresh_time":
                30,
                "module_types": [{
                    "type": "pressure",
                    "attributes": [{
                        "attribute": "inner"
                    }]
                }]
            }]
        })

        self.ws.send(msg)
        assureIsClosed(self, self.ws)

    """
	Register device whose module type 'humidity' does not match with the
	known module 'pressure' for that device type on the server. The server
	must fail to register this devices and provide an appropriate response.
	The response has to have same id as the request and the status of response
	has to be 2 (failure).
	"""

    def test4_new_device_group_fail_invalid_module(self):
        id = str(uuid.uuid4())

        msg = json.dumps({
            "message_type":
            "new_device_group_request",
            "id":
            id,
            "group_name":
            "Group",
            "vendor":
            "BeeeOn",
            "devices": [{
                "device_id":
                "0xa100998877665544",
                "product_name":
                "Internal Pressure v1.0",
                "refresh_time":
                30,
                "module_types": [{
                    "type": "humidity",
                    "attributes": [{
                        "attribute": "inner"
                    }]
                }]
            }]
        })

        self.ws.send(msg)
        msg = json.loads(self.ws.recv())

        self.assertEqual("generic_response", msg["message_type"])
        self.assertEqual(id, msg["id"])
        self.assertEqual(2, msg["status"])
        assureNotClosed(self, self.ws)

        event = self.zmq.pop_data()
        self.assertEqual("on-refused-new-device", event["event"])
        self.assertEqual("0xa100998877665544", event["device_id"])
        self.assertEqual(config.gateway_id, event["gateway_id"])

    """
	Register group of 2 devices. The first device however contains a module
	that is not known to the server. The server must fail to register these devices
	and provide an appropriate response. The response has to have same id as the
	request and the status of response has to be 2 (failure).
	"""

    def test5_new_device_group_fail_too_many_modules(self):
        id = str(uuid.uuid4())

        msg = json.dumps({
            "message_type":
            "new_device_group_request",
            "id":
            id,
            "group_name":
            "BeeeOn Group",
            "vendor":
            "BeeeOn",
            "devices": [{
                "device_id":
                "0xa100998877665555",
                "product_name":
                "Internal Pressure v1.0",
                "refresh_time":
                30,
                "module_types": [{
                    "type": "pressure",
                    "attributes": [{
                        "attribute": "inner"
                    }]
                }, {
                    "type": "humidity",
                    "attributes": []
                }]
            }, {
                "device_id":
                "0xa100998877665566",
                "product_name":
                "Temperature Humidity v1.0",
                "refresh_time":
                30,
                "module_types": [{
                    "type": "temperature",
                    "attributes": [{
                        "attribute": "inner"
                    }]
                }, {
                    "type": "temperature",
                    "attributes": [{
                        "attribute": "outer"
                    }]
                }, {
                    "type": "humidity",
                    "attributes": [{
                        "attribute": "inner"
                    }]
                }, {
                    "type": "battery",
                    "attributes": []
                }, {
                    "type": "rssi",
                    "attributes": []
                }]
            }]
        })

        self.ws.send(msg)
        msg = json.loads(self.ws.recv())

        self.assertEqual("generic_response", msg["message_type"])
        self.assertEqual(id, msg["id"])
        self.assertEqual(2, msg["status"])
        assureNotClosed(self, self.ws)

        event = self.zmq.pop_data()
        self.assertEqual("on-refused-new-device", event["event"])
        self.assertEqual("0xa100998877665555", event["device_id"])
        self.assertEqual(config.gateway_id, event["gateway_id"])

        event = self.zmq.pop_data()
        self.assertEqual("on-refused-new-device", event["event"])
        self.assertEqual("0xa100998877665566", event["device_id"])
        self.assertEqual(config.gateway_id, event["gateway_id"])
Ejemplo n.º 6
0
class TestLastValue(unittest.TestCase):
    def setUp(self):
        self.zmq = ZMQConnection(config.gws_zmq_endpoint)
        self.zmq.accept(lambda m: "gateway_id" in m)
        self.zmq.open()

        self.ws = websocket.WebSocket()
        self.ws.connect(config.gws_ws_uri)

        registerGateway(self, self.ws, config.gateway_id)

        event = self.zmq.pop_data()
        self.assertEqual("on-connected", event["event"])
        self.assertEqual(config.gateway_id, event["gateway_id"])

    def tearDown(self):
        self.ws.close()

        try:
            event = self.zmq.pop_data()
            self.assertEqual("on-disconnected", event["event"])
            self.assertEqual(config.gateway_id, event["gateway_id"])
        finally:
            self.zmq.close()

    """
	Obtain last value of the device's 0xa32d27aa5e94ecfd (11758097814818974973)
	module 0. The last value of such sensor is 20.0 (see testing-data.sql).
	"""

    def test1_last_value_success(self):
        id = str(uuid.uuid4())

        msg = json.dumps({
            "message_type": "last_value_request",
            "id": id,
            "device_id": "0xa32d27aa5e94ecfd",
            "module_id": 0
        })

        self.ws.send(msg)
        msg = json.loads(self.ws.recv())

        self.assertEqual("last_value_response", msg["message_type"])
        self.assertEqual(id, msg["id"])
        self.assertEqual(1, msg["status"])
        self.assertEqual(True, msg["valid"])
        self.assertEqual(20.0, msg["value"])
        assureNotClosed(self, self.ws)

    """
	Obtain last value of the device's 0xa32d27aa5e94ecfd (11758097814818974973)
	module 1. There is no last value of that module, expect an error response.
	"""

    def test2_last_value_fail(self):
        id = str(uuid.uuid4())

        msg = json.dumps({
            "message_type": "last_value_request",
            "id": id,
            "device_id": "0xa32d27aa5e94ecfd",
            "module_id": 1
        })

        self.ws.send(msg)
        msg = json.loads(self.ws.recv())

        self.assertEqual("last_value_response", msg["message_type"])
        self.assertEqual(id, msg["id"])
        self.assertEqual(2, msg["status"])
        assureNotClosed(self, self.ws)
class TestSensorData(unittest.TestCase):
    def setUp(self):
        self.zmq = ZMQConnection(config.gws_zmq_endpoint)
        self.zmq.accept(lambda m: "gateway_id" in m)
        self.zmq.open()

        self.ws = websocket.WebSocket()
        self.ws.connect(config.gws_ws_uri)

        registerGateway(self, self.ws, config.gateway_id)

        event = self.zmq.pop_data()
        self.assertEqual("on-connected", event["event"])
        self.assertEqual(config.gateway_id, event["gateway_id"])

    def tearDown(self):
        self.ws.close()

        try:
            event = self.zmq.pop_data()
            self.assertEqual("on-disconnected", event["event"])
            self.assertEqual(config.gateway_id, event["gateway_id"])
        finally:
            self.zmq.close()

    """
	Server just confirms that it received valid sensor data message,
	but nothing more can be determined from its response
	"""

    def test1_export_successful(self):
        id = str(uuid.uuid4())
        timestamp = int(time.time() * 1000000)

        msg = json.dumps({
            "message_type":
            "sensor_data_export",
            "id":
            id,
            "data": [{
                "device_id":
                "0xa32d27aa5e94ecfd",
                "timestamp":
                timestamp,
                "values": [{
                    "module_id": "0",
                    "value": 30.0,
                    "valid": "true"
                }, {
                    "module_id": "1",
                    "valid": "false"
                }, {
                    "module_id": "2",
                    "value": 60.0,
                    "valid": "true"
                }]
            }]
        })

        self.ws.send(msg)
        msg = json.loads(self.ws.recv())

        self.assertEqual("sensor_data_confirm", msg["message_type"])
        self.assertEqual(id, msg["id"])
        assureNotClosed(self, self.ws)

        event = self.zmq.pop_data()
        self.assertEqual("on-sensor-data", event["event"])
        self.assertEqual(config.gateway_id, event["gateway_id"])
        self.assertEqual("0xa32d27aa5e94ecfd", event["device_id"])
        self.assertEqual(timestamp, event["timestamp"])
        self.assertEqual(30, event["data"]["0"])
        self.assertIsNone(event["data"]["1"])
        self.assertEqual(60, event["data"]["2"])

    """
	Even if we send an invalid export message, we get just "confirm" response.
	This test is semi-automatic, it requires to check the server log.
	"""

    def test2_export_fails_due_to_unexisting_device(self):
        id = str(uuid.uuid4())

        msg = json.dumps({
            "message_type":
            "sensor_data_export",
            "id":
            id,
            "data": [{
                "device_id":
                "0xa32d275555555555",
                "timestamp":
                0,
                "values": [{
                    "module_id": "5",
                    "value": -1230.0,
                    "valid": "true"
                }, {
                    "module_id": "22",
                    "valid": "false"
                }, {
                    "module_id": "89",
                    "value": 3460.132,
                    "valid": "true"
                }]
            }]
        })

        self.ws.send(msg)
        msg = json.loads(self.ws.recv())

        self.assertEqual("sensor_data_confirm", msg["message_type"])
        self.assertEqual(id, msg["id"])
        assureNotClosed(self, self.ws)

    """
	Send conflicting data (same timestamp). We cannot test anything there
	automatically. But it allows at least a semi-automatic test.
	"""

    def test3_export_fails_due_to_conflicts(self):
        id = str(uuid.uuid4())
        timestamp = int(time.time() * 1000000)

        msg = json.dumps({
            "message_type":
            "sensor_data_export",
            "id":
            id,
            "data": [{
                "device_id":
                "0xa32d27aa5e94ecfd",
                "timestamp":
                timestamp,
                "values": [{
                    "module_id": "0",
                    "value": 30.0,
                    "valid": "true"
                }, {
                    "module_id": "0",
                    "valid": "false"
                }]
            }]
        })

        self.ws.send(msg)
        msg = json.loads(self.ws.recv())

        self.assertEqual("sensor_data_confirm", msg["message_type"])
        self.assertEqual(id, msg["id"])
        assureNotClosed(self, self.ws)

        event = self.zmq.pop_data()
        self.assertEqual("on-sensor-data", event["event"])
        self.assertEqual(config.gateway_id, event["gateway_id"])
        self.assertEqual("0xa32d27aa5e94ecfd", event["device_id"])
        self.assertEqual(timestamp, event["timestamp"])
        self.assertEqual(30, event["data"]["0"])
Ejemplo n.º 8
0
class TestNewDevice(unittest.TestCase):
	def setUp(self):
		self.zmq = ZMQConnection(config.gws_zmq_endpoint)
		self.zmq.accept(lambda m: "gateway_id" in m)
		self.zmq.open()

		self.ws = websocket.WebSocket()
		self.ws.connect(config.gws_ws_uri)

		registerGateway(self, self.ws, config.gateway_id)

		event = self.zmq.pop_data()
		self.assertEqual("on-connected", event["event"])
		self.assertEqual(config.gateway_id, event["gateway_id"])

	def tearDown(self):
		self.ws.close()

		try:
			event = self.zmq.pop_data()
			self.assertEqual("on-disconnected", event["event"])
			self.assertEqual(config.gateway_id, event["gateway_id"])
		finally:
			self.zmq.close()

	"""
	Register device with a valid type. It should be accepted without any issue.
	"""
	def test1_new_device_success(self):
		id = str(uuid.uuid4())

		msg = json.dumps({
			"message_type" : "new_device_request",
			"id" : id,
			"device_id" : "0xa123123412341234",
			"vendor" : "BeeeOn",
			"product_name" : "Internal Pressure v1.0",
			"refresh_time" : 30,
			"module_types" : [
				{
					"type" : "pressure",
					"attributes" : [
						{"attribute" : "inner"}
					]
				}
			],
			"ip_address" : "10.0.0.1",
			"mac_address": "00:11:22:33:44:55",
			"firmware": "v1.0"
		})

		self.ws.send(msg)
		response = json.loads(self.ws.recv())

		self.assertEqual("generic_response", response["message_type"])
		self.assertEqual(id, response["id"])
		self.assertEqual(1, response["status"])
		assureNotClosed(self, self.ws)

		event = self.zmq.pop_data()
		self.assertEqual("on-new-device", event["event"])
		self.assertEqual("0xa123123412341234", event["device_id"])
		self.assertEqual("Internal Pressure v1.0", event["device_name"])
		self.assertEqual(1, len(event["modules"]))
		self.assertEqual("pressure", event["modules"][0]["type"])
		self.assertEqual(config.gateway_id, event["gateway_id"])

	"""
	Register device that does not match to any types known on the
	server. The server must fail to register this devices and provide
	an appropriate response.
	"""
	def test2_new_device_fail_invalid_product(self):
		id = str(uuid.uuid4())

		msg = json.dumps({
			"message_type" : "new_device_request",
			"id" : id,
			"device_id" : "0xa123123412349999",
			"vendor" : "Good Company",
			"product_name" : "Nice Product",
			"refresh_time" : 30,
			"module_types" : [
				{
					"type" : "pressure",
					"attributes" : [
						{"attribute" : "inner"}
					]
				}
			]
		})

		self.ws.send(msg)
		response = json.loads(self.ws.recv())

		self.assertEqual("generic_response", response["message_type"])
		self.assertEqual(id, response["id"])
		self.assertEqual(2, response["status"])
		assureNotClosed(self, self.ws)

		event = self.zmq.pop_data()
		self.assertEqual("on-refused-new-device", event["event"])
		self.assertEqual("0xa123123412349999", event["device_id"])
		self.assertEqual(config.gateway_id, event["gateway_id"])

	"""
	Server must deny accepting of device with an invalid device ID.
	The type of the device would be valid and acceptable otherwise.
	"""
	def test3_new_device_disconnect_invalid_id(self):
		id = str(uuid.uuid4())

		msg = json.dumps({
			"message_type" : "new_device_request",
			"id" : id,
			"device_id" : "123",
			"vendor" : "BeeeOn",
			"product_name" : "Internal Pressure v1.0",
			"refresh_time" : 30,
			"module_types" : [
				{
					"type" : "pressure",
					"attributes" : [
						{"attribute" : "inner"}
					]
				}
			]
		})

		self.ws.send(msg)
		assureIsClosed(self, self.ws)

	"""
	Register device that module type 'humidity' does not match with known module
	'pressure' for that device type on the server. The server must fail
	to register this devices and provide an appropriate response.
	"""
	def test4_new_device_fail_invalid_module(self):
		id = str(uuid.uuid4())

		msg = json.dumps({
			"message_type" : "new_device_request",
			"id" : id,
			"device_id" : "0xa123123412341111",
			"vendor" : "BeeeOn",
			"product_name" : "Internal Pressure v1.0",
			"refresh_time" : 30,
			"module_types" : [
				{
					"type" : "humidity",
					"attributes" : [
						{"attribute" : "inner"}
					]
				}
			]
		})

		self.ws.send(msg)
		response = json.loads(self.ws.recv())

		self.assertEqual("generic_response", response["message_type"])
		self.assertEqual(id, response["id"])
		self.assertEqual(2, response["status"])
		assureNotClosed(self, self.ws)

		event = self.zmq.pop_data()
		self.assertEqual("on-refused-new-device", event["event"])
		self.assertEqual("0xa123123412341111", event["device_id"])
		self.assertEqual(config.gateway_id, event["gateway_id"])

	"""
	Register device with 2 modules, but this device type has just one module
	'pressure' known on the server. The server must fail
	to register this devices and provide an appropriate response.
	"""
	def test5_new_device_fail_too_many_modules(self):
		id = str(uuid.uuid4())

		msg = json.dumps({
			"message_type" : "new_device_request",
			"id" : id,
			"device_id" : "0xa123123412342222",
			"vendor" : "BeeeOn",
			"product_name" : "Internal Pressure v1.0",
			"refresh_time" : 30,
			"module_types" : [
				{
					"type" : "pressure",
					"attributes" : [
						{"attribute" : "inner"}
					]
				},
				{
					"type" : "humidity",
					"attributes" : []
				}
			]
		})

		self.ws.send(msg)
		response = json.loads(self.ws.recv())

		self.assertEqual("generic_response", response["message_type"])
		self.assertEqual(id, response["id"])
		self.assertEqual(2, response["status"])
		assureNotClosed(self, self.ws)

		event = self.zmq.pop_data()
		self.assertEqual("on-refused-new-device", event["event"])
		self.assertEqual("0xa123123412342222", event["device_id"])
		self.assertEqual(config.gateway_id, event["gateway_id"])

	"""
	Test that a second new_device_request for the same device where its product_name
	is not important for type recognition is used as an update and its name is
	updated accordingly.
	"""
	def test6_new_device_and_update(self):
		id = str(uuid.uuid4())

		msg1 = json.dumps({
			"message_type" : "new_device_request",
			"id" : id,
			"device_id" : "0xa123123412343333",
			"vendor" : "Availability",
			"product_name" : "",
			"refresh_time" : 30,
			"module_types" : [
				{
					"type" : "availability",
					"attributes" : []
				}
			],
			"serial_number": "122342341231"
		})

		self.ws.send(msg1)
		response = json.loads(self.ws.recv())

		self.assertEqual("generic_response", response["message_type"])
		self.assertEqual(id, response["id"])
		self.assertEqual(1, response["status"])
		assureNotClosed(self, self.ws)

		notification = self.zmq.pop_data()
		self.assertEqual("on-new-device", notification["event"])
		self.assertEqual("0xa123123412343333", notification["device_id"])
		self.assertNotIn("device_name", notification)
		self.assertEqual(1, len(notification["modules"]))
		self.assertEqual("availability", notification["modules"][0]["type"])
		self.assertEqual(config.gateway_id, notification["gateway_id"])

		msg2 = json.dumps({
			"message_type" : "new_device_request",
			"id" : id,
			"device_id" : "0xa123123412343333",
			"vendor" : "Availability",
			"name": "Super device",
			"product_name" : "",
			"refresh_time" : 30,
			"module_types" : [
				{
					"type" : "availability",
					"attributes" : []
				}
			],
			"serial_number": "122342341231"
		})

		self.ws.send(msg2)
		response = json.loads(self.ws.recv())

		self.assertEqual("generic_response", response["message_type"])
		self.assertEqual(id, response["id"])
		self.assertEqual(1, response["status"])
		assureNotClosed(self, self.ws)

		notification = self.zmq.pop_data()
		self.assertEqual("on-new-device", notification["event"])
		self.assertEqual("0xa123123412343333", notification["device_id"])
		self.assertEqual("Super device", notification["device_name"])
		self.assertEqual(1, len(notification["modules"]))
		self.assertEqual("availability", notification["modules"][0]["type"])
		self.assertEqual(config.gateway_id, notification["gateway_id"])

	"""
	Register new device with unknown modules. Such device should
	be registered successfully. The modules are resolved by server
	and reported via ZeroMQ events.
	"""
	def test7_new_device_with_unknown_modules(self):
		id = str(uuid.uuid4())

		msg1 = json.dumps({
			"message_type" : "new_device_request",
			"id" : id,
			"device_id" : "0xa123123412355431",
			"vendor" : "Unknown sensors producer",
			"product_name" : "Device with unknown sensors",
			"refresh_time" : 30,
			"module_types" : [
				{
					"type" : "unknown",
					"attributes" : []
				},
				{
					"type" : "unknown",
					"attributes" : [
						{"attribute": "controllable"}
					]
				}
			]
		})

		self.ws.send(msg1)
		response = json.loads(self.ws.recv())

		self.assertEqual("generic_response", response["message_type"])
		self.assertEqual(id, response["id"])
		self.assertEqual(1, response["status"])
		assureNotClosed(self, self.ws)

		event = self.zmq.pop_data()
		self.assertEqual("on-new-device", event["event"])
		self.assertEqual("0xa123123412355431", event["device_id"])
		self.assertEqual("Device with unknown sensors", event["device_name"])
		self.assertEqual(2, len(event["modules"]))
		self.assertEqual("temperature", event["modules"][0]["type"])
		self.assertEqual(0, event["modules"][0]["controllable"])
		self.assertEqual("temperature", event["modules"][1]["type"])
		self.assertEqual(1, event["modules"][1]["controllable"])
		self.assertEqual(config.gateway_id, event["gateway_id"])
Ejemplo n.º 9
0
class TestDeviceList(unittest.TestCase):
    def setUp(self):
        self.zmq = ZMQConnection(config.gws_zmq_endpoint)
        self.zmq.accept(lambda m: "gateway_id" in m)
        self.zmq.open()

        self.ws = websocket.WebSocket()
        self.ws.connect(config.gws_ws_uri)

        registerGateway(self, self.ws, config.gateway_id)

        event = self.zmq.pop_data()
        self.assertEqual("on-connected", event["event"])
        self.assertEqual(config.gateway_id, event["gateway_id"])

    def tearDown(self):
        self.ws.close()

        try:
            event = self.zmq.pop_data()
            self.assertEqual("on-disconnected", event["event"])
            self.assertEqual(config.gateway_id, event["gateway_id"])
        finally:
            self.zmq.close()

    """
	Gateway 1284174504043136 has already associated 4 devices via the testing-data.sql
	init script. 3 of them are active (paired). Ask server for the paired virtual devices
	and test it give us them all.
	"""

    def test1_device_list_success_3_virtual(self):
        id = str(uuid.uuid4())

        msg = json.dumps({
            "message_type": "device_list_request",
            "id": id,
            "device_prefix": "VirtualDevice"
        })

        self.ws.send(msg)
        self.ws.settimeout(
            5)  # this can take more time, suboptimal implementation
        msg = json.loads(self.ws.recv())

        self.assertEqual("device_list_response", msg["message_type"])
        self.assertEqual(id, msg["id"])
        self.assertEqual(1, msg["status"])
        self.assertEqual(3, len(msg["devices"]))
        self.assertEqual("0xa32d27aa5e94ecfd", msg["devices"][0]["device_id"])
        self.assertEqual("0xa335d00019f5234e", msg["devices"][1]["device_id"])
        self.assertEqual("0xa37e0f7f0302324d", msg["devices"][2]["device_id"])

        self.assertEqual(2, len(msg["values"]))
        self.assertIn("0xa32d27aa5e94ecfd", msg["values"])
        self.assertIn("0", msg["values"]["0xa32d27aa5e94ecfd"])
        self.assertNotIn("1", msg["values"]["0xa32d27aa5e94ecfd"])
        self.assertEqual(20, msg["values"]["0xa32d27aa5e94ecfd"]["0"])

        self.assertIn("0xa335d00019f5234e", msg["values"])
        self.assertIn("0", msg["values"]["0xa335d00019f5234e"])
        self.assertIn("1", msg["values"]["0xa335d00019f5234e"])
        self.assertIn("2", msg["values"]["0xa335d00019f5234e"])
        self.assertNotIn("3", msg["values"]["0xa335d00019f5234e"])
        self.assertEqual(19.5, msg["values"]["0xa335d00019f5234e"]["0"])
        self.assertEqual(0, msg["values"]["0xa335d00019f5234e"]["1"])
        # 0xa335d00019f5234e[2] is a random value and cannot be easily tested

        self.assertEqual("10.0.0.1",
                         msg["config"]["0xa32d27aa5e94ecfd"]["ip-address"])
        self.assertEqual("super-secret",
                         msg["config"]["0xa32d27aa5e94ecfd"]["password"])
        self.assertEqual("v1.0-6453",
                         msg["config"]["0xa335d00019f5234e"]["firmware"])

        assureNotClosed(self, self.ws)

    """
	The gateway_id 1284174504043136 has no Jablotron device registered. Test we
	are given no such device by the server.
	"""

    def test2_device_list_success_0_jablotron(self):
        id = str(uuid.uuid4())

        msg = json.dumps({
            "message_type": "device_list_request",
            "id": id,
            "device_prefix": "Jablotron"
        })

        self.ws.send(msg)
        msg = json.loads(self.ws.recv())

        self.assertEqual("device_list_response", msg["message_type"])
        self.assertEqual(id, msg["id"])
        self.assertEqual(1, msg["status"])
        self.assertEqual(0, len(msg["devices"]))
        self.assertNotIn("values", msg)
        assureNotClosed(self, self.ws)

    """
	When asking for devices of an unknown device prefix, the server encounters
	an exception which leads to closing the connection. This behaviour would be
	changed in the future. Now, make sure that an unknown prefix breaks the
	connection of the gateway.
	"""

    def test3_device_list_disconnect_bad_prefix(self):
        id = str(uuid.uuid4())

        msg = json.dumps({
            "message_type": "device_list_request",
            "id": id,
            "device_prefix": "Cool"
        })

        self.ws.send(msg)
        assureIsClosed(self, self.ws)