Skip to content

Commit eedb487

Browse files
authored
Merge pull request #141 from EmixamPP/test_command
Test command
2 parents fd9a885 + 0207867 commit eedb487

15 files changed

+310
-63
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ sudo rm -rf /usr/lib64/linux-enable-ir-emitter \
2525
```
2626

2727
## How to enable your infrared emitter?
28-
1. Stand in front of the camera and make sure the room is well lit.
28+
1. Stand in front of and close to the camera and make sure the room is well lit.
2929
2. Ensure to not use the camera during the execution.
3030
3. Be patient, do not kill the process.
3131
4. Execute `sudo linux-enable-ir-emitter configure`.

camera/autocamera.cpp

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -65,15 +65,32 @@ long long unsigned AutoCamera::intensityVariationSum()
6565
long long unsigned sum = 0;
6666
for (unsigned i = 0; i < diffs.size() - 1; ++i)
6767
sum += static_cast<long long unsigned>(abs(diffs[i] - diffs[i + 1]));
68-
68+
6969
closeCap();
7070
return sum;
7171
}
7272

73+
74+
/**
75+
* @brief Check if the emitter is working,
76+
* without asking for manual confirmation
77+
*
78+
* @return true if yes, false if not
79+
*/
80+
bool AutoCamera::isEmitterWorkingNoConfirm()
81+
{
82+
return intensityVariationSum() > refIntesityVarSum * MAGIC_REF_INTENSITY_VAR_COEF;
83+
}
84+
85+
/**
86+
* @brief Check if the emitter is working,
87+
* if so, ask for manual confirmation
88+
*
89+
* @return true if yes, false if not
90+
*/
7391
bool AutoCamera::isEmitterWorking()
7492
{
75-
bool isWorking = intensityVariationSum() > refIntesityVarSum * MAGIC_REF_INTENSITY_VAR_COEF;
76-
return isWorking && Camera::isEmitterWorking();
93+
return isEmitterWorkingNoConfirm() && Camera::isEmitterWorking();
7794
}
7895

7996
AutoCamera::AutoCamera(const string &device, unsigned captureTimeMs) : Camera(device), captureTimeMs(captureTimeMs), refIntesityVarSum(intensityVariationSum()) {}

camera/autocamera.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ class AutoCamera : public Camera
2525

2626
bool isEmitterWorking() override;
2727

28+
bool isEmitterWorkingNoConfirm();
29+
2830
AutoCamera &operator=(const AutoCamera &) = delete;
2931

3032
AutoCamera(const AutoCamera &) = delete;

camera/camera.cpp

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,28 @@ Camera::~Camera()
127127
closeCap();
128128
}
129129

130+
/**
131+
* @brief Show a video feedback until the user exit
132+
*/
133+
void Camera::play()
134+
{
135+
openCap();
136+
cv::Mat frame;
137+
int key = -1;
138+
139+
cout << "Press any key in the window to close" << endl;
140+
141+
while (key == -1)
142+
{
143+
cap->read(frame);
144+
cv::imshow("linux-enable-ir-emitter", frame);
145+
key = cv::waitKey(5);
146+
}
147+
148+
closeCap();
149+
cv::destroyAllWindows();
150+
}
151+
130152
/**
131153
* @brief Apply an instruction on the camera
132154
*
@@ -166,6 +188,8 @@ unique_ptr<cv::Mat> Camera::read1()
166188

167189
/**
168190
* @brief Check if the emitter is working
191+
* by showing a video feedback and
192+
* asking confirmation to the user
169193
*
170194
* @throw CameraException if unable to open the camera device
171195
*
@@ -190,7 +214,7 @@ bool Camera::isEmitterWorking()
190214

191215
closeCap();
192216
cv::destroyAllWindows();
193-
217+
194218
return key == OK_KEY;
195219
}
196220

camera/camera.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@ class Camera
5353

5454
Camera(Camera &&other) = delete;
5555

56+
void play();
57+
5658
bool apply(const CameraInstruction &instruction);
5759

5860
virtual bool isEmitterWorking();

camera/is-emitter-working.cpp

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
#include <memory>
2+
using namespace std;
3+
4+
#include "autocamera.hpp"
5+
#include "opencv.hpp"
6+
7+
constexpr unsigned EXIT_FD_ERROR = 126;
8+
9+
/**
10+
* Check if a ir emitter is working using the automatic detection algorithm
11+
*
12+
* usage: is-emitter-camera [device]
13+
* device path to the camera
14+
*
15+
* Exit code: 0 Success
16+
* 1 Error
17+
* 126 Unable to open the camera device
18+
*/
19+
int main(int, const char **argv)
20+
{
21+
AutoCamera camera(argv[1]);
22+
try
23+
{
24+
return static_cast<int>(camera.isEmitterWorkingNoConfirm());
25+
}
26+
catch (CameraException &e)
27+
{
28+
cerr << e.what() << endl;
29+
return EXIT_FD_ERROR;
30+
}
31+
}

camera/is-gray-camera.cpp

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
#include <memory>
2+
using namespace std;
3+
4+
#include "camera.hpp"
5+
#include "opencv.hpp"
6+
7+
constexpr unsigned EXIT_FD_ERROR = 126;
8+
9+
/**
10+
* Check if a camera is in gray scale
11+
*
12+
* usage: is-gray-camera [device]
13+
* device path to the camera
14+
*
15+
* Exit code: 0 Success
16+
* 1 Error
17+
* 126 Unable to open the camera device
18+
*/
19+
int main(int, const char **argv)
20+
{
21+
Camera camera(argv[1]);
22+
try
23+
{
24+
unique_ptr<cv::Mat> frame = camera.read1();
25+
26+
if (frame->channels() != 3)
27+
return EXIT_FAILURE;
28+
29+
for (int r = 0; r < frame->rows; ++r)
30+
for (int c = 0; c < frame->cols; ++c)
31+
{
32+
const cv::Vec3b &pixel = frame->at<cv::Vec3b>(r, c);
33+
if (pixel[0] != pixel[1] || pixel[0] != pixel[2])
34+
return EXIT_FAILURE;
35+
}
36+
37+
return EXIT_SUCCESS;
38+
}
39+
catch (CameraException &e)
40+
{
41+
cerr << e.what() << endl;
42+
return EXIT_FD_ERROR;
43+
}
44+
}

camera/is-ir-camera.cpp

Lines changed: 0 additions & 24 deletions
This file was deleted.

camera/video-feedback.cpp

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
#include <memory>
2+
using namespace std;
3+
4+
#include "autocamera.hpp"
5+
#include "opencv.hpp"
6+
7+
constexpr unsigned EXIT_FD_ERROR = 126;
8+
9+
/**
10+
* Check if a ir emitter is working using the automatic detection algorithm
11+
*
12+
* usage: is-emitter-camera [device]
13+
* device path to the camera
14+
*
15+
* Exit code: 0 Success
16+
* 126 Unable to open the camera device
17+
*/
18+
int main(int, const char **argv)
19+
{
20+
Camera camera(argv[1]);
21+
try
22+
{
23+
camera.play();
24+
return EXIT_SUCCESS;
25+
}
26+
catch (CameraException &e)
27+
{
28+
cerr << e.what() << endl;
29+
return EXIT_FD_ERROR;
30+
}
31+
}

command/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,4 @@
22
from command.configure import configure
33
from command.delete import delete
44
from command.run import run
5+
from command.test import test

command/configure.py

Lines changed: 16 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,17 @@
44
import subprocess
55

66
from command import boot
7-
from globals import (BIN_GENERATE_DRIVER_PATH, SAVE_DRIVER_FOLDER_PATH,
8-
BIN_IS_CAMERA_PATH, ExitCode)
7+
from globals import (
8+
BIN_GENERATE_DRIVER_PATH,
9+
SAVE_DRIVER_FOLDER_PATH,
10+
find_grayscale_camera,
11+
ExitCode,
12+
)
913

1014

11-
def configure(device: str | None, manual: bool, emitters: int, neg_answer_limit: int) -> NoReturn:
15+
def configure(
16+
device: str | None, manual: bool, emitters: int, neg_answer_limit: int
17+
) -> NoReturn:
1218
"""Find a driver for the infrared camera and exit.
1319
1420
Args:
@@ -17,33 +23,15 @@ def configure(device: str | None, manual: bool, emitters: int, neg_answer_limit:
1723
emitters (int): number of emitters on the device
1824
neg_answer_limit (int): number of negative answer before the pattern is skiped. Use -1 for unlimited
1925
"""
26+
logging.info(
27+
"Stand in front of and close to the camera and make sure the room is well lit."
28+
)
2029
logging.info("Ensure to not use the camera during the execution.")
2130
logging.info("Warning to do not kill the process !")
2231

2332
if device is None:
24-
dev_devices = subprocess.run(
25-
f"ls /dev/v4l/by-path/*",
26-
shell=True,
27-
capture_output=True,
28-
text=True,
29-
).stdout.strip().split()
30-
31-
for dev in dev_devices:
32-
exit_code = subprocess.call(
33-
[BIN_IS_CAMERA_PATH, dev],
34-
stdout=subprocess.DEVNULL,
35-
stderr=subprocess.DEVNULL
36-
)
37-
if exit_code == ExitCode.SUCCESS:
38-
device = dev
39-
break
33+
device = find_grayscale_camera()
4034

41-
if device is None:
42-
logging.critical("Impossible to find your infrared camera.")
43-
logging.info(
44-
"Please specify your infrared camera path using the -d option."
45-
)
46-
exit(ExitCode.FAILURE)
4735
logging.info(f"Configuring the camera: {device}.")
4836
log_level = int(logging.getLogger().level == logging.DEBUG)
4937
exit_code = subprocess.call(
@@ -62,7 +50,9 @@ def configure(device: str | None, manual: bool, emitters: int, neg_answer_limit:
6250
logging.error("The configuration has failed.")
6351
logging.error("Please retry in manual mode by adding the '-m' option.")
6452
logging.info("Do not hesitate to visit the GitHub !")
65-
logging.info("https://github.com/EmixamPP/linux-enable-ir-emitter/blob/master/docs/README.md")
53+
logging.info(
54+
"https://github.com/EmixamPP/linux-enable-ir-emitter/blob/master/docs/README.md"
55+
)
6656
else:
6757
logging.info("The driver has been successfully generated.")
6858
boot("enable")

command/test.py

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
from typing import NoReturn
2+
3+
import subprocess
4+
import logging
5+
6+
from globals import (
7+
BIN_IS_GRAY_CAMERA_PATH,
8+
BIN_IS_EMITTER_WORKING_PATH,
9+
BIN_VIDEO_FEEDBACK_PATH,
10+
find_grayscale_camera,
11+
ExitCode,
12+
)
13+
14+
15+
def test(device: str | None) -> NoReturn:
16+
"""Test if the camera is in grayscale and if the emitter is working.
17+
Also display a video feedback, then exit.
18+
19+
Args:
20+
device (str | None): path to the camera, None for automatic detection
21+
"""
22+
if device is None:
23+
device = find_grayscale_camera()
24+
25+
exit_code = subprocess.call(
26+
[BIN_IS_GRAY_CAMERA_PATH, device],
27+
stdout=subprocess.DEVNULL,
28+
stderr=subprocess.DEVNULL,
29+
)
30+
if exit_code == ExitCode.FILE_DESCRIPTOR_ERROR:
31+
exit(exit_code)
32+
elif exit_code == ExitCode.SUCCESS:
33+
logging.info(
34+
"The camera is in gray scale. This is probably your infrared camera."
35+
)
36+
else:
37+
logging.error(
38+
"The camera is not in gray scale. This is probably your regular camera."
39+
)
40+
41+
exit_code = subprocess.call(
42+
[BIN_IS_EMITTER_WORKING_PATH, device],
43+
stdout=subprocess.DEVNULL,
44+
stderr=subprocess.DEVNULL,
45+
)
46+
if exit_code == ExitCode.FILE_DESCRIPTOR_ERROR:
47+
exit(exit_code)
48+
elif exit_code == ExitCode.SUCCESS:
49+
logging.info("The infrared emitter is working.")
50+
else:
51+
logging.error("The infrared emitter is not working.")
52+
53+
exit_code = subprocess.call(
54+
[BIN_VIDEO_FEEDBACK_PATH, device],
55+
stdout=subprocess.DEVNULL,
56+
stderr=subprocess.DEVNULL,
57+
)
58+
if exit_code == ExitCode.FILE_DESCRIPTOR_ERROR:
59+
exit(exit_code)
60+
61+
exit(ExitCode.SUCCESS)

0 commit comments

Comments
 (0)