Server¶
pybarst.core.server
¶
Creation of a channel or server instance does not result in extra process communication. However, instance methods does, and may therefore take significant time before the method returns.
The point is that the channel exists on the server, so deleting a client instance will not delete the channel from the server, even if no client is connected to the server.
Typical usage¶
you open and close with open_channel, close client/server.
-
class
pybarst.core.server.
BarstPipe
(pipe_name='', timeout=None, **kwargs)¶ Bases:
object
An abstract class that provides the client / server communication functionality. This base class should not be instantiated directly.
Parameters: - pipe_name: bytes
The name of the pipe used for client / server communication. Examples are \.\pipe\TestPipe for a local pipe named TestPipe or \Jace\pipe\TestPipe for a pipe named TestPipe on a remote computer named Jace.
- timeout: int
The duration (in ms) to wait before returning with a timeout when opening the pipe. If zero or None, it defaults to
pybarst.core.default_server_timeout
in ms. Defaults to None.
-
pipe_name
¶ pipe_name: bytes
The name of the pipe used to communicate with the server for the channel. See
BarstPipe
description. This is read only and is automatically set by the channel.Note
Unicode pipe names are not currently supported.
-
timeout
¶ timeout: ‘DWORD’
The amount of time to wait when connecting to the server before a timeout occurs. Defaults to
default_server_timeout
ms. This only effects the initial connection wait.
-
class
pybarst.core.server.
BarstServer
(barst_path=None, curr_dir=None, write_size=None, read_size=None, max_server_size=-1, **kwargs)¶ Bases:
pybarst.core.server.BarstPipe
The server class that controls and provides client based access to a remote server. A Barst server provides access to devices connected to the server’s system. Using a server client, a client can open, read/write, and close those channels in the server.
If the pipe name used to communicate with the server is local and a server with that name has not been created, a new server instance will be created on this system.
Multiple clients may connect safely to a single server. However, the server’s main pipe is single threaded, therefore, reading and writing to it can only be done by a single client at any time. So while a client is e.g. creating a new channel, other clients cannot create other channels. Once a channel is created, the channel gets its own pipe. A channel pipe is fully multithreaded allowing many clients to communicate with the channel at any time. See individual channels, e.g.
FTDIChannel
for details.A server can control different device types. Before each device type can be created, a manager for it must be created on the server. For example, to create a serial port channel, one first creates the server’s serial manager using
get_manager()
. Then, using the manager one can create new serial channels. Typically, when a new channel instance is created, its manager is automatically created first. As mentioned, each new channel created gets its own pipe, leaving the server’s main pipe for channel creation/deletion.Parameters: - barst_path: str
The full path to the Barst executable. It only needs to be provided when the server is local and has not been created yet. If None, we look for the executable in
pybarst.dep_bins
and then in Program Files\Barst\ (or the x86 program files if the server is 32-bit). Defaults to None. Seebarst_path
for details.- curr_dir: str
The working directory of the server. See
curr_dir
for details. Defaults to None.- write_size: int
The size of the buffer used to write to the server’s main pipe. If None it defaults to 1024 bytes. Defaults to None. See
write_size
for details.- read_size: int
The size of the buffer used to read from the server’s main pipe. If None it defaults to 1024 bytes. Defaults to None. See
read_size
for details.- max_server_size: 64-bit integer
The maximum number of bytes that the server can queue to send to clients at any time, if not -1. Defaults to -1. See
max_server_size
.
Warning
In cases where messages to/from the server’s main pipe are larger than 1024 bytes, the buffer sizes should be enlarged. Windows might return an error saying that all data could not be read if the buffer is too small. Channel pipe are guaranteed to be large enough to hold the data required for reading/writing, only the server’s main pipe size can not be predicted.
-
barst_path
¶ barst_path: object
The full path to the Barst binary. When the server doesn’t exist yet, we launch a server instance using this binary when
open_server()
is called.barst_path
is a string, defaults to ‘’.
-
clock
(self)¶ Returns the current server time using a high precision clock on the server.
The server has a single global high precision clock that it uses for time stamping data. All channels pass some data from/to the server. For example, the
MCDAQChannel
channel can read and write to the channel. Each read/write is time stamped by the server with the time it occurred. This method returns the current time as measured using that clock.Returns: a 2-tuple of (server_time, utc_time). - server_time: double
- The current server time measured using the high precision clock. This clock starts running when the server is created. This is the clock used to time stamp data sent by the server.
- utc_time: double
- The current utc time measured by the server’s system. This
clock is much less precise/accurate. By calling this many
times, one can correlate time between the server time, utc
time, and the time of a clients system. For example, one can
call it repeatedly to try to find on average what time on a
clients system corresponds to a particular time stamp of the
server.
The value represents the number of second that has passed since 12:00 A.M. January 1, 1601 Coordinated Universal Time (UTC). This is commonly called Windows file time (http://msdn.microsoft.com/en-us/library/windows/desktop/ms724284%28v=vs.85%29.aspx).
For example:
>>> import time >>> server = BarstServer(barst_path=path, pipe_name=r'\\.\pipe\TestPipe') >>> server.open_server() >>> print(server.clock()) (0.027729689422222512, 13045704696.357197) >>> print(server.clock()) (0.02788367253417604, 13045704696.357197) >>> time.sleep(1.5) >>> print(server.clock()) (1.528171928919753, 13045704697.857283)
-
close_manager
(self, str manager)¶ Closes a manager. If the manager has not been created yet by this instance of the server’s client, we will create the manager and then close it. The reason is that another client elsewhere could have created the manager, even if it has not been created locally. So we need to ensure we close it on the server.
If the manager had any open channels, those channels will also be closed by the server.
-
close_server
(self)¶ Notifies the server to shut down.
Shuts down the server and all its open managers and channels. Afterwards, the server process should have closed. To open the server again, call
open_server()
.
-
connected
¶ connected: ‘int’
Whether the instance opened it’s connection with the server. If False,
open_server()
must be called. Closing the server sets this to False. Read only.
-
curr_dir
¶ curr_dir: object
When we launch the binary at
barst_path
, which creates the server,curr_dir
is the directory used by the binary as the current directory. Defaults tobarst_path
if None or empty.
-
get_manager
(self, str manager)¶ Creates a manager in the server if it has not been created yet.
As described in the class description, a server is constructed from a single main pipe through which you create managers which in turn manage and create specific channels, e.g. a serial port channel. Once the manager is created, we can create channels using that driver. By default, creating a channel will automatically create its manager.
For example:
>>> server = BarstServer(barst_path=r'path_to_barst', ... pipe_name=r'\\.\pipe\TestPipe') >>> print(server) <pybarst.barst_core.BarstServer object at 0x02C77F30> >>> print(server.get_version()) 20000 >>> print(server.get_manager('ftdi')) {'version': 197127L, 'chan': 0, 'chan_id': 'FTDIMan'}
Parameters: - manager: str
The name of the manager to create. Can be one of ‘ftdi’, ‘rtv’, ‘serial’, or ‘mcdaq’.
Returns: a dict describing the manager. See
managers
.
-
get_version
(self) → DWORD¶ Returns Barst’s version.
Returns: int. The version in the form where e.g. 10000 means 1.00.00.
-
managers
¶ managers: dict
A dictionary containing the managers opened with this server instance. Other managers can be open on the server, even if not contained here. Read only. See
get_manager()
.For example, after the FTDI manager is opened:
>>> server.open_server() >>> server.get_manager('ftdi') >>> print(server.managers) {'ftdi': {'version': 197127L, 'chan': 0, 'chan_id': 'FTDIMan'}}
For each manager, the values in the dict is:
- version: int
- The version of that manager’s driver.
- chan: int
- The channel number of the manager in the server.
- chan_id: str
- The string ID given to that manager by barst.
-
max_server_size
¶ max_server_size: ‘long long’
The maximum number of bytes that the server can queue to send to clients at any time. If -1, it’s unlimited. There are many channels which when requested, the server will continuously send data to clients, e.g. RTV channels. When -1, if the client never reads, the server will still continuously queue more data, exhausting its RAM after some time. Using this value, once the server has exceeded
max_server_size
bytes in its queue, new data waiting to be sent will simply be discarded.Note
This is a global server wide value. That is, the write queues of all the channels are combined when checking if the size is too large. Therefore, once exceeded, no channel will be able to send data to a client until the client resolves the waiting data. Also, while some channels will resume sending data once the value is not exceeded anymore, other channels might disable their pipes. So once exceeded, the server should be thought of as being in a unrecoverable error state.
-
open_server
(self)¶ Opens the server with the settings specified when creating the
BarstServer
instance. If a server with this pipe name doesn’t exist yet, one will be created, provided the pipe is local andbarst_path
was provided.
-
read_size
¶ read_size: ‘DWORD’
The maximum buffer size used by the client for reading from the server’s main pipe. The default value should be large enough for all the messages, however, if there errors indicating that the whole messages was not read, this value should be increased.
Note
The value only affects the server’s main pipe, not the pipes of the individual channels. Individual channels will always create pipes large enough for their data. If there are issues, errors would arise when creating/opening a channel. This parameter is only used when the server is launched by the client, not when the server already exists.
-
write_size
¶ write_size: ‘DWORD’
The maximum buffer size used by the client for writing to the server’s main pipe. The default value should be large enough for all the messages, however, if there errors indicating that the whole messages was not written, this value should be increased.
Note
The value only affects the server’s main pipe, not the pipes of the individual channels. Individual channels will always create pipes large enough for their data. If there are issues, errors would arise when creating/opening a channel. This parameter is only used when the server is launched by the client, not when the server already exists.
-
class
pybarst.core.server.
BarstChannel
¶ Bases:
pybarst.core.server.BarstPipe
An abstract representation class of a client connected to a channel on the server. This class is never instantiated directly.
See derived classes, e.g.
RTVChannel
for examples.The class provides methods commonly used by the client classes.
-
barst_chan_type
¶ barst_chan_type: str
The string ID given to the channel type by the server. Each channel type has a unique string assigned by barst. Read only.
-
cancel_read
(self, flush=False)¶ Cancels a continuous read.
This method is only implemented for for the classes that indicate that e.g.
MCDAQChannel
. For other classes, it doesn’t do anything.Some classes offer an option where the server continuously sends data read back to the client. For those classes, one can stop the read operation by setting the state to inactive with
set_state()
, which will affect all the clients connected, or by calling this method. With this method, the read operation is only canceled for this client.Parameters: - flush: bool
Whether any data already waiting to be read by the client will be discarded. This forces a disconnection and reconnection with the server for this client. flush defaults to False.
After canceling, the server will not queue any new data to be sent to the client. However, the server might have already queued data to be sent to the client. This parameter controls whether that data will sill be sent.
If flush is False, that data will be available to the client when it calls read, until the server has no more data available and read will then return an error once. Calling read after the error, will trigger the server to start sending new data again.
If flush is True, then all data waiting to be sent will be discarded. In addition, no error will be raised upon a subsequent call to read, but instead it will trigger the server to start sending data to the client again.
Note
Calling this method while a read operation is not ongoing may result in an exception.
-
chan
¶ chan: ‘int’
The channel number assigned to this channel by the server. For example, an FTDI channel may be one channel among many in the FTDI manager - each channel gets its own channel number. Read only.
-
close_channel_client
(self)¶ Closes this client’s connection to the channel without affecting the channel on the server. Other clients are not affected by this.
After this is called, the channel will still exist on the server, but this instance won’t be connected to it. Therefore, calling other channel methods will likely raise an exception until
open_channel()
is called again.If a class method, e.g. a read or write operation got stuck communicating with the server, calling this method from another thread will force the waiting method to return, possibly with an error.
-
close_channel_server
(self)¶ Closes the channel on the server. This deletes the channel from the server. Therefore any other clients that may be connected to the channel will return an error when they try to communicate with it after this method has been called.
This method internally also calls
close_channel_client()
.To only close the connection of this client without affecting the state of the channel on the server, call
close_channel_client()
.
-
connected
¶ connected: ‘int’
Whether the instance opened it’s connection with the server. If False,
open_channel()
must be called. Closing the channel sets this to False. Read only.
-
open_channel
(self)¶ Opens the client’s connection to this channel on the server. If the channel doesn’t exist yet it creates it first, otherwise it just opens a new client for the channel.
Before any other operations can be done on the channel, this method must be called.
All channels are designed such that when the class instance is created, no client/server communication occurs. Then, to actually create/open the channel, this method must be called.
Similarly, after closing a channel with
close_channel_server()
orclose_channel_client()
one can recreate or reopen the client’s connection to the channel using this method.
-
parent_chan
¶ parent_chan: ‘int’
The channel number of this channel’s parent, e.g. if this is a FTDI channel then it’s parent channel is the FTDI manager and this value will represent the FTDI manager’s channel number in the server. Read only.
-
server
¶ server: pybarst.core.server.BarstServer
A
BarstServer
instance in which this channel exists / will exist.
-
set_state
(self, int state, flush=False)¶ Sets the state of the channel to active or inactive (True or False). The activation state of a channel is global, and therefore affects all the clients of a channel.
For most channels, after the channel is created on the server with
open_channel()
, before you can read/write to it, the channel must be activated. Because the state is global, once activated, further clients opening the channel will already be in a activate state.Similarly, to stop an active channel from reading or writing data, you set the channel into an inactive state. Typically, the channel uses less resource when inactive because e.g. sampling is disabled etc. so it is preferred to deactivate channels that are not used. Again, once deactivated, the channel will be inactive for all the clients.
When deactivating, all the read or write requests being performed will be canceled. Also, reading or writing data to an inactive channel will result in an error. Typically, one sets the state to active/inactive in cycles as they are needed.
Parameters: - state: bool
The state to set the channel in. Can be either True for activation and False for inactivation.
- flush: bool
Whether any data waiting to be sent, or read by the client will be discarded. This forces a disconnection and reconnection with the server for this client.
Typically, this is only used for channels that continuously send data back to clients, e.g.
RTVChannel
. Always, when deactivating, the server will not queue any new data to be sent to a client. However, the server might have already queued data to be sent to the client. This parameter controls whether that data will sill be sent.If flush is False, that data will be available to the client when it calls read, until the server has no more data available and read will return an error. For channels that support that, the channel will only be considered inactive after the last read once that error is raised.
If flush is True, then all data waiting to be sent will be discarded. In addition, the channel will instantly become inactive. If the channel is in a read or write, then that method will return with an exception.
flush is only used when state is False. flush defaults to False.
See
cancel_read()
for an alternative method to cancel ongoing server reads.
-