Skip to content

Proxy Instruments#46

Merged
Benjamin-Nussbaum merged 53 commits into
masterfrom
feature/proxy-instruments
Dec 21, 2024
Merged

Proxy Instruments#46
Benjamin-Nussbaum merged 53 commits into
masterfrom
feature/proxy-instruments

Conversation

@marcosfrenkel
Copy link
Copy Markdown
Collaborator

Opening the PR as draft since I am encountering some mypy issues that will require a little more syntax noodling before the code is ready, the big picture idea and structure should not change however.

The idea of a Proxy instrument is that when using a remote resource in the network, a client can simply ask for a device from a node and a ProxyInstrument is created on the client side. This ProxyInstrument should behave as if the instrument is running locally to the user but in the background it asks whatever router that client was talking to send CONTROL packets to a node that then executes them.

To test it again simply run the router.py, node.py, and client.py in that order in your computer.

I have tested it with the rotator working through the PI and I was able to control the pi without having to ssh into it.

I am not convinced that the ProxyInstrument and InstrumentClient should live in the same client.py but I was having some import errors so I left them there for now.

marcosfrenkel and others added 30 commits September 5, 2024 14:52
…ct in the testing notebook. Did some modification to base driver
…struments

# Conflicts:
#	src/pqnstack/base/errors.py
@marcosfrenkel
Copy link
Copy Markdown
Collaborator Author

@Benjamin-Nussbaum @SoroushHoseini I have just pushed the mypy and ruff clean up so this PR is ready for a review.

I expect some pushback on some of the things here, we can discuss this in the software meeting if this is too little time for a proper review beforehand since it is also a big PR

@marcosfrenkel marcosfrenkel changed the title [DRAFT] Proxy Instruments Proxy Instruments Nov 14, 2024
# Conflicts:
#	src/pqnstack/base/driver.py
#	src/pqnstack/base/errors.py
#	src/pqnstack/network/client.py
#	src/pqnstack/network/node.py
#	tests/messaging/client.py
#	tests/messaging/node.py
Comment thread src/pqnstack/network/client.py Outdated

class InstrumentClient(ClientBase):
def __init__(
self, name: str, host: str, port: int | str, router_name: str, instrument_name: str, node_name: str
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Standardize type of port to one of int or str, not a union of both. I suggest int since the port is always just a number. (Python stdlib also uses int for ports)

Comment thread src/pqnstack/network/client.py Outdated
def trigger_operation(self, operation: str, *args, **kwargs) -> Any:
packet = Packet(
intent=PacketIntent.CONTROL,
request=str(self.instrument_name) + ":OPERATION:" + operation,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

instrument_name is supplied as a str in the constructor - the explicit str() call seems unnecessary.

Comment thread src/pqnstack/network/client.py Outdated
Comment on lines +144 to +157
def trigger_parameter(self, parameter: str, *args, **kwargs) -> Any:
packet = Packet(
intent=PacketIntent.CONTROL,
request=str(self.instrument_name) + ":PARAMETER:" + parameter,
source=self.name,
destination=self.node_name,
payload=(args, kwargs),
)
response = self.ask(packet)
if response is None:
msg = "No response received."
raise PacketError(msg)

return response.payload
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Quite similar to the operation code - one route to fix would be separating creation/use of the Packets.

Comment thread src/pqnstack/network/client.py Outdated
Comment on lines +167 to +170
response = self.ask(packet)
if response is None:
msg = "No response received."
raise PacketError(msg)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it be a bad idea to put this None check inside ask()?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did this now, the only change that this means is that when a timeout error happens it is raised instead of returning None. Now those checks are not necessary anymore

Comment thread src/pqnstack/network/client.py Outdated
Comment on lines +179 to +195
class ProxyInstrument(DeviceDriver):
"""The address here is the zmq address of the router that the InstrumentClient will talk to."""

DEVICE_CLASS = DeviceClass.PROXY

def __init__(
self,
name: str,
desc: str,
address: str,
host: str,
port: str,
node_name: str,
router_name: str,
parameters: set[str],
operations: dict[str, Callable],
) -> None:
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like a lot of arguments to initialize a ProxyInstrument - are they all needed?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They kinda are. I can merge host and port but then I would need to separate them by code for the client. Same with parameters and operations, I already have those when I ask the server for them, I don't need to have them there but they would add an extra call to the server.

If those things are ok, I can implement those changes

Comment thread src/pqnstack/network/node.py Outdated
Comment on lines +196 to +202
return Packet(
intent=PacketIntent.ERROR,
request="ERROR",
source=self.name,
destination=packet.source,
payload=f"Instrument '{packet.payload}' not found.",
)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It might be a good idea to create a wrapper function that returns error Packets so only the destination and payload are needed here.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lots of logic handling instrument control - compacting the Packet creation will help make it more digestible, but it might also be worth separating out the logic to handle each request_type in its own function.

@Benjamin-Nussbaum Benjamin-Nussbaum force-pushed the feature/proxy-instruments branch from 8d258b9 to 95d4693 Compare December 21, 2024 00:05
@Benjamin-Nussbaum Benjamin-Nussbaum merged commit 98aac77 into master Dec 21, 2024
@Benjamin-Nussbaum Benjamin-Nussbaum deleted the feature/proxy-instruments branch December 21, 2024 00:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants