Coverage for tutorials/ngsi_v2/e3_context_entities/e3_context_entities.py: 0%

11 statements  

« prev     ^ index     » next       coverage.py v7.10.2, created at 2025-08-05 11:07 +0000

1""" 

2# # Exercise 3: Context Entities and Relationships 

3 

4# Create a building context entity of type 'Building' according to FIWARE's 

5# SmartData Models with the properties: `id`, `type`, `address`, `category`, 

6# https://github.com/smart-data-models/dataModel.Building/blob/master/Building/doc/spec.md 

7 

8# For the single properties check the "Data Model description of 

9# properties" section. The input sections are marked with 'ToDo' 

10 

11# #### Steps to complete: 

12# 1. Set up the missing parameters in the parameter section 

13# 2. Find the Building data model online: 

14# https://github.com/smart-data-models/dataModel.Building/blob/master/Building/doc/spec.md 

15# 3. Create a `ContextEntity` object for your building 

16# 4. Create the required `ContextAttributes` and add them to your building model 

17# 5. Create a `ContextBrokerClient` and add post your building to the 

18# ContextBroker. Afterwards, check if the Context Broker returns the 

19# correct information about your building 

20# 6. Create an `opening hours` attribute add them to the server 

21# 7. Retrieve the `opening hours`, manipulate them and update the model in the 

22# server 

23# 8. Repeat the procedure with a thermal zone. Currently, the smart data 

24# models hold no definition of a thermal zone. Therefore, we first only add a 

25# description attribute. 

26# 9. Add a `Relationship` attribute to your thermal zone with the name 

27# `refBuilding` and type `Relationship` pointing to your building and post 

28# the model to the context broker 

29# 10. Add a `Relationship` attribute to your building with name 

30# `hasZone` and type `Relationship` pointing to your thermal zone and 

31# update the model in the context broker. 

32# 11. Update the thermal zone and the building in the context broker 

33# 12. Retrieve the data by using query statements for their relationships. 

34""" 

35 

36# ## Import packages 

37import json 

38from pathlib import Path 

39 

40# filip imports 

41from filip.clients.ngsi_v2 import ContextBrokerClient 

42from filip.models import FiwareHeader 

43from filip.models.ngsi_v2.context import ContextEntity, NamedContextAttribute 

44from filip.utils.cleanup import clear_context_broker 

45from filip.utils.simple_ql import QueryString 

46 

47# ## Parameters 

48# ToDo: Enter your context broker host and port, e.g. http://localhost:1026. 

49CB_URL = "http://localhost:1026" 

50 

51# ToDo: Change the name of your service to something unique. If you run 

52# on a shared instance this is very important in order to avoid user 

53# collisions. You will use this service through the whole tutorial. 

54# If you forget to change it, an error will be raised! 

55# FIWARE-Service 

56SERVICE = "filip_tutorial" 

57# FIWARE-Service path 

58SERVICE_PATH = "/" 

59 

60# ToDo: Path to json-files to store entity data for follow up exercises, 

61# e.g. ../e3_my_entities.json. Files that are used in exercises and files 

62# that are used in solutions are different from each other so be careful 

63# when working with them. You can of course change the paths as you wish, 

64# but it is recommended to use the already given path names. 

65WRITE_ENTITIES_FILEPATH = Path("../e3_context_entities.json") 

66 

67# ## Main script 

68if __name__ == "__main__": 

69 # create a fiware header object 

70 fiware_header = FiwareHeader(service=SERVICE, service_path=SERVICE_PATH) 

71 # clear the state of your service and scope 

72 clear_context_broker(url=CB_URL, fiware_header=fiware_header) 

73 

74 # Create a context entity for a `building` following the smart data models 

75 # specifications 

76 building = ContextEntity(id="urn:ngsi-ld:building:001", type="Building") 

77 

78 # create the property `category` to your building 

79 category = NamedContextAttribute(name="category", type="Array", value=["office"]) 

80 

81 # ToDo: Create a property `address` for your building. Follow the full yaml 

82 # description in the specifications. It reuses the specification from 

83 # here: https://schema.org/PostalAddress 

84 address = NamedContextAttribute(name="address", type="PostalAddress", value={...}) 

85 

86 # ToDo: Create a `description` property for your building. 

87 building_description = NamedContextAttribute(...) 

88 

89 # add all properties to your building using the 

90 # `add_attribute` function of your building object 

91 building.add_attributes(attrs=[building_description, category, address]) 

92 

93 # ToDo: Create a context broker client and add the fiware_header. 

94 cbc = ... 

95 # ToDo: Send your building model to the context broker. Check the client 

96 # for proper functioning. 

97 ... 

98 

99 # Update your local building model with the one from the server 

100 building = cbc.get_entity(entity_id=building.id, entity_type=building.type) 

