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
CircuitPython Driver for Adafruit 24LC32 I2C EEPROM Breakout 32Kbit / 4 KB

Introduction CircuitPython driver for Adafruit 24LC32 I2C EEPROM Breakout Dependencies This driver depends on: Adafruit CircuitPython Bus Device Regis

foamyguy 0 Dec 20, 2021
Custom component for interacting with Octopus Energy

Home Assistant Octopus Energy ** WARNING: This component is currently a work in progress ** Custom component built from the ground up to bring your Oc

David Kendall 116 Jan 02, 2023
AERO 421: Spacecraft Attitude, Dynamics, and Control Final Project.

AERO - 421 Final Project Redevelopment Spacecraft Attitude, Dynamics, and Control: Simulation to determine and control a satellite's attitude in LEO.

Gagandeep Thapar 3 Dec 16, 2022
This tool emulates an EMV-CAP device, to illustrate the article "Banque en ligne : à la decouverte d'EMV-CAP" published in MISC

About This tool emulates an EMV-CAP device, to illustrate the article "Banque en ligne : à la decouverte d'EMV-CAP" published in MISC, issue #56 and f

Philippe Teuwen 28 Nov 21, 2022
A global contest to grow and monitor your own food with Raspberry Pi

growlab A global contest to grow and monitor your own food with Raspberry Pi A capture from phototimer of my seed tray with a wide-angle camera positi

Alex Ellis 442 Dec 23, 2022
3d printable macropad

Pico Mpad A 3D printable macropad for automating frequently repeated actions. Hardware To build this project you need access to a 3d printer. The mode

Dmytro Panin 94 Jan 07, 2023
Iec62056-21-mqtt - Publish DSMR P1 telegrams acquired over IEC62056-21 to MQTT

IEC 62056-21 Publish DSMR P1 telegrams acquired over IEC62056-21 to MQTT. -21 is

Marijn Suijten 1 Jun 05, 2022
Extremely simple PyBadge examples to demonstrate different aspects of CircuitPython using PyBadge hardware.

BeginnerPyBadge I purchased a PyBadge recently. I'm new to hardware. I was surprised how hard it was to find easy examples demonstrating how different

Rubini LaForest 2 Oct 21, 2021
A Raspberry Pi Pico plant sensor hub coded in Micropython

plantsensor A Raspberry Pi Pico plant sensor hub coded in Micropython I used: 1x Raspberry Pi Pico - microcontroller 1x Waveshare Pico OLED 1.3 - scre

78 Sep 20, 2022
Python script for printing to the Hanshow price-tag

This repository contains Python code for talking to the ATC_TLSR_Paper open-source firmware for the Hanshow e-paper pricetag. Installation # Clone the

12 Oct 06, 2022
A python library written for the raspberry pi.

A python package for using certain components on the raspberry pi.

Builder212 1 Nov 09, 2021
Samples for robotics, node, python, and bash

RaspberryPi Robot Project Technologies: Render: intent Currently designed to act as programmable sentry.

Martin George 1 May 31, 2022
CircuitPython library for the CH559 USB to Serial chip

CH559 (USB to Serial) CircuitPython Library Why? Because you might want to get keyboard/mouse/gamepad/HID input into your CircuitPython projects witho

Guy Dupont 3 Nov 19, 2022
Isaac Gym Environments for Legged Robots

Isaac Gym Environments for Legged Robots This repository provides the environment used to train ANYmal (and other robots) to walk on rough terrain usi

Robotic Systems Lab - Legged Robotics at ETH Zürich 372 Jan 08, 2023
The project is an open-source and low-cost kit to get started with underactuated robotics.

Torque Limited Simple Pendulum Introduction The project is an open-source and low-cost kit to get started with underactuated robotics. The kit targets

34 Dec 14, 2022
ENC28J60 Ethernet chip driver for MicroPython (RP2)

micropy-ENC28J60 ENC28J60 Ethernet chip driver for MicroPython v1.17 (RP2) Rationale ENC28J60 is a popular and cheap module for DIY projects. At the m

11 Nov 16, 2022
An open source two key macro-pad modeled to look like a cartoony melting popsicle

macropopsicle An open source two key macro-pad modeled to look like a cartoony melting popsicle. Build instructions Parts List -1x Top case half (3D p

17 Aug 18, 2022
A dashboard for Raspberry Pi to display environmental weather data, rain radar, weather forecast, etc. written in Python

Weather Clock for Raspberry PI This project is a dashboard for Raspberry Pi to display environmental weather data, rain radar, weather forecast, etc.

Markus Geiger 1 May 01, 2022
Imbalaced Classification and Robust Semantic Segmentation

Imbalaced Classification and Robust Semantic Segmentation This repo implements two algoritms. The imbalance clibration (IC) algorithm for image classi

24 Jul 23, 2022
HA-Edge-Connector - HA Edge Connector For Python

HA-Edge-Connector 1. Required a. Smartthings Hub & Homeassistant must be in same

chals 21 Dec 29, 2022