def __init__(self): """Initialization""" # # use envirnment variables # os.environ["CONFIG_FILE"] = "False" # define parameters self.params = {} self.params['controller_name'] = os.getenv("CONTROLLER_NAME", 'PID_1') self.params['type'] = "PID_Controller" self.params['setpoint'] = float(os.getenv("SETPOINT", '293.15')) # reverse mode can be activated by passing negative tunings to controller self.params['Kp'] = float(os.getenv("KP", '1.0')) self.params['Ki'] = float(os.getenv("KI", '0')) self.params['Kd'] = float(os.getenv("KD", '0')) self.params['lim_low'] = float(os.getenv("LIM_LOW", '0')) self.params['lim_upper'] = float(os.getenv("LIM_UPPER", '100')) self.params['pause_time'] = float(os.getenv("PAUSE_TIME", 0.2)) self.params['sensor_entity_name'] = os.getenv("SENSOR_ENTITY_NAME", '') self.params['sensor_type'] = os.getenv("SENSOR_TYPE", None) self.params['sensor_attr'] = os.getenv("SENSOR_ATTR", '') self.params['actuator_entity_name'] = os.getenv( "ACTUATOR_ENTITY_NAME", '') self.params['actuator_type'] = os.getenv("ACTUATOR_TYPE", '') self.params['actuator_command'] = os.getenv("ACTUATOR_COMMAND", '') self.params['actuator_command_value'] = self.params[ 'actuator_command'] + '_info' self.params['service'] = os.getenv("FIWARE_SERVICE", '') self.params['service_path'] = os.getenv("FIWARE_SERVICE_PATH", '') self.params['cb_url'] = os.getenv("CB_URL", "http://localhost:1026") # settings for security mode self.security_mode = os.getenv("SECURITY_MODE", 'False').lower() in ('true', '1', 'yes') self.params['token'] = (None, None) # Get token from keycloak in security mode if self.security_mode: self.kp = KeycloakPython() self.params['token'] = self.kp.get_access_token() # Create simple pid instance self.pid = PID(self.params['Kp'], self.params['Ki'], self.params['Kd'], setpoint=self.params['setpoint'], output_limits=(self.params['lim_low'], self.params['lim_upper'])) # Additional parameters self.auto_mode = True self.u = None # control variable u self.y_act = self.params[ 'setpoint'] # set the initial measurement to set point # Create the fiware header fiware_header = FiwareHeader(service=self.params['service'], service_path=self.params['service_path']) # Create orion context broker client self.ORION_CB = ContextBrokerClient(url=self.params['cb_url'], fiware_header=fiware_header)
def setUp(self) -> None: """ Setup test data Returns: None """ self.fiware_header = FiwareHeader( service=settings.FIWARE_SERVICE, service_path=settings.FIWARE_SERVICEPATH) clear_all(fiware_header=self.fiware_header, cb_url=settings.CB_URL, iota_url=settings.IOTA_JSON_URL) self.resources = { "entities_url": "/v2/entities", "types_url": "/v2/types", "subscriptions_url": "/v2/subscriptions", "registrations_url": "/v2/registrations" } self.attr = {'temperature': {'value': 20.0, 'type': 'Number'}} self.entity = ContextEntity(id='MyId', type='MyType', **self.attr) self.client = ContextBrokerClient( url=settings.CB_URL, fiware_header=self.fiware_header) self.subscription = Subscription.parse_obj({ "description": "One subscription to rule them all", "subject": { "entities": [ { "idPattern": ".*", "type": "Room" } ], "condition": { "attrs": [ "temperature" ], "expression": { "q": "temperature>40" } } }, "notification": { "http": { "url": "http://localhost:1234" }, "attrs": [ "temperature", "humidity" ] }, "expires": datetime.now(), "throttling": 0 })
def setUp(self) -> None: """ Setup test data Returns: None """ self.fiware_header = FiwareHeader( service=settings.FIWARE_SERVICE, service_path=settings.FIWARE_SERVICEPATH) self.ql_client = QuantumLeapClient(url=settings.QL_URL, fiware_header=self.fiware_header) self.cb_client = ContextBrokerClient(url=settings.CB_URL, fiware_header=self.fiware_header)
def test_metadata(self): """ Test for metadata works but the api of iot agent-json seems not working correctly Returns: None """ metadata = {"accuracy": {"type": "Text", "value": "+-5%"}} attr = DeviceAttribute(name="temperature", object_id="temperature", type="Number", metadata=metadata) device = Device(**self.device) device.device_id = "device_with_meta" device.add_attribute(attribute=attr) logger.info(device.json(indent=2)) with IoTAClient( url=settings.IOTA_JSON_URL, fiware_header=self.fiware_header) as client: client.post_device(device=device) logger.info(client.get_device(device_id=device.device_id).json( indent=2, exclude_unset=True)) with ContextBrokerClient( url=settings.CB_URL, fiware_header=self.fiware_header) as client: logger.info(client.get_entity(entity_id=device.entity_name).json( indent=2))
def test_subscription_set_status(self): """ Test subscription operations of context broker client """ sub = self.subscription.copy( update={'expires': datetime.now() + timedelta(days=1)}) with ContextBrokerClient( url=settings.CB_URL, fiware_header=self.fiware_header) as client: sub_id = client.post_subscription(subscription=sub) sub_res = client.get_subscription(subscription_id=sub_id) self.assertEqual(sub_res.status, Status.ACTIVE) sub_inactive = sub_res.copy(update={'status': Status.INACTIVE}) client.update_subscription(subscription=sub_inactive) sub_res_inactive = client.get_subscription(subscription_id=sub_id) self.assertEqual(sub_res_inactive.status, Status.INACTIVE) sub_active = sub_res_inactive.copy(update={'status': Status.ACTIVE}) client.update_subscription(subscription=sub_active) sub_res_active = client.get_subscription(subscription_id=sub_id) self.assertEqual(sub_res_active.status, Status.ACTIVE) sub_expired = sub_res_active.copy( update={'expires': datetime.now() - timedelta(days=365)}) client.update_subscription(subscription=sub_expired) sub_res_expired = client.get_subscription(subscription_id=sub_id) self.assertEqual(sub_res_expired.status, Status.EXPIRED)
def test_statistics(self): """ Test statistics of context broker client """ with ContextBrokerClient( url=settings.CB_URL, fiware_header=self.fiware_header) as client: self.assertIsNotNone(client.get_statistics())
def test_management_endpoints(self): """ Test management functions of context broker client """ with ContextBrokerClient( url=settings.CB_URL, fiware_header=self.fiware_header) as client: self.assertIsNotNone(client.get_version()) self.assertEqual(client.get_resources(), self.resources)
def __init__(self, config: Union[str, Path, HttpClientConfig, Dict] = None, session: Session = None, fiware_header: FiwareHeader = None, **kwargs): """ Constructor for master client Args: config (Union[str, Path, Dict]): Configuration object session (request.Session): Session object fiware_header (FiwareHeader): Fiware header **kwargs: Optional arguments that ``request`` takes. """ if config: self.config = config else: self.config = HttpClientConfig() super().__init__(session=session, fiware_header=fiware_header, **kwargs) # initialize sub clients self.cb = ContextBrokerClient(url=self.config.cb_url, session=self.session, fiware_header=self.fiware_headers, **self.kwargs) self.iota = IoTAClient(url=self.config.iota_url, session=self.session, fiware_header=self.fiware_headers, **self.kwargs) self.timeseries = QuantumLeapClient(url=self.config.ql_url, session=self.session, fiware_header=self.fiware_headers, **self.kwargs) # from here on deprecated? auth_types = { 'basicauth': self.__http_basic_auth, 'digestauth': self.__http_digest_auth } # 'oauth2': self.__oauth2} if self.config.auth: assert self.config.auth['type'].lower() in auth_types.keys() self.__get_secrets_file(path=self.config.auth['secret']) auth_types[self.config.auth['type']]() self.__secrets = { "username": None, "password": None, "client_id": None, "client_secret": None }
def __init__(self): # initialize controller parameters (in dict) self.params = self.initialize_params() # FIWARE parameters self.cb_url = os.getenv("CB_URL", "http://localhost:1026") self.entity_id = None # will be read on the web GUI self.entity_type = "PID_Controller" self.service = os.getenv("FIWARE_SERVICE", '') self.service_path = os.getenv("FIWARE_SERVICE_PATH", '') # Create the fiware header fiware_header = FiwareHeader(service=self.service, service_path=self.service_path) # Create orion context broker client self.ORION_CB = ContextBrokerClient(url=self.cb_url, fiware_header=fiware_header) # initial pid controller list self.controller_list = [] try: self.refresh_list() except: pass # initialize gui window sg.theme("DarkBlue") pid_id_bar = [[ sg.Text("Controller ID", size=(10, 1)), sg.Combo(self.controller_list, key="controller_list"), sg.Button("Refresh") ]] param_bars = [[ sg.Text(param.capitalize(), size=(10, 1)), sg.InputText(self.params[param], key=param) ] for param in self.params.keys()] io_bars = [[sg.Button("Send"), sg.Button("Read")]] layout = pid_id_bar + param_bars + io_bars self.window = sg.Window("PID controller", layout, web_port=80, web_start_browser=True)
def tearDown(self) -> None: # Cleanup test server with ContextBrokerClient(url=settings.CB_URL) as client: client.fiware_service = settings.FIWARE_SERVICE for path in self.service_paths: header = FiwareHeader(service=settings.FIWARE_SERVICE, service_path=path) clear_all(fiware_header=header, cb_url=settings.CB_URL) client.close()
def test_subscription_models(self) -> None: """ Test subscription models Returns: None """ sub_dict = { "description": "One subscription to rule them all", "subject": { "entities": [ { "idPattern": ".*", "type": "Room" } ], "condition": { "attrs": [ "temperature" ], "expression": { "q": "temperature>40" } } }, "notification": { "http": { "url": "http://localhost:1234" }, "attrs": [ "temperature", "humidity" ] }, "expires": "2030-04-05T14:00:00Z", "throttling": 5 } sub = Subscription.parse_obj(sub_dict) fiware_header = FiwareHeader(service=settings.FIWARE_SERVICE, service_path=settings.FIWARE_SERVICEPATH) with ContextBrokerClient( url=settings.CB_URL, fiware_header=fiware_header) as client: sub_id = client.post_subscription(subscription=sub) sub_res = client.get_subscription(subscription_id=sub_id) def compare_dicts(dict1: dict, dict2: dict): for key, value in dict1.items(): if isinstance(value, dict): compare_dicts(value, dict2[key]) else: self.assertEqual(str(value), str(dict2[key])) compare_dicts(sub.dict(exclude={'id'}), sub_res.dict(exclude={'id'}))
def test_entity_filtering(self): """ Test filter operations of context broker client """ with ContextBrokerClient( url=settings.CB_URL, fiware_header=self.fiware_header) as client: # test patterns with self.assertRaises(ValueError): client.get_entity_list(id_pattern='(&()?') with self.assertRaises(ValueError): client.get_entity_list(type_pattern='(&()?') entities_a = [ContextEntity(id=str(i), type=f'filip:object:TypeA') for i in range(0, 5)] client.update(action_type=ActionType.APPEND, entities=entities_a) entities_b = [ContextEntity(id=str(i), type=f'filip:object:TypeB') for i in range(6, 10)] client.update(action_type=ActionType.APPEND, entities=entities_b) entities_all = client.get_entity_list() entities_by_id_pattern = client.get_entity_list( id_pattern='.*[1-5]') self.assertLess(len(entities_by_id_pattern), len(entities_all)) entities_by_type_pattern = client.get_entity_list( type_pattern=".*TypeA$") self.assertLess(len(entities_by_type_pattern), len(entities_all)) qs = QueryString(qs=[('presentValue', '>', 0)]) entities_by_query = client.get_entity_list(q=qs) self.assertLess(len(entities_by_query), len(entities_all)) # test options for opt in list(AttrsFormat): entities_by_option = client.get_entity_list(response_format=opt) self.assertEqual(len(entities_by_option), len(entities_all)) self.assertEqual(client.get_entity( entity_id='0', response_format=opt), entities_by_option[0]) with self.assertRaises(ValueError): client.get_entity_list(response_format='not in AttrFormat') client.update(action_type=ActionType.DELETE, entities=entities_a) client.update(action_type=ActionType.DELETE, entities=entities_b)
def test_type_operations(self): """ Test type operations of context broker client """ with ContextBrokerClient( url=settings.CB_URL, fiware_header=self.fiware_header) as client: self.assertIsNotNone(client.post_entity(entity=self.entity, update=True)) client.get_entity_types() client.get_entity_types(options='count') client.get_entity_types(options='values') client.get_entity_type(entity_type='MyType') client.delete_entity(entity_id=self.entity.id, entity_type=self.entity.type)
def get_client(instance_header: InstanceHeader) \ -> ContextBrokerClient: """Get the correct ContextBrokerClient to be used with the given header Args: instance_header (InstanceHeader): Header to be used with client Returns: ContextBrokerClient """ if instance_header.ngsi_version == NgsiVersion.v2: return ContextBrokerClient( url=instance_header.cb_url, fiware_header=instance_header.get_fiware_header()) else: # todo LD raise Exception("FiwareVersion not yet supported")
def test_fiware_header(self): """ Test for fiware header """ header = FiwareHeader.parse_obj(self.fiware_header) self.assertEqual(header.dict(by_alias=True), self.fiware_header) self.assertEqual(header.json(by_alias=True), json.dumps(self.fiware_header)) self.assertRaises(ValidationError, FiwareHeader, service='jkgsadh ', service_path='/testing') self.assertRaises(ValidationError, FiwareHeader, service='%', service_path='/testing') self.assertRaises(ValidationError, FiwareHeader, service='filip', service_path='testing/') self.assertRaises(ValidationError, FiwareHeader, service='filip', service_path='/$testing') self.assertRaises(ValidationError, FiwareHeader, service='filip', service_path='/testing ') self.assertRaises(ValidationError, FiwareHeader, service='filip', service_path='#') headers = FiwareHeader.parse_obj(self.fiware_header) with ContextBrokerClient(url=settings.CB_URL, fiware_header=headers) as client: entity = ContextEntity(id='myId', type='MyType') for path in self.service_paths: client.fiware_service_path = path client.post_entity(entity=entity) client.get_entity(entity_id=entity.id) client.fiware_service_path = '/#' self.assertGreaterEqual(len(client.get_entity_list()), len(self.service_paths)) for path in self.service_paths: client.fiware_service_path = path client.delete_entity(entity_id=entity.id, entity_type=entity.type)
def test_subscriptions(self): """ Test subscription operations of context broker client """ with ContextBrokerClient( url=settings.CB_URL, fiware_header=self.fiware_header) as client: sub_id = client.post_subscription(subscription=self.subscription, skip_initial_notification=True) sub_res = client.get_subscription(subscription_id=sub_id) time.sleep(1) sub_update = sub_res.copy( update={'expires': datetime.now() + timedelta(days=1)}) client.update_subscription(subscription=sub_update) sub_res_updated = client.get_subscription(subscription_id=sub_id) self.assertNotEqual(sub_res.expires, sub_res_updated.expires) self.assertEqual(sub_res.id, sub_res_updated.id) self.assertGreaterEqual(sub_res_updated.expires, sub_res.expires) # test duplicate prevention and update sub = self.subscription.copy() id1 = client.post_subscription(sub) sub_first_version = client.get_subscription(id1) sub.description = "This subscription shall not pass" id2 = client.post_subscription(sub, update=False) self.assertEqual(id1, id2) sub_second_version = client.get_subscription(id2) self.assertEqual(sub_first_version.description, sub_second_version.description) id2 = client.post_subscription(sub, update=True) self.assertEqual(id1, id2) sub_second_version = client.get_subscription(id2) self.assertNotEqual(sub_first_version.description, sub_second_version.description) # test that duplicate prevention does not prevent to much sub2 = self.subscription.copy() sub2.description = "Take this subscription to Fiware" sub2.subject.entities[0] = { "idPattern": ".*", "type": "Building" } id3 = client.post_subscription(sub2) self.assertNotEqual(id1, id3)
def test_pagination(self): """ Test pagination of context broker client Test pagination. only works if enough entities are available """ with ContextBrokerClient( url=settings.CB_URL, fiware_header=self.fiware_header) as client: entities_a = [ContextEntity(id=str(i), type=f'filip:object:TypeA') for i in range(0, 1000)] client.update(action_type=ActionType.APPEND, entities=entities_a) entities_b = [ContextEntity(id=str(i), type=f'filip:object:TypeB') for i in range(1000, 2001)] client.update(action_type=ActionType.APPEND, entities=entities_b) self.assertLessEqual(len(client.get_entity_list(limit=1)), 1) self.assertLessEqual(len(client.get_entity_list(limit=999)), 999) self.assertLessEqual(len(client.get_entity_list(limit=1001)), 1001) self.assertLessEqual(len(client.get_entity_list(limit=2001)), 2001)
def test_batch_operations(self): """ Test batch operations of context broker client """ with ContextBrokerClient( url=settings.CB_URL, fiware_header=self.fiware_header) as client: entities = [ContextEntity(id=str(i), type=f'filip:object:TypeA') for i in range(0, 1000)] client.update(entities=entities, action_type=ActionType.APPEND) entities = [ContextEntity(id=str(i), type=f'filip:object:TypeB') for i in range(0, 1000)] client.update(entities=entities, action_type=ActionType.APPEND) entity = EntityPattern(idPattern=".*", typePattern=".*TypeA$") query = Query.parse_obj( {"entities": [entity.dict(exclude_unset=True)]}) self.assertEqual(1000, len(client.query(query=query, response_format='keyValues')))
def test__14_device_deleting(self): """ Test if SemanticDeviceClass.delete() completly removes the device and context entry from Fiware. All other interactions are covered in the "deleting test" """ from tests.semantics.models2 import Class1, Class3, semantic_manager # clear local state to ensure standard test condition self.clear_registry() # Test 1: Local deletion # create class class3_ = Class3(id="13") class3_.device_settings.endpoint = "http://test.com" class3_.device_settings.transport = TransportProtocol.HTTP semantic_manager.save_state(assert_validity=False) self.clear_registry() # load class from Fiware, and delete it class3_ = Class3(id="13") class3_.delete() semantic_manager.save_state(assert_validity=False) self.clear_registry() self.assertTrue(len(semantic_manager.instance_registry.get_all()) == 0) time.sleep(1) # class no longer exists in fiware iota or context broker with IoTAClient(url=semantic_manager.default_header.iota_url, fiware_header=semantic_manager.default_header. get_fiware_header()) as client: self.assertEqual(0, len(client.get_device_list())) with ContextBrokerClient(url=semantic_manager.default_header.cb_url, fiware_header=semantic_manager.default_header. get_fiware_header()) as client: self.assertEqual(0, len(client.get_entity_list()))
def test_entity_operations(self): """ Test entity operations of context broker client """ with ContextBrokerClient( url=settings.CB_URL, fiware_header=self.fiware_header) as client: client.post_entity(entity=self.entity, update=True) res_entity = client.get_entity(entity_id=self.entity.id) client.get_entity(entity_id=self.entity.id, attrs=['temperature']) self.assertEqual(client.get_entity_attributes( entity_id=self.entity.id), res_entity.get_properties( response_format='dict')) res_entity.temperature.value = 25 client.update_entity(entity=res_entity) self.assertEqual(client.get_entity(entity_id=self.entity.id), res_entity) res_entity.add_attributes({'pressure': ContextAttribute( type='Number', value=1050)}) client.update_entity(entity=res_entity) self.assertEqual(client.get_entity(entity_id=self.entity.id), res_entity)
READ_ENTITIES_FILEPATH = \ Path("./e3_context_entities_entities.json") # ## Main script if __name__ == '__main__': # create a fiware header object fiware_header = FiwareHeader(service=SERVICE, service_path=SERVICE_PATH) # clear the state of your service and scope clear_iot_agent(url=IOTA_URL, fiware_header=fiware_header) clear_context_broker(url=CB_URL, fiware_header=fiware_header) # Create clients and restore devices and groups from file groups = parse_file_as(List[ServiceGroup], READ_GROUPS_FILEPATH) devices = parse_file_as(List[Device], READ_DEVICES_FILEPATH) entities = parse_file_as(List[ContextEntity], READ_ENTITIES_FILEPATH) cbc = ContextBrokerClient(url=CB_URL, fiware_header=fiware_header) for entity in entities: cbc.post_entity(entity=entity) iotac = IoTAClient(url=IOTA_URL, fiware_header=fiware_header) iotac.post_groups(service_groups=groups) iotac.post_devices(devices=devices) # ToDo: Retrieve all iot resources from the IoT-Agent # Get the group and device configurations from the server group = iotac.get_group(resource="/iot/json", apikey=APIKEY) weather_station = iotac.get_device(device_id="device:001") zone_temperature_sensor = iotac.get_device(device_id="device:002") heater = iotac.get_device(device_id="device:003") # ToDo: Get context entities from the Context Broker
def test__13_device_saving_and_loading(self): """ Test if a Device can be correctly saved and loaded. And the live methods of Commands and DeviceAttributes """ from tests.semantics.models2 import Class1, Class3, semantic_manager class3_ = Class3(id="c3") class3_.device_settings.endpoint = "http://test.com" class3_.device_settings.transport = TransportProtocol.HTTP class3_.oProp1.add(Class1(id="19")) class3_.dataProp1.add("Test") # Class1(id="19").oProp1.add(class3_) class3_.commandProp.add(Command(name="on")) class3_.commandProp.add(Command(name="off")) class3_.attributeProp.add( DeviceAttribute(name="d1", attribute_type=DeviceAttributeType.lazy)) class3_.attributeProp.add( DeviceAttribute(name="d2", attribute_type=DeviceAttributeType.active)) # test that live access methods fail, because state was not saved self.assertRaises(Exception, class3_.attributeProp.get_all()[0].get_value) self.assertRaises(Exception, class3_.commandProp.get_all()[0].get_info) self.assertRaises(Exception, class3_.commandProp.get_all()[0].get_status) self.assertRaises(Exception, class3_.commandProp.get_all()[0].send) semantic_manager.save_state(assert_validity=False) # Test if device could be processed correctly -> corresponding entity # in Fiware with ContextBrokerClient( url=class3_.header.cb_url, fiware_header=class3_.header.get_fiware_header()) as client: assert client.get_entity(entity_id="c3", entity_type="Class3") self.clear_registry() loaded_class = Class3(id="c3") attr2 = [a for a in class3_.attributeProp.get_all() if a.name == "d2"][0] attr2_ = [ a for a in loaded_class.attributeProp.get_all() if a.name == "d2" ][0] self.assertEqual(attr2.name, attr2_.name) self.assertEqual(attr2.attribute_type, attr2_.attribute_type) self.assertEqual(attr2._instance_link.instance_identifier, attr2_._instance_link.instance_identifier) self.assertEqual(attr2._instance_link.field_name, attr2_._instance_link.field_name) com2 = [c for c in class3_.commandProp.get_all() if c.name == "off"][0] com2_ = [ c for c in loaded_class.commandProp.get_all() if c.name == "off" ][0] self.assertEqual(com2.name, com2_.name) self.assertEqual(com2._instance_link.instance_identifier, com2_._instance_link.instance_identifier) self.assertEqual(attr2._instance_link.field_name, attr2_._instance_link.field_name) self.assertEqual(class3_.references, loaded_class.references) self.assertEqual(class3_.device_settings.dict(), loaded_class.device_settings.dict()) # test that live access methods succeed, because state was saved class3_.attributeProp.get_all()[0].get_value() class3_.commandProp.get_all()[0].get_info() class3_.commandProp.get_all()[0].get_status() # todo, find out what causes the send command to fail when running # in the CI # class3_.commandProp.get_all()[0].send() # test if fields are removed and updated class3_.commandProp.clear() class3_.attributeProp.clear() class3_.commandProp.add(Command(name="NEW_COMMAND")) class3_.attributeProp.add( DeviceAttribute(name="NEW_ATT", attribute_type=DeviceAttributeType.lazy)) class3_.dataProp1.add("TEST!!!") semantic_manager.save_state(assert_validity=False) self.clear_registry() with semantic_manager.get_iota_client(class3_.header) as client: device = client.get_device(device_id=class3_.get_device_id()) self.assertTrue(len(device.commands), 1) self.assertTrue(len(device.attributes), 1) for command in device.commands: self.assertTrue(command.name, "NEW_COMMAND") for attr in device.attributes: self.assertTrue(attr.name, "NEW_ATT") for static_attr in device.static_attributes: if static_attr.name == "dataProp1": self.assertTrue(static_attr.value, ["TEST!!!"])
# Setting up logging logging.basicConfig( level='INFO', format='%(asctime)s %(name)s %(levelname)s: %(message)s') logger = logging.getLogger(__name__) if __name__ == "__main__": # # 1 Setup client and models # fiware_header = FiwareHeader(service=SERVICE, service_path=SERVICE_PATH) # ## 1.1 Store entities # with ContextBrokerClient(fiware_header=fiware_header, url=CB_URL) as cb_client: # make sure that the server is clean cb_client.delete_entities(cb_client.get_entity_list()) store_dict = [{"type": "Store", "id": "urn:ngsi-ld:Store:001", "address": { "type": "Text", "value": "Bornholmer Straße 65" }, "location": { "type": "Text", "value": "[13.3986, 52.5547]" }, "name": { "type": "Text", "value": "Bösebrücke Einkauf"
# First a create a fiware header that you want to work with # For more details on the headers check the official documentation: # https://fiware-orion.readthedocs.io/en/master/user/multitenancy/index.html # # In short a fiware header specifies a location in Fiware where the # created entities will be saved and requests are executed. # It can be thought of as a separated subdirectory where you work in. fiware_header = FiwareHeader(service='filip', service_path='/example') # # 2 Client modes # You can run the clients in different modes: # # ## 2.1 Run it as pure python object. # # This will open and close a connection each time you use a function. cb_client = ContextBrokerClient(url="http://134.130.166.184:1026", fiware_header=fiware_header) print(f"OCB Version: {cb_client.get_version()}") # ## 2.2 Run the client via the python's context protocol. # # This will initialize requests.session that the client will reuse for # each function. # Formally, this usually lead to an performance boost because the # connection was reused reused. The client and its connection will be # closed after the end of the with-statement. However, thanks to urllib3 # the keep-alive and session reuse is handled totally automatically. with ContextBrokerClient(fiware_header=fiware_header) as cb_client: print(f"OCB Version: {cb_client.get_version()}") # ## 2.3 Run the client with an externally provided requests.Session object #
def test_patch_device(self): """ Test the methode: patch_device of the iota client """ device = Device(**self.device) device.endpoint = "http://test.com" device.transport = "MQTT" device.add_attribute(DeviceAttribute( name="Att1", object_id="o1", type=DataType.STRUCTUREDVALUE)) device.add_attribute(StaticDeviceAttribute( name="Stat1", value="test", type=DataType.STRUCTUREDVALUE)) device.add_attribute(StaticDeviceAttribute( name="Stat2", value="test", type=DataType.STRUCTUREDVALUE)) device.add_command(DeviceCommand(name="Com1")) # use patch_device to post self.client.patch_device(device=device) cb_client = ContextBrokerClient(url=settings.CB_URL, fiware_header=self.fiware_header) # test if attributes exists correctly live_entity = cb_client.get_entity(entity_id=device.entity_name) live_entity.get_attribute("Att1") live_entity.get_attribute("Com1") live_entity.get_attribute("Com1_info") live_entity.get_attribute("Com1_status") self.assertEqual(live_entity.get_attribute("Stat1").value, "test") # change device attributes and update device.get_attribute("Stat1").value = "new_test" device.delete_attribute(device.get_attribute("Stat2")) device.delete_attribute(device.get_attribute("Att1")) device.delete_attribute(device.get_attribute("Com1")) device.add_attribute(DeviceAttribute( name="Att2", object_id="o1", type=DataType.STRUCTUREDVALUE)) device.add_attribute(StaticDeviceAttribute( name="Stat3", value="test3", type=DataType.STRUCTUREDVALUE)) device.add_command(DeviceCommand(name="Com2")) self.client.patch_device(device=device, cb_url=settings.CB_URL) # test if update does what it should, for the device. It does not # change the entity completely: live_entity = cb_client.get_entity(entity_id=device.entity_name) with self.assertRaises(KeyError): live_entity.get_attribute("Att1") with self.assertRaises(KeyError): live_entity.get_attribute("Com1_info") with self.assertRaises(KeyError): live_entity.get_attribute("Stat2") self.assertEqual(live_entity.get_attribute("Stat1").value, "new_test") live_entity.get_attribute("Stat3") live_entity.get_attribute("Com2_info") live_entity.get_attribute("Att2") # test update where device information were changed device_settings = {"endpoint": "http://localhost:7071", "device_id": "new_id", "entity_name": "new_name", "entity_type": "new_type", "timestamp": False, "apikey": "zuiop", "protocol": "HTTP", "transport": "HTTP"} for key, value in device_settings.items(): device.__setattr__(key, value) self.client.patch_device(device=device) live_device = self.client.get_device(device_id=device.device_id) self.assertEqual(live_device.__getattribute__(key), value) cb_client.close()
def test_update_device(self): """ Test the methode: update_device of the iota client """ device = Device(**self.device) device.endpoint = "http://test.com" device.transport = "MQTT" device.add_attribute(DeviceAttribute( name="Att1", object_id="o1", type=DataType.STRUCTUREDVALUE)) device.add_attribute(StaticDeviceAttribute( name="Stat1", value="test", type=DataType.STRUCTUREDVALUE)) device.add_attribute(StaticDeviceAttribute( name="Stat2", value="test", type=DataType.STRUCTUREDVALUE)) device.add_command(DeviceCommand(name="Com1")) # use update_device to post self.client.update_device(device=device, add=True) cb_client = ContextBrokerClient(url=settings.CB_URL, fiware_header=self.fiware_header) # test if attributes exists correctly live_entity = cb_client.get_entity(entity_id=device.entity_name) live_entity.get_attribute("Att1") live_entity.get_attribute("Com1") live_entity.get_attribute("Com1_info") live_entity.get_attribute("Com1_status") self.assertEqual(live_entity.get_attribute("Stat1").value, "test") # change device attributes and update device.get_attribute("Stat1").value = "new_test" device.delete_attribute(device.get_attribute("Stat2")) device.delete_attribute(device.get_attribute("Att1")) device.delete_attribute(device.get_attribute("Com1")) device.add_attribute(DeviceAttribute( name="Att2", object_id="o1", type=DataType.STRUCTUREDVALUE)) device.add_attribute(StaticDeviceAttribute( name="Stat3", value="test3", type=DataType.STRUCTUREDVALUE)) device.add_command(DeviceCommand(name="Com2")) # device.endpoint = "http://localhost:8080" self.client.update_device(device=device) # test if update does what it should, for the device. It does not # change the entity completely: live_device = self.client.get_device(device_id=device.device_id) with self.assertRaises(KeyError): live_device.get_attribute("Att1") with self.assertRaises(KeyError): live_device.get_attribute("Com1_info") with self.assertRaises(KeyError): live_device.get_attribute("Stat2") self.assertEqual(live_device.get_attribute("Stat1").value, "new_test") live_device.get_attribute("Stat3") live_device.get_command("Com2") live_device.get_attribute("Att2") cb_client.close()
IoTAClient, \ QuantumLeapClient # ## Parameters # ToDo: Enter your context broker url and port, e.g. http://localhost:1026 CB_URL = "http://localhost:1026" # ToDo: Enter your IoT-Agent url and port, e.g. http://localhost:4041 IOTA_URL = "http://localhost:4041" # ToDo: Enter your QuantumLeap url and port, e.g. http://localhost:8668 QL_URL = "http://localhost:8668" # ## Main script if __name__ == "__main__": # Create a single client for each service and check the service for # its version cbc = ContextBrokerClient(url=CB_URL) print(cbc.get_version()) iotac = ... qlc = ... # ToDo: Create a configuration object for a multi client config = HttpClientConfig(...) # ToDo: Create a multi client check again all services for their version multic = HttpClient(config=config) print(multic.cb.get_version()) ...
def patch_device(self, device: Device, patch_entity: bool = True, cb_url: AnyHttpUrl = settings.CB_URL) -> None: """ Updates a device state in Fiware, if the device does not exists it is created, else its values are updated. If the device settings (endpoint,..) were changed the device and entity are deleted and re-added. If patch_entity is true the corresponding entity in the ContextBroker is also correctly updated. Else only new attributes are added there. Args: device (Device): Device to be posted to /updated in Fiware patch_entity (bool): If true the corresponding entity is completely synced cb_url (AnyHttpUrl): Url of the ContextBroker where the entity is found Returns: None """ try: live_device = self.get_device(device_id=device.device_id) except requests.RequestException: # device does not exist yet, post it self.post_device(device=device) return # if the device settings were changed we need to delete the device # and repost it settings_dict = { "device_id", "service", "service_path", "entity_name", "entity_type", "timestamp", "apikey", "endpoint", "protocol", "transport", "expressionLanguage" } import json live_settings = live_device.dict(include=settings_dict) new_settings = device.dict(include=settings_dict) if not live_settings == new_settings: self.delete_device(device_id=device.device_id, delete_entity=True, force_entity_deletion=True) self.post_device(device=device) return # We are at a state where the device exists, but only attributes were # changed. # we need to update the device, and the context entry separately, # as update device only takes over a part of the changes to the # ContextBroker. # update device self.update_device(device=device) # update context entry # 1. build context entity from information in device # 2. patch it from filip.models.ngsi_v2.context import \ ContextEntity, NamedContextAttribute def build_context_entity_from_device(device: Device) -> ContextEntity: from filip.models.base import DataType entity = ContextEntity(id=device.entity_name, type=device.entity_type) for command in device.commands: entity.add_attributes([ # Command attribute will be registered by the device_update NamedContextAttribute(name=f"{command.name}_info", type=DataType.COMMAND_RESULT), NamedContextAttribute(name=f"{command.name}_status", type=DataType.COMMAND_STATUS) ]) for attribute in device.attributes: entity.add_attributes([ NamedContextAttribute(name=attribute.name, type=DataType.STRUCTUREDVALUE, metadata=attribute.metadata) ]) for static_attribute in device.static_attributes: entity.add_attributes([ NamedContextAttribute(name=static_attribute.name, type=static_attribute.type, value=static_attribute.value, metadata=static_attribute.metadata) ]) return entity if patch_entity: from filip.clients.ngsi_v2 import ContextBrokerClient with ContextBrokerClient( url=cb_url, fiware_header=self.fiware_headers) as client: client.patch_entity( entity=build_context_entity_from_device(device))
def simulation( TEMPERATURE_MAX=10, # maximal ambient temperature TEMPERATURE_MIN=-5, # minimal ambient temperature TEMPERATURE_ZONE_START=10, # start value of the zone temperature T_SIM_START=0, # simulation start time in seconds T_SIM_END=24 * 60 * 60, # simulation end time in seconds COM_STEP=60 * 15, # 1 min communication step in seconds SLEEP_TIME=0.2 # sleep time between every simulation step ): # create a fiware header object fiware_header = FiwareHeader(service=SERVICE, service_path=SERVICE_PATH) # instantiate simulation model sim_model = SimulationModel(t_start=T_SIM_START, t_end=T_SIM_END, temp_max=TEMPERATURE_MAX, temp_min=TEMPERATURE_MIN, temp_start=TEMPERATURE_ZONE_START) # Create clients and restore devices and groups from files groups = parse_file_as(List[ServiceGroup], READ_GROUPS_FILEPATH) devices = parse_file_as(List[Device], READ_DEVICES_FILEPATH) cbc = ContextBrokerClient(url=CB_URL, fiware_header=fiware_header) iotac = IoTAClient(url=IOTA_URL, fiware_header=fiware_header) iotac.post_groups(service_groups=groups, update=True) iotac.post_devices(devices=devices, update=True) # Get the device configurations from the server weather_station = iotac.get_device(device_id="device:001") zone_temperature_sensor = iotac.get_device(device_id="device:002") heater = iotac.get_device(device_id="device:003") # Get the service group configurations from the server group = iotac.get_group(resource="/iot/json", apikey=APIKEY) # Create a http subscriptions that get triggered by updates of your # device attributes and send data to Quantum Leap. qlc = QuantumLeapClient(url=QL_URL, fiware_header=fiware_header) qlc.post_subscription(entity_id=weather_station.entity_name, entity_type=weather_station.entity_type, cb_url="http://orion:1026", ql_url="http://quantumleap:8668", throttling=0) qlc.post_subscription(entity_id=zone_temperature_sensor.entity_name, entity_type=zone_temperature_sensor.entity_type, cb_url="http://orion:1026", ql_url="http://quantumleap:8668", throttling=0) qlc.post_subscription(entity_id=heater.entity_name, entity_type=heater.entity_type, cb_url="http://orion:1026", ql_url="http://quantumleap:8668", throttling=0) # create a MQTTv5 client with paho-mqtt and the known groups and devices. mqttc = IoTAMQTTClient( protocol=mqtt.MQTTv5, devices=[weather_station, zone_temperature_sensor, heater], service_groups=[group]) # set user data if required mqttc.username_pw_set(username=MQTT_USER, password=MQTT_PW) # Implement a callback function that gets triggered when the # command is sent to the device. The incoming command should update the # heater power of the simulation model def on_command(client, obj, msg): """ Callback for incoming commands """ # Decode the message payload using the libraries builtin encoders apikey, device_id, payload = \ client.get_encoder(PayloadProtocol.IOTA_JSON).decode_message( msg=msg) # Update the heating power of the simulation model sim_model.heater_power = payload["heater_power"] # Acknowledge the command. client.publish(device_id=device_id, command_name=next(iter(payload)), payload=payload) # Add the command callback to your MQTTClient. This will get # triggered for the specified device_id mqttc.add_command_callback(device_id=heater.device_id, callback=on_command) # connect to the mqtt broker and subscribe to your topic mqtt_url = urlparse(MQTT_BROKER_URL_EXPOSED) mqttc.connect(host=mqtt_url.hostname, port=mqtt_url.port, keepalive=60, bind_address="", bind_port=0, clean_start=mqtt.MQTT_CLEAN_START_FIRST_ONLY, properties=None) # subscribe to all incoming command topics for the registered devices mqttc.subscribe() # create a non-blocking thread for mqtt communication mqttc.loop_start() # define lists to store historical data history_weather_station = [] history_zone_temperature_sensor = [] history_heater_power = [] # simulation without heater # Create a loop that publishes regularly a message to the broker # that holds the simulation time "simtime" and the corresponding # temperature "temperature" the loop should. You may use the `object_id` # or the attribute name as key in your payload. print("Simulation starts") for t_sim in range(sim_model.t_start, sim_model.t_end + int(COM_STEP), int(COM_STEP)): # publish the simulated ambient temperature mqttc.publish(device_id=weather_station.device_id, payload={ "temperature": sim_model.t_amb, "simtime": sim_model.t_sim }) # publish the simulated zone temperature mqttc.publish(device_id=zone_temperature_sensor.device_id, payload={ "temperature": sim_model.t_zone, "simtime": sim_model.t_sim }) # publish the 'simtime' for the heater device mqttc.publish(device_id=heater.device_id, payload={"simtime": sim_model.t_sim}) # simulation step for next loop sim_model.do_step(int(t_sim + COM_STEP)) # wait for one second before publishing the next values time.sleep(SLEEP_TIME) # Get corresponding entities and write values to history weather_station_entity = cbc.get_entity( entity_id=weather_station.entity_name, entity_type=weather_station.entity_type) # append the data to the local history history_weather_station.append({ "simtime": weather_station_entity.simtime.value, "temperature": weather_station_entity.temperature.value }) # Get ZoneTemperatureSensor and write values to history zone_temperature_sensor_entity = cbc.get_entity( entity_id=zone_temperature_sensor.entity_name, entity_type=zone_temperature_sensor.entity_type) history_zone_temperature_sensor.append({ "simtime": zone_temperature_sensor_entity.simtime.value, "temperature": zone_temperature_sensor_entity.temperature.value }) # Get ZoneTemperatureSensor and write values to history heater_entity = cbc.get_entity(entity_id=heater.entity_name, entity_type=heater.entity_type) history_heater_power.append({ "simtime": heater_entity.simtime.value, "heater_power": sim_model.heater_power }) # close the mqtt listening thread mqttc.loop_stop() # disconnect the mqtt device mqttc.disconnect() clear_iot_agent(url=IOTA_URL, fiware_header=fiware_header) clear_context_broker(url=CB_URL, fiware_header=fiware_header) return history_weather_station, history_zone_temperature_sensor, history_heater_power
def test_deletions(self): """ Test the deletion of a context entity/device if the state is always correctly cleared """ self.tearDown() device_id = 'device_id' entity_id = 'entity_id' device = Device(device_id=device_id, entity_name=entity_id, entity_type='Thing2', protocol='IoTA-JSON', transport='HTTP', apikey='filip-iot-test-device') cb_client = ContextBrokerClient(url=settings.CB_URL, fiware_header=self.fiware_header) # Test 1: Only delete device # delete without optional parameter -> entity needs to continue existing self.client.post_device(device=device) self.client.delete_device(device_id=device_id, cb_url=settings.CB_URL) self.assertTrue( len(cb_client.get_entity_list(entity_ids=[entity_id])) == 1) cb_client.delete_entity(entity_id=entity_id, entity_type='Thing2') # Test 2:Delete device and corresponding entity # delete with optional parameter -> entity needs to be deleted self.client.post_device(device=device) self.client.delete_device(device_id=device_id, cb_url=settings.CB_URL, delete_entity=True) self.assertTrue( len(cb_client.get_entity_list(entity_ids=[entity_id])) == 0) # Test 3:Delete device and corresponding entity, # that is linked to multiple devices # delete with optional parameter -> entity needs to be deleted self.client.post_device(device=device) device2 = copy.deepcopy(device) device2.device_id = "device_id2" self.client.post_device(device=device2) self.assertRaises(Exception, self.client.delete_device, device_id=device_id, delete_entity=True) self.assertTrue( len(cb_client.get_entity_list(entity_ids=[entity_id])) == 1) self.client.delete_device(device_id=device2.device_id) # Test 4: Only delete entity # delete without optional parameter -> device needs to continue existing self.client.post_device(device=device) cb_client.delete_entity(entity_id=entity_id, entity_type='Thing2') self.client.get_device(device_id=device_id) self.client.delete_device(device_id=device_id) # Test 5: Delete entity, and all devices # # delete with optional parameter -> all devices need to be deleted self.client.post_device(device=device) device2 = copy.deepcopy(device) device2.device_id = "device_id2" self.client.post_device(device=device2) cb_client.delete_entity(entity_id=entity_id, delete_devices=True, entity_type='Thing2', iota_url=settings.IOTA_JSON_URL) self.assertEqual(len(self.client.get_device_list()), 0)