Skip to content

Commit ac54d0e

Browse files
initial module copied from viam-modular-resources
1 parent a78662d commit ac54d0e

File tree

9 files changed

+250
-0
lines changed

9 files changed

+250
-0
lines changed

.env

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
MODULE_DIR=$(dirname $0)
2+
VIRTUAL_ENV=$MODULE_DIR/.venv
3+
PYTHON=$VIRTUAL_ENV/bin/python

.github/workflows/build-action.yaml

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# see https://github.com/viamrobotics/build-action for help
2+
on:
3+
push:
4+
tags:
5+
- "*" # the build-action will trigger on all tags including RC versions
6+
7+
jobs:
8+
publish:
9+
runs-on: ubuntu-latest
10+
steps:
11+
- uses: actions/checkout@v3
12+
- uses: viamrobotics/build-action@v1
13+
with:
14+
# note: you can replace this line with 'version: ""' if
15+
# you want to test the build process without deploying
16+
version: ${{ github.ref_name }}
17+
ref: ${{ github.sha }}
18+
key-id: ${{ secrets.viam_key_id }}
19+
key-value: ${{ secrets.viam_key_value }}

LICENSE

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2024 Michael Lee
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.

build.sh

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
#!/bin/bash
2+
apt-get install -y python3.11-venv
3+
python3 -m venv .venv
4+
. .venv/bin/activate
5+
pip3 install -r requirements.txt
6+
python3 -m PyInstaller --onefile --hidden-import="googleapiclient" --hidden-import="viam-wrap" models.py
7+
tar -czvf dist/archive.tar.gz dist/models

exec.sh

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#!/usr/bin/env bash
2+
3+
# bash safe mode. look at `set --help` to see what these are doing
4+
set -euxo pipefail
5+
6+
cd $(dirname $0)
7+
source .env
8+
./setup.sh
9+
10+
# Be sure to use `exec` so that termination signals reach the python process,
11+
# or handle forwarding termination signals manually
12+
exec $PYTHON models.py $@

meta.json

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
{
2+
"module_id": "michaellee1019:ht16k33",
3+
"visibility": "public",
4+
"url": "https://github.com/michaellee1019/ht16k33",
5+
"description": "",
6+
"models": [
7+
{
8+
"api": "rdk:component:generic",
9+
"model": "michaellee1019:ht16k33:seg_14_x_4"
10+
}
11+
],
12+
"build": {
13+
"build": "sh build.sh",
14+
"path": "dist/archive.tar.gz",
15+
"arch" : ["linux/arm64", "linux/amd64"]
16+
},
17+
"entrypoint": "dist/models"
18+
}

models.py

