Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Initial commit of WarpScript code for encoding/decoding #6

Merged
merged 1 commit into from
May 9, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
96 changes: 96 additions & 0 deletions warpscript/makair/decode.mc2
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
//
// Set the TTL of the macro to 1 minute so we can modify it and have
// it reloaded in Warp 10 within 60 seconds.
//
1 m MSTU / MACROTTL
{
'name' 'makair/decode'
'since' '2.5.1'
'desc'
<'
Decode a message encoded via `@makair/encode` and output the individual frames.
'>
'sig' [
[ [ 'message:BYTES' ] [ 'frames:LIST<MAP>' ] ]
]
'params' {
'message' 'Encoded message that needs to be decoded.'
'frames' 'List of extracted frames.'
}
} '.info' STORE
<%
!$.info INFO
SAVE '.context' STORE
//
// Decode the Protobuf message
//
@makair/proto
'MakAirTelemetry' PB->
'message' STORE
//
// Extract the device_id
//
$message 'device_id' GET 'device_id' STORE
$message 'timestamp' GET 'timestamp' STORE
$message 'encoded' GET 0 GET
// Decompress content
@senx/gzip/UNOPTGZIP
'encoded' STORE

//
// Decode the VARINTs
//
$encoded VARINT-> 'varints' STORE

//
// Reshape the array.
// Each frame contains 9 numbers
//
$varints [ $varints SIZE 9 / 9 ] RESHAPE

<%
0 !=
<%
'current' STORE
// Add the current values with those from the previous
// reconstructed array
[ $last $current ] ZIP
<%
LIST-> DROP
// Undo the zig zag trick
'unsigned' STORE
$unsigned 63 << 63 >> $unsigned ^ 1 >>
// Flip the top bit
$unsigned 1 63 << & ^
+
%> false LMAP
%>
IFT
'last' STORE $last
%> LMAP

//
// We now have an array with arrays containing the original
// values from each frame. We will rebuild the frames.
//
<%
{} SWAP
[
'systick'
'cycle'
'peak_command'
'plateau_command'
'peep_command'
'cpm_command'
'previous_peak_pressure'
'previous_plateau_pressure'
'previous_peep_pressure'
]
2 ->LIST ZIP
<%
LIST-> DROP PUT
%> FOREACH
$device_id 'device_id' PUT
%> false LMAP
$.context RESTORE
%>
133 changes: 133 additions & 0 deletions warpscript/makair/encode.mc2
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
//
// Set the TTL of the macro to 1 minute so we can modify it and have
// it reloaded in Warp 10 within 60 seconds.
//
1 m MSTU / MACROTTL

{
'name' 'makair/encode'
// This macro needs the ->VARINT function which appeared in 2.5.1
'since' '2.5.1'
'desc'
<'
Encodes a number of MakAir telemetry `MachineStateSnapshot` frames into a Protobuf message suitable for transmission over LoRa.

The current alarm codes from the frames are NOT included in the message. They need to be transmitted independently. Since they are related to a life threatening situation, they can be transmitted over LoRa without respecting the air time limit.
'>
'sig' [
[ [ 'timestamp:LONG' 'frames:LIST<BYTES>' ] [ 'message:BYTES' ] ]
]
'params' {
'timestamp' 'Timestamp (in platform time units) of the first frame of the list.'
'frames' 'List of telemetry frames of type `MachineStateSnapshot`.'
'message' 'Protobuf messages containing the input frames.'
}
} '.info' STORE
<%
!$.info INFO
SAVE '.context' STORE
[ 'frames' 'timestamp' ] STORE

//
// Iterate over the frames, keeping only the `MachineStateSnapshot` ones
//
[]
$frames
<%
MAKAIR.TELEMETRY-> 'frame' STORE
$frame 'type' GET
'MachineStateSnapshot' != <% CONTINUE %> IFT
// Add the frame to the list
$frame +!
%> FOREACH

// Replace the original list with only the `MachineStateSnapshot`
'frames' STORE

//
// Now extract all fields in an array for each frame
// Note: we ignore the current alarm codes
//

// Remove variable $device_id if set
'device_id' FORGET

$frames
<%
'telemetry' STORE
// Extract the device_id, the first one will be used
// for all frames
$telemetry 'device_id' GET 'device_id' CSTORE
[
$telemetry 'systick' GET
$telemetry 'cycle' GET
$telemetry 'peak_command' GET
$telemetry 'plateau_command' GET
$telemetry 'peep_command' GET
$telemetry 'cpm_command' GET
$telemetry 'previous_peak_pressure' GET
$telemetry 'previous_plateau_pressure' GET
$telemetry 'previous_peep_pressure' GET
]
%> false LMAP
'values' STORE

//
// Compute deltas
//
$values
<%
'idx' STORE
// Keep the first array as is
$idx 0 ==
<%
'last' STORE $last
// We do not ZigZag encode the first array as we assume
// numbers are not negative and we want to encode the
// first systick value on as few bytes as possible
%>
<%
'current' STORE
[ $current $last ] ZIP
<%
LIST-> DROP -
%> false LMAP
$current 'last' STORE
// Adapt value so we alternatively encode positive and negative values
<%
DUP 1 << SWAP 63 >> ^
%> false LMAP
%>
IFTE
// Encode all the LONGs using VARINT encoding, producing
// a single byte array
->VARINT
%> LMAP

//
// Concatenate the byte arrays resulting from the ->VARINT calls
//
'' 'ASCII' ->BYTES SWAP
<% + %> FOREACH

//
// Compress the resulting byte array using optimized GZIP
// This macro in on SenX' WarpFleet repository:
//
// https://warpfleet.senx.io/macros/senx/gzip/OPTGZIP.mc2
//
@senx/gzip/OPTGZIP
'encoded' STORE

//
// Now build the protobuf message
//
{
'device_id' $device_id
'timestamp' $timestamp
// We do not need to set 'encoding' since the default
// enum value for Encoding is MAKAIR_DELTA_OPTGZIP
'encoded' [ $encoded ]
} @makair/proto 'MakAirTelemetry' ->PB
$.context RESTORE
%>
Loading