Skip to content

Commit 5db04be

Browse files
fix: Picamera2 CMA Memory Allocation Error (#17)
* fix: add exceptions to trigger restart * fix: change image capture format and call stop * fix: don't call configure each time * fix: change close to stop * fix: change yuv420 to xrgb8888 back * feat: add memory information command * fix: give command as str
1 parent d910da4 commit 5db04be

File tree

4 files changed

+54
-16
lines changed

4 files changed

+54
-16
lines changed

core/observers/subject/eye_subject.py

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -81,26 +81,39 @@ def _run_in_loop(self,
8181
wifi_lock = Lock()
8282

8383
# Save an initial image.
84-
initial_frame = eye_strategy.get_frame()
84+
try:
85+
initial_frame = eye_strategy.get_frame()
86+
except RuntimeError as error:
87+
logger.error(
88+
"[EyeSubject] An error occurred while capturing the frame.")
89+
raise RuntimeError from error
8590
file_location = f"{self._image_path}/initial_frame.jpg"
8691
cv2.imwrite(file_location, initial_frame)
8792
logger.debug("[EyeSubject] Initial frame has been saved.")
8893

8994
while True:
9095
# If WiFi subject would give rights to use camera,
9196
# Check if any intruders detected.
92-
logger.debug("[EyeSubject] WiFi Lock Status: %s", wifi_lock.locked())
97+
logger.debug("[EyeSubject] WiFi Lock Status: %s",
98+
wifi_lock.locked())
9399
if not wifi_lock.locked():
94-
result = eye_strategy.check_if_detected()
95-
logger.debug("[EyeSubject] EyeStrategyResult: %s", str(result.result))
100+
try:
101+
result = eye_strategy.check_if_detected()
102+
except RuntimeError as error:
103+
logger.error(
104+
"[EyeSubject] An error occurred while checking if detected.")
105+
raise RuntimeError from error
106+
logger.debug("[EyeSubject] EyeStrategyResult: %s",
107+
str(result.result))
96108

97109
if result.result:
98110
logger.debug("[EyeSubject] Changing state to DETECTED...")
99111
self._save_image(result)
100112
self.set_state(EyeStates.DETECTED)
101113
sleep_interval = EyeSubject.SLEEP_INTERVAL_DETECTED
102114
else:
103-
logger.debug("[EyeSubject] Changing state to NOT_DETECTED...")
115+
logger.debug(
116+
"[EyeSubject] Changing state to NOT_DETECTED...")
104117
self.set_state(EyeStates.NOT_DETECTED)
105118
sleep_interval = EyeSubject.DEFAULT_SLEEP_INTERVAL
106119

core/strategies/eye/base_eye_strategy.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,10 @@ def _detect_humans(self, frame: ndarray) -> DetectorResult:
3636
def check_if_detected(self) -> EyeStrategyResult:
3737
"""This method checks if there are any protectors around."""
3838
#  Get the frame from the camera.
39-
frame = self.get_frame()
39+
try:
40+
frame = self.get_frame()
41+
except RuntimeError as error:
42+
raise RuntimeError from error
4043
# Detect humans in the frame.
4144
result = self._detect_humans(frame)
4245
return EyeStrategyResult(image=result.image, result=result.human_found)

core/strategies/eye/picamera_strategy.py

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,14 @@ class PiCameraStrategy(BaseEyeStrategy):
1717
"""
1818
The camera strategy for eye strategies.
1919
"""
20+
2021
def __init__(self):
2122
self._detector = None
23+
self._picam2 = Picamera2()
24+
still_configuration = self._picam2.create_still_configuration(
25+
main={"format": 'XRGB8888'}
26+
)
27+
self._picam2.configure(still_configuration)
2228

2329
# Interface methods.
2430
def set_detector(self, detector: BaseDetectorStrategy) -> None:
@@ -31,12 +37,13 @@ def get_detector(self) -> BaseDetectorStrategy:
3137

3238
def get_frame(self) -> numpy.ndarray:
3339
"""This method returns the frame from the camera."""
34-
# Internal attributes
35-
picam2 = Picamera2()
36-
still_configuration = picam2.create_still_configuration(main={"format": 'XRGB8888'})
37-
picam2.configure(still_configuration)
38-
picam2.start()
39-
frame = picam2.capture_array()
40-
picam2.close()
41-
del picam2
42-
return cv2.rotate(frame, cv2.ROTATE_90_COUNTERCLOCKWISE)
40+
try:
41+
self._picam2.start()
42+
frame = self._picam2.capture_array()
43+
self._picam2.stop()
44+
except Exception as error:
45+
logger.error(
46+
"An error occurred while capturing the frame: %s", error)
47+
raise RuntimeError from error
48+
return cv2.rotate(frame,
49+
cv2.ROTATE_90_COUNTERCLOCKWISE)

servicer.py

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,8 @@ def read_configurations() -> tuple[dict[str, Any], dict[str, Any]]:
3737

3838
# Definitations
3939
MAIN_CONIGS, STRATEGY_CONFIGS = read_configurations()
40-
SERVICER_BOT = AsyncTeleBot(token=STRATEGY_CONFIGS["telegram_strategy"]["bot_key"])
40+
SERVICER_BOT = AsyncTeleBot(
41+
token=STRATEGY_CONFIGS["telegram_strategy"]["bot_key"])
4142
KNOWN_LOG_LOCATIONS: dict[str, str] = {
4243
"hss.service": "/home/raspberry/.home-security-system/logs/hss.log"
4344
}
@@ -57,6 +58,7 @@ async def info(message):
5758
"/logs hss.service:N - provides the latest N logs.\n"
5859
"/inhouse - provides if protectors are in house, and whose.\n"
5960
"/imageshot - captures an image and sends.\n"
61+
"/meminfo - provides the memory information.\n"
6062
"/reboot - reboots the hardware.\n"
6163
"/shell echo 'test'- provides a shell access to the hardware.\n"
6264
"/info, /help, /hi - this help text.\n")
@@ -147,6 +149,19 @@ async def image_shot(message):
147149
del frame, encoded_frame
148150

149151

152+
@SERVICER_BOT.message_handler(commands=['meminfo'])
153+
async def mem_info(message):
154+
"""
155+
This method is called when the /meminfo command is sent.
156+
"""
157+
process = await asyncio.create_subprocess_shell(
158+
"cat /proc/meminfo",
159+
stdout=asyncio.subprocess.PIPE,
160+
stderr=asyncio.subprocess.PIPE)
161+
stdout, _ = await process.communicate()
162+
await SERVICER_BOT.reply_to(message, f"Memory Information: \n{stdout.decode()}")
163+
164+
150165
@SERVICER_BOT.message_handler(commands=['reboot'])
151166
async def reboot(message):
152167
"""

0 commit comments

Comments
 (0)