SLASD 0.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- slasd/__init__.py +8 -0
- slasd/commands/__init__.py +1 -0
- slasd/commands/command.py +34 -0
- slasd/commands/noResp.py +24 -0
- slasd/fastrakAnimator.py +133 -0
- slasd/ledAnimationDriver.py +121 -0
- slasd-0.0.0.dist-info/METADATA +311 -0
- slasd-0.0.0.dist-info/RECORD +10 -0
- slasd-0.0.0.dist-info/WHEEL +4 -0
- slasd-0.0.0.dist-info/licenses/LICENSE +21 -0
slasd/__init__.py
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Marks the package containing the SLASD Commands."""
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"""Collection of serial command interfaces."""
|
|
2
|
+
|
|
3
|
+
from typing import Protocol
|
|
4
|
+
|
|
5
|
+
import serial
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class SerialCommand(Protocol):
|
|
9
|
+
"""Interface describing a generic serial command to the Arduino.
|
|
10
|
+
|
|
11
|
+
Attributes
|
|
12
|
+
----------
|
|
13
|
+
_commandId : str
|
|
14
|
+
ID of the command. Usually a single ASCII char.
|
|
15
|
+
_payload : bytearray
|
|
16
|
+
Data payload to send with command.
|
|
17
|
+
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
_commandId: str
|
|
21
|
+
_payload: bytearray
|
|
22
|
+
|
|
23
|
+
def send(self, ser: serial.Serial) -> None:
|
|
24
|
+
"""Send a single serial command to the Arduino.
|
|
25
|
+
|
|
26
|
+
Parameters
|
|
27
|
+
----------
|
|
28
|
+
ser : serial.Serial
|
|
29
|
+
Serial connection to send the frame on.
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
"""
|
|
33
|
+
cmdBytes = bytes(self._commandId, 'ASCII')
|
|
34
|
+
ser.write(cmdBytes + self._payload)
|
slasd/commands/noResp.py
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"""Fastrak serial commands with no response path."""
|
|
2
|
+
|
|
3
|
+
from .command import SerialCommand
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class SetLedState(SerialCommand):
|
|
7
|
+
"""Send a command to the Arduino to set the LED array state."""
|
|
8
|
+
|
|
9
|
+
def __init__(
|
|
10
|
+
self,
|
|
11
|
+
data: bytearray,
|
|
12
|
+
) -> None:
|
|
13
|
+
"""Class constructor.
|
|
14
|
+
|
|
15
|
+
Parameters
|
|
16
|
+
----------
|
|
17
|
+
data : bytearray
|
|
18
|
+
The data payload to provide to the Arduino.
|
|
19
|
+
|
|
20
|
+
"""
|
|
21
|
+
self._commandId = 'S'
|
|
22
|
+
self._payload = bytearray()
|
|
23
|
+
self._payload = data
|
|
24
|
+
self._payload += b'\n'
|
slasd/fastrakAnimator.py
ADDED
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
"""Contains the Fastrak device angular illuminator class."""
|
|
2
|
+
|
|
3
|
+
import struct
|
|
4
|
+
from math import floor
|
|
5
|
+
from typing import TypedDict
|
|
6
|
+
|
|
7
|
+
from fastrakSerialDriver.fastrakPosition import FastrakPostion
|
|
8
|
+
from typing_extensions import Unpack
|
|
9
|
+
|
|
10
|
+
from .ledAnimationDriver import LedAnimationDevice
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class FastrakParams(TypedDict):
|
|
14
|
+
r"""Describe the typing of the kwargs for the Fastrak animation state computation.
|
|
15
|
+
|
|
16
|
+
Attributes
|
|
17
|
+
----------
|
|
18
|
+
posData : FastrakPostion
|
|
19
|
+
A position reported by a Fastrak hardware device.
|
|
20
|
+
angleToLight : int
|
|
21
|
+
The angular range $\\theta$, in degrees, to light up. In the example below the `O`
|
|
22
|
+
correspond to lit LED and `X` to unlit LED.
|
|
23
|
+
```ascii
|
|
24
|
+
OOOOOOOOOOO
|
|
25
|
+
OOOOO OOOOO
|
|
26
|
+
OO OO
|
|
27
|
+
XO θ .'XX
|
|
28
|
+
X `. ------- .' X
|
|
29
|
+
X `. / \ .' X
|
|
30
|
+
X `. / X
|
|
31
|
+
X `. .' X
|
|
32
|
+
X ,-. .' X
|
|
33
|
+
X _(*_*)_ X
|
|
34
|
+
X (_ o _) X
|
|
35
|
+
X / o \ X
|
|
36
|
+
X (_/ \_) X
|
|
37
|
+
X X
|
|
38
|
+
X X
|
|
39
|
+
X X
|
|
40
|
+
X X
|
|
41
|
+
XX XX
|
|
42
|
+
XX XX
|
|
43
|
+
XXXXX XXXXX
|
|
44
|
+
XXXXXXXXXXX
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
colorR : int
|
|
48
|
+
The red component of the LED lit color.
|
|
49
|
+
colorG : int
|
|
50
|
+
The green component of the LED lit color.
|
|
51
|
+
colorB : int
|
|
52
|
+
The blue component of the LED lit color.
|
|
53
|
+
"""
|
|
54
|
+
|
|
55
|
+
posData: FastrakPostion
|
|
56
|
+
angleToLight: int
|
|
57
|
+
colorR: int
|
|
58
|
+
colorG: int
|
|
59
|
+
colorB: int
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
class FastrakAnimationDevice(LedAnimationDevice):
|
|
63
|
+
"""Implements LedAnimationDevice for the Fastrak look position use case."""
|
|
64
|
+
|
|
65
|
+
def _computeState(self, **kwargs: Unpack[FastrakParams]) -> bytearray: # ty:ignore[invalid-method-override]
|
|
66
|
+
"""Compute the state array for the LED in the Fastrak look position use case.
|
|
67
|
+
|
|
68
|
+
Parameters
|
|
69
|
+
----------
|
|
70
|
+
**kwargs : Unpack[FastrakParams]
|
|
71
|
+
Collection of key word arguments for the Fastrak look position use case.
|
|
72
|
+
|
|
73
|
+
Returns
|
|
74
|
+
-------
|
|
75
|
+
bytearray
|
|
76
|
+
The on/off and color state for each LED in the array.
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
"""
|
|
80
|
+
if (
|
|
81
|
+
kwargs is None
|
|
82
|
+
or 'posData' not in kwargs
|
|
83
|
+
or 'angleToLight' not in kwargs
|
|
84
|
+
or 'colorR' not in kwargs
|
|
85
|
+
or 'colorG' not in kwargs
|
|
86
|
+
or 'colorB' not in kwargs
|
|
87
|
+
or type(kwargs['posData']) is not FastrakPostion
|
|
88
|
+
or type(kwargs['angleToLight']) is not int
|
|
89
|
+
or type(kwargs['colorR']) is not int
|
|
90
|
+
or type(kwargs['colorG']) is not int
|
|
91
|
+
or type(kwargs['colorB']) is not int
|
|
92
|
+
):
|
|
93
|
+
raise TypeError
|
|
94
|
+
|
|
95
|
+
if kwargs['colorR'] < 0 or kwargs['colorR'] > 255:
|
|
96
|
+
raise TypeError
|
|
97
|
+
if kwargs['colorG'] < 0 or kwargs['colorG'] > 255:
|
|
98
|
+
raise TypeError
|
|
99
|
+
if kwargs['colorB'] < 0 or kwargs['colorB'] > 255:
|
|
100
|
+
raise TypeError
|
|
101
|
+
|
|
102
|
+
byteCr = struct.pack('<B', kwargs['colorR'])
|
|
103
|
+
byteCg = struct.pack('<B', kwargs['colorG'])
|
|
104
|
+
byteCb = struct.pack('<B', kwargs['colorB'])
|
|
105
|
+
|
|
106
|
+
if len(byteCb) != 1 or len(byteCg) != 1 or len(byteCr) != 1:
|
|
107
|
+
raise TypeError
|
|
108
|
+
|
|
109
|
+
pos = kwargs['posData']
|
|
110
|
+
lightAngle = kwargs['angleToLight']
|
|
111
|
+
litCenterLed = floor((self._ledCount / 360) * pos.psi)
|
|
112
|
+
lookAngleCnt = floor((self._ledCount / 360) * lightAngle)
|
|
113
|
+
payload = bytearray(b'\0' * (3 * self._ledCount))
|
|
114
|
+
|
|
115
|
+
for i in range(
|
|
116
|
+
floor(litCenterLed - (lookAngleCnt / 2)),
|
|
117
|
+
litCenterLed,
|
|
118
|
+
3,
|
|
119
|
+
):
|
|
120
|
+
payload[i] = byteCr[0]
|
|
121
|
+
payload[i + 1] = byteCg[0]
|
|
122
|
+
payload[i + 2] = byteCb[0]
|
|
123
|
+
|
|
124
|
+
for i in range(
|
|
125
|
+
litCenterLed,
|
|
126
|
+
floor(litCenterLed + (lookAngleCnt / 2)) + 1,
|
|
127
|
+
3,
|
|
128
|
+
):
|
|
129
|
+
payload[i] = byteCr[0]
|
|
130
|
+
payload[i + 1] = byteCg[0]
|
|
131
|
+
payload[i + 2] = byteCb[0]
|
|
132
|
+
|
|
133
|
+
return payload
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
"""Base class for an LED animation driver."""
|
|
2
|
+
|
|
3
|
+
from serial import Serial
|
|
4
|
+
|
|
5
|
+
from .commands.noResp import SetLedState
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class LedAnimationDevice:
|
|
9
|
+
"""Defines interface for connecting, setting up, and streaming from a Fastrak.
|
|
10
|
+
|
|
11
|
+
Attributes
|
|
12
|
+
----------
|
|
13
|
+
_ser : Serial | None
|
|
14
|
+
Serial connection to an Arduino.
|
|
15
|
+
|
|
16
|
+
_COMport :
|
|
17
|
+
String representing the COM port to be connected to.
|
|
18
|
+
|
|
19
|
+
_baud : SerialBaudrates
|
|
20
|
+
Baudrate for the serial connection.
|
|
21
|
+
|
|
22
|
+
_timeout : int, default: 1second
|
|
23
|
+
Serial timeout for the connection.
|
|
24
|
+
|
|
25
|
+
_ledCount: int
|
|
26
|
+
The number of LED in the array.
|
|
27
|
+
|
|
28
|
+
"""
|
|
29
|
+
|
|
30
|
+
_ser: Serial | None
|
|
31
|
+
_COMport: str
|
|
32
|
+
_baud: int
|
|
33
|
+
_timeout: int
|
|
34
|
+
_ledCount: int
|
|
35
|
+
|
|
36
|
+
def __init__(
|
|
37
|
+
self,
|
|
38
|
+
COMport: str = 'COM1',
|
|
39
|
+
baud: int = 115200,
|
|
40
|
+
timeout: int = 1,
|
|
41
|
+
ledCount: int = 100,
|
|
42
|
+
setup: bool = True,
|
|
43
|
+
) -> None:
|
|
44
|
+
"""Construct a LedAnimationDevice class.
|
|
45
|
+
|
|
46
|
+
Parameters
|
|
47
|
+
----------
|
|
48
|
+
COMport : str
|
|
49
|
+
String representing the COM port to be connected to.
|
|
50
|
+
|
|
51
|
+
baud : int, default: 1115200
|
|
52
|
+
Baudrate for the serial connection.
|
|
53
|
+
|
|
54
|
+
timeout : int, default: 1second
|
|
55
|
+
Serial timeout for the connection.
|
|
56
|
+
|
|
57
|
+
ledCount: int, defualt: 100
|
|
58
|
+
The number of LED in the array.
|
|
59
|
+
|
|
60
|
+
setup : int, default: True
|
|
61
|
+
Flag indicating if the device should connect to the serial interface.
|
|
62
|
+
|
|
63
|
+
"""
|
|
64
|
+
self._ser = None
|
|
65
|
+
self._COMport = COMport
|
|
66
|
+
self._baud = baud
|
|
67
|
+
self._timeout = timeout
|
|
68
|
+
self._ledCount = ledCount
|
|
69
|
+
if setup:
|
|
70
|
+
self.connect()
|
|
71
|
+
|
|
72
|
+
def connect(self) -> None:
|
|
73
|
+
"""Connect to the serial device."""
|
|
74
|
+
if self._ser is not None:
|
|
75
|
+
if not self._ser.is_open:
|
|
76
|
+
self._ser.open()
|
|
77
|
+
else:
|
|
78
|
+
self._ser = Serial(self._COMport, self._baud, timeout=self._timeout)
|
|
79
|
+
|
|
80
|
+
def _sendState(self, data: bytearray) -> None:
|
|
81
|
+
"""Send state data to the serial device.
|
|
82
|
+
|
|
83
|
+
Parameters
|
|
84
|
+
----------
|
|
85
|
+
data : bytearray
|
|
86
|
+
LED array state data to send to the device.
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
"""
|
|
90
|
+
if self._ser is not None:
|
|
91
|
+
SetLedState(data).send(self._ser)
|
|
92
|
+
|
|
93
|
+
def _computeState(self, **kwargs) -> bytearray:
|
|
94
|
+
"""State computation interface.
|
|
95
|
+
|
|
96
|
+
Parameters
|
|
97
|
+
----------
|
|
98
|
+
**kwargs: dict
|
|
99
|
+
Collection of keyword arguments. Unique to each animation class.
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
Returns
|
|
103
|
+
-------
|
|
104
|
+
bytearray
|
|
105
|
+
The computed state of the LED array.
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
"""
|
|
109
|
+
raise NotImplementedError
|
|
110
|
+
|
|
111
|
+
def compNSndState(self, **kwargs) -> None:
|
|
112
|
+
"""Compute and set the state of the LED array.
|
|
113
|
+
|
|
114
|
+
Parameters
|
|
115
|
+
----------
|
|
116
|
+
**kwargs : dict
|
|
117
|
+
Collection of keyword arguments. Unique to each animation class.
|
|
118
|
+
|
|
119
|
+
"""
|
|
120
|
+
payload = self._computeState(**kwargs)
|
|
121
|
+
self._sendState(payload)
|
|
@@ -0,0 +1,311 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: SLASD
|
|
3
|
+
Version: 0.0.0
|
|
4
|
+
Summary: A serial driver and arduino project for 'animating' on a simple LED string.
|
|
5
|
+
License-File: LICENSE
|
|
6
|
+
Requires-Python: >=3.10
|
|
7
|
+
Requires-Dist: fastrakserialdriver>=0.2.1
|
|
8
|
+
Requires-Dist: pyserial>=3.5
|
|
9
|
+
Description-Content-Type: text/markdown
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
title: Simple Arduino Controlled LED Serial Driver
|
|
13
|
+
authors:
|
|
14
|
+
- joe_starr
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
[](https://opensource.org/licenses/MIT)
|
|
18
|
+
[{width=10%}](https://brainmade.org)
|
|
19
|
+
|
|
20
|
+

|
|
21
|
+
|
|
22
|
+
/// caption
|
|
23
|
+
Arduino Mega from `amperka/hardware-drawings` [@amperka_hardware_drawings_2016]
|
|
24
|
+
///
|
|
25
|
+
|
|
26
|
+
## Note to Reader
|
|
27
|
+
|
|
28
|
+
### What Am I?
|
|
29
|
+
|
|
30
|
+
This repository contains an Arduino sketch which uses the FastLED library to control a collection
|
|
31
|
+
(strip) of NEOPIXEL LED. The repository also contains a Python serial driver for commanding the
|
|
32
|
+
Arduino. The python side is primarily designed around controlling the LED array based on feedback
|
|
33
|
+
from a [Polhemus Fastrak](https://polhemus.com/all-trackers/fastrak).
|
|
34
|
+
|
|
35
|
+
Simple installation by pip. You should probably be using uv projects: `uv add SLASD`
|
|
36
|
+
|
|
37
|
+
### About the Documentation
|
|
38
|
+
|
|
39
|
+
The following document describes the "rules" and expectation for development. The
|
|
40
|
+
["API Reference"](./reference/fastrakSerialDriver/) page contains the technical context descriptions
|
|
41
|
+
found in the source files. The ["Use Cases"](./content/usecase/usecase) page contains a collection
|
|
42
|
+
of use cases and a use case diagram for the tool. The ["Decisions"](./content/madr/) page contains a
|
|
43
|
+
collection of [architectural decision records](https://adr.github.io/madr/) [@Kopp2018] giving
|
|
44
|
+
context on why this tool is the way it is.
|
|
45
|
+
|
|
46
|
+
### Issues
|
|
47
|
+
|
|
48
|
+
If you discover an issue with this repository or have a question, please feel free to open an issue.
|
|
49
|
+
I've included templates for the following issues:
|
|
50
|
+
|
|
51
|
+
- 🖋️ Spelling and Grammar: Found some language that is incorrect?
|
|
52
|
+
- 🤷 Clarity: Found a section that just makes no sense?
|
|
53
|
+
- ❓ Question: Do you have a general question?
|
|
54
|
+
- 🐞 Bug: Found an error in the code?
|
|
55
|
+
- 🚀 Enhancement: Have a suggestion for improving the toolchain?
|
|
56
|
+
|
|
57
|
+
[:fontawesome-solid-paper-plane: Open Issue!](https://github.com/Nontrivial-Solutions/psychopy-6dof/issues/new/choose){ .md-button }
|
|
58
|
+
|
|
59
|
+
## 📃 Cite Me
|
|
60
|
+
|
|
61
|
+
## ⚖️ License
|
|
62
|
+
|
|
63
|
+
Documentation:
|
|
64
|
+
[](https://creativecommons.org/licenses/by-sa/4.0/)
|
|
65
|
+
|
|
66
|
+
Code:
|
|
67
|
+
[](https://opensource.org/licenses/MIT)
|
|
68
|
+
|
|
69
|
+
## Planning and Administration
|
|
70
|
+
|
|
71
|
+
### Tasks
|
|
72
|
+
|
|
73
|
+
Tasks are tracked as GitHub issues.
|
|
74
|
+
|
|
75
|
+
### Version Control
|
|
76
|
+
|
|
77
|
+
The toolchain shall be kept under Git versioning. Development shall take place on branches with
|
|
78
|
+
`main` on GitHub as a source of truth. GitHub pull requests shall serve as the arbiter for inclusion
|
|
79
|
+
on main with the following quality gates:
|
|
80
|
+
|
|
81
|
+
- Running and passing the unit test suite.
|
|
82
|
+
- Running and passing linting and style enforcers.
|
|
83
|
+
- Successful generation of documentation.
|
|
84
|
+
|
|
85
|
+
#### Release Tagging
|
|
86
|
+
|
|
87
|
+
The project shall be tagged when a new feature or bug fix is merged into main. The tag shall follow
|
|
88
|
+
[semantic versioning](https://semver.org) for labels.
|
|
89
|
+
|
|
90
|
+
```text
|
|
91
|
+
vMAJOR.MINOR.PATCH
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### Project Structure
|
|
95
|
+
|
|
96
|
+
Files and directories shall be lower case, where capital is not required by a tool, and contain no
|
|
97
|
+
`' '`.
|
|
98
|
+
|
|
99
|
+
```text
|
|
100
|
+
📁 .
|
|
101
|
+
├── 📁 .github
|
|
102
|
+
│ ├── 📁 ISSUE_TEMPLATE
|
|
103
|
+
│ ├── 📁 PULL_REQUEST_TEMPLATE
|
|
104
|
+
│ ├── 📁 workflows
|
|
105
|
+
│ └── 📝 pull_request_template.md
|
|
106
|
+
├── 📁 .vscode
|
|
107
|
+
│ └── ⚙️ launch.json
|
|
108
|
+
├── 📁 docs
|
|
109
|
+
│ ├── 📁 contentt
|
|
110
|
+
│ │ ├── 📁 madr
|
|
111
|
+
│ │ ├── 📁 units
|
|
112
|
+
│ │ └── 📁 usecase
|
|
113
|
+
│ ├── 📁 infra
|
|
114
|
+
│ └── 📖 README.md
|
|
115
|
+
├── 📁 arduino_src
|
|
116
|
+
│ └── 🇨 arduino_src.ino
|
|
117
|
+
├── 📁 slasd
|
|
118
|
+
│ └── 🐍 __init__.py
|
|
119
|
+
├── ⚙️ .editorconfig
|
|
120
|
+
├── 🙈 .gitignore
|
|
121
|
+
├── 🛠️ .pre-commit-config.yaml
|
|
122
|
+
├── ⚙️ .rumdl.toml
|
|
123
|
+
├── ❄️ flake.lock
|
|
124
|
+
├── ❄️ flake.nix
|
|
125
|
+
├── 🛠️ Justfile
|
|
126
|
+
├── 📜 LICENSE
|
|
127
|
+
├── 📄 mkdocs.yml
|
|
128
|
+
├── 🐍 pyproject.toml
|
|
129
|
+
└── 🔒 uv.lock
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
### Directories of Interest
|
|
133
|
+
|
|
134
|
+
- docs: This directory contains the high level documentation for the tool.
|
|
135
|
+
- arduino_src: This directory contains the source code of the Arduino side of the tool.
|
|
136
|
+
- slasd: This directory contains the source code of the python side of the tool.
|
|
137
|
+
- .github: This directory contains the GitHub infrastructure.
|
|
138
|
+
- .vscode: This directory contains the debugger configuration.
|
|
139
|
+
|
|
140
|
+
### Define a Unit
|
|
141
|
+
|
|
142
|
+
A unit shall be a Python module.
|
|
143
|
+
|
|
144
|
+
### Quality
|
|
145
|
+
|
|
146
|
+
The tool and its units shall fail-safe, that is the tool and its units can fail, but the failure
|
|
147
|
+
must be detectable. A segfault is okay, an off by one error that computes the wrong value is not.
|
|
148
|
+
|
|
149
|
+
#### Unit Testing
|
|
150
|
+
|
|
151
|
+
No unit testing in the project only integration testing. See
|
|
152
|
+
[ADR00002][./content/madr/00002_testing.md].
|
|
153
|
+
|
|
154
|
+
#### Integration Testing
|
|
155
|
+
|
|
156
|
+
The plugin shall have manual integration testing.
|
|
157
|
+
|
|
158
|
+
### Requirements
|
|
159
|
+
|
|
160
|
+
#### Use Cases
|
|
161
|
+
|
|
162
|
+
Requirements are described as a collection of use cases and actors. There are two collections of the
|
|
163
|
+
artifacts one for the [client](./content/arduino_src/usecase/) and one for the
|
|
164
|
+
[server](./content/python_driver/usecase/usecase/). These are in turn collected into the following
|
|
165
|
+
use case diagrams:
|
|
166
|
+
|
|
167
|
+
##### Client
|
|
168
|
+
|
|
169
|
+
```mermaid
|
|
170
|
+
flowchart LR
|
|
171
|
+
aS["👤 Server"]
|
|
172
|
+
|
|
173
|
+
SS(["Set State"])
|
|
174
|
+
RC(["Receive Command"])
|
|
175
|
+
|
|
176
|
+
aS --> RC
|
|
177
|
+
|
|
178
|
+
RC -. include .->SS
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
##### Server
|
|
182
|
+
|
|
183
|
+
```mermaid
|
|
184
|
+
flowchart LR
|
|
185
|
+
aU["👤 User"]
|
|
186
|
+
|
|
187
|
+
SC(["Send Command"])
|
|
188
|
+
|
|
189
|
+
aU --> SC
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
##### Architectural Decisions
|
|
193
|
+
|
|
194
|
+
Architectural decisions [MADR](<https://github.com/adr/madr>) [@Kopp2018] serve as the primary
|
|
195
|
+
documentation for architectural decisions.
|
|
196
|
+
|
|
197
|
+
The following is the order of operations for the proposal of a MADR:
|
|
198
|
+
|
|
199
|
+
1. Create a branch for a proposal with the name:
|
|
200
|
+
|
|
201
|
+
```text
|
|
202
|
+
proposal-{{short title}}
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
1. Create a pull request with this template.
|
|
206
|
+
1. In the branch create a Markdown file based on the
|
|
207
|
+
[MADR Template](https://github.com/adr/madr/blob/4.0.0/template/adr-template.md). Name the
|
|
208
|
+
Markdown file:
|
|
209
|
+
|
|
210
|
+
```text
|
|
211
|
+
{{issue# padded to five digits}}-{{title}}
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
1. When a decision is made change the status to:
|
|
215
|
+
- "accepted" and pull the branch into main branch
|
|
216
|
+
- "rejected" and pull the branch into main branch
|
|
217
|
+
|
|
218
|
+
#### Nonfunctional Requirements
|
|
219
|
+
|
|
220
|
+
##### Colors
|
|
221
|
+
|
|
222
|
+
Diagrams included in documentation for features (use case and unit descriptions) are expected to use
|
|
223
|
+
the [COLORS](https://clrs.cc) color palette.
|
|
224
|
+
|
|
225
|
+
##### Technologies
|
|
226
|
+
|
|
227
|
+
###### Languages and Frameworks
|
|
228
|
+
|
|
229
|
+
- git
|
|
230
|
+
- Python
|
|
231
|
+
- mermaid.js
|
|
232
|
+
- prek
|
|
233
|
+
- tombi
|
|
234
|
+
- rumdl
|
|
235
|
+
- ruff
|
|
236
|
+
- uv
|
|
237
|
+
- MADR[@Kopp2018]
|
|
238
|
+
|
|
239
|
+
###### Documentation of Implementation
|
|
240
|
+
|
|
241
|
+
###### Code Style Guide
|
|
242
|
+
|
|
243
|
+
Python code shall be formatted with ruff using the included style settings. Markdown files shall be
|
|
244
|
+
formatted with ruff using the included style settings. TOML files shall be formatted with tombi
|
|
245
|
+
using the included style settings.
|
|
246
|
+
|
|
247
|
+
## Design and Documentation
|
|
248
|
+
|
|
249
|
+
### System
|
|
250
|
+
|
|
251
|
+
#### Block Diagram
|
|
252
|
+
|
|
253
|
+
```mermaid
|
|
254
|
+
flowchart LR
|
|
255
|
+
device["BaseLedAnimator"]
|
|
256
|
+
cwr@{ shape: processes, label: "{{Collection}}<br>Device specific animators" }
|
|
257
|
+
commands@{ shape: processes, label: "{{Collection}}<br>Available Commands" }
|
|
258
|
+
|
|
259
|
+
device --> cwr
|
|
260
|
+
device --> commands
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
#### Class Diagram
|
|
264
|
+
|
|
265
|
+
```mermaid
|
|
266
|
+
classDiagram
|
|
267
|
+
class LedAnimationDevice {
|
|
268
|
+
+ init( COMport, baud, timeout, ledCount)
|
|
269
|
+
+ connect()
|
|
270
|
+
+ compNSndState( **kwargs)
|
|
271
|
+
- sendState( data)
|
|
272
|
+
- computeState( **kwargs)
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
class FastrakAnimationDevice {
|
|
276
|
+
- computeState( **kwargs)
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
class FastrakParams {
|
|
280
|
+
+ FastrakPostion posData
|
|
281
|
+
+ int angleToLight
|
|
282
|
+
+ int colorR
|
|
283
|
+
+ int colorG
|
|
284
|
+
+ int colorB
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
|
|
288
|
+
class SetLedState {
|
|
289
|
+
+ init(self, data)
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
class SerialCommand {
|
|
293
|
+
<<interface>>
|
|
294
|
+
- str commandId
|
|
295
|
+
- bytearray payload
|
|
296
|
+
+ send(ser)
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
SetLedState ..|> SerialCommand
|
|
300
|
+
|
|
301
|
+
FastrakAnimationDevice --|> LedAnimationDevice
|
|
302
|
+
|
|
303
|
+
FastrakParams --* FastrakAnimationDevice
|
|
304
|
+
SetLedState --* LedAnimationDevice
|
|
305
|
+
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
#### Unit Designs
|
|
309
|
+
|
|
310
|
+
Unit designs (and test description) for the client and server units (public members and methods) is
|
|
311
|
+
found under their respective documentation sections.
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
slasd/__init__.py,sha256=1woE1s4Dk7Jc9BGPlw4xKww2jBURu8Nf-ZzIkr8yMEI,248
|
|
2
|
+
slasd/fastrakAnimator.py,sha256=qfE3q4pyyOblf2SyZxkOFsxgeP3PvvelBBxtxrnMX_I,4471
|
|
3
|
+
slasd/ledAnimationDriver.py,sha256=Td-JTnqrrRZ4n3TBGjPxnB-M2xVJoFspRJGGQosnD9Y,2971
|
|
4
|
+
slasd/commands/__init__.py,sha256=n2FGkS4jOSkVD_NJhlYWtpvSDvD_Fxw97gdKEqoSTXw,55
|
|
5
|
+
slasd/commands/command.py,sha256=qPvRmlArAseudxJs-pCy05x8t4Fo9N5Z-aMUnVybt7Y,756
|
|
6
|
+
slasd/commands/noResp.py,sha256=S1o8DEfe_MgGFGBLNAL7dDVoC5bXn_pFiR-uwnvQlRA,555
|
|
7
|
+
slasd-0.0.0.dist-info/METADATA,sha256=yUaTCQIw7AsAuJUxVwc2phaowanh0uPY4-f-GS7jVcs,8553
|
|
8
|
+
slasd-0.0.0.dist-info/WHEEL,sha256=W3fkpkm7-wf9vBI5Z-7s0eWkeM-spu78I8Neb98DeEg,87
|
|
9
|
+
slasd-0.0.0.dist-info/licenses/LICENSE,sha256=1MTKLFfNXi_QF-p6BP0RGjsHRii9jsza5z1ExtHxvwM,1065
|
|
10
|
+
slasd-0.0.0.dist-info/RECORD,,
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Joe Starr
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|