Remove assumption that USB device can be found at /dev/ttyUSB0.

Instead, interrogate all devices under /dev/serial/by-id, looking for a UART device.

Commit
12bfe878e8bd06bec5d70a4a48030be766047c8d
Author
Marius Peter <dev@marius-peter.com>
Author date
Committer
Marius Peter <dev@marius-peter.com>
Committer date
Changed files
roles/daq-node/bin/fapg-daq-node
index dfef666d..f114ad0f 100755..100755
@@ -10,6 +10,7 @@
10 10 use lib "$Bin/../lib/perl5";
11 11
12 12 use FAPG::DAQ::EZO::USB qw(
13 Added: discover_ezo_usb_device
13 14 open_ezo_usb
14 15 read_probe_info
15 16 read_once
@@ -23,20 +24,22 @@
23 24
24 25 =cut
25 26
26 Removed: my $device = $ENV{EZO_SERIAL_DEVICE} // '/dev/ttyUSB0';
27 27 my $read_interval = positive_number_from_env( READ_INTERVAL => 5 );
28 28 my $retry_delay = positive_number_from_env( EZO_RECONNECT_INTERVAL => 5 );
29 29
30 Removed: my ( $serial, $info );
30 Added: my ( $serial, $info, $device );
31 31
32 32 while (1) {
33 33 if ( !defined $serial || !defined $info ) {
34 Removed: ( $serial, $info ) = eval { connect_probe($device) };
34 Added: ( $serial, $info ) = eval {
35 Added: $device = serial_device();
36 Added: connect_probe($device);
37 Added: };
35 38
36 39 if ($@) {
37 40 warn "DAQ probe connection error: $@";
38 41 close_serial($serial);
39 Removed: ( $serial, $info ) = ();
42 Added: ( $serial, $info, $device ) = ();
40 43 sleep $retry_delay;
41 44 next;
42 45 }
@@ -47,7 +50,7 @@
47 50 if ($@) {
48 51 warn "DAQ probe read error, reconnecting to $device: $@";
49 52 close_serial($serial);
50 Removed: ( $serial, $info ) = ();
53 Added: ( $serial, $info, $device ) = ();
51 54 sleep $retry_delay;
52 55 next;
53 56 }
@@ -79,6 +82,17 @@
79 82 EOF
80 83
81 84 return ( $serial, $info );
85 Added: }
86 Added:
87 Added: sub serial_device {
88 Added: return $ENV{EZO_SERIAL_DEVICE} if defined $ENV{EZO_SERIAL_DEVICE} && $ENV{EZO_SERIAL_DEVICE} ne q{};
89 Added:
90 Added: if ( defined $ENV{SERIAL_DEVICE} && $ENV{SERIAL_DEVICE} ne q{} ) {
91 Added: return $ENV{SERIAL_DEVICE} if -e $ENV{SERIAL_DEVICE};
92 Added: warn "Configured SERIAL_DEVICE=$ENV{SERIAL_DEVICE} does not exist; attempting USB serial discovery\n";
93 Added: }
94 Added:
95 Added: return discover_ezo_usb_device();
82 96 }
83 97
84 98 sub close_serial {
roles/daq-node/deploy
index 840c5958..c5a25a2c 100755..100755
@@ -17,7 +17,7 @@
17 17 readonly RUN_USER='fapg-daq'
18 18 readonly RUN_GROUP='fapg-daq'
19 19
20 Removed: readonly SERIAL_DEVICE='/dev/ttyUSB0'
20 Added: readonly SERIAL_DEVICE=''
21 21 readonly READ_INTERVAL=5
22 22 readonly MQTT_HOST='fapg-daq-five-01'
23 23 readonly MQTT_PORT='1883'
@@ -95,13 +95,16 @@
95 95 cat > "${ENV_FILE}" <<EOF
96 96 MQTT_SIMPLE_ALLOW_INSECURE_LOGIN=1
97 97
98 Removed: SERIAL_DEVICE="${SERIAL_DEVICE}"
99 98 READ_INTERVAL=${READ_INTERVAL}
100 99 MQTT_HOST="${MQTT_HOST}"
101 100 MQTT_PORT="${MQTT_PORT}"
102 101 MQTT_USERNAME="${MQTT_USERNAME}"
103 102 MQTT_PASSWORD="${MQTT_PASSWORD}"
104 103 EOF
104 Added:
105 Added: if [[ -n "${SERIAL_DEVICE}" ]]; then
106 Added: echo "SERIAL_DEVICE=\"${SERIAL_DEVICE}\"" >> "${ENV_FILE}"
107 Added: fi
105 108
106 109 chown root:"${RUN_GROUP}" "${ENV_FILE}"
107 110 chmod 0640 "${ENV_FILE}"
roles/daq-node/lib/perl5/FAPG/DAQ/EZO/USB.pm
index 80ec502a..9d0200a9 100644..100644
@@ -11,6 +11,7 @@
11 11 use Time::HiRes qw(time sleep);
12 12
13 13 our @EXPORT_OK = qw(
14 Added: discover_ezo_usb_device
14 15 open_ezo_usb
15 16 drain_serial
16 17 ezo_command
@@ -25,6 +26,37 @@
25 26 my $DEFAULT_BAUDRATE = 9_600;
26 27 my $DEFAULT_TIMEOUT_S = 1.5;
27 28 my $EOL = "\r";
29 Added:
30 Added: sub discover_ezo_usb_device {
31 Added: my %opt = @_;
32 Added:
33 Added: my $by_id_dir = $opt{by_id_dir} // '/dev/serial/by-id';
34 Added: my $preferred_pattern = $opt{preferred_pattern} // qr/UART/i;
35 Added: my @fallback_patterns = exists $opt{fallback_patterns}
36 Added: ? $opt{fallback_patterns}->@*
37 Added: : qw(/dev/ttyUSB* /dev/ttyACM*);
38 Added:
39 Added: my @candidates;
40 Added:
41 Added: if ( opendir my $dh, $by_id_dir ) {
42 Added: my @by_id = map { "$by_id_dir/$_" }
43 Added: sort grep { $_ !~ /\A\.\.?\z/ && -e "$by_id_dir/$_" } readdir $dh;
44 Added:
45 Added: push @candidates, grep { /$preferred_pattern/ } @by_id;
46 Added: push @candidates, grep { $_ !~ /$preferred_pattern/ } @by_id;
47 Added: }
48 Added:
49 Added: for my $pattern (@fallback_patterns) {
50 Added: push @candidates, sort grep { -e $_ && !-d $_ } glob $pattern;
51 Added: }
52 Added:
53 Added: my %seen;
54 Added: @candidates = grep { !$seen{$_}++ } @candidates;
55 Added:
56 Added: return $candidates[0] if @candidates;
57 Added:
58 Added: croak "cannot discover EZO USB serial device under $by_id_dir, /dev/ttyUSB*, or /dev/ttyACM*";
59 Added: }
28 60
29 61 sub open_ezo_usb {
30 62 my %opt = @_;
roles/daq-node/t/01-ezo-usb.t
index aa1a2bd9..28d8e366 100644..100644
@@ -5,11 +5,14 @@
5 5 use warnings;
6 6
7 7 use Test2::V0;
8 Added: use File::Path qw(make_path);
9 Added: use File::Temp qw(tempdir);
8 10
9 11 use FindBin;
10 12 use lib "${FindBin::Bin}/../lib/perl5/";
11 13
12 14 use FAPG::DAQ::EZO::USB qw(
15 Added: discover_ezo_usb_device
13 16 ezo_command
14 17 read_probe_info
15 18 detect_probe_type
@@ -105,6 +108,22 @@
105 108 is unit_for_probe_type('ph'), 'pH';
106 109 is unit_for_probe_type('redox'), 'mV';
107 110 is unit_for_probe_type('ec'), 'uS/cm';
111 Added: };
112 Added:
113 Added: subtest 'USB device discovery prefers UART by-id devices' => sub {
114 Added: my $tmp = tempdir( CLEANUP => 1 );
115 Added: my $by_id = "$tmp/serial/by-id";
116 Added:
117 Added: make_path($by_id);
118 Added:
119 Added: open my $other, '>', "$by_id/usb-Other_Device" or die "cannot create test device: $!";
120 Added: close $other;
121 Added:
122 Added: open my $uart, '>', "$by_id/usb-FTDI_FT232R_USB_UART_A10" or die "cannot create test device: $!";
123 Added: close $uart;
124 Added:
125 Added: is discover_ezo_usb_device( by_id_dir => $by_id, fallback_patterns => [] ),
126 Added: "$by_id/usb-FTDI_FT232R_USB_UART_A10";
108 127 };
109 128
110 129 done_testing;