Event-based hardware simulation framework

Related tags

Hardwaretickit
Overview

tickit

Code CI Docs CI Test Coverage Latest PyPI version Apache License

An event-based multi-device simulation framework providing configuration and orchestration of complex multi-device simulations.

PyPI pip install tickit
Source code https://github.com/dls-controls/tickit
Documentation https://dls-controls.github.io/tickit
Changelog https://github.com/dls-controls/tickit/blob/master/CHANGELOG.rst

An example device which emits a random value between 0 and 255 whenever called and asks to be called again once the simulation has progressed by the callback_period:

None: self.callback_period = SimTime(callback_period) def update(self, time: SimTime, inputs: Inputs) -> DeviceUpdate[Outputs]: output = randint(0, 255) LOGGER.debug( "Boing! (delta: {}, inputs: {}, output: {})".format(time, inputs, output) ) return DeviceUpdate( RandomTrampoline.Outputs(output=output), SimTime(time + self.callback_period), ) ">
class RandomTrampoline(ConfigurableDevice):

Inputs: TypedDict = TypedDict("Inputs", {})
Outputs: TypedDict = TypedDict("Outputs", {"output": int})

def __init__(self, callback_period: int = int(1e9)) -> None:
    self.callback_period = SimTime(callback_period)

def update(self, time: SimTime, inputs: Inputs) -> DeviceUpdate[Outputs]:
    output = randint(0, 255)
    LOGGER.debug(
        "Boing! (delta: {}, inputs: {}, output: {})".format(time, inputs, output)
    )
    return DeviceUpdate(
        RandomTrampoline.Outputs(output=output),
        SimTime(time + self.callback_period),
    )

An example simulation defines a RemoteControlled device named tcp_contr and a Sink device named contr_sink. The observed output of tcp_contr is wired to the input input of contr_sink. Additionally, extenal control of tcp_contr is afforded by a RemoteControlledAdapter which is exposed extenally through a TCPServer:

- tickit.core.components.device_simulation.DeviceSimulation:
    adapters:
    - examples.devices.remote_controlled.RemoteControlledAdapter:
        server:
        tickit.adapters.servers.tcp.TcpServer:
            format: "%b\r\n"
    device:
    examples.devices.remote_controlled.RemoteControlled: {}
    inputs: {}
    name: tcp_contr
- tickit.core.components.device_simulation.DeviceSimulation:
    adapters: []
    device:
    tickit.devices.sink.Sink: {}
    inputs:
    input: tcp_contr:observed
    name: contr_sink

See https://dls-controls.github.io/tickit for more detailed documentation.

Comments
  • Change deserialization based around ComponentConfig instances

    Change deserialization based around ComponentConfig instances

    The YAML looks cleaner now, but there's some ugliness:

    • DeviceSimulation sets Adapter.device and Adapter.raise_interrupt~~, mypy complains about the latter~~
    • Component vs BaseComponent, mypy doesn't like returning a DeviceSimulation when the call signature says it wants a Component
    • I find myself wanting to write class TCPServer(Server). Should Server, Adapter, Component be abstract base classes instead of protocols?
    • Does the contents of configurable.py belong in component.py?

    I expect there will be more issues as I convert the rest, but I wanted to PR early...

    Fixes #4

    opened by thomascobb 7
  • 'click' module not included in default installation.

    'click' module not included in default installation.

    When trying to run tickit using the default installation I discovered that the click module is missing. This does raise the question of what else might be missing from the default installation and whether this points to a gap in our testing suite that this went unnoticed until now.

    bug 
    opened by collang 5
  • Simulate a motorRecord

    Simulate a motorRecord

    It would be useful to be able to use an EpicsAdapter to simulate a motorRecord. Currently we cannot do this as https://github.com/dls-controls/pythonSoftIOC does not support motor records

    opened by DominicOram 4
  • Configuration snippits in README.md and docs/* are outdataed

    Configuration snippits in README.md and docs/* are outdataed

    The configuration snippet in README.md and those throughout the documentation were not updated alongside #16, as such the continue to contain the outdated, verbose, configuration format. These snippets should be updated to conform to the current format.

    documentation 
    opened by garryod 3
  • Bugged entries in

    Bugged entries in "Pipfile.lock"

    There's a few entries in the master branch of Pipfile.lock which cause issues with the installation:

    On python3.8 and python3.9 I get apischema.validation.ValidationError("No module named typing-extensions"). As we can see, the module will only be installed for python<3.8.

    "typing-extensions": {
                "hashes": [
                    "sha256:49f75d16ff11f1cd258e1b988ccff82a3ca5570217d7ad8c5f48205dd99a677e",
                    "sha256:d8226d10bc02a29bcc81df19a26e56a9647f8b0a6d4a83924139f4a8b01f17b7",
                    "sha256:f1d25edafde516b146ecd0613dabcc61409817af4766fbbcfb8d1ad4ec441a34"
                ],
                "markers": "python_version < '3.8' and python_version < '3.8'",
                "version": "==3.10.0.2"
            },
    

    As I understand, this module should only be required for python<=3.8 but the error will also be raised when running python3.9.

    Similarly, mypy will only be installed for python==3.7:

    "mypy": {
                "hashes": [
                    "sha256:088cd9c7904b4ad80bec811053272986611b84221835e079be5bcad029e79dd9",
                    "sha256:0aadfb2d3935988ec3815952e44058a3100499f5be5b28c34ac9d79f002a4a9a",
                    "sha256:119bed3832d961f3a880787bf621634ba042cb8dc850a7429f643508eeac97b9",
                    "sha256:1a85e280d4d217150ce8cb1a6dddffd14e753a4e0c3cf90baabb32cefa41b59e",
                    "sha256:3c4b8ca36877fc75339253721f69603a9c7fdb5d4d5a95a1a1b899d8b86a4de2",
                    "sha256:3e382b29f8e0ccf19a2df2b29a167591245df90c0b5a2542249873b5c1d78212",
                    "sha256:42c266ced41b65ed40a282c575705325fa7991af370036d3f134518336636f5b",
                    "sha256:53fd2eb27a8ee2892614370896956af2ff61254c275aaee4c230ae771cadd885",
                    "sha256:704098302473cb31a218f1775a873b376b30b4c18229421e9e9dc8916fd16150",
                    "sha256:7df1ead20c81371ccd6091fa3e2878559b5c4d4caadaf1a484cf88d93ca06703",
                    "sha256:866c41f28cee548475f146aa4d39a51cf3b6a84246969f3759cb3e9c742fc072",
                    "sha256:a155d80ea6cee511a3694b108c4494a39f42de11ee4e61e72bc424c490e46457",
                    "sha256:adaeee09bfde366d2c13fe6093a7df5df83c9a2ba98638c7d76b010694db760e",
                    "sha256:b6fb13123aeef4a3abbcfd7e71773ff3ff1526a7d3dc538f3929a49b42be03f0",
                    "sha256:b94e4b785e304a04ea0828759172a15add27088520dc7e49ceade7834275bedb",
                    "sha256:c0df2d30ed496a08de5daed2a9ea807d07c21ae0ab23acf541ab88c24b26ab97",
                    "sha256:c6c2602dffb74867498f86e6129fd52a2770c48b7cd3ece77ada4fa38f94eba8",
                    "sha256:ceb6e0a6e27fb364fb3853389607cf7eb3a126ad335790fa1e14ed02fba50811",
                    "sha256:d9dd839eb0dc1bbe866a288ba3c1afc33a202015d2ad83b31e875b5905a079b6",
                    "sha256:e4dab234478e3bd3ce83bac4193b2ecd9cf94e720ddd95ce69840273bf44f6de",
                    "sha256:ec4e0cd079db280b6bdabdc807047ff3e199f334050db5cbb91ba3e959a67504",
                    "sha256:ecd2c3fe726758037234c93df7e98deb257fd15c24c9180dacf1ef829da5f921",
                    "sha256:ef565033fa5a958e62796867b1df10c40263ea9ded87164d67572834e57a174d"
                ],
                "markers": "python_version < '3.8'",
                "version": "==0.910"
            }
    

    Steps to reproduce:

    1. make a new virtual environment with python>3.7
    2. install pipenv to the virtual environment
    3. make sure your version of tickit is up to date with the master branch
    4. run pipenv install --dev
    5. run python3 -m tickit all examples/configs/current-monitor.yaml, you should get an apischema.validation.errors.ValidationError
    6. run python3 -m pytest tests/, you should receive a ModuleNotFoundError: No module named 'mypy' message.
    opened by collang 3
  • Increase test coverage

    Increase test coverage

    Adds tests for EpicsAdapter, CryostreamBase Cryostream, Femto, Pneumatic and Cli.

    Some general improvements to the Femto, CryostreamBase and EpicsAdapter have also ended up here.

    opened by collang 3
  • Containerise Tickit

    Containerise Tickit

    TODO:

    • [x] Dockerfile which contains a 3-stage build, see https://github.com/epics-containers/epics-base/blob/main/Dockerfile for an example multi-stage build.
    • [x] Stage 1: Base stage
    • [x] Stage 2: Dev stage
    • [x] Stage 3: Runtime stage
    • [x] Stages 2 and 3 are based on 1
    • [x] CI to publish images, see https://github.com/epics-containers/epics-base/blob/main/.github/workflows/buiild.yml

    Add to review: @callumforrester @thomascobb @gilesknap

    enhancement 
    opened by callumforrester 3
  • (De)serialization rework

    (De)serialization rework

    The current (de)serialization system is clunky, it requires significant rework to improve usability of the library.

    Current System

    The current system operates by defining "config" classes for each interface (e.g. DeviceConfig for Device(Protocol)); such classes act as an apischema tagged union of derived "config" classes. User classes are made configurable by the addition of a nested "config" class (via a decorator or inheritance of a type which applies the decorator), which joins the tagged union of it's template.

    At deserilization time, all classes referenced by the configuration file must be loaded prior to apischema deserialzation such that the nested config classes can be created. This necessitates an ugly two stage process in which the config file is first parsed for fully qualified names to load them, and then parsed again to perform deserialization.

    On the end user front, this requires the following boilerplate:

    class MyDevice(ConfigurableDevice):
        ...
    

    Such that MyDevice can be given a nested class MyDeviceConfig which subtypes DeviceConfig, allowing for apischema deserialization by tagged union where the qualified name of MyDevice.

    Target System

    An ideal system would have the following benefits over the current system:

    • Requires no additional boilerplate for the end user
    • Removes the need for passing of "config" objects
    • Perform a single parsing of the configuration file

    Proposed System

    I expect deserialization would likely operate as follows, though I would love to hear suggestions of alternatives:

    The config file (yaml) is read & parsed with `PyYAML`
    Recursively, for each object in the parsed config:
        If module of object not already loaded:
            Load module of object
            Generate config (data)class for object type - based on __init__ signature
        Check class is instance of the expected type
        Check generated config class is instance of the config of the expected type (possibly superfluous)
        Instantiate config with configured parameters
        Build object and pass / pass config
    

    The primary issue with this system stems from the fact that we wish to inject some init arguments during the instantiation process, there exist several possible solutions to this problem, the merits of which must be weighed:

    1. Allow for passing of either built objects or configs which implement a build() method which takes injected arguments
    2. Do not perform argument injection in __init__, instead pass them to methods such as run_forever()
    3. Require passing of configs which implement a build() method which takes injected arguments
    enhancement 
    opened by garryod 3
  • Pin flake8 version

    Pin flake8 version

    See https://github.com/tholo/pytest-flake8/issues/87

    To test:

    • Run the CI with no lock on main, confirm flake8 is broken
    • Run on this branch, confirm it works
    opened by DominicOram 1
  • Update docs

    Update docs

    Updating the docs to be split into user and dev docs.

    I am currently moderately happy with the state of the user docs and could do with feedback @callumforrester .

    I have not yet really done anything for the dev docs, I figured once I had figured out the right level for the user ones it would become more clear, which I think it has.

    I also tried to partially adopt the new pip3 skeleton style docs as it has the preferential format, but that does not build the docs right now.

    opened by abbiemery 2
  • Make user interface for components more friendly

    Make user interface for components more friendly

    Currently to set up a component you have to override the __call__ method of ComponentConfig. This is user facing so should be made to avoid a dunder method.

    Maybe something like:

    @component
    def my_detector(thing: int, other_thing: str) -> Component:
        return DeviceSimulation(
            MyDetectorDevice(thing),
            MyDetectorAdapter(other_thing)
        )
    
    needed next 
    opened by abbiemery 0
  • Fix Disjoining Components

    Fix Disjoining Components

    The disjoining component fix didn't actually work and so needs fixing. It is likely to be fixed within the future developments needed for the Zebra since we would want all simulations run as 'tickit in tickit' system simulations, so any disconnected input is actually connected to a shared larger starting input.

    However, I wanted to note this down in case somebody found it not working.

    needed next 
    opened by abbiemery 0
  • 93 change regex command

    93 change regex command

    Requires #89 Fixes #92 and #93 Required for #90

    • Allows for RegexCommand to parse from data of type AnyStr rather than just bytes.
    • RegexCommand.parse now also returns the start and end indices of the match within the message, as well as the length of the message matched against. This gives enough information for MultiCommandInterprerter to strip off a matched command and for CommandInterpreter to check for a full match.
    • CommandInterpreter.handle logic updated to use the new return signature.
    • Tests added for RegexCommand and CommandInterpreter
    opened by MattPrit 1
  • Have RegexCommand.parse return more information

    Have RegexCommand.parse return more information

    Required for #90 The more complex MultiCommandInterpreter requires more information to be returned form parse. Specifically, it requires information about where within the message a match is found; these indices need to be with respect to the original message, not (if applicable) the message after it has been decoded. This could be achieved by encoding the regex pattern rather than decoding the message when format is not None. Since there will be changes to the return signature of Command.parse, the handle method of CommandInterpreter will need to be updated.

    opened by MattPrit 0
Releases(0.1.1)
Owner
Diamond Light Source Controls Group
Diamond Light Source Controls Group
Code for the onshape macropad.

Onshape_Macropad Code for the onshape macropad. This is a macropad built using the Pimoroni Keybow and the KPrepublic Enclosure. pimoroni_keybow kprep

Justin Cole 1 Nov 23, 2021
Home Assistant component to handle key atom

KeyAtome Home Assistant component to handle key atom, a Linky-compatible device made by Total/Direct-Energie. Installation Either use HACS (default),

18 Dec 21, 2022
Implementation of Forwards Kinematics, Inverse Kinematics, Point to Point Movement and Synchronous movement for Kuka KR 120 R2700-2.

I made this project for my university course in robotics. I rarely found any information regarding the implementation of mathematics in code. So I decided to make this repo in order to help others :)

2 Dec 27, 2022
Examples to accompany the

Examples to accompany the "Raspberry Pi Pico Python SDK" book published by Raspberry Pi Trading, which forms part of the technical documentation in support of Raspberry Pi Pico and the MicroPython po

Raspberry Pi 589 Jan 08, 2023
Classes and functions for animated text and graphics on an LED display

LEDarcade A collection of classes and functions for animated text and graphics on an Adafruit LED Matrix.

datagod 31 Jan 04, 2023
Robot Framework keyword library wrapper for atlassian-python-api

Robot Framework keyword library wrapper for atlassian-python-api

Marcin Koperski 3 Jul 29, 2022
BoneIO is a compact IO controller for home automation.

Project description BoneIO is a compact IO controller for home automation. Main features of this controller are Compact size (27x11x6)cm - 15 DIN modu

Maciej Krasuski 120 Nov 30, 2022
Technical Answers to Real-World Problems. Evolution of Watering Manually to Watering Automatically.

Automatic Watering System using Soil Moisture Sensor and RTC Timer with Arduino Technical Answers to Real-World Problems Know the plant, Grow the plan

NelakurthiSudheer 3 Jan 03, 2022
Component for deep integration LedFx from Home Assistant.

LedFX for Home Assistant Component for deep integration LedFx from Home Assistant. Table of Contents FAQ Install Config Performance FAQ Q. What versio

Dmitry Mamontov 28 Dec 13, 2022
Simple Python script to decode and verify an European Health Certificate QR-code

A simple Python script to decode and verify an European Health Certificate QR-code.

Mathias Panzenböck 61 Oct 05, 2022
Doughskript interpreter for converting simple command sequences into executable Arduino C++ code.

Doughskript interpreter for converting simple command sequences into executable Arduino C++ code.

Svjatoslav 2 Jan 11, 2022
Micro Displays for Raspberry Pi

micro-displays Micro Displays for Raspberry Pi Why? I'm super bored in lockdown. Add a Raspberry Pi 400 and a few tiny displays... The top half of the

ig 291 Jul 06, 2022
A script and GUI for controlling stepper motors from an arduino

A script and GUI for controlling stepper motors from an arduino (nema 23 in my case but should work for others in general)

Pip 2 Aug 01, 2022
Blender Camera Switcher

Blender Camera Switcher A simple camera switcher addon for blender. Useful when use reference image for camera. This addon will automatically fix the

Corgice 1 Jan 31, 2022
Pure micropython ESP32 SPI driver for sdcard and screen at the same SPI bus

micropython-esp32-spi-sdcard-and-screen-driver Proof of concept of Pure micropython espidf SPI driver for sdcard with screen at the same SPI bus (exam

Thomas Favennec 7 Mar 14, 2022
A battery pack simulation tool that uses the PyBaMM framework

Overview of liionpack liionpack takes a 1D PyBaMM model and makes it into a pack. You can either specify the configuration e.g. 16 cells in parallel a

PyBaMM Team 40 Jan 05, 2023
智能无人机路径规划仿真系统是一个具有操作控制精细、平台整合性强、全方向模型建立与应用自动化特点的软件

Drone智能无人机路径规划仿真系统是一个具有操作控制精细、平台整合性强、全方向模型建立与应用自动化特点的软件。它以A、B两国在C区开展无人机战争为背景,该系统的核心功能是通过仿真平台规划无人机航线,并进行验证输出,数据可导入真实无人机,使其按照规定路线精准抵达战场任一位置,支持多人多设备编队联合行动。

wwy 349 Jan 03, 2023
A ch341dll Wrap is for using in Python 32bits windows to access I2C SPI and MDIO (by GPIO), and Demo with display PC sreen on OLED by i2c or SPI .

ch341dll_wrap_typcal_app A ch341dll Wrap is for using in Python 32bits windows to access I2C SPI and MDIO (by GPIO). In addition, I provided 3 Demo. I

13 Jan 02, 2023
Designed a system that can efficiently sort recyclables and transfer them to corresponding bins using Python, a Raspberry Pi, and Quanser Labs.

System for Sorting and Recycling Containers - Project 3 Table of contents Overview The challenge Screenshot My process Built with Code snippets What I

Mit Patel 2 Dec 02, 2022
Create a low powered, renewable generation forecast display with a Raspberry Pi Zero & Inky wHAT.

GB Renewable Forecast Display This Raspberry Pi powered eInk display aims to give you a quick way to time your home energy usage to help balance the g

Andy Brace 32 Jul 02, 2022