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
Python code written to utilize the Korlan usb2can hardware to send and receive data over the can-bus on a 2008 Nissan 350z

nissan_ecu_hacking Python code written to utilize the Korlan usb2can hardware to send and receive data over the can-bus on a 2008 Nissan 350z My goal

Liam Goss 11 Sep 24, 2022
DongshanPI Seven for STM32MP157DAC.

STM32MP1 Buildroot External Tree

DongshanPI 14 May 06, 2022
Activate Numpad inside the touchpad with top right corner switch or F8 key

This is a python service which enables switching between numpad and touchpad for the Asus UX433. It may work for other models.

Mohamed Badaoui 230 Jan 08, 2023
Micropython-wifimanager-esp8266 - Simple Wifi Manager for ESP8266 using MicroPython

micropython-wifimanager-esp8266 Simple Wifi Manager for ESP8266 using MicroPytho

Abhinuv Nitin Pitale 1 Jan 04, 2022
Smart Tech Automation Remote via Kinematics Gesture control for IoT devices

STARK Smart Tech Automation Remote via Kinematics Gesture control for IoT devices View Demo · Report Bug · Request Feature Table of Contents About The

Juseong (Joe) Kim 1 Jan 29, 2022
Andreas Frisch 1 Jan 10, 2022
DNP3 Stalker is a project to analyze and interact with DNP3 devices

DNP3 Stalker Purpose DNP3 Stalker is a project to analyze and interact with DNP3

Cutaway Security, LLC. 2 Feb 10, 2022
Jarvis: a personal assistant which can help you to manage your system

Jarvis Jarvis is personal AI based assistant which can help you to manage stuff in your computer. This is demo but I decided to make it more better so

2 Jun 02, 2022
A lightweight script for updating custom components for Home Assistant

Updater for Home Assistant This is a lightweight script for updating custom components for Home Assistant. If for some reason you do not want to use H

Alex X 12 Sep 21, 2022
GUI wrapper designed for convenient service work with TI CC1352/CC2538/CC2652 based Zigbee sticks or gateways. Packed into single executable file

ZigStar GW Multi tool is GUI wrapper firtsly designed for convenient service work with Zig Star LAN GW, but now supports any TI CC1352/CC2538/CC2652 b

133 Jan 01, 2023
hardware design of the 250mm drone

hardware design of the 250mm drone

ZJU FAST Lab 645 Dec 25, 2022
I made this so I can control my Tapo L510 light bulb and Govee H6159 light strip using the PyP100 module and the Govee public API

TAPO-And-Govee-Controller I made this so I can control my Tapo L510 light bulb and Govee H6159 light strip using the PyP100 module and the Govee publi

James Westhead 0 Nov 23, 2021
Yet another automation project because a smart light is more than just on or off.

Automate home Yet another home automation project because a smart light is more than just on or off. Overview When talking about home automation there

Maja Massarini 62 Oct 10, 2022
Turns a compatible Raspberry Pi device into a smart USB drive for PS4/PS5.

PSBerry A WIP project for Raspberry Pi, which turns a compatible RPI device into a smart USB drive for PS4/PS5. Allows for save management of PS4 game

Filip Tomaszewski 2 Jan 15, 2022
Claussoft Personal Digital Assistant

Claussoft Personal Digital Assistant Install on Linux $ sudo apt update $ sudo apt install espeak ffmpeg libespeak1 portaudio19-dev $ pip install -r r

Christian Clauss 3 Dec 14, 2022
NYCT-GTFS - Real-time NYC subway data parsing for humans

NYCT-GTFS - Real-time NYC subway data parsing for humans This python library provides a human-friendly, native python interface for dealing with the N

Andrew Dickinson 37 Dec 27, 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
raspberry pi servo control using pca9685

RPi_servo-control_pca9685 raspberry pi 180° servo control using pca9685 Requirements Requires you to have the adafruit servokit library installed You

1 Jan 10, 2022
A versatile program that uses the raspberry pi camera and provides it as a service

PiCameleon Is a daemon program meant to provide the RaspberryPi Camera as a service while running according to a configuration.

André Esser 52 Oct 16, 2022