kopia lustrzana https://github.com/PiInTheSky/lora-gateway
Add HABpack Telemetry & Calling mode.
rodzic
7d501594c2
commit
a9f7d9f03c
Plik diff jest za duży
Load Diff
|
@ -0,0 +1,526 @@
|
|||
/*
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017 Charles Gunyon
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef CMP_H__
|
||||
#define CMP_H__
|
||||
|
||||
struct cmp_ctx_s;
|
||||
|
||||
typedef bool (*cmp_reader)(struct cmp_ctx_s *ctx, void *data, size_t limit);
|
||||
typedef bool (*cmp_skipper)(struct cmp_ctx_s *ctx, size_t count);
|
||||
typedef size_t (*cmp_writer)(struct cmp_ctx_s *ctx, const void *data,
|
||||
size_t count);
|
||||
|
||||
enum {
|
||||
CMP_TYPE_POSITIVE_FIXNUM, /* 0 */
|
||||
CMP_TYPE_FIXMAP, /* 1 */
|
||||
CMP_TYPE_FIXARRAY, /* 2 */
|
||||
CMP_TYPE_FIXSTR, /* 3 */
|
||||
CMP_TYPE_NIL, /* 4 */
|
||||
CMP_TYPE_BOOLEAN, /* 5 */
|
||||
CMP_TYPE_BIN8, /* 6 */
|
||||
CMP_TYPE_BIN16, /* 7 */
|
||||
CMP_TYPE_BIN32, /* 8 */
|
||||
CMP_TYPE_EXT8, /* 9 */
|
||||
CMP_TYPE_EXT16, /* 10 */
|
||||
CMP_TYPE_EXT32, /* 11 */
|
||||
CMP_TYPE_FLOAT, /* 12 */
|
||||
CMP_TYPE_DOUBLE, /* 13 */
|
||||
CMP_TYPE_UINT8, /* 14 */
|
||||
CMP_TYPE_UINT16, /* 15 */
|
||||
CMP_TYPE_UINT32, /* 16 */
|
||||
CMP_TYPE_UINT64, /* 17 */
|
||||
CMP_TYPE_SINT8, /* 18 */
|
||||
CMP_TYPE_SINT16, /* 19 */
|
||||
CMP_TYPE_SINT32, /* 20 */
|
||||
CMP_TYPE_SINT64, /* 21 */
|
||||
CMP_TYPE_FIXEXT1, /* 22 */
|
||||
CMP_TYPE_FIXEXT2, /* 23 */
|
||||
CMP_TYPE_FIXEXT4, /* 24 */
|
||||
CMP_TYPE_FIXEXT8, /* 25 */
|
||||
CMP_TYPE_FIXEXT16, /* 26 */
|
||||
CMP_TYPE_STR8, /* 27 */
|
||||
CMP_TYPE_STR16, /* 28 */
|
||||
CMP_TYPE_STR32, /* 29 */
|
||||
CMP_TYPE_ARRAY16, /* 30 */
|
||||
CMP_TYPE_ARRAY32, /* 31 */
|
||||
CMP_TYPE_MAP16, /* 32 */
|
||||
CMP_TYPE_MAP32, /* 33 */
|
||||
CMP_TYPE_NEGATIVE_FIXNUM /* 34 */
|
||||
};
|
||||
|
||||
typedef struct cmp_ext_s {
|
||||
int8_t type;
|
||||
uint32_t size;
|
||||
} cmp_ext_t;
|
||||
|
||||
union cmp_object_data_u {
|
||||
bool boolean;
|
||||
uint8_t u8;
|
||||
uint16_t u16;
|
||||
uint32_t u32;
|
||||
uint64_t u64;
|
||||
int8_t s8;
|
||||
int16_t s16;
|
||||
int32_t s32;
|
||||
int64_t s64;
|
||||
float flt;
|
||||
double dbl;
|
||||
uint32_t array_size;
|
||||
uint32_t map_size;
|
||||
uint32_t str_size;
|
||||
uint32_t bin_size;
|
||||
cmp_ext_t ext;
|
||||
};
|
||||
|
||||
typedef struct cmp_ctx_s {
|
||||
uint8_t error;
|
||||
void *buf;
|
||||
cmp_reader read;
|
||||
cmp_skipper skip;
|
||||
cmp_writer write;
|
||||
} cmp_ctx_t;
|
||||
|
||||
typedef struct cmp_object_s {
|
||||
uint8_t type;
|
||||
union cmp_object_data_u as;
|
||||
} cmp_object_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* ============================================================================
|
||||
* === Main API
|
||||
* ============================================================================
|
||||
*/
|
||||
|
||||
/*
|
||||
* Initializes a CMP context
|
||||
*
|
||||
* If you don't intend to read, `read` may be NULL, but calling `*read*`
|
||||
* functions will crash; there is no check.
|
||||
*
|
||||
* `skip` may be NULL, in which case skipping functions will use `read`.
|
||||
*
|
||||
* If you don't intend to write, `write` may be NULL, but calling `*write*`
|
||||
* functions will crash; there is no check.
|
||||
*/
|
||||
void cmp_init(cmp_ctx_t *ctx, void *buf, cmp_reader read,
|
||||
cmp_skipper skip,
|
||||
cmp_writer write);
|
||||
|
||||
/* Returns CMP's version */
|
||||
uint32_t cmp_version(void);
|
||||
|
||||
/* Returns the MessagePack version employed by CMP */
|
||||
uint32_t cmp_mp_version(void);
|
||||
|
||||
/* Returns a string description of a CMP context's error */
|
||||
const char* cmp_strerror(cmp_ctx_t *ctx);
|
||||
|
||||
/* Writes a signed integer to the backend */
|
||||
bool cmp_write_integer(cmp_ctx_t *ctx, int64_t d);
|
||||
|
||||
/* Writes an unsigned integer to the backend */
|
||||
bool cmp_write_uinteger(cmp_ctx_t *ctx, uint64_t u);
|
||||
|
||||
/*
|
||||
* Writes a floating-point value (either single or double-precision) to the
|
||||
* backend
|
||||
*/
|
||||
bool cmp_write_decimal(cmp_ctx_t *ctx, double d);
|
||||
|
||||
/* Writes NULL to the backend */
|
||||
bool cmp_write_nil(cmp_ctx_t *ctx);
|
||||
|
||||
/* Writes true to the backend */
|
||||
bool cmp_write_true(cmp_ctx_t *ctx);
|
||||
|
||||
/* Writes false to the backend */
|
||||
bool cmp_write_false(cmp_ctx_t *ctx);
|
||||
|
||||
/* Writes a boolean value to the backend */
|
||||
bool cmp_write_bool(cmp_ctx_t *ctx, bool b);
|
||||
|
||||
/*
|
||||
* Writes an unsigned char's value to the backend as a boolean. This is useful
|
||||
* if you are using a different boolean type in your application.
|
||||
*/
|
||||
bool cmp_write_u8_as_bool(cmp_ctx_t *ctx, uint8_t b);
|
||||
|
||||
/*
|
||||
* Writes a string to the backend; according to the MessagePack spec, this must
|
||||
* be encoded using UTF-8, but CMP leaves that job up to the programmer.
|
||||
*/
|
||||
bool cmp_write_str(cmp_ctx_t *ctx, const char *data, uint32_t size);
|
||||
|
||||
/*
|
||||
* Writes a string to the backend. This avoids using the STR8 marker, which
|
||||
* is unsupported by MessagePack v4, the version implemented by many other
|
||||
* MessagePack libraries. No encoding is assumed in this case, not that it
|
||||
* matters.
|
||||
*/
|
||||
bool cmp_write_str_v4(cmp_ctx_t *ctx, const char *data, uint32_t size);
|
||||
|
||||
/*
|
||||
* Writes the string marker to the backend. This is useful if you are writing
|
||||
* data in chunks instead of a single shot.
|
||||
*/
|
||||
bool cmp_write_str_marker(cmp_ctx_t *ctx, uint32_t size);
|
||||
|
||||
/*
|
||||
* Writes the string marker to the backend. This is useful if you are writing
|
||||
* data in chunks instead of a single shot. This avoids using the STR8
|
||||
* marker, which is unsupported by MessagePack v4, the version implemented by
|
||||
* many other MessagePack libraries. No encoding is assumed in this case, not
|
||||
* that it matters.
|
||||
*/
|
||||
bool cmp_write_str_marker_v4(cmp_ctx_t *ctx, uint32_t size);
|
||||
|
||||
/* Writes binary data to the backend */
|
||||
bool cmp_write_bin(cmp_ctx_t *ctx, const void *data, uint32_t size);
|
||||
|
||||
/*
|
||||
* Writes the binary data marker to the backend. This is useful if you are
|
||||
* writing data in chunks instead of a single shot.
|
||||
*/
|
||||
bool cmp_write_bin_marker(cmp_ctx_t *ctx, uint32_t size);
|
||||
|
||||
/* Writes an array to the backend. */
|
||||
bool cmp_write_array(cmp_ctx_t *ctx, uint32_t size);
|
||||
|
||||
/* Writes a map to the backend. */
|
||||
bool cmp_write_map(cmp_ctx_t *ctx, uint32_t size);
|
||||
|
||||
/* Writes an extended type to the backend */
|
||||
bool cmp_write_ext(cmp_ctx_t *ctx, int8_t type, uint32_t size,
|
||||
const void *data);
|
||||
|
||||
/*
|
||||
* Writes the extended type marker to the backend. This is useful if you want
|
||||
* to write the type's data in chunks instead of a single shot.
|
||||
*/
|
||||
bool cmp_write_ext_marker(cmp_ctx_t *ctx, int8_t type, uint32_t size);
|
||||
|
||||
/* Writes an object to the backend */
|
||||
bool cmp_write_object(cmp_ctx_t *ctx, cmp_object_t *obj);
|
||||
|
||||
/*
|
||||
* Writes an object to the backend. This avoids using the STR8 marker, which
|
||||
* is unsupported by MessagePack v4, the version implemented by many other
|
||||
* MessagePack libraries.
|
||||
*/
|
||||
bool cmp_write_object_v4(cmp_ctx_t *ctx, cmp_object_t *obj);
|
||||
|
||||
/* Reads a signed integer that fits inside a signed char */
|
||||
bool cmp_read_char(cmp_ctx_t *ctx, int8_t *c);
|
||||
|
||||
/* Reads a signed integer that fits inside a signed short */
|
||||
bool cmp_read_short(cmp_ctx_t *ctx, int16_t *s);
|
||||
|
||||
/* Reads a signed integer that fits inside a signed int */
|
||||
bool cmp_read_int(cmp_ctx_t *ctx, int32_t *i);
|
||||
|
||||
/* Reads a signed integer that fits inside a signed long */
|
||||
bool cmp_read_long(cmp_ctx_t *ctx, int64_t *d);
|
||||
|
||||
/* Reads a signed integer */
|
||||
bool cmp_read_integer(cmp_ctx_t *ctx, int64_t *d);
|
||||
|
||||
/* Reads an unsigned integer that fits inside an unsigned char */
|
||||
bool cmp_read_uchar(cmp_ctx_t *ctx, uint8_t *c);
|
||||
|
||||
/* Reads an unsigned integer that fits inside an unsigned short */
|
||||
bool cmp_read_ushort(cmp_ctx_t *ctx, uint16_t *s);
|
||||
|
||||
/* Reads an unsigned integer that fits inside an unsigned int */
|
||||
bool cmp_read_uint(cmp_ctx_t *ctx, uint32_t *i);
|
||||
|
||||
/* Reads an unsigned integer that fits inside an unsigned long */
|
||||
bool cmp_read_ulong(cmp_ctx_t *ctx, uint64_t *u);
|
||||
|
||||
/* Reads an unsigned integer */
|
||||
bool cmp_read_uinteger(cmp_ctx_t *ctx, uint64_t *u);
|
||||
|
||||
/*
|
||||
* Reads a floating point value (either single or double-precision) from the
|
||||
* backend
|
||||
*/
|
||||
bool cmp_read_decimal(cmp_ctx_t *ctx, double *d);
|
||||
|
||||
/* "Reads" (more like "skips") a NULL value from the backend */
|
||||
bool cmp_read_nil(cmp_ctx_t *ctx);
|
||||
|
||||
/* Reads a boolean from the backend */
|
||||
bool cmp_read_bool(cmp_ctx_t *ctx, bool *b);
|
||||
|
||||
/*
|
||||
* Reads a boolean as an unsigned char from the backend; this is useful if your
|
||||
* application uses a different boolean type.
|
||||
*/
|
||||
bool cmp_read_bool_as_u8(cmp_ctx_t *ctx, uint8_t *b);
|
||||
|
||||
/* Reads a string's size from the backend */
|
||||
bool cmp_read_str_size(cmp_ctx_t *ctx, uint32_t *size);
|
||||
|
||||
/*
|
||||
* Reads a string from the backend; according to the spec, the string's data
|
||||
* ought to be encoded using UTF-8,
|
||||
*/
|
||||
bool cmp_read_str(cmp_ctx_t *ctx, char *data, uint32_t *size);
|
||||
|
||||
/* Reads the size of packed binary data from the backend */
|
||||
bool cmp_read_bin_size(cmp_ctx_t *ctx, uint32_t *size);
|
||||
|
||||
/* Reads packed binary data from the backend */
|
||||
bool cmp_read_bin(cmp_ctx_t *ctx, void *data, uint32_t *size);
|
||||
|
||||
/* Reads an array from the backend */
|
||||
bool cmp_read_array(cmp_ctx_t *ctx, uint32_t *size);
|
||||
|
||||
/* Reads a map from the backend */
|
||||
bool cmp_read_map(cmp_ctx_t *ctx, uint32_t *size);
|
||||
|
||||
/* Reads the extended type's marker from the backend */
|
||||
bool cmp_read_ext_marker(cmp_ctx_t *ctx, int8_t *type, uint32_t *size);
|
||||
|
||||
/* Reads an extended type from the backend */
|
||||
bool cmp_read_ext(cmp_ctx_t *ctx, int8_t *type, uint32_t *size, void *data);
|
||||
|
||||
/* Reads an object from the backend */
|
||||
bool cmp_read_object(cmp_ctx_t *ctx, cmp_object_t *obj);
|
||||
|
||||
/*
|
||||
* Skips the next object from the backend. If that object is an array or map,
|
||||
* this function will:
|
||||
* - If `obj` is not `NULL`, fill in `obj` with that object
|
||||
* - Set `ctx->error` to `SKIP_DEPTH_LIMIT_EXCEEDED_ERROR`
|
||||
* - Return `false`
|
||||
* Otherwise:
|
||||
* - (Don't touch `obj`)
|
||||
* - Return `true`
|
||||
*/
|
||||
bool cmp_skip_object(cmp_ctx_t *ctx, cmp_object_t *obj);
|
||||
|
||||
/*
|
||||
* This is similar to `cmp_skip_object`, except it tolerates up to `limit`
|
||||
* levels of nesting. For example, in order to skip an array that contains a
|
||||
* map, call `cmp_skip_object_limit(ctx, &obj, 2)`. Or in other words,
|
||||
* `cmp_skip_object(ctx, &obj)` acts similarly to `cmp_skip_object_limit(ctx,
|
||||
* &obj, 0)`
|
||||
*
|
||||
* Specifically, `limit` refers to depth, not breadth. So in order to skip an
|
||||
* array that contains two arrays that each contain 3 strings, you would call
|
||||
* `cmp_skip_object_limit(ctx, &obj, 2). In order to skip an array that
|
||||
* contains 4 arrays that each contain 1 string, you would still call
|
||||
* `cmp_skip_object_limit(ctx, &obj, 2).
|
||||
*/
|
||||
bool cmp_skip_object_limit(cmp_ctx_t *ctx, cmp_object_t *obj, uint32_t limit);
|
||||
|
||||
/*
|
||||
* This is similar to `cmp_skip_object`, except it will continually skip
|
||||
* nested data structures.
|
||||
*
|
||||
* WARNING: This can cause your application to spend an unbounded amount of
|
||||
* time reading nested data structures. Unless you completely trust
|
||||
* the data source, you should strongly consider `cmp_skip_object` or
|
||||
* `cmp_skip_object_limit`.
|
||||
*/
|
||||
bool cmp_skip_object_no_limit(cmp_ctx_t *ctx);
|
||||
|
||||
/*
|
||||
* ============================================================================
|
||||
* === Specific API
|
||||
* ============================================================================
|
||||
*/
|
||||
|
||||
bool cmp_write_pfix(cmp_ctx_t *ctx, uint8_t c);
|
||||
bool cmp_write_nfix(cmp_ctx_t *ctx, int8_t c);
|
||||
|
||||
bool cmp_write_sfix(cmp_ctx_t *ctx, int8_t c);
|
||||
bool cmp_write_s8(cmp_ctx_t *ctx, int8_t c);
|
||||
bool cmp_write_s16(cmp_ctx_t *ctx, int16_t s);
|
||||
bool cmp_write_s32(cmp_ctx_t *ctx, int32_t i);
|
||||
bool cmp_write_s64(cmp_ctx_t *ctx, int64_t l);
|
||||
|
||||
bool cmp_write_ufix(cmp_ctx_t *ctx, uint8_t c);
|
||||
bool cmp_write_u8(cmp_ctx_t *ctx, uint8_t c);
|
||||
bool cmp_write_u16(cmp_ctx_t *ctx, uint16_t s);
|
||||
bool cmp_write_u32(cmp_ctx_t *ctx, uint32_t i);
|
||||
bool cmp_write_u64(cmp_ctx_t *ctx, uint64_t l);
|
||||
|
||||
bool cmp_write_float(cmp_ctx_t *ctx, float f);
|
||||
bool cmp_write_double(cmp_ctx_t *ctx, double d);
|
||||
|
||||
bool cmp_write_fixstr_marker(cmp_ctx_t *ctx, uint8_t size);
|
||||
bool cmp_write_fixstr(cmp_ctx_t *ctx, const char *data, uint8_t size);
|
||||
bool cmp_write_str8_marker(cmp_ctx_t *ctx, uint8_t size);
|
||||
bool cmp_write_str8(cmp_ctx_t *ctx, const char *data, uint8_t size);
|
||||
bool cmp_write_str16_marker(cmp_ctx_t *ctx, uint16_t size);
|
||||
bool cmp_write_str16(cmp_ctx_t *ctx, const char *data, uint16_t size);
|
||||
bool cmp_write_str32_marker(cmp_ctx_t *ctx, uint32_t size);
|
||||
bool cmp_write_str32(cmp_ctx_t *ctx, const char *data, uint32_t size);
|
||||
|
||||
bool cmp_write_bin8_marker(cmp_ctx_t *ctx, uint8_t size);
|
||||
bool cmp_write_bin8(cmp_ctx_t *ctx, const void *data, uint8_t size);
|
||||
bool cmp_write_bin16_marker(cmp_ctx_t *ctx, uint16_t size);
|
||||
bool cmp_write_bin16(cmp_ctx_t *ctx, const void *data, uint16_t size);
|
||||
bool cmp_write_bin32_marker(cmp_ctx_t *ctx, uint32_t size);
|
||||
bool cmp_write_bin32(cmp_ctx_t *ctx, const void *data, uint32_t size);
|
||||
|
||||
bool cmp_write_fixarray(cmp_ctx_t *ctx, uint8_t size);
|
||||
bool cmp_write_array16(cmp_ctx_t *ctx, uint16_t size);
|
||||
bool cmp_write_array32(cmp_ctx_t *ctx, uint32_t size);
|
||||
|
||||
bool cmp_write_fixmap(cmp_ctx_t *ctx, uint8_t size);
|
||||
bool cmp_write_map16(cmp_ctx_t *ctx, uint16_t size);
|
||||
bool cmp_write_map32(cmp_ctx_t *ctx, uint32_t size);
|
||||
|
||||
bool cmp_write_fixext1_marker(cmp_ctx_t *ctx, int8_t type);
|
||||
bool cmp_write_fixext1(cmp_ctx_t *ctx, int8_t type, const void *data);
|
||||
bool cmp_write_fixext2_marker(cmp_ctx_t *ctx, int8_t type);
|
||||
bool cmp_write_fixext2(cmp_ctx_t *ctx, int8_t type, const void *data);
|
||||
bool cmp_write_fixext4_marker(cmp_ctx_t *ctx, int8_t type);
|
||||
bool cmp_write_fixext4(cmp_ctx_t *ctx, int8_t type, const void *data);
|
||||
bool cmp_write_fixext8_marker(cmp_ctx_t *ctx, int8_t type);
|
||||
bool cmp_write_fixext8(cmp_ctx_t *ctx, int8_t type, const void *data);
|
||||
bool cmp_write_fixext16_marker(cmp_ctx_t *ctx, int8_t type);
|
||||
bool cmp_write_fixext16(cmp_ctx_t *ctx, int8_t type, const void *data);
|
||||
|
||||
bool cmp_write_ext8_marker(cmp_ctx_t *ctx, int8_t type, uint8_t size);
|
||||
bool cmp_write_ext8(cmp_ctx_t *ctx, int8_t type, uint8_t size,
|
||||
const void *data);
|
||||
bool cmp_write_ext16_marker(cmp_ctx_t *ctx, int8_t type, uint16_t size);
|
||||
bool cmp_write_ext16(cmp_ctx_t *ctx, int8_t type, uint16_t size,
|
||||
const void *data);
|
||||
bool cmp_write_ext32_marker(cmp_ctx_t *ctx, int8_t type, uint32_t size);
|
||||
bool cmp_write_ext32(cmp_ctx_t *ctx, int8_t type, uint32_t size,
|
||||
const void *data);
|
||||
|
||||
bool cmp_read_pfix(cmp_ctx_t *ctx, uint8_t *c);
|
||||
bool cmp_read_nfix(cmp_ctx_t *ctx, int8_t *c);
|
||||
|
||||
bool cmp_read_sfix(cmp_ctx_t *ctx, int8_t *c);
|
||||
bool cmp_read_s8(cmp_ctx_t *ctx, int8_t *c);
|
||||
bool cmp_read_s16(cmp_ctx_t *ctx, int16_t *s);
|
||||
bool cmp_read_s32(cmp_ctx_t *ctx, int32_t *i);
|
||||
bool cmp_read_s64(cmp_ctx_t *ctx, int64_t *l);
|
||||
|
||||
bool cmp_read_ufix(cmp_ctx_t *ctx, uint8_t *c);
|
||||
bool cmp_read_u8(cmp_ctx_t *ctx, uint8_t *c);
|
||||
bool cmp_read_u16(cmp_ctx_t *ctx, uint16_t *s);
|
||||
bool cmp_read_u32(cmp_ctx_t *ctx, uint32_t *i);
|
||||
bool cmp_read_u64(cmp_ctx_t *ctx, uint64_t *l);
|
||||
|
||||
bool cmp_read_float(cmp_ctx_t *ctx, float *f);
|
||||
bool cmp_read_double(cmp_ctx_t *ctx, double *d);
|
||||
|
||||
bool cmp_read_fixext1_marker(cmp_ctx_t *ctx, int8_t *type);
|
||||
bool cmp_read_fixext1(cmp_ctx_t *ctx, int8_t *type, void *data);
|
||||
bool cmp_read_fixext2_marker(cmp_ctx_t *ctx, int8_t *type);
|
||||
bool cmp_read_fixext2(cmp_ctx_t *ctx, int8_t *type, void *data);
|
||||
bool cmp_read_fixext4_marker(cmp_ctx_t *ctx, int8_t *type);
|
||||
bool cmp_read_fixext4(cmp_ctx_t *ctx, int8_t *type, void *data);
|
||||
bool cmp_read_fixext8_marker(cmp_ctx_t *ctx, int8_t *type);
|
||||
bool cmp_read_fixext8(cmp_ctx_t *ctx, int8_t *type, void *data);
|
||||
bool cmp_read_fixext16_marker(cmp_ctx_t *ctx, int8_t *type);
|
||||
bool cmp_read_fixext16(cmp_ctx_t *ctx, int8_t *type, void *data);
|
||||
|
||||
bool cmp_read_ext8_marker(cmp_ctx_t *ctx, int8_t *type, uint8_t *size);
|
||||
bool cmp_read_ext8(cmp_ctx_t *ctx, int8_t *type, uint8_t *size, void *data);
|
||||
bool cmp_read_ext16_marker(cmp_ctx_t *ctx, int8_t *type, uint16_t *size);
|
||||
bool cmp_read_ext16(cmp_ctx_t *ctx, int8_t *type, uint16_t *size, void *data);
|
||||
bool cmp_read_ext32_marker(cmp_ctx_t *ctx, int8_t *type, uint32_t *size);
|
||||
bool cmp_read_ext32(cmp_ctx_t *ctx, int8_t *type, uint32_t *size, void *data);
|
||||
|
||||
/*
|
||||
* ============================================================================
|
||||
* === Object API
|
||||
* ============================================================================
|
||||
*/
|
||||
|
||||
bool cmp_object_is_char(cmp_object_t *obj);
|
||||
bool cmp_object_is_short(cmp_object_t *obj);
|
||||
bool cmp_object_is_int(cmp_object_t *obj);
|
||||
bool cmp_object_is_long(cmp_object_t *obj);
|
||||
bool cmp_object_is_sinteger(cmp_object_t *obj);
|
||||
bool cmp_object_is_uchar(cmp_object_t *obj);
|
||||
bool cmp_object_is_ushort(cmp_object_t *obj);
|
||||
bool cmp_object_is_uint(cmp_object_t *obj);
|
||||
bool cmp_object_is_ulong(cmp_object_t *obj);
|
||||
bool cmp_object_is_uinteger(cmp_object_t *obj);
|
||||
bool cmp_object_is_float(cmp_object_t *obj);
|
||||
bool cmp_object_is_double(cmp_object_t *obj);
|
||||
bool cmp_object_is_nil(cmp_object_t *obj);
|
||||
bool cmp_object_is_bool(cmp_object_t *obj);
|
||||
bool cmp_object_is_str(cmp_object_t *obj);
|
||||
bool cmp_object_is_bin(cmp_object_t *obj);
|
||||
bool cmp_object_is_array(cmp_object_t *obj);
|
||||
bool cmp_object_is_map(cmp_object_t *obj);
|
||||
bool cmp_object_is_ext(cmp_object_t *obj);
|
||||
|
||||
bool cmp_object_as_char(cmp_object_t *obj, int8_t *c);
|
||||
bool cmp_object_as_short(cmp_object_t *obj, int16_t *s);
|
||||
bool cmp_object_as_int(cmp_object_t *obj, int32_t *i);
|
||||
bool cmp_object_as_long(cmp_object_t *obj, int64_t *d);
|
||||
bool cmp_object_as_sinteger(cmp_object_t *obj, int64_t *d);
|
||||
bool cmp_object_as_uchar(cmp_object_t *obj, uint8_t *c);
|
||||
bool cmp_object_as_ushort(cmp_object_t *obj, uint16_t *s);
|
||||
bool cmp_object_as_uint(cmp_object_t *obj, uint32_t *i);
|
||||
bool cmp_object_as_ulong(cmp_object_t *obj, uint64_t *u);
|
||||
bool cmp_object_as_uinteger(cmp_object_t *obj, uint64_t *u);
|
||||
bool cmp_object_as_float(cmp_object_t *obj, float *f);
|
||||
bool cmp_object_as_double(cmp_object_t *obj, double *d);
|
||||
bool cmp_object_as_bool(cmp_object_t *obj, bool *b);
|
||||
bool cmp_object_as_str(cmp_object_t *obj, uint32_t *size);
|
||||
bool cmp_object_as_bin(cmp_object_t *obj, uint32_t *size);
|
||||
bool cmp_object_as_array(cmp_object_t *obj, uint32_t *size);
|
||||
bool cmp_object_as_map(cmp_object_t *obj, uint32_t *size);
|
||||
bool cmp_object_as_ext(cmp_object_t *obj, int8_t *type, uint32_t *size);
|
||||
|
||||
bool cmp_object_to_str(cmp_ctx_t *ctx, cmp_object_t *obj, char *data, uint32_t buf_size);
|
||||
bool cmp_object_to_bin(cmp_ctx_t *ctx, cmp_object_t *obj, void *data, uint32_t buf_size);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
/*
|
||||
* ============================================================================
|
||||
* === Backwards compatibility defines
|
||||
* ============================================================================
|
||||
*/
|
||||
|
||||
#define cmp_write_int cmp_write_integer
|
||||
#define cmp_write_sint cmp_write_integer
|
||||
#define cmp_write_sinteger cmp_write_integer
|
||||
#define cmp_write_uint cmp_write_uinteger
|
||||
#define cmp_read_sinteger cmp_read_integer
|
||||
|
||||
#endif /* CMP_H__ */
|
||||
|
||||
/* vi: set et ts=2 sw=2: */
|
||||
|
278
gateway.c
278
gateway.c
|
@ -36,6 +36,7 @@
|
|||
#include "config.h"
|
||||
#include "gui.h"
|
||||
#include "listener.h"
|
||||
#include "habpack.h"
|
||||
#include "udpclient.h"
|
||||
|
||||
#define VERSION "V1.8.19"
|
||||
|
@ -173,7 +174,7 @@ int help_win_displayed = 0;
|
|||
|
||||
pthread_mutex_t var = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
#pragma pack(1)
|
||||
#pragma pack(push,1)
|
||||
|
||||
struct TBinaryPacket {
|
||||
uint8_t PayloadIDs;
|
||||
|
@ -184,6 +185,8 @@ struct TBinaryPacket {
|
|||
uint16_t Altitude;
|
||||
};
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
// Create pipes for inter proces communication
|
||||
// GLOBAL AS CALLED FROM INTERRRUPT
|
||||
int telem_pipe_fd[2];
|
||||
|
@ -746,6 +749,54 @@ void ProcessCallingMessage(int Channel, char *Message)
|
|||
}
|
||||
}
|
||||
|
||||
void ProcessCallingHABpack(int Channel, received_t *Received)
|
||||
{
|
||||
double Frequency;
|
||||
|
||||
ChannelPrintf( Channel, 3, 1, "Calling message (HABpack)");
|
||||
|
||||
Frequency = (double)Received->Telemetry.DownlinkFrequency / 1000000;
|
||||
|
||||
if (Config.LoRaDevices[Channel].AFC)
|
||||
{
|
||||
Frequency += (Config.LoRaDevices[Channel].activeFreq - Config.LoRaDevices[Channel].Frequency);
|
||||
}
|
||||
|
||||
// Decoded OK
|
||||
setMode( Channel, RF98_MODE_SLEEP );
|
||||
|
||||
setFrequency( Channel, Frequency );
|
||||
|
||||
if(Received->Telemetry.DownlinkLoraMode >= 0)
|
||||
{
|
||||
|
||||
SetLoRaParameters(Channel,
|
||||
LoRaModes[Received->Telemetry.DownlinkLoraMode].ImplicitOrExplicit,
|
||||
ECToInt(LoRaModes[Received->Telemetry.DownlinkLoraMode].ErrorCoding),
|
||||
BandwidthToDouble(LoRaModes[Received->Telemetry.DownlinkLoraMode].Bandwidth),
|
||||
SFToInt(LoRaModes[Received->Telemetry.DownlinkLoraMode].SpreadingFactor),
|
||||
LowOptToInt(LoRaModes[Received->Telemetry.DownlinkLoraMode].LowDataRateOptimize)
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
SetLoRaParameters(Channel,
|
||||
Received->Telemetry.DownlinkLoraImplicit,
|
||||
Received->Telemetry.DownlinkLoraErrorCoding,
|
||||
Received->Telemetry.DownlinkLoraBandwidth,
|
||||
Received->Telemetry.DownlinkLoraSpreadingFactor,
|
||||
Received->Telemetry.DownlinkLoraLowDatarateOptimise
|
||||
);
|
||||
}
|
||||
|
||||
setMode( Channel, RF98_MODE_RX_CONTINUOUS );
|
||||
|
||||
LogMessage( "Ch %d: Calling message, new frequency %7.3lf\n", Channel,
|
||||
Frequency );
|
||||
|
||||
Config.LoRaDevices[Channel].InCallingMode = 1;
|
||||
}
|
||||
|
||||
void RemoveOldPayloads(void)
|
||||
{
|
||||
int i;
|
||||
|
@ -831,23 +882,23 @@ void DoPositionCalcs(int PayloadIndex)
|
|||
Config.Payloads[PayloadIndex].PreviousAltitude = Config.Payloads[PayloadIndex].Altitude;
|
||||
}
|
||||
|
||||
void ProcessLine(int Channel, char *Line)
|
||||
void ProcessLineUKHAS(int Channel, char *Line)
|
||||
{
|
||||
int PayloadIndex;
|
||||
char Payload[32], OziSentence[200];
|
||||
char Payload[32];
|
||||
|
||||
// Find free position for this payload
|
||||
sscanf(Line + 2, "%31[^,]", Payload);
|
||||
PayloadIndex = FindFreePayload(Payload);
|
||||
// Find free position for this payload
|
||||
sscanf(Line + 2, "%31[^,]", Payload);
|
||||
PayloadIndex = FindFreePayload(Payload);
|
||||
|
||||
// Store sentence against this payload
|
||||
// Store sentence against this payload
|
||||
strcpy(Config.Payloads[PayloadIndex].Telemetry, Line);
|
||||
|
||||
// Fill in source channel
|
||||
Config.Payloads[PayloadIndex].Channel = Channel;
|
||||
|
||||
// Parse key fields from sentence
|
||||
sscanf( Line + 2, "%15[^,],%u,%8[^,],%lf,%lf,%u",
|
||||
sscanf( Line + 2, "%15[^,],%u,%8[^,],%lf,%lf,%d",
|
||||
(Config.Payloads[PayloadIndex].Payload),
|
||||
&(Config.Payloads[PayloadIndex].Counter),
|
||||
(Config.Payloads[PayloadIndex].Time),
|
||||
|
@ -863,41 +914,89 @@ void ProcessLine(int Channel, char *Line)
|
|||
|
||||
// Ascent rate
|
||||
DoPositionCalcs(PayloadIndex);
|
||||
|
||||
// Update display
|
||||
ChannelPrintf(Channel, 4, 1, "%8.5lf, %8.5lf, %05u ",
|
||||
|
||||
// Update display
|
||||
ChannelPrintf(Channel, 4, 1, "%8.5lf, %8.5lf, %05d ",
|
||||
Config.Payloads[PayloadIndex].Latitude,
|
||||
Config.Payloads[PayloadIndex].Longitude,
|
||||
Config.Payloads[PayloadIndex].Altitude);
|
||||
|
||||
// Send out to any OziMux clients
|
||||
if (Config.OziPort > 0)
|
||||
{
|
||||
sprintf(OziSentence, "TELEMETRY,%s,%lf,%lf,%u\n",
|
||||
Config.Payloads[PayloadIndex].Time,
|
||||
Config.Payloads[PayloadIndex].Latitude,
|
||||
Config.Payloads[PayloadIndex].Longitude,
|
||||
Config.Payloads[PayloadIndex].Altitude);
|
||||
UDPSend(OziSentence, Config.OziPort);
|
||||
}
|
||||
Config.Payloads[PayloadIndex].Altitude);
|
||||
|
||||
// Send out to any OziMux clients
|
||||
if (Config.OziPort > 0)
|
||||
{
|
||||
char OziSentence[200];
|
||||
sprintf(OziSentence, "TELEMETRY,%s,%lf,%lf,%d\n",
|
||||
Config.Payloads[PayloadIndex].Time,
|
||||
Config.Payloads[PayloadIndex].Latitude,
|
||||
Config.Payloads[PayloadIndex].Longitude,
|
||||
Config.Payloads[PayloadIndex].Altitude);
|
||||
UDPSend(OziSentence, Config.OziPort);
|
||||
}
|
||||
}
|
||||
|
||||
void ProcessLineHABpack(int Channel, received_t *Received)
|
||||
{
|
||||
int PayloadIndex;
|
||||
|
||||
PayloadIndex = FindFreePayload(Received->Telemetry.Callsign);
|
||||
|
||||
// Store sentence against this payload
|
||||
strcpy(Config.Payloads[PayloadIndex].Telemetry, Received->UKHASstring);
|
||||
|
||||
// Fill in source channel
|
||||
Config.Payloads[PayloadIndex].Channel = Channel;
|
||||
|
||||
strncpy(Config.Payloads[PayloadIndex].Payload, Received->Telemetry.Callsign, 15);
|
||||
Config.Payloads[PayloadIndex].Counter = Received->Telemetry.SentenceId;
|
||||
strncpy(Config.Payloads[PayloadIndex].Time, Received->Telemetry.TimeString, 8);
|
||||
Config.Payloads[PayloadIndex].Latitude = Received->Telemetry.Latitude;
|
||||
Config.Payloads[PayloadIndex].Longitude = Received->Telemetry.Longitude;
|
||||
Config.Payloads[PayloadIndex].Altitude = Received->Telemetry.Altitude;
|
||||
|
||||
// Mark when this was received, so we can time-out old payloads
|
||||
Config.Payloads[PayloadIndex].LastPacketAt = time(NULL);
|
||||
|
||||
// Mark for server socket to send to client
|
||||
Config.Payloads[PayloadIndex].SendToClients = 1;
|
||||
|
||||
// Ascent rate
|
||||
DoPositionCalcs(PayloadIndex);
|
||||
|
||||
// Update display
|
||||
ChannelPrintf(Channel, 4, 1, "%8.5lf, %8.5lf, %05d ",
|
||||
Config.Payloads[PayloadIndex].Latitude,
|
||||
Config.Payloads[PayloadIndex].Longitude,
|
||||
Config.Payloads[PayloadIndex].Altitude);
|
||||
|
||||
// Send out to any OziMux clients
|
||||
if (Config.OziPort > 0)
|
||||
{
|
||||
char OziSentence[200];
|
||||
sprintf(OziSentence, "TELEMETRY,%s,%lf,%lf,%d\n",
|
||||
Config.Payloads[PayloadIndex].Time,
|
||||
Config.Payloads[PayloadIndex].Latitude,
|
||||
Config.Payloads[PayloadIndex].Longitude,
|
||||
Config.Payloads[PayloadIndex].Altitude);
|
||||
UDPSend(OziSentence, Config.OziPort);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ProcessTelemetryMessage(int Channel, char *Message, rx_metadata_t *Metadata)
|
||||
void ProcessTelemetryMessage(int Channel, received_t *Received)
|
||||
{
|
||||
if (strlen(Message + 1) < 250)
|
||||
if (strlen(Received->UKHASstring) < 250)
|
||||
{
|
||||
char *startmessage, *endmessage;
|
||||
char telem[40];
|
||||
char buffer[40];
|
||||
|
||||
sprintf(telem, "Telemetry %d bytes", strlen( Message + 1 ));
|
||||
sprintf(telem, "Telemetry %d bytes", strlen( Received->UKHASstring ));
|
||||
|
||||
// Pad the string with spaces to the size of the window
|
||||
sprintf(buffer,"%-37s", telem );
|
||||
ChannelPrintf( Channel, 3, 1, buffer);
|
||||
|
||||
startmessage = Message + strspn(Message, "$%") - 2;
|
||||
startmessage = Received->UKHASstring + strspn(Received->UKHASstring, "$%") - 2;
|
||||
endmessage = strchr( startmessage, '\n' );
|
||||
if (endmessage == NULL) endmessage = strchr(startmessage, 0);
|
||||
|
||||
|
@ -916,22 +1015,12 @@ void ProcessTelemetryMessage(int Channel, char *Message, rx_metadata_t *Metadata
|
|||
}
|
||||
|
||||
strcpy( Config.LoRaDevices[Channel].Telemetry, startmessage );
|
||||
|
||||
ProcessLine(Channel, startmessage);
|
||||
|
||||
tm = localtime( &Metadata->Timestamp );
|
||||
|
||||
Config.LoRaDevices[Channel].TelemetryCount++;
|
||||
|
||||
if ( Config.EnableHabitat )
|
||||
{
|
||||
|
||||
// Create a telemetry packet
|
||||
telemetry_t t;
|
||||
memcpy( t.Telemetry, startmessage, strlen( startmessage ) + 1 );
|
||||
memcpy( &t.Metadata, Metadata, sizeof( rx_metadata_t ) );
|
||||
|
||||
// Add the telemetry packet to the pipe
|
||||
int result = write( telem_pipe_fd[1], &t, sizeof( t ) );
|
||||
int result = write( telem_pipe_fd[1], Received, sizeof( *Received ) );
|
||||
if ( result == -1 )
|
||||
{
|
||||
exit_error("Error writing to the telemetry pipe\n");
|
||||
|
@ -945,16 +1034,15 @@ void ProcessTelemetryMessage(int Channel, char *Message, rx_metadata_t *Metadata
|
|||
htsv.packet_count++;
|
||||
}
|
||||
}
|
||||
|
||||
Config.LoRaDevices[Channel].TelemetryCount++;
|
||||
|
||||
tm = localtime( &Received->Metadata.Timestamp );
|
||||
LogMessage("%02d:%02d:%02d Ch%d: %s%s\n", tm->tm_hour, tm->tm_min, tm->tm_sec, Channel, startmessage, Repeated ? " (repeated)" : "");
|
||||
|
||||
startmessage = endmessage + 1;
|
||||
endmessage = strchr( startmessage, '\n' );
|
||||
}
|
||||
|
||||
Config.LoRaDevices[Channel].LastTelemetryPacketAt = Metadata->Timestamp;
|
||||
Config.LoRaDevices[Channel].LastTelemetryPacketAt = Received->Metadata.Timestamp;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1015,9 +1103,10 @@ FileExists( char *filename )
|
|||
return stat( filename, &st ) == 0;
|
||||
}
|
||||
|
||||
void ProcessSSDVMessage( int Channel, char *Message, int Repeated)
|
||||
void ProcessSSDVMessage( int Channel, char *Message_in, int Repeated)
|
||||
{
|
||||
// SSDV packet
|
||||
char Message[257];
|
||||
uint32_t CallsignCode;
|
||||
char Callsign[7], *FileMode;
|
||||
int ImageNumber, PacketNumber;
|
||||
|
@ -1029,6 +1118,9 @@ void ProcessSSDVMessage( int Channel, char *Message, int Repeated)
|
|||
now = time( 0 );
|
||||
tm = localtime( &now );
|
||||
|
||||
// Move into new buffer with preceding char
|
||||
memcpy((Message + 1), Message_in, 256);
|
||||
|
||||
Message[0] = 0x55;
|
||||
|
||||
CallsignCode = Message[2];
|
||||
|
@ -1220,17 +1312,14 @@ void DIO0_Interrupt( int Channel )
|
|||
}
|
||||
else
|
||||
{
|
||||
int Bytes;
|
||||
char Message[257];
|
||||
rx_metadata_t Metadata;
|
||||
received_t Received = { .Telemetry = { .habpack_extra = NULL } };
|
||||
|
||||
Metadata.Channel = Channel;
|
||||
|
||||
Bytes = receiveMessage( Channel, Message + 1, &Metadata );
|
||||
Received.Metadata.Channel = Channel;
|
||||
Received.Bytes = receiveMessage( Channel, Received.Message, &Received.Metadata );
|
||||
|
||||
Config.LoRaDevices[Channel].GotReply = 1;
|
||||
|
||||
if ( Bytes > 0 )
|
||||
if ( Received.Bytes > 0 )
|
||||
{
|
||||
if ( Config.LoRaDevices[Channel].ActivityLED >= 0 )
|
||||
{
|
||||
|
@ -1238,60 +1327,63 @@ void DIO0_Interrupt( int Channel )
|
|||
LEDCounts[Channel] = 5;
|
||||
}
|
||||
|
||||
if ( Message[1] == '!' )
|
||||
if ( Received.Message[0] == '!' )
|
||||
{
|
||||
ProcessUploadMessage( Channel, Message + 1 );
|
||||
ProcessUploadMessage( Channel, Received.Message);
|
||||
}
|
||||
else if ( Message[1] == '^' )
|
||||
else if ( Received.Message[0] == '^' )
|
||||
{
|
||||
ProcessCallingMessage( Channel, Message + 1 );
|
||||
ProcessCallingMessage( Channel, Received.Message);
|
||||
}
|
||||
else if ((Message[1] == '$') || (Message[1] == '%'))
|
||||
else if ((Received.Message[0] == '$') || (Received.Message[0] == '%'))
|
||||
{
|
||||
ProcessTelemetryMessage(Channel, Message + 1, &Metadata);
|
||||
TestMessageForSMSAcknowledgement( Channel, Message + 1);
|
||||
strcpy(Config.LoRaDevices[Channel].LocalDataBuffer, Message+1);
|
||||
/* RTTY */
|
||||
strncpy(Received.UKHASstring, Received.Message, Received.Bytes);
|
||||
ProcessTelemetryMessage(Channel, &Received);
|
||||
ProcessLineUKHAS(Channel, Config.LoRaDevices[Channel].Telemetry);
|
||||
TestMessageForSMSAcknowledgement( Channel, Received.UKHASstring);
|
||||
strcpy(Config.LoRaDevices[Channel].LocalDataBuffer, Received.UKHASstring);
|
||||
strcat(Config.LoRaDevices[Channel].LocalDataBuffer, "\r\n");
|
||||
Config.LoRaDevices[Channel].LocalDataCount = Bytes+1;
|
||||
UDPSend(Message + 1, Config.UDPPort);
|
||||
Config.LoRaDevices[Channel].LocalDataCount = Received.Bytes;
|
||||
UDPSend(Received.UKHASstring, Config.UDPPort);
|
||||
}
|
||||
else if ( Message[1] == '>' )
|
||||
else if ( Received.Message[0] == '>' )
|
||||
{
|
||||
LogMessage( "Flight Controller message %d bytes = %s\n", Bytes, Message + 1 );
|
||||
LogMessage( "Flight Controller message %d bytes = %s\n", Received.Bytes, Received.Message );
|
||||
}
|
||||
else if ( Message[1] == '<' )
|
||||
else if ( Received.Message[0] == '<' )
|
||||
{
|
||||
LogMessage("Local Data %d bytes = %s", Bytes, Message+1);
|
||||
strcpy(Config.LoRaDevices[Channel].LocalDataBuffer, Message+1);
|
||||
LogMessage("Local Data %d bytes = %s", Received.Bytes, Received.Message);
|
||||
strcpy(Config.LoRaDevices[Channel].LocalDataBuffer, Received.Message);
|
||||
strcat(Config.LoRaDevices[Channel].LocalDataBuffer, "\r\n");
|
||||
Config.LoRaDevices[Channel].LocalDataCount = Bytes+1;
|
||||
Config.LoRaDevices[Channel].LocalDataCount = Received.Bytes;
|
||||
}
|
||||
else if ( Message[1] == '*' )
|
||||
else if ( Received.Message[0] == '*' )
|
||||
{
|
||||
LogMessage( "Uplink Command message %d bytes = %s\n", Bytes, Message + 1 );
|
||||
LogMessage( "Uplink Command message %d bytes = %s\n", Received.Bytes, Received.Message );
|
||||
}
|
||||
else if (Message[1] == '+')
|
||||
else if ( Received.Message[0] == '+')
|
||||
{
|
||||
LogMessage( "Telnet Uplink message %d packet ID %d bytes = '%s'\n", Bytes, Message[2], Message + 3);
|
||||
LogMessage( "Telnet Uplink message %d packet ID %d bytes = '%s'\n", Received.Bytes, Received.Message[1], Received.Message + 2);
|
||||
}
|
||||
else if ( Message[1] == '-' )
|
||||
else if ( Received.Message[0] == '-' )
|
||||
{
|
||||
ProcessTelnetMessage(Channel, Message+1, Bytes);
|
||||
ProcessTelnetMessage(Channel, Received.Message, Received.Bytes);
|
||||
}
|
||||
else if (((Message[1] & 0x7F) == 0x66) || // SSDV JPG format
|
||||
((Message[1] & 0x7F) == 0x67) || // SSDV other formats
|
||||
((Message[1] & 0x7F) == 0x68) ||
|
||||
((Message[1] & 0x7F) == 0x69))
|
||||
else if (((Received.Message[0] & 0x7F) == 0x66) || // SSDV JPG format
|
||||
((Received.Message[0] & 0x7F) == 0x67) || // SSDV other formats
|
||||
((Received.Message[0] & 0x7F) == 0x68) ||
|
||||
((Received.Message[0] & 0x7F) == 0x69))
|
||||
{
|
||||
int Repeated;
|
||||
|
||||
// Handle repeater bit
|
||||
Repeated = Message[1] & 0x80;
|
||||
Message[1] &= 0x7F;
|
||||
Repeated = Received.Message[0] & 0x80;
|
||||
Received.Message[0] &= 0x7F;
|
||||
|
||||
ProcessSSDVMessage( Channel, Message, Repeated);
|
||||
ProcessSSDVMessage( Channel, Received.Message, Repeated);
|
||||
}
|
||||
else if ( Message[1] == 0x00)
|
||||
else if ( Received.Message[0] == 0x00)
|
||||
{
|
||||
time_t now;
|
||||
struct tm *tm;
|
||||
|
@ -1301,10 +1393,25 @@ void DIO0_Interrupt( int Channel )
|
|||
|
||||
LogMessage("%02d:%02d:%02d Ch%d: Null uplink packet\n", tm->tm_hour, tm->tm_min, tm->tm_sec, Channel);
|
||||
}
|
||||
else if ( ((Received.Message[0] & 0xF0) == 0x80) || (Received.Message[0] == 0xde))
|
||||
{
|
||||
/* HABpack Binary Message - https://ukhas.org.uk/communication:habpack */
|
||||
Habpack_Process_Message(&Received);
|
||||
if(Received.isCallingBeacon == false)
|
||||
{
|
||||
ProcessTelemetryMessage(Channel, &Received);
|
||||
ProcessLineHABpack(Channel, &Received);
|
||||
TestMessageForSMSAcknowledgement(Channel, Received.UKHASstring);
|
||||
}
|
||||
else
|
||||
{
|
||||
ProcessCallingHABpack(Channel, &Received);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LogMessage("Unknown packet type is %02Xh, RSSI %d\n", Message[1], PacketRSSI(Channel));
|
||||
ChannelPrintf( Channel, 3, 1, "Unknown Packet %d, %d bytes", Message[0], Bytes);
|
||||
LogMessage("Unknown packet type is %02Xh, RSSI %d\n", Received.Message[0], PacketRSSI(Channel));
|
||||
ChannelPrintf( Channel, 3, 1, "Unknown Packet %d, %d bytes", Received.Message[0], Received.Bytes);
|
||||
Config.LoRaDevices[Channel].UnknownCount++;
|
||||
}
|
||||
|
||||
|
@ -1322,6 +1429,8 @@ void DIO0_Interrupt( int Channel )
|
|||
|
||||
ShowPacketCounts( Channel );
|
||||
}
|
||||
/* Free habpack linked list */
|
||||
Habpack_Telem_Destroy(&Received);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1783,7 +1892,7 @@ WINDOW *InitDisplay(void)
|
|||
|
||||
char buffer[80];
|
||||
|
||||
sprintf( buffer, "LoRa Habitat and SSDV Gateway by M0RPI, M0RJX - " VERSION);
|
||||
sprintf( buffer, "LoRa Habitat and SSDV Gateway by M0RPI, M0DNY, M0RJX - " VERSION);
|
||||
|
||||
// Title bar
|
||||
mvaddstr( 0, ( 80 - strlen( buffer ) ) / 2, buffer );
|
||||
|
@ -2496,5 +2605,4 @@ int main( int argc, char **argv )
|
|||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
}
|
210
global.h
210
global.h
|
@ -1,39 +1,46 @@
|
|||
#ifndef _H_Global
|
||||
#define _H_Global
|
||||
|
||||
#include <curses.h>
|
||||
|
||||
#include <curses.h>
|
||||
|
||||
#define RUNNING 1 // The main program is running
|
||||
#define STOPPED 0 // The main program has stopped
|
||||
|
||||
#define MAX_PAYLOADS 32
|
||||
|
||||
struct TPayload
|
||||
{
|
||||
|
||||
#define MAX_PAYLOADS 32
|
||||
|
||||
struct TPayload
|
||||
{
|
||||
int InUse;
|
||||
int SendToClients;
|
||||
int Channel;
|
||||
|
||||
time_t LastPacketAt;
|
||||
|
||||
char Telemetry[256];
|
||||
char Payload[32];
|
||||
|
||||
char Time[12];
|
||||
unsigned int Counter, LastCounter;
|
||||
double Longitude, Latitude;
|
||||
unsigned int Altitude, PreviousAltitude;
|
||||
float AscentRate;
|
||||
unsigned long LastPositionAt;
|
||||
};
struct TLoRaDevice
{
|
||||
double Frequency;
|
||||
double Bandwidth;
|
||||
double CurrentBandwidth;
|
||||
int InUse;
int DIO0;
int DIO5;
double activeFreq;
|
||||
int SendToClients;
|
||||
int Channel;
|
||||
|
||||
int AFC; // Enable Automatic Frequency Control
|
||||
double MaxAFCStep; // Maximum adjustment, in kHz, per packet
|
||||
int AFCTimeout; // Revert to original frequency if no packets for this period (in seconds)
|
||||
time_t LastPacketAt;
|
||||
|
||||
char Telemetry[256];
|
||||
char Payload[32];
|
||||
|
||||
char Time[12];
|
||||
unsigned int Counter, LastCounter;
|
||||
double Longitude, Latitude;
|
||||
int Altitude, PreviousAltitude;
|
||||
float AscentRate;
|
||||
unsigned long LastPositionAt;
|
||||
};
|
||||
|
||||
struct TLoRaDevice
|
||||
{
|
||||
double Frequency;
|
||||
double Bandwidth;
|
||||
double CurrentBandwidth;
|
||||
|
||||
int InUse;
|
||||
int DIO0;
|
||||
int DIO5;
|
||||
double activeFreq;
|
||||
|
||||
int AFC; // Enable Automatic Frequency Control
|
||||
double MaxAFCStep; // Maximum adjustment, in kHz, per packet
|
||||
int AFCTimeout; // Revert to original frequency if no packets for this period (in seconds)
|
||||
|
||||
int SpeedMode;
|
||||
int Power;
|
||||
|
@ -50,33 +57,33 @@ struct TPayload
|
|||
// unsigned int Satellites;
|
||||
time_t LastSSDVPacketAt, LastTelemetryPacketAt;
|
||||
time_t ReturnToCallingModeAt;
|
||||
time_t ReturnToOriginalFrequencyAt;
|
||||
time_t ReturnToOriginalFrequencyAt;
|
||||
int InCallingMode;
|
||||
int ActivityLED;
|
||||
double UplinkFrequency;
|
||||
int ActivityLED;
|
||||
double UplinkFrequency;
|
||||
int UplinkMode;
|
||||
|
||||
// Normal (non TDM) uplink
|
||||
|
||||
// Normal (non TDM) uplink
|
||||
int UplinkTime;
|
||||
int UplinkCycle;
|
||||
int IdleUplink;
|
||||
int SSDVUplink;
|
||||
char UplinkMessage[256];
|
||||
|
||||
// Telnet uplink
|
||||
char Telemetry[256];
|
||||
unsigned char PacketID;
|
||||
int TimeSinceLastTx;
|
||||
int HABAck; // Received message ACKd our last Tx
|
||||
int HABConnected; // 1 if HAB has telnet connection
|
||||
char ToTelnetBuffer[256]; // Buffer for data Telnet --> LoRa
|
||||
int ToTelnetBufferCount;
|
||||
char FromTelnetBuffer[256]; // Buffer for data LoRa --> Telnet
|
||||
int FromTelnetBufferCount;
|
||||
char HABUplink[256];
|
||||
int HABUplinkCount;
|
||||
int GotHABReply;
|
||||
int GotReply;
|
||||
int UplinkCycle;
|
||||
int IdleUplink;
|
||||
int SSDVUplink;
|
||||
char UplinkMessage[256];
|
||||
|
||||
// Telnet uplink
|
||||
char Telemetry[256];
|
||||
unsigned char PacketID;
|
||||
int TimeSinceLastTx;
|
||||
int HABAck; // Received message ACKd our last Tx
|
||||
int HABConnected; // 1 if HAB has telnet connection
|
||||
char ToTelnetBuffer[256]; // Buffer for data Telnet --> LoRa
|
||||
int ToTelnetBufferCount;
|
||||
char FromTelnetBuffer[256]; // Buffer for data LoRa --> Telnet
|
||||
int FromTelnetBufferCount;
|
||||
char HABUplink[256];
|
||||
int HABUplinkCount;
|
||||
int GotHABReply;
|
||||
int GotReply;
|
||||
|
||||
// Local data packets
|
||||
int LocalDataCount;
|
||||
|
@ -87,9 +94,13 @@ struct TPayload
|
|||
int PacketSNR, PacketRSSI;
|
||||
double FrequencyError;
|
||||
};
|
||||
struct TConfig
{
char Tracker[16]; // Callsign or name of receiver
|
||||
double latitude, longitude; // Receiver's location
|
||||
int EnableHabitat;
|
||||
|
||||
struct TConfig
|
||||
{
|
||||
char Tracker[16]; // Callsign or name of receiver
|
||||
double latitude, longitude; // Receiver's location
|
||||
|
||||
int EnableHabitat;
|
||||
int EnableSSDV;
|
||||
int EnableTelemetryLogging;
|
||||
int EnablePacketLogging;
|
||||
|
@ -99,23 +110,24 @@ struct TPayload
|
|||
char ftpUser[32];
|
||||
char ftpPassword[32];
|
||||
char ftpFolder[64];
|
||||
struct TLoRaDevice LoRaDevices[2];
|
||||
struct TLoRaDevice LoRaDevices[2];
|
||||
struct TPayload Payloads[MAX_PAYLOADS];
|
||||
int NetworkLED;
|
||||
int InternetLED;
|
||||
int ServerPort; // JSON port for telemetry, settings
|
||||
int UDPPort; // UDP Broadcast port for raw received data packets
|
||||
int OziPort; // UDP Broadcast port for OziMux formatted packets
|
||||
int HABPort; // Telnet style port for comms with HAB
|
||||
int HABTimeout; // Timeout in ms for telnet uplink
|
||||
int HABChannel; // LoRa Channel for uplink
|
||||
int OziPort; // UDP Broadcast port for OziMux formatted packets
|
||||
int HABPort; // Telnet style port for comms with HAB
|
||||
int HABTimeout; // Timeout in ms for telnet uplink
|
||||
int HABChannel; // LoRa Channel for uplink
|
||||
int DataPort; // Raw received data packet port
|
||||
char SMSFolder[64];
|
||||
char antenna[64];
|
||||
int EnableDev;
|
||||
char UplinkCode[64];
|
||||
int EnableDev;
|
||||
char UplinkCode[64];
|
||||
};
|
||||
typedef struct {
|
||||
|
||||
typedef struct {
|
||||
int parent_status;
|
||||
unsigned long packet_count;
|
||||
} thread_shared_vars_t;
|
||||
|
@ -135,28 +147,72 @@ typedef struct {
|
|||
int RSSI;
|
||||
} rx_metadata_t;
|
||||
|
||||
/* HABpack Telemetry Storage */
|
||||
typedef enum { HB_VALUE_INTEGER, HB_VALUE_REAL } HB_Value_Type;
|
||||
typedef struct habpack_telem_linklist_entry {
|
||||
uint32_t type;
|
||||
char name[32];
|
||||
HB_Value_Type value_type;
|
||||
union {
|
||||
int64_t integer;
|
||||
double real;
|
||||
} value;
|
||||
struct habpack_telem_linklist_entry *next;
|
||||
} habpack_telem_linklist_entry_t;
|
||||
|
||||
typedef struct {
|
||||
char Telemetry[257];
|
||||
/* Core Telemetry */
|
||||
char Callsign[32];
|
||||
uint64_t SentenceId;
|
||||
uint64_t Time;
|
||||
char TimeString[9];
|
||||
double Latitude;
|
||||
double Longitude;
|
||||
int64_t Altitude;
|
||||
/* Calling Beacon Values */
|
||||
uint64_t DownlinkFrequency;
|
||||
int64_t DownlinkLoraMode;
|
||||
int DownlinkLoraImplicit;
|
||||
int DownlinkLoraErrorCoding;
|
||||
double DownlinkLoraBandwidth;
|
||||
int DownlinkLoraSpreadingFactor;
|
||||
int DownlinkLoraLowDatarateOptimise;
|
||||
/* Linked list of additional telem fields */
|
||||
habpack_telem_linklist_entry_t *habpack_extra;
|
||||
} rx_telemetry_t;
|
||||
|
||||
#define Message_length 257
|
||||
#define UKHASstring_length 257
|
||||
typedef struct {
|
||||
char Message[Message_length];
|
||||
int Bytes;
|
||||
/* UKHAS ASCII Telemetry String for habitat upload */
|
||||
char UKHASstring[UKHASstring_length];
|
||||
bool isCallingBeacon;
|
||||
double AscentRate;
|
||||
/* Telemetry values */
|
||||
rx_telemetry_t Telemetry;
|
||||
rx_metadata_t Metadata;
|
||||
} telemetry_t;
|
||||
} received_t;
|
||||
|
||||
typedef struct {
|
||||
short int Channel;
|
||||
char SSDV_Packet[257];
|
||||
int Packet_Number;
|
||||
} ssdv_t;
|
||||
|
||||
struct TServerInfo
|
||||
{
|
||||
int Port;
|
||||
int Connected;
|
||||
int ServerIndex;
|
||||
int sockfd;
|
||||
};
|
||||
|
||||
struct TServerInfo
|
||||
{
|
||||
int Port;
|
||||
int Connected;
|
||||
int ServerIndex;
|
||||
int sockfd;
|
||||
};
|
||||
|
||||
extern struct TConfig Config;
|
||||
extern int SSDVSendArrayIndex;
|
||||
extern pthread_mutex_t ssdv_mutex;
|
||||
void LogMessage( const char *format, ... );
|
||||
extern int SSDVSendArrayIndex;
|
||||
extern pthread_mutex_t ssdv_mutex;
|
||||
|
||||
void LogMessage( const char *format, ... );
|
||||
|
||||
#endif /* _H_Global */
|
||||
|
|
|
@ -46,7 +46,7 @@ void hash_to_hex( unsigned char *hash, char *line )
|
|||
line[64] = '\0';
|
||||
}
|
||||
|
||||
void UploadTelemetryPacket( telemetry_t * t )
|
||||
void UploadTelemetryPacket( received_t * t )
|
||||
{
|
||||
CURL *curl;
|
||||
CURLcode res;
|
||||
|
@ -93,7 +93,7 @@ void UploadTelemetryPacket( telemetry_t * t )
|
|||
curl_easy_setopt( curl, CURLOPT_NOSIGNAL, 1 );
|
||||
|
||||
// Grab current telemetry string and append a linefeed
|
||||
sprintf( Sentence, "%s\n", t->Telemetry );
|
||||
sprintf( Sentence, "%s\n", t->UKHASstring );
|
||||
|
||||
// Convert sentence to base64
|
||||
base64_encode( Sentence, strlen( Sentence ), &base64_length,
|
||||
|
@ -174,7 +174,7 @@ void *HabitatLoop( void *vars )
|
|||
{
|
||||
thread_shared_vars_t *htsv;
|
||||
htsv = vars;
|
||||
telemetry_t t;
|
||||
received_t t;
|
||||
int packets = 0;
|
||||
unsigned long total_packets = 0;
|
||||
|
||||
|
|
Plik diff jest za duży
Load Diff
|
@ -0,0 +1,48 @@
|
|||
#ifndef __HABPACK_H__
|
||||
#define __HABPACK_H__
|
||||
|
||||
#include "global.h"
|
||||
|
||||
/* Core Telemetry */
|
||||
#define HABPACK_CALLSIGN 0
|
||||
#define HABPACK_SENTENCE_ID 1
|
||||
#define HABPACK_TIME 2
|
||||
#define HABPACK_POSITION 3
|
||||
#define HABPACK_GNSS_SATELLITES 4
|
||||
#define HABPACK_GNSS_LOCK 5
|
||||
#define HABPACK_VOLTAGE 6
|
||||
|
||||
/* Environmental Telemetry */
|
||||
#define HABPACK_INTERNAL_TEMPERATURE 10
|
||||
#define HABPACK_EXTERNAL_TEMPERATURE 11
|
||||
#define HABPACK_PRESSURE 12
|
||||
#define HABPACK_RELATIVE_HUMIDITY 13
|
||||
#define HABPACK_ABSOLUTE_HUMIDITY 14
|
||||
|
||||
/* Calling Beacon */
|
||||
#define HABPACK_DOWNLINK_FREQUENCY 20
|
||||
/* Common LoRa Mode */
|
||||
#define HABPACK_DOWNLINK_LORA_MODE 21
|
||||
/* _or_ Custom LoRa Parameters */
|
||||
#define HABPACK_DOWNLINK_LORA_IMPLICIT 22
|
||||
#define HABPACK_DOWNLINK_LORA_ERRORCODING 23
|
||||
#define HABPACK_DOWNLINK_LORA_BANDWIDTH 24
|
||||
#define HABPACK_DOWNLINK_LORA_SPREADING 25
|
||||
#define HABPACK_DOWNLINK_LORA_LDO 26
|
||||
|
||||
/* Uplink */
|
||||
#define HABPACK_UPLINK_COUNT 30
|
||||
|
||||
/* Landing Prediction */
|
||||
#define HABPACK_PREDICTED_LANDING_TIME 40
|
||||
#define HABPACK_PREDICTED_LANDING_POSITION 41
|
||||
|
||||
/* Multi-Position. TODO: Parsing unimplemented */
|
||||
#define HABPACK_MULTI_POS_POSITION_SCALING 60
|
||||
#define HABPACK_MULTI_POS_ALTITUDE_SCALING 61
|
||||
#define HABPACK_MULTI_POS_ARRAY 62
|
||||
|
||||
int Habpack_Process_Message(received_t *Received);
|
||||
void Habpack_Telem_Destroy(received_t *Received);
|
||||
|
||||
#endif /* __HABPACK_H__ */
|
4
server.c
4
server.c
|
@ -52,7 +52,7 @@ void ProcessJSONClientLine(int connfd, char *line)
|
|||
if (strchr(line, '=') != NULL)
|
||||
{
|
||||
// Setting
|
||||
char *setting, *value, *saveptr;
|
||||
char *setting, *value, *saveptr = NULL;
|
||||
|
||||
setting = strtok_r(line, "=", &saveptr);
|
||||
value = strtok_r( NULL, "\n", &saveptr);
|
||||
|
@ -62,7 +62,7 @@ void ProcessJSONClientLine(int connfd, char *line)
|
|||
else if (strchr(line, ':') != NULL)
|
||||
{
|
||||
// Command with parameters
|
||||
char *command, *value, *saveptr;
|
||||
char *command, *value, *saveptr = NULL;
|
||||
|
||||
command = strtok_r(line, ":", &saveptr);
|
||||
value = strtok_r(NULL, "\n", &saveptr);
|
||||
|
|
Ładowanie…
Reference in New Issue