+129
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
import viam_wrap
2+
from viam.components.generic import Generic
3+
from viam.proto.app.robot import ComponentConfig
4+
from typing import Mapping, Optional, Self
5+
from viam.utils import ValueTypes
6+
from viam.proto.common import ResourceName
7+
from viam.resource.base import ResourceBase
8+
import sys
9+
10+
# Import all board pins and bus interface.
11+
import board
12+
import busio
13+
14+
# Import the HT16K33 LED matrix module.
15+
from adafruit_ht16k33 import segments, ht16k33
16+
17+
class Ht16k33_Seg14x4(Generic):
18+
MODEL = "michaellee1019:ht16k33:seg_14_x_4"
19+
i2c = None
20+
segs = None
21+
22+
async def do_command(
23+
self,
24+
command: Mapping[str, ValueTypes],
25+
*,
26+
timeout: Optional[float] = None,
27+
**kwargs
28+
) -> Mapping[str, ValueTypes]:
29+
result = {key: False for key in command.keys()}
30+
for (name, args) in command.items():
31+
if name == 'marquee':
32+
if 'text' in args:
33+
#TODO: NoneType is not converted to None
34+
self.marquee(args['text'], args.get('delay'))
35+
result[name] = True
36+
else:
37+
result[name] = 'missing text parameter'
38+
if name == 'print':
39+
if 'value' in args:
40+
# TODO: decimal results in Error: TypeError - slice indices must be integers or None or have an __index__ method
41+
self.print(args['value'], args.get('decimal'))
42+
result[name] = True
43+
else:
44+
result[name] = 'missing value parameter'
45+
if name == 'print_hex':
46+
if 'value' in args:
47+
self.print_hex(args['value'])
48+
result[name] = True
49+
else:
50+
result[name] = 'missing value parameter'
51+
if name == 'scroll':
52+
if 'count' in args:
53+
self.scroll(args['count'])
54+
result[name] = True
55+
else:
56+
result[name] = 'missing count parameter'
57+
if name == 'set_digit_raw':
58+
if all(k in args for k in ('index','bitmask')):
59+
self.set_digit_raw(args['index'], args['bitmask'])
60+
result[name] = True
61+
else:
62+
result[name] = 'missing index and/or bitmask parameters'
63+
return result
64+
65+
66+
def marquee(self, text: str, delay: float) -> None:
67+
# TODO try to support loop
68+
self.segs.marquee(text, loop = False, delay= 0 if delay is None else delay)
69+
70+
def print(self, value, decimal: int) -> None:
71+
self.segs.print(value, decimal= 0 if decimal is None else decimal)
72+
73+
def print_hex(self, value: int) -> None:
74+
self.segs.print_hex(value)
75+
76+
def scroll(self, count: int) -> None:
77+
# TODO Error: IndexError - bytearray index out of range
78+
self.segs.scroll(2)
79+
80+
def set_digit_raw(self, index: int, bitmask: int) -> None:
81+
# TODO Error: TypeError - unsupported operand type(s) for &=: 'float' and 'int'
82+
self.segs.set_digit_raw(1, bitmask)
83+
84+
@classmethod
85+
def new(self, config: ComponentConfig, dependencies: Mapping[ResourceName, ResourceBase]) -> Self:
86+
self.i2c = busio.I2C(board.SCL, board.SDA)
87+
88+
brightness = None
89+
auto_write = None
90+
if 'brightness' in config.attributes.fields:
91+
brightness = config.attributes.fields["brightness"].number_value
92+
if 'auto_write' in config.attributes.fields:
93+
auto_write = config.attributes.fields["auto_write"].bool_value
94+
95+
addresses = config.attributes.fields["addresses"].list_value
96+
hex_addresses=[]
97+
for address in addresses:
98+
hex_addresses.append(int(address,16))
99+
# set brightness through base class
100+
101+
self.segs = segments.Seg14x4(
102+
i2c=self.i2c,
103+
address=hex_addresses,
104+
auto_write= True if auto_write is None else auto_write,
105+
chars_per_display=4)
106+
107+
if brightness is not None:
108+
ht16k33.HT16K33(self.i2c, hex_addresses, brightness=brightness)
109+
110+
output = self(config.name)
111+
return output
112+
113+
@classmethod
114+
def validate_config(self, config: ComponentConfig) -> None:
115+
addresses = config.attributes.fields["addresses"].list_value
116+
if addresses is None:
117+
raise Exception('A address attribute is required for seg_14_x_4 component. Must be a string array of 1 or more addresses in hexidecimal format such as "0x00".')
118+
119+
# TODO: assert len()>1, parse addresses here
120+
121+
return None
122+
123+
if __name__ == '__main__':
124+
# necessary for pyinstaller to see it
125+
# build this with:
126+
# pyinstaller --onefile --hidden-import viam-wrap --paths $VIRTUAL_ENV/lib/python3.10/site-packages installable.py
127+
# `--paths` arg may no longer be necessary once viam-wrap is published somewhere
128+
# todo: utility to append this stanza automatically at build time
129+
viam_wrap.main(sys.modules.get(__name__))

requirements.txt

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
viam-sdk
2+
pyinstaller
3+
git+https://github.com/viam-labs/1liner
4+
adafruit-circuitpython-ht16k33

setup.sh

+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
#!/usr/bin/env bash
2+
# setup.sh -- environment bootstrapper for python virtualenv
3+
4+
set -euo pipefail
5+
6+
SUDO=sudo
7+
if ! command -v $SUDO; then
8+
echo no sudo on this system, proceeding as current user
9+
SUDO=""
10+
fi
11+
12+
if command -v apt-get; then
13+
if dpkg --status python3-venv > /dev/null; then
14+
echo "python3-venv is installed, skipping setup"
15+
else
16+
if ! apt info python3-venv; then
17+
echo package info not found, trying apt update
18+
$SUDO apt-get -qq update
19+
fi
20+
$SUDO apt-get install -qqy python3-venv
21+
fi
22+
else
23+
echo Skipping tool installation because your platform is missing apt-get.
24+
echo If you see failures below, install the equivalent of python3-venv for your system.
25+
fi
26+
27+
source .env
28+
if [ -f $VIRTUAL_ENV/.install_complete ]; then
29+
echo "completion marker is present, skipping virtualenv setup"
30+
else
31+
sudo apt install -y git
32+
echo creating virtualenv at $VIRTUAL_ENV
33+
python3 -m venv $VIRTUAL_ENV
34+
echo installing dependencies from requirements.txt
35+
$VIRTUAL_ENV/bin/pip install -r requirements.txt
36+
touch $VIRTUAL_ENV/.install_complete
37+
fi

0 commit comments

Comments
 (0)