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

Support for \x1b escape characters #7

Closed
gijsn opened this issue Dec 5, 2023 · 5 comments
Closed

Support for \x1b escape characters #7

gijsn opened this issue Dec 5, 2023 · 5 comments
Assignees
Labels
enhancement New feature or request

Comments

@gijsn
Copy link

gijsn commented Dec 5, 2023

According to the manual, section 7, any USB control characters like '+' and 'ESC' that are used as data and not for control need to be additionally escaped by the escape character \x1b. Is there a way to logically implement the support for such escape sequences?

Thanks

@Stefanhg
Copy link
Owner

Stefanhg commented Dec 6, 2023

I would assume it could be done in a pretty easy way by simply just checking if either of those characters are in the data and then just add it to the data written.

I might have to do a good overhaul of this library when I fix this, it surely would do it good to match PEP8. Some Python experience has been gained since I started this.

Do you think this is sufficient? If not please provide some actual data where the characters are needed and included, then I can also make some testcases for this.

def write(self, data):
    if '+' in data or 'ESC' in data:
        data += "\x1b"
    
    if(currentGPIB != self.resourceAddress):
        self.selectAddress(self.resourceAddress)
    GPIBcom.write((data + "\n").encode())

@gijsn
Copy link
Author

gijsn commented Dec 6, 2023

Thanks for the fast reply and sorry for the confusion, with ESC, I meant the escape character 27, sometimes refered to as CTRL+[ or x\1b

I was thinking more along the lines of:

def write(self, data):
   data = data.replace('\x1b', '\x1b\x1b')
   data = data.replace('+', '\x1b+')
    
    if(currentGPIB != self.resourceAddress):
        self.selectAddress(self.resourceAddress)
    GPIBcom.write((data + "\n").encode())

lmk

@Stefanhg
Copy link
Owner

Stefanhg commented Dec 6, 2023

Hello.

Yeah you are right. Some additional characters are needed!
I have rewritten a good amount of the code. I found my dusty GPIBPrologix and gave it a go with a few testcases and it worked.
Does this work for you? If so then i will commit it soon!

import logging
import serial

logger = logging.getLogger(__name__)


class ResourceManager:
    """
    Controls the resources of the GpibPrologix
    """
    active_address = None
    """ Stores the active selected address """

    def __init__(self, comport, read_timeout_ms=1000, baud=115200, timeout=2):
        """
        Initializes the resource manager of the GpibPrologix
        :param comport: comport of the device. Example COM8, ttyS0
        :param read_timeout_ms: Read timeout of the GPIBPrologix in milliseconds
        :param baud: Baudrate of the GPIBPrologix.
        :param timeout: Timeout of Serial interface
        """
        logger.debug(f"Opening serial resource")
        self.inst = serial.Serial(comport, baudrate=baud, timeout=timeout)
        self.inst.write(f"++read_tmo_ms {read_timeout_ms}\n".encode())

    def open_resource(self, address):
        """
        Opens the resource and returns
        """
        return self.GpibPrologix(self.inst, address)

    def close(self):
        """
        Closes the opened object
        """
        self.inst.close()
        self.inst = None

    class GpibPrologix:

        def __init__(self, inst, address):
            self.address = address
            self.inst = inst

        def _select_address(self):
            """
            Selects which address objects uses if address is not already selected
            """
            if self.address != ResourceManager.active_address:
                logger.debug(f"selecting address {self.address}")
                self.inst.write(f"++addr {self.address}\n".encode())
                ResourceManager.active_address = self.address

        def write(self, data):
            """
            Write data to GPIB.
            Method ensures the correct address is selected when writing to target.
            :param data: Data to send
            :return:
            """
            logger.debug(f"Sending {data}")
            # section 7 of GPIB prologix's manual describes having to additional characters for
            # characters with escape code


            data = (data.replace('\x0A', '\x1b\x0A').replace('\x1D', '\x1b\x0D')
                    .replace('\x1b', '\x1b\x1b').replace('\x2b', '\x1b\x2b+'))
            data = f"{data}\n".encode()
            self._select_address()
            self.inst.write(data)

        def read(self) -> str:
            """
            Reads the next line of data available and returns it.
            """

            self.inst.write(b"++read eoi\n")
            data = self.inst.readline().decode('utf-8').rstrip()
            logger.debug(f"Read {data}")
            return data

        def query(self, data: str) -> str:
            """
            Send data and wait for data to return.
            :param data: Data to send
            :return:
            """
            self.write(data)
            return self.read()

@Stefanhg
Copy link
Owner

@gijsn Any updates on this?

@Stefanhg Stefanhg self-assigned this Dec 22, 2023
@Stefanhg Stefanhg added the enhancement New feature or request label Dec 22, 2023
@Stefanhg
Copy link
Owner

I have released a 0.1.1 and closing the issue.
Feel free to give me an update if the release does not work.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants