movingsign_api 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +22 -0
- data/.rspec +2 -0
- data/.travis.yml +8 -0
- data/.yardopts +1 -0
- data/CHANGELOG.md +11 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +60 -0
- data/Rakefile +1 -0
- data/lib/movingsign_api/commands/command.rb +76 -0
- data/lib/movingsign_api/commands/hard_reset_command.rb +16 -0
- data/lib/movingsign_api/commands/internal/align_mode.rb +50 -0
- data/lib/movingsign_api/commands/internal/display_mode.rb +61 -0
- data/lib/movingsign_api/commands/internal/display_pause.rb +33 -0
- data/lib/movingsign_api/commands/internal/display_speed.rb +45 -0
- data/lib/movingsign_api/commands/internal/file_handle.rb +54 -0
- data/lib/movingsign_api/commands/internal/pretty_keyable.rb +50 -0
- data/lib/movingsign_api/commands/internal/sender_receiver_address.rb +82 -0
- data/lib/movingsign_api/commands/internal/utilities.rb +8 -0
- data/lib/movingsign_api/commands/set_clock_command.rb +32 -0
- data/lib/movingsign_api/commands/set_sound_command.rb +21 -0
- data/lib/movingsign_api/commands/software_reset_command.rb +16 -0
- data/lib/movingsign_api/commands/write_control_command.rb +35 -0
- data/lib/movingsign_api/commands/write_text_command.rb +116 -0
- data/lib/movingsign_api/errors.rb +22 -0
- data/lib/movingsign_api/sign.rb +144 -0
- data/lib/movingsign_api/version.rb +3 -0
- data/lib/movingsign_api.rb +13 -0
- data/movingsign_api.gemspec +30 -0
- data/spec/align_mode_spec.rb +28 -0
- data/spec/commands/set_sound_command_spec.rb +19 -0
- data/spec/display_mode_spec.rb +57 -0
- data/spec/display_speed_spec.rb +23 -0
- data/spec/examples/example_A_spec.rb +24 -0
- data/spec/examples/example_C_spec.rb +16 -0
- data/spec/examples/example_D_spec.rb +14 -0
- data/spec/examples/example_K_spec.rb +14 -0
- data/spec/examples/expected.rb +130 -0
- data/spec/file_handle_spec.rb +17 -0
- data/spec/sender_receiver_address_spec.rb +60 -0
- data/spec/spec_helper.rb +19 -0
- data/spec/tutorials/readme_1.rb +5 -0
- data/spec/tutorials/readme_2.rb +5 -0
- data/spec/tutorials/tutorials_spec.rb +14 -0
- metadata +188 -0
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'movingsign_api/commands/write_control_command'
|
2
|
+
|
3
|
+
module MovingsignApi
|
4
|
+
# Performs a soft reset of the sign
|
5
|
+
#
|
6
|
+
# @note The sign will restart after receiving this command.
|
7
|
+
class SoftwareResetCommand < WriteControlCommand
|
8
|
+
def subcommand_code
|
9
|
+
'B'
|
10
|
+
end
|
11
|
+
|
12
|
+
def subcommand_payload_bytes
|
13
|
+
[]
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'movingsign_api/commands/command'
|
2
|
+
|
3
|
+
module MovingsignApi
|
4
|
+
# Write control command base class, subclassed by actual implementations
|
5
|
+
#
|
6
|
+
# In subclasses, be sure to implement:
|
7
|
+
# - {#subcommand_code}
|
8
|
+
# - {#subcommand_payload_bytes}
|
9
|
+
class WriteControlCommand < Command
|
10
|
+
def command_code
|
11
|
+
'W'
|
12
|
+
end
|
13
|
+
|
14
|
+
def subcommand_code
|
15
|
+
raise MovingsignApi::NotImplementedError, "Needs to be implemented in subclass."
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def command_payload_bytes
|
21
|
+
bytes = []
|
22
|
+
|
23
|
+
bytes.concat string_to_ascii_bytes subcommand_code
|
24
|
+
bytes.concat subcommand_payload_bytes
|
25
|
+
|
26
|
+
bytes
|
27
|
+
end
|
28
|
+
|
29
|
+
# generates control sub-command specific bytes
|
30
|
+
def subcommand_payload_bytes
|
31
|
+
raise MovingsignApi::NotImplementedError, "Needs to be implemented in subclass."
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,116 @@
|
|
1
|
+
require 'movingsign_api/commands/command'
|
2
|
+
require 'movingsign_api/commands/internal/file_handle'
|
3
|
+
require 'movingsign_api/commands/internal/display_mode'
|
4
|
+
require 'movingsign_api/commands/internal/display_speed'
|
5
|
+
require 'movingsign_api/commands/internal/display_pause'
|
6
|
+
require 'movingsign_api/commands/internal/align_mode'
|
7
|
+
|
8
|
+
module MovingsignApi
|
9
|
+
# Writes text to a sign
|
10
|
+
class WriteTextCommand < MovingsignApi::Command
|
11
|
+
# Index of the file to write to. 0 - 35 (363 total). See {FileHandle}
|
12
|
+
#
|
13
|
+
# @param value [Integer] 0 - 35 (default: 0)
|
14
|
+
attr_accessor :file_handle
|
15
|
+
|
16
|
+
# Display mode to use. See {DisplayMode}
|
17
|
+
#
|
18
|
+
# @param value [Sybol] (default: +:hold+)
|
19
|
+
attr_accessor :display_mode
|
20
|
+
|
21
|
+
# Display speed of effects. See {DisplaySpeed}
|
22
|
+
#
|
23
|
+
# @param value [Symbol] default: +:normal+
|
24
|
+
attr_accessor :display_speed
|
25
|
+
|
26
|
+
# Display pause between screens of information. See {DisplayPause}
|
27
|
+
#
|
28
|
+
# @param value [Integer] default: +2+
|
29
|
+
attr_accessor :display_pause
|
30
|
+
|
31
|
+
# Day of week mask. See specification for an explaination of this parameter
|
32
|
+
#
|
33
|
+
# @param value [String] default: +'7F'+
|
34
|
+
attr_accessor :dayofweek_mask
|
35
|
+
|
36
|
+
# Align mode to use. See {AlignMode}
|
37
|
+
#
|
38
|
+
# @param value [Symbol] One of +:left+ +:right+ +:center+ (default +:left+)
|
39
|
+
attr_accessor :align_mode
|
40
|
+
|
41
|
+
# Display start time
|
42
|
+
# @note work in progress
|
43
|
+
#
|
44
|
+
# @param value [String] default: +'0000'+
|
45
|
+
attr_accessor :start_time
|
46
|
+
|
47
|
+
# Display end time
|
48
|
+
# @note work in progress
|
49
|
+
#
|
50
|
+
# @param value [String] default: +'2359'+
|
51
|
+
attr_accessor :end_time
|
52
|
+
|
53
|
+
# Text to display
|
54
|
+
#
|
55
|
+
# @param value [String] the message to display
|
56
|
+
attr_accessor :text
|
57
|
+
|
58
|
+
def file_handle=(handle)
|
59
|
+
@file_handle = FileHandle.new(handle)
|
60
|
+
end
|
61
|
+
|
62
|
+
def display_mode=(mode)
|
63
|
+
@display_mode = DisplayMode.parse(mode)
|
64
|
+
end
|
65
|
+
|
66
|
+
def display_speed=(speed)
|
67
|
+
@display_speed = DisplaySpeed.parse(speed)
|
68
|
+
end
|
69
|
+
|
70
|
+
def display_pause=(seconds)
|
71
|
+
@display_pause = DisplayPause.new seconds
|
72
|
+
end
|
73
|
+
|
74
|
+
def align_mode=(align)
|
75
|
+
@align_mode = AlignMode.parse(align)
|
76
|
+
end
|
77
|
+
|
78
|
+
# (see Command#command_code)
|
79
|
+
# 'A' for the "Write Text" command
|
80
|
+
def command_code
|
81
|
+
'A'
|
82
|
+
end
|
83
|
+
|
84
|
+
private
|
85
|
+
|
86
|
+
def command_payload_bytes
|
87
|
+
# set defaults if needed
|
88
|
+
self.file_handle ||= 0
|
89
|
+
self.display_mode ||= :hold
|
90
|
+
self.display_speed ||= :normal
|
91
|
+
self.display_pause ||= 2
|
92
|
+
self.dayofweek_mask ||= '7F'
|
93
|
+
self.align_mode ||= :left
|
94
|
+
self.start_time ||= '0000'
|
95
|
+
self.end_time ||= '2359'
|
96
|
+
raise InvalidInputError, "text not set" unless self.text
|
97
|
+
|
98
|
+
bytes = []
|
99
|
+
|
100
|
+
bytes.concat self.file_handle.to_bytes # Filename
|
101
|
+
bytes.concat self.display_mode.to_bytes # Display Mode
|
102
|
+
bytes.concat self.display_speed.to_bytes # Display Speed
|
103
|
+
bytes.concat self.display_pause.to_bytes # Display Pause
|
104
|
+
bytes.concat string_to_ascii_bytes(self.dayofweek_mask) # Show Date
|
105
|
+
bytes.concat string_to_ascii_bytes(self.start_time) # Start Time
|
106
|
+
bytes.concat string_to_ascii_bytes(self.end_time) # End Time
|
107
|
+
bytes.concat string_to_ascii_bytes('000') # Reserved
|
108
|
+
bytes.concat self.align_mode.to_bytes # Align Mode
|
109
|
+
#bytes.concat string_to_ascii_bytes("\xFD\x42" + self.text.gsub("\n", "\x7F")) # Text
|
110
|
+
bytes.concat string_to_ascii_bytes(self.text.gsub("\n", "\x7F")) # Text
|
111
|
+
|
112
|
+
bytes
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module MovingsignApi
|
2
|
+
# Base error for all MovingsignApi errors.
|
3
|
+
class Error < StandardError
|
4
|
+
|
5
|
+
end
|
6
|
+
|
7
|
+
# Raised when a method has been be implemented, usually due to improperly subclassed class or code that is in
|
8
|
+
# progress.
|
9
|
+
class NotImplementedError < Error
|
10
|
+
|
11
|
+
end
|
12
|
+
|
13
|
+
# Raised when an input is invalid in the given context.
|
14
|
+
class InvalidInputError < Error
|
15
|
+
|
16
|
+
end
|
17
|
+
|
18
|
+
# Raised when there are errors reading/writing to the serial port
|
19
|
+
class IOError < Error
|
20
|
+
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,144 @@
|
|
1
|
+
require 'serialport'
|
2
|
+
|
3
|
+
module MovingsignApi
|
4
|
+
# Manipulates a Movingsign attached to a serial port
|
5
|
+
#
|
6
|
+
# @example Construct a sign
|
7
|
+
# require 'movingsign_api'
|
8
|
+
#
|
9
|
+
# sign = MovingsignApi::Sign.new('/dev/ttyUSB0')
|
10
|
+
#
|
11
|
+
# @example Show Text
|
12
|
+
# sign.show_text('Hello World!')
|
13
|
+
#
|
14
|
+
# @example Turn Sound Off
|
15
|
+
# sign.set_sound false
|
16
|
+
#
|
17
|
+
class Sign
|
18
|
+
# Serial port device path (ie: /dev/ttyUSB0)
|
19
|
+
attr_accessor :device_path
|
20
|
+
|
21
|
+
# @param device_path [String] the serial port device path (ie: /dev/ttyUSB0, different depending on platform)
|
22
|
+
def initialize(device_path)
|
23
|
+
@device_path = device_path
|
24
|
+
end
|
25
|
+
|
26
|
+
# Show the {#device_path} value on the display (useful for diagnostics)
|
27
|
+
def show_identity
|
28
|
+
cmd = WriteTextCommand.new
|
29
|
+
cmd.text = self.device_path
|
30
|
+
|
31
|
+
send_command cmd
|
32
|
+
end
|
33
|
+
|
34
|
+
# Displays the given text on the board.
|
35
|
+
#
|
36
|
+
# This is short-hand for the {WriteTextCommand}
|
37
|
+
#
|
38
|
+
# @param text [String] the text to display on the sign
|
39
|
+
# @param options [Hash] options for {WriteTextCommand}
|
40
|
+
# @option options [Integer] :display_pause (2) Time to pause (in seconds) between pages of text. See {WriteTextCommand#display_pause}
|
41
|
+
#
|
42
|
+
# @return [self]
|
43
|
+
def show_text(text, options = {})
|
44
|
+
cmd = WriteTextCommand.new
|
45
|
+
cmd.display_pause = options[:display_pause] if options[:display_pause]
|
46
|
+
cmd.text = text
|
47
|
+
|
48
|
+
send_command cmd
|
49
|
+
end
|
50
|
+
alias :write_text :show_text
|
51
|
+
|
52
|
+
# Turns on/off sound when the sign receives a command
|
53
|
+
#
|
54
|
+
# This is a shorthand for {SetSoundCommand}
|
55
|
+
#
|
56
|
+
# @param on [Boolean] true to turn sound on, false otherwise
|
57
|
+
#
|
58
|
+
# @return [self]
|
59
|
+
def set_sound(on)
|
60
|
+
cmd = SetSoundCommand.new on
|
61
|
+
|
62
|
+
send_command cmd
|
63
|
+
end
|
64
|
+
|
65
|
+
# Sends the specified Movingsign command to this sign's serial port
|
66
|
+
#
|
67
|
+
# @param [MovingsignApi::Command] command subclass to send
|
68
|
+
#
|
69
|
+
# @return [self]
|
70
|
+
def send_command(command)
|
71
|
+
SerialPort.open(self.device_path, 9600, 8, 1) do |port|
|
72
|
+
# flush anything existing on the port
|
73
|
+
port.flush
|
74
|
+
flush_read_buffer(port)
|
75
|
+
|
76
|
+
byte_string = command.to_bytes.pack('C*')
|
77
|
+
|
78
|
+
begin
|
79
|
+
while byte_string && byte_string.length != 0
|
80
|
+
count = port.write_nonblock(byte_string)
|
81
|
+
byte_string = byte_string[count,-1]
|
82
|
+
|
83
|
+
port.flush
|
84
|
+
end
|
85
|
+
rescue IO::WaitWritable
|
86
|
+
if IO.select([], [port], [], 5)
|
87
|
+
retry
|
88
|
+
else
|
89
|
+
raise IOError, "Timeout writing command to #{self.device_path}"
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
# wait for expected confirmation signals
|
94
|
+
got_eot = false
|
95
|
+
got_soh = false
|
96
|
+
loop do
|
97
|
+
begin
|
98
|
+
c = port.read_nonblock(1)
|
99
|
+
|
100
|
+
case c
|
101
|
+
when "\x04"
|
102
|
+
if ! got_eot
|
103
|
+
got_eot = true
|
104
|
+
else
|
105
|
+
raise IOError, "Got EOT reply twice from #{self.device_path}"
|
106
|
+
end
|
107
|
+
when "\x01"
|
108
|
+
if got_eot
|
109
|
+
if ! got_soh
|
110
|
+
got_soh = true
|
111
|
+
|
112
|
+
break
|
113
|
+
else
|
114
|
+
raise IOError, "Got SOH twice from #{self.device_path}"
|
115
|
+
end
|
116
|
+
else
|
117
|
+
raise IOError, "Got SOH before EOT from #{self.device_path}"
|
118
|
+
end
|
119
|
+
end
|
120
|
+
rescue IO::WaitReadable
|
121
|
+
if IO.select([port], [], [], 3)
|
122
|
+
retry
|
123
|
+
else
|
124
|
+
raise IOError, "Timeout waiting for command reply from #{self.device_path}. EOT:#{got_eot} SOH:#{got_soh}"
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
self
|
131
|
+
end
|
132
|
+
|
133
|
+
private
|
134
|
+
|
135
|
+
def flush_read_buffer(port)
|
136
|
+
begin
|
137
|
+
while true
|
138
|
+
port.read_nonblock(1024)
|
139
|
+
end
|
140
|
+
rescue IO::WaitReadable
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require "movingsign_api/errors"
|
2
|
+
require "movingsign_api/version"
|
3
|
+
require 'movingsign_api/commands/write_text_command'
|
4
|
+
require 'movingsign_api/commands/set_clock_command'
|
5
|
+
require 'movingsign_api/commands/software_reset_command'
|
6
|
+
require 'movingsign_api/commands/hard_reset_command'
|
7
|
+
require 'movingsign_api/commands/set_clock_command'
|
8
|
+
require 'movingsign_api/commands/set_sound_command'
|
9
|
+
require 'movingsign_api/sign'
|
10
|
+
|
11
|
+
module MovingsignApi
|
12
|
+
# Your code goes here...
|
13
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'movingsign_api/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "movingsign_api"
|
8
|
+
spec.version = MovingsignApi::VERSION
|
9
|
+
spec.authors = ["Eric Webb"]
|
10
|
+
spec.email = ["opensource@collectivegenius.net"]
|
11
|
+
spec.description = "MovingSign Communication Protocol V2.1 Implementation in Ruby"
|
12
|
+
spec.summary = "MovingSign Communication Protocol V2.1 Implementation in Ruby"
|
13
|
+
spec.homepage = ""
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/)
|
17
|
+
.reject { |path| path.match /\A\.idea\// } # Ignore .idea/ IntelliJ project directory
|
18
|
+
.reject { |path| path.match /\A[^\/]+\.iml/ } # Ignore *.iml IntelliJ module file
|
19
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
20
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
21
|
+
spec.require_paths = ["lib"]
|
22
|
+
|
23
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
24
|
+
spec.add_development_dependency "rake"
|
25
|
+
spec.add_development_dependency "rspec", "~> 2.14"
|
26
|
+
spec.add_development_dependency "yard", "0.8.7.3"
|
27
|
+
spec.add_development_dependency "wwtd"
|
28
|
+
|
29
|
+
spec.add_runtime_dependency 'serialport', '~> 1.3'
|
30
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
|
4
|
+
ALIGN_MODES = {
|
5
|
+
:left => '1',
|
6
|
+
:right => '3',
|
7
|
+
:center => '2',
|
8
|
+
}
|
9
|
+
|
10
|
+
describe MovingsignApi::AlignMode do
|
11
|
+
describe '::parse' do
|
12
|
+
it "Symbol" do
|
13
|
+
# valid keys
|
14
|
+
ALIGN_MODES.keys.each do |key|
|
15
|
+
expect(described_class.parse(key).key).to eq key
|
16
|
+
end
|
17
|
+
|
18
|
+
# invalid keys
|
19
|
+
expect {described_class.parse(:invalid).key}.to raise_error(MovingsignApi::InvalidInputError)
|
20
|
+
expect {described_class.parse(nil).key}.to raise_error(MovingsignApi::InvalidInputError)
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'Code' do
|
24
|
+
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe MovingsignApi::SetSoundCommand do
|
4
|
+
describe "sound on" do
|
5
|
+
subject { MovingsignApi::SetSoundCommand.new(true) }
|
6
|
+
|
7
|
+
it "#subcommand_payload_bytes" do
|
8
|
+
expect(subject.subcommand_payload_bytes).to eq [0x31]
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
describe "sound off" do
|
13
|
+
subject { MovingsignApi::SetSoundCommand.new(false) }
|
14
|
+
|
15
|
+
it "#subcommand_payload_bytes" do
|
16
|
+
expect(subject.subcommand_payload_bytes).to eq [0x30]
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
|
4
|
+
DISPLAY_MODES = {
|
5
|
+
:auto => 'A',
|
6
|
+
:flash => 'B',
|
7
|
+
:hold => 'C',
|
8
|
+
:interlock => 'D',
|
9
|
+
:rolldown => 'E',
|
10
|
+
:rollup => 'F',
|
11
|
+
:rollin => 'G',
|
12
|
+
:rollout => 'H',
|
13
|
+
:rollleft => 'I',
|
14
|
+
:rollright => 'J',
|
15
|
+
:rotate => 'K',
|
16
|
+
:slide => 'L',
|
17
|
+
:snow => 'M',
|
18
|
+
:sparkle => 'N',
|
19
|
+
:spray => 'O',
|
20
|
+
:starburst => 'P',
|
21
|
+
:switch => 'Q',
|
22
|
+
:twinkle => 'R',
|
23
|
+
:wipedown => 'S',
|
24
|
+
:wipeup => 'T',
|
25
|
+
:wipein => 'U',
|
26
|
+
:wipeout => 'V',
|
27
|
+
:wipeleft => 'W',
|
28
|
+
:wiperight => 'X',
|
29
|
+
:cyclecolor => 'Y',
|
30
|
+
:clock => 'Z',
|
31
|
+
}
|
32
|
+
|
33
|
+
describe MovingsignApi::DisplayMode do
|
34
|
+
describe '::parse' do
|
35
|
+
it "Symbol" do
|
36
|
+
# All valid keys
|
37
|
+
DISPLAY_MODES.keys.each do |key|
|
38
|
+
expect(described_class.parse(key).key).to eq key
|
39
|
+
end
|
40
|
+
|
41
|
+
# invalid keys
|
42
|
+
expect {described_class.parse(:invalid).key}.to raise_error(MovingsignApi::InvalidInputError)
|
43
|
+
expect {described_class.parse(:+).key}.to raise_error(MovingsignApi::InvalidInputError)
|
44
|
+
expect {described_class.parse(nil).key}.to raise_error(MovingsignApi::InvalidInputError)
|
45
|
+
end
|
46
|
+
|
47
|
+
it "ASCII Code" do
|
48
|
+
# All valid ASCII codes
|
49
|
+
DISPLAY_MODES.each_pair do |key, code|
|
50
|
+
expect(described_class.parse(code).key).to eq key
|
51
|
+
end
|
52
|
+
|
53
|
+
expect {described_class.parse('0').key}.to raise_error(MovingsignApi::InvalidInputError)
|
54
|
+
expect {described_class.parse('z').key}.to raise_error(MovingsignApi::InvalidInputError)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
DISPLAY_SPEEDS = {
|
4
|
+
:fastest => '1',
|
5
|
+
:faster => '2',
|
6
|
+
:normal => '3',
|
7
|
+
:slow => '4',
|
8
|
+
:slower => '5',
|
9
|
+
}
|
10
|
+
|
11
|
+
describe MovingsignApi::DisplaySpeed do
|
12
|
+
describe '::parse' do
|
13
|
+
it "Symbol" do
|
14
|
+
DISPLAY_SPEEDS.keys.each do |key|
|
15
|
+
expect(described_class.parse(key).key).to eq key
|
16
|
+
end
|
17
|
+
|
18
|
+
# invalid keys
|
19
|
+
expect {described_class.parse(:invalid).key}.to raise_error(MovingsignApi::InvalidInputError)
|
20
|
+
expect {described_class.parse(nil).key}.to raise_error(MovingsignApi::InvalidInputError)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
require_relative 'expected'
|
4
|
+
|
5
|
+
describe "Specification Example A - Write Text File" do
|
6
|
+
it "Generates Expected Output" do
|
7
|
+
command = MovingsignApi::WriteTextCommand.new
|
8
|
+
|
9
|
+
command.sender = :pc
|
10
|
+
command.receiver = 3
|
11
|
+
|
12
|
+
command.file_handle = 'A' # aka 10
|
13
|
+
command.display_mode = :auto
|
14
|
+
command.display_speed = :faster
|
15
|
+
command.display_pause = 2
|
16
|
+
command.dayofweek_mask = '7F' # todo: make this pretty
|
17
|
+
command.start_time = '0100'
|
18
|
+
command.end_time = '1200'
|
19
|
+
command.align_mode = :left
|
20
|
+
command.text = 'HELLO'
|
21
|
+
|
22
|
+
expect(command.to_bytes).to eq EXAMPLE_A_EXPECTED
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
require_relative 'expected'
|
4
|
+
|
5
|
+
describe "Specification Example C - Set Clock Command" do
|
6
|
+
it "Generates Expected Output" do
|
7
|
+
command = MovingsignApi::SetClockCommand.new
|
8
|
+
|
9
|
+
command.sender = :pc
|
10
|
+
command.receiver = 34
|
11
|
+
|
12
|
+
command.datetime = Time.new(2004,04,02,12,36,23)
|
13
|
+
|
14
|
+
expect(command.to_bytes).to eq EXAMPLE_C_EXPECTED
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
require_relative 'expected'
|
4
|
+
|
5
|
+
describe "Specification Example D - Software Reset Command" do
|
6
|
+
it "Generates Expected Output" do
|
7
|
+
command = MovingsignApi::SoftwareResetCommand.new
|
8
|
+
|
9
|
+
command.sender = :pc
|
10
|
+
command.receiver = 34
|
11
|
+
|
12
|
+
expect(command.to_bytes).to eq EXAMPLE_D_EXPECTED
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
require_relative 'expected'
|
4
|
+
|
5
|
+
describe "Specification Example K - Hard Reset Command" do
|
6
|
+
it "Generates Expected Output" do
|
7
|
+
command = MovingsignApi::HardResetCommand.new
|
8
|
+
|
9
|
+
command.sender = :pc
|
10
|
+
command.receiver = 16
|
11
|
+
|
12
|
+
expect(command.to_bytes).to eq EXAMPLE_K_EXPECTED
|
13
|
+
end
|
14
|
+
end
|