timex_datalink_client 0.2.0 → 0.4.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: fab69b897b4f8d5bcb249c9e238d7cc2a4889598598528b7c2137eab7f68b93f
4
- data.tar.gz: 87d353f312b3ba49b75b6024b8bbecb8d858a64974876364fd5b510d9f74c21b
3
+ metadata.gz: 499c12fec3a8fae40770efc4173421e0a996b999a98a19a7e9ec64295628d757
4
+ data.tar.gz: 29b1bec826b2d5a2c25f7d7c9e47405760a2c08526e04f7f84084587dfec44c5
5
5
  SHA512:
6
- metadata.gz: 3104f3d9a9b9099a90b9899abc28f575c955633aca3ff7ca20483f425106fbd94e2da647702ccac620657a03fc96875a519f107c9d72fffbd0230d068c378695
7
- data.tar.gz: d3c9344aa520f93e797549112f54510c9ed358577dbaf797e0c87ce9d86427b4d2f59345a395dafed0b1224931bbeaa1a1b4ab301b8cb35a7afc762346b8d648
6
+ metadata.gz: 1278164bd72754ee49ad9d26b7cf3a953de3f164e6bb19a42a30a34528ed012b6d967f605aeb244b6554ca29541312edec4b4d2730c1fadfa38b9946d862e76e
7
+ data.tar.gz: ad536dfbf0e894b5474be3fc36c4c8b0387cdc47e7134c58c98e7c6978ac004a78b20c4f54059e63d8cc3accda0e7b2f60199920be8bdbe128d98afa62798727
@@ -14,6 +14,13 @@ class TimexDatalinkClient
14
14
 
15
15
  attr_accessor :number, :audible, :time, :message
16
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.
17
24
  def initialize(number:, audible:, time:, message:)
18
25
  @number = number
19
26
  @audible = audible
@@ -21,6 +28,9 @@ class TimexDatalinkClient
21
28
  @message = message
22
29
  end
23
30
 
31
+ # Compile packets for an alarm.
32
+ #
33
+ # @return [Array<Array<Integer>>] Two-dimensional array of integers that represent bytes.
24
34
  def packets