101 

102 # print your `building model` as json 

103 print(f"This is your building model: \n {building.model_dump_json(indent=2)} \n") 

104 

105 # ToDo: Create an `opening hours` property and add it to the building object 

106 # in the context broker. Do not update the whole entity! In real 

107 # scenarios it might have been modified by other users. 

108 opening_hours = NamedContextAttribute( 

109 name="openingHours", type="array", value=[...] 

110 ) 

111 

112 cbc.update_or_append_entity_attributes( 

113 entity_id=building.id, entity_type=building.type, attrs=[opening_hours] 

114 ) 

115 

116 # ToDo: Retrieve and print the property `opening hours`. 

117 hours = cbc.get_attribute_value(...) 

118 

119 print(f"Your opening hours: {hours} \n") 

120 

121 # ToDo: Modify the property `opening hours` of the building. 

122 cbc.update_attribute_value(...) 

123 

124 # ToDo: At this point you might have already noticed that your local 

125 # building model and the building model in the context broker are out of 

126 # sync. Hence, synchronize them again! 

127 building = cbc.get_entity(entity_id=building.id, entity_type=building.type) 

128 

129 # print your building 

130 print(f"Your updated building model: \n {building.model_dump_json(indent=2)} \n") 

131 

132 # ToDo: Create an entity of the thermal zone and add a description property 

133 # to it. 

134 thermal_zone = ContextEntity(id="ThermalZone:001", type="ThermalZone") 

135 

136 thermal_zone_description = NamedContextAttribute( 

137 name="description", 

138 type="Text", 

139 value="This zones covers " "the entire building", 

140 ) 

141 thermal_zone.add_attributes(attrs=[thermal_zone_description]) 

142 

143 # ToDo: Create and add a property that references your building model. Use the 

144 # `Relationship` for type and `refBuilding` for its name. 

145 ref_building = NamedContextAttribute( 

146 name="refBuilding", type="Relationship", value=building.id 

147 ) 

148 thermal_zone.add_attributes(attrs=[ref_building]) 

149 

150 # print all relationships of your thermal zone 

151 for relationship in thermal_zone.get_relationships(): 

152 print( 

153 f"Relationship properties of your thermal zone model: \n " 

154 f"{relationship.model_dump_json(indent=2)} \n" 

155 ) 

156 

157 # ToDo: Post your thermal zone model to the context broker. 

158 ... 

159 ... 

160 

161 # ToDo: Create and add a property that references your thermal zone. Use the 

162 # `Relationship` for type and `hasZone` for its name. Make sure that 

163 # your local model and the server model are in sync afterwards. 

164 ref_zone = NamedContextAttribute(...) 

165 

166 cbc.update_or_append_entity_attributes(...) 

167 

168 building = cbc.get_entity(entity_id=building.id, entity_type=building.type) 

169 

170 # ToDo: Create a filter request that retrieves all entities from the 

171 # server that have `refBuilding` attribute that reference your building 

172 # by using the FIWARE's simple query language. 

173 # `filip.utils.simple_ql` module helps you to validate your query string. 

174 # 1. Prepare the query string using the `filip.utils.simple_ql`. 

175 # 2. Use the string in a context broker request and retrieve the entities. 

176 query = QueryString(qs=("refBuilding", "==", building.id)) 

177 for entity in cbc.get_entity_list(q=query): 

178 print( 

179 f"All entities referencing the building: " 

180 f"\n {entity.model_dump_json(indent=2)}\n" 

181 ) 

182 

183 # ToDo: Create a filter request that retrieves all entities from the 

184 # server that have `hasZone` attribute that reference your thermal zone 

185 # by using the FIWARE's simple query language. 

186 # `filip.utils.simple_ql` module helps you to validate your query string. 

187 # 1. Prepare the query string using the `filip.utils.simple_ql`. 

188 # 2. Use the string in a context broker request and retrieve the entities. 

189 query = ... 

190 for entity in cbc.get_entity_list(q=query): 

191 print( 

192 f"All entities referencing the thermal zone: " 

193 f"\n {entity.model_dump_json(indent=2)} \n" 

194 ) 

195 

196 # write entities to file and clear server state 

197 assert ( 

198 WRITE_ENTITIES_FILEPATH.suffix == ".json" 

199 ), f"Wrong file extension! {WRITE_ENTITIES_FILEPATH.suffix}" 

200 WRITE_ENTITIES_FILEPATH.touch(exist_ok=True) 

201 with WRITE_ENTITIES_FILEPATH.open("w", encoding="utf-8") as f: 

202 entities = [item.model_dump() for item in cbc.get_entity_list()] 

203 json.dump(entities, f, ensure_ascii=False, indent=2) 

204 

205 clear_context_broker(url=CB_URL, fiware_header=fiware_header)