SELKIELogger  1.0.0
LPMSMessagesFromFile.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2023 Swansea University
3  *
4  * This file is part of the SELKIELogger suite of tools.
5  *
6  * SELKIELogger is free software: you can redistribute it and/or modify it
7  * under the terms of the GNU General Public License as published by the Free
8  * Software Foundation, either version 3 of the License, or (at your option)
9  * any later version.
10  *
11  * SELKIELogger is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14  * more details.
15  *
16  * You should have received a copy of the GNU General Public License along
17  * with this SELKIELogger product.
18  * If not, see <http://www.gnu.org/licenses/>.
19 */
20 
21 #include <stdbool.h>
22 #include <stdint.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <unistd.h>
27 
28 #include "SELKIELoggerBase.h"
29 
30 #include "SELKIELoggerLPMS.h"
31 
32 #include "version.h"
44 #define BUFSIZE 1024
45 
56 int main(int argc, char *argv[]) {
57  program_state state = {0};
58  state.verbose = 1;
59 
60  //LCOV_EXCL_START
61  // Should be 1 spare arguments: The file to convert
62  if (argc - optind != 1) {
63  log_error(&state, "Invalid arguments");
64  fprintf(stderr, "%s <datafile>\n", argv[0]);
65  return -1;
66  }
67 
68  FILE *nf = fopen(argv[optind], "r");
69 
70  if (nf == NULL) {
71  log_error(&state, "Unable to open input file \"%s\"", argv[optind]);
72  return -1;
73  }
74  //LCOV_EXCL_STOP
75 
76  state.started = true;
77  bool processing = true;
78 
79  uint8_t buf[BUFSIZE] = {0};
80  size_t hw = 0;
81  int count = 0;
82  size_t end = 0;
83  while (processing || hw > 10) {
84  //LCOV_EXCL_START
85  if (feof(nf) && processing) {
86  log_info(&state, 2, "End of file reached");
87  processing = false;
88  }
89  //LCOV_EXCL_STOP
90  lpms_message *m = calloc(1, sizeof(lpms_message));
91  if (!m) {
92  //LCOV_EXCL_START
93  perror("lpms_message calloc");
94  return EXIT_FAILURE;
95  //LCOV_EXCL_STOP
96  }
97  bool r = lpms_readMessage_buf(fileno(nf), m, buf, &end, &hw);
98  if (r) {
99  uint16_t cs = 0;
100  bool csOK = (lpms_checksum(m, &cs) && cs == m->checksum);
101  if (m->command == LPMS_MSG_GET_IMUDATA) {
102  lpms_data d = {0};
103  // Guess based on observed data until detection implemented
104  d.present |= (1 << LPMS_IMU_ACCEL_RAW);
105  d.present |= (1 << LPMS_IMU_ACCEL_CAL);
106  d.present |= (1 << LPMS_IMU_MAG_RAW);
107  d.present |= (1 << LPMS_IMU_MAG_CAL);
108  d.present |= (1 << LPMS_IMU_GYRO_RAW);
109  d.present |= (1 << LPMS_IMU_GYRO_CAL);
110  d.present |= (1 << LPMS_IMU_GYRO_ALIGN);
111  d.present |= (1 << LPMS_IMU_OMEGA);
112  d.present |= (1 << LPMS_IMU_EULER);
113  d.present |= (1 << LPMS_IMU_ALTITUDE);
114  d.present |= (1 << LPMS_IMU_TEMPERATURE);
115  if (lpms_imu_set_timestamp(m, &d)) {
116  log_info(&state, 1, "%02x: Timestamp: %u", m->id,
117  d.timestamp);
118  } else {
119  //LCOV_EXCL_START
120  log_warning(&state, "%02x: Timestamp invalid", m->id);
121  return -1;
122  //LCOV_EXCL_STOP
123  }
124  if (lpms_imu_set_accel_raw(m, &d)) {
125  log_info(&state, 1,
126  "%02x: Raw Acceleration: (%+.4f, %+.4f, %+4.f)",
127  m->id, d.accel_raw[0], d.accel_raw[1],
128  d.accel_raw[2]);
129  }
130  if (lpms_imu_set_accel_cal(m, &d)) {
131  log_info(
132  &state, 1,
133  "%02x: Calibrated Acceleration: (%+.4f, %+.4f, %+4.f)",
134  m->id, d.accel_cal[0], d.accel_cal[1],
135  d.accel_cal[2]);
136  }
137  if (lpms_imu_set_gyro_raw(m, &d)) {
138  log_info(&state, 1,
139  "%02x: Raw Gyro: (%+.4f, %+.4f, %+4.f)", m->id,
140  d.gyro_raw[0], d.gyro_raw[1], d.gyro_raw[2]);
141  }
142  if (lpms_imu_set_gyro_cal(m, &d)) {
143  log_info(&state, 1,
144  "%02x: Calibrated Gyro: (%+.4f, %+.4f, %+4.f)",
145  m->id, d.gyro_cal[0], d.gyro_cal[1],
146  d.gyro_cal[2]);
147  }
148  if (lpms_imu_set_gyro_aligned(m, &d)) {
149  log_info(&state, 1,
150  "%02x: Aligned Gyro: (%+.4f, %+.4f, %+4.f)",
151  m->id, d.gyro_aligned[0], d.gyro_aligned[1],
152  d.gyro_aligned[2]);
153  }
154  if (lpms_imu_set_mag_raw(m, &d)) {
155  log_info(&state, 1,
156  "%02x: Raw Magnetic Field: (%+.4f, %+.4f, %+4.f)",
157  m->id, d.mag_raw[0], d.mag_raw[1], d.mag_raw[2]);
158  }
159  if (lpms_imu_set_mag_cal(m, &d)) {
160  log_info(
161  &state, 1,
162  "%02x: Calibrated Magnetic Field: (%+.4f, %+.4f, %+4.f)",
163  m->id, d.mag_cal[0], d.mag_cal[1], d.mag_cal[2]);
164  }
165  if (lpms_imu_set_euler_angles(m, &d)) {
166  log_info(&state, 1,
167  "%02x: Euler roll angles: (%+.4f, %+.4f, %+.4f)",
168  m->id, d.euler_angles[0], d.euler_angles[1],
169  d.euler_angles[2]);
170  }
171  if (lpms_imu_set_altitude(m, &d)) {
172  log_info(&state, 1, "%02x: Altitude: %.2f", m->id,
173  d.altitude);
174  }
175  if (lpms_imu_set_temperature(m, &d)) {
176  log_info(&state, 1, "%02x: Temperature: %.2f", m->id,
177  d.temperature);
178  }
179  } else {
180  //LCOV_EXCL_START
181  log_info(&state, 2, "%02x: Command %02x, %u bytes, checksum %s",
182  m->id, m->command, m->length, csOK ? "OK" : "not OK");
183  //LCOV_EXCL_STOP
184  }
185  count++;
186  } else {
187  if (m->id == 0xAA || m->id == 0xEE) {
188  //LCOV_EXCL_START
189  log_error(&state,
190  "Error reading messages from file (Code: 0x%02x)\n",
191  (uint8_t)m->id);
192  //LCOV_EXCL_STOP
193  }
194 
195  if (m->id == 0xFD) {
196  processing = false;
197  if (end < hw) { end++; }
198  }
199  }
200 
201  if (m) {
202  if (m->data) { free(m->data); }
203  free(m);
204  m = NULL;
205  }
206  }
207  log_info(&state, 0, "%d messages successfully read from file", count);
208  fclose(nf);
209  return 0;
210 }
bool lpms_readMessage_buf(int handle, lpms_message *out, uint8_t buf[LPMS_BUFF], size_t *index, size_t *hw)
Read data from handle, and parse message if able.
int main(int argc, char *argv[])
#define BUFSIZE
Allocated read buffer size.
bool lpms_imu_set_temperature(const lpms_message *msg, lpms_data *d)
Extract temperature from lpms_message into lpms_data, if available.
Definition: LPMSMessages.c:501
bool lpms_checksum(const lpms_message *msg, uint16_t *csum)
Calculate checksum for LPMS message packet.
Definition: LPMSMessages.c:135
bool lpms_imu_set_gyro_aligned(const lpms_message *msg, lpms_data *d)
Extract gyro_aligned from lpms_message into lpms_data, if available.
Definition: LPMSMessages.c:258
bool lpms_imu_set_mag_cal(const lpms_message *msg, lpms_data *d)
Extract mag_cal from lpms_message into lpms_data, if available.
Definition: LPMSMessages.c:305
bool lpms_imu_set_altitude(const lpms_message *msg, lpms_data *d)
Extract altitude from lpms_message into lpms_data, if available.
Definition: LPMSMessages.c:470
bool lpms_imu_set_euler_angles(const lpms_message *msg, lpms_data *d)
Extract euler_angles from lpms_message into lpms_data, if available.
Definition: LPMSMessages.c:383
bool lpms_imu_set_gyro_raw(const lpms_message *msg, lpms_data *d)
Extract gyro_raw from lpms_message into lpms_data, if available.
Definition: LPMSMessages.c:214
bool lpms_imu_set_accel_raw(const lpms_message *msg, lpms_data *d)
Extract accel_raw from lpms_message into lpms_data, if available.
Definition: LPMSMessages.c:178
bool lpms_imu_set_timestamp(const lpms_message *msg, lpms_data *d)
Extract timestamp from lpms_message into lpms_data, if available.
Definition: LPMSMessages.c:161
bool lpms_imu_set_accel_cal(const lpms_message *msg, lpms_data *d)
Extract accel_cal from lpms_message into lpms_data, if available.
Definition: LPMSMessages.c:194
bool lpms_imu_set_mag_raw(const lpms_message *msg, lpms_data *d)
Extract mag_raw from lpms_message into lpms_data, if available.
Definition: LPMSMessages.c:281
bool lpms_imu_set_gyro_cal(const lpms_message *msg, lpms_data *d)
Extract gyro_cal from lpms_message into lpms_data, if available.
Definition: LPMSMessages.c:235
#define LPMS_IMU_MAG_RAW
mag_raw[] will contain data
Definition: LPMSTypes.h:105
#define LPMS_IMU_EULER
euler[] will contain data
Definition: LPMSTypes.h:109
#define LPMS_IMU_OMEGA
omega[] will contain data
Definition: LPMSTypes.h:107
#define LPMS_IMU_ACCEL_CAL
accel_cal[] will contain data
Definition: LPMSTypes.h:101
#define LPMS_IMU_MAG_CAL
mag_cal[] will contain data
Definition: LPMSTypes.h:106
#define LPMS_IMU_GYRO_ALIGN
gyro_align[] will contain data
Definition: LPMSTypes.h:104
#define LPMS_IMU_TEMPERATURE
temperature will contain data
Definition: LPMSTypes.h:113
#define LPMS_IMU_ALTITUDE
altitude will contain data
Definition: LPMSTypes.h:112
#define LPMS_IMU_GYRO_CAL
gyro_cal[] will contain data
Definition: LPMSTypes.h:103
#define LPMS_IMU_GYRO_RAW
gyro_raw[] will contain data
Definition: LPMSTypes.h:102
#define LPMS_IMU_ACCEL_RAW
accel_raw[] will contain data
Definition: LPMSTypes.h:100
#define LPMS_MSG_GET_IMUDATA
IMU data, as configured by LPMS_MSG_SET_OUTPUTS.
Definition: LPMSMessages.h:58
void log_info(const program_state *s, const int level, const char *format,...)
Output formatted information message at a given level.
Definition: logging.c:125
void log_warning(const program_state *s, const char *format,...)
Output formatted warning message.
Definition: logging.c:86
void log_error(const program_state *s, const char *format,...)
Output formatted error message.
Definition: logging.c:47
LPMS IMU data packet.
Definition: LPMSTypes.h:72
float euler_angles[3]
Orientation as Euler roll angles [X].
Definition: LPMSTypes.h:83
float altitude
Altitude [m].
Definition: LPMSTypes.h:86
float temperature
Temperature [Celsius].
Definition: LPMSTypes.h:87
float gyro_aligned[3]
Calibrated and aligned gyroscope values [X/s].
Definition: LPMSTypes.h:78
float mag_cal[3]
Calibrated magnetometer values [uT].
Definition: LPMSTypes.h:80
float gyro_raw[3]
Raw gyroscope values [X/s].
Definition: LPMSTypes.h:76
uint32_t timestamp
Counted in 0.002s increments.
Definition: LPMSTypes.h:73
float accel_cal[3]
Calibrated accelerometer values [g].
Definition: LPMSTypes.h:75
float gyro_cal[3]
Calibrated gyroscope values [X/s].
Definition: LPMSTypes.h:77
float mag_raw[3]
Raw magnetometer values [uT].
Definition: LPMSTypes.h:79
float accel_raw[3]
Raw accelerometer values [g].
Definition: LPMSTypes.h:74
uint32_t present
Bitmask indicating set/valid members.
Definition: LPMSTypes.h:88
Represent LPMS message.
Definition: LPMSTypes.h:48
uint16_t length
Length of data, in bytes.
Definition: LPMSTypes.h:51
uint16_t checksum
Sum of all preceding message bytes.
Definition: LPMSTypes.h:52
uint8_t * data
Pointer to data array.
Definition: LPMSTypes.h:53
uint16_t id
Source/Destination Sensor ID.
Definition: LPMSTypes.h:49
uint16_t command
Message type.
Definition: LPMSTypes.h:50
Program state and logging information.
Definition: logging.h:40
int verbose
Current log verbosity (console output)
Definition: logging.h:43
bool started
Indicates startup completed.
Definition: logging.h:41