Skip to content

Commit

Permalink
Merge pull request #6 from makers-for-life/warpscript
Browse files Browse the repository at this point in the history
Initial commit of WarpScript code for encoding/decoding
  • Loading branch information
Mefl authored May 9, 2020
2 parents c66c924 + 731352a commit ee56cd4
Show file tree
Hide file tree
Showing 3 changed files with 421 additions and 0 deletions.
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

0 comments on commit ee56cd4

Please sign in to comment.