Download Latest Version Korad KD3005P V4.zip (134.2 kB)
Email in envelope

Get an email when there's a new version of Korad GUI

Home
Name Modified Size InfoDownloads / Week
Korad KD3005P V4.zip 2024-01-27 134.2 kB
Embed Example.zip 2023-12-21 136.3 kB
README.txt 2023-12-07 8.3 kB
Korad KD3005P V3.zip 2023-10-28 131.2 kB
Korad KD3005P V2.zip 2023-08-13 128.5 kB
Totals: 5 Items   538.5 kB 1
This project uses workcells which are virtual autonomous machines which communicate with other workcells using a
virtual wireless network. Since workcells transmit messages wirelessly, it is very easy for one workcell to
communicate to multiple other workcells.
There is no API as each workcell is instantiated anonymously and all of its variables and methods are private. All
communication between workcells is only by messaging. Each workcell maintains its own state and how and if it
responds to a message is dependent only on its internal state. The network itself is implemented by a dedicated
workcell which is also controlled by messaging.
Messages consist of a unique text string, also known as a trigger, which is used to identify the message and a
payload which can be any Python object.
To receive a message, a workcell will associate a method with the trigger. When a message is received, the method
will run to completion before the network can send another message. This guarantees determinancy in how workcells
interact with each other.
The workcells are derived from high level Tkinter objects such as Toplevel, Frame and Labelframe. By doing this
each workcell can run in its own thread which is managed by Tkinter and as Tkinter objects they may also have a
visual presentation useful for creating a GUI.
To create a GUI two problems have to be solved, visual presentation of the widgets used for interaction with the user
and an asynchronous communication network for passing events.
Ideally, each of these problems should be solved independently of each other because the ideal structure for visual
presentation is a hierarchical structure which is possibly the least optimal solution for an asynchronous network.
A better solution is to retain the visual presentation and create a separate communications network for event handling.
This communication network is ideal not only for the GUI, but also handling other asychronous events like serial port
management.
Tkinter provides the ideal environment for this. High level classes like Toplevel, Labelframe and Frame can be used to
create anonymously instantiated objects which can be placed in a hierarchical structure for visual presentation. The
object can also be derived from a Transceiver class which implements a message based peer to peer communication
network. Messages can then be passed from one object to another without regard to the hierarchical structure used for
the visual presentation.
A serial port manager can be derived from the Tkinter Frame class and embedded in an application with widgets used for
port parameter setup. The Frame's event loop can then be used for serial port setup and polling. When serial data is
received, it can be sent as a message payload to other objects in the application. The Frame event loop is also useful
for transmission when handshaking is required. The Frame object can run autonomously which simplifies program
development.
The network itself is configured as a star topology with a central hub, also a workcell, which receives messages from
the other workcells, queues the messages and then forwards them to the other workcells.
Each workcell is completely autonomous with all methods and variables private. All interaction is done only through
messaging. Also, when the hub sends a message to a workcell, the workcell completes the task associated with the message
before the hub can send another message. This guarantees determinism because a workcell can guarantee that it is in a
particular state before it will react to a new message. Also, it's internal state is completely private and cannot be
influenced by outside forces, other than through messaging.
For practical purposes, the hub has to maintain a database of all workcell names and a reference to a 'transfer' method
within each workcell for passing messages between workcells. No other part of the workcell is exposed.
Each workcell maintains a dictionary which associates a trigger string within the message with an internal method. When
the hub sends a message to a workcell it will call the workcell's transfer method and pass it the message. If the
trigger is associated with a method in the workcell, that method is executed and then control passed back to the hub.
If no method is associated with the message, no action is taken by the workcell and control passed back to the hub.
The hub is derived only from the Tkinter Frame class and has two class variables, a dictionary used as for the workcells
database and a SimpleQueue object used to hold incoming messages. The hub class contains methods for maintaining the
workcells database and operating the queue. When a Transceiver object is instantiated, it instantiates its own hub
object so that it has access to the hub class methods and class variables.
All hub operations are initiated through messaging and are done atomically. This prevents race conditions when the hub
database is changed. When a message is added to the queue, a queue read request is added to the Frame event loop to run
when the event loop is idle. This way each message is kept in temporal order on the message queue with a matching read
request. The queue read is blocking so that each message's associated task has to be completed before the next message
can be read.
A workcell is derived either from a Toplevel Tkinter class for a standalone application, or a Frame or Lableframe class
where a workcell will be embedded in another object. For a LabelFrame or Frame class, the workcell constructor is
passed a reference to the parent object and a unique workcell name. For a Toplevel class, only the unique workcell name
is required. The workcell name is then passed to Transceiver __init__ method. The transceiver __init__ method then sends
a registration message to the hub workcell. When the hub receives the message, it verifies that the name is unique and
adds the name and reference to the workcell's transfer method to its database.
A runtime error will be raised if the name is not unique.
A message consists of a trigger, which is a unique text string and a payload which is a reference to a Python object.
The trigger is a concatentation of a workcell name and a tag string such as 'Stop', 'Start', etc. Because the workcell
name is unique, tag strings can be reused because the concatenation of workcell name and tag will be unique.
Two types of messages are used, status and request. Status messages are sent by a workcell when the recipients are not
known in advance and may be sent to multiple workcells simultaneously. Request messages are sent when the recipient is
known in advance and are sent only to a single workcell.
For status messages, the sending workcell name is used to create the trigger because this is the only workcell name that
is known at instantiation. The receiving workcells can set up their message response dictionaries using triggers derived
from the expected sending workcell name.
For request messages, the receiving workcell name is used to create the trigger because this is the only workcell name
known to the receiver at instantiation. The receiver can then set up its message response dictionary using triggers
derived from its own name.
Because the triggers are text based, the workcell associated with a trigger doesn't need to exist when the message
response dictionary is set up. A runtime error will occur only when a message is sent to an uninstantiated workcell.
A workcell prepares to receive a message by using the bindRequest and bindStatus methods to bind a trigger to an
internal method. If None or no method reference is passed to bindRequest or bindStatus methods, the message will be
ignored.
The binding methods are not direct acting, instead they send a request message to the hub which acts on the request when
it reaches the top of the queue. This prevents race conditions because any prior messages in the queue will be acted on
before the binding can change.
A special broadcast method is also available. This method sends out request messages to every workcell with the same
tag. This is used for special purposes like sending a shutdown message when the main application is closed. This gives
workcells a chance to do housekeeping tasks like closing serial ports before shutting down.




Source: README.txt, updated 2023-12-07