timex_datalink_client 0.4.1 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/timex_datalink_client/helpers/cpacket_paginator.rb +2 -4
- data/lib/timex_datalink_client/protocol_1/alarm.rb +82 -0
- data/lib/timex_datalink_client/protocol_1/eeprom.rb +100 -0
- data/lib/timex_datalink_client/protocol_1/end.rb +10 -0
- data/lib/timex_datalink_client/protocol_1/start.rb +20 -0
- data/lib/timex_datalink_client/protocol_1/sync.rb +10 -0
- data/lib/timex_datalink_client/protocol_1/time.rb +61 -0
- data/lib/timex_datalink_client/protocol_1/time_name.rb +46 -0
- data/lib/timex_datalink_client/protocol_3/alarm.rb +59 -0
- data/lib/timex_datalink_client/protocol_3/eeprom.rb +95 -0
- data/lib/timex_datalink_client/protocol_3/end.rb +10 -0
- data/lib/timex_datalink_client/protocol_3/sound_options.rb +42 -0
- data/lib/timex_datalink_client/protocol_3/sound_theme.rb +65 -0
- data/lib/timex_datalink_client/protocol_3/start.rb +20 -0
- data/lib/timex_datalink_client/protocol_3/sync.rb +10 -0
- data/lib/timex_datalink_client/protocol_3/time.rb +77 -0
- data/lib/timex_datalink_client/protocol_3/wrist_app.rb +67 -0
- data/lib/timex_datalink_client/version.rb +1 -1
- data/lib/timex_datalink_client.rb +23 -12
- metadata +19 -10
- data/lib/timex_datalink_client/alarm.rb +0 -59
- data/lib/timex_datalink_client/eeprom.rb +0 -92
- data/lib/timex_datalink_client/sound_options.rb +0 -40
- data/lib/timex_datalink_client/sound_theme.rb +0 -62
- data/lib/timex_datalink_client/start.rb +0 -18
- data/lib/timex_datalink_client/time.rb +0 -75
- data/lib/timex_datalink_client/wrist_app.rb +0 -64
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 061a85e62bc26614e71a4fa43dc9c17cc6092a516a417d5545d7ecd029a34af6
|
4
|
+
data.tar.gz: 4e3fc39203b45c38599c6980c72c42e6e05efdc87e7c7d5c9f4cc099e995d39e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 40b7dbbfd0af7b4600b5d94623584615b193b2011b976ed229ee7ba084892ba05d31002150dd9decfafcaecb301d2fa44d1c9a5a03ecace2a20441edda50b6ca
|
7
|
+
data.tar.gz: b902ecee9de6ebf920e86a08c57e9651730335492c1e05ccfe55d0169fbf7c714ac5ba02f8640983ea69bc5d34ae1269e8f1d97b9e36f4d3921e07cdea0f039c
|
@@ -3,10 +3,8 @@
|
|
3
3
|
class TimexDatalinkClient
|
4
4
|
class Helpers
|
5
5
|
module CpacketPaginator
|
6
|
-
|
7
|
-
|
8
|
-
def paginate_cpackets(header:, cpackets:)
|
9
|
-
paginated_cpackets = cpackets.each_slice(ITEMS_PER_PACKET)
|
6
|
+
def paginate_cpackets(header:, length:, cpackets:)
|
7
|
+
paginated_cpackets = cpackets.each_slice(length)
|
10
8
|
|
11
9
|
paginated_cpackets.map.with_index(1) do |paginated_cpacket, index|
|
12
10
|
header + [index] + paginated_cpacket
|
@@ -0,0 +1,82 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "timex_datalink_client/helpers/char_encoders"
|
4
|
+
require "timex_datalink_client/helpers/crc_packets_wrapper"
|
5
|
+
|
6
|
+
class TimexDatalinkClient
|
7
|
+
class Protocol1
|
8
|
+
class Alarm
|
9
|
+
include Helpers::CharEncoders
|
10
|
+
prepend Helpers::CrcPacketsWrapper
|
11
|
+
|
12
|
+
CPACKET_ALARM = [0x50]
|
13
|
+
CPACKET_ALARM_SILENT = [0x70, 0x00]
|
14
|
+
|
15
|
+
ALARM_SILENT_START_INDEX = 0x61
|
16
|
+
|
17
|
+
attr_accessor :number, :audible, :time, :message, :month, :day
|
18
|
+
|
19
|
+
# Create an Alarm instance.
|
20
|
+
#
|
21
|
+
# @param number [Integer] Alarm number (from 1 to 5).
|
22
|
+
# @param audible [Boolean] Toggle alarm sounds.
|
23
|
+
# @param time [::Time] Time of alarm.
|
24
|
+
# @param message [String] Alarm message text.
|
25
|
+
# @param month [Integer, nil] Month of alarm.
|
26
|
+
# @param day [Integer, nil] Day of alarm.
|
27
|
+
# @return [Alarm] Alarm instance.
|
28
|
+
def initialize(number:, audible:, time:, message:, month: nil, day: nil)
|
29
|
+
@number = number
|
30
|
+
@audible = audible
|
31
|
+
@time = time
|
32
|
+
@message = message
|
33
|
+
@month = month
|
34
|
+
@day = day
|
35
|
+
end
|
36
|
+
|
37
|
+
# Compile packets for an alarm.
|
38
|
+
#
|
39
|
+
# @return [Array<Array<Integer>>] Two-dimensional array of integers that represent bytes.
|
40
|
+
def packets
|
41
|
+
[alarm_data_packet].tap do |packets|
|
42
|
+
packets << alarm_silent_packet unless audible
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
def alarm_data_packet
|
49
|
+
[
|
50
|
+
CPACKET_ALARM,
|
51
|
+
number,
|
52
|
+
time.hour,
|
53
|
+
time.min,
|
54
|
+
month.to_i,
|
55
|
+
day.to_i,
|
56
|
+
message_characters,
|
57
|
+
audible_integer
|
58
|
+
].flatten
|
59
|
+
end
|
60
|
+
|
61
|
+
def alarm_silent_packet
|
62
|
+
[
|
63
|
+
CPACKET_ALARM_SILENT,
|
64
|
+
alarm_silent_index,
|
65
|
+
0
|
66
|
+
].flatten
|
67
|
+
end
|
68
|
+
|
69
|
+
def message_characters
|
70
|
+
chars_for(message, length: 8, pad: true)
|
71
|
+
end
|
72
|
+
|
73
|
+
def audible_integer
|
74
|
+
audible ? 1 : 0
|
75
|
+
end
|
76
|
+
|
77
|
+
def alarm_silent_index
|
78
|
+
ALARM_SILENT_START_INDEX + number
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,100 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "timex_datalink_client/helpers/cpacket_paginator"
|
4
|
+
require "timex_datalink_client/helpers/crc_packets_wrapper"
|
5
|
+
|
6
|
+
class TimexDatalinkClient
|
7
|
+
class Protocol1
|
8
|
+
class Eeprom
|
9
|
+
include Helpers::CpacketPaginator
|
10
|
+
prepend Helpers::CrcPacketsWrapper
|
11
|
+
|
12
|
+
CPACKET_SECT = [0x60]
|
13
|
+
CPACKET_DATA = [0x61]
|
14
|
+
CPACKET_END = [0x62]
|
15
|
+
|
16
|
+
CPACKET_DATA_LENGTH = 27
|
17
|
+
START_INDEX = 14
|
18
|
+
APPOINTMENT_NO_NOTIFICATION = 0xff
|
19
|
+
|
20
|
+
attr_accessor :appointments, :anniversaries, :phone_numbers, :lists, :appointment_notification
|
21
|
+
|
22
|
+
# Create an Eeprom instance.
|
23
|
+
#
|
24
|
+
# @param appointments [Array<Appointment>] Appointments to be added to EEPROM data.
|
25
|
+
# @param anniversaries [Array<Anniversary>] Anniversaries to be added to EEPROM data.
|
26
|
+
# @param phone_numbers [Array<PhoneNumber>] Phone numbers to be added to EEPROM data.
|
27
|
+
# @param lists [Array<List>] Lists to be added to EEPROM data.
|
28
|
+
# @param appointment_notification [Integer] Appointment notification (intervals of 15 minutes, 255 for no
|
29
|
+
# notification)
|
30
|
+
# @return [Eeprom] Eeprom instance.
|
31
|
+
def initialize(appointments: [], anniversaries: [], phone_numbers: [], lists: [], appointment_notification: APPOINTMENT_NO_NOTIFICATION)
|
32
|
+
@appointments = appointments
|
33
|
+
@anniversaries = anniversaries
|
34
|
+
@phone_numbers = phone_numbers
|
35
|
+
@lists = lists
|
36
|
+
@appointment_notification = appointment_notification
|
37
|
+
end
|
38
|
+
|
39
|
+
# Compile packets for EEPROM data.
|
40
|
+
#
|
41
|
+
# @return [Array<Array<Integer>>] Two-dimensional array of integers that represent bytes.
|
42
|
+
def packets
|
43
|
+
[header] + payloads + [CPACKET_END]
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
def header
|
49
|
+
[
|
50
|
+
CPACKET_SECT,
|
51
|
+
payloads.length
|
52
|
+
].flatten
|
53
|
+
end
|
54
|
+
|
55
|
+
def payload
|
56
|
+
[
|
57
|
+
items_indexes,
|
58
|
+
items_lengths,
|
59
|
+
earliest_appointment_year,
|
60
|
+
appointment_notification,
|
61
|
+
all_packets
|
62
|
+
].flatten
|
63
|
+
end
|
64
|
+
|
65
|
+
def payloads
|
66
|
+
paginate_cpackets(header: CPACKET_DATA, length: CPACKET_DATA_LENGTH, cpackets: payload)
|
67
|
+
end
|
68
|
+
|
69
|
+
def all_items
|
70
|
+
[appointments, lists, phone_numbers, anniversaries]
|
71
|
+
end
|
72
|
+
|
73
|
+
def all_packets
|
74
|
+
all_items.flatten.map(&:packet).flatten
|
75
|
+
end
|
76
|
+
|
77
|
+
def items_indexes
|
78
|
+
index = START_INDEX
|
79
|
+
|
80
|
+
all_items.each_with_object([]) do |items, indexes|
|
81
|
+
indexes.concat(index.divmod(256))
|
82
|
+
|
83
|
+
index += items.sum { |item| item.packet.length }
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def items_lengths
|
88
|
+
all_items.map(&:length)
|
89
|
+
end
|
90
|
+
|
91
|
+
def earliest_appointment_year
|
92
|
+
earliest_appointment = appointments.min_by(&:time)
|
93
|
+
|
94
|
+
return 0 unless earliest_appointment
|
95
|
+
|
96
|
+
earliest_appointment.time.year % 100
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "timex_datalink_client/helpers/crc_packets_wrapper"
|
4
|
+
|
5
|
+
class TimexDatalinkClient
|
6
|
+
class Protocol1
|
7
|
+
class Start
|
8
|
+
prepend Helpers::CrcPacketsWrapper
|
9
|
+
|
10
|
+
CPACKET_START = [0x20, 0x00, 0x00, 0x01]
|
11
|
+
|
12
|
+
# Compile packets for data start command.
|
13
|
+
#
|
14
|
+
# @return [Array<Array<Integer>>] Two-dimensional array of integers that represent bytes.
|
15
|
+
def packets
|
16
|
+
[CPACKET_START]
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "timex_datalink_client/helpers/crc_packets_wrapper"
|
4
|
+
|
5
|
+
class TimexDatalinkClient
|
6
|
+
class Protocol1
|
7
|
+
class Time
|
8
|
+
prepend Helpers::CrcPacketsWrapper
|
9
|
+
|
10
|
+
CPACKET_TIME = [0x30]
|
11
|
+
|
12
|
+
attr_accessor :zone, :is_24h, :time
|
13
|
+
|
14
|
+
# Create a Time instance.
|
15
|
+
#
|
16
|
+
# @param zone [Integer] Time zone number (1 or 2).
|
17
|
+
# @param is_24h [Boolean] Toggle 24 hour time.
|
18
|
+
# @param time [::Time] Time to set.
|
19
|
+
# @return [Time] Time instance.
|
20
|
+
def initialize(zone:, is_24h:, time:)
|
21
|
+
@zone = zone
|
22
|
+
@is_24h = is_24h
|
23
|
+
@time = time
|
24
|
+
end
|
25
|
+
|
26
|
+
# Compile packets for a time.
|
27
|
+
#
|
28
|
+
# @return [Array<Array<Integer>>] Two-dimensional array of integers that represent bytes.
|
29
|
+
def packets
|
30
|
+
[
|
31
|
+
[
|
32
|
+
CPACKET_TIME,
|
33
|
+
zone,
|
34
|
+
time.hour,
|
35
|
+
time.min,
|
36
|
+
time.month,
|
37
|
+
time.day,
|
38
|
+
year_mod_1900,
|
39
|
+
wday_from_monday,
|
40
|
+
time.sec,
|
41
|
+
is_24h_value
|
42
|
+
].flatten
|
43
|
+
]
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
def year_mod_1900
|
49
|
+
time.year % 100
|
50
|
+
end
|
51
|
+
|
52
|
+
def wday_from_monday
|
53
|
+
(time.wday + 6) % 7
|
54
|
+
end
|
55
|
+
|
56
|
+
def is_24h_value
|
57
|
+
is_24h ? 2 : 1
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "timex_datalink_client/helpers/char_encoders"
|
4
|
+
require "timex_datalink_client/helpers/crc_packets_wrapper"
|
5
|
+
|
6
|
+
class TimexDatalinkClient
|
7
|
+
class Protocol1
|
8
|
+
class TimeName
|
9
|
+
include Helpers::CharEncoders
|
10
|
+
prepend Helpers::CrcPacketsWrapper
|
11
|
+
|
12
|
+
CPACKET_NAME = [0x31]
|
13
|
+
|
14
|
+
attr_accessor :zone, :name
|
15
|
+
|
16
|
+
# Create a TimeName instance.
|
17
|
+
#
|
18
|
+
# @param zone [Integer] Time zone number (1 or 2).
|
19
|
+
# @param name [String] Name of time zone (3 chars max)
|
20
|
+
# @return [TimeName] TimeName instance.
|
21
|
+
def initialize(zone:, name:)
|
22
|
+
@zone = zone
|
23
|
+
@name = name
|
24
|
+
end
|
25
|
+
|
26
|
+
# Compile packets for a time name.
|
27
|
+
#
|
28
|
+
# @return [Array<Array<Integer>>] Two-dimensional array of integers that represent bytes.
|
29
|
+
def packets
|
30
|
+
[
|
31
|
+
[
|
32
|
+
CPACKET_NAME,
|
33
|
+
zone,
|
34
|
+
name_characters
|
35
|
+
].flatten
|
36
|
+
]
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
def name_characters
|
42
|
+
chars_for(name, length: 3, pad: true)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "timex_datalink_client/helpers/char_encoders"
|
4
|
+
require "timex_datalink_client/helpers/crc_packets_wrapper"
|
5
|
+
|
6
|
+
class TimexDatalinkClient
|
7
|
+
class Protocol3
|
8
|
+
class Alarm
|
9
|
+
include Helpers::CharEncoders
|
10
|
+
prepend Helpers::CrcPacketsWrapper
|
11
|
+
|
12
|
+
CPACKET_ALARM = [0x50]
|
13
|
+
|
14
|
+
attr_accessor :number, :audible, :time, :message
|
15
|
+
|
16
|
+
# Create an Alarm instance.
|
17
|
+
#
|
18
|
+
# @param number [Integer] Alarm number (from 1 to 5).
|
19
|
+
# @param audible [Boolean] Toggle alarm sounds.
|
20
|
+
# @param time [::Time] Time of alarm.
|
21
|
+
# @param message [String] Alarm message text.
|
22
|
+
# @return [Alarm] Alarm instance.
|
23
|
+
def initialize(number:, audible:, time:, message:)
|
24
|
+
@number = number
|
25
|
+
@audible = audible
|
26
|
+
@time = time
|
27
|
+
@message = message
|
28
|
+
end
|
29
|
+
|
30
|
+
# Compile packets for an alarm.
|
31
|
+
#
|
32
|
+
# @return [Array<Array<Integer>>] Two-dimensional array of integers that represent bytes.
|
33
|
+
def packets
|
34
|
+
[
|
35
|
+
[
|
36
|
+
CPACKET_ALARM,
|
37
|
+
number,
|
38
|
+
time.hour,
|
39
|
+
time.min,
|
40
|
+
0,
|
41
|
+
0,
|
42
|
+
message_characters,
|
43
|
+
audible_integer
|
44
|
+
].flatten
|
45
|
+
]
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
|
50
|
+
def message_characters
|
51
|
+
chars_for(message, length: 8, pad: true)
|
52
|
+
end
|
53
|
+
|
54
|
+
def audible_integer
|
55
|
+
audible ? 1 : 0
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,95 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "timex_datalink_client/helpers/cpacket_paginator"
|
4
|
+
require "timex_datalink_client/helpers/crc_packets_wrapper"
|
5
|
+
|
6
|
+
class TimexDatalinkClient
|
7
|
+
class Protocol3
|
8
|
+
class Eeprom
|
9
|
+
include Helpers::CpacketPaginator
|
10
|
+
prepend Helpers::CrcPacketsWrapper
|
11
|
+
|
12
|
+
CPACKET_CLEAR = [0x93, 0x01]
|
13
|
+
CPACKET_SECT = [0x90, 0x01]
|
14
|
+
CPACKET_DATA = [0x91, 0x01]
|
15
|
+
CPACKET_END = [0x92, 0x01]
|
16
|
+
|
17
|
+
CPACKET_DATA_LENGTH = 32
|
18
|
+
START_ADDRESS = 0x0236
|
19
|
+
APPOINTMENT_NO_NOTIFICATION = 0xff
|
20
|
+
|
21
|
+
attr_accessor :appointments, :anniversaries, :phone_numbers, :lists, :appointment_notification
|
22
|
+
|
23
|
+
# Create an Eeprom instance.
|
24
|
+
#
|
25
|
+
# @param appointments [Array<Appointment>] Appointments to be added to EEPROM data.
|
26
|
+
# @param anniversaries [Array<Anniversary>] Anniversaries to be added to EEPROM data.
|
27
|
+
# @param phone_numbers [Array<PhoneNumber>] Phone numbers to be added to EEPROM data.
|
28
|
+
# @param lists [Array<List>] Lists to be added to EEPROM data.
|
29
|
+
# @param appointment_notification [Integer] Appointment notification (intervals of 15 minutes, 255 for no
|
30
|
+
# notification)
|
31
|
+
# @return [Eeprom] Eeprom instance.
|
32
|
+
def initialize(appointments: [], anniversaries: [], phone_numbers: [], lists: [], appointment_notification: APPOINTMENT_NO_NOTIFICATION)
|
33
|
+
@appointments = appointments
|
34
|
+
@anniversaries = anniversaries
|
35
|
+
@phone_numbers = phone_numbers
|
36
|
+
@lists = lists
|
37
|
+
@appointment_notification = appointment_notification
|
38
|
+
end
|
39
|
+
|
40
|
+
# Compile packets for EEPROM data.
|
41
|
+
#
|
42
|
+
# @return [Array<Array<Integer>>] Two-dimensional array of integers that represent bytes.
|
43
|
+
def packets
|
44
|
+
[CPACKET_CLEAR, header] + payloads + [CPACKET_END]
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
|
49
|
+
def header
|
50
|
+
[
|
51
|
+
CPACKET_SECT,
|
52
|
+
payloads.length,
|
53
|
+
items_addresses,
|
54
|
+
items_lengths,
|
55
|
+
earliest_appointment_year,
|
56
|
+
appointment_notification
|
57
|
+
].flatten
|
58
|
+
end
|
59
|
+
|
60
|
+
def payloads
|
61
|
+
paginate_cpackets(header: CPACKET_DATA, length: CPACKET_DATA_LENGTH, cpackets: all_packets)
|
62
|
+
end
|
63
|
+
|
64
|
+
def all_items
|
65
|
+
[appointments, lists, phone_numbers, anniversaries]
|
66
|
+
end
|
67
|
+
|
68
|
+
def all_packets
|
69
|
+
all_items.flatten.map(&:packet).flatten
|
70
|
+
end
|
71
|
+
|
72
|
+
def items_addresses
|
73
|
+
address = START_ADDRESS
|
74
|
+
|
75
|
+
all_items.each_with_object([]) do |items, addresses|
|
76
|
+
addresses.concat(address.divmod(256))
|
77
|
+
|
78
|
+
address += items.sum { |item| item.packet.length }
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def items_lengths
|
83
|
+
all_items.map(&:length)
|
84
|
+
end
|
85
|
+
|
86
|
+
def earliest_appointment_year
|
87
|
+
earliest_appointment = appointments.min_by(&:time)
|
88
|
+
|
89
|
+
return 0 unless earliest_appointment
|
90
|
+
|
91
|
+
earliest_appointment.time.year % 100
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "timex_datalink_client/helpers/crc_packets_wrapper"
|
4
|
+
|
5
|
+
class TimexDatalinkClient
|
6
|
+
class Protocol3
|
7
|
+
class SoundOptions
|
8
|
+
prepend Helpers::CrcPacketsWrapper
|
9
|
+
|
10
|
+
CPACKET_BEEPS = [0x71]
|
11
|
+
|
12
|
+
attr_accessor :hourly_chime, :button_beep
|
13
|
+
|
14
|
+
# Create a SoundOptions instance.
|
15
|
+
#
|
16
|
+
# @param hourly_chime [Boolean] Toggle hourly chime sounds.
|
17
|
+
# @param button_beep [Boolean] Toggle button beep sounds.
|
18
|
+
# @return [SoundOptions] SoundOptions instance.
|
19
|
+
def initialize(hourly_chime:, button_beep:)
|
20
|
+
@hourly_chime = hourly_chime
|
21
|
+
@button_beep = button_beep
|
22
|
+
end
|
23
|
+
|
24
|
+
# Compile packets for sound options.
|
25
|
+
#
|
26
|
+
# @return [Array<Array<Integer>>] Two-dimensional array of integers that represent bytes.
|
27
|
+
def packets
|
28
|
+
[
|
29
|
+
CPACKET_BEEPS + [hourly_chime_integer, button_beep_integer]
|
30
|
+
]
|
31
|
+
end
|
32
|
+
|
33
|
+
def hourly_chime_integer
|
34
|
+
hourly_chime ? 1 : 0
|
35
|
+
end
|
36
|
+
|
37
|
+
def button_beep_integer
|
38
|
+
button_beep ? 1 : 0
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "timex_datalink_client/helpers/cpacket_paginator"
|
4
|
+
require "timex_datalink_client/helpers/crc_packets_wrapper"
|
5
|
+
|
6
|
+
class TimexDatalinkClient
|
7
|
+
class Protocol3
|
8
|
+
class SoundTheme
|
9
|
+
include Helpers::CpacketPaginator
|
10
|
+
prepend Helpers::CrcPacketsWrapper
|
11
|
+
|
12
|
+
CPACKET_SECT = [0x90, 0x03]
|
13
|
+
CPACKET_DATA = [0x91, 0x03]
|
14
|
+
CPACKET_END = [0x92, 0x03]
|
15
|
+
|
16
|
+
CPACKET_DATA_LENGTH = 32
|
17
|
+
SOUND_DATA_HEADER = "\x25\x04\x19\x69"
|
18
|
+
|
19
|
+
attr_accessor :spc_file
|
20
|
+
|
21
|
+
# Create a SoundTheme instance.
|
22
|
+
#
|
23
|
+
# @param sound_theme_data [String, nil] Sound theme data.
|
24
|
+
# @param spc_file [String, nil] Path to SPC file.
|
25
|
+
# @return [SoundTheme] SoundTheme instance.
|
26
|
+
def initialize(sound_theme_data: nil, spc_file: nil)
|
27
|
+
@sound_theme_data = sound_theme_data
|
28
|
+
@spc_file = spc_file
|
29
|
+
end
|
30
|
+
|
31
|
+
# Compile packets for a sound theme.
|
32
|
+
#
|
33
|
+
# @return [Array<Array<Integer>>] Two-dimensional array of integers that represent bytes.
|
34
|
+
def packets
|
35
|
+
[load_sect] + payloads + [CPACKET_END]
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
def load_sect
|
41
|
+
CPACKET_SECT + [payloads.length, offset]
|
42
|
+
end
|
43
|
+
|
44
|
+
def payloads
|
45
|
+
paginate_cpackets(header: CPACKET_DATA, length: CPACKET_DATA_LENGTH, cpackets: sound_theme_data.bytes)
|
46
|
+
end
|
47
|
+
|
48
|
+
def sound_theme_data
|
49
|
+
@sound_theme_data || spc_file_data_without_header
|
50
|
+
end
|
51
|
+
|
52
|
+
def spc_file_data
|
53
|
+
File.open(spc_file, "rb").read
|
54
|
+
end
|
55
|
+
|
56
|
+
def spc_file_data_without_header
|
57
|
+
spc_file_data.delete_prefix(SOUND_DATA_HEADER)
|
58
|
+
end
|
59
|
+
|
60
|
+
def offset
|
61
|
+
0x100 - sound_theme_data.bytesize
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "timex_datalink_client/helpers/crc_packets_wrapper"
|
4
|
+
|
5
|
+
class TimexDatalinkClient
|
6
|
+
class Protocol3
|
7
|
+
class Start
|
8
|
+
prepend Helpers::CrcPacketsWrapper
|
9
|
+
|
10
|
+
CPACKET_START = [0x20, 0x00, 0x00, 0x03]
|
11
|
+
|
12
|
+
# Compile packets for data start command.
|
13
|
+
#
|
14
|
+
# @return [Array<Array<Integer>>] Two-dimensional array of integers that represent bytes.
|
15
|
+
def packets
|
16
|
+
[CPACKET_START]
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "timex_datalink_client/helpers/char_encoders"
|
4
|
+
require "timex_datalink_client/helpers/crc_packets_wrapper"
|
5
|
+
|
6
|
+
class TimexDatalinkClient
|
7
|
+
class Protocol3
|
8
|
+
class Time
|
9
|
+
include Helpers::CharEncoders
|
10
|
+
prepend Helpers::CrcPacketsWrapper
|
11
|
+
|
12
|
+
CPACKET_TIME = [0x32]
|
13
|
+
|
14
|
+
attr_accessor :zone, :is_24h, :date_format, :time
|
15
|
+
|
16
|
+
# Create a Time instance.
|
17
|
+
#
|
18
|
+
# @param zone [Integer] Time zone number (1 or 2).
|
19
|
+
# @param is_24h [Boolean] Toggle 24 hour time.
|
20
|
+
# @param date_format [Integer] Date format.
|
21
|
+
# @param time [::Time] Time to set (including time zone).
|
22
|
+
# @param name [String, nil] Name of time zone (defaults to zone from time; 3 chars max)
|
23
|
+
# @return [Time] Time instance.
|
24
|
+
def initialize(zone:, is_24h:, date_format:, time:, name: nil)
|
25
|
+
@zone = zone
|
26
|
+
@is_24h = is_24h
|
27
|
+
@date_format = date_format
|
28
|
+
@time = time
|
29
|
+
@name = name
|
30
|
+
end
|
31
|
+
|
32
|
+
# Compile packets for a time.
|
33
|
+
#
|
34
|
+
# @return [Array<Array<Integer>>] Two-dimensional array of integers that represent bytes.
|
35
|
+
def packets
|
36
|
+
[
|
37
|
+
[
|
38
|
+
CPACKET_TIME,
|
39
|
+
zone,
|
40
|
+
time.sec,
|
41
|
+
time.hour,
|
42
|
+
time.min,
|
43
|
+
time.month,
|
44
|
+
time.day,
|
45
|
+
year_mod_1900,
|
46
|
+
name_characters,
|
47
|
+
wday_from_monday,
|
48
|
+
is_24h_value,
|
49
|
+
date_format
|
50
|
+
].flatten
|
51
|
+
]
|
52
|
+
end
|
53
|
+
|
54
|
+
private
|
55
|
+
|
56
|
+
def name
|
57
|
+
@name || time.zone.downcase
|
58
|
+
end
|
59
|
+
|
60
|
+
def name_characters
|
61
|
+
chars_for(name, length: 3, pad: true)
|
62
|
+
end
|
63
|
+
|
64
|
+
def year_mod_1900
|
65
|
+
time.year % 100
|
66
|
+
end
|
67
|
+
|
68
|
+
def wday_from_monday
|
69
|
+
(time.wday + 6) % 7
|
70
|
+
end
|
71
|
+
|
72
|
+
def is_24h_value
|
73
|
+
is_24h ? 2 : 1
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "timex_datalink_client/helpers/cpacket_paginator"
|
4
|
+
require "timex_datalink_client/helpers/crc_packets_wrapper"
|
5
|
+
|
6
|
+
class TimexDatalinkClient
|
7
|
+
class Protocol3
|
8
|
+
class WristApp
|
9
|
+
include Helpers::CpacketPaginator
|
10
|
+
prepend Helpers::CrcPacketsWrapper
|
11
|
+
|
12
|
+
CPACKET_CLEAR = [0x93, 0x02]
|
13
|
+
CPACKET_SECT = [0x90, 0x02]
|
14
|
+
CPACKET_DATA = [0x91, 0x02]
|
15
|
+
CPACKET_END = [0x92, 0x02]
|
16
|
+
|
17
|
+
CPACKET_DATA_LENGTH = 32
|
18
|
+
WRIST_APP_DELIMITER = /\xac.*\r\n/n
|
19
|
+
WRIST_APP_CODE_INDEX = 8
|
20
|
+
|
21
|
+
attr_accessor :zap_file
|
22
|
+
|
23
|
+
# Create a WristApp instance.
|
24
|
+
#
|
25
|
+
# @param wrist_app_data [String, nil] WristApp data.
|
26
|
+
# @param zap_file [String, nil] Path to ZAP file.
|
27
|
+
# @return [WristApp] WristApp instance.
|
28
|
+
def initialize(wrist_app_data: nil, zap_file: nil)
|
29
|
+
@wrist_app_data = wrist_app_data
|
30
|
+
@zap_file = zap_file
|
31
|
+
end
|
32
|
+
|
33
|
+
# Compile packets for an alarm.
|
34
|
+
#
|
35
|
+
# @return [Array<Array<Integer>>] Two-dimensional array of integers that represent bytes.
|
36
|
+
def packets
|
37
|
+
[CPACKET_CLEAR, cpacket_sect] + payloads + [CPACKET_END]
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
def cpacket_sect
|
43
|
+
CPACKET_SECT + [payloads.length, 1]
|
44
|
+
end
|
45
|
+
|
46
|
+
def payloads
|
47
|
+
paginate_cpackets(header: CPACKET_DATA, length: CPACKET_DATA_LENGTH, cpackets: wrist_app_data.bytes)
|
48
|
+
end
|
49
|
+
|
50
|
+
def wrist_app_data
|
51
|
+
@wrist_app_data || zap_file_data_binary
|
52
|
+
end
|
53
|
+
|
54
|
+
def zap_file_data
|
55
|
+
File.open(zap_file, "rb").read
|
56
|
+
end
|
57
|
+
|
58
|
+
def zap_file_data_ascii
|
59
|
+
zap_file_data.split(WRIST_APP_DELIMITER)[WRIST_APP_CODE_INDEX]
|
60
|
+
end
|
61
|
+
|
62
|
+
def zap_file_data_binary
|
63
|
+
[zap_file_data_ascii].pack("H*")
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -1,20 +1,30 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "timex_datalink_client/
|
4
|
-
require "timex_datalink_client/
|
3
|
+
require "timex_datalink_client/version"
|
4
|
+
require "timex_datalink_client/notebook_adapter"
|
5
|
+
|
5
6
|
require "timex_datalink_client/eeprom/anniversary"
|
6
7
|
require "timex_datalink_client/eeprom/appointment"
|
7
8
|
require "timex_datalink_client/eeprom/list"
|
8
9
|
require "timex_datalink_client/eeprom/phone_number"
|
9
|
-
|
10
|
-
require "timex_datalink_client/
|
11
|
-
require "timex_datalink_client/
|
12
|
-
require "timex_datalink_client/
|
13
|
-
require "timex_datalink_client/start"
|
14
|
-
require "timex_datalink_client/sync"
|
15
|
-
require "timex_datalink_client/time"
|
16
|
-
require "timex_datalink_client/
|
17
|
-
|
10
|
+
|
11
|
+
require "timex_datalink_client/protocol_1/alarm"
|
12
|
+
require "timex_datalink_client/protocol_1/eeprom"
|
13
|
+
require "timex_datalink_client/protocol_1/end"
|
14
|
+
require "timex_datalink_client/protocol_1/start"
|
15
|
+
require "timex_datalink_client/protocol_1/sync"
|
16
|
+
require "timex_datalink_client/protocol_1/time"
|
17
|
+
require "timex_datalink_client/protocol_1/time_name"
|
18
|
+
|
19
|
+
require "timex_datalink_client/protocol_3/alarm"
|
20
|
+
require "timex_datalink_client/protocol_3/eeprom"
|
21
|
+
require "timex_datalink_client/protocol_3/end"
|
22
|
+
require "timex_datalink_client/protocol_3/sound_options"
|
23
|
+
require "timex_datalink_client/protocol_3/sound_theme"
|
24
|
+
require "timex_datalink_client/protocol_3/start"
|
25
|
+
require "timex_datalink_client/protocol_3/sync"
|
26
|
+
require "timex_datalink_client/protocol_3/time"
|
27
|
+
require "timex_datalink_client/protocol_3/wrist_app"
|
18
28
|
|
19
29
|
class TimexDatalinkClient
|
20
30
|
attr_accessor :serial_device, :models, :byte_sleep, :packet_sleep, :verbose
|
@@ -22,7 +32,8 @@ class TimexDatalinkClient
|
|
22
32
|
# Create a TimexDatalinkClient instance.
|
23
33
|
#
|
24
34
|
# @param serial_device [String] Path to serial device.
|
25
|
-
# @param models [Array<Alarm, Eeprom, End, SoundOptions,
|
35
|
+
# @param models [Array<Protocol3::Alarm, Protocol3::Eeprom, Protocol3::End, Protocol3::SoundOptions,
|
36
|
+
# Protocol3::SoundTheme, Protocol3::Start, Protocol3::Sync, Protocol3::Time, Protocol3::WristApp>] Models to compile
|
26
37
|
# data for.
|
27
38
|
# @param byte_sleep [Integer, nil] Time to sleep after sending byte.
|
28
39
|
# @param packet_sleep [Integer, nil] Time to sleep after sending packet of bytes.
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: timex_datalink_client
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Maxwell Pray
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-09-
|
11
|
+
date: 2022-09-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: crc
|
@@ -87,8 +87,6 @@ extensions: []
|
|
87
87
|
extra_rdoc_files: []
|
88
88
|
files:
|
89
89
|
- lib/timex_datalink_client.rb
|
90
|
-
- lib/timex_datalink_client/alarm.rb
|
91
|
-
- lib/timex_datalink_client/eeprom.rb
|
92
90
|
- lib/timex_datalink_client/eeprom/anniversary.rb
|
93
91
|
- lib/timex_datalink_client/eeprom/appointment.rb
|
94
92
|
- lib/timex_datalink_client/eeprom/list.rb
|
@@ -99,14 +97,25 @@ files:
|
|
99
97
|
- lib/timex_datalink_client/helpers/crc_packets_wrapper.rb
|
100
98
|
- lib/timex_datalink_client/helpers/length_packet_wrapper.rb
|
101
99
|
- lib/timex_datalink_client/notebook_adapter.rb
|
102
|
-
- lib/timex_datalink_client/
|
103
|
-
- lib/timex_datalink_client/
|
104
|
-
- lib/timex_datalink_client/
|
100
|
+
- lib/timex_datalink_client/protocol_1/alarm.rb
|
101
|
+
- lib/timex_datalink_client/protocol_1/eeprom.rb
|
102
|
+
- lib/timex_datalink_client/protocol_1/end.rb
|
103
|
+
- lib/timex_datalink_client/protocol_1/start.rb
|
104
|
+
- lib/timex_datalink_client/protocol_1/sync.rb
|
105
|
+
- lib/timex_datalink_client/protocol_1/time.rb
|
106
|
+
- lib/timex_datalink_client/protocol_1/time_name.rb
|
107
|
+
- lib/timex_datalink_client/protocol_3/alarm.rb
|
108
|
+
- lib/timex_datalink_client/protocol_3/eeprom.rb
|
109
|
+
- lib/timex_datalink_client/protocol_3/end.rb
|
110
|
+
- lib/timex_datalink_client/protocol_3/sound_options.rb
|
111
|
+
- lib/timex_datalink_client/protocol_3/sound_theme.rb
|
112
|
+
- lib/timex_datalink_client/protocol_3/start.rb
|
113
|
+
- lib/timex_datalink_client/protocol_3/sync.rb
|
114
|
+
- lib/timex_datalink_client/protocol_3/time.rb
|
115
|
+
- lib/timex_datalink_client/protocol_3/wrist_app.rb
|
105
116
|
- lib/timex_datalink_client/sync.rb
|
106
|
-
- lib/timex_datalink_client/time.rb
|
107
117
|
- lib/timex_datalink_client/version.rb
|
108
|
-
|
109
|
-
homepage: https://github.com/synthead/timex_datalink_client/tree/v0.4.1
|
118
|
+
homepage: https://github.com/synthead/timex_datalink_client/tree/v0.5.0
|
110
119
|
licenses:
|
111
120
|
- MIT
|
112
121
|
metadata: {}
|
@@ -1,59 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "timex_datalink_client/helpers/char_encoders"
|
4
|
-
require "timex_datalink_client/helpers/crc_packets_wrapper"
|
5
|
-
|
6
|
-
class TimexDatalinkClient
|
7
|
-
class Alarm
|
8
|
-
include Helpers::CharEncoders
|
9
|
-
prepend Helpers::CrcPacketsWrapper
|
10
|
-
|
11
|
-
CPACKET_ALARM = [0x50]
|
12
|
-
|
13
|
-
MESSAGE_LENGTH = 8
|
14
|
-
|
15
|
-
attr_accessor :number, :audible, :time, :message
|
16
|
-
|
17
|
-
# Create an Alarm instance.
|
18
|
-
#
|
19
|
-
# @param number [Integer] Alarm number (from 1 to 5).
|
20
|
-
# @param audible [Boolean] Toggle alarm sounds.
|
21
|
-
# @param time [::Time] Time of alarm.
|
22
|
-
# @param message [String] Alarm message text.
|
23
|
-
# @return [Alarm] Alarm instance.
|
24
|
-
def initialize(number:, audible:, time:, message:)
|
25
|
-
@number = number
|
26
|
-
@audible = audible
|
27
|
-
@time = time
|
28
|
-
@message = message
|
29
|
-
end
|
30
|
-
|
31
|
-
# Compile packets for an alarm.
|
32
|
-
#
|
33
|
-
# @return [Array<Array<Integer>>] Two-dimensional array of integers that represent bytes.
|
34
|
-
def packets
|
35
|
-
[
|
36
|
-
[
|
37
|
-
CPACKET_ALARM,
|
38
|
-
number,
|
39
|
-
time.hour,
|
40
|
-
time.min,
|
41
|
-
0,
|
42
|
-
0,
|
43
|
-
message_characters,
|
44
|
-
audible_integer
|
45
|
-
].flatten
|
46
|
-
]
|
47
|
-
end
|
48
|
-
|
49
|
-
private
|
50
|
-
|
51
|
-
def message_characters
|
52
|
-
chars_for(message, length: 8, pad: true)
|
53
|
-
end
|
54
|
-
|
55
|
-
def audible_integer
|
56
|
-
audible ? 1 : 0
|
57
|
-
end
|
58
|
-
end
|
59
|
-
end
|
@@ -1,92 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "timex_datalink_client/helpers/cpacket_paginator"
|
4
|
-
require "timex_datalink_client/helpers/crc_packets_wrapper"
|
5
|
-
|
6
|
-
class TimexDatalinkClient
|
7
|
-
class Eeprom
|
8
|
-
include Helpers::CpacketPaginator
|
9
|
-
prepend Helpers::CrcPacketsWrapper
|
10
|
-
|
11
|
-
CPACKET_CLEAR = [0x93, 0x01]
|
12
|
-
CPACKET_SECT = [0x90, 0x01]
|
13
|
-
CPACKET_DATA = [0x91, 0x01]
|
14
|
-
CPACKET_END = [0x92, 0x01]
|
15
|
-
|
16
|
-
START_ADDRESS = 0x0236
|
17
|
-
APPOINTMENT_NO_NOTIFICATION = 0xff
|
18
|
-
|
19
|
-
attr_accessor :appointments, :anniversaries, :phone_numbers, :lists, :appointment_notification
|
20
|
-
|
21
|
-
# Create an Eeprom instance.
|
22
|
-
#
|
23
|
-
# @param appointments [Array<Appointment>] Appointments to be added to EEPROM data.
|
24
|
-
# @param anniversaries [Array<Anniversary>] Anniversaries to be added to EEPROM data.
|
25
|
-
# @param phone_numbers [Array<PhoneNumber>] Phone numbers to be added to EEPROM data.
|
26
|
-
# @param lists [Array<List>] Lists to be added to EEPROM data.
|
27
|
-
# @param appointment_notification [Integer] Appointment notification (intervals of 15 minutes, 255 for no
|
28
|
-
# notification)
|
29
|
-
# @return [Eeprom] Eeprom instance.
|
30
|
-
def initialize(appointments: [], anniversaries: [], phone_numbers: [], lists: [], appointment_notification: APPOINTMENT_NO_NOTIFICATION)
|
31
|
-
@appointments = appointments
|
32
|
-
@anniversaries = anniversaries
|
33
|
-
@phone_numbers = phone_numbers
|
34
|
-
@lists = lists
|
35
|
-
@appointment_notification = appointment_notification
|
36
|
-
end
|
37
|
-
|
38
|
-
# Compile packets for EEPROM data.
|
39
|
-
#
|
40
|
-
# @return [Array<Array<Integer>>] Two-dimensional array of integers that represent bytes.
|
41
|
-
def packets
|
42
|
-
[CPACKET_CLEAR, header] + payloads + [CPACKET_END]
|
43
|
-
end
|
44
|
-
|
45
|
-
private
|
46
|
-
|
47
|
-
def header
|
48
|
-
[
|
49
|
-
CPACKET_SECT,
|
50
|
-
payloads.length,
|
51
|
-
items_addresses,
|
52
|
-
items_lengths,
|
53
|
-
earliest_appointment_year,
|
54
|
-
appointment_notification
|
55
|
-
].flatten
|
56
|
-
end
|
57
|
-
|
58
|
-
def payloads
|
59
|
-
paginate_cpackets(header: CPACKET_DATA, cpackets: all_packets)
|
60
|
-
end
|
61
|
-
|
62
|
-
def all_items
|
63
|
-
[appointments, lists, phone_numbers, anniversaries]
|
64
|
-
end
|
65
|
-
|
66
|
-
def all_packets
|
67
|
-
all_items.flatten.map(&:packet).flatten
|
68
|
-
end
|
69
|
-
|
70
|
-
def items_addresses
|
71
|
-
address = START_ADDRESS
|
72
|
-
|
73
|
-
all_items.each_with_object([]) do |items, addresses|
|
74
|
-
addresses.concat(address.divmod(256))
|
75
|
-
|
76
|
-
address += items.sum { |item| item.packet.length }
|
77
|
-
end
|
78
|
-
end
|
79
|
-
|
80
|
-
def items_lengths
|
81
|
-
all_items.map(&:length)
|
82
|
-
end
|
83
|
-
|
84
|
-
def earliest_appointment_year
|
85
|
-
earliest_appointment = appointments.min_by(&:time)
|
86
|
-
|
87
|
-
return 0 unless earliest_appointment
|
88
|
-
|
89
|
-
earliest_appointment.time.year % 100
|
90
|
-
end
|
91
|
-
end
|
92
|
-
end
|
@@ -1,40 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "timex_datalink_client/helpers/crc_packets_wrapper"
|
4
|
-
|
5
|
-
class TimexDatalinkClient
|
6
|
-
class SoundOptions
|
7
|
-
prepend Helpers::CrcPacketsWrapper
|
8
|
-
|
9
|
-
CPACKET_BEEPS = [0x71]
|
10
|
-
|
11
|
-
attr_accessor :hourly_chime, :button_beep
|
12
|
-
|
13
|
-
# Create a SoundOptions instance.
|
14
|
-
#
|
15
|
-
# @param hourly_chime [Boolean] Toggle hourly chime sounds.
|
16
|
-
# @param button_beep [Boolean] Toggle button beep sounds.
|
17
|
-
# @return [SoundOptions] SoundOptions instance.
|
18
|
-
def initialize(hourly_chime:, button_beep:)
|
19
|
-
@hourly_chime = hourly_chime
|
20
|
-
@button_beep = button_beep
|
21
|
-
end
|
22
|
-
|
23
|
-
# Compile packets for sound options.
|
24
|
-
#
|
25
|
-
# @return [Array<Array<Integer>>] Two-dimensional array of integers that represent bytes.
|
26
|
-
def packets
|
27
|
-
[
|
28
|
-
CPACKET_BEEPS + [hourly_chime_integer, button_beep_integer]
|
29
|
-
]
|
30
|
-
end
|
31
|
-
|
32
|
-
def hourly_chime_integer
|
33
|
-
hourly_chime ? 1 : 0
|
34
|
-
end
|
35
|
-
|
36
|
-
def button_beep_integer
|
37
|
-
button_beep ? 1 : 0
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|
@@ -1,62 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "timex_datalink_client/helpers/cpacket_paginator"
|
4
|
-
require "timex_datalink_client/helpers/crc_packets_wrapper"
|
5
|
-
|
6
|
-
class TimexDatalinkClient
|
7
|
-
class SoundTheme
|
8
|
-
include Helpers::CpacketPaginator
|
9
|
-
prepend Helpers::CrcPacketsWrapper
|
10
|
-
|
11
|
-
CPACKET_SECT = [0x90, 0x03]
|
12
|
-
CPACKET_DATA = [0x91, 0x03]
|
13
|
-
CPACKET_END = [0x92, 0x03]
|
14
|
-
|
15
|
-
SOUND_DATA_HEADER = "\x25\x04\x19\x69"
|
16
|
-
|
17
|
-
attr_accessor :spc_file
|
18
|
-
|
19
|
-
# Create a SoundTheme instance.
|
20
|
-
#
|
21
|
-
# @param sound_theme_data [String, nil] Sound theme data.
|
22
|
-
# @param spc_file [String, nil] Path to SPC file.
|
23
|
-
# @return [SoundTheme] SoundTheme instance.
|
24
|
-
def initialize(sound_theme_data: nil, spc_file: nil)
|
25
|
-
@sound_theme_data = sound_theme_data
|
26
|
-
@spc_file = spc_file
|
27
|
-
end
|
28
|
-
|
29
|
-
# Compile packets for a sound theme.
|
30
|
-
#
|
31
|
-
# @return [Array<Array<Integer>>] Two-dimensional array of integers that represent bytes.
|
32
|
-
def packets
|
33
|
-
[load_sect] + payloads + [CPACKET_END]
|
34
|
-
end
|
35
|
-
|
36
|
-
private
|
37
|
-
|
38
|
-
def load_sect
|
39
|
-
CPACKET_SECT + [payloads.length, offset]
|
40
|
-
end
|
41
|
-
|
42
|
-
def payloads
|
43
|
-
paginate_cpackets(header: CPACKET_DATA, cpackets: sound_theme_data.bytes)
|
44
|
-
end
|
45
|
-
|
46
|
-
def sound_theme_data
|
47
|
-
@sound_theme_data || spc_file_data_without_header
|
48
|
-
end
|
49
|
-
|
50
|
-
def spc_file_data
|
51
|
-
File.open(spc_file, "rb").read
|
52
|
-
end
|
53
|
-
|
54
|
-
def spc_file_data_without_header
|
55
|
-
spc_file_data.delete_prefix(SOUND_DATA_HEADER)
|
56
|
-
end
|
57
|
-
|
58
|
-
def offset
|
59
|
-
0x100 - sound_theme_data.bytesize
|
60
|
-
end
|
61
|
-
end
|
62
|
-
end
|
@@ -1,18 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "timex_datalink_client/helpers/crc_packets_wrapper"
|
4
|
-
|
5
|
-
class TimexDatalinkClient
|
6
|
-
class Start
|
7
|
-
prepend Helpers::CrcPacketsWrapper
|
8
|
-
|
9
|
-
CPACKET_START = [0x20, 0x00, 0x00, 0x03]
|
10
|
-
|
11
|
-
# Compile packets for data start command.
|
12
|
-
#
|
13
|
-
# @return [Array<Array<Integer>>] Two-dimensional array of integers that represent bytes.
|
14
|
-
def packets
|
15
|
-
[CPACKET_START]
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
@@ -1,75 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "timex_datalink_client/helpers/char_encoders"
|
4
|
-
require "timex_datalink_client/helpers/crc_packets_wrapper"
|
5
|
-
|
6
|
-
class TimexDatalinkClient
|
7
|
-
class Time
|
8
|
-
include Helpers::CharEncoders
|
9
|
-
prepend Helpers::CrcPacketsWrapper
|
10
|
-
|
11
|
-
CPACKET_TIME = [0x32]
|
12
|
-
|
13
|
-
attr_accessor :zone, :is_24h, :date_format, :time
|
14
|
-
|
15
|
-
# Create a Time instance.
|
16
|
-
#
|
17
|
-
# @param zone [Integer] Time zone number (1 or 2).
|
18
|
-
# @param is_24h [Boolean] Toggle 24 hour time.
|
19
|
-
# @param date_format [Integer] Date format.
|
20
|
-
# @param time [::Time] Time to set (including time zone).
|
21
|
-
# @param name [String, nil] Name of time zone (defaults to zone from time; 3 chars max)
|
22
|
-
# @return [Time] Time instance.
|
23
|
-
def initialize(zone:, is_24h:, date_format:, time:, name: nil)
|
24
|
-
@zone = zone
|
25
|
-
@is_24h = is_24h
|
26
|
-
@date_format = date_format
|
27
|
-
@time = time
|
28
|
-
@name = name
|
29
|
-
end
|
30
|
-
|
31
|
-
# Compile packets for a time.
|
32
|
-
#
|
33
|
-
# @return [Array<Array<Integer>>] Two-dimensional array of integers that represent bytes.
|
34
|
-
def packets
|
35
|
-
[
|
36
|
-
[
|
37
|
-
CPACKET_TIME,
|
38
|
-
zone,
|
39
|
-
time.sec,
|
40
|
-
time.hour,
|
41
|
-
time.min,
|
42
|
-
time.month,
|
43
|
-
time.day,
|
44
|
-
year_mod_1900,
|
45
|
-
name_characters,
|
46
|
-
wday_from_monday,
|
47
|
-
is_24h_value,
|
48
|
-
date_format
|
49
|
-
].flatten
|
50
|
-
]
|
51
|
-
end
|
52
|
-
|
53
|
-
private
|
54
|
-
|
55
|
-
def name
|
56
|
-
@name || time.zone.downcase
|
57
|
-
end
|
58
|
-
|
59
|
-
def name_characters
|
60
|
-
chars_for(name, length: 3, pad: true)
|
61
|
-
end
|
62
|
-
|
63
|
-
def year_mod_1900
|
64
|
-
time.year % 100
|
65
|
-
end
|
66
|
-
|
67
|
-
def wday_from_monday
|
68
|
-
(time.wday + 6) % 7
|
69
|
-
end
|
70
|
-
|
71
|
-
def is_24h_value
|
72
|
-
is_24h ? 2 : 1
|
73
|
-
end
|
74
|
-
end
|
75
|
-
end
|
@@ -1,64 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "timex_datalink_client/helpers/cpacket_paginator"
|
4
|
-
require "timex_datalink_client/helpers/crc_packets_wrapper"
|
5
|
-
|
6
|
-
class TimexDatalinkClient
|
7
|
-
class WristApp
|
8
|
-
include Helpers::CpacketPaginator
|
9
|
-
prepend Helpers::CrcPacketsWrapper
|
10
|
-
|
11
|
-
CPACKET_CLEAR = [0x93, 0x02]
|
12
|
-
CPACKET_SECT = [0x90, 0x02]
|
13
|
-
CPACKET_DATA = [0x91, 0x02]
|
14
|
-
CPACKET_END = [0x92, 0x02]
|
15
|
-
|
16
|
-
WRIST_APP_DELIMITER = /\xac.*\r\n/n
|
17
|
-
WRIST_APP_CODE_INDEX = 8
|
18
|
-
|
19
|
-
attr_accessor :zap_file
|
20
|
-
|
21
|
-
# Create a WristApp instance.
|
22
|
-
#
|
23
|
-
# @param wrist_app_data [String, nil] WristApp data.
|
24
|
-
# @param zap_file [String, nil] Path to ZAP file.
|
25
|
-
# @return [WristApp] WristApp instance.
|
26
|
-
def initialize(wrist_app_data: nil, zap_file: nil)
|
27
|
-
@wrist_app_data = wrist_app_data
|
28
|
-
@zap_file = zap_file
|
29
|
-
end
|
30
|
-
|
31
|
-
# Compile packets for an alarm.
|
32
|
-
#
|
33
|
-
# @return [Array<Array<Integer>>] Two-dimensional array of integers that represent bytes.
|
34
|
-
def packets
|
35
|
-
[CPACKET_CLEAR, cpacket_sect] + payloads + [CPACKET_END]
|
36
|
-
end
|
37
|
-
|
38
|
-
private
|
39
|
-
|
40
|
-
def cpacket_sect
|
41
|
-
CPACKET_SECT + [payloads.length, 1]
|
42
|
-
end
|
43
|
-
|
44
|
-
def payloads
|
45
|
-
paginate_cpackets(header: CPACKET_DATA, cpackets: wrist_app_data.bytes)
|
46
|
-
end
|
47
|
-
|
48
|
-
def wrist_app_data
|
49
|
-
@wrist_app_data || zap_file_data_binary
|
50
|
-
end
|
51
|
-
|
52
|
-
def zap_file_data
|
53
|
-
File.open(zap_file, "rb").read
|
54
|
-
end
|
55
|
-
|
56
|
-
def zap_file_data_ascii
|
57
|
-
zap_file_data.split(WRIST_APP_DELIMITER)[WRIST_APP_CODE_INDEX]
|
58
|
-
end
|
59
|
-
|
60
|
-
def zap_file_data_binary
|
61
|
-
[zap_file_data_ascii].pack("H*")
|
62
|
-
end
|
63
|
-
end
|
64
|
-
end
|