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

16 statements  

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

1""" 

2# # Exercise 8: MultiEntity and Expression Language 

3 

4# The MultiEntity plugin allows the devices provisioned in the IoTAgent to map their 

5attributes to more than one entity, declaring the target entity through the 

6Configuration or Device provisioning APIs. 

7 

8# The IoTAgent Library provides an expression language for measurement transformation, 

9that can be used to adapt the # information coming from the South Bound APIs to the 

10information reported to the Context Broker. This is really useful when you need to 

11adapt measure. 

12 

13# There are available two different expression languages jexl and legacy. The 

14recommended language to use is jexl, which is newer and most powerful. 

15 

16# The input sections are marked with 'TODO' 

17 

18# #### Steps to complete: 

19# 1. Setting up the expression language jexl 

20# 2. Applying the expression language to device attributes 

21# 3. Testing the expression language via MQTT messages 

22# 4. Applying the expression language to device attributes in a multi-entity scenario 

23""" 

24 

25# Import packages 

26import time 

27import datetime 

28 

29from filip.clients.ngsi_v2 import IoTAClient, ContextBrokerClient 

30from filip.models.base import FiwareHeader 

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

32from filip.models.ngsi_v2.iot import ( 

33 Device, 

34 ServiceGroup, 

35 TransportProtocol, 

36 PayloadProtocol, 

37 DeviceAttribute, 

38 ExpressionLanguage, 

39) 

40from filip.utils.cleanup import clear_all 

41from paho.mqtt import client as mqtt_client 

42from paho.mqtt.client import CallbackAPIVersion 

43 

44# Host address of Context Broker 

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

46 

47# Host address of IoT-Agent 

48IOTA_URL = "http://localhost:4041" 

49 

50# MQTT Broker 

51MQTT_BROKER_HOST = "localhost" 

52MQTT_BROKER_PORT = 1883 

53 

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

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

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

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

58# FIWARE Service 

59SERVICE = "filip_tutorial" 

60SERVICE_PATH = "/" 

61 

62# ToDo: Change the APIKEY to something unique. This represent the "token" 

63# for IoT devices to connect (send/receive data ) with the platform. In the 

64# context of MQTT, APIKEY is linked with the topic used for communication. 

65APIKEY = "your_apikey" 

66 

67if __name__ == "__main__": 

68 # FIWARE Header 

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

70 

71 # Cleanup at the beginning 

72 clear_all(fiware_header=fiware_header, cb_url=CB_URL, iota_url=IOTA_URL) 

73 

74 # IoT Agent and OCB Client 

75 iota_client = IoTAClient(url=IOTA_URL, fiware_header=fiware_header) 

76 cb_client = ContextBrokerClient(url=CB_URL, fiware_header=fiware_header) 

77 

78 # TODO: Setting expression language to JEXL at Service Group level 

79 service_group1 = ServiceGroup( 

80 entity_type="Thing", 

81 resource="/iot/json", 

82 apikey=APIKEY, 

83 # ... 

84 ) 

85 iota_client.post_group(service_group=service_group1) 

86 

87 # TODO: Create a device with two attributes 'location' and 'fillingLevel' that use 

88 # expressions. These attributes are based on the attributes 'longitude', 

89 # 'latitude' and 'level', while: 

90 # 1. 'location' is an array with 'longitude' and 'latitude'. 

91 # 2. 'fillingLevel' is 'level' divided by 100 

92 device1 = Device( 

93 device_id="waste_container_001", 

94 entity_name="urn:ngsi-ld:WasteContainer:001", 

95 entity_type="WasteContainer", 

96 transport=TransportProtocol.MQTT, 

97 protocol=PayloadProtocol.IOTA_JSON, 

98 # ... 

99 ) 

100 iota_client.post_device(device=device1) 

101 

102 # TODO: Setting expression language to JEXL at Device level with five attributes, while 

103 # 1. The attribute 'value' (Number) is itself multiplied by 5. The attribute 

104 # 2. 'consumption' (Text) is the trimmed version of the attribute 'spaces' (Text). 

105 # 3. The attribute 'iso_time' (Text) is the current 'timestamp' (Number) transformed into the ISO format. 

106 device2 = Device( 

107 device_id="waste_container_002", 

108 entity_name="urn:ngsi-ld:WasteContainer:002", 

109 entity_type="WasteContainer", 

110 transport=TransportProtocol.MQTT, 

111 protocol=PayloadProtocol.IOTA_JSON, 

112 # ... 

113 ) 

114 iota_client.post_device(device=device2) 

115 

116 client = mqtt_client.Client(callback_api_version=CallbackAPIVersion.VERSION2) 

117 client.username_pw_set(username="", password="") 

118 client.connect(MQTT_BROKER_HOST, MQTT_BROKER_PORT) 

119 client.loop_start() 

120 

121 # TODO: Publish attributes 'level', 'longitude' and 'latitude' of device1 

122 client.publish(...) 

123 

124 # TODO: Publish attributes 'value', 'spaces' and 'timestamp' (in ms) of device2 

125 client.publish(...) 

126 

127 client.disconnect() 

128 

129 time.sleep(2) 

130 

131 # Printing context entities of OCB 

132 for context_entity in cb_client.get_entity_list(entity_types=["WasteContainer"]): 

133 print(context_entity.model_dump_json(indent=4)) 

134 

135 # Creating two SubWeatherStation entities 

136 entity1 = ContextEntity( 

137 id="urn:ngsi-ld:SubWeatherStation:001", type="SubWeatherStation" 

138 ) 

139 entity1.add_attributes(attrs=[NamedContextAttribute(name="vol", type="Number")]) 

140 cb_client.post_entity(entity1) 

141 

142 entity2 = ContextEntity( 

143 id="urn:ngsi-ld:SubWeatherStation:002", type="SubWeatherStation" 

144 ) 

145 entity2.add_attributes(attrs=[NamedContextAttribute(name="vol", type="Number")]) 

146 cb_client.post_entity(entity2) 

147 

148 # TODO: Create a weather station device with multi entity attributes (Number). 

149 # 'v' is multiplied by 100 and is a standard attribute. 

150 # 'v1' and 'v2' are multiplied by 100 and should be linked with entities of 

151 # the SubWeatherStation. 

152 # The name of each attribute is 'vol'. 

153 device3 = Device( 

154 device_id="weather_station_001", 

155 entity_name="urn:ngsi-ld:WeatherStation:001", 

156 entity_type="WeatherStation", 

157 transport=TransportProtocol.MQTT, 

158 protocol=PayloadProtocol.IOTA_JSON, 

159 # ... 

160 ) 

161 iota_client.post_device(device=device3) 

162 

163 client = mqtt_client.Client(callback_api_version=CallbackAPIVersion.VERSION2) 

164 client.username_pw_set(username="", password="") 

165 client.connect(MQTT_BROKER_HOST, MQTT_BROKER_PORT) 

166 client.loop_start() 

167 

168 # TODO: Publish values to all attributes of device3 

169 client.publish(...) 

170 

171 client.disconnect() 

172 

173 time.sleep(2) 

174 

175 # Printing context entities of OCB 

176 for context_entity in cb_client.get_entity_list( 

177 entity_types=["WeatherStation", "SubWeatherStation"] 

178 ): 

179 print(context_entity.model_dump_json(indent=4))