-
Notifications
You must be signed in to change notification settings - Fork 9
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
Docs re-write, including for asyncio support #14
Merged
Merged
Changes from all commits
Commits
Show all changes
16 commits
Select commit
Hold shift + click to select a range
6d18b9a
fix typo
AlexanderWells-diamond f198e73
Beginning to rewrite create-an-ioc.
AlexanderWells-diamond 3708bea
First draft of rewritten creating-an-ioc
AlexanderWells-diamond f04dbc3
Fix README. Add asyncio example.
AlexanderWells-diamond b9a991d
Merge branch 'master' into documentation_update
AlexanderWells-diamond fcbcfcf
Update the asyncio example file
AlexanderWells-diamond 7a32999
Updated examples
coretl b5c3e1b
Finish publish ioc and use asyncio pages.
AlexanderWells-diamond 4d7f891
Correct the shebang line based on latest published version
AlexanderWells-diamond ebe736b
New how-to read from an IOC. Some touchups to other work.
AlexanderWells-diamond 457ea8d
Use a lambda rather than the defined function.
AlexanderWells-diamond 06ca777
Minor grammatical changes from proof-reading
AlexanderWells-diamond 26cb480
Docstring update for AsyncioDispatcher
AlexanderWells-diamond 338be4d
Fix linting error
AlexanderWells-diamond a873d0e
Remove all unncecessary :role: tags that I can find.
AlexanderWells-diamond 79e0cba
Merge remote-tracking branch 'origin/master' into documentation_update
AlexanderWells-diamond File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
# Import the basic framework components. | ||
from softioc import softioc, builder, asyncio_dispatcher | ||
import asyncio | ||
|
||
# Create an asyncio dispatcher, the event loop is now running | ||
dispatcher = asyncio_dispatcher.AsyncioDispatcher() | ||
|
||
# Set the record prefix | ||
builder.SetDeviceName("MY-DEVICE-PREFIX") | ||
|
||
# Create some records | ||
ai = builder.aIn('AI', initial_value=5) | ||
ao = builder.aOut('AO', initial_value=12.45, always_update=True, | ||
on_update=lambda v: ai.set(v)) | ||
|
||
# Boilerplate get the IOC started | ||
builder.LoadDatabase() | ||
softioc.iocInit(dispatcher) | ||
|
||
# Start processes required to be run after iocInit | ||
async def update(): | ||
while True: | ||
ai.set(ai.get() + 1) | ||
await asyncio.sleep(1) | ||
|
||
asyncio.run_coroutine_threadsafe(update(), dispatcher.loop) | ||
|
||
# Finally leave the IOC running with an interactive shell. | ||
softioc.interactive_ioc(globals()) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
# Import the basic framework components. | ||
from softioc import softioc, builder | ||
import cothread | ||
|
||
# Set the record prefix | ||
builder.SetDeviceName("MY-DEVICE-PREFIX") | ||
|
||
# Create some records | ||
ai = builder.aIn('AI', initial_value=5) | ||
ao = builder.aOut('AO', initial_value=12.45, always_update=True, | ||
on_update=lambda v: ai.set(v)) | ||
|
||
# Boilerplate get the IOC started | ||
builder.LoadDatabase() | ||
softioc.iocInit() | ||
|
||
# Start processes required to be run after iocInit | ||
def update(): | ||
while True: | ||
ai.set(ai.get() + 1) | ||
cothread.Sleep(1) | ||
|
||
cothread.Spawn(update) | ||
|
||
# Finally leave the IOC running with an interactive shell. | ||
softioc.interactive_ioc(globals()) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
from softioc import softioc | ||
from cothread.catools import caget, caput, camonitor | ||
|
||
print(caget("MY-DEVICE-PREFIX:AI")) | ||
print(caget("MY-DEVICE-PREFIX:AO")) | ||
print(caput("MY-DEVICE-PREFIX:AO", "999")) | ||
print(caget("MY-DEVICE-PREFIX:AO")) | ||
|
||
softioc.interactive_ioc(globals()) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
Create a Publishable IOC | ||
======================== | ||
|
||
As seen in `../tutorials/creating-an-ioc`, a single Python script can be an IOC. | ||
It is also possible (and the most common situation) to have an entire Python module | ||
comprising an IOC. This guide explains both, as well as how to publish an IOC within | ||
the DLS environment. | ||
|
||
Single File IOC | ||
---------------- | ||
An IOC that is entirely contained within a single Python source file can be used as an | ||
IOC inside DLS simply by adding this shebang line:: | ||
|
||
#!/dls_sw/prod/python3/RHEL7-x86_64/softioc/3.0b2/prefix/bin/pythonIoc | ||
|
||
|
||
IOC entry point for a module | ||
------------------------------ | ||
If your IOC is more complicated than one file, it is recommended to write a python | ||
module (including docs/tests/etc.). The Panda Blocks Client will be an example of | ||
this. | ||
|
||
|
||
Make an IOC publishable at DLS | ||
------------------------------ | ||
To make the IOC publishable, a makefile is required: | ||
|
||
``Makefile`` | ||
This file is necessary in order to run ``dls-release.py``, and needs to have | ||
both ``install`` and ``clean`` targets, but doesn't need to actually do | ||
anything. Thus the following content for this file is enough:: | ||
|
||
install: | ||
clean: | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
Read data from an IOC | ||
====================== | ||
|
||
This guide explains how to read data from an IOC in a separate Python program. | ||
|
||
.. note:: | ||
Please ensure your firewall allows both TCP and UDP traffic on ports 5064 and 5065. | ||
These are used by EPICS for channel access to the PVs. | ||
|
||
|
||
To start, run the `cothread` IOC from `../tutorials/creating-an-ioc` or the | ||
`asyncio` IOC from `use-asyncio-in-an-ioc` and leave it running at the | ||
interactive shell. | ||
|
||
We will read data from that IOC using this script: | ||
|
||
.. literalinclude:: ../examples/example_read_from_ioc.py | ||
|
||
.. note:: | ||
You may see warnings regarding the missing "caRepeater" program. This is an EPICS tool | ||
that is used to track when PVs start and stop. It is not required for this simple example, | ||
and so the warning can be ignored. | ||
|
||
From the interactive command line you can now use the ``caget`` and ``caput`` functions to operate on | ||
the PVs exposed in the IOC. Another interesting command to try is:: | ||
|
||
camonitor("MY-DEVICE-PREFIX:AI", lambda val: print(val)) | ||
|
||
|
||
You should observe the value of ``AI`` being printed out, once per second, every time the PV value | ||
updates. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,33 @@ | ||
Use `asyncio` in an IOC | ||
======================= | ||
|
||
Write about the differences creating an IOC using `AsyncioDispatcher` | ||
There are two libraries available for asynchronous operations in PythonIOC: | ||
`cothread` and `asyncio`. This guide shows how to use the latter in | ||
an IOC. | ||
|
||
.. note:: | ||
This page only explains the differences between using `cothread` and `asyncio`. | ||
For more thorough explanation of the IOC itself see `../tutorials/creating-an-ioc` | ||
|
||
.. literalinclude:: ../examples/example_asyncio_ioc.py | ||
|
||
|
||
The ``dispatcher`` is created and passed to :func:`~softioc.softioc.iocInit`. This is what | ||
allows the use of `asyncio` functions in this IOC. It contains a new event loop to handle | ||
this. | ||
|
||
The ``async update`` function will increment the value of ``ai`` once per second, | ||
sleeping that coroutine between updates. | ||
Note that we run this coroutine in the ``loop`` of the ``dispatcher``, and not in the | ||
main event loop. | ||
|
||
This IOC will, like the one in `../tutorials/creating-an-ioc`, leave an interactive | ||
shell open. The values of the PVs can be queried using the methods defined in the | ||
`softioc.softioc` module. | ||
|
||
|
||
Asynchronous Channel Access | ||
--------------------------- | ||
|
||
PVs can be retrieved externally from a PV in an asynchronous manner by using the :py`aioca` module. | ||
It provides ``await``-able implementations of ``caget``, ``caput``, etc. See that module for more information. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
According to DiamondLightSource/aioca#12 (comment) then if you upgrade the epicscorelibs dependency to
epicscorelibs>=7.0.5.99.1.0a2
(in pyproject.toml) then remove the Pipfile.lock and runpipenv --rm && pipenv install --dev
then these warnings should go away. Please could you try that?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Doing this update causes tests to fail due to a missing import. I also see the same error when just trying to start up my example IOCs:
File "docs/examples/example_cothread_ioc.py", line 2, in <module> from softioc import softioc, builder ModuleNotFoundError: No module named 'softioc'
I can verify that this is entirely caused by changing the epicscorelibs dependency - swapping the required version back and reinstalling the pipenv makes the tests (and my example IOCs) work again.
I can't say I understand this error at the moment, so I'll investigate it a little more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oops, you need to do
dls-py3 download-one-dependency epicscorelibs 7.0.5.99.1.0a2
first