25
35
  [
26
36
  [
@@ -39,9 +49,7 @@ class TimexDatalinkClient
39
49
  private
40
50
 
41
51
  def message_characters
42
- message_padded = message.ljust(MESSAGE_LENGTH)
43
-
44
- chars_for(message_padded)
52
+ chars_for(message, length: 8, pad: true)
45
53
  end
46
54
 
47
55
  def audible_integer
@@ -11,11 +11,19 @@ class TimexDatalinkClient
11
11
 
12
12
  attr_accessor :time, :anniversary
13
13
 
14
+ # Create an Anniversary instance.
15
+ #
16
+ # @param time [::Time] Time of anniversary.
17
+ # @param anniversary [String] Anniversary text.
18
+ # @return [Anniversary] Anniversary instance.
14
19
  def initialize(time:, anniversary:)
15
20
  @time = time
16
21
  @anniversary = anniversary
17
22
  end
18
23
 
24
+ # Compile a packet for an anniversary.
25
+ #
26
+ # @return [Array<Integer>] Array of integers that represent bytes.
19
27
  def packet
20
28
  [
21
29
  time.month,
@@ -11,11 +11,19 @@ class TimexDatalinkClient
11
11
 
12
12
  attr_accessor :time, :message
13
13
 
14
+ # Create an Appointment instance.
15
+ #
16
+ # @param time [::Time] Time of appointment.
17
+ # @param message [String] Appointment text.
18
+ # @return [Appointment] Appointment instance.
14
19
  def initialize(time:, message:)
15
20
  @time = time
16
21
  @message = message
17
22
  end
18
23
 
24
+ # Compile a packet for an appointment.
25
+ #
26
+ # @return [Array<Integer>] Array of integers that represent bytes.
19
27
  def packet
20
28
  [
21
29
  time.month,
@@ -11,11 +11,19 @@ class TimexDatalinkClient
11
11
 
12
12
  attr_accessor :list_entry, :priority
13
13
 
14
+ # Create a List instance.
15
+ #
16
+ # @param list_entry [String] List entry text.
17
+ # @param priority [Integer] List priority.
18
+ # @return [List] List instance.
14
19
  def initialize(list_entry:, priority:)
15
20
  @list_entry = list_entry
16
21
  @priority = priority
17
22
  end
18
23
 
24
+ # Compile a packet for a list.
25
+ #
26
+ # @return [Array<Integer>] Array of integers that represent bytes.
19
27
  def packet
20
28
  [
21
29
  priority,
@@ -13,12 +13,21 @@ class TimexDatalinkClient
13
13
 
14
14
  attr_accessor :name, :number, :type
15
15
 
16
+ # Create a PhoneNumber instance.
17
+ #
18
+ # @param name [String] Name associated to phone number.
19
+ # @param number [String] Phone number text.
20
+ # @param type [String] Phone number type.
21
+ # @return [PhoneNumber] PhoneNumber instance.
16
22
  def initialize(name:, number:, type: " ")
17
23
  @name = name
18
24
  @number = number
19
25
  @type = type
20
26
  end
21
27
 
28
+ # Compile a packet for a phone number.
29
+ #
30
+ # @return [Array<Integer>] Array of integers that represent bytes.
22
31
  def packet
23
32
  [
24
33
  number_with_type_characters,
@@ -18,6 +18,15 @@ class TimexDatalinkClient
18
18
 
19
19
  attr_accessor :appointments, :anniversaries, :phone_numbers, :lists, :appointment_notification
20
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.
21
30
  def initialize(appointments: [], anniversaries: [], phone_numbers: [], lists: [], appointment_notification: APPOINTMENT_NO_NOTIFICATION)
22
31
  @appointments = appointments
23
32
  @anniversaries = anniversaries
@@ -26,6 +35,9 @@ class TimexDatalinkClient
26
35
  @appointment_notification = appointment_notification
27
36
  end
28
37
 
38
+ # Compile packets for EEPROM data.
39
+ #
40
+ # @return [Array<Array<Integer>>] Two-dimensional array of integers that represent bytes.
29
41
  def packets
30
42
  [CPACKET_CLEAR, header] + payloads + [CPACKET_END]
31
43
  end
@@ -8,6 +8,9 @@ class TimexDatalinkClient
8
8
 
9
9
  CPACKET_SKIP = [0x21]
10
10
 
11
+ # Compile packets for data end command.
12
+ #
13
+ # @return [Array<Array<Integer>>] Two-dimensional array of integers that represent bytes.
11
14
  def packets
12
15
  [CPACKET_SKIP]
13
16
  end
@@ -3,19 +3,23 @@
3
3
  class TimexDatalinkClient
4
4
  class Helpers
5
5
  module CharEncoders
6
- CHARS = "0123456789abcdefghijklmnopqrstuvwxyz !\"#$%&'()*+,-./:\\;=@?ABCDEF"
6
+ CHARS = "0123456789abcdefghijklmnopqrstuvwxyz !\"#$%&'()*+,-./:\\;=@?_|<>[]"
7
+
7
8
  EEPROM_TERMINATOR = 0x3f
8
9
 
9
10
  PHONE_CHARS = "0123456789cfhpw "
10
11
 
11
- def chars_for(string_chars, char_map: CHARS)
12
- string_chars.each_char.map do |string_char|
13
- char_map.index(string_char)
12
+ def chars_for(string_chars, char_map: CHARS, length: nil, pad: false)
13
+ formatted_chars = string_chars.downcase[0..length.to_i - 1]
14
+ formatted_chars = formatted_chars.ljust(length) if pad
15
+
16
+ formatted_chars.each_char.map do |char|
17
+ char_map.index(char)
14
18
  end
15
19
  end
16
20
 
17
21
  def eeprom_chars_for(string_chars)
18
- chars = chars_for(string_chars).append(EEPROM_TERMINATOR)
22
+ chars = chars_for(string_chars, length: 31).append(EEPROM_TERMINATOR)
19
23
 
20
24
  packed_int = chars.each_with_index.sum do |char, index|
21
25
  char << (6 * index)
@@ -25,7 +29,7 @@ class TimexDatalinkClient
25
29
  end
26
30
 
27
31
  def phone_chars_for(string_chars)
28
- chars = chars_for(string_chars, char_map: PHONE_CHARS)
32
+ chars = chars_for(string_chars, char_map: PHONE_CHARS, length: 12)
29
33
 
30
34
  packed_int = chars.each_with_index.sum do |char, index|
31
35
  char << (4 * index)
@@ -4,16 +4,29 @@ require "rubyserial"
4
4
 
5
5
  class TimexDatalinkClient
6
6
  class NotebookAdapter
7
- BYTE_SLEEP = 0.025
8
- PACKET_SLEEP = 0.25
9
-
10
- attr_accessor :serial_device, :verbose
11
-
12
- def initialize(serial_device:, verbose: false)
7
+ BYTE_SLEEP_DEFAULT = 0.025
8
+ PACKET_SLEEP_DEFAULT = 0.25
9
+
10
+ attr_accessor :serial_device, :byte_sleep, :packet_sleep, :verbose
11
+
12
+ # Create a NotebookAdapter instance.
13
+ #
14
+ # @param serial_device [String] Path to serial device.
15
+ # @param byte_sleep [Integer, nil] Time to sleep after sending byte.
16
+ # @param packet_sleep [Integer, nil] Time to sleep after sending packet of bytes.
17
+ # @param verbose [Boolean] Write verbose output to console.
18
+ # @return [NotebookAdapter] NotebookAdapter instance.
19
+ def initialize(serial_device:, byte_sleep: nil, packet_sleep: nil, verbose: false)
13
20
  @serial_device = serial_device
21
+ @byte_sleep = byte_sleep || BYTE_SLEEP_DEFAULT
22
+ @packet_sleep = packet_sleep || PACKET_SLEEP_DEFAULT
14
23
  @verbose = verbose
15
24
  end
16
25
 
26
+ # Write packets of bytes to serial device.
27
+ #
28
+ # @param packets [Array<Array<Integer>>] Two-dimensional array of integers that represent bytes.
29
+ # @return [void]
17
30
  def write(packets)
18
31
  packets.each do |packet|
19
32
  packet.each do |byte|
@@ -21,10 +34,10 @@ class TimexDatalinkClient
21
34
 
22
35
  serial.write(byte.chr)
23
36
 
24
- sleep(BYTE_SLEEP)
37
+ sleep(byte_sleep)
25
38
  end
26
39
 
27
- sleep(PACKET_SLEEP)
40
+ sleep(packet_sleep)
28
41
 
29
42
  puts if verbose
30
43
  end
@@ -10,11 +10,19 @@ class TimexDatalinkClient
10
10
 
11
11
  attr_accessor :hourly_chime, :button_beep
12
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.
13
18
  def initialize(hourly_chime:, button_beep:)
14
19
  @hourly_chime = hourly_chime
15
20
  @button_beep = button_beep
16
21
  end
17
22
 
23
+ # Compile packets for sound options.
24
+ #
25
+ # @return [Array<Array<Integer>>] Two-dimensional array of integers that represent bytes.
18
26
  def packets
19
27
  [
20
28
  CPACKET_BEEPS + [hourly_chime_integer, button_beep_integer]
@@ -14,32 +14,49 @@ class TimexDatalinkClient
14
14
 
15
15
  SOUND_DATA_HEADER = "\x25\x04\x19\x69"
16
16
 
17
- attr_accessor :sound_data
18
-
19
- def initialize(sound_data:)
20
- @sound_data = sound_data
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
21
27
  end
22
28
 
29
+ # Compile packets for a sound theme.
30
+ #
31
+ # @return [Array<Array<Integer>>] Two-dimensional array of integers that represent bytes.
23
32
  def packets
24
33
  [load_sect] + payloads + [CPACKET_END]
25
34
  end
26
35
 
27
36
  private
28
37
 
29
- def sound_bytes
30
- sound_data.delete_prefix(SOUND_DATA_HEADER).bytes
31
- end
32
-
33
38
  def load_sect
34
39
  CPACKET_SECT + [payloads.length, offset]
35
40
  end
36
41
 
37
42
  def payloads
38
- paginate_cpackets(header: CPACKET_DATA, cpackets: sound_bytes)
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)
39
56
  end
40
57
 
41
58
  def offset
42
- 0x100 - sound_bytes.length
59
+ 0x100 - sound_theme_data.bytesize
43
60
  end
44
61
  end
45
62
  end
@@ -8,6 +8,9 @@ class TimexDatalinkClient
8
8
 
9
9
  CPACKET_START = [0x20, 0x00, 0x00, 0x03]
10
10
 
11
+ # Compile packets for data start command.
12
+ #
13
+ # @return [Array<Array<Integer>>] Two-dimensional array of integers that represent bytes.
11
14
  def packets
12
15
  [CPACKET_START]
13
16
  end
@@ -9,10 +9,17 @@ class TimexDatalinkClient
9
9
 
10
10
  attr_accessor :length
11
11
 
12
+ # Create a Sync instance.
13
+ #
14
+ # @param length [Integer] Number of 0x55 sync bytes to use.
15
+ # @return [Sync] Sync instance.
12
16
  def initialize(length: 300)
13
17
  @length = length
14
18
  end
15
19
 
20
+ # Compile packets for syncronization data.
21
+ #
22
+ # @return [Array<Array<Integer>>] Two-dimensional array of integers that represent bytes.
16
23
  def packets
17
24
  [render_sync_1 + render_sync_2]
18
25
  end
@@ -12,13 +12,25 @@ class TimexDatalinkClient
12
12
 
13
13
  attr_accessor :zone, :is_24h, :date_format, :time
14
14
 
15
- def initialize(zone:, is_24h:, date_format:, time:)
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)
16
24
  @zone = zone
17
25
  @is_24h = is_24h
18
26
  @date_format = date_format
19
27
  @time = time
28
+ @name = name
20
29
  end
21
30
 
31
+ # Compile packets for a time.
32
+ #
33
+ # @return [Array<Array<Integer>>] Two-dimensional array of integers that represent bytes.
22
34
  def packets
23
35
  [
24
36
  [
@@ -30,7 +42,7 @@ class TimexDatalinkClient
30
42
  time.month,
31
43
  time.day,
32
44
  year_mod_1900,
33
- timezone_characters,
45
+ name_characters,
34
46
  wday_from_monday,
35
47
  is_24h_value,
36
48
  date_format
@@ -40,8 +52,12 @@ class TimexDatalinkClient
40
52
 
41
53
  private
42
54
 
43
- def timezone_characters
44
- chars_for(time.zone.downcase)
55
+ def name
56
+ @name || time.zone.downcase
57
+ end
58
+
59
+ def name_characters
60
+ chars_for(name, length: 3, pad: true)
45
61
  end
46
62
 
47
63
  def year_mod_1900
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class TimexDatalinkClient
4
- VERSION = "0.2.0"
4
+ VERSION = "0.4.0"
5
5
  end
@@ -16,12 +16,21 @@ class TimexDatalinkClient
16
16
  WRIST_APP_DELIMITER = /\xac.*\r\n/n
17
17
  WRIST_APP_CODE_INDEX = 8
18
18
 
19
- attr_accessor :wrist_app_data
19
+ attr_accessor :zap_file
20
20
 
21
- def initialize(wrist_app_data:)
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)
22
27
  @wrist_app_data = wrist_app_data
28
+ @zap_file = zap_file
23
29
  end
24
30
 
31
+ # Compile packets for an alarm.
32
+ #
33
+ # @return [Array<Array<Integer>>] Two-dimensional array of integers that represent bytes.
25
34
  def packets
26
35
  [CPACKET_CLEAR, cpacket_sect] + payloads + [CPACKET_END]
27
36
  end
@@ -32,16 +41,24 @@ class TimexDatalinkClient
32
41
  CPACKET_SECT + [payloads.length, 1]
33
42
  end
34
43
 
35
- def wrist_app_ascii
36
- wrist_app_data.split(WRIST_APP_DELIMITER)[WRIST_APP_CODE_INDEX]
44
+ def payloads
45
+ paginate_cpackets(header: CPACKET_DATA, cpackets: wrist_app_data.bytes)
37
46
  end
38
47
 
39
- def wrist_app_bytes
40
- [wrist_app_ascii].pack("H*").bytes
48
+ def wrist_app_data
49
+ @wrist_app_data || zap_file_data_binary
41
50
  end
42
51
 
43
- def payloads
44
- paginate_cpackets(header: CPACKET_DATA, cpackets: wrist_app_bytes)
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*")
45
62
  end
46
63
  end
47
64
  end
@@ -17,18 +17,35 @@ require "timex_datalink_client/version"
17
17
  require "timex_datalink_client/wrist_app"
18
18
 
19
19
  class TimexDatalinkClient
20
- attr_accessor :serial_device, :models, :verbose
20
+ attr_accessor :serial_device, :models, :byte_sleep, :packet_sleep, :verbose
21
21
 
22
- def initialize(serial_device:, models: [], verbose: false)
22
+ # Create a TimexDatalinkClient instance.
23
+ #
24
+ # @param serial_device [String] Path to serial device.
25
+ # @param models [Array<Alarm, Eeprom, End, SoundOptions, SoundTheme, Start, Sync, Time, WristApp>] Models to compile
26
+ # data for.
27
+ # @param byte_sleep [Integer, nil] Time to sleep after sending byte.
28
+ # @param packet_sleep [Integer, nil] Time to sleep after sending packet of bytes.
29
+ # @param verbose [Boolean] Write verbose output to console.
30
+ # @return [TimexDatalinkClient] TimexDatalinkClient instance.
31
+ def initialize(serial_device:, models: [], byte_sleep: nil, packet_sleep: nil, verbose: false)
23
32
  @serial_device = serial_device
24
33
  @models = models
34
+ @byte_sleep = byte_sleep
35
+ @packet_sleep = packet_sleep
25
36
  @verbose = verbose
26
37
  end
27
38
 
39
+ # Write data for all models to serial device.
40
+ #
41
+ # @return [void]
28
42
  def write
29
43
  notebook_adapter.write(packets)
30
44
  end
31
45
 
46
+ # Compile packets for all models.
47
+ #
48
+ # @return [Array<Array<Integer>>] Two-dimensional array of integers that represent bytes.
32
49
  def packets
33
50
  models.map(&:packets).flatten(1)
34
51
  end
@@ -38,6 +55,8 @@ class TimexDatalinkClient
38
55
  def notebook_adapter
39
56
  @notebook_adapter ||= NotebookAdapter.new(
40
57
  serial_device: serial_device,
58
+ byte_sleep: byte_sleep,
59
+ packet_sleep: packet_sleep,
41
60
  verbose: verbose
42
61
  )
43
62
  end
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.2.0
4
+ version: 0.4.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-07 00:00:00.000000000 Z
11
+ date: 2022-09-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: crc
@@ -66,6 +66,20 @@ dependencies:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
68
  version: 2.0.5
69
+ - !ruby/object:Gem::Dependency
70
+ name: yard-junk
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: 0.0.9
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: 0.0.9
69
83
  description: Write data to Timex Datalink watches with an optical sensor
70
84
  email: synthead@gmail.com
71
85
  executables: []