timex_datalink_client 0.1.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 +7 -0
- data/lib/timex_datalink_client/alarm.rb +47 -0
- data/lib/timex_datalink_client/eeprom/anniversary.rb +34 -0
- data/lib/timex_datalink_client/eeprom/appointment.rb +39 -0
- data/lib/timex_datalink_client/eeprom/list.rb +33 -0
- data/lib/timex_datalink_client/eeprom/phone_number.rb +47 -0
- data/lib/timex_datalink_client/eeprom.rb +80 -0
- data/lib/timex_datalink_client/end.rb +15 -0
- data/lib/timex_datalink_client/helpers/char_encoders.rb +38 -0
- data/lib/timex_datalink_client/helpers/cpacket_paginator.rb +17 -0
- data/lib/timex_datalink_client/helpers/crc_packets_wrapper.rb +28 -0
- data/lib/timex_datalink_client/helpers/length_packet_wrapper.rb +11 -0
- data/lib/timex_datalink_client/notebook_adapter.rb +34 -0
- data/lib/timex_datalink_client/sound_options.rb +24 -0
- data/lib/timex_datalink_client/sound_theme.rb +45 -0
- data/lib/timex_datalink_client/start.rb +15 -0
- data/lib/timex_datalink_client/sync.rb +30 -0
- data/lib/timex_datalink_client/time.rb +59 -0
- data/lib/timex_datalink_client/version.rb +5 -0
- data/lib/timex_datalink_client/wrist_app.rb +47 -0
- data/lib/timex_datalink_client.rb +40 -0
- metadata +118 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: b30f06f6a23f4312ee7167089c7e0704ef5f799b4c3f7a2be36d57b445074f46
|
4
|
+
data.tar.gz: f2a82191c18efa5a7c51b422ff6b8c0ad30589890eac654a47507ece261ec445
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 78ddeedea22f0d2476b934d84a0751e67c63c2528cdab1a077cf5a4ddde7310e716da02be053d7abfee90e17bd9110ea92d75f84df510b7acc79e81c814598c3
|
7
|
+
data.tar.gz: 9a4974b2abd86722dacc1d4badd802fcc3b7ac84fab8d27d2bc6f39c31269d0c188635cf4e89e55b189aa86c9290a5148e26925e9c9f15337503d539df01c838
|
@@ -0,0 +1,47 @@
|
|
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
|
+
def initialize(number:, audible:, time:, message:)
|
18
|
+
@number = number
|
19
|
+
@audible = audible
|
20
|
+
@time = time
|
21
|
+
@message = message
|
22
|
+
end
|
23
|
+
|
24
|
+
def packets
|
25
|
+
[
|
26
|
+
[
|
27
|
+
CPACKET_ALARM,
|
28
|
+
number,
|
29
|
+
time.hour,
|
30
|
+
time.min,
|
31
|
+
0,
|
32
|
+
0,
|
33
|
+
message_characters,
|
34
|
+
audible
|
35
|
+
].flatten
|
36
|
+
]
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
def message_characters
|
42
|
+
message_padded = message.ljust(MESSAGE_LENGTH)
|
43
|
+
|
44
|
+
chars_for(message_padded)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,34 @@
|
|
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 Eeprom
|
8
|
+
class Anniversary
|
9
|
+
include Helpers::CharEncoders
|
10
|
+
prepend Helpers::LengthPacketWrapper
|
11
|
+
|
12
|
+
attr_accessor :time, :anniversary
|
13
|
+
|
14
|
+
def initialize(time:, anniversary:)
|
15
|
+
@time = time
|
16
|
+
@anniversary = anniversary
|
17
|
+
end
|
18
|
+
|
19
|
+
def packet
|
20
|
+
[
|
21
|
+
time.month,
|
22
|
+
time.day,
|
23
|
+
anniversary_characters
|
24
|
+
].flatten
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def anniversary_characters
|
30
|
+
eeprom_chars_for(anniversary)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,39 @@
|
|
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 Eeprom
|
8
|
+
class Appointment
|
9
|
+
include Helpers::CharEncoders
|
10
|
+
prepend Helpers::LengthPacketWrapper
|
11
|
+
|
12
|
+
attr_accessor :time, :message
|
13
|
+
|
14
|
+
def initialize(time:, message:)
|
15
|
+
@time = time
|
16
|
+
@message = message
|
17
|
+
end
|
18
|
+
|
19
|
+
def packet
|
20
|
+
[
|
21
|
+
time.month,
|
22
|
+
time.day,
|
23
|
+
time_15m,
|
24
|
+
message_characters
|
25
|
+
].flatten
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def time_15m
|
31
|
+
time.hour * 4 + time.min / 15
|
32
|
+
end
|
33
|
+
|
34
|
+
def message_characters
|
35
|
+
eeprom_chars_for(message)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,33 @@
|
|
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 Eeprom
|
8
|
+
class List
|
9
|
+
include Helpers::CharEncoders
|
10
|
+
prepend Helpers::LengthPacketWrapper
|
11
|
+
|
12
|
+
attr_accessor :list_entry, :priority
|
13
|
+
|
14
|
+
def initialize(list_entry:, priority:)
|
15
|
+
@list_entry = list_entry
|
16
|
+
@priority = priority
|
17
|
+
end
|
18
|
+
|
19
|
+
def packet
|
20
|
+
[
|
21
|
+
priority,
|
22
|
+
list_entry_characters
|
23
|
+
].flatten
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def list_entry_characters
|
29
|
+
eeprom_chars_for(list_entry)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,47 @@
|
|
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 Eeprom
|
8
|
+
class PhoneNumber
|
9
|
+
include Helpers::CharEncoders
|
10
|
+
prepend Helpers::LengthPacketWrapper
|
11
|
+
|
12
|
+
PHONE_DIGITS = 12
|
13
|
+
|
14
|
+
attr_accessor :name, :number, :type
|
15
|
+
|
16
|
+
def initialize(name:, number:, type: " ")
|
17
|
+
@name = name
|
18
|
+
@number = number
|
19
|
+
@type = type
|
20
|
+
end
|
21
|
+
|
22
|
+
def packet
|
23
|
+
[
|
24
|
+
number_with_type_characters,
|
25
|
+
name_characters,
|
26
|
+
].flatten
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def number_with_type_truncated
|
32
|
+
number_with_type = "#{number} #{type}"
|
33
|
+
padded_number_with_type = number_with_type.rjust(PHONE_DIGITS)
|
34
|
+
|
35
|
+
padded_number_with_type[0..PHONE_DIGITS - 1]
|
36
|
+
end
|
37
|
+
|
38
|
+
def number_with_type_characters
|
39
|
+
phone_chars_for(number_with_type_truncated)
|
40
|
+
end
|
41
|
+
|
42
|
+
def name_characters
|
43
|
+
eeprom_chars_for(name)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,80 @@
|
|
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
|
+
def initialize(appointments: [], anniversaries: [], phone_numbers: [], lists: [], appointment_notification: APPOINTMENT_NO_NOTIFICATION)
|
22
|
+
@appointments = appointments
|
23
|
+
@anniversaries = anniversaries
|
24
|
+
@phone_numbers = phone_numbers
|
25
|
+
@lists = lists
|
26
|
+
@appointment_notification = appointment_notification
|
27
|
+
end
|
28
|
+
|
29
|
+
def packets
|
30
|
+
[CPACKET_CLEAR, header] + payloads + [CPACKET_END]
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def header
|
36
|
+
[
|
37
|
+
CPACKET_SECT,
|
38
|
+
payloads.length,
|
39
|
+
items_addresses,
|
40
|
+
items_lengths,
|
41
|
+
earliest_appointment_year,
|
42
|
+
appointment_notification
|
43
|
+
].flatten
|
44
|
+
end
|
45
|
+
|
46
|
+
def payloads
|
47
|
+
paginate_cpackets(header: CPACKET_DATA, cpackets: all_packets)
|
48
|
+
end
|
49
|
+
|
50
|
+
def all_items
|
51
|
+
[appointments, lists, phone_numbers, anniversaries]
|
52
|
+
end
|
53
|
+
|
54
|
+
def all_packets
|
55
|
+
all_items.flatten.map(&:packet).flatten
|
56
|
+
end
|
57
|
+
|
58
|
+
def items_addresses
|
59
|
+
address = START_ADDRESS
|
60
|
+
|
61
|
+
all_items.each_with_object([]) do |items, addresses|
|
62
|
+
addresses.concat(address.divmod(256))
|
63
|
+
|
64
|
+
address += items.sum { |item| item.packet.length }
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def items_lengths
|
69
|
+
all_items.map(&:length)
|
70
|
+
end
|
71
|
+
|
72
|
+
def earliest_appointment_year
|
73
|
+
earliest_appointment = appointments.min_by(&:time)
|
74
|
+
|
75
|
+
return 0 unless earliest_appointment
|
76
|
+
|
77
|
+
earliest_appointment.time.year % 100
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "timex_datalink_client/helpers/crc_packets_wrapper"
|
4
|
+
|
5
|
+
class TimexDatalinkClient
|
6
|
+
class End
|
7
|
+
prepend Helpers::CrcPacketsWrapper
|
8
|
+
|
9
|
+
CPACKET_SKIP = [0x21]
|
10
|
+
|
11
|
+
def packets
|
12
|
+
[CPACKET_SKIP]
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class TimexDatalinkClient
|
4
|
+
class Helpers
|
5
|
+
module CharEncoders
|
6
|
+
CHARS = "0123456789abcdefghijklmnopqrstuvwxyz !\"#$%&'()*+,-./:\\;=@?ABCDEF"
|
7
|
+
EEPROM_TERMINATOR = 0x3f
|
8
|
+
|
9
|
+
PHONE_CHARS = "0123456789cfhpw "
|
10
|
+
|
11
|
+
def chars_for(string_chars, char_map: CHARS)
|
12
|
+
string_chars.each_char.map do |string_char|
|
13
|
+
char_map.index(string_char)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def eeprom_chars_for(string_chars)
|
18
|
+
chars = chars_for(string_chars).append(EEPROM_TERMINATOR)
|
19
|
+
|
20
|
+
packed_int = chars.each_with_index.sum do |char, index|
|
21
|
+
char << (6 * index)
|
22
|
+
end
|
23
|
+
|
24
|
+
packed_int.digits(256)
|
25
|
+
end
|
26
|
+
|
27
|
+
def phone_chars_for(string_chars)
|
28
|
+
chars = chars_for(string_chars, char_map: PHONE_CHARS)
|
29
|
+
|
30
|
+
packed_int = chars.each_with_index.sum do |char, index|
|
31
|
+
char << (4 * index)
|
32
|
+
end
|
33
|
+
|
34
|
+
packed_int.digits(256)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class TimexDatalinkClient
|
4
|
+
class Helpers
|
5
|
+
module CpacketPaginator
|
6
|
+
ITEMS_PER_PACKET = 32
|
7
|
+
|
8
|
+
def paginate_cpackets(header:, cpackets:)
|
9
|
+
paginated_cpackets = cpackets.each_slice(ITEMS_PER_PACKET)
|
10
|
+
|
11
|
+
paginated_cpackets.map.with_index(1) do |paginated_cpacket, index|
|
12
|
+
header + [index] + paginated_cpacket
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "crc"
|
4
|
+
|
5
|
+
class TimexDatalinkClient
|
6
|
+
class Helpers
|
7
|
+
module CrcPacketsWrapper
|
8
|
+
def packets
|
9
|
+
super.map do |packet|
|
10
|
+
crc_header(packet) + packet + crc_footer(packet)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def crc_header(packet)
|
17
|
+
[packet.length + 3]
|
18
|
+
end
|
19
|
+
|
20
|
+
def crc_footer(packet)
|
21
|
+
crc_check = (crc_header(packet) + packet).pack("C*")
|
22
|
+
crc = CRC.crc16_arc(crc_check)
|
23
|
+
|
24
|
+
crc.divmod(256)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "rubyserial"
|
4
|
+
|
5
|
+
class TimexDatalinkClient
|
6
|
+
class NotebookAdapter
|
7
|
+
BYTE_SLEEP = 0.025
|
8
|
+
PACKET_SLEEP = 0.25
|
9
|
+
|
10
|
+
attr_accessor :serial_device
|
11
|
+
|
12
|
+
def initialize(serial_device)
|
13
|
+
@serial_device = serial_device
|
14
|
+
end
|
15
|
+
|
16
|
+
def write(packets)
|
17
|
+
packets.each do |packet|
|
18
|
+
packet.each do |byte|
|
19
|
+
serial.write(byte.chr)
|
20
|
+
|
21
|
+
sleep(BYTE_SLEEP)
|
22
|
+
end
|
23
|
+
|
24
|
+
sleep(PACKET_SLEEP)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def serial
|
31
|
+
@serial ||= Serial.new(serial_device)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,24 @@
|
|
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_chimes, :button_beep
|
12
|
+
|
13
|
+
def initialize(hourly_chimes:, button_beep:)
|
14
|
+
@hourly_chimes = hourly_chimes
|
15
|
+
@button_beep = button_beep
|
16
|
+
end
|
17
|
+
|
18
|
+
def packets
|
19
|
+
[
|
20
|
+
CPACKET_BEEPS + [hourly_chimes, button_beep]
|
21
|
+
]
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,45 @@
|
|
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 :sound_data
|
18
|
+
|
19
|
+
def initialize(sound_data:)
|
20
|
+
@sound_data = sound_data
|
21
|
+
end
|
22
|
+
|
23
|
+
def packets
|
24
|
+
[load_sect] + payloads + [CPACKET_END]
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def sound_bytes
|
30
|
+
sound_data.delete_prefix(SOUND_DATA_HEADER).bytes
|
31
|
+
end
|
32
|
+
|
33
|
+
def load_sect
|
34
|
+
CPACKET_SECT + [payloads.length, offset]
|
35
|
+
end
|
36
|
+
|
37
|
+
def payloads
|
38
|
+
paginate_cpackets(header: CPACKET_DATA, cpackets: sound_bytes)
|
39
|
+
end
|
40
|
+
|
41
|
+
def offset
|
42
|
+
0x100 - sound_bytes.length
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,15 @@
|
|
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
|
+
def packets
|
12
|
+
[CPACKET_START]
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class TimexDatalinkClient
|
4
|
+
class Sync
|
5
|
+
SYNC_1_BYTE = [0x55]
|
6
|
+
SYNC_2_BYTE = [0xaa]
|
7
|
+
|
8
|
+
SYNC_2_LENGTH = 40
|
9
|
+
|
10
|
+
attr_accessor :length
|
11
|
+
|
12
|
+
def initialize(length: 300)
|
13
|
+
@length = length
|
14
|
+
end
|
15
|
+
|
16
|
+
def packets
|
17
|
+
[render_sync_1 + render_sync_2]
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def render_sync_1
|
23
|
+
SYNC_1_BYTE * length
|
24
|
+
end
|
25
|
+
|
26
|
+
def render_sync_2
|
27
|
+
SYNC_2_BYTE * SYNC_2_LENGTH
|
28
|
+
end
|
29
|
+
end
|
30
|
+
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 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
|
+
def initialize(zone:, is_24h:, date_format:, time:)
|
16
|
+
@zone = zone
|
17
|
+
@is_24h = is_24h
|
18
|
+
@date_format = date_format
|
19
|
+
@time = time
|
20
|
+
end
|
21
|
+
|
22
|
+
def packets
|
23
|
+
[
|
24
|
+
[
|
25
|
+
CPACKET_TIME,
|
26
|
+
zone,
|
27
|
+
time.sec,
|
28
|
+
time.hour,
|
29
|
+
time.min,
|
30
|
+
time.month,
|
31
|
+
time.day,
|
32
|
+
year_mod_1900,
|
33
|
+
timezone_characters,
|
34
|
+
wday_from_monday,
|
35
|
+
is_24h_value,
|
36
|
+
date_format
|
37
|
+
].flatten
|
38
|
+
]
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def timezone_characters
|
44
|
+
chars_for(time.zone.downcase)
|
45
|
+
end
|
46
|
+
|
47
|
+
def year_mod_1900
|
48
|
+
time.year % 100
|
49
|
+
end
|
50
|
+
|
51
|
+
def wday_from_monday
|
52
|
+
(time.wday + 6) % 7
|
53
|
+
end
|
54
|
+
|
55
|
+
def is_24h_value
|
56
|
+
is_24h ? 2 : 1
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,47 @@
|
|
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 :wrist_app_data
|
20
|
+
|
21
|
+
def initialize(wrist_app_data:)
|
22
|
+
@wrist_app_data = wrist_app_data
|
23
|
+
end
|
24
|
+
|
25
|
+
def packets
|
26
|
+
[CPACKET_CLEAR, cpacket_sect] + payloads + [CPACKET_END]
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def cpacket_sect
|
32
|
+
CPACKET_SECT + [payloads.length, 1]
|
33
|
+
end
|
34
|
+
|
35
|
+
def wrist_app_ascii
|
36
|
+
wrist_app_data.split(WRIST_APP_DELIMITER)[WRIST_APP_CODE_INDEX]
|
37
|
+
end
|
38
|
+
|
39
|
+
def wrist_app_bytes
|
40
|
+
[wrist_app_ascii].pack("H*").bytes
|
41
|
+
end
|
42
|
+
|
43
|
+
def payloads
|
44
|
+
paginate_cpackets(header: CPACKET_DATA, cpackets: wrist_app_bytes)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "timex_datalink_client/alarm"
|
4
|
+
require "timex_datalink_client/eeprom"
|
5
|
+
require "timex_datalink_client/eeprom/anniversary"
|
6
|
+
require "timex_datalink_client/eeprom/appointment"
|
7
|
+
require "timex_datalink_client/eeprom/list"
|
8
|
+
require "timex_datalink_client/eeprom/phone_number"
|
9
|
+
require "timex_datalink_client/end"
|
10
|
+
require "timex_datalink_client/notebook_adapter"
|
11
|
+
require "timex_datalink_client/sound_options"
|
12
|
+
require "timex_datalink_client/sound_theme"
|
13
|
+
require "timex_datalink_client/start"
|
14
|
+
require "timex_datalink_client/sync"
|
15
|
+
require "timex_datalink_client/time"
|
16
|
+
require "timex_datalink_client/version"
|
17
|
+
require "timex_datalink_client/wrist_app"
|
18
|
+
|
19
|
+
class TimexDatalinkClient
|
20
|
+
attr_accessor :serial_device, :models
|
21
|
+
|
22
|
+
def initialize(serial_device:, models: [])
|
23
|
+
@serial_device = serial_device
|
24
|
+
@models = models
|
25
|
+
end
|
26
|
+
|
27
|
+
def write
|
28
|
+
notebook_adapter.write(packets)
|
29
|
+
end
|
30
|
+
|
31
|
+
def packets
|
32
|
+
models.map(&:packets).flatten(1)
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def notebook_adapter
|
38
|
+
@notebook_adapter ||= NotebookAdapter.new(serial_device)
|
39
|
+
end
|
40
|
+
end
|
metadata
ADDED
@@ -0,0 +1,118 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: timex_datalink_client
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Maxwell Pray
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2022-09-05 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: crc
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 0.4.2
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 0.4.2
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rubyserial
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 0.6.0
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 0.6.0
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 3.11.0
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 3.11.0
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: tzinfo
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 2.0.5
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: 2.0.5
|
69
|
+
description: Write data to Timex Datalink watches with an optical sensor
|
70
|
+
email: synthead@gmail.com
|
71
|
+
executables: []
|
72
|
+
extensions: []
|
73
|
+
extra_rdoc_files: []
|
74
|
+
files:
|
75
|
+
- lib/timex_datalink_client.rb
|
76
|
+
- lib/timex_datalink_client/alarm.rb
|
77
|
+
- lib/timex_datalink_client/eeprom.rb
|
78
|
+
- lib/timex_datalink_client/eeprom/anniversary.rb
|
79
|
+
- lib/timex_datalink_client/eeprom/appointment.rb
|
80
|
+
- lib/timex_datalink_client/eeprom/list.rb
|
81
|
+
- lib/timex_datalink_client/eeprom/phone_number.rb
|
82
|
+
- lib/timex_datalink_client/end.rb
|
83
|
+
- lib/timex_datalink_client/helpers/char_encoders.rb
|
84
|
+
- lib/timex_datalink_client/helpers/cpacket_paginator.rb
|
85
|
+
- lib/timex_datalink_client/helpers/crc_packets_wrapper.rb
|
86
|
+
- lib/timex_datalink_client/helpers/length_packet_wrapper.rb
|
87
|
+
- lib/timex_datalink_client/notebook_adapter.rb
|
88
|
+
- lib/timex_datalink_client/sound_options.rb
|
89
|
+
- lib/timex_datalink_client/sound_theme.rb
|
90
|
+
- lib/timex_datalink_client/start.rb
|
91
|
+
- lib/timex_datalink_client/sync.rb
|
92
|
+
- lib/timex_datalink_client/time.rb
|
93
|
+
- lib/timex_datalink_client/version.rb
|
94
|
+
- lib/timex_datalink_client/wrist_app.rb
|
95
|
+
homepage: https://github.com/synthead/timex_datalink_client
|
96
|
+
licenses:
|
97
|
+
- MIT
|
98
|
+
metadata: {}
|
99
|
+
post_install_message:
|
100
|
+
rdoc_options: []
|
101
|
+
require_paths:
|
102
|
+
- lib
|
103
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
104
|
+
requirements:
|
105
|
+
- - ">="
|
106
|
+
- !ruby/object:Gem::Version
|
107
|
+
version: '0'
|
108
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
109
|
+
requirements:
|
110
|
+
- - ">="
|
111
|
+
- !ruby/object:Gem::Version
|
112
|
+
version: '0'
|
113
|
+
requirements: []
|
114
|
+
rubygems_version: 3.3.7
|
115
|
+
signing_key:
|
116
|
+
specification_version: 4
|
117
|
+
summary: Library for optical Timex Datalink watches
|
118
|
+
test_files: []
|