Frontend API
Purple Arrows in the image above indicate the UDP communication between the different software components of the Q-Scope framework.
Receiving UDP messages from cspy
The incoming grid information from cspy (as described in the previous chapter) is deciphered in grid.py
UDP communication is initialized in frontend.py. The frontend object has a thread running for each of the physical tables and links them to each of the grids, so the grids can receive messages from each of the according tag decoders. Additionally, it starts a third thread to function as an UDP server to receive messages from GAMA and forward them to the infoscreen.
Upon initialization, the grids will be allocated a callback function, that is executed whenever a message is received from the tag decoders: read_scanner_data. In this function, the received message will be interpreted so the grids can process the id and rotation of each grid cell. It is possible to infer the relative rotation from a previous state, which can be used as means of interaction (which, btw, is NOT done in the QUARREE100 project).
Note
The actual UDPServer class can be found in UDP.py.
The grid is either updated when interacting with a computer mouse (left- right- or middle-click on the cells) or if the tag decoder detects a change in the physical grid. In the latter case, a json-formatted string is sent to the frontend via UDP and decoded in the according grid.
def read_scanner_data(self, message):
try:
msg = json.loads(message)
except json.decoder.JSONDecodeError:
print("Invalid JSON")
return
try:
# update grid cells
for y, row in enumerate(self.grid):
for x, cell in enumerate(row):
cell.id, cell.rot = msg['grid'][y * self.x_size + x]
cell.selected = cell.id != 5 # any non-white object selects cells
# calculate relative rotation
if cell.rot == -1: # an inactive cell has a rotation value of -1
cell.rel_rot = 0
elif cell.prev_rot != cell.rot:
cell.rel_rot = cell.rot - cell.prev_rot if cell.prev_rot > -1 else 0
cell.prev_rot = cell.rot
session.flag_export_canvas = True
session.active_mode.process_grid_change()
# update slider values
for slider_id in self.sliders.keys():
if msg['sliders'][slider_id] is not None: self.sliders[slider_id].value = msg['sliders'][slider_id]
self.sliders[slider_id].process_value()
except TypeError as t:
# pass
print("type error", t)
except IndexError:
print("Warning: incoming grid data is incomplete")
Frontend and GAMA
The frontend can start a gama simulation in a subprocess by entering the simulation mode. GAMA will create csv files containing simulation results, which are used by the frontend to generate graphs. These graphs are displayed on the infoscreen in the data view modes<individual_data_view>.
More information on the exported simulation results can be found in the according ABM section<simulation_outputs> of this documentation.
Sending UDP messages to the infoscreen
The messages sent from the frontend have the following generic structure:
{
"buildings_groups": {
"group_0": {
"buildings": [
{
"address": string,
"spec_heat_consumption": number,
"spec_power_consumption": number,
"cluster_size": number,
"emissions_graphs": string, #path to a GAMA generated image
"energy_prices_graphs": string, #path to a GAMA generated image
"CO2": number,
"connection_to_heat_grid": boolean,
"connection_to_heat_grid_prior": boolean,
"refurbished": boolean,
"refurbished_prior": boolean,
"save_energy": boolean,
"save_energy_prior": boolean,
"energy_source": string, #"Gas" or "Strom"
"cell": sting
},
... #can have multiple buildings
],
"connections": 0,
"slider_handles": list #"save_energy", "connection_to_heat_grid", or/and "refurbished"
},
...# should have group_0 to group_3
}
}
They are emitted each time a grid change is received from cspy. All UDP messages are composed using a set of tools from q100viz/api.py:
send_message
: simple function to finally send a message via UDP. It should have json format for the infoscreen to process it properly.send_dataframe_as_json
: make a json struct from a pandas DataFrame object and send it via send_message()send_df_with_session_env
: translates a pandas DataFrame to json format and appends the session.environment dictsend_session_env
: simply send the session.environment dict as json formatforward_gama_message
: formats gama simulation status message to percentage and forwards it to the infoscreen via send_message()export_json
: Export a dataframe to JSON file. This is necessary to transform GeoDataFrames into a JSON serializable format.