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

28 statements  

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

1""" 

2# # Exercise 4: Virtual Thermal Zone 

3 

4# Create two virtual IoT devices. One of them represents the temperature 

5# sensor for the air temperature of a thermal zone, whereas the second 

6# represents a virtual weather station. Both devices publish their values to 

7# the platform via MQTT. Use the simulation model of 

8# e1_virtual_weatherstation.py 

9# 

10# The input sections are marked with 'ToDo' 

11# 

12# #### Steps to complete: 

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

14# 2. Create a service group and two corresponding devices 

15# 3. Provision the service group and the devices 

16# 4. Create an MQTT client using the filip.client.mqtt package and register 

17# your service group and your devices 

18# 5. Check if the IoT-Agent correctly creates the corresponding entities 

19# 5. Create a function that publishes the simulated temperature via MQTT, 

20# retrieves the entity data after each message and writes the values to a 

21# history 

22# 6. Run the simulation and plot the results 

23""" 

24 

25# ## Import packages 

26import json 

27from pathlib import Path 

28import time 

29from urllib.parse import urlparse 

30import matplotlib.pyplot as plt 

31import paho.mqtt.client as mqtt 

32 

33# import from filip 

34from filip.clients.ngsi_v2 import ContextBrokerClient, IoTAClient 

35from filip.clients.mqtt import IoTAMQTTClient 

36from filip.models.base import FiwareHeader 

37from filip.models.ngsi_v2.iot import Device, DeviceAttribute, ServiceGroup 

38from filip.utils.cleanup import clear_context_broker, clear_iot_agent 

39 

40# import simulation model 

41from tutorials.ngsi_v2.simulation_model import SimulationModel 

42 

43# ## Parameters 

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

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

46# ToDo: Enter your IoT-Agent host and port, e.g. http://localhost:4041. 

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

48# ToDo: Enter your mqtt broker url, e.g. mqtt://test.mosquitto.org:1883. 

49MQTT_BROKER_URL = "mqtt://localhost:1883" 

50# ToDo: If required, enter your username and password. 

51MQTT_USER = "" 

52MQTT_PW = "" 

53 

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

55# on a shared instance this is 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" 

60# FIWARE-Service path 

61SERVICE_PATH = "/" 

62 

63# ToDo: Change the APIKEY to something unique. This represents the "token" 

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

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

66APIKEY = "your_apikey" 

67 

68# path to json-files to device configuration data for follow-up exercises 

69WRITE_GROUPS_FILEPATH = Path("../e4_iot_thermal_zone_sensors_groups.json") 

70WRITE_DEVICES_FILEPATH = Path("../e4_iot_thermal_zone_sensors_devices.json") 

71 

72# set parameters for the temperature simulation 

73TEMPERATURE_MAX = 10 # maximal ambient temperature 

74TEMPERATURE_MIN = -5 # minimal ambient temperature 

75TEMPERATURE_ZONE_START = 20 # start value of the zone temperature 

76 

77T_SIM_START = 0 # simulation start time in seconds 

78T_SIM_END = 24 * 60 * 60 # simulation end time in seconds 

79COM_STEP = 60 * 60 * 0.25 # 15 min communication step in seconds 

80 

81# ## Main script 

82if __name__ == "__main__": 

83 # create a fiware header object 

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

85 # clear the state of your service and scope 

86 clear_iot_agent(url=IOTA_URL, fiware_header=fiware_header) 

87 clear_context_broker(url=CB_URL, fiware_header=fiware_header) 

88 

89 # instantiate simulation model 

90 sim_model = SimulationModel( 

91 t_start=T_SIM_START, 

92 t_end=T_SIM_END, 

93 temp_max=TEMPERATURE_MAX, 

94 temp_min=TEMPERATURE_MIN, 

95 temp_start=TEMPERATURE_ZONE_START, 

96 ) 

97 

98 # define lists to store historical data 

99 history_weather_station = [] 

100 history_zone_temperature_sensor = [] 

101 

102 # create a service group with your api key 

103 service_group = ServiceGroup(apikey=APIKEY, resource="/iot/json") 

104 

105 # ToDo: Create two IoTA-MQTT devices for the weather station and the zone 

106 # temperature sensor. Also add the simulation time as `active attribute` 

107 # to each device! 

108 # create the weather station device 

109 # create the `sim_time` attribute and add it to the weather station's attributes 

110 t_sim = DeviceAttribute(name="sim_time", object_id="t_sim", type="Number") 

111 

112 weather_station = Device( 

113 device_id="device:001", 

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

115 entity_type="WeatherStation", 

116 protocol="IoTA-JSON", 

117 transport="MQTT", 

118 apikey=APIKEY, 

119 attributes=[t_sim], 

120 commands=[], 

121 ) 

122 

123 # create a temperature attribute and add it via the api of the 

124 # `device`-model. Use the `t_amb` as `object_id`. `object_id` specifies 

125 # what key will be used in the MQTT Message payload 

126 t_amb = DeviceAttribute(name="temperature", object_id="t_amb", type="Number") 

127 

128 weather_station.add_attribute(t_amb) 

129 

130 # ToDo: Create the zone temperature device and add the `t_sim` attribute upon 

