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
Point Density-Aware Voxels for LiDAR 3D Object Detection (CVPR 2022)

PDV PDV is LiDAR 3D object detection method. This repository is based off [OpenPCDet]. Point Density-Aware Voxels for LiDAR 3D Object Detection Jordan

Toronto Robotics and AI Laboratory 114 Dec 21, 2022
Example for Calculating Robot Dynamics Using Pinocchio Library

A Example for Calculating Robot Dynamics Using Pinocchio Library Developed by: Xinyang Tian. Platform: Linux + Pinocchio. In this work, i use Pinocchi

Rot_Tianers 33 Dec 28, 2022
Pylorawan is a Micropython wrapper for lorawan devices from RAK Wireless.

pylorawan Pylorawan is a Micropython wrapper for lorawan devices from RAK Wireless. Tested on a Raspberry PI Pico with a RAK4200(H) Evaluation Board (

Peter Houghton 3 Nov 04, 2022
Setup DevTerm to be a cool non-GUI device

DevTerm hobby project I bought this amazing device: DevTerm A-0604. It has a beefy ARM processor, runs a custom version of Armbian, embraces Open Sour

Alex Shteinikov 9 Nov 17, 2022
Alternative firmware for ESP8266 with easy configuration using webUI, OTA updates, automation using timers or rules, expandability and entirely local control over MQTT, HTTP, Serial or KNX. Full documentation at

Alternative firmware for ESP8266/ESP32 based devices with easy configuration using webUI, OTA updates, automation using timers or rules, expandability

Theo Arends 59 Dec 26, 2022
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
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
A Python script to monitor the latest block on an LCD.

PiHole-Monitoring A Python script to monitor the latest block on a lcd display. The first number represents the dns queries from the last 24h, the sec

Maxi 4 Dec 05, 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
Unofficial Playdate reverse-engineering notes/tools - covers file formats, server API and USB commands

Unofficial Playdate reverse-engineering notes/tools - covers file formats, server API and USB commands ⚠️ This documentation is unofficial and is not

James 106 Dec 31, 2022
🌱 - WebhookHard◞ Fines Educativos ◟

v1.0.0 WebhookHardware ¿Que es WebhookHardware? WebhookHardware se trata de un proyecto tratado para sacar informacion sobre el hardware de tus victim

3 Jun 14, 2021
Simples Keylogger para Windows com um autoboot implementado no sistema

MKW Keylogger Keylogger simples para Windos com um autoboot implementado no sistema, o malware irá capturar pressionamentos de tecla e armazená-lo em

3 Jul 03, 2021
A install script for installing qtile and my configs on Raspberry Pi OS

QPI OS - Qtile + Raspberry PI OS Qtile + Raspberry Pi OS :) Installation Run this command in the terminal

RPICoder 3 Dec 19, 2021
KIRI - Keyboard Interception, Remapping, and Injection using Raspberry Pi as an HID Proxy.

KIRI - Keyboard Interception, Remapping and Injection using Raspberry Pi as a HID Proxy. Near limitless abilities for a keyboard warrior. Features Sim

Viggo Falster 10 Dec 23, 2022
ModbusTCP2MQTT - Sungrow & SMA Solar Inverter addon for Home Assistant

ModbusTCP2MQTT Sungrow & SMA Solar Inverter addon for Home Assistant This addon will connect directly to your Inverter using Modbus TCP. Support model

Teny Smart 40 Dec 21, 2022
Keystroke logging, often referred to as keylogging or keyboard capturing

Keystroke logging, often referred to as keylogging or keyboard capturing, is the action of recording the keys struck on a keyboard, typically covertly, so that a person using the keyboard is unaware

Bhumika R 2 Jan 11, 2022
Raspberry Pi Power Button - Wake/Power Off/Restart(Double Press)

Control Raspberry pi with physically attached button. Wake, Power Off, and Restart (Double Press) . Python3 script runs as a service with easy installation.

Stas Yakobov 16 Oct 22, 2022
A python module for interacting with rolimon's, a roblox value site.

rpi - rolimon's python interaction rpi is an open source python-based rolimon's api wrapper. It provides an end-to-end pipeline in which each componen

Acier 11 Nov 08, 2022
🎃 Some spooky code samples to hack yourself a pumpkin 👻

🎃 Tech Or Treat 👻 It's spooky season for those who celebrate Halloween, and to get in the spirit (spirit - get it? 👻 ) we thought it would be fun t

Jim Bennett 5 Feb 07, 2022
Make your MacOS keyboard brightness fade in and out

Make your MacOS keyboard brightness fade in and out. (It's working depends on the Kbrightness file, which only works for 2015 Macs, so this will only work on 2015 Macs.)

1 Dec 16, 2021