diff --git a/.github/workflows/docker-test.yml b/.github/workflows/docker-test.yml index 49c869d..c643dc1 100644 --- a/.github/workflows/docker-test.yml +++ b/.github/workflows/docker-test.yml @@ -8,39 +8,39 @@ jobs: fail-fast: false matrix: os: [ubuntu-latest] - python-version: ['3.10'] + python-version: ["3.10"] steps: - - uses: actions/checkout@v2 - - name: build docker container - shell: bash - run: | - docker build --progress=plain -t oedisi-example:0.0.0 . - env: - SSH_KEY: ${{secrets.SGIDAL_CLONE_KEY}} - DOCKER_BUILDKIT: '1' - - name: run docker continaer - shell: bash - run: | - mkdir outputs_build - docker volume create --name oedisi_output --opt type=none --opt device=$(pwd)/outputs_build --opt o=bind - docker run --rm --mount source=oedisi_output,target=/simulation/outputs oedisi-example:0.0.0 - - name: Set up Python ${{ matrix.python-version }} - uses: conda-incubator/setup-miniconda@v2 - with: - auto-update-conda: true - python-version: ${{ matrix.python-version }} - - name: Run plots - shell: bash -l {0} - run: | - pip install matplotlib pyarrow numpy matplotlib pandas - pip install oedisi==1.2.1 + - uses: actions/checkout@v2 + - name: build docker container + shell: bash + run: | + docker build --progress=plain -t oedisi-example:0.0.0 . + env: + SSH_KEY: ${{secrets.SGIDAL_CLONE_KEY}} + DOCKER_BUILDKIT: "1" + - name: run docker continaer + shell: bash + run: | + mkdir outputs_build + docker volume create --name oedisi_output --opt type=none --opt device=$(pwd)/outputs_build --opt o=bind + docker run --rm --mount source=oedisi_output,target=/simulation/outputs oedisi-example:0.0.0 + - name: Set up Python ${{ matrix.python-version }} + uses: conda-incubator/setup-miniconda@v2 + with: + auto-update-conda: true + python-version: ${{ matrix.python-version }} + - name: Run plots + shell: bash -l {0} + run: | + pip install matplotlib pyarrow numpy matplotlib pandas + pip install oedisi~=3.0 - python post_analysis.py outputs_build - - name: Archive logs - uses: actions/upload-artifact@v4 - if: always() - with: - name: docker_logs - path: | - outputs_build/*.log - *.png + python post_analysis.py outputs_build + - name: Archive logs + uses: actions/upload-artifact@v4 + if: always() + with: + name: docker_logs + path: | + outputs_build/*.log + *.png diff --git a/LocalFeeder/requirements.txt b/LocalFeeder/requirements.txt index a4310db..7e54da8 100644 --- a/LocalFeeder/requirements.txt +++ b/LocalFeeder/requirements.txt @@ -10,5 +10,5 @@ boto3 xarray fastapi uvicorn -oedisi>=2.0.2,<3 +oedisi~=3.0 python-multipart diff --git a/LocalFeeder/sender_cosim.py b/LocalFeeder/sender_cosim.py index fd07f3b..8d52c25 100644 --- a/LocalFeeder/sender_cosim.py +++ b/LocalFeeder/sender_cosim.py @@ -340,7 +340,7 @@ def go_cosim( h.helicsFederateEnterExecutingMode(vfed) initial_data = get_initial_data(sim, config) - topology_dict = initial_data.topology.dict() + topology_dict = initial_data.topology.model_dump() topology_dict["bus_coords"] = sim.get_bus_coords() topology_json = json.dumps(topology_dict) logger.info("Sending topology and saving to topology.json") @@ -352,7 +352,7 @@ def go_cosim( logger.info("Evaluating the forecasted PV") forecast_data = sim.forcast_pv(int(config.number_of_timesteps)) PVforecast = [MeasurementArray(**xarray_to_dict(forecast), - units="kW").json() for forecast in forecast_data] + units="kW").model_dump_json() for forecast in forecast_data] pub_pv_forecast.publish(json.dumps(PVforecast)) granted_time = -1 @@ -377,11 +377,11 @@ def go_cosim( config.start_date, "%Y-%m-%d %H:%M:%S" ) + timedelta(seconds=current_index * config.run_freq_sec) - change_obj_cmds = CommandList.parse_obj(sub_command_set.json) - sim.change_obj(change_obj_cmds.__root__) + change_obj_cmds = CommandList.model_validate(sub_command_set.json) + sim.change_obj(change_obj_cmds.root) - inverter_controls = InverterControlList.parse_obj(sub_invcontrol.json) - for inv_control in inverter_controls.__root__: + inverter_controls = InverterControlList.model_validate(sub_invcontrol.json) + for inv_control in inverter_controls.root: sim.apply_inverter_control(inv_control) pv_sets = sub_pv_set.json @@ -427,46 +427,46 @@ def go_cosim( VoltagesMagnitude( **xarray_to_dict(voltage_magnitudes), time=current_timestamp, - ).json() + ).model_dump_json() ) pub_voltages_real.publish( VoltagesReal( **xarray_to_dict(current_data.feeder_voltages.real), time=current_timestamp, - ).json() + ).model_dump_json() ) pub_voltages_imag.publish( VoltagesImaginary( **xarray_to_dict(current_data.feeder_voltages.imag), time=current_timestamp, - ).json() + ).model_dump_json() ) pub_powers_real.publish( PowersReal( **xarray_to_dict(current_data.PQ_injections_all.real), time=current_timestamp, - ).json() + ).model_dump_json() ) pub_powers_imag.publish( PowersImaginary( **xarray_to_dict(current_data.PQ_injections_all.imag), time=current_timestamp, - ).json() + ).model_dump_json() ) - pub_injections.publish(current_data.injections.json()) + pub_injections.publish(current_data.injections.model_dump_json()) pub_available_power.publish( MeasurementArray( **xarray_to_dict(sim.get_available_pv()), time=current_timestamp, units="kWA", - ).json() + ).model_dump_json() ) if config.use_sparse_admittance: pub_load_y_matrix.publish( sparse_to_admittance_sparse( current_data.load_y_matrix, sim._AllNodeNames - ).json() + ).model_dump_json() ) else: pub_load_y_matrix.publish( @@ -475,7 +475,7 @@ def go_cosim( current_data.load_y_matrix.toarray() ), ids=sim._AllNodeNames, - ).json() + ).model_dump_json() ) logger.info("end time: " + str(datetime.now())) diff --git a/LocalFeeder/server.py b/LocalFeeder/server.py index 85032fc..a9f1167 100644 --- a/LocalFeeder/server.py +++ b/LocalFeeder/server.py @@ -33,12 +33,12 @@ async def timeout_middleware(request: Request, call_next): if endpoint == "sensor": response = ServerReply( detail="Request processing time exceeded limit. Upload a model and associated profiles before simulation before starting the simulation." - ).dict() + ).model_dump() return JSONResponse(response, 504) else: response = ServerReply( detail="Request processing time exceeded limit" - ).dict() + ).model_dump() return JSONResponse(response, 504) @@ -46,7 +46,7 @@ async def timeout_middleware(request: Request, call_next): def read_root(): hostname = socket.gethostname() host_ip = socket.gethostbyname(hostname) - response = HeathCheck(hostname=hostname, host_ip=host_ip).dict() + response = HeathCheck(hostname=hostname, host_ip=host_ip).model_dump() return JSONResponse(response, 200) @@ -83,7 +83,7 @@ async def upload_profiles(file: UploadFile): ) and os.path.exists(os.path.join(profile_path, "pv_profiles")): response = ServerReply( detail=f"File uploaded to server: {file.filename}" - ).dict() + ).model_dump() return JSONResponse(response, 200) else: HTTPException( @@ -116,7 +116,7 @@ async def upload_model(file: UploadFile): if os.path.exists(os.path.join(model_path, "master.dss")): response = ServerReply( detail=f"File uploaded to server: {file.filename}" - ).dict() + ).model_dump() return JSONResponse(response, 200) else: @@ -132,7 +132,7 @@ async def run_feeder( logging.info(broker_config) try: background_tasks.add_task(run_simulator, broker_config) - response = ServerReply(detail="Task sucessfully added.").dict() + response = ServerReply(detail="Task sucessfully added.").model_dump() return JSONResponse(response, 200) except Exception as e: @@ -152,7 +152,7 @@ async def configure(component_struct:ComponentStruct): json.dump(params , open(DefaultFileNames.STATIC_INPUTS.value, "w")) response = ServerReply( detail = f"Sucessfully updated configuration files." - ).dict() + ).model_dump() return JSONResponse(response, 200) if __name__ == "__main__": diff --git a/broker/requirements.txt b/broker/requirements.txt index 08474c4..6a3d2eb 100644 --- a/broker/requirements.txt +++ b/broker/requirements.txt @@ -2,6 +2,6 @@ helics>=3.4.0 pyyaml fastapi uvicorn -oedisi>=2.0.2,<3 +oedisi~=3.0 grequests python-multipart diff --git a/broker/server.py b/broker/server.py index 72f3ae5..c9e3428 100644 --- a/broker/server.py +++ b/broker/server.py @@ -73,7 +73,7 @@ def read_root(): hostname = socket.gethostname() host_ip = socket.gethostbyname(hostname) - response = HeathCheck(hostname=hostname, host_ip=host_ip).dict() + response = HeathCheck(hostname=hostname, host_ip=host_ip).model_dump() return JSONResponse(response, 200) @@ -99,7 +99,7 @@ async def upload_profiles(file: UploadFile): files = {"file": open(file.filename, "rb")} r = requests.post(url, files=files) - response = ServerReply(detail=r.text).dict() + response = ServerReply(detail=r.text).model_dump() return JSONResponse(response, r.status_code) raise HTTPException(status_code=404, detail="Unable to upload profiles") except Exception as e: @@ -128,7 +128,7 @@ async def upload_model(file: UploadFile): files = {"file": open(file.filename, "rb")} r = requests.post(url, files=files) - response = ServerReply(detail=r.text).dict() + response = ServerReply(detail=r.text).model_dump() return JSONResponse(response, r.status_code) raise HTTPException(status_code=404, detail="Unable to upload model") except Exception as e: @@ -222,7 +222,7 @@ def run_simulation(): async def run_feeder(background_tasks: BackgroundTasks): try: background_tasks.add_task(run_simulation) - response = ServerReply(detail="Task sucessfully added.").dict() + response = ServerReply(detail="Task sucessfully added.").model_dump() return JSONResponse({"detail": response}, 200) except Exception as e: err = traceback.format_exc() @@ -234,7 +234,7 @@ async def configure(wiring_diagram: WiringDiagram): global WIRING_DIAGRAM WIRING_DIAGRAM = wiring_diagram - json.dump(wiring_diagram.dict(), open(WIRING_DIAGRAM_FILENAME, "w")) + json.dump(wiring_diagram.model_dump(), open(WIRING_DIAGRAM_FILENAME, "w")) for component in wiring_diagram.components: component_model = ComponentStruct(component=component, links=[]) for link in wiring_diagram.links: @@ -244,14 +244,14 @@ async def configure(wiring_diagram: WiringDiagram): url = build_url(component.host, component.container_port, ["configure"]) logger.info(f"making a request to url - {url}") - r = requests.post(url, json=component_model.dict()) + r = requests.post(url, json=component_model.model_dump()) assert ( r.status_code == 200 ), f"POST request to update configuration failed for url - {url}" return JSONResponse( ServerReply( detail="Sucessfully updated config files for all containers" - ).dict(), + ).model_dump(), 200, ) diff --git a/errors.png b/errors.png index 6623ab1..26883a5 100644 Binary files a/errors.png and b/errors.png differ diff --git a/lindistflow_federate/opf_federate.py b/lindistflow_federate/opf_federate.py index 5d5aa39..4255508 100644 --- a/lindistflow_federate/opf_federate.py +++ b/lindistflow_federate/opf_federate.py @@ -112,7 +112,7 @@ def run(self) -> None: ) continue - topology = Topology.parse_obj(self.sub.topology.json) + topology = Topology.model_validate(self.sub.topology.json) [branch_info, bus_info] = adapter.extract_info(topology) slack = topology.slack_bus[0] @@ -120,14 +120,14 @@ def run(self) -> None: area_branch, area_bus = area_info(branch_info, bus_info, slack_bus) - voltages_mag = VoltagesMagnitude.parse_obj(self.sub.voltages_mag.json) + voltages_mag = VoltagesMagnitude.model_validate(self.sub.voltages_mag.json) area_bus = adapter.extract_voltages(area_bus, voltages_mag) time = voltages_mag.time logger.info(time) - injection = Injection.parse_obj(self.sub.injections.json) + injection = Injection.model_validate(self.sub.injections.json) area_bus = adapter.extract_injection(area_bus, injection) voltages, power_flow, control, conversion = lindistflow.optimal_power_flow( @@ -179,10 +179,10 @@ def run(self) -> None: logger.info(commands) if commands: - self.pub_commands.publish(CommandList(__root__=commands).json()) + self.pub_commands.publish(CommandList(root=commands).model_dump_json()) pub_mags = adapter.pack_voltages(voltages, time) - self.pub_voltages.publish(pub_mags.json()) + self.pub_voltages.publish(pub_mags.model_dump_json()) self.stop() diff --git a/lindistflow_federate/requirements.txt b/lindistflow_federate/requirements.txt index b17efad..8e0d757 100644 --- a/lindistflow_federate/requirements.txt +++ b/lindistflow_federate/requirements.txt @@ -1,8 +1,8 @@ helics>=3.4.0 -pydantic>=1.7,<2 +pydantic cvxpy numpy networkx -oedisi>=2,<3 +oedisi~=3.0 fastapi uvicorn diff --git a/lindistflow_federate/server.py b/lindistflow_federate/server.py index 1a94e4b..1bf3f41 100644 --- a/lindistflow_federate/server.py +++ b/lindistflow_federate/server.py @@ -25,7 +25,7 @@ def read_root(): host_ip = socket.gethostbyname(socket.gethostname() + ".local") except socket.gaierror: pass - response = HeathCheck(hostname=hostname, host_ip=host_ip).dict() + response = HeathCheck(hostname=hostname, host_ip=host_ip).model_dump() return JSONResponse(response, 200) @@ -35,7 +35,7 @@ async def run_model(broker_config: BrokerConfig, background_tasks: BackgroundTas federate = EchoFederate(broker_config) try: background_tasks.add_task(federate.run) - response = ServerReply(detail="Task sucessfully added.").dict() + response = ServerReply(detail="Task sucessfully added.").model_dump() return JSONResponse(response, 200) except Exception as _: err = traceback.format_exc() @@ -52,7 +52,7 @@ async def configure(component_struct: ComponentStruct): links[link.target_port] = f"{link.source}/{link.source_port}" json.dump(links, open(DefaultFileNames.INPUT_MAPPING.value, "w")) json.dump(params, open(DefaultFileNames.STATIC_INPUTS.value, "w")) - response = ServerReply(detail="Sucessfully updated configuration files.").dict() + response = ServerReply(detail="Sucessfully updated configuration files.").model_dump() return JSONResponse(response, 200) diff --git a/measuring_federate/generate_test_config.py b/measuring_federate/generate_test_config.py index a764a00..5e54001 100644 --- a/measuring_federate/generate_test_config.py +++ b/measuring_federate/generate_test_config.py @@ -229,5 +229,5 @@ class MeasurementConfig(BaseModel): voltage_ids=sample(BUSES, 3 * len(BUSES) // 4), real_power_ids=sample(BUSES, 3 * len(BUSES) // 4), reactive_power_ids=sample(BUSES, 3 * len(BUSES) // 4), - ).json() + ).model_dump_json() ) diff --git a/measuring_federate/measuring_federate.py b/measuring_federate/measuring_federate.py index e5742ac..1fcc739 100644 --- a/measuring_federate/measuring_federate.py +++ b/measuring_federate/measuring_federate.py @@ -122,9 +122,9 @@ def run(self): logger.info("start time: " + str(datetime.now())) json_data = self.sub_measurement.json if "equipment_ids" in json_data: - measurement = EquipmentNodeArray.parse_obj(json_data) + measurement = EquipmentNodeArray.model_validate(json_data) else: - measurement = MeasurementArray.parse_obj(json_data) + measurement = MeasurementArray.model_validate(json_data) with open(self.measurement_file, "r") as fp: self.measurement = json.load(fp) @@ -132,7 +132,7 @@ def run(self): logger.debug("measured transformed") logger.debug(measurement_transformed) - self.pub_measurement.publish(measurement_transformed.json()) + self.pub_measurement.publish(measurement_transformed.model_dump_json()) granted_time = h.helicsFederateRequestTime(self.vfed, h.HELICS_TIME_MAXTIME) logger.info("end time: " + str(datetime.now())) diff --git a/measuring_federate/requirements.txt b/measuring_federate/requirements.txt index a2b7050..8c78892 100644 --- a/measuring_federate/requirements.txt +++ b/measuring_federate/requirements.txt @@ -7,4 +7,4 @@ fastapi uvicorn requests grequests -oedisi>=2.0.2,<3 +oedisi~=3.0 diff --git a/measuring_federate/server.py b/measuring_federate/server.py index f3632d3..50c30de 100644 --- a/measuring_federate/server.py +++ b/measuring_federate/server.py @@ -34,7 +34,7 @@ async def read_root(): response = HeathCheck( hostname = hostname, host_ip = host_ip - ).dict() + ).model_dump() return JSONResponse(response, 200) @app.post("/run") @@ -57,7 +57,7 @@ async def run_model(broker_config:BrokerConfig, background_tasks: BackgroundTask background_tasks.add_task(run_simulator, broker_config) response = ServerReply( detail = f"Task sucessfully added." - ).dict() + ).model_dump() return JSONResponse(response, 200) except Exception as e: err = traceback.format_exc() @@ -75,7 +75,7 @@ async def configure(component_struct:ComponentStruct): json.dump(params , open(DefaultFileNames.STATIC_INPUTS.value, "w")) response = ServerReply( detail = f"Sucessfully updated configuration files." - ).dict() + ).model_dump() return JSONResponse(response, 200) if __name__ == "__main__": diff --git a/omoo_federate/OMOO.py b/omoo_federate/OMOO.py index df7e35c..25f6a39 100644 --- a/omoo_federate/OMOO.py +++ b/omoo_federate/OMOO.py @@ -558,7 +558,7 @@ def run(self): # granted_time = h.helicsFederateRequestTime(self.vfed, h.HELICS_TIME_MAXTIME) granted_time = h.helicsFederateRequestTime(self.vfed, 1000) - topology = Topology.parse_obj(self.sub_topology.json) + topology = Topology.model_validate(self.sub_topology.json) ids = topology.base_voltage_magnitudes.ids logger.info("Topology has been read") slack_index = None @@ -612,8 +612,8 @@ def run(self): ) continue - voltages_real = VoltagesReal.parse_obj(self.sub_voltages_real.json) - voltages_imag = VoltagesImaginary.parse_obj( + voltages_real = VoltagesReal.model_validate(self.sub_voltages_real.json) + voltages_imag = VoltagesImaginary.model_validate( self.sub_voltages_imaginary.json ) voltages = measurement_to_xarray( @@ -622,7 +622,7 @@ def run(self): logger.debug(np.max(np.abs(voltages) / v)) assert topology.base_voltage_magnitudes.ids == list(voltages.ids.data) - injections = Injection.parse_obj(self.injections.json) + injections = Injection.model_validate(self.injections.json) power_injections = eqarray_to_xarray( injections.power_real ) + 1j * eqarray_to_xarray(injections.power_imaginary) @@ -631,7 +631,7 @@ def run(self): ] _, pv_injections = xr.align(pv_ratings, pv_injections) available_power = measurement_to_xarray( - MeasurementArray.parse_obj(self.sub_available_power.json) + MeasurementArray.model_validate(self.sub_available_power.json) ) split_power = available_power / pv_injections.ids.groupby( @@ -662,8 +662,8 @@ def run(self): logger.debug("PVframe") logger.debug(pv) - power_P = PowersReal.parse_obj(self.sub_power_P.json) - power_Q = PowersImaginary.parse_obj(self.sub_power_Q.json) + power_P = PowersReal.model_validate(self.sub_power_P.json) + power_Q = PowersImaginary.model_validate(self.sub_power_Q.json) assert topology.base_voltage_magnitudes.ids == power_P.ids assert topology.base_voltage_magnitudes.ids == power_Q.ids ts = time.time() @@ -720,7 +720,7 @@ def run(self): power_set_xr.values[i].imag, ) ) - command_list_obj = CommandList(__root__=command_list) + command_list_obj = CommandList(root=command_list) logger.debug(command_list_obj) # Turn P_set and Q_set into commands if set_power: @@ -751,9 +751,9 @@ def destroy(self): config = json.load(f) federate_name = config["name"] if "algorithm_parameters" in config: - parameters = OMOOParameters.parse_obj(config["algorithm_parameters"]) + parameters = OMOOParameters.model_validate(config["algorithm_parameters"]) else: - parameters = OMOOParameters.parse_obj({}) + parameters = OMOOParameters.model_validate({}) with open("input_mapping.json") as f: input_mapping = json.load(f) diff --git a/opf_analysis.py b/opf_analysis.py index 3d5346b..ad6e35e 100644 --- a/opf_analysis.py +++ b/opf_analysis.py @@ -20,7 +20,8 @@ def extract_data(path): voltage_real = pd.read_feather(join(path, "voltage_real.feather")) voltage_imag = pd.read_feather(join(path, "voltage_imag.feather")) - topology = Topology.parse_file(join(path, "topology.json")) + with open(join(path, "topology.json")) as f: + topology = Topology.model_validate_json(f.read()) base_voltage_magnitudes = np.array(topology.base_voltage_magnitudes.values) diff --git a/post_analysis.py b/post_analysis.py index b8b6837..9552031 100644 --- a/post_analysis.py +++ b/post_analysis.py @@ -26,7 +26,7 @@ ) with open(os.path.join(args.directory, "topology.json")) as f: - topology = Topology.parse_obj(json.load(f)) + topology = Topology.model_validate(json.load(f)) base_voltage_df = pd.DataFrame( { "id": topology.base_voltage_magnitudes.ids, diff --git a/recorder/requirements.txt b/recorder/requirements.txt index 16b5310..0fe9bfa 100644 --- a/recorder/requirements.txt +++ b/recorder/requirements.txt @@ -5,4 +5,4 @@ numpy pandas fastapi uvicorn -oedisi>=2.0.2,<3 +oedisi~=3.0 diff --git a/recorder/server.py b/recorder/server.py index 8e5249d..0313fbf 100644 --- a/recorder/server.py +++ b/recorder/server.py @@ -25,7 +25,7 @@ def read_root(): hostname = socket.gethostname() host_ip = socket.gethostbyname(hostname) - response = HeathCheck(hostname=hostname, host_ip=host_ip).dict() + response = HeathCheck(hostname=hostname, host_ip=host_ip).model_dump() return JSONResponse(response, 200) @@ -51,7 +51,7 @@ async def run_model(broker_config: BrokerConfig, background_tasks: BackgroundTas logging.info(broker_config) try: background_tasks.add_task(run_simulator, broker_config) - response = ServerReply(detail="Task sucessfully added.").dict() + response = ServerReply(detail="Task sucessfully added.").model_dump() return JSONResponse(response, 200) except Exception as e: err = traceback.format_exc() @@ -70,7 +70,7 @@ async def configure(component_struct:ComponentStruct): json.dump(params , open(DefaultFileNames.STATIC_INPUTS.value, "w")) response = ServerReply( detail = f"Sucessfully updated configuration files." - ).dict() + ).model_dump() return JSONResponse(response, 200) if __name__ == "__main__": diff --git a/requirements.txt b/requirements.txt index 1d5814f..5bf6c69 100644 --- a/requirements.txt +++ b/requirements.txt @@ -3,7 +3,7 @@ scipy matplotlib numpy pandas -oedisi>=2.0.2,<3 +oedisi~=3.0 helics>=3.6.1 -r recorder/requirements.txt -r LocalFeeder/requirements.txt diff --git a/voltage_angles_0.png b/voltage_angles_0.png index ec48f80..7e8cdc3 100644 Binary files a/voltage_angles_0.png and b/voltage_angles_0.png differ diff --git a/voltage_angles_95.png b/voltage_angles_95.png index 7334b6c..da61c74 100644 Binary files a/voltage_angles_95.png and b/voltage_angles_95.png differ diff --git a/voltage_magnitudes_0.png b/voltage_magnitudes_0.png index 9d1cc91..f08aef8 100644 Binary files a/voltage_magnitudes_0.png and b/voltage_magnitudes_0.png differ diff --git a/voltage_magnitudes_95.png b/voltage_magnitudes_95.png index cc13493..09654f0 100644 Binary files a/voltage_magnitudes_95.png and b/voltage_magnitudes_95.png differ diff --git a/wls_federate/requirements.txt b/wls_federate/requirements.txt index db123a4..3a2a356 100644 --- a/wls_federate/requirements.txt +++ b/wls_federate/requirements.txt @@ -4,4 +4,4 @@ scipy numpy fastapi uvicorn -oedisi>=2.0.2,<3 +oedisi~=3.0 diff --git a/wls_federate/server.py b/wls_federate/server.py index c907802..01302fa 100644 --- a/wls_federate/server.py +++ b/wls_federate/server.py @@ -22,7 +22,7 @@ def read_root(): response = HeathCheck( hostname=hostname, host_ip=host_ip - ).dict() + ).model_dump() return JSONResponse(response, 200) @@ -33,7 +33,7 @@ async def run_model(broker_config: BrokerConfig, background_tasks: BackgroundTas background_tasks.add_task(run_simulator, broker_config) response = ServerReply( detail="Task sucessfully added." - ).dict() + ).model_dump() return JSONResponse(response, 200) except Exception as e: err = traceback.format_exc() @@ -52,7 +52,7 @@ async def configure(component_struct:ComponentStruct): json.dump(params , open(DefaultFileNames.STATIC_INPUTS.value, "w")) response = ServerReply( detail = f"Sucessfully updated configuration files." - ).dict() + ).model_dump() return JSONResponse(response, 200) if __name__ == "__main__": diff --git a/wls_federate/state_estimator_federate.py b/wls_federate/state_estimator_federate.py index 6d26ca5..850342e 100644 --- a/wls_federate/state_estimator_federate.py +++ b/wls_federate/state_estimator_federate.py @@ -126,12 +126,11 @@ def get_indices(topology, measurement): class AlgorithmParameters(BaseModel): + model_config = {"use_enum_values": True} + tol: float = 5e-7 base_power: Optional[float] = 100.0 - class Config: - use_enum_values = True - def state_estimator( parameters: AlgorithmParameters, @@ -290,7 +289,7 @@ def run(self): self.initial_ang = None self.initial_V = None - topology = Topology.parse_obj(self.sub_topology.json) + topology = Topology.model_validate(self.sub_topology.json) ids = topology.base_voltage_magnitudes.ids logger.info("Topology has been read") slack_index = None @@ -312,9 +311,9 @@ def run(self): logger.info("start time: " + str(datetime.now())) - voltages = VoltagesMagnitude.parse_obj(self.sub_voltages_magnitude.json) - power_P = PowersReal.parse_obj(self.sub_power_P.json) - power_Q = PowersImaginary.parse_obj(self.sub_power_Q.json) + voltages = VoltagesMagnitude.model_validate(self.sub_voltages_magnitude.json) + power_P = PowersReal.model_validate(self.sub_power_P.json) + power_Q = PowersImaginary.model_validate(self.sub_power_Q.json) knownV = get_indices(topology, voltages) if self.initial_V is None: @@ -347,12 +346,12 @@ def run(self): self.pub_voltage_mag.publish( VoltagesMagnitude( values=list(voltage_magnitudes), ids=ids, time=voltages.time - ).json() + ).model_dump_json() ) self.pub_voltage_angle.publish( VoltagesAngle( values=list(voltage_angles), ids=ids, time=voltages.time - ).json() + ).model_dump_json() ) logger.info("end time: " + str(datetime.now())) @@ -372,9 +371,9 @@ def run_simulator(broker_config: BrokerConfig): config = json.load(f) federate_name = config["name"] if "algorithm_parameters" in config: - parameters = AlgorithmParameters.parse_obj(config["algorithm_parameters"]) + parameters = AlgorithmParameters.model_validate(config["algorithm_parameters"]) else: - parameters = AlgorithmParameters.parse_obj({}) + parameters = AlgorithmParameters.model_validate({}) with open("input_mapping.json") as f: input_mapping = json.load(f) diff --git a/wls_federate/tests/make_test_data.py b/wls_federate/tests/make_test_data.py index e7f8319..d4fcd39 100644 --- a/wls_federate/tests/make_test_data.py +++ b/wls_federate/tests/make_test_data.py @@ -17,7 +17,7 @@ def load_timestep(filename, timestep): def write_test_data(outputsdir, targetdir, timestep): - topology = Topology.parse_file(outputsdir / "topology.json") + topology = Topology.model_validate_json((outputsdir / "topology.json").read_text()) power_real = load_timestep(outputsdir / "measured_power_real.feather", timestep) power_imag = load_timestep(outputsdir / "measured_power_imag.feather", timestep) voltage_mag = load_timestep( @@ -27,17 +27,17 @@ def write_test_data(outputsdir, targetdir, timestep): voltage_imag = load_timestep(outputsdir / "voltage_imag.feather", timestep) with open(targetdir / "topology.json", "w") as f: - f.write(topology.json()) + f.write(topology.model_dump_json()) with open(targetdir / "power_real.json", "w") as f: - f.write(PowersReal(**power_real, equipment_ids=[]).json()) + f.write(PowersReal(**power_real, equipment_ids=[]).model_dump_json()) with open(targetdir / "power_imag.json", "w") as f: - f.write(PowersImaginary(**power_imag, equipment_ids=[]).json()) + f.write(PowersImaginary(**power_imag, equipment_ids=[]).model_dump_json()) with open(targetdir / "voltage_magnitude.json", "w") as f: - f.write(VoltagesMagnitude(**voltage_mag).json()) + f.write(VoltagesMagnitude(**voltage_mag).model_dump_json()) with open(targetdir / "voltage_real.json", "w") as f: - f.write(VoltagesReal(**voltage_real).json()) + f.write(VoltagesReal(**voltage_real).model_dump_json()) with open(targetdir / "voltage_imaginary.json", "w") as f: - f.write(VoltagesImaginary(**voltage_imag).json()) + f.write(VoltagesImaginary(**voltage_imag).model_dump_json()) test_data_dir = "wls_federate/tests/small_smartds_tap_time_3" diff --git a/wls_federate/tests/test_state_estimator.py b/wls_federate/tests/test_state_estimator.py index ded4cfc..6d92a41 100644 --- a/wls_federate/tests/test_state_estimator.py +++ b/wls_federate/tests/test_state_estimator.py @@ -72,29 +72,32 @@ def small_smartds_tap_time_40(): def get_topology(directory): - return Topology.parse_file(os.path.join(directory, "topology.json")) + with open(os.path.join(directory, "topology.json")) as f: + return Topology.model_validate_json(f.read()) def get_measurements(directory): - return ( - PowersReal.parse_file(os.path.join(directory, "power_real.json")), - PowersImaginary.parse_file(os.path.join(directory, "power_imag.json")), - VoltagesMagnitude.parse_file(os.path.join(directory, "voltage_magnitude.json")), - ) + with open(os.path.join(directory, "power_real.json")) as f: + power_real = PowersReal.model_validate_json(f.read()) + with open(os.path.join(directory, "power_imag.json")) as f: + power_imag = PowersImaginary.model_validate_json(f.read()) + with open(os.path.join(directory, "voltage_magnitude.json")) as f: + voltage_mag = VoltagesMagnitude.model_validate_json(f.read()) + return (power_real, power_imag, voltage_mag) @pytest.fixture() def sparse_topology(): - return Topology.parse_file( - os.path.join(TEST_DIR, "ieee123data", "sparse_topology.json") - ) + with open(os.path.join(TEST_DIR, "ieee123data", "sparse_topology.json")) as f: + return Topology.model_validate_json(f.read()) def get_actuals(directory): - return ( - VoltagesReal.parse_file(os.path.join(directory, "voltage_real.json")), - VoltagesImaginary.parse_file(os.path.join(directory, "voltage_imaginary.json")), - ) + with open(os.path.join(directory, "voltage_real.json")) as f: + voltage_real = VoltagesReal.model_validate_json(f.read()) + with open(os.path.join(directory, "voltage_imaginary.json")) as f: + voltage_imag = VoltagesImaginary.model_validate_json(f.read()) + return (voltage_real, voltage_imag) def inner_args(parameters, topology, measurements):