39 if (act == NULL || out == NULL || len == NULL) {
return false; }
41 (*out) = calloc(5 + act->
length + 2 * act->
datalen,
sizeof(uint8_t));
51 (*out)[5] = (act->
PGN & 0x0000FF);
52 (*out)[6] = (act->
PGN & 0x00FF00) >> 8;
53 (*out)[7] = (act->
PGN & 0xFF0000) >> 16;
57 (*out)[10] = (act->
timestamp & 0x000000FF);
58 (*out)[11] = (act->
timestamp & 0x0000FF00) >> 8;
59 (*out)[12] = (act->
timestamp & 0x00FF0000) >> 16;
60 (*out)[13] = (act->
timestamp & 0xFF000000) >> 24;
63 for (
int i = 0; i < act->
datalen; i++) {
64 (*out)[ix++] = act->
data[i];
70 (*out)[ix++] = act->
csum;
74 uint8_t *o = realloc((*out), ix *
sizeof(uint8_t));
99 if (in == NULL || msg == NULL || len < 18 || pos == NULL) {
return NULL; }
102 while (((*pos) + 18) < len) {
116 if (debug) { fprintf(stderr,
"N2K: No start marker found\n"); }
119 if ((len - start) < in[start + 3]) {
122 if (debug) { fprintf(stderr,
"N2K: Insufficient data\n"); }
127 if ((*msg) == NULL) {
128 perror(
"n2k_act_from_bytes");
132 (*msg)->length = in[start + 3];
133 (*msg)->priority = in[start + 4];
134 (*msg)->PGN = in[start + 5] + ((uint32_t)in[start + 6] << 8) + ((uint32_t)in[start + 7] << 16);
138 (*msg)->dst = in[start + 8];
139 (*msg)->src = in[start + 9];
143 (*msg)->timestamp = in[start + 10] + ((uint32_t)in[start + 11] << 8) + ((uint32_t)in[start + 12] << 16) +
144 ((uint32_t)in[start + 13] << 24);
145 (*msg)->datalen = in[start + 14];
147 volatile ssize_t remaining = len - start - 15;
148 if (remaining <= ((*msg)->datalen + 3)) {
153 if (debug) { fprintf(stderr,
"N2K: Insufficient data to read in message content\n"); }
157 (*msg)->data = calloc((*msg)->datalen,
sizeof(uint8_t));
158 if ((*msg)->data == NULL) {
159 perror(
"n2k_act_from_bytes:data-calloc");
167 for (
int i = 0; i < (*msg)->datalen; i++) {
168 uint8_t c = in[(start + off++)];
171 uint8_t next = in[(start + off++)];
177 (*pos) = (start + off);
181 if (debug) { fprintf(stderr,
"N2K: Premature Termination\n"); }
186 (*pos) = (start + off - 2);
190 if (debug) { fprintf(stderr,
"N2K: Unexpected start of message marker\n"); }
194 (*pos) = (start + off);
199 fprintf(stderr,
"N2K: Bad character escape sequence (ESC + 0x%02x\n", next);
207 if (remaining < ((*msg)->datalen - i + 3)) {
211 if (debug) { fprintf(stderr,
"N2K: Out of data while parsing\n"); }
216 (*msg)->csum = in[(start + off++)];
218 uint8_t ee = in[(start + off++)];
219 uint8_t et = in[(start + off++)];
221 if (et ==
ACT_ESC && (ssize_t)(start + off) < remaining) {
222 uint8_t next = in[(start + off)];
227 fprintf(stderr,
"Unexpected sequence at end of message: 0x%02x 0x%02x\n", ee, et);
232 (*pos) = start + off;
235 if ((*msg)->csum != cs) {
237 fprintf(stderr,
"Bad checksum (%d => %d\tPGN %d)\n", (*msg)->src, (*msg)->dst, (*msg)->PGN);
252 csum += (msg->
PGN & 0x0000FF);
253 csum += ((msg->
PGN & 0x00FF00) >> 8);
254 csum += ((msg->
PGN & 0xFF0000) >> 16);
258 csum += ((msg->
timestamp & 0x0000FF00) >> 8);
259 csum += ((msg->
timestamp & 0x00FF0000) >> 16);
260 csum += ((msg->
timestamp & 0xFF000000) >> 24);
263 for (
int i = 0; i < msg->
datalen; ++i) {
264 csum += msg->
data[i];
279 fprintf(stdout,
"N2k ACT Message: ");
280 for (
unsigned int j = 0; j < len; ++j) {
281 fprintf(stdout,
"%c%02x", j > 0 ?
':' :
' ', tmp[j]);
283 fprintf(stdout,
"\n");
285 fprintf(stdout,
"N2k ACT Message: [Byte conversion failed]\n");
#define ACT_N2K
N2k Message.
#define ACT_ESC
Escape character.
bool n2k_act_from_bytes(const uint8_t *in, const size_t len, n2k_act_message **msg, size_t *pos, bool debug)
Convert a series of recieved bytes from ACT gateway devices into a message representation.
void n2k_act_print(const n2k_act_message *msg)
Print representation of an n2k_act_message to standard output.
uint8_t n2k_act_checksum(const n2k_act_message *msg)
Calculate checksum for n2k_act_message.
bool n2k_act_to_bytes(const n2k_act_message *act, uint8_t **out, size_t *len)
Convert N2K message to a series of bytes compatible with ACT gateway devices.
#define ACT_EOT
End of text.
#define ACT_SOT
Start of text.
uint8_t priority
N2K Message priority value.
uint32_t PGN
24 bit PGN identifier
uint8_t * data
Message payload.
uint8_t datalen
Length of *data.
uint8_t dst
Message destination.
uint32_t timestamp
Message timestamp.
uint8_t src
Message source.
uint8_t length
Counted from priority to csum.