bluer-sbc 8.3.1__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.
Potentially problematic release.
This version of bluer-sbc might be problematic. Click here for more details.
- bluer_sbc/.abcli/abcli.sh +12 -0
- bluer_sbc/.abcli/actions.sh +11 -0
- bluer_sbc/.abcli/adafruit_rgb_matrix.sh +14 -0
- bluer_sbc/.abcli/alias.sh +5 -0
- bluer_sbc/.abcli/blue_sbc.sh +11 -0
- bluer_sbc/.abcli/camera.sh +20 -0
- bluer_sbc/.abcli/grove.sh +43 -0
- bluer_sbc/.abcli/hat.sh +22 -0
- bluer_sbc/.abcli/install/adafruit_rgb_matrix.sh +15 -0
- bluer_sbc/.abcli/install/grove.sh +29 -0
- bluer_sbc/.abcli/install/lepton.sh +33 -0
- bluer_sbc/.abcli/install/rpi.sh +65 -0
- bluer_sbc/.abcli/install/scroll_phat_hd.sh +14 -0
- bluer_sbc/.abcli/install/sparkfun_top_phat.sh +33 -0
- bluer_sbc/.abcli/install/template.sh +9 -0
- bluer_sbc/.abcli/install/unicorn_16x16.sh +16 -0
- bluer_sbc/.abcli/lepton.sh +15 -0
- bluer_sbc/.abcli/scroll_phat_hd.sh +14 -0
- bluer_sbc/.abcli/session.sh +39 -0
- bluer_sbc/.abcli/sparkfun_top_phat.sh +27 -0
- bluer_sbc/.abcli/tests/README.sh +8 -0
- bluer_sbc/.abcli/tests/camera.sh +47 -0
- bluer_sbc/.abcli/tests/help.sh +65 -0
- bluer_sbc/.abcli/tests/version.sh +8 -0
- bluer_sbc/.abcli/unicorn_16x16.sh +14 -0
- bluer_sbc/README.py +51 -0
- bluer_sbc/__init__.py +17 -0
- bluer_sbc/__main__.py +16 -0
- bluer_sbc/algo/__init__.py +0 -0
- bluer_sbc/algo/diff.py +81 -0
- bluer_sbc/config.env +30 -0
- bluer_sbc/env.py +35 -0
- bluer_sbc/hardware/__init__.py +38 -0
- bluer_sbc/hardware/adafruit_rgb_matrix.py +30 -0
- bluer_sbc/hardware/display.py +112 -0
- bluer_sbc/hardware/grove.py +104 -0
- bluer_sbc/hardware/hardware.py +58 -0
- bluer_sbc/hardware/hat/__init__.py +0 -0
- bluer_sbc/hardware/hat/__main__.py +91 -0
- bluer_sbc/hardware/hat/abstract.py +136 -0
- bluer_sbc/hardware/hat/prototype.py +161 -0
- bluer_sbc/hardware/screen.py +17 -0
- bluer_sbc/hardware/scroll_phat_hd.py +35 -0
- bluer_sbc/hardware/sparkfun_top_phat/__init__.py +0 -0
- bluer_sbc/hardware/sparkfun_top_phat/__main__.py +51 -0
- bluer_sbc/hardware/sparkfun_top_phat/classes.py +104 -0
- bluer_sbc/hardware/unicorn_16x16.py +44 -0
- bluer_sbc/help/__init__.py +0 -0
- bluer_sbc/help/__main__.py +10 -0
- bluer_sbc/help/adafruit_rgb_matrix.py +23 -0
- bluer_sbc/help/camera.py +71 -0
- bluer_sbc/help/functions.py +52 -0
- bluer_sbc/help/grove.py +59 -0
- bluer_sbc/help/hat.py +56 -0
- bluer_sbc/help/lepton.py +39 -0
- bluer_sbc/help/scroll_phat_hd.py +23 -0
- bluer_sbc/help/session.py +26 -0
- bluer_sbc/help/sparkfun_top_phat.py +26 -0
- bluer_sbc/help/unicorn_16x16.py +23 -0
- bluer_sbc/host.py +11 -0
- bluer_sbc/imager/__init__.py +16 -0
- bluer_sbc/imager/camera/__init__.py +3 -0
- bluer_sbc/imager/camera/__main__.py +69 -0
- bluer_sbc/imager/camera/classes.py +259 -0
- bluer_sbc/imager/camera/constants.py +30 -0
- bluer_sbc/imager/classes.py +25 -0
- bluer_sbc/imager/lepton/__init__.py +3 -0
- bluer_sbc/imager/lepton/__main__.py +51 -0
- bluer_sbc/imager/lepton/classes.py +35 -0
- bluer_sbc/imager/lepton/python2.py +70 -0
- bluer_sbc/logger.py +5 -0
- bluer_sbc/sample.env +1 -0
- bluer_sbc/session/__init__.py +0 -0
- bluer_sbc/session/__main__.py +27 -0
- bluer_sbc/session/classes.py +318 -0
- bluer_sbc/session/functions.py +22 -0
- bluer_sbc/urls.py +1 -0
- bluer_sbc-8.3.1.dist-info/METADATA +58 -0
- bluer_sbc-8.3.1.dist-info/RECORD +82 -0
- bluer_sbc-8.3.1.dist-info/WHEEL +5 -0
- bluer_sbc-8.3.1.dist-info/licenses/LICENSE +121 -0
- bluer_sbc-8.3.1.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
from typing import Tuple, List
|
|
2
|
+
import numpy as np
|
|
3
|
+
|
|
4
|
+
from blueness import module
|
|
5
|
+
|
|
6
|
+
from bluer_sbc import NAME
|
|
7
|
+
|
|
8
|
+
NAME = module.name(__file__, NAME)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class Imager:
|
|
12
|
+
def capture(self) -> Tuple[bool, np.ndarray]:
|
|
13
|
+
return True, np.zeros(())
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class TemplateImager(Imager):
|
|
17
|
+
def capture(self) -> Tuple[bool, np.ndarray]:
|
|
18
|
+
success, image = super().capture()
|
|
19
|
+
|
|
20
|
+
# TODO: capture the image here
|
|
21
|
+
|
|
22
|
+
return success, image
|
|
23
|
+
|
|
24
|
+
def signature(self) -> List[str]:
|
|
25
|
+
return [self.__class__.__name__]
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import argparse
|
|
2
|
+
import os
|
|
3
|
+
|
|
4
|
+
from blueness import module
|
|
5
|
+
|
|
6
|
+
from bluer_sbc import NAME
|
|
7
|
+
from bluer_sbc.imager.lepton import instance as lepton
|
|
8
|
+
from bluer_sbc.hardware import hardware
|
|
9
|
+
from bluer_sbc.logger import logger
|
|
10
|
+
|
|
11
|
+
NAME = module.name(__file__, NAME)
|
|
12
|
+
|
|
13
|
+
parser = argparse.ArgumentParser(NAME)
|
|
14
|
+
parser.add_argument(
|
|
15
|
+
"task",
|
|
16
|
+
type=str,
|
|
17
|
+
default="",
|
|
18
|
+
help="capture|preview",
|
|
19
|
+
)
|
|
20
|
+
parser.add_argument(
|
|
21
|
+
"--filename",
|
|
22
|
+
default="",
|
|
23
|
+
type=str,
|
|
24
|
+
)
|
|
25
|
+
parser.add_argument(
|
|
26
|
+
"--output_path",
|
|
27
|
+
type=str,
|
|
28
|
+
default="",
|
|
29
|
+
)
|
|
30
|
+
args = parser.parse_args()
|
|
31
|
+
|
|
32
|
+
success = False
|
|
33
|
+
if args.task == "capture":
|
|
34
|
+
success, _, _ = lepton.capture(
|
|
35
|
+
filename=os.path.join(args.output_path, "camera.jpg"),
|
|
36
|
+
)
|
|
37
|
+
elif args.task == "preview":
|
|
38
|
+
success = True
|
|
39
|
+
|
|
40
|
+
hardware.sign_images = False
|
|
41
|
+
try:
|
|
42
|
+
while not hardware.pressed("qe"):
|
|
43
|
+
_, image = lepton.capture()
|
|
44
|
+
hardware.update_screen(image)
|
|
45
|
+
finally:
|
|
46
|
+
pass
|
|
47
|
+
else:
|
|
48
|
+
logger.error(f"-{NAME}: {args.task}: command not found.")
|
|
49
|
+
|
|
50
|
+
if not success:
|
|
51
|
+
logger.error(f"-{NAME}: {args.task}: failed.")
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
from typing import Tuple
|
|
2
|
+
import numpy as np
|
|
3
|
+
|
|
4
|
+
from blueness import module
|
|
5
|
+
from bluer_options import string
|
|
6
|
+
from bluer_objects import file
|
|
7
|
+
from bluer_objects import path
|
|
8
|
+
from bluer_objects.env import abcli_path_git
|
|
9
|
+
from bluer_objects.host import shell
|
|
10
|
+
|
|
11
|
+
from bluer_sbc import NAME
|
|
12
|
+
from bluer_sbc.imager.classes import Imager
|
|
13
|
+
from bluer_sbc.logger import logger
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
NAME = module.name(__file__, NAME)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class Lepton(Imager):
|
|
20
|
+
def capture(self) -> Tuple[bool, np.ndarray]:
|
|
21
|
+
success, image = super().capture()
|
|
22
|
+
|
|
23
|
+
temp_dir = path.auxiliary("lepton")
|
|
24
|
+
success = shell(
|
|
25
|
+
f"python python2.py capture --output_path {temp_dir}",
|
|
26
|
+
work_dir=f"{abcli_path_git}/bluer-sbc/bluer_sbc/imager/lepton",
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
if success:
|
|
30
|
+
success, image = file.load_image(f"{temp_dir}/image.jpg")
|
|
31
|
+
|
|
32
|
+
if success:
|
|
33
|
+
logger.info(f"{NAME}.capture(): {string.pretty_shape_of_matrix(image)}")
|
|
34
|
+
|
|
35
|
+
return success, image
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import argparse
|
|
2
|
+
import cv2
|
|
3
|
+
from datetime import datetime
|
|
4
|
+
import numpy as np
|
|
5
|
+
import os.path
|
|
6
|
+
import time
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def capture(flip_v=True, device="/dev/spidev0.0"):
|
|
10
|
+
from pylepton import Lepton
|
|
11
|
+
|
|
12
|
+
with Lepton(device) as l:
|
|
13
|
+
a, _ = l.capture()
|
|
14
|
+
|
|
15
|
+
if flip_v:
|
|
16
|
+
cv2.flip(a, 0, a)
|
|
17
|
+
|
|
18
|
+
cv2.normalize(a, a, 0, 65535, cv2.NORM_MINMAX)
|
|
19
|
+
np.right_shift(a, 8, a)
|
|
20
|
+
|
|
21
|
+
return np.uint8(a)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def capture_and_save(path):
|
|
25
|
+
try:
|
|
26
|
+
for _ in range(2):
|
|
27
|
+
image = capture(False, "/dev/spidev0.0")
|
|
28
|
+
time.sleep(1)
|
|
29
|
+
|
|
30
|
+
cv2.imwrite(os.path.join(path, "image_raw.jpg"), image)
|
|
31
|
+
|
|
32
|
+
cv2.imwrite(
|
|
33
|
+
os.path.join(path, "image.jpg"),
|
|
34
|
+
cv2.resize(image, (1280, 960), interpolation=cv2.INTER_NEAREST),
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
print(
|
|
38
|
+
"lepton.capture_and_save({}) completed: {}.".format(
|
|
39
|
+
path, "x".join([str(dim) for dim in image.shape])
|
|
40
|
+
)
|
|
41
|
+
)
|
|
42
|
+
except Exception as e:
|
|
43
|
+
print("lepton.capture_and_save() crashed: {}".format(e))
|
|
44
|
+
return False
|
|
45
|
+
|
|
46
|
+
return True
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
if __name__ == "__main__":
|
|
50
|
+
parser = argparse.ArgumentParser()
|
|
51
|
+
parser.add_argument(
|
|
52
|
+
"task",
|
|
53
|
+
type=str,
|
|
54
|
+
default="",
|
|
55
|
+
help="capture",
|
|
56
|
+
)
|
|
57
|
+
parser.add_argument(
|
|
58
|
+
"--output_path",
|
|
59
|
+
default="",
|
|
60
|
+
)
|
|
61
|
+
args = parser.parse_args()
|
|
62
|
+
|
|
63
|
+
success = False
|
|
64
|
+
if args.task == "capture":
|
|
65
|
+
success = capture_and_save(args.output_path)
|
|
66
|
+
else:
|
|
67
|
+
print("-lepton: {}: command not found.".format(args.task))
|
|
68
|
+
|
|
69
|
+
if not success:
|
|
70
|
+
print("-lepton: {}: failed.".format(args.task))
|
bluer_sbc/logger.py
ADDED
bluer_sbc/sample.env
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
BLUER_SBC_SECRET=value
|
|
File without changes
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import argparse
|
|
2
|
+
|
|
3
|
+
from blueness import module
|
|
4
|
+
|
|
5
|
+
from bluer_sbc import NAME
|
|
6
|
+
from bluer_sbc.session.classes import Session
|
|
7
|
+
from bluer_sbc.logger import logger
|
|
8
|
+
|
|
9
|
+
NAME = module.name(__file__, NAME)
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
parser = argparse.ArgumentParser(NAME)
|
|
13
|
+
parser.add_argument(
|
|
14
|
+
"task",
|
|
15
|
+
type=str,
|
|
16
|
+
help="start",
|
|
17
|
+
)
|
|
18
|
+
args = parser.parse_args()
|
|
19
|
+
|
|
20
|
+
success = False
|
|
21
|
+
if args.task == "start":
|
|
22
|
+
success = Session.start()
|
|
23
|
+
else:
|
|
24
|
+
logger.error(f"-{NAME}: {args.task}: command not found.")
|
|
25
|
+
|
|
26
|
+
if not success:
|
|
27
|
+
logger.error(f"-{NAME}: {args.task}: failed.")
|
|
@@ -0,0 +1,318 @@
|
|
|
1
|
+
import os
|
|
2
|
+
|
|
3
|
+
from blueness import module
|
|
4
|
+
from bluer_options import string
|
|
5
|
+
from bluer_options import host
|
|
6
|
+
from bluer_options.logger import crash_report
|
|
7
|
+
from bluer_options.timer import Timer
|
|
8
|
+
from bluer_objects import file
|
|
9
|
+
from bluer_objects import objects
|
|
10
|
+
from bluer_objects.storage import instance as storage
|
|
11
|
+
from bluer_objects.graphics.signature import add_signature
|
|
12
|
+
from bluer_ai import VERSION as abcli_VERSION
|
|
13
|
+
from bluer_ai.modules import terraform
|
|
14
|
+
from bluer_objects.env import abcli_object_name
|
|
15
|
+
|
|
16
|
+
from bluer_sbc import NAME
|
|
17
|
+
from bluer_sbc import env
|
|
18
|
+
from bluer_sbc.host import signature
|
|
19
|
+
from bluer_sbc.session.functions import reply_to_bash
|
|
20
|
+
from bluer_sbc.algo.diff import Diff
|
|
21
|
+
from bluer_sbc.hardware import hardware
|
|
22
|
+
from bluer_sbc.imager import imager
|
|
23
|
+
from bluer_sbc.logger import logger
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
NAME = module.name(__file__, NAME)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class Session:
|
|
30
|
+
def __init__(self):
|
|
31
|
+
self.bash_keys = {
|
|
32
|
+
"e": "exit",
|
|
33
|
+
"r": "reboot",
|
|
34
|
+
"s": "shutdown",
|
|
35
|
+
"u": "update",
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
self.diff = Diff(env.BLUER_SBC_SESSION_IMAGER_DIFF)
|
|
39
|
+
|
|
40
|
+
self.capture_requested = False
|
|
41
|
+
|
|
42
|
+
self.frame = 0
|
|
43
|
+
self.new_frame = False
|
|
44
|
+
self.frame_image = terraform.poster(None)
|
|
45
|
+
self.frame_filename = ""
|
|
46
|
+
|
|
47
|
+
self.auto_upload = env.BLUER_SBC_SESSION_AUTO_UPLOAD
|
|
48
|
+
|
|
49
|
+
self.messages = []
|
|
50
|
+
|
|
51
|
+
self.model = None
|
|
52
|
+
|
|
53
|
+
self.params = {"iteration": -1}
|
|
54
|
+
|
|
55
|
+
self.state = {}
|
|
56
|
+
|
|
57
|
+
self.timer = {}
|
|
58
|
+
for name, period in {
|
|
59
|
+
"imager": env.BLUER_SBC_SESSION_IMAGER_PERIOD,
|
|
60
|
+
"messenger": env.BLUER_SBC_SESSION_MESSENGER_PERIOD,
|
|
61
|
+
"reboot": env.BLUER_SBC_SESSION_REBOOT_PERIOD,
|
|
62
|
+
"screen": env.BLUER_SBC_SESSION_SCREEN_PERIOD,
|
|
63
|
+
"temperature": env.BLUER_SBC_SESSION_TEMPERATURE_PERIOD,
|
|
64
|
+
}.items():
|
|
65
|
+
self.add_timer(name, period)
|
|
66
|
+
|
|
67
|
+
def add_timer(
|
|
68
|
+
self,
|
|
69
|
+
name: str,
|
|
70
|
+
period: float,
|
|
71
|
+
):
|
|
72
|
+
if name not in self.timer:
|
|
73
|
+
self.timer[name] = Timer(period, name)
|
|
74
|
+
logger.info(
|
|
75
|
+
"{}: timer[{}]:{}".format(
|
|
76
|
+
NAME,
|
|
77
|
+
name,
|
|
78
|
+
string.pretty_frequency(1 / period),
|
|
79
|
+
)
|
|
80
|
+
)
|
|
81
|
+
return True
|
|
82
|
+
return False
|
|
83
|
+
|
|
84
|
+
def check_imager(self):
|
|
85
|
+
self.new_frame = False
|
|
86
|
+
|
|
87
|
+
if not env.BLUER_SBC_SESSION_IMAGER_ENABLED:
|
|
88
|
+
return
|
|
89
|
+
if not self.capture_requested and not self.timer["imager"].tick():
|
|
90
|
+
return
|
|
91
|
+
self.capture_requested = False
|
|
92
|
+
|
|
93
|
+
success, image = imager.capture()
|
|
94
|
+
if not success:
|
|
95
|
+
return
|
|
96
|
+
|
|
97
|
+
hardware.pulse("data")
|
|
98
|
+
|
|
99
|
+
if self.diff.same(image):
|
|
100
|
+
return
|
|
101
|
+
|
|
102
|
+
self.frame += 1
|
|
103
|
+
|
|
104
|
+
image = add_signature(
|
|
105
|
+
image,
|
|
106
|
+
[" | ".join(objects.signature(self.frame))],
|
|
107
|
+
[" | ".join(signature())],
|
|
108
|
+
)
|
|
109
|
+
|
|
110
|
+
filename = objects.path_of(
|
|
111
|
+
object_name=abcli_object_name,
|
|
112
|
+
filename=f"{self.frame:016d}.jpg",
|
|
113
|
+
)
|
|
114
|
+
if not file.save_image(filename, image):
|
|
115
|
+
return
|
|
116
|
+
|
|
117
|
+
self.new_frame = True
|
|
118
|
+
self.frame_image = image
|
|
119
|
+
self.frame_filename = filename
|
|
120
|
+
|
|
121
|
+
if self.auto_upload:
|
|
122
|
+
storage.upload_file(self.frame_filename)
|
|
123
|
+
|
|
124
|
+
def check_keys(self):
|
|
125
|
+
for key in hardware.key_buffer:
|
|
126
|
+
if key in self.bash_keys:
|
|
127
|
+
reply_to_bash(self.bash_keys[key])
|
|
128
|
+
return False
|
|
129
|
+
|
|
130
|
+
if " " in hardware.key_buffer:
|
|
131
|
+
self.capture_requested = True
|
|
132
|
+
|
|
133
|
+
hardware.key_buffer = []
|
|
134
|
+
|
|
135
|
+
return None
|
|
136
|
+
|
|
137
|
+
def check_seed(self):
|
|
138
|
+
seed_filename = host.get_seed_filename()
|
|
139
|
+
if not file.exists(seed_filename):
|
|
140
|
+
return None
|
|
141
|
+
|
|
142
|
+
success, content = file.load_json(file.set_extension(seed_filename, "json"))
|
|
143
|
+
if not success:
|
|
144
|
+
return None
|
|
145
|
+
|
|
146
|
+
hardware.pulse("outputs")
|
|
147
|
+
|
|
148
|
+
seed_version = content.get("version", "")
|
|
149
|
+
if seed_version <= abcli_VERSION:
|
|
150
|
+
return None
|
|
151
|
+
|
|
152
|
+
logger.info(f"{NAME}: seed {seed_version} detected.")
|
|
153
|
+
reply_to_bash("seed", [seed_filename])
|
|
154
|
+
return False
|
|
155
|
+
|
|
156
|
+
def check_timers(self):
|
|
157
|
+
if self.timer["screen"].tick():
|
|
158
|
+
hardware.update_screen(
|
|
159
|
+
image=self.frame_image,
|
|
160
|
+
session=self,
|
|
161
|
+
header=self.signature(),
|
|
162
|
+
)
|
|
163
|
+
elif hardware.animated:
|
|
164
|
+
hardware.animate()
|
|
165
|
+
|
|
166
|
+
if self.timer["reboot"].tick("wait"):
|
|
167
|
+
reply_to_bash("reboot")
|
|
168
|
+
return False
|
|
169
|
+
|
|
170
|
+
if self.timer["temperature"].tick():
|
|
171
|
+
self.read_temperature()
|
|
172
|
+
|
|
173
|
+
return None
|
|
174
|
+
|
|
175
|
+
def close(self):
|
|
176
|
+
hardware.release()
|
|
177
|
+
|
|
178
|
+
def process_message(self, message):
|
|
179
|
+
if (
|
|
180
|
+
env.BLUER_SBC_SESSION_OUTBOUND_QUEUE
|
|
181
|
+
and message.subject in "bolt,frame".split(",")
|
|
182
|
+
and not host.is_headless()
|
|
183
|
+
):
|
|
184
|
+
logger.info(f"{NAME}: frame received: {message.as_string()}")
|
|
185
|
+
self.new_frame, self.frame_image = file.load_image(message.filename)
|
|
186
|
+
|
|
187
|
+
if message.subject == "capture":
|
|
188
|
+
logger.info(f"{NAME}: capture message received.")
|
|
189
|
+
self.capture_requested = True
|
|
190
|
+
|
|
191
|
+
if message.subject in "reboot,shutdown".split(","):
|
|
192
|
+
logger.info(f"{NAME}: {message.subject} message received.")
|
|
193
|
+
reply_to_bash(message.subject)
|
|
194
|
+
return False
|
|
195
|
+
|
|
196
|
+
if message.subject == "update":
|
|
197
|
+
try:
|
|
198
|
+
if message.data["version"] > abcli_VERSION:
|
|
199
|
+
reply_to_bash("update")
|
|
200
|
+
return False
|
|
201
|
+
except Exception as e:
|
|
202
|
+
crash_report(e)
|
|
203
|
+
|
|
204
|
+
return None
|
|
205
|
+
|
|
206
|
+
# https://www.cyberciti.biz/faq/linux-find-out-raspberry-pi-gpu-and-arm-cpu-temperature-command/
|
|
207
|
+
def read_temperature(self):
|
|
208
|
+
if not host.is_rpi():
|
|
209
|
+
return
|
|
210
|
+
|
|
211
|
+
params = {}
|
|
212
|
+
|
|
213
|
+
success, output = file.load_text("/sys/class/thermal/thermal_zone0/temp")
|
|
214
|
+
if success:
|
|
215
|
+
output = [thing for thing in output if thing]
|
|
216
|
+
if output:
|
|
217
|
+
try:
|
|
218
|
+
params["temperature.cpu"] = float(output[0]) / 1000
|
|
219
|
+
except Exception as e:
|
|
220
|
+
crash_report(e)
|
|
221
|
+
return
|
|
222
|
+
|
|
223
|
+
self.params.update(params)
|
|
224
|
+
logger.info(
|
|
225
|
+
"{}: {}".format(
|
|
226
|
+
NAME,
|
|
227
|
+
", ".join(string.pretty_param(params)),
|
|
228
|
+
)
|
|
229
|
+
)
|
|
230
|
+
|
|
231
|
+
def signature(self):
|
|
232
|
+
return [
|
|
233
|
+
" | ".join(objects.signature()),
|
|
234
|
+
" | ".join(sorted([timer.signature() for timer in self.timer.values()])),
|
|
235
|
+
" | ".join(
|
|
236
|
+
(["*"] if self.new_frame else [])
|
|
237
|
+
+ (["^"] if self.auto_upload else [])
|
|
238
|
+
+ ([f">{self.outbound_queue}"] if self.outbound_queue else [])
|
|
239
|
+
+ hardware.signature()
|
|
240
|
+
+ [
|
|
241
|
+
"diff: {:.03f} - {}".format(
|
|
242
|
+
self.diff.last_diff,
|
|
243
|
+
string.pretty_duration(
|
|
244
|
+
self.diff.last_same_period,
|
|
245
|
+
largest=True,
|
|
246
|
+
include_ms=True,
|
|
247
|
+
short=True,
|
|
248
|
+
),
|
|
249
|
+
),
|
|
250
|
+
string.pretty_shape_of_matrix(self.frame_image),
|
|
251
|
+
]
|
|
252
|
+
+ ([] if self.model is None else self.model.signature())
|
|
253
|
+
),
|
|
254
|
+
]
|
|
255
|
+
|
|
256
|
+
@staticmethod
|
|
257
|
+
def start():
|
|
258
|
+
success = True
|
|
259
|
+
logger.info(f"{NAME}: started ...")
|
|
260
|
+
|
|
261
|
+
try:
|
|
262
|
+
session = Session()
|
|
263
|
+
|
|
264
|
+
while session.step():
|
|
265
|
+
pass
|
|
266
|
+
|
|
267
|
+
logger.info(f"{NAME}: stopped.")
|
|
268
|
+
except KeyboardInterrupt:
|
|
269
|
+
logger.info(f"{NAME}: Ctrl+C: stopped.")
|
|
270
|
+
reply_to_bash("exit")
|
|
271
|
+
except Exception as e:
|
|
272
|
+
crash_report(e)
|
|
273
|
+
success = False
|
|
274
|
+
|
|
275
|
+
try:
|
|
276
|
+
session.close()
|
|
277
|
+
except Exception as e:
|
|
278
|
+
crash_report(e)
|
|
279
|
+
success = False
|
|
280
|
+
|
|
281
|
+
return success
|
|
282
|
+
|
|
283
|
+
def step(
|
|
284
|
+
self,
|
|
285
|
+
steps="all",
|
|
286
|
+
) -> bool:
|
|
287
|
+
if steps == "all":
|
|
288
|
+
steps = "imager,keys,messages,seed,switch,timers".split(",")
|
|
289
|
+
|
|
290
|
+
self.params["iteration"] += 1
|
|
291
|
+
|
|
292
|
+
hardware.pulse("loop", 0)
|
|
293
|
+
|
|
294
|
+
for enabled, step_ in zip(
|
|
295
|
+
[
|
|
296
|
+
"keys" in steps,
|
|
297
|
+
"messages" in steps,
|
|
298
|
+
"timers" in steps,
|
|
299
|
+
"seed" in steps,
|
|
300
|
+
"imager" in steps,
|
|
301
|
+
],
|
|
302
|
+
[
|
|
303
|
+
self.check_keys,
|
|
304
|
+
self.check_messages,
|
|
305
|
+
self.check_timers,
|
|
306
|
+
self.check_seed,
|
|
307
|
+
self.check_imager,
|
|
308
|
+
],
|
|
309
|
+
):
|
|
310
|
+
if not enabled:
|
|
311
|
+
continue
|
|
312
|
+
output = step_()
|
|
313
|
+
if output in [False, True]:
|
|
314
|
+
return output
|
|
315
|
+
|
|
316
|
+
hardware.clock()
|
|
317
|
+
|
|
318
|
+
return True
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import os
|
|
2
|
+
from typing import List
|
|
3
|
+
|
|
4
|
+
from bluer_ai.env import ABCLI_PATH_IGNORE
|
|
5
|
+
from bluer_objects import file
|
|
6
|
+
|
|
7
|
+
from bluer_sbc.logger import logger
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def reply_to_bash(
|
|
11
|
+
status: str, # exit/reboot/seed/shutdown/update
|
|
12
|
+
content: List[str] = [],
|
|
13
|
+
) -> bool:
|
|
14
|
+
logger.info(f"session.reply_to_bash({status}).")
|
|
15
|
+
|
|
16
|
+
return file.save_text(
|
|
17
|
+
filename=os.path.join(
|
|
18
|
+
ABCLI_PATH_IGNORE,
|
|
19
|
+
f"session_reply_{status}",
|
|
20
|
+
),
|
|
21
|
+
text=content,
|
|
22
|
+
)
|
bluer_sbc/urls.py
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
urlpatterns = []
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: bluer_sbc
|
|
3
|
+
Version: 8.3.1
|
|
4
|
+
Summary: 🌀 AI for single board computers.
|
|
5
|
+
Home-page: https://github.com/kamangir/bluer-sbc
|
|
6
|
+
Author: Arash Abadpour (Kamangir)
|
|
7
|
+
Author-email: arash@kamangir.net
|
|
8
|
+
License: Public Domain
|
|
9
|
+
Classifier: Programming Language :: Python :: 3
|
|
10
|
+
Classifier: Programming Language :: Unix Shell
|
|
11
|
+
Classifier: License :: Public Domain
|
|
12
|
+
Classifier: Operating System :: OS Independent
|
|
13
|
+
Description-Content-Type: text/markdown
|
|
14
|
+
License-File: LICENSE
|
|
15
|
+
Requires-Dist: bluer_ai
|
|
16
|
+
Requires-Dist: bluer_sbc
|
|
17
|
+
Dynamic: author
|
|
18
|
+
Dynamic: author-email
|
|
19
|
+
Dynamic: classifier
|
|
20
|
+
Dynamic: description
|
|
21
|
+
Dynamic: description-content-type
|
|
22
|
+
Dynamic: home-page
|
|
23
|
+
Dynamic: license
|
|
24
|
+
Dynamic: license-file
|
|
25
|
+
Dynamic: requires-dist
|
|
26
|
+
Dynamic: summary
|
|
27
|
+
|
|
28
|
+
# 🌀 bluer-sbc
|
|
29
|
+
|
|
30
|
+
🌀 `bluer-sbc` is a [`bluer-ai`](https://github.com/kamangir/bluer-ai) plugin for edge computing on [single board computers](https://github.com/kamangir/blue-bracket).
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
pip install bluer_sbc
|
|
34
|
+
|
|
35
|
+
# @env dot list
|
|
36
|
+
@env dot cp <env-name> local
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
| | | | |
|
|
40
|
+
| --- | --- | --- | --- |
|
|
41
|
+
| [](https://github.com/kamangir/blue-bracket/blob/main/designs/blue3.md) | [](https://github.com/kamangir/blue-bracket/blob/main/designs/chenar-grove.md) | [](https://github.com/kamangir/blue-bracket/blob/main/designs/cube.md) | [](https://github.com/kamangir/blue-bracket/blob/main/designs/eye_nano.md) |
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
> 🌀 [`blue-sbc`](https://github.com/kamangir/blue-sbc) for the [Global South](https://github.com/kamangir/bluer-south).
|
|
48
|
+
|
|
49
|
+
---
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
[](https://github.com/kamangir/bluer-sbc/actions/workflows/pylint.yml) [](https://github.com/kamangir/bluer-sbc/actions/workflows/pytest.yml) [](https://github.com/kamangir/bluer-sbc/actions/workflows/bashtest.yml) [](https://pypi.org/project/bluer-sbc/) [](https://pypistats.org/packages/bluer-sbc)
|
|
53
|
+
|
|
54
|
+
built by 🌀 [`bluer_options-5.32.1`](https://github.com/kamangir/awesome-bash-cli), based on 🌀 [`bluer_sbc-8.3.1`](https://github.com/kamangir/bluer-sbc).
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
built by 🌀 [`blueness-3.96.1`](https://github.com/kamangir/blueness).
|