Skip to content

Conversation

@erikamundson
Copy link

@erikamundson erikamundson commented Jan 23, 2024

Hi all, could use some help here.

Have been attempting to implement the JumpChannel command but am currently stuck getting socket timeout errors (am able to run the already existing commands with no issue).

Error message:

Timeout on receiving message from Arbin!
Traceback (most recent call last):
  File "<fp>\pycti\pyctiarbin\cycler_interface.py", line 132, in _send_receive_msg
    rx_msg += self.__sock.recv(self.__config.msg_buffer_size)
TimeoutError: timed out

Any help or pointers would be appreciated. Thanks!

@erikamundson erikamundson marked this pull request as draft January 23, 2024 00:44
@chintanp
Copy link
Contributor

chintanp commented Jan 27, 2024

@erikamundson thank you for submitting the PR. We do not have spare channels at the moment to test the jump_step functionality, but I was able to find an old code that worked at the time:

def jump_step(self, str_step):
        """
        Commands a jump to a specific step type in the schedule.

        Args:
            str_step (str): Any of the keys in schedule_step_idx("rest", "charge", "discharge", "voltage")

        Returns:
            int: 0 if successful otherwise the error code returned by the cycler.
        """
        msg = bytearray([])
        msg += struct.pack('<Q', header)
        msg += struct.pack('<L', 4+4+4+4+101+2)
        msg += struct.pack('<LL', command_codes["SCHEDULE_JUMP"], 0x00000000)

        # Step index
        msg += struct.pack('<L', schedule_step_idx[str_step] - 1)
        # Channel to stop
        msg += struct.pack('<L', self.chan_num - 1)
        msg += bytearray([0x00 for i in range(101)])
        msg += struct.pack('<H', sum(msg))

        resp = self.func_socket(msg)

        idx = 8
        data_len = struct.unpack('<L', resp[idx:idx+4])[0]
        if data_len != 128:
            return -1
        elif data_len != len(resp):
            return -1
        idx += 4
        return_cmd = struct.unpack('<L', resp[idx:idx+4])[0]
        idx += 4+4
        ch_idx = struct.unpack('<L', resp[idx:idx+4])[0]
        idx += 4
        result = struct.unpack('<B', resp[idx:idx+1])[0]
        idx += 1

        if result == 0:
            program_logger.info("Jumped to step {} on channel {}.".format(str_step, self.chan_num))
        elif result == 0x26:
            program_logger.critical("Jumping to step {} on channel {} failed with error code {}: safety check failed.".format(str_step, self.chan_num, result))
        else:
            program_logger.error("Jumping to step {} on channel {} failed with error code {}.".format(str_step, self.chan_num, result))
            if result == 18:
                    program_logger.error("Exiting!.")
                    sys.exit(18)
        return result

This is not class based and is a bit basic, but can potentially be helpful to debug? Please let me know if this works or not and we can try to implement this in class-based version of pycti.

Though, since your error is timeout related, I am not sure if the implementation itself is the culprit. Can you describe your setup a bit? The version of MITS Pro, whether you are running this from the same machine as the cycler computer, etc.

@erikamundson
Copy link
Author

erikamundson commented Jan 29, 2024

@chintanp Thanks for the response.

I'm having a hard time testing that code since it looks like it's part of a class that I don't have access to. I did try updating the message length and byte formats to match that function and the timeout still occurs.

Though, since your error is timeout related, I am not sure if the implementation itself is the culprit. Can you describe your setup a bit? The version of MITS Pro, whether you are running this from the same machine as the cycler computer, etc.

We're running MITS Pro version MITS8 202103, which I believe does have the jump command based on the CTI instructions given to us by Arbin (using the C# DLL). I am testing this from the same computer that's running the MITS software.

The code I'm using to test is:

if __name__ == '__main__':
    CHANNEL_INTERFACE_CONFIG = CYCLER_INTERFACE_CONFIG.copy()
    CHANNEL_INTERFACE_CONFIG["channel"] = 25
    channel_interface = ChannelInterface(CHANNEL_INTERFACE_CONFIG)

    print(channel_interface.read_channel_status())
    response = channel_interface.jump_channel(2)
    print(response)

The channel_interface.read_channel_status() works correctly and prints the expected info, but the jump_channel command runs into a timeout (I tried increasing it to 60s and it still times out).

@chintanp
Copy link
Contributor

Will try jumping channel this week and get back to you. Just to make sure you are trying to "jump to the next step", correct? Maybe renaming the function will make the intent clearer.

@erikamundson
Copy link
Author

erikamundson commented Jan 30, 2024

Will try jumping channel this week and get back to you. Just to make sure you are trying to "jump to the next step", correct? Maybe renaming the function will make the intent clearer.

Yes, it is supposed to jump to the given step ID as defined by the schedule file. I named the function jump_channel since the CTI protocol calls it "THIRD_PARTY_JUMP_CHANNEL", but something like jump_to_step might be a better name.

@erikamundson
Copy link
Author

Hi @chintanp were you able to find some time to test out the jump functionality?

@chintanp
Copy link
Contributor

Hi @chintanp were you able to find some time to test out the jump functionality?

@erikamundson a few people working on this are out sick, unfortunately I dont have a expected date on this. Could you tell a little more whey you need the jump functionality? We found this to be rather flaky in our first implementation and therefore didnt implement it this time around.

@erikamundson
Copy link
Author

erikamundson commented Feb 26, 2024

@erikamundson a few people working on this are out sick, unfortunately I dont have a expected date on this. Could you tell a little more whey you need the jump functionality? We found this to be rather flaky in our first implementation and therefore didnt implement it this time around.

No worries, there's no big rush for us and we can use the provided C# DLL temporarily if we need to.

Our main use case is remote intervention in case of unsafe conditions. For example, if we detect a short during a charge we would want to jump that channel to a rest step. We'd also like to apply the same rules across different cyclers (eg. Neware, Maccor, Arbin), so writing our business logic into the schedule files is not ideal.

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