timex_datalink_client 0.11.0 → 0.12.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/char_encoders.rb +5 -0
- data/lib/timex_datalink_client/protocol_1/time_name.rb +6 -2
- data/lib/timex_datalink_client/protocol_3/time.rb +5 -5
- data/lib/timex_datalink_client/protocol_4/time.rb +5 -5
- data/lib/timex_datalink_client/protocol_6/alarm.rb +124 -0
- data/lib/timex_datalink_client/protocol_6/eeprom/phone_number.rb +75 -0
- data/lib/timex_datalink_client/protocol_6/eeprom.rb +68 -0
- data/lib/timex_datalink_client/protocol_6/end.rb +20 -0
- data/lib/timex_datalink_client/protocol_6/night_mode_options.rb +59 -0
- data/lib/timex_datalink_client/protocol_6/pager_options.rb +89 -0
- data/lib/timex_datalink_client/protocol_6/sound_scroll_options.rb +58 -0
- data/lib/timex_datalink_client/protocol_6/start.rb +20 -0
- data/lib/timex_datalink_client/protocol_6/sync.rb +41 -0
- data/lib/timex_datalink_client/protocol_6/time.rb +203 -0
- data/lib/timex_datalink_client/protocol_9/time_name.rb +6 -2
- data/lib/timex_datalink_client/version.rb +1 -1
- data/lib/timex_datalink_client.rb +11 -0
- metadata +14 -88
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6b3a3f3ffde31a9f937f60f6ebba23851aeacc62d49b5677f7769f7392a9a1ea
|
4
|
+
data.tar.gz: 5a9f3acd574998d9bf430225459bb7f98f2954b5e1f6fff038a240145c5ffef5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 93da0a4e3153cbeb4feaae86574a25034e315d82182833f5b7822796d00cc6d4dbc8f57830bde9e906b6e21471a6829808f0e621b432937314cfefb2090d52f7
|
7
|
+
data.tar.gz: b4c516c8b2db51e393b60324ed0d723f00562f34823a6e43c62b07c276b6bfae7edaa9c4f8ab338af6b2fe395afed38729f4e072381d977baef6371c08370802
|
@@ -4,6 +4,7 @@ class TimexDatalinkClient
|
|
4
4
|
class Helpers
|
5
5
|
module CharEncoders
|
6
6
|
CHARS = "0123456789abcdefghijklmnopqrstuvwxyz !\"#$%&'()*+,-./:\\;=@?_|<>[]"
|
7
|
+
CHARS_PROTOCOL_6 = "0123456789 abcdefghijklmnopqrstuvwxyz!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~"
|
7
8
|
EEPROM_CHARS = "0123456789abcdefghijklmnopqrstuvwxyz !\"#$%&'()*+,-./:\\;=@?_|<>["
|
8
9
|
PHONE_CHARS = "0123456789cfhpw "
|
9
10
|
INVALID_CHAR = " "
|
@@ -19,6 +20,10 @@ class TimexDatalinkClient
|
|
19
20
|
end
|
20
21
|
end
|
21
22
|
|
23
|
+
def protocol_6_chars_for(string_chars, length: nil, pad: false)
|
24
|
+
chars_for(string_chars, char_map: CHARS_PROTOCOL_6, length:, pad:)
|
25
|
+
end
|
26
|
+
|
22
27
|
def eeprom_chars_for(string_chars, length: 31)
|
23
28
|
chars = chars_for(string_chars, char_map: EEPROM_CHARS, length:).append(EEPROM_TERMINATOR)
|
24
29
|
|
@@ -24,7 +24,7 @@ class TimexDatalinkClient
|
|
24
24
|
# Create a TimeName instance.
|
25
25
|
#
|
26
26
|
# @param zone [Integer] Time zone number (1 or 2).
|
27
|
-
# @param name [String] Name of time zone (3 chars max)
|
27
|
+
# @param name [String] Name of time zone (3 chars max).
|
28
28
|
# @return [TimeName] TimeName instance.
|
29
29
|
def initialize(zone:, name:)
|
30
30
|
@zone = zone
|
@@ -49,8 +49,12 @@ class TimexDatalinkClient
|
|
49
49
|
|
50
50
|
private
|
51
51
|
|
52
|
+
def name_formatted
|
53
|
+
name || "tz#{zone}"
|
54
|
+
end
|
55
|
+
|
52
56
|
def name_characters
|
53
|
-
chars_for(
|
57
|
+
chars_for(name_formatted, length: 3, pad: true)
|
54
58
|
end
|
55
59
|
end
|
56
60
|
end
|
@@ -33,7 +33,7 @@ class TimexDatalinkClient
|
|
33
33
|
message: "%{value} is invalid! Valid date formats are #{DATE_FORMAT_MAP.keys}."
|
34
34
|
}
|
35
35
|
|
36
|
-
attr_accessor :zone, :is_24h, :date_format, :time
|
36
|
+
attr_accessor :zone, :is_24h, :date_format, :time, :name
|
37
37
|
|
38
38
|
# Create a Time instance.
|
39
39
|
#
|
@@ -42,7 +42,7 @@ class TimexDatalinkClient
|
|
42
42
|
# @param date_format ["%_m-%d-%y", "%_d-%m-%y", "%y-%m-%d", "%_m.%d.%y", "%_d.%m.%y", "%y.%m.%d"] Date format
|
43
43
|
# (represented by Time#strftime format).
|
44
44
|
# @param time [::Time] Time to set (including time zone).
|
45
|
-
# @param name [String, nil] Name of time zone (defaults to zone from time; 3 chars max)
|
45
|
+
# @param name [String, nil] Name of time zone (defaults to zone from time; 3 chars max).
|
46
46
|
# @return [Time] Time instance.
|
47
47
|
def initialize(zone:, is_24h:, date_format:, time:, name: nil)
|
48
48
|
@zone = zone
|
@@ -79,12 +79,12 @@ class TimexDatalinkClient
|
|
79
79
|
|
80
80
|
private
|
81
81
|
|
82
|
-
def
|
83
|
-
|
82
|
+
def name_formatted
|
83
|
+
name || time.zone || "tz#{zone}"
|
84
84
|
end
|
85
85
|
|
86
86
|
def name_characters
|
87
|
-
chars_for(
|
87
|
+
chars_for(name_formatted, length: 3, pad: true)
|
88
88
|
end
|
89
89
|
|
90
90
|
def year_mod_1900
|
@@ -33,7 +33,7 @@ class TimexDatalinkClient
|
|
33
33
|
message: "%{value} is invalid! Valid date formats are #{DATE_FORMAT_MAP.keys}."
|
34
34
|
}
|
35
35
|
|
36
|
-
attr_accessor :zone, :is_24h, :date_format, :time
|
36
|
+
attr_accessor :zone, :is_24h, :date_format, :time, :name
|
37
37
|
|
38
38
|
# Create a Time instance.
|
39
39
|
#
|
@@ -42,7 +42,7 @@ class TimexDatalinkClient
|
|
42
42
|
# @param date_format ["%_m-%d-%y", "%_d-%m-%y", "%y-%m-%d", "%_m.%d.%y", "%_d.%m.%y", "%y.%m.%d"] Date format
|
43
43
|
# (represented by Time#strftime format).
|
44
44
|
# @param time [::Time] Time to set (including time zone).
|
45
|
-
# @param name [String, nil] Name of time zone (defaults to zone from time; 3 chars max)
|
45
|
+
# @param name [String, nil] Name of time zone (defaults to zone from time; 3 chars max).
|
46
46
|
# @return [Time] Time instance.
|
47
47
|
def initialize(zone:, is_24h:, date_format:, time:, name: nil)
|
48
48
|
@zone = zone
|
@@ -79,12 +79,12 @@ class TimexDatalinkClient
|
|
79
79
|
|
80
80
|
private
|
81
81
|
|
82
|
-
def
|
83
|
-
|
82
|
+
def name_formatted
|
83
|
+
name || time.zone || "tz#{zone}"
|
84
84
|
end
|
85
85
|
|
86
86
|
def name_characters
|
87
|
-
chars_for(
|
87
|
+
chars_for(name_formatted, length: 3, pad: true)
|
88
88
|
end
|
89
89
|
|
90
90
|
def year_mod_1900
|
@@ -0,0 +1,124 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_model"
|
4
|
+
|
5
|
+
require "timex_datalink_client/helpers/char_encoders"
|
6
|
+
require "timex_datalink_client/helpers/crc_packets_wrapper"
|
7
|
+
|
8
|
+
class TimexDatalinkClient
|
9
|
+
class Protocol6
|
10
|
+
class Alarm
|
11
|
+
include ActiveModel::Validations
|
12
|
+
include Helpers::CharEncoders
|
13
|
+
prepend Helpers::CrcPacketsWrapper
|
14
|
+
|
15
|
+
CPACKET_ALARM = 0x51
|
16
|
+
|
17
|
+
VALID_DAYS_IN_MONTH = {
|
18
|
+
1 => 1..31,
|
19
|
+
2 => 1..29,
|
20
|
+
3 => 1..31,
|
21
|
+
4 => 1..30,
|
22
|
+
5 => 1..31,
|
23
|
+
6 => 1..30,
|
24
|
+
7 => 1..31,
|
25
|
+
8 => 1..31,
|
26
|
+
9 => 1..30,
|
27
|
+
10 => 1..31,
|
28
|
+
11 => 1..30,
|
29
|
+
12 => 1..31
|
30
|
+
}.freeze
|
31
|
+
|
32
|
+
ALARM_STATUS_MAP = {
|
33
|
+
disarmed: 0,
|
34
|
+
armed: 1,
|
35
|
+
unused: 2
|
36
|
+
}.freeze
|
37
|
+
|
38
|
+
DEFAULT_TIME = Time.new(0, 1, 1, 6, 0)
|
39
|
+
|
40
|
+
attr_accessor :number, :status, :time, :message, :month, :day
|
41
|
+
|
42
|
+
validates :number, inclusion: {
|
43
|
+
in: 1..8,
|
44
|
+
message: "value %{value} is invalid! Valid number values are 1..8."
|
45
|
+
}
|
46
|
+
|
47
|
+
validates :status, inclusion: {
|
48
|
+
in: ALARM_STATUS_MAP.keys,
|
49
|
+
message: "%{value} is invalid! Valid date formats are #{ALARM_STATUS_MAP.keys}."
|
50
|
+
}
|
51
|
+
|
52
|
+
validates :month, inclusion: {
|
53
|
+
in: 1..12,
|
54
|
+
allow_nil: true,
|
55
|
+
message: "%{value} is invalid! Valid months are 1..12 and nil."
|
56
|
+
}
|
57
|
+
|
58
|
+
validates :day, inclusion: {
|
59
|
+
if: ->(alarm) { alarm.month.nil? },
|
60
|
+
in: 1..31,
|
61
|
+
allow_nil: true,
|
62
|
+
message: "%{value} is invalid! Valid days are 1..31 and nil."
|
63
|
+
}
|
64
|
+
|
65
|
+
validates :day, inclusion: {
|
66
|
+
if: ->(alarm) { alarm.day && alarm.month },
|
67
|
+
in: ->(alarm) { VALID_DAYS_IN_MONTH[alarm.month] },
|
68
|
+
message: ->(alarm, _attributes) do
|
69
|
+
"#{alarm.day} is invalid for month #{alarm.month}! " \
|
70
|
+
"Valid days are #{VALID_DAYS_IN_MONTH[alarm.month]} and nil when month is #{alarm.month}."
|
71
|
+
end
|
72
|
+
}
|
73
|
+
|
74
|
+
# Create an Alarm instance.
|
75
|
+
#
|
76
|
+
# @param number [Integer] Alarm number (from 1 to 8).
|
77
|
+
# @param status [Symbol] Alarm status (:armed, :disarmed, or :unused).
|
78
|
+
# @param time [::Time] Time of alarm.
|
79
|
+
# @param message [String] Alarm message text.
|
80
|
+
# @param month [Integer, nil] Month of alarm.
|
81
|
+
# @param day [Integer, nil] Day of alarm.
|
82
|
+
# @return [Alarm] Alarm instance.
|
83
|
+
def initialize(number:, status:, time: DEFAULT_TIME, message: "", month: nil, day: nil)
|
84
|
+
@number = number
|
85
|
+
@status = status
|
86
|
+
@time = time
|
87
|
+
@message = message
|
88
|
+
@month = month
|
89
|
+
@day = day
|
90
|
+
end
|
91
|
+
|
92
|
+
# Compile packets for an alarm.
|
93
|
+
#
|
94
|
+
# @raise [ActiveModel::ValidationError] One or more model values are invalid.
|
95
|
+
# @return [Array<Array<Integer>>] Two-dimensional array of integers that represent bytes.
|
96
|
+
def packets
|
97
|
+
validate!
|
98
|
+
|
99
|
+
[
|
100
|
+
[
|
101
|
+
CPACKET_ALARM,
|
102
|
+
number,
|
103
|
+
time.hour,
|
104
|
+
time.min,
|
105
|
+
month.to_i,
|
106
|
+
day.to_i,
|
107
|
+
status_formatted,
|
108
|
+
message_characters,
|
109
|
+
].flatten
|
110
|
+
]
|
111
|
+
end
|
112
|
+
|
113
|
+
private
|
114
|
+
|
115
|
+
def message_characters
|
116
|
+
protocol_6_chars_for(message, length: 16, pad: true)
|
117
|
+
end
|
118
|
+
|
119
|
+
def status_formatted
|
120
|
+
ALARM_STATUS_MAP[status]
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "timex_datalink_client/helpers/char_encoders"
|
4
|
+
require "timex_datalink_client/helpers/length_packet_wrapper"
|
5
|
+
|
6
|
+
class TimexDatalinkClient
|
7
|
+
class Protocol6
|
8
|
+
class Eeprom
|
9
|
+
class PhoneNumber
|
10
|
+
include Helpers::CharEncoders
|
11
|
+
prepend Helpers::LengthPacketWrapper
|
12
|
+
|
13
|
+
PHONE_DIGITS = 12
|
14
|
+
NAME_MAX_LENGTH = 31
|
15
|
+
|
16
|
+
NUMBER_NAME_DELIMITER = "-"
|
17
|
+
NUMBER_NAME_MAX_NUMBER_LENGTH = 30
|
18
|
+
|
19
|
+
TERMINATOR = 0x5c
|
20
|
+
|
21
|
+
attr_accessor :name, :number, :type
|
22
|
+
|
23
|
+
# Create a PhoneNumber instance.
|
24
|
+
#
|
25
|
+
# @param name [String] Name associated to phone number.
|
26
|
+
# @param number [String] Phone number text.
|
27
|
+
# @param type [String] Phone number type.
|
28
|
+
# @return [PhoneNumber] PhoneNumber instance.
|
29
|
+
def initialize(name:, number:, type: " ")
|
30
|
+
@name = name
|
31
|
+
@number = number
|
32
|
+
@type = type
|
33
|
+
end
|
34
|
+
|
35
|
+
# Compile a packet for a phone number.
|
36
|
+
#
|
37
|
+
# @return [Array<Integer>] Array of integers that represent bytes.
|
38
|
+
def packet
|
39
|
+
[
|
40
|
+
number_with_type_characters,
|
41
|
+
name_characters,
|
42
|
+
TERMINATOR
|
43
|
+
].flatten
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
def number_with_type_characters
|
49
|
+
phone_chars_for(number_with_type_padded)
|
50
|
+
end
|
51
|
+
|
52
|
+
def name_characters
|
53
|
+
return protocol_6_chars_for(name_with_number) if number.length > PHONE_DIGITS
|
54
|
+
|
55
|
+
protocol_6_chars_for(name, length: NAME_MAX_LENGTH)
|
56
|
+
end
|
57
|
+
|
58
|
+
def number_with_type_padded
|
59
|
+
number_with_type = "#{number} #{type}"
|
60
|
+
number_with_type.rjust(PHONE_DIGITS)
|
61
|
+
end
|
62
|
+
|
63
|
+
def name_with_number
|
64
|
+
number_name = NUMBER_NAME_DELIMITER
|
65
|
+
number_name += number[PHONE_DIGITS..NUMBER_NAME_MAX_NUMBER_LENGTH - 1]
|
66
|
+
|
67
|
+
name_length = NUMBER_NAME_MAX_NUMBER_LENGTH - number_name.length
|
68
|
+
truncated_name = name[..name_length - 1]
|
69
|
+
|
70
|
+
"#{truncated_name}#{number_name}"
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "timex_datalink_client/helpers/cpacket_paginator"
|
4
|
+
require "timex_datalink_client/helpers/crc_packets_wrapper"
|
5
|
+
require "timex_datalink_client/helpers/lsb_msb_formatter"
|
6
|
+
|
7
|
+
class TimexDatalinkClient
|
8
|
+
class Protocol6
|
9
|
+
class Eeprom
|
10
|
+
include Helpers::CpacketPaginator
|
11
|
+
include Helpers::LsbMsbFormatter
|
12
|
+
prepend Helpers::CrcPacketsWrapper
|
13
|
+
|
14
|
+
CPACKET_CLEAR = [0x93, 0x01]
|
15
|
+
CPACKET_SECT = [0x90, 0x01]
|
16
|
+
CPACKET_DATA = [0x91, 0x01]
|
17
|
+
CPACKET_END = [0x92, 0x01]
|
18
|
+
|
19
|
+
CPACKET_DATA_LENGTH = 32
|
20
|
+
|
21
|
+
attr_accessor :phone_numbers
|
22
|
+
|
23
|
+
# Create an Eeprom instance.
|
24
|
+
#
|
25
|
+
# @param phone_numbers [Array<PhoneNumber>] Phone numbers to be added to EEPROM data.
|
26
|
+
# @return [Eeprom] Eeprom instance.
|
27
|
+
def initialize(phone_numbers: [])
|
28
|
+
@phone_numbers = phone_numbers
|
29
|
+
end
|
30
|
+
|
31
|
+
# Compile packets for EEPROM data.
|
32
|
+
#
|
33
|
+
# @return [Array<Array<Integer>>] Two-dimensional array of integers that represent bytes.
|
34
|
+
def packets
|
35
|
+
[CPACKET_CLEAR, header] + payloads + [CPACKET_END]
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
def header
|
41
|
+
[
|
42
|
+
CPACKET_SECT,
|
43
|
+
payloads_length,
|
44
|
+
0x04,
|
45
|
+
phone_numbers_length,
|
46
|
+
].flatten
|
47
|
+
end
|
48
|
+
|
49
|
+
def payloads
|
50
|
+
paginate_cpackets(header: CPACKET_DATA, length: CPACKET_DATA_LENGTH, cpackets: all_packets)
|
51
|
+
end
|
52
|
+
|
53
|
+
def all_packets
|
54
|
+
phone_numbers.map(&:packet).flatten
|
55
|
+
end
|
56
|
+
|
57
|
+
def payloads_length
|
58
|
+
lsb_msb_format_for(payloads.length)
|
59
|
+
end
|
60
|
+
|
61
|
+
def phone_numbers_length
|
62
|
+
length_lsb = lsb_msb_format_for(phone_numbers.length).first
|
63
|
+
|
64
|
+
[length_lsb, 0]
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
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 Protocol6
|
7
|
+
class End
|
8
|
+
prepend Helpers::CrcPacketsWrapper
|
9
|
+
|
10
|
+
CPACKET_SKIP = [0x21]
|
11
|
+
|
12
|
+
# Compile packets for data end command.
|
13
|
+
#
|
14
|
+
# @return [Array<Array<Integer>>] Two-dimensional array of integers that represent bytes.
|
15
|
+
def packets
|
16
|
+
[CPACKET_SKIP]
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "timex_datalink_client/helpers/crc_packets_wrapper"
|
4
|
+
|
5
|
+
class TimexDatalinkClient
|
6
|
+
class Protocol6
|
7
|
+
class NightModeOptions
|
8
|
+
include ActiveModel::Validations
|
9
|
+
prepend Helpers::CrcPacketsWrapper
|
10
|
+
|
11
|
+
CPACKET_NIGHT_MODE = 0x72
|
12
|
+
|
13
|
+
validates :night_mode_deactivate_hours, inclusion: {
|
14
|
+
in: 3..12,
|
15
|
+
message: "%{value} is invalid! Valid night mode deactivate hour values are 3..12."
|
16
|
+
}
|
17
|
+
|
18
|
+
validates :indiglo_timeout_seconds, inclusion: {
|
19
|
+
in: 3..10,
|
20
|
+
message: "%{value} is invalid! Valid Indiglo timeout second values are 3..10."
|
21
|
+
}
|
22
|
+
|
23
|
+
attr_accessor :night_mode_deactivate_hours, :indiglo_timeout_seconds, :night_mode_on_notification
|
24
|
+
|
25
|
+
# Create a NightModeOptions instance.
|
26
|
+
#
|
27
|
+
# @param night_mode_deactivate_hours [Integer] Automatically deactivate night mode after specified hours.
|
28
|
+
# @param indiglo_timeout_seconds [Integer] Turn Indiglo light off after specified seconds after each button push.
|
29
|
+
# @param night_mode_on_notification [Boolean] Toggle activating night mode on any pager or alarm event.
|
30
|
+
# @return [NightModeOptions] NightModeOptions instance.
|
31
|
+
def initialize(night_mode_deactivate_hours: 8, indiglo_timeout_seconds: 4, night_mode_on_notification: false)
|
32
|
+
@night_mode_deactivate_hours = night_mode_deactivate_hours
|
33
|
+
@indiglo_timeout_seconds = indiglo_timeout_seconds
|
34
|
+
@night_mode_on_notification = night_mode_on_notification
|
35
|
+
end
|
36
|
+
|
37
|
+
# Compile packets for night mode options.
|
38
|
+
#
|
39
|
+
# @raise [ActiveModel::ValidationError] One or more model values are invalid.
|
40
|
+
# @return [Array<Array<Integer>>] Two-dimensional array of integers that represent bytes.
|
41
|
+
def packets
|
42
|
+
validate!
|
43
|
+
|
44
|
+
[
|
45
|
+
[
|
46
|
+
CPACKET_NIGHT_MODE,
|
47
|
+
night_mode_on_notification_formatted,
|
48
|
+
night_mode_deactivate_hours,
|
49
|
+
indiglo_timeout_seconds
|
50
|
+
]
|
51
|
+
]
|
52
|
+
end
|
53
|
+
|
54
|
+
def night_mode_on_notification_formatted
|
55
|
+
night_mode_on_notification ? 1 : 0
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "timex_datalink_client/helpers/crc_packets_wrapper"
|
4
|
+
|
5
|
+
class TimexDatalinkClient
|
6
|
+
class Protocol6
|
7
|
+
class PagerOptions
|
8
|
+
include ActiveModel::Validations
|
9
|
+
prepend Helpers::CrcPacketsWrapper
|
10
|
+
|
11
|
+
CPACKET_PAGER = 0x73
|
12
|
+
ALERT_SOUND_SILENT = 6
|
13
|
+
|
14
|
+
validates :on_hour, inclusion: {
|
15
|
+
in: 0..23,
|
16
|
+
message: "%{value} is invalid! Valid on hour values are 0..23."
|
17
|
+
}
|
18
|
+
|
19
|
+
validates :on_minute, inclusion: {
|
20
|
+
in: 0..59,
|
21
|
+
message: "%{value} is invalid! Valid on minute values are 0..59."
|
22
|
+
}
|
23
|
+
|
24
|
+
validates :off_hour, inclusion: {
|
25
|
+
in: 0..23,
|
26
|
+
message: "%{value} is invalid! Valid off hour values are 0..23."
|
27
|
+
}
|
28
|
+
|
29
|
+
validates :off_minute, inclusion: {
|
30
|
+
in: 0..59,
|
31
|
+
message: "%{value} is invalid! Valid off minute values are 0..59."
|
32
|
+
}
|
33
|
+
|
34
|
+
validates :alert_sound, inclusion: {
|
35
|
+
in: 0..5,
|
36
|
+
allow_nil: true,
|
37
|
+
message: "%{value} is invalid! Valid alert sound values are 0..5 and nil."
|
38
|
+
}
|
39
|
+
|
40
|
+
attr_accessor :auto_on_off, :on_hour, :on_minute, :off_hour, :off_minute, :alert_sound
|
41
|
+
|
42
|
+
# Create a PagerOptions instance.
|
43
|
+
#
|
44
|
+
# @param auto_on_off [Boolean] Toggle turning pager on and off every day.
|
45
|
+
# @param on_hour [Integer] Hour to turn pager on at.
|
46
|
+
# @param on_minute [Integer] Minute to turn pager on at.
|
47
|
+
# @param off_hour [Integer] Hour to turn pager off at.
|
48
|
+
# @param off_minute [Integer] Minute to turn pager off at.
|
49
|
+
# @param alert_sound [Integer, nil] Pager alert sound (0 to 5 or nil for silent).
|
50
|
+
# @return [PagerOptions] PagerOptions instance.
|
51
|
+
def initialize(auto_on_off: false, on_hour: 0, on_minute: 0, off_hour: 0, off_minute: 0, alert_sound: 0)
|
52
|
+
@auto_on_off = auto_on_off
|
53
|
+
@on_hour = on_hour
|
54
|
+
@on_minute = on_minute
|
55
|
+
@off_hour = off_hour
|
56
|
+
@off_minute = off_minute
|
57
|
+
@alert_sound = alert_sound
|
58
|
+
end
|
59
|
+
|
60
|
+
# Compile packets for pager options.
|
61
|
+
#
|
62
|
+
# @raise [ActiveModel::ValidationError] One or more model values are invalid.
|
63
|
+
# @return [Array<Array<Integer>>] Two-dimensional array of integers that represent bytes.
|
64
|
+
def packets
|
65
|
+
validate!
|
66
|
+
|
67
|
+
[
|
68
|
+
[
|
69
|
+
CPACKET_PAGER,
|
70
|
+
auto_on_off_formatted,
|
71
|
+
on_hour,
|
72
|
+
on_minute,
|
73
|
+
off_hour,
|
74
|
+
off_minute,
|
75
|
+
alert_sound_formatted
|
76
|
+
]
|
77
|
+
]
|
78
|
+
end
|
79
|
+
|
80
|
+
def auto_on_off_formatted
|
81
|
+
auto_on_off ? 1 : 0
|
82
|
+
end
|
83
|
+
|
84
|
+
def alert_sound_formatted
|
85
|
+
alert_sound || ALERT_SOUND_SILENT
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "timex_datalink_client/helpers/crc_packets_wrapper"
|
4
|
+
|
5
|
+
class TimexDatalinkClient
|
6
|
+
class Protocol6
|
7
|
+
class SoundScrollOptions
|
8
|
+
include ActiveModel::Validations
|
9
|
+
prepend Helpers::CrcPacketsWrapper
|
10
|
+
|
11
|
+
CPACKET_SOUND_SCROLL = 0x71
|
12
|
+
|
13
|
+
validates :scroll_speed, inclusion: {
|
14
|
+
in: 0..2,
|
15
|
+
message: "%{value} is invalid! Valid scroll speed values are 0..2."
|
16
|
+
}
|
17
|
+
|
18
|
+
attr_accessor :hourly_chime, :button_beep, :scroll_speed
|
19
|
+
|
20
|
+
# Create a SoundScrollOptions instance.
|
21
|
+
#
|
22
|
+
# @param hourly_chime [Boolean] Toggle hourly chime.
|
23
|
+
# @param button_beep [Boolean] Toggle button beep.
|
24
|
+
# @param scroll_speed [Integer] Message scroll speed (0 to 2).
|
25
|
+
# @return [SoundScrollOptions] SoundScrollOptions instance.
|
26
|
+
def initialize(hourly_chime: false, button_beep: false, scroll_speed: 1)
|
27
|
+
@hourly_chime = hourly_chime
|
28
|
+
@button_beep = button_beep
|
29
|
+
@scroll_speed = scroll_speed
|
30
|
+
end
|
31
|
+
|
32
|
+
# Compile packets for sound and scroll options.
|
33
|
+
#
|
34
|
+
# @raise [ActiveModel::ValidationError] One or more model values are invalid.
|
35
|
+
# @return [Array<Array<Integer>>] Two-dimensional array of integers that represent bytes.
|
36
|
+
def packets
|
37
|
+
validate!
|
38
|
+
|
39
|
+
[
|
40
|
+
[
|
41
|
+
CPACKET_SOUND_SCROLL,
|
42
|
+
hourly_chime_formatted,
|
43
|
+
button_beep_formatted,
|
44
|
+
scroll_speed
|
45
|
+
]
|
46
|
+
]
|
47
|
+
end
|
48
|
+
|
49
|
+
def hourly_chime_formatted
|
50
|
+
hourly_chime ? 1 : 0
|
51
|
+
end
|
52
|
+
|
53
|
+
def button_beep_formatted
|
54
|
+
button_beep ? 1 : 0
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
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 Protocol6
|
7
|
+
class Start
|
8
|
+
prepend Helpers::CrcPacketsWrapper
|
9
|
+
|
10
|
+
CPACKET_START = [0x20, 0x00, 0x00, 0x06]
|
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,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class TimexDatalinkClient
|
4
|
+
class Protocol6
|
5
|
+
class Sync
|
6
|
+
PING_BYTE = [0x78]
|
7
|
+
FAST_MODE_BYTE = [0x56]
|
8
|
+
SYNC_1_BYTE = [0x55]
|
9
|
+
SYNC_2_BYTE = [0xaa]
|
10
|
+
|
11
|
+
SYNC_2_LENGTH = 40
|
12
|
+
|
13
|
+
attr_accessor :length
|
14
|
+
|
15
|
+
# Create a Sync instance.
|
16
|
+
#
|
17
|
+
# @param length [Integer] Number of 0x55 sync bytes to use.
|
18
|
+
# @return [Sync] Sync instance.
|
19
|
+
def initialize(length: 300)
|
20
|
+
@length = length
|
21
|
+
end
|
22
|
+
|
23
|
+
# Compile packets for syncronization data.
|
24
|
+
#
|
25
|
+
# @return [Array<Array<Integer>>] Two-dimensional array of integers that represent bytes.
|
26
|
+
def packets
|
27
|
+
[PING_BYTE + FAST_MODE_BYTE + render_sync_1 + render_sync_2]
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def render_sync_1
|
33
|
+
SYNC_1_BYTE * length
|
34
|
+
end
|
35
|
+
|
36
|
+
def render_sync_2
|
37
|
+
SYNC_2_BYTE * SYNC_2_LENGTH
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,203 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_model"
|
4
|
+
|
5
|
+
require "timex_datalink_client/helpers/char_encoders"
|
6
|
+
require "timex_datalink_client/helpers/crc_packets_wrapper"
|
7
|
+
|
8
|
+
class TimexDatalinkClient
|
9
|
+
class Protocol6
|
10
|
+
class Time
|
11
|
+
include ActiveModel::Validations
|
12
|
+
include Helpers::CharEncoders
|
13
|
+
prepend Helpers::CrcPacketsWrapper
|
14
|
+
|
15
|
+
CPACKET_TIME = [0x32].freeze
|
16
|
+
CPACKET_FLEX_TIME = [0x33].freeze
|
17
|
+
|
18
|
+
ZONE_OFFSET_MAP = {
|
19
|
+
-39600 => 0x15,
|
20
|
+
-36000 => 0x16,
|
21
|
+
-32400 => 0x17,
|
22
|
+
-28800 => 0x18,
|
23
|
+
-25200 => 0x19,
|
24
|
+
-21600 => 0x1a,
|
25
|
+
-18000 => 0x1b,
|
26
|
+
-14400 => 0x1c,
|
27
|
+
-12600 => 0x14,
|
28
|
+
-10800 => 0x1d,
|
29
|
+
-7200 => 0x1e,
|
30
|
+
-3600 => 0x1f,
|
31
|
+
0 => 0x00,
|
32
|
+
3600 => 0x01,
|
33
|
+
7200 => 0x02,
|
34
|
+
10800 => 0x03,
|
35
|
+
12600 => 0x0d,
|
36
|
+
14400 => 0x04,
|
37
|
+
16200 => 0x0e,
|
38
|
+
18000 => 0x05,
|
39
|
+
19800 => 0x0f,
|
40
|
+
20700 => 0x11,
|
41
|
+
21600 => 0x06,
|
42
|
+
23400 => 0x12,
|
43
|
+
25200 => 0x07,
|
44
|
+
28800 => 0x08,
|
45
|
+
32400 => 0x09,
|
46
|
+
34200 => 0x13,
|
47
|
+
36000 => 0x0a,
|
48
|
+
39600 => 0x0b,
|
49
|
+
43200 => 0x0c
|
50
|
+
}.freeze
|
51
|
+
|
52
|
+
FLEX_TIME_ZONE = 0x10
|
53
|
+
FLEX_DST_VALUE = 0x08
|
54
|
+
|
55
|
+
DATE_FORMAT_MAP = {
|
56
|
+
"%_m-%d-%y" => 0x00,
|
57
|
+
"%_d-%m-%y" => 0x01,
|
58
|
+
"%y-%m-%d" => 0x02,
|
59
|
+
"%_m.%d.%y" => 0x04,
|
60
|
+
"%_d.%m.%y" => 0x05,
|
61
|
+
"%y.%m.%d" => 0x06
|
62
|
+
}.freeze
|
63
|
+
|
64
|
+
validates :zone, inclusion: {
|
65
|
+
in: 1..2,
|
66
|
+
message: "%{value} is invalid! Valid zones are 1..2."
|
67
|
+
}
|
68
|
+
|
69
|
+
validates :date_format, inclusion: {
|
70
|
+
in: DATE_FORMAT_MAP.keys,
|
71
|
+
message: "%{value} is invalid! Valid date formats are #{DATE_FORMAT_MAP.keys}."
|
72
|
+
}
|
73
|
+
|
74
|
+
validates :flex_time_zone, unless: :flex_time, inclusion: {
|
75
|
+
in: [false],
|
76
|
+
message: "cannot be enabled unless FLEXtime is also enabled."
|
77
|
+
}
|
78
|
+
|
79
|
+
validates :flex_dst, unless: :flex_time, inclusion: {
|
80
|
+
in: [false],
|
81
|
+
message: "cannot be enabled unless FLEXtime is also enabled."
|
82
|
+
}
|
83
|
+
|
84
|
+
attr_accessor :zone, :is_24h, :date_format, :time, :name, :flex_time, :flex_time_zone, :flex_dst
|
85
|
+
|
86
|
+
# Create a Time instance.
|
87
|
+
#
|
88
|
+
# @param zone [Integer] Time zone number (1 or 2).
|
89
|
+
# @param is_24h [Boolean] Toggle 24 hour time.
|
90
|
+
# @param date_format ["%_m-%d-%y", "%_d-%m-%y", "%y-%m-%d", "%_m.%d.%y", "%_d.%m.%y", "%y.%m.%d"] Date format
|
91
|
+
# (represented by Time#strftime format).
|
92
|
+
# @param time [::Time] Time to set (including time zone).
|
93
|
+
# @param name [String, nil] Name of time zone (defaults to zone from time; 3 chars max).
|
94
|
+
# @param flex_time [Boolean] Toggle using FLEXtime to set time and date.
|
95
|
+
# @param flex_time_zone [Boolean] Toggle using FLEXtime to set time zone.
|
96
|
+
# @param flex_dst [Boolean] Toggle using FLEXtime to apply daylight savings time offset.
|
97
|
+
# @return [Time] Time instance.
|
98
|
+
def initialize(
|
99
|
+
zone:, is_24h:, date_format:, time:, name: nil, flex_time: false, flex_time_zone: false, flex_dst: false
|
100
|
+
)
|
101
|
+
@zone = zone
|
102
|
+
@is_24h = is_24h
|
103
|
+
@date_format = date_format
|
104
|
+
@time = time
|
105
|
+
@name = name
|
106
|
+
@flex_time = flex_time
|
107
|
+
@flex_time_zone = flex_time_zone
|
108
|
+
@flex_dst = flex_dst
|
109
|
+
end
|
110
|
+
|
111
|
+
# Compile packets for a time.
|
112
|
+
#
|
113
|
+
# @raise [ActiveModel::ValidationError] One or more model values are invalid.
|
114
|
+
# @return [Array<Array<Integer>>] Two-dimensional array of integers that represent bytes.
|
115
|
+
def packets
|
116
|
+
validate!
|
117
|
+
|
118
|
+
[
|
119
|
+
[
|
120
|
+
cpacket,
|
121
|
+
zone,
|
122
|
+
second,
|
123
|
+
hour,
|
124
|
+
minute,
|
125
|
+
month,
|
126
|
+
day,
|
127
|
+
year_mod_1900,
|
128
|
+
name_characters,
|
129
|
+
wday_from_monday,
|
130
|
+
formatted_time_zone,
|
131
|
+
is_24h_value,
|
132
|
+
date_format_value
|
133
|
+
].flatten
|
134
|
+
]
|
135
|
+
end
|
136
|
+
|
137
|
+
private
|
138
|
+
|
139
|
+
def cpacket
|
140
|
+
flex_time ? CPACKET_FLEX_TIME : CPACKET_TIME
|
141
|
+
end
|
142
|
+
|
143
|
+
def second
|
144
|
+
flex_time ? 0 : formatted_time.sec
|
145
|
+
end
|
146
|
+
|
147
|
+
def hour
|
148
|
+
flex_time ? 0 : formatted_time.hour
|
149
|
+
end
|
150
|
+
|
151
|
+
def minute
|
152
|
+
flex_time ? 0 : formatted_time.min
|
153
|
+
end
|
154
|
+
|
155
|
+
def month
|
156
|
+
flex_time ? 0 : formatted_time.month
|
157
|
+
end
|
158
|
+
|
159
|
+
def day
|
160
|
+
flex_time ? 0 : formatted_time.day
|
161
|
+
end
|
162
|
+
|
163
|
+
def formatted_name
|
164
|
+
name || time.zone || "tz#{zone}"
|
165
|
+
end
|
166
|
+
|
167
|
+
def name_characters
|
168
|
+
protocol_6_chars_for(formatted_name, length: 3, pad: true)
|
169
|
+
end
|
170
|
+
|
171
|
+
def year_mod_1900
|
172
|
+
flex_time ? 0 : formatted_time.year % 100
|
173
|
+
end
|
174
|
+
|
175
|
+
def wday_from_monday
|
176
|
+
flex_time ? 0 : (formatted_time.wday + 6) % 7
|
177
|
+
end
|
178
|
+
|
179
|
+
def formatted_time
|
180
|
+
time.dst? ? time + 3600 : time
|
181
|
+
end
|
182
|
+
|
183
|
+
def formatted_utc_offset
|
184
|
+
time.dst? ? time.utc_offset - 3600 : time.utc_offset
|
185
|
+
end
|
186
|
+
|
187
|
+
def formatted_time_zone
|
188
|
+
flex_time_zone ? FLEX_TIME_ZONE : ZONE_OFFSET_MAP[formatted_utc_offset]
|
189
|
+
end
|
190
|
+
|
191
|
+
def is_24h_value
|
192
|
+
is_24h ? 2 : 1
|
193
|
+
end
|
194
|
+
|
195
|
+
def date_format_value
|
196
|
+
format = DATE_FORMAT_MAP.fetch(date_format)
|
197
|
+
format += FLEX_DST_VALUE if flex_dst
|
198
|
+
|
199
|
+
format
|
200
|
+
end
|
201
|
+
end
|
202
|
+
end
|
203
|
+
end
|
@@ -24,7 +24,7 @@ class TimexDatalinkClient
|
|
24
24
|
# Create a TimeName instance.
|
25
25
|
#
|
26
26
|
# @param zone [Integer] Time zone number (1 or 2).
|
27
|
-
# @param name [String] Name of time zone (3 chars max)
|
27
|
+
# @param name [String] Name of time zone (3 chars max).
|
28
28
|
# @return [TimeName] TimeName instance.
|
29
29
|
def initialize(zone:, name:)
|
30
30
|
@zone = zone
|
@@ -49,8 +49,12 @@ class TimexDatalinkClient
|
|
49
49
|
|
50
50
|
private
|
51
51
|
|
52
|
+
def name_formatted
|
53
|
+
name || "tz#{zone}"
|
54
|
+
end
|
55
|
+
|
52
56
|
def name_characters
|
53
|
-
chars_for(
|
57
|
+
chars_for(name_formatted, length: 3, pad: true)
|
54
58
|
end
|
55
59
|
end
|
56
60
|
end
|
@@ -43,6 +43,17 @@ require "timex_datalink_client/protocol_4/sync"
|
|
43
43
|
require "timex_datalink_client/protocol_4/time"
|
44
44
|
require "timex_datalink_client/protocol_4/wrist_app"
|
45
45
|
|
46
|
+
require "timex_datalink_client/protocol_6/alarm"
|
47
|
+
require "timex_datalink_client/protocol_6/eeprom"
|
48
|
+
require "timex_datalink_client/protocol_6/eeprom/phone_number"
|
49
|
+
require "timex_datalink_client/protocol_6/end"
|
50
|
+
require "timex_datalink_client/protocol_6/night_mode_options"
|
51
|
+
require "timex_datalink_client/protocol_6/pager_options"
|
52
|
+
require "timex_datalink_client/protocol_6/sound_scroll_options"
|
53
|
+
require "timex_datalink_client/protocol_6/start"
|
54
|
+
require "timex_datalink_client/protocol_6/sync"
|
55
|
+
require "timex_datalink_client/protocol_6/time"
|
56
|
+
|
46
57
|
require "timex_datalink_client/protocol_7/eeprom"
|
47
58
|
require "timex_datalink_client/protocol_7/eeprom/activity"
|
48
59
|
require "timex_datalink_client/protocol_7/eeprom/calendar"
|
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.12.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:
|
11
|
+
date: 2023-07-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activemodel
|
@@ -66,90 +66,6 @@ dependencies:
|
|
66
66
|
- - "~>"
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: 0.6.0
|
69
|
-
- !ruby/object:Gem::Dependency
|
70
|
-
name: mdl
|
71
|
-
requirement: !ruby/object:Gem::Requirement
|
72
|
-
requirements:
|
73
|
-
- - "~>"
|
74
|
-
- !ruby/object:Gem::Version
|
75
|
-
version: 0.12.0
|
76
|
-
type: :development
|
77
|
-
prerelease: false
|
78
|
-
version_requirements: !ruby/object:Gem::Requirement
|
79
|
-
requirements:
|
80
|
-
- - "~>"
|
81
|
-
- !ruby/object:Gem::Version
|
82
|
-
version: 0.12.0
|
83
|
-
- !ruby/object:Gem::Dependency
|
84
|
-
name: rspec
|
85
|
-
requirement: !ruby/object:Gem::Requirement
|
86
|
-
requirements:
|
87
|
-
- - "~>"
|
88
|
-
- !ruby/object:Gem::Version
|
89
|
-
version: 3.11.0
|
90
|
-
type: :development
|
91
|
-
prerelease: false
|
92
|
-
version_requirements: !ruby/object:Gem::Requirement
|
93
|
-
requirements:
|
94
|
-
- - "~>"
|
95
|
-
- !ruby/object:Gem::Version
|
96
|
-
version: 3.11.0
|
97
|
-
- !ruby/object:Gem::Dependency
|
98
|
-
name: rubocop
|
99
|
-
requirement: !ruby/object:Gem::Requirement
|
100
|
-
requirements:
|
101
|
-
- - "~>"
|
102
|
-
- !ruby/object:Gem::Version
|
103
|
-
version: 1.41.1
|
104
|
-
type: :development
|
105
|
-
prerelease: false
|
106
|
-
version_requirements: !ruby/object:Gem::Requirement
|
107
|
-
requirements:
|
108
|
-
- - "~>"
|
109
|
-
- !ruby/object:Gem::Version
|
110
|
-
version: 1.41.1
|
111
|
-
- !ruby/object:Gem::Dependency
|
112
|
-
name: rubocop-github
|
113
|
-
requirement: !ruby/object:Gem::Requirement
|
114
|
-
requirements:
|
115
|
-
- - "~>"
|
116
|
-
- !ruby/object:Gem::Version
|
117
|
-
version: 0.20.0
|
118
|
-
type: :development
|
119
|
-
prerelease: false
|
120
|
-
version_requirements: !ruby/object:Gem::Requirement
|
121
|
-
requirements:
|
122
|
-
- - "~>"
|
123
|
-
- !ruby/object:Gem::Version
|
124
|
-
version: 0.20.0
|
125
|
-
- !ruby/object:Gem::Dependency
|
126
|
-
name: tzinfo
|
127
|
-
requirement: !ruby/object:Gem::Requirement
|
128
|
-
requirements:
|
129
|
-
- - "~>"
|
130
|
-
- !ruby/object:Gem::Version
|
131
|
-
version: 2.0.5
|
132
|
-
type: :development
|
133
|
-
prerelease: false
|
134
|
-
version_requirements: !ruby/object:Gem::Requirement
|
135
|
-
requirements:
|
136
|
-
- - "~>"
|
137
|
-
- !ruby/object:Gem::Version
|
138
|
-
version: 2.0.5
|
139
|
-
- !ruby/object:Gem::Dependency
|
140
|
-
name: yard-junk
|
141
|
-
requirement: !ruby/object:Gem::Requirement
|
142
|
-
requirements:
|
143
|
-
- - "~>"
|
144
|
-
- !ruby/object:Gem::Version
|
145
|
-
version: 0.0.9
|
146
|
-
type: :development
|
147
|
-
prerelease: false
|
148
|
-
version_requirements: !ruby/object:Gem::Requirement
|
149
|
-
requirements:
|
150
|
-
- - "~>"
|
151
|
-
- !ruby/object:Gem::Version
|
152
|
-
version: 0.0.9
|
153
69
|
description:
|
154
70
|
email: synthead@gmail.com
|
155
71
|
executables: []
|
@@ -201,6 +117,16 @@ files:
|
|
201
117
|
- lib/timex_datalink_client/protocol_4/sync.rb
|
202
118
|
- lib/timex_datalink_client/protocol_4/time.rb
|
203
119
|
- lib/timex_datalink_client/protocol_4/wrist_app.rb
|
120
|
+
- lib/timex_datalink_client/protocol_6/alarm.rb
|
121
|
+
- lib/timex_datalink_client/protocol_6/eeprom.rb
|
122
|
+
- lib/timex_datalink_client/protocol_6/eeprom/phone_number.rb
|
123
|
+
- lib/timex_datalink_client/protocol_6/end.rb
|
124
|
+
- lib/timex_datalink_client/protocol_6/night_mode_options.rb
|
125
|
+
- lib/timex_datalink_client/protocol_6/pager_options.rb
|
126
|
+
- lib/timex_datalink_client/protocol_6/sound_scroll_options.rb
|
127
|
+
- lib/timex_datalink_client/protocol_6/start.rb
|
128
|
+
- lib/timex_datalink_client/protocol_6/sync.rb
|
129
|
+
- lib/timex_datalink_client/protocol_6/time.rb
|
204
130
|
- lib/timex_datalink_client/protocol_7/eeprom.rb
|
205
131
|
- lib/timex_datalink_client/protocol_7/eeprom/activity.rb
|
206
132
|
- lib/timex_datalink_client/protocol_7/eeprom/calendar.rb
|
@@ -224,7 +150,7 @@ files:
|
|
224
150
|
- lib/timex_datalink_client/protocol_9/time_name.rb
|
225
151
|
- lib/timex_datalink_client/protocol_9/timer.rb
|
226
152
|
- lib/timex_datalink_client/version.rb
|
227
|
-
homepage: https://github.com/synthead/timex_datalink_client/tree/v0.
|
153
|
+
homepage: https://github.com/synthead/timex_datalink_client/tree/v0.12.0
|
228
154
|
licenses:
|
229
155
|
- MIT
|
230
156
|
metadata: {}
|
@@ -243,7 +169,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
243
169
|
- !ruby/object:Gem::Version
|
244
170
|
version: '0'
|
245
171
|
requirements: []
|
246
|
-
rubygems_version: 3.
|
172
|
+
rubygems_version: 3.4.10
|
247
173
|
signing_key:
|
248
174
|
specification_version: 4
|
249
175
|
summary: Write data to Timex Datalink devices with an optical sensor
|