131 # creation. 

132 zone_temperature_sensor = Device(...) 

133 

134 # ToDo: Create the temperature attribute. Use the `t_zone` as `object_id`. 

135 # `object_id` specifies what key will be used in the MQTT Message payload. 

136 t_zone = DeviceAttribute(...) 

137 

138 zone_temperature_sensor.add_attribute(t_zone) 

139 

140 # ToDo: Create an IoTAClient. 

141 iotac = ... 

142 # ToDo: Provision service group and add it to your IoTAMQTTClient. 

143 ... 

144 # ToDo: Provision the devices at the IoTA-Agent. 

145 # provision the weather station device 

146 iotac.post_device(device=weather_station, update=True) 

147 # ToDo: Provision the zone temperature device. 

148 ... 

149 

150 # ToDo: Create a context broker client. 

151 # ToDo: Check in the context broker whether the entities corresponding to your 

152 # devices were correctly created. 

153 cbc = ContextBrokerClient(url=CB_URL, fiware_header=fiware_header) 

154 # get weather station entity 

155 print( 

156 f"Weather station:\n{cbc.get_entity(weather_station.entity_name).model_dump_json(indent=2)}" 

157 ) 

158 # ToDo: Get zone temperature sensor entity. 

159 print(...) 

160 

161 # ToDo: Create an MQTTv5 client using filip.clients.mqtt.IoTAMQTTClient. 

162 mqttc = IoTAMQTTClient(protocol=...) 

163 # ToDo: Register the service group with your MQTT-Client. 

164 mqttc.add_service_group(service_group=service_group) 

165 # ToDo: Register devices with your MQTT-Client. 

166 # register the weather station 

167 mqttc.add_device(weather_station) 

168 # ToDo: Register the zone temperature sensor. 

169 ... 

170 

171 # The IoTAMQTTClient automatically creates outgoing topics from the 

172 # device configuration during runtime. Hence, we need to construct them 

173 # manually in order to subscribe to them. This is usually not required as 

174 # only the platform should listen to the incoming traffic. 

175 # If you want to listen subscribe to the following topics: 

176 # "/json/<APIKEY>/<weather_station.device_id>/attrs" 

177 # "/json/<APIKEY>/<zone_temperature_sensor.device_id>/attrs" 

178 

179 # ToDO: Connect to the MQTT broker and subscribe to your topic. 

180 ... 

181 

182 # subscribe to topics 

183 # subscribe to all incoming command topics for the registered devices 

184 mqttc.subscribe() 

185 # create a non-blocking thread for mqtt communication 

186 mqttc.loop_start() 

187 

188 # ToDo: Create a loop that publishes a message every 100 milliseconds 

189 # to the broker that holds the simulation time `sim_time` and the 

190 # corresponding temperature `temperature`. You may use the `object_id` 

191 # or the attribute name as a key in your payload. 

192 for t_sim in range( 

193 sim_model.t_start, sim_model.t_end + int(COM_STEP), int(COM_STEP) 

194 ): 

195 # publish the simulated ambient temperature 

196 mqttc.publish( 

197 device_id=weather_station.device_id, 

198 payload={"temperature": sim_model.t_amb, "sim_time": sim_model.t_sim}, 

199 ) 

200 

201 # ToDo: Publish the simulated zone temperature. 

202 ... 

203 

204 # simulation step for the next loop 

205 sim_model.do_step(int(t_sim + COM_STEP)) 

206 # wait for one second before publishing the next values 

207 time.sleep(0.1) 

208 

209 # get corresponding entities and store the data 

210 weather_station_entity = cbc.get_entity( 

211 entity_id=weather_station.entity_name, 

212 entity_type=weather_station.entity_type, 

213 ) 

214 # append the data to the local history 

215 history_weather_station.append( 

216 { 

217 "sim_time": weather_station_entity.sim_time.value, 

218 "temperature": weather_station_entity.temperature.value, 

219 } 

220 ) 

221 

222 # ToDo: Get zone temperature sensor and store the data. 

223 zone_temperature_sensor_entity = ... 

224 

225 history_zone_temperature_sensor.append(...) 

226 

227 # close the mqtt listening thread 

228 mqttc.loop_stop() 

229 # disconnect the mqtt device 

230 mqttc.disconnect() 

231 

232 # plot the results 

233 fig, ax = plt.subplots() 

234 t_simulation = [item["sim_time"] / 3600 for item in history_weather_station] 

235 temperature = [item["temperature"] for item in history_weather_station] 

236 ax.plot(t_simulation, temperature) 

237 ax.title.set_text("Weather Station") 

238 ax.set_xlabel("time in h") 

239 ax.set_ylabel("ambient temperature in °C") 

240 

241 fig2, ax2 = plt.subplots() 

242 t_simulation = [item["sim_time"] / 3600 for item in history_zone_temperature_sensor] 

243 temperature = [item["temperature"] for item in history_zone_temperature_sensor] 

244 ax2.plot(t_simulation, temperature) 

245 ax2.title.set_text("Zone Temperature Sensor") 

246 ax2.set_xlabel("time in h") 

247 ax2.set_ylabel("zone temperature in °C") 

248 

249 plt.show()