Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
B
balloon-tx-monolith
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Package registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Stephen D
balloon-tx-monolith
Commits
964aab47
Commit
964aab47
authored
1 year ago
by
Stephen D
Browse files
Options
Downloads
Patches
Plain Diff
wire up requesting high quality images
parent
6886b843
No related branches found
Branches containing commit
No related tags found
No related merge requests found
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
src/aprs.rs
+4
-4
4 additions, 4 deletions
src/aprs.rs
src/control.rs
+42
-20
42 additions, 20 deletions
src/control.rs
src/img.rs
+71
-15
71 additions, 15 deletions
src/img.rs
src/main.rs
+1
-1
1 addition, 1 deletion
src/main.rs
src/ssdv.rs
+9
-2
9 additions, 2 deletions
src/ssdv.rs
with
127 additions
and
42 deletions
src/aprs.rs
+
4
−
4
View file @
964aab47
...
...
@@ -39,7 +39,7 @@ pub struct CommandHandler {
burst_command
:
String
,
cutdown_command
:
String
,
img_request
_queue
:
Sender
<
u8
>
,
img_request
:
Sender
<
u8
>
,
}
impl
CommandHandler
{
...
...
@@ -48,7 +48,7 @@ impl CommandHandler {
secret
:
String
,
burst_command
:
String
,
cutdown_command
:
String
,
img_request
_queue
:
Sender
<
u8
>
,
img_request
:
Sender
<
u8
>
,
)
->
Self
{
Self
{
callsign
,
...
...
@@ -57,11 +57,11 @@ impl CommandHandler {
burst_command
,
cutdown_command
,
img_request
_queue
,
img_request
,
}
}
fn
process_forever
(
&
self
)
{
pub
fn
process_forever
(
&
self
)
{
tokio
::
runtime
::
Builder
::
new_current_thread
()
.enable_all
()
.build
()
...
...
This diff is collapsed.
Click to expand it.
src/control.rs
+
42
−
20
View file @
964aab47
use
std
::{
io
::{
Read
,
Write
},
path
::
PathBuf
,
sync
::
mpsc
::{
self
,
Receiver
,
SyncSender
},
sync
::
mpsc
::{
self
,
Receiver
,
Sender
,
SyncSender
},
thread
,
time
::
Duration
,
};
...
...
@@ -9,36 +8,38 @@ use std::{
use
anyhow
::
Context
;
use
serial
::{
BaudRate
::
BaudOther
,
SerialPort
};
use
crate
::{
img
::
ImgManager
,
packet
::
FecPacket
,
ssdv
::
ssdv_encode
};
use
crate
::{
aprs
::
CommandHandler
,
config
::
Config
,
img
::
ImgManager
,
packet
::
FecPacket
,
ssdv
::
ssdv_encode
,
};
const
IMAGE_PACKET_QUEUE_LENGTH
:
usize
=
1024
;
pub
struct
Controller
{
callsign
:
String
,
manager
:
ImgManager
,
config
:
Config
,
}
impl
Controller
{
pub
fn
new
(
callsign
:
String
,
paths
:
Vec
<
PathBuf
>
)
->
Self
{
Self
{
callsign
,
manager
:
ImgManager
::
new
(
paths
),
}
pub
fn
new
(
config
:
Config
)
->
Self
{
Self
{
config
}
}
pub
fn
run_forever
(
&
mut
self
)
{
let
(
tx
,
rx
)
=
mpsc
::
sync_channel
(
IMAGE_PACKET_QUEUE_LENGTH
);
pub
fn
run_forever
(
self
)
{
let
(
img_tx
,
img_rx
)
=
mpsc
::
sync_channel
(
IMAGE_PACKET_QUEUE_LENGTH
);
let
(
cmd_tx
,
cmd_rx
)
=
mpsc
::
channel
();
thread
::
spawn
(||
Self
::
tx_thread
(
img_rx
));
{
let
config
=
self
.config
.clone
();
thread
::
spawn
(||
Self
::
aprs_thread
(
config
,
cmd_tx
));
}
thread
::
spawn
(||
Self
::
tx_thread
(
rx
)
)
;
let
mut
manager
=
ImgManager
::
new
(
self
.config.paths
.clone
(),
cmd_
rx
);
let
mut
idx
=
0
;
loop
{
while
let
Some
(
bytes
)
=
self
.
manager
.next
()
{
if
let
Err
(
e
)
=
self
.process_image
(
&
bytes
,
idx
,
&
tx
)
{
while
let
Some
(
(
idx
,
bytes
,
lossless
))
=
manager
.next
()
{
if
let
Err
(
e
)
=
self
.process_image
(
&
bytes
,
idx
,
&
img_tx
,
lossless
)
{
eprintln!
(
"Error processing image: {e}"
);
}
idx
=
idx
.wrapping_add
(
1
);
}
// after we don't find anything, sleep for a bit while
...
...
@@ -47,14 +48,35 @@ impl Controller {
}
}
fn
process_image
(
&
self
,
img
:
&
[
u8
],
idx
:
u8
,
tx
:
&
SyncSender
<
FecPacket
>
)
->
anyhow
::
Result
<
()
>
{
for
p
in
ssdv_encode
(
&
self
.callsign
,
img
,
idx
)
?
{
fn
process_image
(
&
self
,
img
:
&
[
u8
],
idx
:
u8
,
tx
:
&
SyncSender
<
FecPacket
>
,
lossless
:
bool
,
)
->
anyhow
::
Result
<
()
>
{
for
p
in
ssdv_encode
(
&
self
.config.callsign
,
img
,
idx
,
lossless
)
?
{
tx
.send
(
p
.into
())
.context
(
"TX thread died"
)
?
;
}
Ok
(())
}
// manages incoming APRS packets
// used to request HD images, as well as
// to initiate burst/cutdown
fn
aprs_thread
(
config
:
Config
,
tx
:
Sender
<
u8
>
)
{
let
handler
=
CommandHandler
::
new
(
config
.callsign
,
config
.secret
,
config
.burst_command
,
config
.cutdown_command
,
tx
,
);
handler
.process_forever
();
}
// manages our transceiver
// TODO currently very hacky, because we're going to rip
// most of this out when we stop using a lobotomized NPR-70
...
...
This diff is collapsed.
Click to expand it.
src/img.rs
+
71
−
15
View file @
964aab47
use
image
::{
imageops
::
FilterType
,
io
::
Reader
as
ImageReader
,
ImageOutputFormat
};
use
std
::{
fs
,
io
::
Cursor
,
path
::
PathBuf
};
use
std
::{
fs
,
io
::
Cursor
,
path
::
PathBuf
,
sync
::
mpsc
::
Receiver
};
const
IMG_DIM
:
u32
=
1024
;
const
JPEG_QUALITY
:
u8
=
100
;
// let ssdv do the compression
...
...
@@ -43,35 +43,78 @@ impl ImgInfo {
Ok
(
bytes
)
}
pub
fn
lossless_jpeg_bytes
(
&
self
)
->
anyhow
::
Result
<
Vec
<
u8
>>
{
let
img
=
ImageReader
::
open
(
&
self
.path
)
?
.decode
()
?
;
// turn image into a square, making it bigger in the process
// must be divisible by 16
let
mut
dim
=
img
.width
()
.max
(
img
.height
());
let
offset
=
dim
%
16
;
dim
+=
(
16
-
offset
)
%
16
;
img
.crop_imm
(
0
,
0
,
dim
,
dim
);
let
mut
bytes
=
vec!
[];
img
.write_to
(
&
mut
Cursor
::
new
(
&
mut
bytes
),
ImageOutputFormat
::
Jpeg
(
JPEG_QUALITY
),
)
?
;
Ok
(
bytes
)
}
}
pub
struct
ImgManager
{
paths
:
Vec
<
PathBuf
>
,
imgs
:
Vec
<
ImgInfo
>
,
// used to receive image requests, which will be sent at full resolution
rx
:
Receiver
<
u8
>
,
// state for iterator
iter
:
u64
,
path_idx
:
usize
,
found
:
bool
,
tx_idx
:
u8
,
// map between sent image ids, the the images
// in the array above
// used for decoding rx requests
img_map
:
[
usize
;
256
],
}
impl
ImgManager
{
pub
fn
new
(
paths
:
Vec
<
PathBuf
>
)
->
Self
{
pub
fn
new
(
paths
:
Vec
<
PathBuf
>
,
rx
:
Receiver
<
u8
>
)
->
Self
{
Self
{
paths
,
imgs
:
vec!
[],
rx
,
iter
:
0
,
path_idx
:
0
,
found
:
false
,
tx_idx
:
0
,
img_map
:
[
0
;
256
],
}
}
// not making this an iterator since
// it's entirely valid to have a Some(...)
// after a None
pub
fn
next
(
&
mut
self
)
->
Option
<
Vec
<
u8
>>
{
pub
fn
next
(
&
mut
self
)
->
Option
<
(
u8
,
Vec
<
u8
>
,
bool
)
>
{
loop
{
if
let
Ok
(
req
)
=
self
.rx
.try_recv
()
{
let
img
=
self
.img_map
.get
(
usize
::
from
(
req
))
.and_then
(|
id
|
self
.imgs
.get
(
*
id
))
.and_then
(|
img
|
img
.lossless_jpeg_bytes
()
.ok
());
if
let
Some
(
img
)
=
img
{
return
Some
((
self
.inc_tx
(
None
),
img
,
true
));
}
}
if
let
Err
(
e
)
=
self
.scan_path
()
{
eprintln!
(
"Error scanning {}: {}"
,
...
...
@@ -84,21 +127,22 @@ impl ImgManager {
let
new
=
self
.imgs
.iter_mut
()
.filter
(|
img
|
!
img
.txed
)
// non-sent images only
.filter
(|
img
|
img
.path_idx
==
self
.path_idx
)
.filter
(|
img
|
img
.found_on_iter
==
self
.iter
)
.max_by_key
(|
img
|
img
.size_bytes
);
.enumerate
()
.filter
(|(
_
,
img
)|
!
img
.txed
)
// non-sent images only
.filter
(|(
_
,
img
)|
img
.path_idx
==
self
.path_idx
)
.filter
(|(
_
,
img
)|
img
.found_on_iter
==
self
.iter
)
.max_by_key
(|(
_
,
img
)|
img
.size_bytes
);
if
let
Some
(
new
)
=
new
{
if
let
Some
(
(
new
_id
,
new
)
)
=
new
{
new
.txed
=
true
;
let
bytes
=
new
.compressed_jpeg_bytes
();
self
.inc_iter
(
true
);
// not perfect. ideally we would keep looking throug the new images
// not perfect. ideally we would keep looking throug
h
the new images
// if this Err'd
if
let
Ok
(
x
)
=
bytes
{
return
Some
(
x
);
return
Some
(
(
self
.inc_tx
(
Some
(
new_id
)),
x
,
false
)
);
}
}
...
...
@@ -106,18 +150,19 @@ impl ImgManager {
let
old
=
self
.imgs
.iter_mut
()
.filter
(|
img
|
!
img
.txed
)
// non-sent images only
.filter
(|
img
|
img
.path_idx
==
self
.path_idx
)
.max_by_key
(|
img
|
img
.size_bytes
);
.enumerate
()
.filter
(|(
_
,
img
)|
!
img
.txed
)
// non-sent images only
.filter
(|(
_
,
img
)|
img
.path_idx
==
self
.path_idx
)
.max_by_key
(|(
_
,
img
)|
img
.size_bytes
);
if
let
Some
(
old
)
=
old
{
if
let
Some
(
(
old
_idx
,
old
)
)
=
old
{
old
.txed
=
true
;
let
bytes
=
old
.compressed_jpeg_bytes
();
self
.inc_iter
(
true
);
if
let
Ok
(
x
)
=
bytes
{
return
Some
(
x
);
return
Some
(
(
self
.inc_tx
(
Some
(
old_idx
)),
x
,
false
)
);
}
}
...
...
@@ -146,6 +191,17 @@ impl ImgManager {
true
}
fn
inc_tx
(
&
mut
self
,
id
:
Option
<
usize
>
)
->
u8
{
let
idx
=
self
.tx_idx
;
self
.tx_idx
=
self
.tx_idx
.wrapping_add
(
1
);
if
let
Some
(
id
)
=
id
{
self
.img_map
[
usize
::
from
(
idx
)]
=
id
;
}
idx
}
fn
scan_path
(
&
mut
self
)
->
anyhow
::
Result
<
()
>
{
// imgs we don't already have
let
new_imgs
:
Vec
<
_
>
=
fs
::
read_dir
(
&
self
.paths
[
self
.path_idx
])
?
...
...
This diff is collapsed.
Click to expand it.
src/main.rs
+
1
−
1
View file @
964aab47
...
...
@@ -13,7 +13,7 @@ mod ssdv;
fn
main
()
->
anyhow
::
Result
<
()
>
{
let
config
=
Config
::
load
()
?
;
let
mut
controller
=
Controller
::
new
(
config
.callsign
,
config
.paths
);
let
controller
=
Controller
::
new
(
config
);
controller
.run_forever
();
...
...
This diff is collapsed.
Click to expand it.
src/ssdv.rs
+
9
−
2
View file @
964aab47
...
...
@@ -4,7 +4,14 @@ use crate::packet::RawPacket;
// TODO eventually rewrite Ssdv in Rust?
// Don't want to use FFI because then segfaults can hurt us
pub
fn
ssdv_encode
(
callsign
:
&
str
,
img
:
&
[
u8
],
img_idx
:
u8
)
->
anyhow
::
Result
<
Vec
<
RawPacket
>>
{
pub
fn
ssdv_encode
(
callsign
:
&
str
,
img
:
&
[
u8
],
img_idx
:
u8
,
lossless
:
bool
,
)
->
anyhow
::
Result
<
Vec
<
RawPacket
>>
{
let
quality
=
if
lossless
{
"7"
}
else
{
"6"
};
let
(
stdout
,
stderr
)
=
subprocess
::
Exec
::
cmd
(
"ssdv"
)
.args
(
&
[
"-e"
,
...
...
@@ -12,7 +19,7 @@ pub fn ssdv_encode(callsign: &str, img: &[u8], img_idx: u8) -> anyhow::Result<Ve
callsign
,
"-n"
,
"-q"
,
"6"
,
quality
,
"-i"
,
&
format!
(
"{}"
,
img_idx
),
])
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment