Add support for time synchronization
Add time synchronisation for the Shearwater dive computers. All models support setting the local time. Only the Teric has basic support for time zones, and can set UTC time with a timezone offset. Co-authored-by: Michael Keller <github@ike.ch>
This commit is contained in:
parent
c16530b8ab
commit
25bd1f9853
@ -599,6 +599,91 @@ shearwater_common_wdbi (shearwater_common_device_t *device, unsigned int id, con
|
||||
return status;
|
||||
}
|
||||
|
||||
dc_status_t
|
||||
shearwater_common_timesync_local (shearwater_common_device_t *device, const dc_datetime_t *datetime)
|
||||
{
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
dc_device_t *abstract = (dc_device_t *) device;
|
||||
|
||||
// Convert to local time.
|
||||
dc_datetime_t local = *datetime;
|
||||
local.timezone = DC_TIMEZONE_NONE;
|
||||
|
||||
dc_ticks_t ticks = dc_datetime_mktime (&local);
|
||||
if (ticks == -1) {
|
||||
ERROR (abstract->context, "Invalid date/time value specified.");
|
||||
return DC_STATUS_INVALIDARGS;
|
||||
}
|
||||
|
||||
const unsigned char timestamp[] = {
|
||||
(ticks >> 24) & 0xFF,
|
||||
(ticks >> 16) & 0xFF,
|
||||
(ticks >> 8) & 0xFF,
|
||||
(ticks ) & 0xFF,
|
||||
};
|
||||
|
||||
status = shearwater_common_wdbi (device, ID_TIME_LOCAL, timestamp, sizeof(timestamp));
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to write the dive computer local time.");
|
||||
return status;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
dc_status_t
|
||||
shearwater_common_timesync_utc (shearwater_common_device_t *device, const dc_datetime_t *datetime)
|
||||
{
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
dc_device_t *abstract = (dc_device_t *) device;
|
||||
|
||||
// Convert to UTC time.
|
||||
dc_ticks_t ticks = dc_datetime_mktime (datetime);
|
||||
if (ticks == -1) {
|
||||
ERROR (abstract->context, "Invalid date/time value specified.");
|
||||
return DC_STATUS_INVALIDARGS;
|
||||
}
|
||||
|
||||
const unsigned char timestamp[] = {
|
||||
(ticks >> 24) & 0xFF,
|
||||
(ticks >> 16) & 0xFF,
|
||||
(ticks >> 8) & 0xFF,
|
||||
(ticks ) & 0xFF,
|
||||
};
|
||||
|
||||
status = shearwater_common_wdbi (device, ID_TIME_UTC, timestamp, sizeof(timestamp));
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to write the dive computer UTC time.");
|
||||
return status;
|
||||
}
|
||||
|
||||
int timezone = datetime->timezone / 60;
|
||||
const unsigned char offset[] = {
|
||||
(timezone >> 24) & 0xFF,
|
||||
(timezone >> 16) & 0xFF,
|
||||
(timezone >> 8) & 0xFF,
|
||||
(timezone ) & 0xFF,
|
||||
};
|
||||
|
||||
status = shearwater_common_wdbi (device, ID_TIME_OFFSET, offset, sizeof (offset));
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to write the dive computer timezone offset.");
|
||||
return status;
|
||||
}
|
||||
|
||||
// We don't have a way to determine the daylight savings time setting,
|
||||
// but the required offset is already factored into the timezone offset.
|
||||
const unsigned char dst[] = {0, 0, 0, 0};
|
||||
|
||||
status = shearwater_common_wdbi (device, ID_TIME_DST, dst, sizeof (dst));
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to write the dive computer DST setting.");
|
||||
return status;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
unsigned int
|
||||
shearwater_common_get_model (shearwater_common_device_t *device, unsigned int hardware)
|
||||
{
|
||||
|
||||
@ -35,6 +35,11 @@ extern "C" {
|
||||
#define ID_LOGUPLOAD 0x8021
|
||||
#define ID_HARDWARE 0x8050
|
||||
|
||||
#define ID_TIME_LOCAL 0x9030
|
||||
#define ID_TIME_UTC 0x9031
|
||||
#define ID_TIME_OFFSET 0x9032
|
||||
#define ID_TIME_DST 0x9033
|
||||
|
||||
#define PREDATOR 2
|
||||
#define PETREL 3
|
||||
#define PETREL2 PETREL
|
||||
@ -70,6 +75,12 @@ shearwater_common_rdbi (shearwater_common_device_t *device, unsigned int id, uns
|
||||
dc_status_t
|
||||
shearwater_common_wdbi (shearwater_common_device_t *device, unsigned int id, const unsigned char data[], unsigned int size);
|
||||
|
||||
dc_status_t
|
||||
shearwater_common_timesync_local (shearwater_common_device_t *device, const dc_datetime_t *datetime);
|
||||
|
||||
dc_status_t
|
||||
shearwater_common_timesync_utc (shearwater_common_device_t *device, const dc_datetime_t *datetime);
|
||||
|
||||
unsigned int
|
||||
shearwater_common_get_model (shearwater_common_device_t *device, unsigned int hardware);
|
||||
|
||||
|
||||
@ -46,6 +46,7 @@ typedef struct shearwater_petrel_device_t {
|
||||
|
||||
static dc_status_t shearwater_petrel_device_set_fingerprint (dc_device_t *abstract, const unsigned char data[], unsigned int size);
|
||||
static dc_status_t shearwater_petrel_device_foreach (dc_device_t *abstract, dc_dive_callback_t callback, void *userdata);
|
||||
static dc_status_t shearwater_petrel_device_timesync (dc_device_t *abstract, const dc_datetime_t *datetime);
|
||||
static dc_status_t shearwater_petrel_device_close (dc_device_t *abstract);
|
||||
|
||||
static const dc_device_vtable_t shearwater_petrel_device_vtable = {
|
||||
@ -56,7 +57,7 @@ static const dc_device_vtable_t shearwater_petrel_device_vtable = {
|
||||
NULL, /* write */
|
||||
NULL, /* dump */
|
||||
shearwater_petrel_device_foreach, /* foreach */
|
||||
NULL, /* timesync */
|
||||
shearwater_petrel_device_timesync,
|
||||
shearwater_petrel_device_close /* close */
|
||||
};
|
||||
|
||||
@ -350,3 +351,28 @@ shearwater_petrel_device_foreach (dc_device_t *abstract, dc_dive_callback_t call
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static dc_status_t
|
||||
shearwater_petrel_device_timesync (dc_device_t *abstract, const dc_datetime_t *datetime)
|
||||
{
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
shearwater_common_device_t *device = (shearwater_common_device_t *) abstract;
|
||||
|
||||
// Read the hardware type.
|
||||
unsigned char rsp_hardware[2] = {0};
|
||||
status = shearwater_common_rdbi (device, ID_HARDWARE, rsp_hardware, sizeof(rsp_hardware));
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to read the hardware type.");
|
||||
return status;
|
||||
}
|
||||
|
||||
// Convert and map to the model number.
|
||||
unsigned int hardware = array_uint16_be (rsp_hardware);
|
||||
unsigned int model = shearwater_common_get_model (device, hardware);
|
||||
|
||||
if (model == TERIC) {
|
||||
return shearwater_common_timesync_utc (device, datetime);
|
||||
} else {
|
||||
return shearwater_common_timesync_local (device, datetime);
|
||||
}
|
||||
}
|
||||
|
||||
@ -44,6 +44,7 @@ typedef struct shearwater_predator_device_t {
|
||||
static dc_status_t shearwater_predator_device_set_fingerprint (dc_device_t *abstract, const unsigned char data[], unsigned int size);
|
||||
static dc_status_t shearwater_predator_device_dump (dc_device_t *abstract, dc_buffer_t *buffer);
|
||||
static dc_status_t shearwater_predator_device_foreach (dc_device_t *abstract, dc_dive_callback_t callback, void *userdata);
|
||||
static dc_status_t shearwater_predator_device_timesync (dc_device_t *abstract, const dc_datetime_t *datetime);
|
||||
|
||||
static const dc_device_vtable_t shearwater_predator_device_vtable = {
|
||||
sizeof(shearwater_predator_device_t),
|
||||
@ -53,7 +54,7 @@ static const dc_device_vtable_t shearwater_predator_device_vtable = {
|
||||
NULL, /* write */
|
||||
shearwater_predator_device_dump, /* dump */
|
||||
shearwater_predator_device_foreach, /* foreach */
|
||||
NULL, /* timesync */
|
||||
shearwater_predator_device_timesync,
|
||||
NULL /* close */
|
||||
};
|
||||
|
||||
@ -357,3 +358,9 @@ shearwater_predator_extract_dives (dc_device_t *abstract, const unsigned char da
|
||||
return shearwater_predator_extract_predator (abstract, data, size, callback, userdata);
|
||||
}
|
||||
}
|
||||
|
||||
static dc_status_t
|
||||
shearwater_predator_device_timesync (dc_device_t *abstract, const dc_datetime_t *datetime)
|
||||
{
|
||||
return shearwater_common_timesync_local ((shearwater_common_device_t *) abstract, datetime);
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user