Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Teresadev #14

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open

Teresadev #14

wants to merge 2 commits into from

Conversation

Tlabting
Copy link

@Tlabting Tlabting commented Aug 3, 2023

Adding ZXY6005S Powersupply Driver

Copy link
Member

@dmitri-mcguckin dmitri-mcguckin left a comment

Choose a reason for hiding this comment

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

In general looks fine.

I would recommend moving any code to the src/ directory so it's organized a bit more and can later be grouped into a callable python module.

Left other comments to be addressed as well.

from enum import Enum

class Commands(Enum):
'''Get power supply unit model. Response: ZXY-6005S'''
Copy link
Member

Choose a reason for hiding this comment

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

The syntax of ''' qutations in a row are usually reserved for python docstrings.

For inline comments use #

Suggested for line 12 and similar scenarios:

MODEL = 'a'  # Get power supply unit model. Response: ZXY-6005S

import serial.tools.list_ports
from enum import Enum

class Commands(Enum):
Copy link
Member

Choose a reason for hiding this comment

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

See comment on the power supply class for in-depth detail on docstrings, but for Enums specifically, it looks nicer if the Enum pairs are defined in one doctring like so:

class Commands(Enum):
    '''
    :param MODEL: Description of param
    :type MODEL: str
    '''

SET_OUTPUT = 'so'


class ZXY6005S:
Copy link
Member

Choose a reason for hiding this comment

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

Docstrings in general are greatly encouraged for:

  1. Public Functions (which are by default all functions in python)
  2. Class Definitions

Suggested add for this class and similar definitions

class ZXY6005S:
    '''
    A short description of what the class does.

    :param MODEL: Get power supply unit model. Response: ZXY-6005S
    :param FIRMWARE_VERSION: Get firmware version. Response: R2.7Z
    '''
    
    def __some_function__(param1, param2) -> int:
        '''
        A short description of what the function does.
        
        :param param1: Description of param1
        :param param2: Description of param2
        :returns: Description of what is returned
        :rtype: int
        ''''
    ...

STOPBITS = serial.STOPBITS_ONE
TIMEOUT = 1

def __init__(self):
Copy link
Member

@dmitri-mcguckin dmitri-mcguckin Nov 8, 2023

Choose a reason for hiding this comment

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

Is this class intended to manage the state of all three power supplies at the same time? Or just one supply and have three instances?

Personally, I would recommend the latter of the two because this scopes the purpose of the class and you can use handy things in client code such as:

for p in [supply_1, supply_2, supply_3]:
    p.send_command(...)

TIMEOUT = 1

def __init__(self):
'''construct objects, using location for X, Y, and Z power supplies'''
Copy link
Member

Choose a reason for hiding this comment

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

It is also recommended that parameters such as device location/name is a configurable item for the constructor as this could change with different supplies or different environment configurations. It is also acceptable to add defaults to the initializers if they are generic settings that may be the same across environments.

Example:

def __init__(self, dev_1: str = '/dev/TTYUSBS10'):
    ...

timeout = self.TIMEOUT,
)

def write_message(self, device_name, msg):
Copy link
Member

@dmitri-mcguckin dmitri-mcguckin Nov 8, 2023

Choose a reason for hiding this comment

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

Since this object seems to be a stateful object It may make sense to store the device name as an attribute on the object so it can be omitted as a parameter here.

Same applies to all similar functions below.

self.write_message(device_name, msg)
return self.read_message(device_name)

def create_command(self, command):
Copy link
Member

@dmitri-mcguckin dmitri-mcguckin Nov 8, 2023

Choose a reason for hiding this comment

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

This is actually excellent that you've separated the command generation from the command sending.

The core functionality of this class, (i.e. directly communicating with the power supply on a serial channel), is not really unit-testable. However the most important part that we can unit-test is making sure that the commands are being generated correctly per the power-supply spec.

I would recommend making a set of unit tests around this function asserting that this function generates all of the correct things else fails safely in a way that will stop it from being sent to the PSU otherwise.

if reply != msg.decode().strip():
raise ValueError(f'Invalid reply was {reply}, expected {msg.decode().strip()}')

def return_amp_hour(self, device_name: str) -> str:
Copy link
Member

Choose a reason for hiding this comment

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

For getters and setters I would recommend either the verbiage get/set or if you wanted to get fancy, (and more pythonic), you could also do:

@amp_hour.setter
def amp_hour(self, value) -> None:
    <methods to set value>
    
@amp_hour.getter
def amp_hour() -> str:
    return <value>

So that calling code would look like:

supply_1.amp_hour = '1.3'
print(supply_1.amp_hour)

@dmitri-mcguckin dmitri-mcguckin mentioned this pull request Nov 8, 2023
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.

2 participants